1: /*
   2:  * monster.c
   3:  *
   4:  * This source herein may be modified and/or distributed by anybody who
   5:  * so desires, with the following restrictions:
   6:  *    1.)  No portion of this notice shall be removed.
   7:  *    2.)  Credit shall not be taken for the creation of this source.
   8:  *    3.)  This code is not to be traded, sold, or used for personal
   9:  *         gain or profit.
  10:  *
  11:  */
  12: 
  13: #ifndef lint
  14: static char sccsid[] = "@(#)monster.c	5.1 (Berkeley) 11/25/87";
  15: #endif /* not lint */
  16: 
  17: #include "rogue.h"
  18: 
  19: object level_monsters;
  20: boolean mon_disappeared;
  21: 
  22: char *m_names[] = {
  23:     "aquator",
  24:     "bat",
  25:     "centaur",
  26:     "dragon",
  27:     "emu",
  28:     "venus fly-trap",
  29:     "griffin",
  30:     "hobgoblin",
  31:     "ice monster",
  32:     "jabberwock",
  33:     "kestrel",
  34:     "leprechaun",
  35:     "medusa",
  36:     "nymph",
  37:     "orc",
  38:     "phantom",
  39:     "quagga",
  40:     "rattlesnake",
  41:     "snake",
  42:     "troll",
  43:     "black unicorn",
  44:     "vampire",
  45:     "wraith",
  46:     "xeroc",
  47:     "yeti",
  48:     "zombie"
  49: };
  50: 
  51: object mon_tab[MONSTERS] = {
  52:     {(ASLEEP|WAKENS|WANDERS|RUSTS),"0d0",25,'A',20,9,18,100,0,0,0,0,0},
  53:     {(ASLEEP|WANDERS|FLITS|FLIES),"1d3",10,'B',2,1,8,60,0,0,0,0,0},
  54:     {(ASLEEP|WANDERS),"3d3/2d5",32,'C',15,7,16,85,0,10,0,0,0},
  55:     {(ASLEEP|WAKENS|FLAMES),"4d6/4d9",145,'D',5000,21,126,100,0,90,0,0,0},
  56:     {(ASLEEP|WAKENS),"1d3",11,'E',2,1,7,65,0,0,0,0,0},
  57:     {(HOLDS|STATIONARY),"5d5",73,'F',91,12,126,80,0,0,0,0,0},
  58:     {(ASLEEP|WAKENS|WANDERS|FLIES),"5d5/5d5",115,'G',
  59:             2000,20,126,85,0,10,0,0,0},
  60:     {(ASLEEP|WAKENS|WANDERS),"1d3/1d2",15,'H',3,1,10,67,0,0,0,0,0},
  61:     {(ASLEEP|FREEZES),"0d0",15,'I',5,2,11,68,0,0,0,0,0},
  62:     {(ASLEEP|WANDERS),"3d10/4d5",132,'J',3000,21,126,100,0,0,0,0,0},
  63:     {(ASLEEP|WAKENS|WANDERS|FLIES),"1d4",10,'K',2,1,6,60,0,0,0,0,0},
  64:     {(ASLEEP|STEALS_GOLD),"0d0",25,'L',21,6,16,75,0,0,0,0,0},
  65:     {(ASLEEP|WAKENS|WANDERS|CONFUSES),"4d4/3d7",97,'M',
  66:             250,18,126,85,0,25,0,0,0},
  67:     {(ASLEEP|STEALS_ITEM),"0d0",25,'N',39,10,19,75,0,100,0,0,0},
  68:     {(ASLEEP|WANDERS|WAKENS|SEEKS_GOLD),"1d6",25,'O',5,4,13,70,0,10,0,0,0},
  69:     {(ASLEEP|INVISIBLE|WANDERS|FLITS),"5d4",76,'P',120,15,24,80,0,50,0,0,0},
  70:     {(ASLEEP|WAKENS|WANDERS),"3d5",30,'Q',20,8,17,78,0,20,0,0,0},
  71:     {(ASLEEP|WAKENS|WANDERS|STINGS),"2d5",19,'R',10,3,12,70,0,0,0,0,0},
  72:     {(ASLEEP|WAKENS|WANDERS),"1d3",8,'S',2,1,9,50,0,0,0,0,0},
  73:     {(ASLEEP|WAKENS|WANDERS),"4d6/1d4",75,'T',125,13,22,75,0,33,0,0,0},
  74:     {(ASLEEP|WAKENS|WANDERS),"4d10",90,'U',
  75:             200,17,26,85,0,33,0,0,0},
  76:     {(ASLEEP|WAKENS|WANDERS|DRAINS_LIFE),"1d14/1d4",55,'V',
  77:             350,19,126,85,0,18,0,0,0},
  78:     {(ASLEEP|WANDERS|DROPS_LEVEL),"2d8",45,'W',55,14,23,75,0,0,0,0,0},
  79:     {(ASLEEP|IMITATES),"4d6",42,'X',110,16,25,75,0,0,0,0,0},
  80:     {(ASLEEP|WANDERS),"3d6",35,'Y',50,11,20,80,0,20,0,0,0},
  81:     {(ASLEEP|WAKENS|WANDERS),"1d7",21,'Z',8,5,14,69,0,0,0,0,0}
  82: };
  83: 
  84: extern short cur_level;
  85: extern short cur_room, party_room;
  86: extern short blind, halluc, haste_self;
  87: extern boolean detect_monster, see_invisible, r_see_invisible;
  88: extern short stealthy;
  89: 
  90: put_mons()
  91: {
  92:     short i;
  93:     short n;
  94:     object *monster;
  95:     short row, col;
  96: 
  97:     n = get_rand(4, 6);
  98: 
  99:     for (i = 0; i < n; i++) {
 100:         monster = gr_monster((object *) 0, 0);
 101:         if ((monster->m_flags & WANDERS) && coin_toss()) {
 102:             wake_up(monster);
 103:         }
 104:         gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
 105:         put_m_at(row, col, monster);
 106:     }
 107: }
 108: 
 109: object *
 110: gr_monster(monster, mn)
 111: register object *monster;
 112: register mn;
 113: {
 114:     if (!monster) {
 115:         monster = alloc_object();
 116: 
 117:         for (;;) {
 118:             mn = get_rand(0, MONSTERS-1);
 119:             if ((cur_level >= mon_tab[mn].first_level) &&
 120:             (cur_level <= mon_tab[mn].last_level)) {
 121:                 break;
 122:             }
 123:         }
 124:     }
 125:     *monster = mon_tab[mn];
 126:     if (monster->m_flags & IMITATES) {
 127:         monster->disguise = gr_obj_char();
 128:     }
 129:     if (cur_level > (AMULET_LEVEL + 2)) {
 130:         monster->m_flags |= HASTED;
 131:     }
 132:     monster->trow = NO_ROOM;
 133:     return(monster);
 134: }
 135: 
 136: mv_mons()
 137: {
 138:     register object *monster, *next_monster;
 139:     boolean flew;
 140: 
 141:     if (haste_self % 2) {
 142:         return;
 143:     }
 144: 
 145:     monster = level_monsters.next_monster;
 146: 
 147:     while (monster) {
 148:         next_monster = monster->next_monster;
 149:         mon_disappeared = 0;
 150:         if (monster->m_flags & HASTED) {
 151:             mv_1_monster(monster, rogue.row, rogue.col);
 152:             if (mon_disappeared) {
 153:                 goto NM;
 154:             }
 155:         } else if (monster->m_flags & SLOWED) {
 156:             monster->slowed_toggle = !monster->slowed_toggle;
 157:             if (monster->slowed_toggle) {
 158:                 goto NM;
 159:             }
 160:         }
 161:         if ((monster->m_flags & CONFUSED) && move_confused(monster)) {
 162:             goto NM;
 163:         }
 164:         flew = 0;
 165:         if (    (monster->m_flags & FLIES) &&
 166:                 !(monster->m_flags & NAPPING) &&
 167:                 !mon_can_go(monster, rogue.row, rogue.col)) {
 168:             flew = 1;
 169:             mv_1_monster(monster, rogue.row, rogue.col);
 170:             if (mon_disappeared) {
 171:                 goto NM;
 172:             }
 173:         }
 174:         if (!(flew && mon_can_go(monster, rogue.row, rogue.col))) {
 175:             mv_1_monster(monster, rogue.row, rogue.col);
 176:         }
 177: NM:     monster = next_monster;
 178:     }
 179: }
 180: 
 181: party_monsters(rn, n)
 182: int rn, n;
 183: {
 184:     short i, j;
 185:     short row, col;
 186:     object *monster;
 187:     boolean found;
 188: 
 189:     n += n;
 190: 
 191:     for (i = 0; i < MONSTERS; i++) {
 192:         mon_tab[i].first_level -= (cur_level % 3);
 193:     }
 194:     for (i = 0; i < n; i++) {
 195:         if (no_room_for_monster(rn)) {
 196:             break;
 197:         }
 198:         for (j = found = 0; ((!found) && (j < 250)); j++) {
 199:             row = get_rand(rooms[rn].top_row+1,
 200:                 rooms[rn].bottom_row-1);
 201:             col = get_rand(rooms[rn].left_col+1,
 202:                 rooms[rn].right_col-1);
 203:             if ((!(dungeon[row][col] & MONSTER)) &&
 204:                 (dungeon[row][col] & (FLOOR | TUNNEL))) {
 205:                 found = 1;
 206:             }
 207:         }
 208:         if (found) {
 209:             monster = gr_monster((object *) 0, 0);
 210:             if (!(monster->m_flags & IMITATES)) {
 211:                 monster->m_flags |= WAKENS;
 212:             }
 213:             put_m_at(row, col, monster);
 214:         }
 215:     }
 216:     for (i = 0; i < MONSTERS; i++) {
 217:         mon_tab[i].first_level += (cur_level % 3);
 218:     }
 219: }
 220: 
 221: gmc_row_col(row, col)
 222: register row, col;
 223: {
 224:     register object *monster;
 225: 
 226:     if (monster = object_at(&level_monsters, row, col)) {
 227:         if ((!(detect_monster || see_invisible || r_see_invisible) &&
 228:             (monster->m_flags & INVISIBLE)) || blind) {
 229:             return(monster->trail_char);
 230:         }
 231:         if (monster->m_flags & IMITATES) {
 232:             return(monster->disguise);
 233:         }
 234:         return(monster->m_char);
 235:     } else {
 236:         return('&');    /* BUG if this ever happens */
 237:     }
 238: }
 239: 
 240: gmc(monster)
 241: object *monster;
 242: {
 243:     if ((!(detect_monster || see_invisible || r_see_invisible) &&
 244:         (monster->m_flags & INVISIBLE))
 245:         || blind) {
 246:         return(monster->trail_char);
 247:     }
 248:     if (monster->m_flags & IMITATES) {
 249:         return(monster->disguise);
 250:     }
 251:     return(monster->m_char);
 252: }
 253: 
 254: mv_1_monster(monster, row, col)
 255: register object *monster;
 256: short row, col;
 257: {
 258:     short i, n;
 259:     boolean tried[6];
 260: 
 261:     if (monster->m_flags & ASLEEP) {
 262:         if (monster->m_flags & NAPPING) {
 263:             if (--monster->nap_length <= 0) {
 264:                 monster->m_flags &= (~(NAPPING | ASLEEP));
 265:             }
 266:             return;
 267:         }
 268:         if ((monster->m_flags & WAKENS) &&
 269:              rogue_is_around(monster->row, monster->col) &&
 270:              rand_percent(((stealthy > 0) ?
 271:                 (WAKE_PERCENT / (STEALTH_FACTOR + stealthy)) :
 272:                 WAKE_PERCENT))) {
 273:             wake_up(monster);
 274:         }
 275:         return;
 276:     } else if (monster->m_flags & ALREADY_MOVED) {
 277:         monster->m_flags &= (~ALREADY_MOVED);
 278:         return;
 279:     }
 280:     if ((monster->m_flags & FLITS) && flit(monster)) {
 281:         return;
 282:     }
 283:     if ((monster->m_flags & STATIONARY) &&
 284:         (!mon_can_go(monster, rogue.row, rogue.col))) {
 285:         return;
 286:     }
 287:     if (monster->m_flags & FREEZING_ROGUE) {
 288:         return;
 289:     }
 290:     if ((monster->m_flags & CONFUSES) && m_confuse(monster)) {
 291:         return;
 292:     }
 293:     if (mon_can_go(monster, rogue.row, rogue.col)) {
 294:         mon_hit(monster);
 295:         return;
 296:     }
 297:     if ((monster->m_flags & FLAMES) && flame_broil(monster)) {
 298:         return;
 299:     }
 300:     if ((monster->m_flags & SEEKS_GOLD) && seek_gold(monster)) {
 301:         return;
 302:     }
 303:     if ((monster->trow == monster->row) &&
 304:            (monster->tcol == monster->col)) {
 305:         monster->trow = NO_ROOM;
 306:     } else if (monster->trow != NO_ROOM) {
 307:         row = monster->trow;
 308:         col = monster->tcol;
 309:     }
 310:     if (monster->row > row) {
 311:         row = monster->row - 1;
 312:     } else if (monster->row < row) {
 313:         row = monster->row + 1;
 314:     }
 315:     if ((dungeon[row][monster->col] & DOOR) &&
 316:          mtry(monster, row, monster->col)) {
 317:         return;
 318:     }
 319:     if (monster->col > col) {
 320:         col = monster->col - 1;
 321:     } else if (monster->col < col) {
 322:         col = monster->col + 1;
 323:     }
 324:     if ((dungeon[monster->row][col] & DOOR) &&
 325:          mtry(monster, monster->row, col)) {
 326:         return;
 327:     }
 328:     if (mtry(monster, row, col)) {
 329:         return;
 330:     }
 331: 
 332:     for (i = 0; i <= 5; i++) tried[i] = 0;
 333: 
 334:     for (i = 0; i < 6; i++) {
 335: NEXT_TRY:   n = get_rand(0, 5);
 336:         switch(n) {
 337:         case 0:
 338:             if (!tried[n] && mtry(monster, row, monster->col-1)) {
 339:                 goto O;
 340:             }
 341:             break;
 342:         case 1:
 343:             if (!tried[n] && mtry(monster, row, monster->col)) {
 344:                 goto O;
 345:             }
 346:             break;
 347:         case 2:
 348:             if (!tried[n] && mtry(monster, row, monster->col+1)) {
 349:                 goto O;
 350:             }
 351:             break;
 352:         case 3:
 353:             if (!tried[n] && mtry(monster, monster->row-1, col)) {
 354:                 goto O;
 355:             }
 356:             break;
 357:         case 4:
 358:             if (!tried[n] && mtry(monster, monster->row, col)) {
 359:                 goto O;
 360:             }
 361:             break;
 362:         case 5:
 363:             if (!tried[n] && mtry(monster, monster->row+1, col)) {
 364:                 goto O;
 365:             }
 366:             break;
 367:         }
 368:         if (!tried[n]) {
 369:             tried[n] = 1;
 370:         } else {
 371:             goto NEXT_TRY;
 372:         }
 373:     }
 374: O:
 375:     if ((monster->row == monster->o_row) && (monster->col == monster->o_col)) {
 376:         if (++(monster->o) > 4) {
 377:             if ((monster->trow == NO_ROOM) &&
 378:                     (!mon_sees(monster, rogue.row, rogue.col))) {
 379:                 monster->trow = get_rand(1, (DROWS - 2));
 380:                 monster->tcol = get_rand(0, (DCOLS - 1));
 381:             } else {
 382:                 monster->trow = NO_ROOM;
 383:                 monster->o = 0;
 384:             }
 385:         }
 386:     } else {
 387:         monster->o_row = monster->row;
 388:         monster->o_col = monster->col;
 389:         monster->o = 0;
 390:     }
 391: }
 392: 
 393: mtry(monster, row, col)
 394: register object *monster;
 395: register short row, col;
 396: {
 397:     if (mon_can_go(monster, row, col)) {
 398:         move_mon_to(monster, row, col);
 399:         return(1);
 400:     }
 401:     return(0);
 402: }
 403: 
 404: move_mon_to(monster, row, col)
 405: register object *monster;
 406: register short row, col;
 407: {
 408:     short c;
 409:     register mrow, mcol;
 410: 
 411:     mrow = monster->row;
 412:     mcol = monster->col;
 413: 
 414:     dungeon[mrow][mcol] &= ~MONSTER;
 415:     dungeon[row][col] |= MONSTER;
 416: 
 417:     c = mvinch(mrow, mcol);
 418: 
 419:     if ((c >= 'A') && (c <= 'Z')) {
 420:         if (!detect_monster) {
 421:             mvaddch(mrow, mcol, monster->trail_char);
 422:         } else {
 423:             if (rogue_can_see(mrow, mcol)) {
 424:                 mvaddch(mrow, mcol, monster->trail_char);
 425:             } else {
 426:                 if (monster->trail_char == '.') {
 427:                     monster->trail_char = ' ';
 428:                 }
 429:                 mvaddch(mrow, mcol, monster->trail_char);
 430:             }
 431:         }
 432:     }
 433:     monster->trail_char = mvinch(row, col);
 434:     if (!blind && (detect_monster || rogue_can_see(row, col))) {
 435:         if ((!(monster->m_flags & INVISIBLE) ||
 436:             (detect_monster || see_invisible || r_see_invisible))) {
 437:             mvaddch(row, col, gmc(monster));
 438:         }
 439:     }
 440:     if ((dungeon[row][col] & DOOR) &&
 441:         (get_room_number(row, col) != cur_room) &&
 442:         (dungeon[mrow][mcol] == FLOOR) && !blind) {
 443:             mvaddch(mrow, mcol, ' ');
 444:     }
 445:     if (dungeon[row][col] & DOOR) {
 446:             dr_course(monster, ((dungeon[mrow][mcol] & TUNNEL) ? 1 : 0),
 447:                 row, col);
 448:     } else {
 449:         monster->row = row;
 450:         monster->col = col;
 451:     }
 452: }
 453: 
 454: mon_can_go(monster, row, col)
 455: register object *monster;
 456: register short row, col;
 457: {
 458:     object *obj;
 459:     short dr, dc;
 460: 
 461:     dr = monster->row - row;    /* check if move distance > 1 */
 462:     if ((dr >= 2) || (dr <= -2)) {
 463:         return(0);
 464:     }
 465:     dc = monster->col - col;
 466:     if ((dc >= 2) || (dc <= -2)) {
 467:         return(0);
 468:     }
 469:     if ((!dungeon[monster->row][col]) || (!dungeon[row][monster->col])) {
 470:         return(0);
 471:     }
 472:     if ((!is_passable(row, col)) || (dungeon[row][col] & MONSTER)) {
 473:         return(0);
 474:     }
 475:     if ((monster->row!=row)&&(monster->col!=col)&&((dungeon[row][col]&DOOR) ||
 476:         (dungeon[monster->row][monster->col]&DOOR))) {
 477:         return(0);
 478:     }
 479:     if (!(monster->m_flags & (FLITS | CONFUSED | CAN_FLIT)) &&
 480:         (monster->trow == NO_ROOM)) {
 481:         if ((monster->row < rogue.row) && (row < monster->row)) return(0);
 482:         if ((monster->row > rogue.row) && (row > monster->row)) return(0);
 483:         if ((monster->col < rogue.col) && (col < monster->col)) return(0);
 484:         if ((monster->col > rogue.col) && (col > monster->col)) return(0);
 485:     }
 486:     if (dungeon[row][col] & OBJECT) {
 487:         obj = object_at(&level_objects, row, col);
 488:         if ((obj->what_is == SCROL) && (obj->which_kind == SCARE_MONSTER)) {
 489:             return(0);
 490:         }
 491:     }
 492:     return(1);
 493: }
 494: 
 495: wake_up(monster)
 496: object *monster;
 497: {
 498:     if (!(monster->m_flags & NAPPING)) {
 499:         monster->m_flags &= (~(ASLEEP | IMITATES | WAKENS));
 500:     }
 501: }
 502: 
 503: wake_room(rn, entering, row, col)
 504: short rn;
 505: boolean entering;
 506: short row, col;
 507: {
 508:     object *monster;
 509:     short wake_percent;
 510:     boolean in_room;
 511: 
 512:     wake_percent = (rn == party_room) ? PARTY_WAKE_PERCENT : WAKE_PERCENT;
 513:     if (stealthy > 0) {
 514:         wake_percent /= (STEALTH_FACTOR + stealthy);
 515:     }
 516: 
 517:     monster = level_monsters.next_monster;
 518: 
 519:     while (monster) {
 520:         in_room = (rn == get_room_number(monster->row, monster->col));
 521:         if (in_room) {
 522:             if (entering) {
 523:                 monster->trow = NO_ROOM;
 524:             } else {
 525:                 monster->trow = row;
 526:                 monster->tcol = col;
 527:             }
 528:         }
 529:         if ((monster->m_flags & WAKENS) &&
 530:             (rn == get_room_number(monster->row, monster->col))) {
 531:             if (rand_percent(wake_percent)) {
 532:                 wake_up(monster);
 533:             }
 534:         }
 535:         monster = monster->next_monster;
 536:     }
 537: }
 538: 
 539: char *
 540: mon_name(monster)
 541: object *monster;
 542: {
 543:     short ch;
 544: 
 545:     if (blind || ((monster->m_flags & INVISIBLE) &&
 546:         !(detect_monster || see_invisible || r_see_invisible))) {
 547:         return("something");
 548:     }
 549:     if (halluc) {
 550:         ch = get_rand('A', 'Z') - 'A';
 551:         return(m_names[ch]);
 552:     }
 553:     ch = monster->m_char - 'A';
 554:     return(m_names[ch]);
 555: }
 556: 
 557: rogue_is_around(row, col)
 558: register row, col;
 559: {
 560:     short rdif, cdif, retval;
 561: 
 562:     rdif = row - rogue.row;
 563:     cdif = col - rogue.col;
 564: 
 565:     retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
 566:     return(retval);
 567: }
 568: 
 569: wanderer()
 570: {
 571:     object *monster;
 572:     short row, col, i;
 573:     boolean found = 0;
 574: 
 575:     for (i = 0; ((i < 15) && (!found)); i++) {
 576:         monster = gr_monster((object *) 0, 0);
 577:         if (!(monster->m_flags & (WAKENS | WANDERS))) {
 578:             free_object(monster);
 579:         } else {
 580:             found = 1;
 581:         }
 582:     }
 583:     if (found) {
 584:         found = 0;
 585:         wake_up(monster);
 586:         for (i = 0; ((i < 25) && (!found)); i++) {
 587:             gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
 588:             if (!rogue_can_see(row, col)) {
 589:                 put_m_at(row, col, monster);
 590:                 found = 1;
 591:             }
 592:         }
 593:         if (!found) {
 594:             free_object(monster);
 595:         }
 596:     }
 597: }
 598: 
 599: show_monsters()
 600: {
 601:     object *monster;
 602: 
 603:     detect_monster = 1;
 604: 
 605:     if (blind) {
 606:         return;
 607:     }
 608:     monster = level_monsters.next_monster;
 609: 
 610:     while (monster) {
 611:         mvaddch(monster->row, monster->col, monster->m_char);
 612:         if (monster->m_flags & IMITATES) {
 613:             monster->m_flags &= (~IMITATES);
 614:             monster->m_flags |= WAKENS;
 615:         }
 616:         monster = monster->next_monster;
 617:     }
 618: }
 619: 
 620: create_monster()
 621: {
 622:     short row, col;
 623:     short i;
 624:     boolean found = 0;
 625:     object *monster;
 626: 
 627:     row = rogue.row;
 628:     col = rogue.col;
 629: 
 630:     for (i = 0; i < 9; i++) {
 631:         rand_around(i, &row, &col);
 632:         if (((row == rogue.row) && (col = rogue.col)) ||
 633:                 (row < MIN_ROW) || (row > (DROWS-2)) ||
 634:                 (col < 0) || (col > (DCOLS-1))) {
 635:             continue;
 636:         }
 637:         if ((!(dungeon[row][col] & MONSTER)) &&
 638:               (dungeon[row][col] & (FLOOR|TUNNEL|STAIRS|DOOR))) {
 639:             found = 1;
 640:             break;
 641:         }
 642:     }
 643:     if (found) {
 644:         monster = gr_monster((object *) 0, 0);
 645:         put_m_at(row, col, monster);
 646:         mvaddch(row, col, gmc(monster));
 647:         if (monster->m_flags & (WANDERS | WAKENS)) {
 648:             wake_up(monster);
 649:         }
 650:     } else {
 651:         message("you hear a faint cry of anguish in the distance", 0);
 652:     }
 653: }
 654: 
 655: put_m_at(row, col, monster)
 656: short row, col;
 657: object *monster;
 658: {
 659:     monster->row = row;
 660:     monster->col = col;
 661:     dungeon[row][col] |= MONSTER;
 662:     monster->trail_char = mvinch(row, col);
 663:     (void) add_to_pack(monster, &level_monsters, 0);
 664:     aim_monster(monster);
 665: }
 666: 
 667: aim_monster(monster)
 668: object *monster;
 669: {
 670:     short i, rn, d, r;
 671: 
 672:     rn = get_room_number(monster->row, monster->col);
 673:     r = get_rand(0, 12);
 674: 
 675:     for (i = 0; i < 4; i++) {
 676:         d = (r + i) % 4;
 677:         if (rooms[rn].doors[d].oth_room != NO_ROOM) {
 678:             monster->trow = rooms[rn].doors[d].door_row;
 679:             monster->tcol = rooms[rn].doors[d].door_col;
 680:             break;
 681:         }
 682:     }
 683: }
 684: 
 685: rogue_can_see(row, col)
 686: register row, col;
 687: {
 688:     register retval;
 689: 
 690:     retval = !blind &&
 691:             (((get_room_number(row, col) == cur_room) &&
 692:                     !(rooms[cur_room].is_room & R_MAZE)) ||
 693:             rogue_is_around(row, col));
 694: 
 695:     return(retval);
 696: }
 697: 
 698: move_confused(monster)
 699: object *monster;
 700: {
 701:     short i, row, col;
 702: 
 703:     if (!(monster->m_flags & ASLEEP)) {
 704:         if (--monster->moves_confused <= 0) {
 705:             monster->m_flags &= (~CONFUSED);
 706:         }
 707:         if (monster->m_flags & STATIONARY) {
 708:             return(coin_toss() ? 1 : 0);
 709:         } else if (rand_percent(15)) {
 710:             return(1);
 711:         }
 712:         row = monster->row;
 713:         col = monster->col;
 714: 
 715:         for (i = 0; i < 9; i++) {
 716:             rand_around(i, &row, &col);
 717:             if ((row == rogue.row) && (col == rogue.col)) {
 718:                 return(0);
 719:             }
 720:             if (mtry(monster, row, col)) {
 721:                 return(1);
 722:             }
 723:         }
 724:     }
 725:     return(0);
 726: }
 727: 
 728: flit(monster)
 729: object *monster;
 730: {
 731:     short i, row, col;
 732: 
 733:     if (!rand_percent(FLIT_PERCENT + ((monster->m_flags & FLIES) ? 20 : 0))) {
 734:         return(0);
 735:     }
 736:     if (rand_percent(10)) {
 737:         return(1);
 738:     }
 739:     row = monster->row;
 740:     col = monster->col;
 741: 
 742:     for (i = 0; i < 9; i++) {
 743:         rand_around(i, &row, &col);
 744:         if ((row == rogue.row) && (col == rogue.col)) {
 745:             continue;
 746:         }
 747:         if (mtry(monster, row, col)) {
 748:             return(1);
 749:         }
 750:     }
 751:     return(1);
 752: }
 753: 
 754: gr_obj_char()
 755: {
 756:     short r;
 757:     char *rs = "%!?]=/):*";
 758: 
 759:     r = get_rand(0, 8);
 760: 
 761:     return(rs[r]);
 762: }
 763: 
 764: no_room_for_monster(rn)
 765: int rn;
 766: {
 767:     short i, j;
 768: 
 769:     for (i = rooms[rn].top_row+1; i < rooms[rn].bottom_row; i++) {
 770:         for (j = rooms[rn].left_col+1; j < rooms[rn].right_col; j++) {
 771:             if (!(dungeon[i][j] & MONSTER)) {
 772:                 return(0);
 773:             }
 774:         }
 775:     }
 776:     return(1);
 777: }
 778: 
 779: aggravate()
 780: {
 781:     object *monster;
 782: 
 783:     message("you hear a high pitched humming noise", 0);
 784: 
 785:     monster = level_monsters.next_monster;
 786: 
 787:     while (monster) {
 788:         wake_up(monster);
 789:         monster->m_flags &= (~IMITATES);
 790:         if (rogue_can_see(monster->row, monster->col)) {
 791:             mvaddch(monster->row, monster->col, monster->m_char);
 792:         }
 793:         monster = monster->next_monster;
 794:     }
 795: }
 796: 
 797: boolean
 798: mon_sees(monster, row, col)
 799: object *monster;
 800: {
 801:     short rn, rdif, cdif, retval;
 802: 
 803:     rn = get_room_number(row, col);
 804: 
 805:     if (    (rn != NO_ROOM) &&
 806:             (rn == get_room_number(monster->row, monster->col)) &&
 807:             !(rooms[rn].is_room & R_MAZE)) {
 808:         return(1);
 809:     }
 810:     rdif = row - monster->row;
 811:     cdif = col - monster->col;
 812: 
 813:     retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
 814:     return(retval);
 815: }
 816: 
 817: mv_aquatars()
 818: {
 819:     object *monster;
 820: 
 821:     monster = level_monsters.next_monster;
 822: 
 823:     while (monster) {
 824:         if ((monster->m_char == 'A') &&
 825:             mon_can_go(monster, rogue.row, rogue.col)) {
 826:             mv_1_monster(monster, rogue.row, rogue.col);
 827:             monster->m_flags |= ALREADY_MOVED;
 828:         }
 829:         monster = monster->next_monster;
 830:     }
 831: }

