2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)monster.c 8.1 (Berkeley) 5/31/93
37 * $FreeBSD: src/games/rogue/monster.c,v 1.6 1999/11/30 03:49:24 billf Exp $
38 * $DragonFly: src/games/rogue/monster.c,v 1.3 2006/09/02 19:31:07 pavalos Exp $
44 * This source herein may be modified and/or distributed by anybody who
45 * so desires, with the following restrictions:
46 * 1.) No portion of this notice shall be removed.
47 * 2.) Credit shall not be taken for the creation of this source.
48 * 3.) This code is not to be traded, sold, or used for personal
55 static boolean
mtry(object
*, short, short);
56 static short rogue_is_around(int, int);
57 static void put_m_at(short, short, object
*);
58 static void aim_monster(object
*);
59 static boolean
move_confused(object
*);
60 static boolean
flit(object
*);
61 static boolean
no_room_for_monster(int);
63 object level_monsters
;
64 boolean mon_disappeared
;
66 const char *const m_names
[] = {
95 object mon_tab
[MONSTERS
] = {
96 {(ASLEEP
|WAKENS
|WANDERS
|RUSTS
),"0d0",25,'A',20,9,18,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
97 {(ASLEEP
|WANDERS
|FLITS
|FLIES
),"1d3",10,'B',2,1,8,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
98 {(ASLEEP
|WANDERS
),"3d3/2d5",32,'C',15,7,16,85,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
99 {(ASLEEP
|WAKENS
|FLAMES
),"4d6/4d9",145,'D',5000,21,126,100,0,90,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
100 {(ASLEEP
|WAKENS
),"1d3",11,'E',2,1,7,65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
101 {(HOLDS
|STATIONARY
),"5d5",73,'F',91,12,126,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
102 {(ASLEEP
|WAKENS
|WANDERS
|FLIES
),"5d5/5d5",115,'G',
103 2000,20,126,85,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
104 {(ASLEEP
|WAKENS
|WANDERS
),"1d3/1d2",15,'H',3,1,10,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
105 {(ASLEEP
|FREEZES
),"0d0",15,'I',5,2,11,68,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
106 {(ASLEEP
|WANDERS
),"3d10/4d5",132,'J',3000,21,126,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
107 {(ASLEEP
|WAKENS
|WANDERS
|FLIES
),"1d4",10,'K',2,1,6,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
108 {(ASLEEP
|STEALS_GOLD
),"0d0",25,'L',21,6,16,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
109 {(ASLEEP
|WAKENS
|WANDERS
|CONFUSES
),"4d4/3d7",97,'M',
110 250,18,126,85,0,25,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
111 {(ASLEEP
|STEALS_ITEM
),"0d0",25,'N',39,10,19,75,0,100,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
112 {(ASLEEP
|WANDERS
|WAKENS
|SEEKS_GOLD
),"1d6",25,'O',5,4,13,70,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
113 {(ASLEEP
|INVISIBLE
|WANDERS
|FLITS
),"5d4",76,'P',120,15,24,80,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
114 {(ASLEEP
|WAKENS
|WANDERS
),"3d5",30,'Q',20,8,17,78,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
115 {(ASLEEP
|WAKENS
|WANDERS
|STINGS
),"2d5",19,'R',10,3,12,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
116 {(ASLEEP
|WAKENS
|WANDERS
),"1d3",8,'S',2,1,9,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
117 {(ASLEEP
|WAKENS
|WANDERS
),"4d6/1d4",75,'T',125,13,22,75,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
118 {(ASLEEP
|WAKENS
|WANDERS
),"4d10",90,'U',
119 200,17,26,85,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
120 {(ASLEEP
|WAKENS
|WANDERS
|DRAINS_LIFE
),"1d14/1d4",55,'V',
121 350,19,126,85,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
122 {(ASLEEP
|WANDERS
|DROPS_LEVEL
),"2d8",45,'W',55,14,23,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
123 {(ASLEEP
|IMITATES
),"4d6",42,'X',110,16,25,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
124 {(ASLEEP
|WANDERS
),"3d6",35,'Y',50,11,20,80,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
},
125 {(ASLEEP
|WAKENS
|WANDERS
),"1d7",21,'Z',8,5,14,69,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,NULL
}
128 extern short cur_level
;
129 extern short cur_room
, party_room
;
130 extern short blind
, halluc
, haste_self
;
131 extern boolean detect_monster
, see_invisible
, r_see_invisible
;
132 extern short stealthy
;
144 for (i
= 0; i
< n
; i
++) {
145 monster
= gr_monster((object
*) 0, 0);
146 if ((monster
->m_flags
& WANDERS
) && coin_toss()) {
149 gr_row_col(&row
, &col
, (FLOOR
| TUNNEL
| STAIRS
| OBJECT
));
150 put_m_at(row
, col
, monster
);
155 gr_monster(object
*monster
, int mn
)
158 monster
= alloc_object();
161 mn
= get_rand(0, MONSTERS
-1);
162 if ((cur_level
>= mon_tab
[mn
].first_level
) &&
163 (cur_level
<= mon_tab
[mn
].last_level
)) {
168 *monster
= mon_tab
[mn
];
169 if (monster
->m_flags
& IMITATES
) {
170 monster
->disguise
= gr_obj_char();
172 if (cur_level
> (AMULET_LEVEL
+ 2)) {
173 monster
->m_flags
|= HASTED
;
175 monster
->trow
= NO_ROOM
;
182 object
*monster
, *next_monster
, *test_mons
;
185 if (haste_self
% 2) {
189 monster
= level_monsters
.next_monster
;
192 next_monster
= monster
->next_monster
;
194 if (monster
->m_flags
& HASTED
) {
195 mv_1_monster(monster
, rogue
.row
, rogue
.col
);
196 if (mon_disappeared
) {
199 } else if (monster
->m_flags
& SLOWED
) {
200 monster
->slowed_toggle
= !monster
->slowed_toggle
;
201 if (monster
->slowed_toggle
) {
205 if ((monster
->m_flags
& CONFUSED
) && move_confused(monster
)) {
209 if ( (monster
->m_flags
& FLIES
) &&
210 !(monster
->m_flags
& NAPPING
) &&
211 !mon_can_go(monster
, rogue
.row
, rogue
.col
)) {
213 mv_1_monster(monster
, rogue
.row
, rogue
.col
);
214 if (mon_disappeared
) {
218 if (!(flew
&& mon_can_go(monster
, rogue
.row
, rogue
.col
))) {
219 mv_1_monster(monster
, rogue
.row
, rogue
.col
);
221 NM
: test_mons
= level_monsters
.next_monster
;
225 if(next_monster
== test_mons
)
227 monster
= next_monster
;
230 test_mons
= test_mons
->next_monster
;
236 party_monsters(int rn
, int 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
)) {
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
))) {
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);
276 gmc_row_col(int row
, int col
)
280 if ((monster
= object_at(&level_monsters
, row
, col
))) {
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
);
290 return('&'); /* BUG if this ever happens */
297 if ((!(detect_monster
|| see_invisible
|| r_see_invisible
) &&
298 (monster
->m_flags
& INVISIBLE
))
300 return(monster
->trail_char
);
302 if (monster
->m_flags
& IMITATES
) {
303 return(monster
->disguise
);
305 return(monster
->m_char
);
309 mv_1_monster(object
*monster
, short row
, short col
)
314 if (monster
->m_flags
& ASLEEP
) {
315 if (monster
->m_flags
& NAPPING
) {
316 if (--monster
->nap_length
<= 0) {
317 monster
->m_flags
&= (~(NAPPING
| ASLEEP
));
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
)) :
329 } else if (monster
->m_flags
& ALREADY_MOVED
) {
330 monster
->m_flags
&= (~ALREADY_MOVED
);
333 if ((monster
->m_flags
& FLITS
) && flit(monster
)) {
336 if ((monster
->m_flags
& STATIONARY
) &&
337 (!mon_can_go(monster
, rogue
.row
, rogue
.col
))) {
340 if (monster
->m_flags
& FREEZING_ROGUE
) {
343 if ((monster
->m_flags
& CONFUSES
) && m_confuse(monster
)) {
346 if (mon_can_go(monster
, rogue
.row
, rogue
.col
)) {
350 if ((monster
->m_flags
& FLAMES
) && flame_broil(monster
)) {
353 if ((monster
->m_flags
& SEEKS_GOLD
) && seek_gold(monster
)) {
356 if ((monster
->trow
== monster
->row
) &&
357 (monster
->tcol
== monster
->col
)) {
358 monster
->trow
= NO_ROOM
;
359 } else if (monster
->trow
!= NO_ROOM
) {
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
)) {
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
)) {
381 if (mtry(monster
, row
, col
)) {
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);
391 if (!tried
[n
] && mtry(monster
, row
, monster
->col
-1)) {
396 if (!tried
[n
] && mtry(monster
, row
, monster
->col
)) {
401 if (!tried
[n
] && mtry(monster
, row
, monster
->col
+1)) {
406 if (!tried
[n
] && mtry(monster
, monster
->row
-1, col
)) {
411 if (!tried
[n
] && mtry(monster
, monster
->row
, col
)) {
416 if (!tried
[n
] && mtry(monster
, monster
->row
+1, col
)) {
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));
435 monster
->trow
= NO_ROOM
;
440 monster
->o_row
= monster
->row
;
441 monster
->o_col
= monster
->col
;
447 mtry(object
*monster
, short row
, short col
)
449 if (mon_can_go(monster
, row
, col
)) {
450 move_mon_to(monster
, row
, col
);
457 move_mon_to(object
*monster
, short row
, short 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
);
474 if (rogue_can_see(mrow
, mcol
)) {
475 mvaddch(mrow
, mcol
, monster
->trail_char
);
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),
506 mon_can_go(const object
*monster
, short row
, short col
)
511 dr
= monster
->row
- row
; /* check if move distance > 1 */
512 if ((dr
>= 2) || (dr
<= -2)) {
515 dc
= monster
->col
- col
;
516 if ((dc
>= 2) || (dc
<= -2)) {
519 if ((!dungeon
[monster
->row
][col
]) || (!dungeon
[row
][monster
->col
])) {
522 if ((!is_passable(row
, col
)) || (dungeon
[row
][col
] & MONSTER
)) {
525 if ((monster
->row
!=row
)&&(monster
->col
!=col
)&&((dungeon
[row
][col
]&DOOR
) ||
526 (dungeon
[monster
->row
][monster
->col
]&DOOR
))) {
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
)) {
546 wake_up(object
*monster
)
548 if (!(monster
->m_flags
& NAPPING
)) {
549 monster
->m_flags
&= (~(ASLEEP
| IMITATES
| WAKENS
));
554 wake_room(short rn
, boolean entering
, short row
, short col
)
560 wake_percent
= (rn
== party_room
) ? PARTY_WAKE_PERCENT
: WAKE_PERCENT
;
562 wake_percent
/= (STEALTH_FACTOR
+ stealthy
);
565 monster
= level_monsters
.next_monster
;
568 in_room
= (rn
== get_room_number(monster
->row
, monster
->col
));
571 monster
->trow
= NO_ROOM
;
577 if ((monster
->m_flags
& WAKENS
) &&
578 (rn
== get_room_number(monster
->row
, monster
->col
))) {
579 if (rand_percent(wake_percent
)) {
583 monster
= monster
->next_monster
;
588 mon_name(const object
*monster
)
592 if (blind
|| ((monster
->m_flags
& INVISIBLE
) &&
593 !(detect_monster
|| see_invisible
|| r_see_invisible
))) {
597 ch
= get_rand('A', 'Z') - 'A';
600 ch
= monster
->m_char
- 'A';
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);
623 for (i
= 0; ((i
< 15) && (!found
)); i
++) {
624 monster
= gr_monster((object
*) 0, 0);
625 if (!(monster
->m_flags
& (WAKENS
| WANDERS
))) {
626 free_object(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
);
642 free_object(monster
);
657 monster
= level_monsters
.next_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
;
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))) {
687 if ((!(dungeon
[row
][col
] & MONSTER
)) &&
688 (dungeon
[row
][col
] & (FLOOR
|TUNNEL
|STAIRS
|DOOR
))) {
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
)) {
701 message("you hear a faint cry of anguish in the distance", 0);
706 put_m_at(short row
, short col
, object
*monster
)
710 dungeon
[row
][col
] |= MONSTER
;
711 monster
->trail_char
= mvinch(row
, col
);
712 add_to_pack(monster
, &level_monsters
, 0);
713 aim_monster(monster
);
717 aim_monster(object
*monster
)
721 rn
= get_room_number(monster
->row
, monster
->col
);
724 for (i
= 0; i
< 4; i
++) {
726 if (rooms
[rn
].doors
[d
].oth_room
!= NO_ROOM
) {
727 monster
->trow
= rooms
[rn
].doors
[d
].door_row
;
728 monster
->tcol
= rooms
[rn
].doors
[d
].door_col
;
735 rogue_can_see(int row
, int col
)
740 (((get_room_number(row
, col
) == cur_room
) &&
741 !(rooms
[cur_room
].is_room
& R_MAZE
)) ||
742 rogue_is_around(row
, col
));
748 move_confused(object
*monster
)
752 if (!(monster
->m_flags
& ASLEEP
)) {
753 if (--monster
->moves_confused
<= 0) {
754 monster
->m_flags
&= (~CONFUSED
);
756 if (monster
->m_flags
& STATIONARY
) {
757 return(coin_toss() ? 1 : 0);
758 } else if (rand_percent(15)) {
764 for (i
= 0; i
< 9; i
++) {
765 rand_around(i
, &row
, &col
);
766 if ((row
== rogue
.row
) && (col
== rogue
.col
)) {
769 if (mtry(monster
, row
, col
)) {
778 flit(object
*monster
)
782 if (!rand_percent(FLIT_PERCENT
+ ((monster
->m_flags
& FLIES
) ? 20 : 0))) {
785 if (rand_percent(10)) {
791 for (i
= 0; i
< 9; i
++) {
792 rand_around(i
, &row
, &col
);
793 if ((row
== rogue
.row
) && (col
== rogue
.col
)) {
796 if (mtry(monster
, row
, col
)) {
807 const char *rs
= "%!?]=/):*";
815 no_room_for_monster(int rn
)
819 for (i
= rooms
[rn
].top_row
+1; i
< rooms
[rn
].bottom_row
; i
++) {
820 for (j
= rooms
[rn
].left_col
+1; j
< rooms
[rn
].right_col
; j
++) {
821 if (!(dungeon
[i
][j
] & MONSTER
)) {
834 message("you hear a high pitched humming noise", 0);
836 monster
= level_monsters
.next_monster
;
840 monster
->m_flags
&= (~IMITATES
);
841 if (rogue_can_see(monster
->row
, monster
->col
)) {
842 mvaddch(monster
->row
, monster
->col
, monster
->m_char
);
844 monster
= monster
->next_monster
;
849 mon_sees(const object
*monster
, int row
, int col
)
851 short rn
, rdif
, cdif
, retval
;
853 rn
= get_room_number(row
, col
);
855 if ( (rn
!= NO_ROOM
) &&
856 (rn
== get_room_number(monster
->row
, monster
->col
)) &&
857 !(rooms
[rn
].is_room
& R_MAZE
)) {
860 rdif
= row
- monster
->row
;
861 cdif
= col
- monster
->col
;
863 retval
= (rdif
>= -1) && (rdif
<= 1) && (cdif
>= -1) && (cdif
<= 1);
872 monster
= level_monsters
.next_monster
;
875 if ((monster
->m_char
== 'A') &&
876 mon_can_go(monster
, rogue
.row
, rogue
.col
)) {
877 mv_1_monster(monster
, rogue
.row
, rogue
.col
);
878 monster
->m_flags
|= ALREADY_MOVED
;
880 monster
= monster
->next_monster
;