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