Defined functions

aggravate defined in line 779; used 1 times
aim_monster defined in line 667; used 1 times
create_monster defined in line 620; used 1 times
flit defined in line 728; used 1 times
gmc defined in line 240; used 3 times
gmc_row_col defined in line 221; used 1 times
gr_monster defined in line 109; used 6 times
gr_obj_char defined in line 754; used 2 times
mon_can_go defined in line 454; used 7 times
move_confused defined in line 698; used 1 times
move_mon_to defined in line 404; used 2 times
mtry defined in line 393; used 11 times
mv_1_monster defined in line 254; used 5 times
mv_aquatars defined in line 817; used 3 times
no_room_for_monster defined in line 764; used 1 times
party_monsters defined in line 181; used 1 times
put_m_at defined in line 655; used 4 times
put_mons defined in line 90; used 1 times
rogue_is_around defined in line 557; used 2 times
show_monsters defined in line 599; used 3 times
wake_room defined in line 503; used 3 times
wanderer defined in line 569; used 1 times

Defined variables

level_monsters defined in line 19; used 7 times
m_names defined in line 22; used 7 times
mon_tab defined in line 51; used 5 times
sccsid defined in line 14; never used
Last modified: 1987-11-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5230
Valid CSS Valid XHTML 1.0 Strict