1 /*
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. 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 8.1 (Berkeley) 05/31/93";
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
put_mons()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 *
gr_monster(monster,mn)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
mv_mons()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
party_monsters(rn,n)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
gmc_row_col(row,col)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
gmc(monster)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
mv_1_monster(monster,row,col)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
mtry(monster,row,col)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
move_mon_to(monster,row,col)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
mon_can_go(monster,row,col)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
wake_up(monster)505 wake_up(monster)
506 object *monster;
507 {
508 if (!(monster->m_flags & NAPPING)) {
509 monster->m_flags &= (~(ASLEEP | IMITATES | WAKENS));
510 }
511 }
512
wake_room(rn,entering,row,col)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 *
mon_name(monster)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
rogue_is_around(row,col)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
wanderer()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
show_monsters()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
create_monster()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
put_m_at(row,col,monster)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
aim_monster(monster)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
rogue_can_see(row,col)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
move_confused(monster)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
flit(monster)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
gr_obj_char()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
no_room_for_monster(rn)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
aggravate()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
mon_sees(monster,row,col)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
mv_aquatars()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