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