etc/protocols - sync with NetBSD-8
[minix.git] / games / rogue / monster.c
blob1d644f65bbf1d2db40f3f8a9a9bbedbe79655e9b
1 /* $NetBSD: monster.c,v 1.17 2013/08/11 03:44:27 dholland Exp $ */
3 /*
4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Timothy C. Stoehr.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
35 #include <sys/cdefs.h>
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)monster.c 8.1 (Berkeley) 5/31/93";
39 #else
40 __RCSID("$NetBSD: monster.c,v 1.17 2013/08/11 03:44:27 dholland Exp $");
41 #endif
42 #endif /* not lint */
45 * monster.c
47 * This source herein may be modified and/or distributed by anybody who
48 * so desires, with the following restrictions:
49 * 1.) No portion of this notice shall be removed.
50 * 2.) Credit shall not be taken for the creation of this source.
51 * 3.) This code is not to be traded, sold, or used for personal
52 * gain or profit.
56 #include "rogue.h"
58 object level_monsters;
59 boolean mon_disappeared;
61 const char *const m_names[] = {
62 "aquator",
63 "bat",
64 "centaur",
65 "dragon",
66 "emu",
67 "venus fly-trap",
68 "griffin",
69 "hobgoblin",
70 "ice monster",
71 "jabberwock",
72 "kestrel",
73 "leprechaun",
74 "medusa",
75 "nymph",
76 "orc",
77 "phantom",
78 "quagga",
79 "rattlesnake",
80 "snake",
81 "troll",
82 "black unicorn",
83 "vampire",
84 "wraith",
85 "xeroc",
86 "yeti",
87 "zombie"
90 #define FILL 0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
92 static object mon_tab[MONSTERS] = {
93 {(ASLEEP|WAKENS|WANDERS|RUSTS),"0d0",25,'A',20,9,18,100,0,0, FILL},
94 {(ASLEEP|WANDERS|FLITS|FLIES),"1d3",10,'B',2,1,8,60,0,0, FILL},
95 {(ASLEEP|WANDERS),"3d3/2d5",32,'C',15,7,16,85,0,10, FILL},
96 {(ASLEEP|WAKENS|FLAMES),"4d6/4d9",145,'D',5000,21,126,100,0,90, FILL},
97 {(ASLEEP|WAKENS),"1d3",11,'E',2,1,7,65,0,0, FILL},
98 {(HOLDS|STATIONARY),"5d5",73,'F',91,12,126,80,0,0, FILL},
99 {(ASLEEP|WAKENS|WANDERS|FLIES),"5d5/5d5",115,'G',
100 2000,20,126,85,0,10, FILL},
101 {(ASLEEP|WAKENS|WANDERS),"1d3/1d2",15,'H',3,1,10,67,0,0, FILL},
102 {(ASLEEP|FREEZES),"0d0",15,'I',5,2,11,68,0,0, FILL},
103 {(ASLEEP|WANDERS),"3d10/4d5",132,'J',3000,21,126,100,0,0, FILL},
104 {(ASLEEP|WAKENS|WANDERS|FLIES),"1d4",10,'K',2,1,6,60,0,0, FILL},
105 {(ASLEEP|STEALS_GOLD),"0d0",25,'L',21,6,16,75,0,0, FILL},
106 {(ASLEEP|WAKENS|WANDERS|CONFUSES),"4d4/3d7",97,'M',
107 250,18,126,85,0,25, FILL},
108 {(ASLEEP|STEALS_ITEM),"0d0",25,'N',39,10,19,75,0,100, FILL},
109 {(ASLEEP|WANDERS|WAKENS|SEEKS_GOLD),"1d6",25,'O',5,4,13,70,0,10, FILL},
110 {(ASLEEP|INVISIBLE|WANDERS|FLITS),"5d4",76,'P',120,15,24,80,0,50, FILL},
111 {(ASLEEP|WAKENS|WANDERS),"3d5",30,'Q',20,8,17,78,0,20, FILL},
112 {(ASLEEP|WAKENS|WANDERS|STINGS),"2d5",19,'R',10,3,12,70,0,0, FILL},
113 {(ASLEEP|WAKENS|WANDERS),"1d3",8,'S',2,1,9,50,0,0, FILL},
114 {(ASLEEP|WAKENS|WANDERS),"4d6/1d4",75,'T',125,13,22,75,0,33, FILL},
115 {(ASLEEP|WAKENS|WANDERS),"4d10",90,'U',
116 200,17,26,85,0,33, FILL},
117 {(ASLEEP|WAKENS|WANDERS|DRAINS_LIFE),"1d14/1d4",55,'V',
118 350,19,126,85,0,18, FILL},
119 {(ASLEEP|WANDERS|DROPS_LEVEL),"2d8",45,'W',55,14,23,75,0,0, FILL},
120 {(ASLEEP|IMITATES),"4d6",42,'X',110,16,25,75,0,0, FILL},
121 {(ASLEEP|WANDERS),"3d6",35,'Y',50,11,20,80,0,20, FILL},
122 {(ASLEEP|WAKENS|WANDERS),"1d7",21,'Z',8,5,14,69,0,0, FILL}
125 static void aim_monster(object *);
126 static int flit(object *);
127 static int move_confused(object *);
128 static int mtry(object *, short, short);
129 static int no_room_for_monster(int);
130 static void put_m_at(short, short, object *);
131 static int rogue_is_around(int, int);
133 void
134 put_mons(void)
136 short i;
137 short n;
138 object *monster;
139 short row, col;
141 n = get_rand(4, 6);
143 for (i = 0; i < n; i++) {
144 monster = gr_monster(NULL, 0);
145 if ((monster->m_flags & WANDERS) && coin_toss()) {
146 wake_up(monster);
148 gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
149 put_m_at(row, col, monster);
153 object *
154 gr_monster(object *monster, int mn)
156 if (!monster) {
157 monster = alloc_object();
159 for (;;) {
160 mn = get_rand(0, MONSTERS-1);
161 if ((cur_level >= mon_tab[mn].first_level) &&
162 (cur_level <= mon_tab[mn].last_level)) {
163 break;
167 *monster = mon_tab[mn];
168 if (monster->m_flags & IMITATES) {
169 monster->disguise = gr_obj_char();
171 if (cur_level > (AMULET_LEVEL + 2)) {
172 monster->m_flags |= HASTED;
174 monster->trow = NO_ROOM;
175 return(monster);
178 void
179 mv_mons(void)
181 object *monster, *next_monster, *test_mons;
182 boolean flew;
184 if (haste_self % 2) {
185 return;
188 monster = level_monsters.next_monster;
190 while (monster) {
191 next_monster = monster->next_monster;
192 mon_disappeared = 0;
193 if (monster->m_flags & HASTED) {
194 mv_1_monster(monster, rogue.row, rogue.col);
195 if (mon_disappeared) {
196 goto NM;
198 } else if (monster->m_flags & SLOWED) {
199 monster->slowed_toggle = !monster->slowed_toggle;
200 if (monster->slowed_toggle) {
201 goto NM;
204 if ((monster->m_flags & CONFUSED) && move_confused(monster)) {
205 goto NM;
207 flew = 0;
208 if ( (monster->m_flags & FLIES) &&
209 !(monster->m_flags & NAPPING) &&
210 !mon_can_go(monster, rogue.row, rogue.col)) {
211 flew = 1;
212 mv_1_monster(monster, rogue.row, rogue.col);
213 if (mon_disappeared) {
214 goto NM;
217 if (!(flew && mon_can_go(monster, rogue.row, rogue.col))) {
218 mv_1_monster(monster, rogue.row, rogue.col);
220 NM: test_mons = level_monsters.next_monster;
221 monster = NULL;
222 while (test_mons)
224 if (next_monster == test_mons)
226 monster = next_monster;
227 break;
229 test_mons = test_mons -> next_monster;
234 void
235 party_monsters(int rn, int n)
237 short i, j;
238 short row, col;
239 object *monster;
240 boolean found;
242 row = col = 0;
243 n += n;
245 for (i = 0; i < MONSTERS; i++) {
246 mon_tab[i].first_level -= (cur_level % 3);
248 for (i = 0; i < n; i++) {
249 if (no_room_for_monster(rn)) {
250 break;
252 for (j = found = 0; ((!found) && (j < 250)); j++) {
253 row = get_rand(rooms[rn].top_row+1,
254 rooms[rn].bottom_row-1);
255 col = get_rand(rooms[rn].left_col+1,
256 rooms[rn].right_col-1);
257 if ((!(dungeon[row][col] & MONSTER)) &&
258 (dungeon[row][col] & (FLOOR | TUNNEL))) {
259 found = 1;
262 if (found) {
263 monster = gr_monster((object *)0, 0);
264 if (!(monster->m_flags & IMITATES)) {
265 monster->m_flags |= WAKENS;
267 put_m_at(row, col, monster);
270 for (i = 0; i < MONSTERS; i++) {
271 mon_tab[i].first_level += (cur_level % 3);
275 char
276 gmc_row_col(int row, int col)
278 object *monster;
280 if ((monster = object_at(&level_monsters, row, col)) != NULL) {
281 if ((!(detect_monster || see_invisible || r_see_invisible) &&
282 (monster->m_flags & INVISIBLE)) || blind) {
283 return(monster->trail_char);
285 if (monster->m_flags & IMITATES) {
286 return(monster->disguise);
288 return(monster->m_char);
289 } else {
290 return('&'); /* BUG if this ever happens */
294 char
295 gmc(object *monster)
297 if ((!(detect_monster || see_invisible || r_see_invisible) &&
298 (monster->m_flags & INVISIBLE))
299 || blind) {
300 return(monster->trail_char);
302 if (monster->m_flags & IMITATES) {
303 return(monster->disguise);
305 return(monster->m_char);
308 void
309 mv_1_monster(object *monster, short row, short col)
311 short i, n;
312 boolean tried[6];
314 if (monster->m_flags & ASLEEP) {
315 if (monster->m_flags & NAPPING) {
316 if (--monster->nap_length <= 0) {
317 monster->m_flags &= (~(NAPPING | ASLEEP));
319 return;
321 if ((monster->m_flags & WAKENS) &&
322 rogue_is_around(monster->row, monster->col) &&
323 rand_percent(((stealthy > 0) ?
324 (WAKE_PERCENT / (STEALTH_FACTOR + stealthy)) :
325 WAKE_PERCENT))) {
326 wake_up(monster);
328 return;
329 } else if (monster->m_flags & ALREADY_MOVED) {
330 monster->m_flags &= (~ALREADY_MOVED);
331 return;
333 if ((monster->m_flags & FLITS) && flit(monster)) {
334 return;
336 if ((monster->m_flags & STATIONARY) &&
337 (!mon_can_go(monster, rogue.row, rogue.col))) {
338 return;
340 if (monster->m_flags & FREEZING_ROGUE) {
341 return;
343 if ((monster->m_flags & CONFUSES) && m_confuse(monster)) {
344 return;
346 if (mon_can_go(monster, rogue.row, rogue.col)) {
347 mon_hit(monster);
348 return;
350 if ((monster->m_flags & FLAMES) && flame_broil(monster)) {
351 return;
353 if ((monster->m_flags & SEEKS_GOLD) && seek_gold(monster)) {
354 return;
356 if ((monster->trow == monster->row) &&
357 (monster->tcol == monster->col)) {
358 monster->trow = NO_ROOM;
359 } else if (monster->trow != NO_ROOM) {
360 row = monster->trow;
361 col = monster->tcol;
363 if (monster->row > row) {
364 row = monster->row - 1;
365 } else if (monster->row < row) {
366 row = monster->row + 1;
368 if ((dungeon[row][monster->col] & DOOR) &&
369 mtry(monster, row, monster->col)) {
370 return;
372 if (monster->col > col) {
373 col = monster->col - 1;
374 } else if (monster->col < col) {
375 col = monster->col + 1;
377 if ((dungeon[monster->row][col] & DOOR) &&
378 mtry(monster, monster->row, col)) {
379 return;
381 if (mtry(monster, row, col)) {
382 return;
385 for (i = 0; i <= 5; i++) tried[i] = 0;
387 for (i = 0; i < 6; i++) {
388 NEXT_TRY: n = get_rand(0, 5);
389 switch(n) {
390 case 0:
391 if (!tried[n] && mtry(monster, row, monster->col-1)) {
392 goto O;
394 break;
395 case 1:
396 if (!tried[n] && mtry(monster, row, monster->col)) {
397 goto O;
399 break;
400 case 2:
401 if (!tried[n] && mtry(monster, row, monster->col+1)) {
402 goto O;
404 break;
405 case 3:
406 if (!tried[n] && mtry(monster, monster->row-1, col)) {
407 goto O;
409 break;
410 case 4:
411 if (!tried[n] && mtry(monster, monster->row, col)) {
412 goto O;
414 break;
415 case 5:
416 if (!tried[n] && mtry(monster, monster->row+1, col)) {
417 goto O;
419 break;
421 if (!tried[n]) {
422 tried[n] = 1;
423 } else {
424 goto NEXT_TRY;
428 if ((monster->row == monster->o_row) && (monster->col == monster->o_col)) {
429 if (++(monster->o) > 4) {
430 if ((monster->trow == NO_ROOM) &&
431 (!mon_sees(monster, rogue.row, rogue.col))) {
432 monster->trow = get_rand(1, (DROWS - 2));
433 monster->tcol = get_rand(0, (DCOLS - 1));
434 } else {
435 monster->trow = NO_ROOM;
436 monster->o = 0;
439 } else {
440 monster->o_row = monster->row;
441 monster->o_col = monster->col;
442 monster->o = 0;
446 static int
447 mtry(object *monster, short row, short col)
449 if (mon_can_go(monster, row, col)) {
450 move_mon_to(monster, row, col);
451 return(1);
453 return(0);
456 void
457 move_mon_to(object *monster, short row, short col)
459 short c;
460 int mrow, mcol;
462 mrow = monster->row;
463 mcol = monster->col;
465 dungeon[mrow][mcol] &= ~MONSTER;
466 dungeon[row][col] |= MONSTER;
468 c = mvinch(mrow, mcol);
470 if ((c >= 'A') && (c <= 'Z')) {
471 if (!detect_monster) {
472 mvaddch(mrow, mcol, monster->trail_char);
473 } else {
474 if (rogue_can_see(mrow, mcol)) {
475 mvaddch(mrow, mcol, monster->trail_char);
476 } else {
477 if (monster->trail_char == '.') {
478 monster->trail_char = ' ';
480 mvaddch(mrow, mcol, monster->trail_char);
484 monster->trail_char = mvinch(row, col);
485 if (!blind && (detect_monster || rogue_can_see(row, col))) {
486 if ((!(monster->m_flags & INVISIBLE) ||
487 (detect_monster || see_invisible || r_see_invisible))) {
488 mvaddch(row, col, gmc(monster));
491 if ((dungeon[row][col] & DOOR) &&
492 (get_room_number(row, col) != cur_room) &&
493 (dungeon[mrow][mcol] == FLOOR) && !blind) {
494 mvaddch(mrow, mcol, ' ');
496 if (dungeon[row][col] & DOOR) {
497 dr_course(monster, ((dungeon[mrow][mcol] & TUNNEL) ? 1 : 0),
498 row, col);
499 } else {
500 monster->row = row;
501 monster->col = col;
506 mon_can_go(const object *monster, short row, short col)
508 object *obj;
509 short dr, dc;
511 dr = monster->row - row; /* check if move distance > 1 */
512 if ((dr >= 2) || (dr <= -2)) {
513 return(0);
515 dc = monster->col - col;
516 if ((dc >= 2) || (dc <= -2)) {
517 return(0);
519 if ((!dungeon[monster->row][col]) || (!dungeon[row][monster->col])) {
520 return(0);
522 if ((!is_passable(row, col)) || (dungeon[row][col] & MONSTER)) {
523 return(0);
525 if ((monster->row!=row)&&(monster->col!=col)&&((dungeon[row][col]&DOOR) ||
526 (dungeon[monster->row][monster->col]&DOOR))) {
527 return(0);
529 if (!(monster->m_flags & (FLITS | CONFUSED | CAN_FLIT)) &&
530 (monster->trow == NO_ROOM)) {
531 if ((monster->row < rogue.row) && (row < monster->row)) return(0);
532 if ((monster->row > rogue.row) && (row > monster->row)) return(0);
533 if ((monster->col < rogue.col) && (col < monster->col)) return(0);
534 if ((monster->col > rogue.col) && (col > monster->col)) return(0);
536 if (dungeon[row][col] & OBJECT) {
537 obj = object_at(&level_objects, row, col);
538 if ((obj->what_is == SCROL) && (obj->which_kind == SCARE_MONSTER)) {
539 return(0);
542 return(1);
545 void
546 wake_up(object *monster)
548 if (!(monster->m_flags & NAPPING)) {
549 monster->m_flags &= (~(ASLEEP | IMITATES | WAKENS));
553 void
554 wake_room(short rn, boolean entering, short row, short col)
556 object *monster;
557 short wake_percent;
558 boolean in_room;
560 wake_percent = (rn == party_room) ? PARTY_WAKE_PERCENT : WAKE_PERCENT;
561 if (stealthy > 0) {
562 wake_percent /= (STEALTH_FACTOR + stealthy);
565 monster = level_monsters.next_monster;
567 while (monster) {
568 in_room = (rn == get_room_number(monster->row, monster->col));
569 if (in_room) {
570 if (entering) {
571 monster->trow = NO_ROOM;
572 } else {
573 monster->trow = row;
574 monster->tcol = col;
577 if ((monster->m_flags & WAKENS) &&
578 (rn == get_room_number(monster->row, monster->col))) {
579 if (rand_percent(wake_percent)) {
580 wake_up(monster);
583 monster = monster->next_monster;
587 const char *
588 mon_name(const object *monster)
590 short ch;
592 if (blind || ((monster->m_flags & INVISIBLE) &&
593 !(detect_monster || see_invisible || r_see_invisible))) {
594 return("something");
596 if (halluc) {
597 ch = get_rand('A', 'Z') - 'A';
598 return(m_names[ch]);
600 ch = monster->m_char - 'A';
601 return(m_names[ch]);
604 static int
605 rogue_is_around(int row, int col)
607 short rdif, cdif, retval;
609 rdif = row - rogue.row;
610 cdif = col - rogue.col;
612 retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
613 return(retval);
616 void
617 wanderer(void)
619 object *monster;
620 short row, col, i;
621 boolean found = 0;
623 monster = NULL; /* XXXGCC -Wuninitialized [powerpc] */
625 for (i = 0; ((i < 15) && (!found)); i++) {
626 monster = gr_monster(NULL, 0);
627 if (!(monster->m_flags & (WAKENS | WANDERS))) {
628 free_object(monster);
629 } else {
630 found = 1;
633 if (found) {
634 found = 0;
635 wake_up(monster);
636 for (i = 0; ((i < 25) && (!found)); i++) {
637 gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
638 if (!rogue_can_see(row, col)) {
639 put_m_at(row, col, monster);
640 found = 1;
643 if (!found) {
644 free_object(monster);
649 void
650 show_monsters(void)
652 object *monster;
654 detect_monster = 1;
656 if (blind) {
657 return;
659 monster = level_monsters.next_monster;
661 while (monster) {
662 mvaddch(monster->row, monster->col, monster->m_char);
663 if (monster->m_flags & IMITATES) {
664 monster->m_flags &= (~IMITATES);
665 monster->m_flags |= WAKENS;
667 monster = monster->next_monster;
671 void
672 create_monster(void)
674 short row, col;
675 short i;
676 boolean found = 0;
677 object *monster;
679 row = rogue.row;
680 col = rogue.col;
682 for (i = 0; i < 9; i++) {
683 rand_around(i, &row, &col);
684 if (((row == rogue.row) && (col == rogue.col)) ||
685 (row < MIN_ROW) || (row > (DROWS-2)) ||
686 (col < 0) || (col > (DCOLS-1))) {
687 continue;
689 if ((!(dungeon[row][col] & MONSTER)) &&
690 (dungeon[row][col] & (FLOOR|TUNNEL|STAIRS|DOOR))) {
691 found = 1;
692 break;
695 if (found) {
696 monster = gr_monster((object *)0, 0);
697 put_m_at(row, col, monster);
698 mvaddch(row, col, gmc(monster));
699 if (monster->m_flags & (WANDERS | WAKENS)) {
700 wake_up(monster);
702 } else {
703 messagef(0, "you hear a faint cry of anguish in the distance");
707 static void
708 put_m_at(short row, short col, object *monster)
710 monster->row = row;
711 monster->col = col;
712 dungeon[row][col] |= MONSTER;
713 monster->trail_char = mvinch(row, col);
714 (void)add_to_pack(monster, &level_monsters, 0);
715 aim_monster(monster);
718 static void
719 aim_monster(object *monster)
721 short i, rn, d, r;
723 rn = get_room_number(monster->row, monster->col);
724 if (rn == NO_ROOM)
725 clean_up("aim_monster: monster not in room");
726 r = get_rand(0, 12);
728 for (i = 0; i < 4; i++) {
729 d = (r + i) % 4;
730 if (rooms[rn].doors[d].oth_room != NO_ROOM) {
731 monster->trow = rooms[rn].doors[d].door_row;
732 monster->tcol = rooms[rn].doors[d].door_col;
733 break;
739 rogue_can_see(int row, int col)
741 int retval;
743 retval = !blind &&
744 (((get_room_number(row, col) == cur_room) &&
745 !(rooms[cur_room].is_room & R_MAZE)) ||
746 rogue_is_around(row, col));
748 return(retval);
751 static int
752 move_confused(object *monster)
754 short i, row, col;
756 if (!(monster->m_flags & ASLEEP)) {
757 if (--monster->moves_confused <= 0) {
758 monster->m_flags &= (~CONFUSED);
760 if (monster->m_flags & STATIONARY) {
761 return(coin_toss() ? 1 : 0);
762 } else if (rand_percent(15)) {
763 return(1);
765 row = monster->row;
766 col = monster->col;
768 for (i = 0; i < 9; i++) {
769 rand_around(i, &row, &col);
770 if ((row == rogue.row) && (col == rogue.col)) {
771 return(0);
773 if (mtry(monster, row, col)) {
774 return(1);
778 return(0);
781 static int
782 flit(object *monster)
784 short i, row, col;
786 if (!rand_percent(FLIT_PERCENT + ((monster->m_flags & FLIES) ? 20 : 0))) {
787 return(0);
789 if (rand_percent(10)) {
790 return(1);
792 row = monster->row;
793 col = monster->col;
795 for (i = 0; i < 9; i++) {
796 rand_around(i, &row, &col);
797 if ((row == rogue.row) && (col == rogue.col)) {
798 continue;
800 if (mtry(monster, row, col)) {
801 return(1);
804 return(1);
807 char
808 gr_obj_char(void)
810 short r;
811 const char *rs = "%!?]=/):*";
813 r = get_rand(0, 8);
815 return(rs[r]);
818 static int
819 no_room_for_monster(int rn)
821 short i, j;
823 for (i = rooms[rn].top_row+1; i < rooms[rn].bottom_row; i++) {
824 for (j = rooms[rn].left_col+1; j < rooms[rn].right_col; j++) {
825 if (!(dungeon[i][j] & MONSTER)) {
826 return(0);
830 return(1);
833 void
834 aggravate(void)
836 object *monster;
838 messagef(0, "you hear a high pitched humming noise");
840 monster = level_monsters.next_monster;
842 while (monster) {
843 wake_up(monster);
844 monster->m_flags &= (~IMITATES);
845 if (rogue_can_see(monster->row, monster->col)) {
846 mvaddch(monster->row, monster->col, monster->m_char);
848 monster = monster->next_monster;
852 boolean
853 mon_sees(const object *monster, int row, int col)
855 short rn, rdif, cdif, retval;
857 rn = get_room_number(row, col);
859 if ( (rn != NO_ROOM) &&
860 (rn == get_room_number(monster->row, monster->col)) &&
861 !(rooms[rn].is_room & R_MAZE)) {
862 return(1);
864 rdif = row - monster->row;
865 cdif = col - monster->col;
867 retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
868 return(retval);
871 void
872 mv_aquatars(void)
874 object *monster;
876 monster = level_monsters.next_monster;
878 while (monster) {
879 if ((monster->m_char == 'A') &&
880 mon_can_go(monster, rogue.row, rogue.col)) {
881 mv_1_monster(monster, rogue.row, rogue.col);
882 monster->m_flags |= ALREADY_MOVED;
884 monster = monster->next_monster;