Sync usage with man page.
[netbsd-mini2440.git] / games / rogue / monster.c
blob17855a7ef6639c5cb696958adbfd8584176f1c85
1 /* $NetBSD: monster.c,v 1.15 2009/08/12 08:44:45 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.15 2009/08/12 08:44:45 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 static object mon_tab[MONSTERS] = {
91 {(ASLEEP|WAKENS|WANDERS|RUSTS),"0d0",25,'A',20,9,18,100,0,0,0,0,0},
92 {(ASLEEP|WANDERS|FLITS|FLIES),"1d3",10,'B',2,1,8,60,0,0,0,0,0},
93 {(ASLEEP|WANDERS),"3d3/2d5",32,'C',15,7,16,85,0,10,0,0,0},
94 {(ASLEEP|WAKENS|FLAMES),"4d6/4d9",145,'D',5000,21,126,100,0,90,0,0,0},
95 {(ASLEEP|WAKENS),"1d3",11,'E',2,1,7,65,0,0,0,0,0},
96 {(HOLDS|STATIONARY),"5d5",73,'F',91,12,126,80,0,0,0,0,0},
97 {(ASLEEP|WAKENS|WANDERS|FLIES),"5d5/5d5",115,'G',
98 2000,20,126,85,0,10,0,0,0},
99 {(ASLEEP|WAKENS|WANDERS),"1d3/1d2",15,'H',3,1,10,67,0,0,0,0,0},
100 {(ASLEEP|FREEZES),"0d0",15,'I',5,2,11,68,0,0,0,0,0},
101 {(ASLEEP|WANDERS),"3d10/4d5",132,'J',3000,21,126,100,0,0,0,0,0},
102 {(ASLEEP|WAKENS|WANDERS|FLIES),"1d4",10,'K',2,1,6,60,0,0,0,0,0},
103 {(ASLEEP|STEALS_GOLD),"0d0",25,'L',21,6,16,75,0,0,0,0,0},
104 {(ASLEEP|WAKENS|WANDERS|CONFUSES),"4d4/3d7",97,'M',
105 250,18,126,85,0,25,0,0,0},
106 {(ASLEEP|STEALS_ITEM),"0d0",25,'N',39,10,19,75,0,100,0,0,0},
107 {(ASLEEP|WANDERS|WAKENS|SEEKS_GOLD),"1d6",25,'O',5,4,13,70,0,10,0,0,0},
108 {(ASLEEP|INVISIBLE|WANDERS|FLITS),"5d4",76,'P',120,15,24,80,0,50,0,0,0},
109 {(ASLEEP|WAKENS|WANDERS),"3d5",30,'Q',20,8,17,78,0,20,0,0,0},
110 {(ASLEEP|WAKENS|WANDERS|STINGS),"2d5",19,'R',10,3,12,70,0,0,0,0,0},
111 {(ASLEEP|WAKENS|WANDERS),"1d3",8,'S',2,1,9,50,0,0,0,0,0},
112 {(ASLEEP|WAKENS|WANDERS),"4d6/1d4",75,'T',125,13,22,75,0,33,0,0,0},
113 {(ASLEEP|WAKENS|WANDERS),"4d10",90,'U',
114 200,17,26,85,0,33,0,0,0},
115 {(ASLEEP|WAKENS|WANDERS|DRAINS_LIFE),"1d14/1d4",55,'V',
116 350,19,126,85,0,18,0,0,0},
117 {(ASLEEP|WANDERS|DROPS_LEVEL),"2d8",45,'W',55,14,23,75,0,0,0,0,0},
118 {(ASLEEP|IMITATES),"4d6",42,'X',110,16,25,75,0,0,0,0,0},
119 {(ASLEEP|WANDERS),"3d6",35,'Y',50,11,20,80,0,20,0,0,0},
120 {(ASLEEP|WAKENS|WANDERS),"1d7",21,'Z',8,5,14,69,0,0,0,0,0}
123 static void aim_monster(object *);
124 static int flit(object *);
125 static int move_confused(object *);
126 static int mtry(object *, short, short);
127 static int no_room_for_monster(int);
128 static void put_m_at(short, short, object *);
129 static int rogue_is_around(int, int);
131 void
132 put_mons(void)
134 short i;
135 short n;
136 object *monster;
137 short row, col;
139 n = get_rand(4, 6);
141 for (i = 0; i < n; i++) {
142 monster = gr_monster(NULL, 0);
143 if ((monster->m_flags & WANDERS) && coin_toss()) {
144 wake_up(monster);
146 gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
147 put_m_at(row, col, monster);
151 object *
152 gr_monster(object *monster, int mn)
154 if (!monster) {
155 monster = alloc_object();
157 for (;;) {
158 mn = get_rand(0, MONSTERS-1);
159 if ((cur_level >= mon_tab[mn].first_level) &&
160 (cur_level <= mon_tab[mn].last_level)) {
161 break;
165 *monster = mon_tab[mn];
166 if (monster->m_flags & IMITATES) {
167 monster->disguise = gr_obj_char();
169 if (cur_level > (AMULET_LEVEL + 2)) {
170 monster->m_flags |= HASTED;
172 monster->trow = NO_ROOM;
173 return(monster);
176 void
177 mv_mons(void)
179 object *monster, *next_monster, *test_mons;
180 boolean flew;
182 if (haste_self % 2) {
183 return;
186 monster = level_monsters.next_monster;
188 while (monster) {
189 next_monster = monster->next_monster;
190 mon_disappeared = 0;
191 if (monster->m_flags & HASTED) {
192 mv_1_monster(monster, rogue.row, rogue.col);
193 if (mon_disappeared) {
194 goto NM;
196 } else if (monster->m_flags & SLOWED) {
197 monster->slowed_toggle = !monster->slowed_toggle;
198 if (monster->slowed_toggle) {
199 goto NM;
202 if ((monster->m_flags & CONFUSED) && move_confused(monster)) {
203 goto NM;
205 flew = 0;
206 if ( (monster->m_flags & FLIES) &&
207 !(monster->m_flags & NAPPING) &&
208 !mon_can_go(monster, rogue.row, rogue.col)) {
209 flew = 1;
210 mv_1_monster(monster, rogue.row, rogue.col);
211 if (mon_disappeared) {
212 goto NM;
215 if (!(flew && mon_can_go(monster, rogue.row, rogue.col))) {
216 mv_1_monster(monster, rogue.row, rogue.col);
218 NM: test_mons = level_monsters.next_monster;
219 monster = NULL;
220 while (test_mons)
222 if (next_monster == test_mons)
224 monster = next_monster;
225 break;
227 test_mons = test_mons -> next_monster;
232 void
233 party_monsters(int rn, int n)
235 short i, j;
236 short row, col;
237 object *monster;
238 boolean found;
240 row = col = 0;
241 n += n;
243 for (i = 0; i < MONSTERS; i++) {
244 mon_tab[i].first_level -= (cur_level % 3);
246 for (i = 0; i < n; i++) {
247 if (no_room_for_monster(rn)) {
248 break;
250 for (j = found = 0; ((!found) && (j < 250)); j++) {
251 row = get_rand(rooms[rn].top_row+1,
252 rooms[rn].bottom_row-1);
253 col = get_rand(rooms[rn].left_col+1,
254 rooms[rn].right_col-1);
255 if ((!(dungeon[row][col] & MONSTER)) &&
256 (dungeon[row][col] & (FLOOR | TUNNEL))) {
257 found = 1;
260 if (found) {
261 monster = gr_monster((object *)0, 0);
262 if (!(monster->m_flags & IMITATES)) {
263 monster->m_flags |= WAKENS;
265 put_m_at(row, col, monster);
268 for (i = 0; i < MONSTERS; i++) {
269 mon_tab[i].first_level += (cur_level % 3);
273 char
274 gmc_row_col(int row, int col)
276 object *monster;
278 if ((monster = object_at(&level_monsters, row, col)) != NULL) {
279 if ((!(detect_monster || see_invisible || r_see_invisible) &&
280 (monster->m_flags & INVISIBLE)) || blind) {
281 return(monster->trail_char);
283 if (monster->m_flags & IMITATES) {
284 return(monster->disguise);
286 return(monster->m_char);
287 } else {
288 return('&'); /* BUG if this ever happens */
292 char
293 gmc(object *monster)
295 if ((!(detect_monster || see_invisible || r_see_invisible) &&
296 (monster->m_flags & INVISIBLE))
297 || blind) {
298 return(monster->trail_char);
300 if (monster->m_flags & IMITATES) {
301 return(monster->disguise);
303 return(monster->m_char);
306 void
307 mv_1_monster(object *monster, short row, short col)
309 short i, n;
310 boolean tried[6];
312 if (monster->m_flags & ASLEEP) {
313 if (monster->m_flags & NAPPING) {
314 if (--monster->nap_length <= 0) {
315 monster->m_flags &= (~(NAPPING | ASLEEP));
317 return;
319 if ((monster->m_flags & WAKENS) &&
320 rogue_is_around(monster->row, monster->col) &&
321 rand_percent(((stealthy > 0) ?
322 (WAKE_PERCENT / (STEALTH_FACTOR + stealthy)) :
323 WAKE_PERCENT))) {
324 wake_up(monster);
326 return;
327 } else if (monster->m_flags & ALREADY_MOVED) {
328 monster->m_flags &= (~ALREADY_MOVED);
329 return;
331 if ((monster->m_flags & FLITS) && flit(monster)) {
332 return;
334 if ((monster->m_flags & STATIONARY) &&
335 (!mon_can_go(monster, rogue.row, rogue.col))) {
336 return;
338 if (monster->m_flags & FREEZING_ROGUE) {
339 return;
341 if ((monster->m_flags & CONFUSES) && m_confuse(monster)) {
342 return;
344 if (mon_can_go(monster, rogue.row, rogue.col)) {
345 mon_hit(monster);
346 return;
348 if ((monster->m_flags & FLAMES) && flame_broil(monster)) {
349 return;
351 if ((monster->m_flags & SEEKS_GOLD) && seek_gold(monster)) {
352 return;
354 if ((monster->trow == monster->row) &&
355 (monster->tcol == monster->col)) {
356 monster->trow = NO_ROOM;
357 } else if (monster->trow != NO_ROOM) {
358 row = monster->trow;
359 col = monster->tcol;
361 if (monster->row > row) {
362 row = monster->row - 1;
363 } else if (monster->row < row) {
364 row = monster->row + 1;
366 if ((dungeon[row][monster->col] & DOOR) &&
367 mtry(monster, row, monster->col)) {
368 return;
370 if (monster->col > col) {
371 col = monster->col - 1;
372 } else if (monster->col < col) {
373 col = monster->col + 1;
375 if ((dungeon[monster->row][col] & DOOR) &&
376 mtry(monster, monster->row, col)) {
377 return;
379 if (mtry(monster, row, col)) {
380 return;
383 for (i = 0; i <= 5; i++) tried[i] = 0;
385 for (i = 0; i < 6; i++) {
386 NEXT_TRY: n = get_rand(0, 5);
387 switch(n) {
388 case 0:
389 if (!tried[n] && mtry(monster, row, monster->col-1)) {
390 goto O;
392 break;
393 case 1:
394 if (!tried[n] && mtry(monster, row, monster->col)) {
395 goto O;
397 break;
398 case 2:
399 if (!tried[n] && mtry(monster, row, monster->col+1)) {
400 goto O;
402 break;
403 case 3:
404 if (!tried[n] && mtry(monster, monster->row-1, col)) {
405 goto O;
407 break;
408 case 4:
409 if (!tried[n] && mtry(monster, monster->row, col)) {
410 goto O;
412 break;
413 case 5:
414 if (!tried[n] && mtry(monster, monster->row+1, col)) {
415 goto O;
417 break;
419 if (!tried[n]) {
420 tried[n] = 1;
421 } else {
422 goto NEXT_TRY;
426 if ((monster->row == monster->o_row) && (monster->col == monster->o_col)) {
427 if (++(monster->o) > 4) {
428 if ((monster->trow == NO_ROOM) &&
429 (!mon_sees(monster, rogue.row, rogue.col))) {
430 monster->trow = get_rand(1, (DROWS - 2));
431 monster->tcol = get_rand(0, (DCOLS - 1));
432 } else {
433 monster->trow = NO_ROOM;
434 monster->o = 0;
437 } else {
438 monster->o_row = monster->row;
439 monster->o_col = monster->col;
440 monster->o = 0;
444 static int
445 mtry(object *monster, short row, short col)
447 if (mon_can_go(monster, row, col)) {
448 move_mon_to(monster, row, col);
449 return(1);
451 return(0);
454 void
455 move_mon_to(object *monster, short row, short col)
457 short c;
458 int mrow, mcol;
460 mrow = monster->row;
461 mcol = monster->col;
463 dungeon[mrow][mcol] &= ~MONSTER;
464 dungeon[row][col] |= MONSTER;
466 c = mvinch(mrow, mcol);
468 if ((c >= 'A') && (c <= 'Z')) {
469 if (!detect_monster) {
470 mvaddch(mrow, mcol, monster->trail_char);
471 } else {
472 if (rogue_can_see(mrow, mcol)) {
473 mvaddch(mrow, mcol, monster->trail_char);
474 } else {
475 if (monster->trail_char == '.') {
476 monster->trail_char = ' ';
478 mvaddch(mrow, mcol, monster->trail_char);
482 monster->trail_char = mvinch(row, col);
483 if (!blind && (detect_monster || rogue_can_see(row, col))) {
484 if ((!(monster->m_flags & INVISIBLE) ||
485 (detect_monster || see_invisible || r_see_invisible))) {
486 mvaddch(row, col, gmc(monster));
489 if ((dungeon[row][col] & DOOR) &&
490 (get_room_number(row, col) != cur_room) &&
491 (dungeon[mrow][mcol] == FLOOR) && !blind) {
492 mvaddch(mrow, mcol, ' ');
494 if (dungeon[row][col] & DOOR) {
495 dr_course(monster, ((dungeon[mrow][mcol] & TUNNEL) ? 1 : 0),
496 row, col);
497 } else {
498 monster->row = row;
499 monster->col = col;
504 mon_can_go(const object *monster, short row, short col)
506 object *obj;
507 short dr, dc;
509 dr = monster->row - row; /* check if move distance > 1 */
510 if ((dr >= 2) || (dr <= -2)) {
511 return(0);
513 dc = monster->col - col;
514 if ((dc >= 2) || (dc <= -2)) {
515 return(0);
517 if ((!dungeon[monster->row][col]) || (!dungeon[row][monster->col])) {
518 return(0);
520 if ((!is_passable(row, col)) || (dungeon[row][col] & MONSTER)) {
521 return(0);
523 if ((monster->row!=row)&&(monster->col!=col)&&((dungeon[row][col]&DOOR) ||
524 (dungeon[monster->row][monster->col]&DOOR))) {
525 return(0);
527 if (!(monster->m_flags & (FLITS | CONFUSED | CAN_FLIT)) &&
528 (monster->trow == NO_ROOM)) {
529 if ((monster->row < rogue.row) && (row < monster->row)) return(0);
530 if ((monster->row > rogue.row) && (row > monster->row)) return(0);
531 if ((monster->col < rogue.col) && (col < monster->col)) return(0);
532 if ((monster->col > rogue.col) && (col > monster->col)) return(0);
534 if (dungeon[row][col] & OBJECT) {
535 obj = object_at(&level_objects, row, col);
536 if ((obj->what_is == SCROL) && (obj->which_kind == SCARE_MONSTER)) {
537 return(0);
540 return(1);
543 void
544 wake_up(object *monster)
546 if (!(monster->m_flags & NAPPING)) {
547 monster->m_flags &= (~(ASLEEP | IMITATES | WAKENS));
551 void
552 wake_room(short rn, boolean entering, short row, short col)
554 object *monster;
555 short wake_percent;
556 boolean in_room;
558 wake_percent = (rn == party_room) ? PARTY_WAKE_PERCENT : WAKE_PERCENT;
559 if (stealthy > 0) {
560 wake_percent /= (STEALTH_FACTOR + stealthy);
563 monster = level_monsters.next_monster;
565 while (monster) {
566 in_room = (rn == get_room_number(monster->row, monster->col));
567 if (in_room) {
568 if (entering) {
569 monster->trow = NO_ROOM;
570 } else {
571 monster->trow = row;
572 monster->tcol = col;
575 if ((monster->m_flags & WAKENS) &&
576 (rn == get_room_number(monster->row, monster->col))) {
577 if (rand_percent(wake_percent)) {
578 wake_up(monster);
581 monster = monster->next_monster;
585 const char *
586 mon_name(const object *monster)
588 short ch;
590 if (blind || ((monster->m_flags & INVISIBLE) &&
591 !(detect_monster || see_invisible || r_see_invisible))) {
592 return("something");
594 if (halluc) {
595 ch = get_rand('A', 'Z') - 'A';
596 return(m_names[ch]);
598 ch = monster->m_char - 'A';
599 return(m_names[ch]);
602 static int
603 rogue_is_around(int row, int col)
605 short rdif, cdif, retval;
607 rdif = row - rogue.row;
608 cdif = col - rogue.col;
610 retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
611 return(retval);
614 void
615 wanderer(void)
617 object *monster;
618 short row, col, i;
619 boolean found = 0;
621 monster = NULL; /* XXXGCC -Wuninitialized [powerpc] */
623 for (i = 0; ((i < 15) && (!found)); i++) {
624 monster = gr_monster(NULL, 0);
625 if (!(monster->m_flags & (WAKENS | WANDERS))) {
626 free_object(monster);
627 } else {
628 found = 1;
631 if (found) {
632 found = 0;
633 wake_up(monster);
634 for (i = 0; ((i < 25) && (!found)); i++) {
635 gr_row_col(&row, &col, (FLOOR | TUNNEL | STAIRS | OBJECT));
636 if (!rogue_can_see(row, col)) {
637 put_m_at(row, col, monster);
638 found = 1;
641 if (!found) {
642 free_object(monster);
647 void
648 show_monsters(void)
650 object *monster;
652 detect_monster = 1;
654 if (blind) {
655 return;
657 monster = level_monsters.next_monster;
659 while (monster) {
660 mvaddch(monster->row, monster->col, monster->m_char);
661 if (monster->m_flags & IMITATES) {
662 monster->m_flags &= (~IMITATES);
663 monster->m_flags |= WAKENS;
665 monster = monster->next_monster;
669 void
670 create_monster(void)
672 short row, col;
673 short i;
674 boolean found = 0;
675 object *monster;
677 row = rogue.row;
678 col = rogue.col;
680 for (i = 0; i < 9; i++) {
681 rand_around(i, &row, &col);
682 if (((row == rogue.row) && (col == rogue.col)) ||
683 (row < MIN_ROW) || (row > (DROWS-2)) ||
684 (col < 0) || (col > (DCOLS-1))) {
685 continue;
687 if ((!(dungeon[row][col] & MONSTER)) &&
688 (dungeon[row][col] & (FLOOR|TUNNEL|STAIRS|DOOR))) {
689 found = 1;
690 break;
693 if (found) {
694 monster = gr_monster((object *)0, 0);
695 put_m_at(row, col, monster);
696 mvaddch(row, col, gmc(monster));
697 if (monster->m_flags & (WANDERS | WAKENS)) {
698 wake_up(monster);
700 } else {
701 messagef(0, "you hear a faint cry of anguish in the distance");
705 static void
706 put_m_at(short row, short col, object *monster)
708 monster->row = row;
709 monster->col = col;
710 dungeon[row][col] |= MONSTER;
711 monster->trail_char = mvinch(row, col);
712 (void)add_to_pack(monster, &level_monsters, 0);
713 aim_monster(monster);
716 static void
717 aim_monster(object *monster)
719 short i, rn, d, r;
721 rn = get_room_number(monster->row, monster->col);
722 if (rn == NO_ROOM)
723 clean_up("aim_monster: monster not in room");
724 r = get_rand(0, 12);
726 for (i = 0; i < 4; i++) {
727 d = (r + i) % 4;
728 if (rooms[rn].doors[d].oth_room != NO_ROOM) {
729 monster->trow = rooms[rn].doors[d].door_row;
730 monster->tcol = rooms[rn].doors[d].door_col;
731 break;
737 rogue_can_see(int row, int col)
739 int retval;
741 retval = !blind &&
742 (((get_room_number(row, col) == cur_room) &&
743 !(rooms[cur_room].is_room & R_MAZE)) ||
744 rogue_is_around(row, col));
746 return(retval);
749 static int
750 move_confused(object *monster)
752 short i, row, col;
754 if (!(monster->m_flags & ASLEEP)) {
755 if (--monster->moves_confused <= 0) {
756 monster->m_flags &= (~CONFUSED);
758 if (monster->m_flags & STATIONARY) {
759 return(coin_toss() ? 1 : 0);
760 } else if (rand_percent(15)) {
761 return(1);
763 row = monster->row;
764 col = monster->col;
766 for (i = 0; i < 9; i++) {
767 rand_around(i, &row, &col);
768 if ((row == rogue.row) && (col == rogue.col)) {
769 return(0);
771 if (mtry(monster, row, col)) {
772 return(1);
776 return(0);
779 static int
780 flit(object *monster)
782 short i, row, col;
784 if (!rand_percent(FLIT_PERCENT + ((monster->m_flags & FLIES) ? 20 : 0))) {
785 return(0);
787 if (rand_percent(10)) {
788 return(1);
790 row = monster->row;
791 col = monster->col;
793 for (i = 0; i < 9; i++) {
794 rand_around(i, &row, &col);
795 if ((row == rogue.row) && (col == rogue.col)) {
796 continue;
798 if (mtry(monster, row, col)) {
799 return(1);
802 return(1);
805 char
806 gr_obj_char(void)
808 short r;
809 const char *rs = "%!?]=/):*";
811 r = get_rand(0, 8);
813 return(rs[r]);
816 static int
817 no_room_for_monster(int rn)
819 short i, j;
821 for (i = rooms[rn].top_row+1; i < rooms[rn].bottom_row; i++) {
822 for (j = rooms[rn].left_col+1; j < rooms[rn].right_col; j++) {
823 if (!(dungeon[i][j] & MONSTER)) {
824 return(0);
828 return(1);
831 void
832 aggravate(void)
834 object *monster;
836 messagef(0, "you hear a high pitched humming noise");
838 monster = level_monsters.next_monster;
840 while (monster) {
841 wake_up(monster);
842 monster->m_flags &= (~IMITATES);
843 if (rogue_can_see(monster->row, monster->col)) {
844 mvaddch(monster->row, monster->col, monster->m_char);
846 monster = monster->next_monster;
850 boolean
851 mon_sees(const object *monster, int row, int col)
853 short rn, rdif, cdif, retval;
855 rn = get_room_number(row, col);
857 if ( (rn != NO_ROOM) &&
858 (rn == get_room_number(monster->row, monster->col)) &&
859 !(rooms[rn].is_room & R_MAZE)) {
860 return(1);
862 rdif = row - monster->row;
863 cdif = col - monster->col;
865 retval = (rdif >= -1) && (rdif <= 1) && (cdif >= -1) && (cdif <= 1);
866 return(retval);
869 void
870 mv_aquatars(void)
872 object *monster;
874 monster = level_monsters.next_monster;
876 while (monster) {
877 if ((monster->m_char == 'A') &&
878 mon_can_go(monster, rogue.row, rogue.col)) {
879 mv_1_monster(monster, rogue.row, rogue.col);
880 monster->m_flags |= ALREADY_MOVED;
882 monster = monster->next_monster;