1 /* SCCS Id: @(#)mon.c 3.4 2003/12/04 */
2 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
3 /* NetHack may be freely redistributed. See license for details. */
4
5 /* If you're using precompiled headers, you don't want this either */
6 #ifdef MICROPORT_BUG
7 #define MKROOM_H
8 #endif
9
10 #include "hack.h"
11 #include "mfndpos.h"
12 #include "edog.h"
13 #include <ctype.h>
14
15 STATIC_DCL boolean FDECL(restrap,(struct monst *));
16 STATIC_DCL long FDECL(mm_aggression, (struct monst *,struct monst *));
17 STATIC_DCL int NDECL(pick_animal);
18 STATIC_DCL void FDECL(kill_eggs, (struct obj *));
19
20 #ifdef REINCARNATION
21 #define LEVEL_SPECIFIC_NOCORPSE(mdat) \
22 (Is_rogue_level(&u.uz) || \
23 (level.flags.graveyard && is_undead(mdat) && rn2(3)))
24 #else
25 #define LEVEL_SPECIFIC_NOCORPSE(mdat) \
26 (level.flags.graveyard && is_undead(mdat) && rn2(3))
27 #endif
28
29
30 #if 0
31 /* part of the original warning code which was replaced in 3.3.1 */
32 #define warnDelay 10
33 long lastwarntime;
34 int lastwarnlev;
35
36 const char *warnings[] = {
37 "white", "pink", "red", "ruby", "purple", "black"
38 };
39
40 STATIC_DCL void NDECL(warn_effects);
41 #endif /* 0 */
42
43 STATIC_DCL struct obj *FDECL(make_corpse,(struct monst *));
44 STATIC_DCL void FDECL(m_detach, (struct monst *, struct permonst *));
45 #ifdef WEBB_DISINT
46 STATIC_DCL void FDECL(lifesaved_monster, (struct monst *, uchar));
47 #else
48 STATIC_DCL void FDECL(lifesaved_monster, (struct monst *));
49 #endif
50 void
remove_monster(x,y)51 remove_monster(x,y)
52 int x,y;
53 {
54 if (level.monsters[x][y] &&
55 (level.monsters[x][y]->data == &mons[PM_GIANT_TURTLE] &&
56 (!level.monsters[x][y]->minvis || See_invisible)))
57 unblock_point(x,y);
58 level.monsters[x][y] = (struct monst *)0;
59 }
60
61
62 /* convert the monster index of an undead to its living counterpart */
63 int
undead_to_corpse(mndx)64 undead_to_corpse(mndx)
65 int mndx;
66 {
67 switch (mndx) {
68 case PM_KOBOLD_ZOMBIE:
69 case PM_KOBOLD_MUMMY: mndx = PM_KOBOLD; break;
70 case PM_DWARF_ZOMBIE:
71 case PM_DWARF_MUMMY: mndx = PM_DWARF; break;
72 case PM_GNOME_ZOMBIE:
73 case PM_GNOME_MUMMY: mndx = PM_GNOME; break;
74 case PM_ORC_ZOMBIE:
75 case PM_ORC_MUMMY: mndx = PM_ORC; break;
76 case PM_ELF_ZOMBIE:
77 case PM_ELF_MUMMY: mndx = PM_ELF; break;
78 case PM_VAMPIRE:
79 case PM_VAMPIRE_LORD:
80 #if 0 /* DEFERRED */
81 case PM_VAMPIRE_MAGE:
82 #endif
83 case PM_HUMAN_ZOMBIE:
84 case PM_HUMAN_MUMMY: mndx = PM_HUMAN; break;
85 case PM_GIANT_ZOMBIE:
86 case PM_GIANT_MUMMY: mndx = PM_GIANT; break;
87 case PM_ETTIN_ZOMBIE:
88 case PM_ETTIN_MUMMY: mndx = PM_ETTIN; break;
89 default: break;
90 }
91 return mndx;
92 }
93
94 /* Convert the monster index of some monsters (such as quest guardians)
95 * to their generic species type.
96 *
97 * Return associated character class monster, rather than species
98 * if mode is 1.
99 */
100 int
genus(mndx,mode)101 genus(mndx, mode)
102 int mndx, mode;
103 {
104 switch (mndx) {
105 /* Quest guardians */
106 case PM_STUDENT: mndx = mode ? PM_ARCHEOLOGIST : PM_HUMAN; break;
107 case PM_CHIEFTAIN: mndx = mode ? PM_BARBARIAN : PM_HUMAN; break;
108 case PM_NEANDERTHAL: mndx = mode ? PM_CAVEMAN : PM_HUMAN; break;
109 case PM_ATTENDANT: mndx = mode ? PM_HEALER : PM_HUMAN; break;
110 case PM_PAGE: mndx = mode ? PM_KNIGHT : PM_HUMAN; break;
111 case PM_ABBOT: mndx = mode ? PM_MONK : PM_HUMAN; break;
112 case PM_ACOLYTE: mndx = mode ? PM_PRIEST : PM_HUMAN; break;
113 case PM_HUNTER: mndx = mode ? PM_RANGER : PM_HUMAN; break;
114 case PM_THUG: mndx = mode ? PM_ROGUE : PM_HUMAN; break;
115 case PM_ROSHI: mndx = mode ? PM_SAMURAI : PM_HUMAN; break;
116 #ifdef TOURIST
117 case PM_GUIDE: mndx = mode ? PM_TOURIST : PM_HUMAN; break;
118 #endif
119 case PM_APPRENTICE: mndx = mode ? PM_WIZARD : PM_HUMAN; break;
120 case PM_WARRIOR: mndx = mode ? PM_VALKYRIE : PM_HUMAN; break;
121 default:
122 if (mndx >= LOW_PM && mndx < NUMMONS) {
123 struct permonst *ptr = &mons[mndx];
124 if (is_human(ptr)) mndx = PM_HUMAN;
125 else if (is_elf(ptr)) mndx = PM_ELF;
126 else if (is_dwarf(ptr)) mndx = PM_DWARF;
127 else if (is_gnome(ptr)) mndx = PM_GNOME;
128 else if (is_orc(ptr)) mndx = PM_ORC;
129 }
130 break;
131 }
132 return mndx;
133 }
134
135 /* convert monster index to chameleon index */
136 int
pm_to_cham(mndx)137 pm_to_cham(mndx)
138 int mndx;
139 {
140 int mcham;
141
142 switch (mndx) {
143 case PM_CHAMELEON: mcham = CHAM_CHAMELEON; break;
144 case PM_DOPPELGANGER: mcham = CHAM_DOPPELGANGER; break;
145 case PM_SANDESTIN: mcham = CHAM_SANDESTIN; break;
146 default: mcham = CHAM_ORDINARY; break;
147 }
148 return mcham;
149 }
150
151 /* convert chameleon index to monster index */
152 STATIC_VAR short cham_to_pm[] = {
153 NON_PM, /* placeholder for CHAM_ORDINARY */
154 PM_CHAMELEON,
155 PM_DOPPELGANGER,
156 PM_SANDESTIN,
157 };
158
159 /* for deciding whether corpse or statue will carry along full monster data */
160 #define KEEPTRAITS(mon) ((mon)->isshk || (mon)->mtame || \
161 ((mon)->data->geno & G_UNIQ) || \
162 is_reviver((mon)->data) || \
163 /* normally leader the will be unique, */ \
164 /* but he might have been polymorphed */ \
165 (mon)->m_id == quest_status.leader_m_id || \
166 /* special cancellation handling for these */ \
167 (dmgtype((mon)->data, AD_SEDU) || \
168 dmgtype((mon)->data, AD_SSEX)))
169
170 /* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
171 * leave corpses. Monsters which leave "special" corpses should have
172 * G_NOCORPSE set in order to prevent wishing for one, finding tins of one,
173 * etc....
174 */
175 STATIC_OVL struct obj *
make_corpse(mtmp)176 make_corpse(mtmp)
177 register struct monst *mtmp;
178 {
179 register struct permonst *mdat = mtmp->data;
180 int num;
181 struct obj *obj = (struct obj *)0;
182 int x = mtmp->mx, y = mtmp->my;
183 int mndx = monsndx(mdat);
184
185 switch(mndx) {
186 case PM_GRAY_DRAGON:
187 case PM_SILVER_DRAGON:
188 #if 0 /* DEFERRED */
189 case PM_SHIMMERING_DRAGON:
190 #endif
191 case PM_RED_DRAGON:
192 case PM_ORANGE_DRAGON:
193 case PM_WHITE_DRAGON:
194 case PM_BLACK_DRAGON:
195 case PM_BLUE_DRAGON:
196 case PM_GREEN_DRAGON:
197 case PM_GLOWING_DRAGON:
198 case PM_YELLOW_DRAGON:
199 case PM_CHROMATIC_DRAGON:
200 /* Make dragon scales. This assumes that the order of the */
201 /* dragons is the same as the order of the scales. */
202 if (!rn2(mtmp->mrevived ? 20 : 3)) {
203 num = GRAY_DRAGON_SCALES + monsndx(mdat) - PM_GRAY_DRAGON;
204 obj = mksobj_at(num, x, y, FALSE, FALSE);
205 obj->spe = 0;
206 obj->cursed = obj->blessed = FALSE;
207 }
208 goto default_1;
209 case PM_TIAMAT:
210 /* Make chromatic dragon scales. */
211 if (!rn2(mtmp->mrevived ? 20 : 1)) {
212 obj = mksobj_at(CHROMATIC_DRAGON_SCALES, x, y, FALSE, FALSE);
213 obj->spe = 0;
214 obj->cursed = obj->blessed = FALSE;
215 }
216 goto default_1;
217
218 case PM_WHITE_UNICORN:
219 case PM_GRAY_UNICORN:
220 case PM_BLACK_UNICORN:
221 if (mtmp->mrevived && rn2(20)) {
222 if (canseemon(mtmp))
223 pline("%s recently regrown horn crumbles to dust.",
224 s_suffix(Monnam(mtmp)));
225 } else
226 (void) mksobj_at(UNICORN_HORN, x, y, TRUE, FALSE);
227 goto default_1;
228 case PM_LONG_WORM:
229 (void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
230 goto default_1;
231 case PM_VAMPIRE:
232 case PM_VAMPIRE_LORD:
233 #if 0 /* DEFERRED */
234 case PM_VAMPIRE_MAGE:
235 #endif
236 /* include mtmp in the mkcorpstat() call */
237 num = undead_to_corpse(mndx);
238 obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE);
239 obj->age -= 100; /* this is an *OLD* corpse */
240 break;
241 case PM_KOBOLD_MUMMY:
242 case PM_DWARF_MUMMY:
243 case PM_GNOME_MUMMY:
244 case PM_ORC_MUMMY:
245 case PM_ELF_MUMMY:
246 case PM_HUMAN_MUMMY:
247 case PM_GIANT_MUMMY:
248 case PM_ETTIN_MUMMY:
249 case PM_KOBOLD_ZOMBIE:
250 case PM_DWARF_ZOMBIE:
251 case PM_GNOME_ZOMBIE:
252 case PM_ORC_ZOMBIE:
253 case PM_ELF_ZOMBIE:
254 case PM_HUMAN_ZOMBIE:
255 case PM_GIANT_ZOMBIE:
256 case PM_ETTIN_ZOMBIE:
257 num = undead_to_corpse(mndx);
258 obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE);
259 obj->age -= 100; /* this is an *OLD* corpse */
260 break;
261 case PM_IRON_GOLEM:
262 num = d(2,6);
263 while (num--)
264 obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE);
265 mtmp->mnamelth = 0;
266 break;
267 case PM_GLASS_GOLEM:
268 num = d(2,4); /* very low chance of creating all glass gems */
269 while (num--)
270 obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE, FALSE);
271 mtmp->mnamelth = 0;
272 break;
273 case PM_CLAY_GOLEM:
274 obj = mksobj_at(ROCK, x, y, FALSE, FALSE);
275 obj->quan = (long)(rn2(20) + 50);
276 obj->owt = weight(obj);
277 mtmp->mnamelth = 0;
278 break;
279 case PM_STONE_GOLEM:
280 obj = mkcorpstat(STATUE, (struct monst *)0,
281 mdat, x, y, FALSE);
282 break;
283 case PM_WOOD_GOLEM:
284 num = d(2,4);
285 while(num--) {
286 obj = mksobj_at(QUARTERSTAFF, x, y, TRUE, FALSE);
287 }
288 mtmp->mnamelth = 0;
289 break;
290 case PM_LEATHER_GOLEM:
291 num = d(2,4);
292 while(num--)
293 obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE, FALSE);
294 mtmp->mnamelth = 0;
295 break;
296 case PM_WAX_GOLEM:
297 num = d(2,4);
298 while (num--)
299 obj = mksobj_at(WAX_CANDLE, x, y, TRUE, FALSE);
300 mtmp->mnamelth = 0;
301 break;
302 case PM_GOLD_GOLEM:
303 /* Good luck gives more coins */
304 obj = mkgold((long)(200 - rnl(101)), x, y);
305 mtmp->mnamelth = 0;
306 break;
307 case PM_PAPER_GOLEM:
308 num = rnd(4);
309 while (num--)
310 obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE);
311 mtmp->mnamelth = 0;
312 break;
313 case PM_SKELETON:
314 if (!rn2(40)) {
315 mksobj_at(SKELETON_KEY, x, y, TRUE, FALSE);
316 }
317 goto default_1;
318 default_1:
319 default:
320 if (mvitals[mndx].mvflags & G_NOCORPSE)
321 return (struct obj *)0;
322 else /* preserve the unique traits of some creatures */
323 obj = mkcorpstat(CORPSE, KEEPTRAITS(mtmp) ? mtmp : 0,
324 mdat, x, y, TRUE);
325 break;
326 }
327 /* All special cases should precede the G_NOCORPSE check */
328
329 /* if polymorph or undead turning has killed this monster,
330 prevent the same attack beam from hitting its corpse */
331 if (flags.bypasses) bypass_obj(obj);
332
333 if (mtmp->mnamelth)
334 obj = oname(obj, NAME(mtmp));
335
336 /* Avoid "It was hidden under a green mold corpse!"
337 * during Blind combat. An unseen monster referred to as "it"
338 * could be killed and leave a corpse. If a hider then hid
339 * underneath it, you could be told the corpse type of a
340 * monster that you never knew was there without this.
341 * The code in hitmu() substitutes the word "something"
342 * if the corpses obj->dknown is 0.
343 */
344 if (Blind && !sensemon(mtmp)) obj->dknown = 0;
345
346 #ifdef INVISIBLE_OBJECTS
347 /* Invisible monster ==> invisible corpse */
348 obj->oinvis = mtmp->minvis;
349 #endif
350
351 stackobj(obj);
352 newsym(x, y);
353 return obj;
354 }
355
356 #if 0
357 /* part of the original warning code which was replaced in 3.3.1 */
358 STATIC_OVL void
359 warn_effects()
360 {
361 if (warnlevel == 100) {
362 if(!Blind && uwep &&
363 (warnlevel > lastwarnlev || moves > lastwarntime + warnDelay)) {
364 Your("%s %s!", aobjnam(uwep, "glow"),
365 hcolor(NH_LIGHT_BLUE));
366 lastwarnlev = warnlevel;
367 lastwarntime = moves;
368 }
369 warnlevel = 0;
370 return;
371 }
372
373 if (warnlevel >= SIZE(warnings))
374 warnlevel = SIZE(warnings)-1;
375 if (!Blind &&
376 (warnlevel > lastwarnlev || moves > lastwarntime + warnDelay)) {
377 const char *which, *what, *how;
378 long rings = (EWarning & (LEFT_RING|RIGHT_RING));
379
380 if (rings) {
381 what = Hallucination ? "mood ring" : "ring";
382 how = "glows"; /* singular verb */
383 if (rings == LEFT_RING) {
384 which = "left ";
385 } else if (rings == RIGHT_RING) {
386 which = "right ";
387 } else { /* both */
388 which = "";
389 what = (const char *) makeplural(what);
390 how = "glow"; /* plural verb */
391 }
392 Your("%s%s %s %s!", which, what, how, hcolor(warnings[warnlevel]));
393 } else {
394 if (Hallucination)
395 Your("spider-sense is tingling...");
396 else
397 You_feel("apprehensive as you sense a %s flash.",
398 warnings[warnlevel]);
399 }
400
401 lastwarntime = moves;
402 lastwarnlev = warnlevel;
403 }
404 }
405 #endif /* 0 */
406
407 /* check mtmp and water/lava for compatibility, 0 (survived), 1 (died) */
408 int
minliquid(mtmp)409 minliquid(mtmp)
410 register struct monst *mtmp;
411 {
412 boolean inpool, inlava, inswamp, infountain, grounded;
413
414 grounded = !is_flyer(mtmp->data) && !is_floater(mtmp->data);
415 inpool = is_pool(mtmp->mx,mtmp->my) && grounded;
416 inlava = is_lava(mtmp->mx,mtmp->my) && grounded;
417 inswamp = is_swamp(mtmp->mx,mtmp->my) && grounded;
418 infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
419
420 #ifdef STEED
421 /* Flying and levitation keeps our steed out of the liquid */
422 /* (but not water-walking or swimming) */
423 if (mtmp == u.usteed && (Flying || Levitation))
424 return (0);
425 #endif
426
427 /* Gremlin multiplying won't go on forever since the hit points
428 * keep going down, and when it gets to 1 hit point the clone
429 * function will fail.
430 */
431 if (mtmp->data == &mons[PM_GREMLIN] && (inpool || infountain || inswamp) && rn2(3)) {
432 if (split_mon(mtmp, (struct monst *)0))
433 dryup(mtmp->mx, mtmp->my, FALSE);
434 if (inpool) water_damage(mtmp->minvent, FALSE, FALSE);
435 return (0);
436 } else if (mtmp->data == &mons[PM_IRON_GOLEM] && (inpool || inswamp) && !rn2(5)) {
437 int dam = d(2,6);
438 if (cansee(mtmp->mx,mtmp->my))
439 pline("%s rusts.", Monnam(mtmp));
440 mtmp->mhp -= dam;
441 if (mtmp->mhpmax > dam) mtmp->mhpmax -= dam;
442 if (mtmp->mhp < 1) {
443 mondead(mtmp);
444 if (mtmp->mhp < 1) return (1);
445 }
446 water_damage(mtmp->minvent, FALSE, FALSE);
447 return (0);
448 }
449
450 if (inlava) {
451 /*
452 * Lava effects much as water effects. Lava likers are able to
453 * protect their stuff. Fire resistant monsters can only protect
454 * themselves --ALI
455 */
456 if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
457 if (!resists_fire(mtmp)) {
458 if (cansee(mtmp->mx,mtmp->my))
459 pline("%s %s.", Monnam(mtmp),
460 mtmp->data == &mons[PM_WATER_ELEMENTAL] ?
461 "boils away" : "burns to a crisp");
462 mondead(mtmp);
463 }
464 else {
465 if (--mtmp->mhp < 1) {
466 if (cansee(mtmp->mx,mtmp->my))
467 pline("%s surrenders to the fire.", Monnam(mtmp));
468 mondead(mtmp);
469 }
470 else if (cansee(mtmp->mx,mtmp->my))
471 pline("%s burns slightly.", Monnam(mtmp));
472 }
473 if (mtmp->mhp > 0) {
474 (void) fire_damage(mtmp->minvent, FALSE, FALSE,
475 mtmp->mx, mtmp->my);
476 (void) rloc(mtmp, FALSE);
477 return 0;
478 }
479 return (1);
480 }
481 } else if (inpool) {
482 /* Most monsters drown in pools. flooreffects() will take care of
483 * water damage to dead monsters' inventory, but survivors need to
484 * be handled here. Swimmers are able to protect their stuff...
485 */
486 if (!is_clinger(mtmp->data)
487 && !is_swimmer(mtmp->data) && !amphibious(mtmp->data)) {
488 if (cansee(mtmp->mx,mtmp->my)) {
489 pline("%s %s.", Monnam(mtmp),
490 is_vegetation(mtmp->data) ? "sinks" : "drowns");
491 }
492 if (u.ustuck && u.uswallow && u.ustuck == mtmp) {
493 /* This can happen after a purple worm plucks you off a
494 flying steed while you are over water. */
495 pline("%s sinks as water rushes in and flushes you out.",
496 Monnam(mtmp));
497 }
498 mondead(mtmp);
499 if (mtmp->mhp > 0) {
500 (void) rloc(mtmp, FALSE);
501 water_damage(mtmp->minvent, FALSE, FALSE);
502 return 0;
503 }
504 return (1);
505 }
506 } else if (inswamp) {
507 if (!is_clinger(mtmp->data)
508 && !is_swimmer(mtmp->data) && !amphibious(mtmp->data)) {
509 water_damage(mtmp->minvent, FALSE, FALSE);
510 return (0);
511 }
512 } else {
513 /* but eels have a difficult time outside */
514 if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
515 if(mtmp->mhp > 1) mtmp->mhp--;
516 monflee(mtmp, 2, FALSE, FALSE);
517 }
518 }
519 return (0);
520 }
521
522
523 int
mcalcmove(mon)524 mcalcmove(mon)
525 struct monst *mon;
526 {
527 int mmove = mon->data->mmove;
528
529 /* Note: MSLOW's `+ 1' prevents slowed speed 1 getting reduced to 0;
530 * MFAST's `+ 2' prevents hasted speed 1 from becoming a no-op;
531 * both adjustments have negligible effect on higher speeds.
532 */
533 if (mon->mspeed == MSLOW)
534 mmove = (2 * mmove + 1) / 3;
535 else if (mon->mspeed == MFAST)
536 mmove = (4 * mmove + 2) / 3;
537
538 #ifdef STEED
539 if (mon == u.usteed) {
540 if (u.ugallop && flags.mv) {
541 /* average movement is 1.50 times normal */
542 mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
543 }
544 }
545 #endif
546
547 return mmove;
548 }
549
550 /* actions that happen once per ``turn'', regardless of each
551 individual monster's metabolism; some of these might need to
552 be reclassified to occur more in proportion with movement rate */
553 void
mcalcdistress()554 mcalcdistress()
555 {
556 struct monst *mtmp;
557
558 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
559 if (DEADMONSTER(mtmp)) continue;
560
561 /* must check non-moving monsters once/turn in case
562 * they managed to end up in liquid */
563 if (mtmp->data->mmove == 0) {
564 if (vision_full_recalc) vision_recalc(0);
565 if (minliquid(mtmp)) continue;
566 }
567
568 /* regenerate hit points */
569 mon_regen(mtmp, FALSE);
570
571 /* possibly polymorph shapechangers and lycanthropes */
572 if (mtmp->cham && !rn2(6))
573 (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
574 were_change(mtmp);
575
576 /* gradually time out temporary problems */
577 if (mtmp->mblinded && !--mtmp->mblinded)
578 mtmp->mcansee = 1;
579 if (mtmp->mfrozen && !--mtmp->mfrozen)
580 mtmp->mcanmove = 1;
581 if (mtmp->mfleetim && !--mtmp->mfleetim)
582 mtmp->mflee = 0;
583
584 /* FIXME: mtmp->mlstmv ought to be updated here */
585 }
586 }
587
588 int
movemon()589 movemon()
590 {
591 register struct monst *mtmp, *nmtmp;
592 register boolean somebody_can_move = FALSE;
593 #if 0
594 /* part of the original warning code which was replaced in 3.3.1 */
595 warnlevel = 0;
596 #endif
597
598 /*
599 Some of you may remember the former assertion here that
600 because of deaths and other actions, a simple one-pass
601 algorithm wasn't possible for movemon. Deaths are no longer
602 removed to the separate list fdmon; they are simply left in
603 the chain with hit points <= 0, to be cleaned up at the end
604 of the pass.
605
606 The only other actions which cause monsters to be removed from
607 the chain are level migrations and losedogs(). I believe losedogs()
608 is a cleanup routine not associated with monster movements, and
609 monsters can only affect level migrations on themselves, not others
610 (hence the fetching of nmon before moving the monster). Currently,
611 monsters can jump into traps, read cursed scrolls of teleportation,
612 and drink cursed potions of raise level to change levels. These are
613 all reflexive at this point. Should one monster be able to level
614 teleport another, this scheme would have problems.
615 */
616
617 for(mtmp = fmon; mtmp; mtmp = nmtmp) {
618 nmtmp = mtmp->nmon;
619
620 /* Find a monster that we have not treated yet. */
621 if(DEADMONSTER(mtmp))
622 continue;
623 if(mtmp->movement < NORMAL_SPEED)
624 continue;
625
626 mtmp->movement -= NORMAL_SPEED;
627 if (mtmp->movement >= NORMAL_SPEED)
628 somebody_can_move = TRUE;
629
630 if (vision_full_recalc) vision_recalc(0); /* vision! */
631
632 if (minliquid(mtmp)) continue;
633
634 if (is_hider(mtmp->data)) {
635 /* unwatched mimics and piercers may hide again [MRS] */
636 if(restrap(mtmp)) continue;
637 if(mtmp->m_ap_type == M_AP_FURNITURE ||
638 mtmp->m_ap_type == M_AP_OBJECT)
639 continue;
640 if(mtmp->mundetected) continue;
641 }
642
643 /* continue if the monster died fighting */
644 if (Conflict && !mtmp->iswiz && mtmp->mcansee) {
645 /* Note:
646 * Conflict does not take effect in the first round.
647 * Therefore, A monster when stepping into the area will
648 * get to swing at you.
649 *
650 * The call to fightm() must be _last_. The monster might
651 * have died if it returns 1.
652 */
653 if (couldsee(mtmp->mx,mtmp->my) &&
654 (distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) &&
655 fightm(mtmp))
656 continue; /* mon might have died */
657 }
658 if(dochugw(mtmp)) /* otherwise just move the monster */
659 continue;
660 }
661 #if 0
662 /* part of the original warning code which was replaced in 3.3.1 */
663 if(warnlevel > 0)
664 warn_effects();
665 #endif
666
667 if (any_light_source())
668 vision_full_recalc = 1; /* in case a mon moved with a light source */
669 dmonsfree(); /* remove all dead monsters */
670
671 /* a monster may have levteleported player -dlc */
672 if (u.utotype) {
673 deferred_goto();
674 /* changed levels, so these monsters are dormant */
675 somebody_can_move = FALSE;
676 }
677
678 return somebody_can_move;
679 }
680
681 #define mstoning(obj) (ofood(obj) && \
682 (touch_petrifies(&mons[(obj)->corpsenm]) || \
683 (obj)->corpsenm == PM_MEDUSA))
684
685 /*
686 * Maybe eat a metallic object (not just gold).
687 * Return value: 0 => nothing happened, 1 => monster ate something,
688 * 2 => monster died (it must have grown into a genocided form, but
689 * that can't happen at present because nothing which eats objects
690 * has young and old forms).
691 */
692 int
meatmetal(mtmp)693 meatmetal(mtmp)
694 register struct monst *mtmp;
695 {
696 register struct obj *otmp;
697 struct permonst *ptr;
698 int poly, grow, heal, mstone;
699
700 /* If a pet, eating is handled separately, in dog.c */
701 if (mtmp->mtame) return 0;
702
703 /* Eats topmost metal object if it is there */
704 for (otmp = level.objects[mtmp->mx][mtmp->my];
705 otmp; otmp = otmp->nexthere) {
706 if (mtmp->data == &mons[PM_RUST_MONSTER] && !is_rustprone(otmp))
707 continue;
708 if (is_metallic(otmp) && !obj_resists(otmp, 5, 95) &&
709 touch_artifact(otmp,mtmp)) {
710 if (mtmp->data == &mons[PM_RUST_MONSTER] && otmp->oerodeproof) {
711 if (canseemon(mtmp) && flags.verbose) {
712 pline("%s eats %s!",
713 Monnam(mtmp),
714 distant_name(otmp,doname));
715 }
716 /* The object's rustproofing is gone now */
717 otmp->oerodeproof = 0;
718 mtmp->mstun = 1;
719 if (canseemon(mtmp) && flags.verbose) {
720 pline("%s spits %s out in disgust!",
721 Monnam(mtmp), distant_name(otmp,doname));
722 }
723 /* KMH -- Don't eat indigestible/choking objects */
724 } else if (otmp->otyp != AMULET_OF_STRANGULATION &&
725 otmp->otyp != RIN_SLOW_DIGESTION) {
726 if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
727 pline("%s eats %s!", Monnam(mtmp),
728 distant_name(otmp,doname));
729 else if (flags.soundok && flags.verbose)
730 You_hear("a crunching sound.");
731 mtmp->meating = otmp->owt/2 + 1;
732 /* Heal up to the object's weight in hp */
733 if (mtmp->mhp < mtmp->mhpmax) {
734 mtmp->mhp += objects[otmp->otyp].oc_weight;
735 if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
736 }
737 if(otmp == uball) {
738 unpunish();
739 delobj(otmp);
740 } else if (otmp == uchain) {
741 unpunish(); /* frees uchain */
742 } else {
743 poly = polyfodder(otmp);
744 grow = mlevelgain(otmp);
745 heal = mhealup(otmp);
746 mstone = mstoning(otmp);
747 delobj(otmp);
748 ptr = mtmp->data;
749 if (poly) {
750 if (newcham(mtmp, (struct permonst *)0,
751 FALSE, FALSE))
752 ptr = mtmp->data;
753 } else if (grow) {
754 ptr = grow_up(mtmp, (struct monst *)0);
755 } else if (mstone) {
756 if (poly_when_stoned(ptr)) {
757 mon_to_stone(mtmp);
758 ptr = mtmp->data;
759 } else if (!resists_ston(mtmp)) {
760 if (canseemon(mtmp))
761 pline("%s turns to stone!", Monnam(mtmp));
762 monstone(mtmp);
763 ptr = (struct permonst *)0;
764 }
765 } else if (heal) {
766 mtmp->mhp = mtmp->mhpmax;
767 }
768 if (!ptr) return 2; /* it died */
769 }
770 /* Left behind a pile? */
771 if (rnd(25) < 3)
772 (void)mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE, FALSE);
773 newsym(mtmp->mx, mtmp->my);
774 return 1;
775 }
776 }
777 }
778 return 0;
779 }
780
781 int
meatobj(mtmp)782 meatobj(mtmp) /* for gelatinous cubes */
783 register struct monst *mtmp;
784 {
785 register struct obj *otmp, *otmp2;
786 struct permonst *ptr;
787 int poly, grow, heal, count = 0, ecount = 0;
788 char buf[BUFSZ];
789
790 buf[0] = '\0';
791 /* If a pet, eating is handled separately, in dog.c */
792 if (mtmp->mtame) return 0;
793
794 /* Eats organic objects, including cloth and wood, if there */
795 /* Engulfs others, except huge rocks and metal attached to player */
796 for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
797 otmp2 = otmp->nexthere;
798 if (is_organic(otmp) && !obj_resists(otmp, 5, 95) &&
799 touch_artifact(otmp,mtmp)) {
800 if (otmp->otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) &&
801 !resists_ston(mtmp))
802 continue;
803 if (otmp->otyp == AMULET_OF_STRANGULATION ||
804 otmp->otyp == RIN_SLOW_DIGESTION)
805 continue;
806 if (Is_sokoprize(otmp)) continue;
807 ++count;
808 if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
809 pline("%s eats %s!", Monnam(mtmp),
810 distant_name(otmp, doname));
811 else if (flags.soundok && flags.verbose)
812 You_hear("a slurping sound.");
813 /* Heal up to the object's weight in hp */
814 if (mtmp->mhp < mtmp->mhpmax) {
815 mtmp->mhp += objects[otmp->otyp].oc_weight;
816 if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
817 }
818 if (Has_contents(otmp)) {
819 register struct obj *otmp3;
820 /* contents of eaten containers become engulfed; this
821 is arbitrary, but otherwise g.cubes are too powerful */
822 while ((otmp3 = otmp->cobj) != 0) {
823 obj_extract_self(otmp3);
824 if (otmp->otyp == ICE_BOX && otmp3->otyp == CORPSE) {
825 otmp3->age = monstermoves - otmp3->age;
826 start_corpse_timeout(otmp3);
827 }
828 (void) mpickobj(mtmp, otmp3);
829 }
830 }
831 poly = polyfodder(otmp);
832 grow = mlevelgain(otmp);
833 heal = mhealup(otmp);
834 delobj(otmp); /* munch */
835 ptr = mtmp->data;
836 if (poly) {
837 if (newcham(mtmp, (struct permonst *)0, FALSE, FALSE))
838 ptr = mtmp->data;
839 } else if (grow) {
840 ptr = grow_up(mtmp, (struct monst *)0);
841 } else if (heal) {
842 mtmp->mhp = mtmp->mhpmax;
843 }
844 /* in case it polymorphed or died */
845 if (ptr != &mons[PM_GELATINOUS_CUBE])
846 return !ptr ? 2 : 1;
847 } else if (otmp->oclass != ROCK_CLASS &&
848 otmp != uball && otmp != uchain &&
849 !Is_sokoprize(otmp)) {
850 ++ecount;
851 if (ecount == 1) {
852 Sprintf(buf, "%s engulfs %s.", Monnam(mtmp),
853 distant_name(otmp,doname));
854 } else if (ecount == 2)
855 Sprintf(buf, "%s engulfs several objects.", Monnam(mtmp));
856 obj_extract_self(otmp);
857 (void) mpickobj(mtmp, otmp); /* slurp */
858 }
859 /* Engulf & devour is instant, so don't set meating */
860 if (mtmp->minvis) newsym(mtmp->mx, mtmp->my);
861 }
862 if (ecount > 0) {
863 if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0])
864 pline("%s", buf);
865 else if (flags.soundok && flags.verbose)
866 You_hear("%s slurping sound%s.",
867 ecount == 1 ? "a" : "several",
868 ecount == 1 ? "" : "s");
869 }
870 return ((count > 0) || (ecount > 0)) ? 1 : 0;
871 }
872
873 void
mpickgold(mtmp)874 mpickgold(mtmp)
875 register struct monst *mtmp;
876 {
877 register struct obj *gold;
878 int mat_idx;
879
880 if ((gold = g_at(mtmp->mx, mtmp->my)) != 0) {
881 mat_idx = objects[gold->otyp].oc_material;
882 #ifndef GOLDOBJ
883 mtmp->mgold += gold->quan;
884 delobj(gold);
885 #else
886 obj_extract_self(gold);
887 add_to_minv(mtmp, gold);
888 #endif
889 if (cansee(mtmp->mx, mtmp->my) ) {
890 if (flags.verbose && !mtmp->isgd)
891 pline("%s picks up some %s.", Monnam(mtmp),
892 mat_idx == GOLD ? "gold" : "money");
893 newsym(mtmp->mx, mtmp->my);
894 }
895 }
896 }
897
898 boolean
mpickstuff(mtmp,str)899 mpickstuff(mtmp, str)
900 register struct monst *mtmp;
901 register const char *str;
902 {
903 register struct obj *otmp, *otmp2;
904
905 /* let angry 1ES pick up stuff so she can smash boulders */
906 if ((mtmp->data != &mons[PM_BLACK_MARKETEER]) && (!mtmp->mpeaceful)) {
907 /* prevent shopkeepers from leaving the door of their shop */
908 if(mtmp->isshk && inhishop(mtmp)) return FALSE;
909 }
910
911 for(otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
912 otmp2 = otmp->nexthere;
913 /* Nymphs take everything. Most monsters don't pick up corpses. */
914 if (!str ? searches_for_item(mtmp,otmp) :
915 !!(index(str, otmp->oclass))) {
916 if (otmp->otyp == CORPSE && mtmp->data->mlet != S_NYMPH &&
917 /* let a handful of corpse types thru to can_carry() */
918 !touch_petrifies(&mons[otmp->corpsenm]) &&
919 otmp->corpsenm != PM_LIZARD &&
920 !acidic(&mons[otmp->corpsenm])) continue;
921 if (!touch_artifact(otmp,mtmp)) continue;
922 if (!can_carry(mtmp,otmp)) continue;
923 if (is_pool(mtmp->mx,mtmp->my)) continue;
924 #ifdef INVISIBLE_OBJECTS
925 if (otmp->oinvis && !perceives(mtmp->data)) continue;
926 #endif
927 if (Is_sokoprize(otmp)) continue;
928
929 /* let monster pickup the object */
930 mpickup_obj(mtmp, otmp);
931
932 return TRUE; /* pick only one object */
933 }
934 }
935 return FALSE;
936 }
937
938 void
mpickup_obj(mtmp,otmp)939 mpickup_obj(mtmp, otmp)
940 struct monst *mtmp;
941 struct obj *otmp;
942 {
943 if (otmp->otyp == BOULDER && is_rockbreaker(mtmp->data)) {
944 if (cansee(mtmp->mx,mtmp->my)) {
945 pline("A thunderclap rings out, and %s shatters!", (distu(mtmp->mx, mtmp->my) <= 5) ? doname(otmp) : distant_name(otmp, doname));
946 pline("%s strides through the dust cloud.", Monnam(mtmp));
947 } else {
948 pline("A thunderclap rings out!");
949 }
950 } else {
951 if (cansee(mtmp->mx,mtmp->my) && flags.verbose) {
952 pline("%s picks up %s.", Monnam(mtmp),
953 (distu(mtmp->mx, mtmp->my) <= 5) ?
954 doname(otmp) : distant_name(otmp, doname));
955 }
956 }
957 if (otmp->otyp == BOULDER && is_rockbreaker(mtmp->data)) {
958 remove_object(otmp);
959 } else {
960 obj_extract_self(otmp);
961 /* unblock point after extract, before pickup */
962 if (otmp->otyp == BOULDER)
963 unblock_point(otmp->ox,otmp->oy); /* vision */
964 (void) mpickobj(mtmp, otmp); /* may merge and free otmp */
965 }
966 m_dowear(mtmp, FALSE);
967 newsym(mtmp->mx, mtmp->my);
968 }
969
970 int
curr_mon_load(mtmp)971 curr_mon_load(mtmp)
972 register struct monst *mtmp;
973 {
974 register int curload = 0;
975 register struct obj *obj;
976
977 for(obj = mtmp->minvent; obj; obj = obj->nobj) {
978 if(obj->otyp != BOULDER || !throws_rocks(mtmp->data))
979 curload += obj->owt;
980 }
981
982 return curload;
983 }
984
985 int
max_mon_load(mtmp)986 max_mon_load(mtmp)
987 register struct monst *mtmp;
988 {
989 register long maxload;
990
991 /* Base monster carrying capacity is equal to human maximum
992 * carrying capacity, or half human maximum if not strong.
993 * (for a polymorphed player, the value used would be the
994 * non-polymorphed carrying capacity instead of max/half max).
995 * This is then modified by the ratio between the monster weights
996 * and human weights. Corpseless monsters are given a capacity
997 * proportional to their size instead of weight.
998 */
999 if (!mtmp->data->cwt)
1000 maxload = (MAX_CARR_CAP * (long)mtmp->data->msize) / MZ_HUMAN;
1001 else if (!strongmonst(mtmp->data)
1002 || (strongmonst(mtmp->data) && (mtmp->data->cwt > WT_HUMAN)))
1003 maxload = (MAX_CARR_CAP * (long)mtmp->data->cwt) / WT_HUMAN;
1004 else maxload = MAX_CARR_CAP; /*strong monsters w/cwt <= WT_HUMAN*/
1005
1006 if (!strongmonst(mtmp->data)) maxload /= 2;
1007
1008 if (maxload < 1) maxload = 1;
1009
1010 return (int) maxload;
1011 }
1012
1013 /* for restricting monsters' object-pickup */
1014 boolean
can_carry(mtmp,otmp)1015 can_carry(mtmp,otmp)
1016 struct monst *mtmp;
1017 struct obj *otmp;
1018 {
1019 int otyp = otmp->otyp, newload = otmp->owt;
1020 struct permonst *mdat = mtmp->data;
1021
1022 if (notake(mdat)) return FALSE; /* can't carry anything */
1023
1024 if (otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) &&
1025 !(mtmp->misc_worn_check & W_ARMG) && !resists_ston(mtmp))
1026 return FALSE;
1027 if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm]))
1028 return FALSE;
1029 if (objects[otyp].oc_material == SILVER && hates_silver(mdat) &&
1030 (otyp != BELL_OF_OPENING || !is_covetous(mdat)))
1031 return FALSE;
1032
1033 #ifdef STEED
1034 /* Steeds don't pick up stuff (to avoid shop abuse) */
1035 if (mtmp == u.usteed) return (FALSE);
1036 #endif
1037 if (mtmp->isshk) return(TRUE); /* no limit */
1038 if (mtmp->mpeaceful && !mtmp->mtame) return(FALSE);
1039 /* otherwise players might find themselves obligated to violate
1040 * their alignment if the monster takes something they need
1041 */
1042
1043 /* special--boulder throwers carry unlimited amounts of boulders
1044 * and some monsters can shatter boulders (will be handled in mpickstuff) */
1045 if ((throws_rocks(mdat) || is_rockbreaker(mdat)) && otyp == BOULDER)
1046 return(TRUE);
1047
1048 /* nymphs deal in stolen merchandise, but not boulders or statues */
1049 if (mdat->mlet == S_NYMPH)
1050 return (boolean)(otmp->oclass != ROCK_CLASS);
1051
1052 if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) return FALSE;
1053
1054 return(TRUE);
1055 }
1056
1057 /* return number of acceptable neighbour positions */
1058 int
mfndpos(mon,poss,info,flag)1059 mfndpos(mon, poss, info, flag)
1060 register struct monst *mon;
1061 coord *poss; /* coord poss[9] */
1062 long *info; /* long info[9] */
1063 long flag;
1064 {
1065 struct permonst *mdat = mon->data;
1066 register xchar x,y,nx,ny;
1067 register int cnt = 0;
1068 register uchar ntyp;
1069 uchar nowtyp;
1070 boolean wantpool,poolok,lavaok,nodiag,quantumlock;
1071 boolean rockok = FALSE, treeok = FALSE, thrudoor;
1072 int maxx, maxy;
1073
1074 x = mon->mx;
1075 y = mon->my;
1076 nowtyp = levl[x][y].typ;
1077
1078 nodiag = (mdat == &mons[PM_GRID_BUG]);
1079 wantpool = mdat->mlet == S_EEL;
1080 poolok = is_flyer(mdat) || is_clinger(mdat) ||
1081 (is_swimmer(mdat) && !wantpool);
1082 lavaok = is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat);
1083 quantumlock = (is_weeping(mdat));
1084 thrudoor = ((flag & (ALLOW_WALL|BUSTDOOR)) != 0L);
1085 if (flag & ALLOW_DIG) {
1086 struct obj *mw_tmp;
1087
1088 /* need to be specific about what can currently be dug */
1089 if (!needspick(mdat)) {
1090 rockok = treeok = TRUE;
1091 } else if ((mw_tmp = MON_WEP(mon)) && mw_tmp->cursed &&
1092 mon->weapon_check == NO_WEAPON_WANTED) {
1093 rockok = is_pick(mw_tmp);
1094 treeok = is_axe(mw_tmp);
1095 } else {
1096 rockok = (m_carrying(mon, PICK_AXE) ||
1097 (m_carrying(mon, DWARVISH_MATTOCK) &&
1098 !which_armor(mon, W_ARMS)));
1099 treeok = (m_carrying(mon, AXE) ||
1100 (m_carrying(mon, BATTLE_AXE) &&
1101 !which_armor(mon, W_ARMS)));
1102 }
1103 thrudoor |= rockok || treeok;
1104 }
1105
1106 nexttry: /* eels prefer the water, but if there is no water nearby,
1107 they will crawl over land */
1108 if(mon->mconf) {
1109 flag |= ALLOW_ALL;
1110 flag &= ~NOTONL;
1111 }
1112 if(!mon->mcansee)
1113 flag |= ALLOW_SSM;
1114 maxx = min(x+1,COLNO-1);
1115 maxy = min(y+1,ROWNO-1);
1116 for(nx = max(1,x-1); nx <= maxx; nx++)
1117 for(ny = max(0,y-1); ny <= maxy; ny++) {
1118 if(nx == x && ny == y) continue;
1119 if(IS_ROCK(ntyp = levl[nx][ny].typ) &&
1120 !((flag & ALLOW_WALL) && may_passwall(nx,ny)) &&
1121 !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
1122 /* KMH -- Added iron bars */
1123 if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
1124 if(IS_DOOR(ntyp) && !amorphous(mdat) &&
1125 ((levl[nx][ny].doormask & D_CLOSED && !(flag & OPENDOOR)) ||
1126 (levl[nx][ny].doormask & D_LOCKED && !(flag & UNLOCKDOOR))) &&
1127 !thrudoor) continue;
1128 if(nx != x && ny != y && (nodiag ||
1129 #ifdef REINCARNATION
1130 ((IS_DOOR(nowtyp) &&
1131 ((levl[x][y].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))) ||
1132 (IS_DOOR(ntyp) &&
1133 ((levl[nx][ny].doormask & ~D_BROKEN) || Is_rogue_level(&u.uz))))
1134 #else
1135 ((IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN)) ||
1136 (IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)))
1137 #endif
1138 ))
1139 continue;
1140 if(nx != 0 && ny != 0 && canseemon(mon) && quantumlock)
1141 continue;
1142 if((is_pool(nx,ny) == wantpool || poolok) &&
1143 (lavaok || !is_lava(nx,ny))) {
1144 int dispx, dispy;
1145 boolean monseeu = (mon->mcansee && (!Invis || perceives(mdat)));
1146 boolean checkobj = OBJ_AT(nx,ny);
1147
1148 /* Displacement also displaces the Elbereth/scare monster,
1149 * as long as you are visible.
1150 */
1151 if(Displaced && monseeu && (mon->mux==nx) && (mon->muy==ny)) {
1152 dispx = u.ux;
1153 dispy = u.uy;
1154 } else {
1155 dispx = nx;
1156 dispy = ny;
1157 }
1158
1159 info[cnt] = 0;
1160 if (onscary(dispx, dispy, mon)) {
1161 if(!(flag & ALLOW_SSM)) continue;
1162 info[cnt] |= ALLOW_SSM;
1163 }
1164 if((nx == u.ux && ny == u.uy) ||
1165 (nx == mon->mux && ny == mon->muy)) {
1166 if (nx == u.ux && ny == u.uy) {
1167 /* If it's right next to you, it found you,
1168 * displaced or no. We must set mux and muy
1169 * right now, so when we return we can tell
1170 * that the ALLOW_U means to attack _you_ and
1171 * not the image.
1172 */
1173 mon->mux = u.ux;
1174 mon->muy = u.uy;
1175 }
1176 if(!(flag & ALLOW_U)) continue;
1177 info[cnt] |= ALLOW_U;
1178 } else {
1179 if(MON_AT(nx, ny)) {
1180 struct monst *mtmp2 = m_at(nx, ny);
1181 long mmflag = flag | mm_aggression(mon, mtmp2);
1182
1183 if (!(mmflag & ALLOW_M)) continue;
1184 info[cnt] |= ALLOW_M;
1185 if (mtmp2->mtame) {
1186 if (!(mmflag & ALLOW_TM)) continue;
1187 info[cnt] |= ALLOW_TM;
1188 }
1189 }
1190 /* Note: ALLOW_SANCT only prevents movement, not */
1191 /* attack, into a temple. */
1192 if(level.flags.has_temple &&
1193 *in_rooms(nx, ny, TEMPLE) &&
1194 !*in_rooms(x, y, TEMPLE) &&
1195 in_your_sanctuary((struct monst *)0, nx, ny)) {
1196 if(!(flag & ALLOW_SANCT)) continue;
1197 info[cnt] |= ALLOW_SANCT;
1198 }
1199 }
1200 if(checkobj && sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
1201 if(flag & NOGARLIC) continue;
1202 info[cnt] |= NOGARLIC;
1203 }
1204 if(checkobj && sobj_at(BOULDER, nx, ny)) {
1205 if(!(flag & ALLOW_ROCK)) continue;
1206 info[cnt] |= ALLOW_ROCK;
1207 }
1208 if (monseeu && onlineu(nx,ny)) {
1209 if(flag & NOTONL) continue;
1210 info[cnt] |= NOTONL;
1211 }
1212 if (nx != x && ny != y && bad_rock(mdat, x, ny)
1213 && bad_rock(mdat, nx, y)
1214 && (bigmonst(mdat) || (curr_mon_load(mon) > 600)))
1215 continue;
1216 /* The monster avoids a particular type of trap if it's familiar
1217 * with the trap type. Pets get ALLOW_TRAPS and checking is
1218 * done in dogmove.c. In either case, "harmless" traps are
1219 * neither avoided nor marked in info[].
1220 */
1221 { register struct trap *ttmp = t_at(nx, ny);
1222 if(ttmp) {
1223 if(ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0) {
1224 impossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
1225 continue;
1226 }
1227 if ((ttmp->ttyp != RUST_TRAP
1228 || mdat == &mons[PM_IRON_GOLEM])
1229 && ttmp->ttyp != STATUE_TRAP
1230 && ((ttmp->ttyp != PIT
1231 && ttmp->ttyp != SPIKED_PIT
1232 && ttmp->ttyp != TRAPDOOR
1233 && ttmp->ttyp != HOLE)
1234 || (!is_flyer(mdat)
1235 && !is_floater(mdat)
1236 && !is_clinger(mdat))
1237 || In_sokoban(&u.uz))
1238 && (ttmp->ttyp != SLP_GAS_TRAP ||
1239 !resists_sleep(mon))
1240 && (ttmp->ttyp != BEAR_TRAP ||
1241 (mdat->msize > MZ_SMALL &&
1242 !amorphous(mdat) && !is_flyer(mdat)))
1243 && (ttmp->ttyp != FIRE_TRAP ||
1244 !resists_fire(mon))
1245 && (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
1246 && (ttmp->ttyp != WEB || (!amorphous(mdat) &&
1247 !webmaker(mdat)))
1248 ) {
1249 if (!(flag & ALLOW_TRAPS)) {
1250 if (mon->mtrapseen & (1L << (ttmp->ttyp - 1)))
1251 continue;
1252 }
1253 info[cnt] |= ALLOW_TRAPS;
1254 }
1255 }
1256 }
1257 poss[cnt].x = nx;
1258 poss[cnt].y = ny;
1259 cnt++;
1260 }
1261 }
1262 if(!cnt && wantpool && !is_pool(x,y)) {
1263 wantpool = FALSE;
1264 goto nexttry;
1265 }
1266 return(cnt);
1267 }
1268
1269 /* Monster against monster special attacks; for the specified monster
1270 combinations, this allows one monster to attack another adjacent one
1271 in the absence of Conflict. There is no provision for targetting
1272 other monsters; just hand to hand fighting when they happen to be
1273 next to each other. */
1274 STATIC_OVL long
mm_aggression(magr,mdef)1275 mm_aggression(magr, mdef)
1276 struct monst *magr, /* monster that is currently deciding where to move */
1277 *mdef; /* another monster which is next to it */
1278 {
1279 struct permonst *ma,*md;
1280
1281 ma = magr->data;
1282 md = mdef->data;
1283 /* supposedly purple worms are attracted to shrieking because they
1284 like to eat shriekers, so attack the latter when feasible */
1285 if (ma == &mons[PM_PURPLE_WORM] &&
1286 md == &mons[PM_SHRIEKER])
1287 return ALLOW_M|ALLOW_TM;
1288
1289 /* Since the quest guardians are under siege, it makes sense to have
1290 them fight hostiles. (But we don't want the quest leader to be in danger.) */
1291 if(ma->msound==MS_GUARDIAN && mdef->mpeaceful==FALSE)
1292 return ALLOW_M|ALLOW_TM;
1293 /* and vice versa */
1294 if(md->msound==MS_GUARDIAN && magr->mpeaceful==FALSE)
1295 return ALLOW_M|ALLOW_TM;
1296
1297 /* elves vs. orcs */
1298 if(is_elf(ma) && is_orc(md))
1299 return ALLOW_M|ALLOW_TM;
1300 /* and vice versa */
1301 if(is_elf(md) && is_orc(ma))
1302 return ALLOW_M|ALLOW_TM;
1303
1304 /* elves vs. kobolds */
1305 if(is_elf(ma) && md->mlet==S_KOBOLD)
1306 return ALLOW_M|ALLOW_TM;
1307 /* and vice versa */
1308 if(is_elf(md) && ma->mlet==S_KOBOLD)
1309 return ALLOW_M|ALLOW_TM;
1310
1311 /* angels vs. demons */
1312 if(ma->mlet==S_ANGEL && is_demon(md))
1313 return ALLOW_M|ALLOW_TM;
1314 /* and vice versa */
1315 if(md->mlet==S_ANGEL && is_demon(ma))
1316 return ALLOW_M|ALLOW_TM;
1317
1318 /* Nazgul vs. hobbits */
1319 if(ma == &mons[PM_NAZGUL] && md == &mons[PM_HOBBIT])
1320 return ALLOW_M|ALLOW_TM;
1321 /* and vice versa */
1322 if(md == &mons[PM_NAZGUL] && ma == &mons[PM_HOBBIT])
1323 return ALLOW_M|ALLOW_TM;
1324
1325 /* deep orcs vs. dwarves */
1326 if(is_dwarf(ma) && md == &mons[PM_DEEP_ORC])
1327 return ALLOW_M|ALLOW_TM;
1328 /* and vice versa */
1329 if(is_dwarf(md) && ma == &mons[PM_DEEP_ORC])
1330 return ALLOW_M|ALLOW_TM;
1331
1332 /* woodchucks vs. The Oracle */
1333 if(ma == &mons[PM_WOODCHUCK] && md == &mons[PM_ORACLE])
1334 return ALLOW_M|ALLOW_TM;
1335
1336 /* ravens like eyes */
1337 if(ma == &mons[PM_RAVEN] && is_eye(md))
1338 return ALLOW_M|ALLOW_TM;
1339
1340 /* dungeon fern spores hate everything */
1341 if(is_fern_spore(ma) && !is_fern_spore(md) && !is_vegetation(md))
1342 return ALLOW_M|ALLOW_TM;
1343 /* and everything hates them */
1344 if(is_fern_spore(md) && !is_fern_spore(ma) && !is_vegetation(ma))
1345 return ALLOW_M|ALLOW_TM;
1346
1347 return 0L;
1348 }
1349
1350 boolean
monnear(mon,x,y)1351 monnear(mon, x, y)
1352 register struct monst *mon;
1353 register int x,y;
1354 /* Is the square close enough for the monster to move or attack into? */
1355 {
1356 register int distance = dist2(mon->mx, mon->my, x, y);
1357 if (distance==2 && mon->data==&mons[PM_GRID_BUG]) return 0;
1358 return((boolean)(distance < 3));
1359 }
1360
1361 /* really free dead monsters */
1362 void
dmonsfree()1363 dmonsfree()
1364 {
1365 struct monst **mtmp;
1366 int count = 0;
1367
1368 for (mtmp = &fmon; *mtmp;) {
1369 if ((*mtmp)->mhp <= 0) {
1370 struct monst *freetmp = *mtmp;
1371 *mtmp = (*mtmp)->nmon;
1372 dealloc_monst(freetmp);
1373 count++;
1374 } else
1375 mtmp = &(*mtmp)->nmon;
1376 }
1377
1378 if (count != iflags.purge_monsters)
1379 impossible("dmonsfree: %d removed doesn't match %d pending",
1380 count, iflags.purge_monsters);
1381 iflags.purge_monsters = 0;
1382 }
1383
1384 /* called when monster is moved to larger structure */
1385 void
replmon(mtmp,mtmp2)1386 replmon(mtmp, mtmp2)
1387 register struct monst *mtmp, *mtmp2;
1388 {
1389 struct obj *otmp;
1390
1391 /* transfer the monster's inventory */
1392 for (otmp = mtmp2->minvent; otmp; otmp = otmp->nobj) {
1393 #ifdef DEBUG
1394 if (otmp->where != OBJ_MINVENT || otmp->ocarry != mtmp)
1395 panic("replmon: minvent inconsistency");
1396 #endif
1397 otmp->ocarry = mtmp2;
1398 }
1399 mtmp->minvent = 0;
1400
1401 /* remove the old monster from the map and from `fmon' list */
1402 relmon(mtmp);
1403
1404 /* finish adding its replacement */
1405 #ifdef STEED
1406 if (mtmp == u.usteed) ; else /* don't place steed onto the map */
1407 #endif
1408 place_monster(mtmp2, mtmp2->mx, mtmp2->my);
1409 if (mtmp2->wormno) /* update level.monsters[wseg->wx][wseg->wy] */
1410 place_wsegs(mtmp2); /* locations to mtmp2 not mtmp. */
1411 if (emits_light(mtmp2->data)) {
1412 /* since this is so rare, we don't have any `mon_move_light_source' */
1413 new_light_source(mtmp2->mx, mtmp2->my,
1414 emits_light(mtmp2->data),
1415 LS_MONSTER, (genericptr_t)mtmp2);
1416 /* here we rely on the fact that `mtmp' hasn't actually been deleted */
1417 del_light_source(LS_MONSTER, (genericptr_t)mtmp);
1418 }
1419 mtmp2->nmon = fmon;
1420 fmon = mtmp2;
1421 if (u.ustuck == mtmp) u.ustuck = mtmp2;
1422 #ifdef STEED
1423 if (u.usteed == mtmp) u.usteed = mtmp2;
1424 #endif
1425 if (mtmp2->isshk) replshk(mtmp,mtmp2);
1426
1427 /* discard the old monster */
1428 dealloc_monst(mtmp);
1429 }
1430
1431 /* release mon from display and monster list */
1432 void
relmon(mon)1433 relmon(mon)
1434 register struct monst *mon;
1435 {
1436 register struct monst *mtmp;
1437
1438 if (fmon == (struct monst *)0) panic ("relmon: no fmon available.");
1439
1440 remove_monster(mon->mx, mon->my);
1441
1442 if(mon == fmon) fmon = fmon->nmon;
1443 else {
1444 for(mtmp = fmon; mtmp && mtmp->nmon != mon; mtmp = mtmp->nmon) ;
1445 if(mtmp) mtmp->nmon = mon->nmon;
1446 else panic("relmon: mon not in list.");
1447 }
1448 }
1449
1450 /* remove effects of mtmp from other data structures */
1451 STATIC_OVL void
m_detach(mtmp,mptr)1452 m_detach(mtmp, mptr)
1453 struct monst *mtmp;
1454 struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
1455 {
1456 if (mtmp->mleashed) m_unleash(mtmp, FALSE);
1457 /* to prevent an infinite relobj-flooreffects-hmon-killed loop */
1458 mtmp->mtrapped = 0;
1459 mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */
1460 relobj(mtmp, 0, FALSE);
1461 remove_monster(mtmp->mx, mtmp->my);
1462 if (emits_light(mptr))
1463 del_light_source(LS_MONSTER, (genericptr_t)mtmp);
1464 newsym(mtmp->mx,mtmp->my);
1465 unstuck(mtmp);
1466 fill_pit(mtmp->mx, mtmp->my);
1467
1468 if(mtmp->isshk) shkgone(mtmp);
1469 if(mtmp->wormno) wormgone(mtmp);
1470 iflags.purge_monsters++;
1471 }
1472
1473 /* find the worn amulet of life saving which will save a monster */
1474 struct obj *
mlifesaver(mon)1475 mlifesaver(mon)
1476 struct monst *mon;
1477 {
1478 if (!nonliving(mon->data)) {
1479 struct obj *otmp = which_armor(mon, W_AMUL);
1480
1481 if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING)
1482 return otmp;
1483 }
1484 return (struct obj *)0;
1485 }
1486
1487 STATIC_OVL void
1488 #ifdef WEBB_DISINT
lifesaved_monster(mtmp,adtyp)1489 lifesaved_monster(mtmp,adtyp)
1490 struct monst *mtmp;
1491 uchar adtyp;
1492 #else
1493 lifesaved_monster(mtmp)
1494 struct monst *mtmp;
1495 #endif
1496 {
1497 struct obj *lifesave = mlifesaver(mtmp);
1498
1499 if (lifesave) {
1500 /* not canseemon; amulets are on the head, so you don't want */
1501 /* to show this for a long worm with only a tail visible. */
1502 /* Nor do you check invisibility, because glowing and disinte- */
1503 /* grating amulets are always visible. */
1504 if (cansee(mtmp->mx, mtmp->my)) {
1505 pline("But wait...");
1506 pline("%s medallion begins to glow!",
1507 s_suffix(Monnam(mtmp)));
1508 makeknown(AMULET_OF_LIFE_SAVING);
1509 if (attacktype(mtmp->data, AT_EXPL)
1510 || attacktype(mtmp->data, AT_BOOM)
1511 #ifdef WEBB_DISINT
1512 || adtyp == AD_DISN
1513 #endif
1514 )
1515 pline("%s reconstitutes!", Monnam(mtmp));
1516 else
1517 pline("%s looks much better!", Monnam(mtmp));
1518 pline_The("medallion crumbles to dust!");
1519 }
1520 m_useup(mtmp, lifesave);
1521 mtmp->mcanmove = 1;
1522 mtmp->mfrozen = 0;
1523 if (mtmp->mtame && !mtmp->isminion) {
1524 wary_dog(mtmp, FALSE);
1525 }
1526 if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
1527 mtmp->mhp = mtmp->mhpmax;
1528 if (mvitals[monsndx(mtmp->data)].mvflags & G_GENOD) {
1529 if (cansee(mtmp->mx, mtmp->my))
1530 pline("Unfortunately %s is still genocided...",
1531 mon_nam(mtmp));
1532 } else
1533 return;
1534 }
1535 mtmp->mhp = 0;
1536 }
1537
1538 #ifndef WEBB_DISINT
1539 void
mondead(mtmp)1540 mondead(mtmp)
1541 register struct monst *mtmp;
1542 #else
1543 void
1544 mondead(mtmp)
1545 register struct monst *mtmp;
1546 {
1547 mondead_helper(mtmp, 0); /* mmm... default parameter values */
1548 }
1549
1550 void
1551 mondead_helper(mtmp, adtyp)
1552 register struct monst * mtmp;
1553 uchar adtyp;
1554 #endif
1555 {
1556 struct permonst *mptr;
1557 int tmp;
1558 struct obj* otmp;
1559
1560 if(mtmp->isgd) {
1561 /* if we're going to abort the death, it *must* be before
1562 * the m_detach or there will be relmon problems later */
1563 if(!grddead(mtmp)) return;
1564 }
1565 #ifdef WEBB_DISINT
1566 lifesaved_monster(mtmp, adtyp);
1567 #else
1568 lifesaved_monster(mtmp);
1569 #endif
1570 if (mtmp->mhp > 0) return;
1571
1572 #ifdef STEED
1573 /* Player is thrown from his steed when it dies */
1574 if (mtmp == u.usteed)
1575 dismount_steed(DISMOUNT_GENERIC);
1576 #endif
1577
1578 /* extinguish monster's armor */
1579 if ((otmp = which_armor(mtmp, W_ARM)) && (Is_glowing_dragon_armor(otmp->otyp)))
1580 end_burn(otmp,FALSE);
1581
1582 mptr = mtmp->data; /* save this for m_detach() */
1583 /* restore chameleon, lycanthropes to true form at death */
1584 if (mtmp->cham)
1585 set_mon_data(mtmp, &mons[cham_to_pm[mtmp->cham]], -1);
1586 else if (mtmp->data == &mons[PM_WEREJACKAL])
1587 set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
1588 else if (mtmp->data == &mons[PM_WEREWOLF])
1589 set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
1590 else if (mtmp->data == &mons[PM_WERERAT])
1591 set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
1592
1593 /* if MAXMONNO monsters of a given type have died, and it
1594 * can be done, extinguish that monster.
1595 *
1596 * mvitals[].died does double duty as total number of dead monsters
1597 * and as experience factor for the player killing more monsters.
1598 * this means that a dragon dying by other means reduces the
1599 * experience the player gets for killing a dragon directly; this
1600 * is probably not too bad, since the player likely finagled the
1601 * first dead dragon via ring of conflict or pets, and extinguishing
1602 * based on only player kills probably opens more avenues of abuse
1603 * for rings of conflict and such.
1604 */
1605 tmp = monsndx(mtmp->data);
1606 if (mvitals[tmp].died < 255) mvitals[tmp].died++;
1607
1608 /* killing an artifact-guardian is ordinary robbery */
1609 if (is_guardian(mtmp->data))
1610 violated(CONDUCT_THIEVERY);
1611
1612 /* if it's a (possibly polymorphed) quest leader, mark him as dead */
1613 if (mtmp->m_id == quest_status.leader_m_id)
1614 quest_status.leader_is_dead = TRUE;
1615 #ifdef MAIL
1616 /* if the mail daemon dies, no more mail delivery. -3. */
1617 if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
1618 #endif
1619
1620 #ifdef KOPS
1621 if (mtmp->data->mlet == S_KOP) {
1622 /* Dead Kops may come back. */
1623 switch(rnd(5)) {
1624 case 1: /* returns near the stairs */
1625 (void) makemon(mtmp->data,xdnstair,ydnstair,NO_MM_FLAGS);
1626 break;
1627 case 2: /* randomly */
1628 (void) makemon(mtmp->data,0,0,NO_MM_FLAGS);
1629 break;
1630 default:
1631 break;
1632 }
1633 }
1634 #endif
1635
1636 #ifdef BLACKMARKET
1637 if (Is_blackmarket(&u.uz) && tmp == PM_ONE_EYED_SAM) {
1638 bars_around_portal(TRUE);
1639 }
1640 #endif /* BLACKMARKET */
1641
1642 if(mtmp->iswiz) wizdead();
1643 if(mtmp->data->msound == MS_NEMESIS) nemdead();
1644
1645 #ifdef RECORD_ACHIEVE
1646 if(mtmp->data == &mons[PM_MEDUSA])
1647 achieve.killed_medusa = 1;
1648 #ifdef LIVELOGFILE
1649 livelog_achieve_update();
1650 #endif
1651 #endif
1652
1653 if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
1654 unmap_object(mtmp->mx, mtmp->my);
1655 m_detach(mtmp, mptr);
1656 }
1657
1658 /** TRUE if corpse might be dropped, magr may die if mon was swallowed */
1659 boolean
corpse_chance(mon,magr,was_swallowed)1660 corpse_chance(mon, magr, was_swallowed)
1661 struct monst *mon;
1662 struct monst *magr; /* killer, if swallowed */
1663 boolean was_swallowed; /* digestion */
1664 {
1665 struct permonst *mdat = mon->data;
1666 int i, tmp;
1667
1668 if (mdat == &mons[PM_VLAD_THE_IMPALER] || mdat->mlet == S_LICH
1669 #ifdef WEBB_DISINT
1670 || mdat == &mons[PM_DISINTEGRATOR]
1671 #endif
1672 ) {
1673 if (cansee(mon->mx, mon->my) && !was_swallowed)
1674 pline("%s body crumbles into dust.", s_suffix(Monnam(mon)));
1675 return FALSE;
1676 }
1677
1678 /* Trolls don't leave a corpse when the player is wielding Trollsbane */
1679 if (mdat->mlet == S_TROLL && uwep && uwep->oartifact == ART_TROLLSBANE) {
1680 if (cansee(mon->mx, mon->my)) {
1681 pline("%s corpse flares brightly and burns to ashes.", s_suffix(Monnam(mon)));
1682 return FALSE;
1683 }
1684 }
1685
1686 /* Gas spores always explode upon death */
1687 for(i = 0; i < NATTK; i++) {
1688 if (mdat->mattk[i].aatyp == AT_BOOM) {
1689 if (mdat->mattk[i].damn)
1690 tmp = d((int)mdat->mattk[i].damn,
1691 (int)mdat->mattk[i].damd);
1692 else if(mdat->mattk[i].damd)
1693 tmp = d((int)mdat->mlevel+1, (int)mdat->mattk[i].damd);
1694 else tmp = 0;
1695 if (was_swallowed && magr) {
1696 if (magr == &youmonst) {
1697 There("is an explosion in your %s!",
1698 body_part(STOMACH));
1699 Sprintf(killer_buf, "%s explosion",
1700 s_suffix(mdat->mname));
1701 if (Half_physical_damage) tmp = (tmp+1) / 2;
1702 losehp(tmp, killer_buf, KILLED_BY_AN);
1703 } else {
1704 if (flags.soundok) You_hear("an explosion.");
1705 magr->mhp -= tmp;
1706 if (magr->mhp < 1) mondied(magr);
1707 if (magr->mhp < 1) { /* maybe lifesaved */
1708 if (canspotmon(magr))
1709 pline("%s rips open!", Monnam(magr));
1710 } else if (canseemon(magr))
1711 pline("%s seems to have indigestion.",
1712 Monnam(magr));
1713 }
1714
1715 return FALSE;
1716 }
1717
1718 Sprintf(killer_buf, "%s explosion", s_suffix(mdat->mname));
1719 killer = killer_buf;
1720 killer_format = KILLED_BY_AN;
1721 explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE, EXPL_NOXIOUS);
1722 return (FALSE);
1723 }
1724 }
1725
1726 /* must duplicate this below check in xkilled() since it results in
1727 * creating no objects as well as no corpse
1728 */
1729 if (LEVEL_SPECIFIC_NOCORPSE(mdat))
1730 return FALSE;
1731
1732 if (bigmonst(mdat) || mdat == &mons[PM_LIZARD]
1733 || is_golem(mdat)
1734 || is_mplayer(mdat)
1735 || is_rider(mdat))
1736 return TRUE;
1737 return (boolean) (!rn2((int)
1738 (2 + ((int)(mdat->geno & G_FREQ)<2) + verysmall(mdat))));
1739 }
1740
1741 /** Creates Cthulhu's death message and death cloud. */
1742 void
cthulhu_dies(mon)1743 cthulhu_dies(mon)
1744 struct monst *mon; /**< Cthulhu's struct */
1745 {
1746 /* really dead? */
1747 if (mon->mhp <= 0) {
1748 /* Cthulhu Deliquesces... */
1749 if (cansee(mon->mx, mon->my)) {
1750 pline("%s body deliquesces into a cloud of noxious gas!",
1751 s_suffix(Monnam(mon)));
1752 } else {
1753 You_hear("hissing and bubbling!");
1754 }
1755 /* ...into a stinking cloud... */
1756 if (mvitals[PM_CTHULHU].died == 1 &&
1757 distu(mon->mx, mon->my) > 2) {
1758 /* Cthulhu got killed while meditating and the player
1759 * was not next to him.
1760 * You can't get rid of the True Final Boss so easily! */
1761 (void) create_cthulhu_death_cloud(mon->mx, mon->my, 2, 4, rnd(4));
1762 } else {
1763 (void) create_cthulhu_death_cloud(mon->mx, mon->my, 3, 8, rn1(30,30));
1764 }
1765 }
1766 }
1767
1768 void
spore_dies(mon)1769 spore_dies(mon)
1770 struct monst *mon;
1771 {
1772 if (mon->mhp <= 0) {
1773 int sporetype;
1774 coord mm; schar ltyp;
1775 mm.x = mon->mx; mm.y = mon->my;
1776 ltyp = levl[mm.x][mm.y].typ;
1777 create_gas_cloud(mm.x, mm.y, rn1(2,1), rnd(8), rn1(3,2));
1778 /* all fern spores have a 2/3 chance of creating nothing, except for
1779 the generic fern spore, which guarantees a terrain-appropriate fern */
1780 if (mon->data == &mons[PM_DUNGEON_FERN_SPORE]) {
1781 /* dungeon ferns cannot reproduce on ice, lava, or water; swamp is okay */
1782 if (!is_ice(mm.x, mm.y) && !is_lava(mm.x, mm.y) && !is_pool(mm.x, mm.y))
1783 sporetype = 0;
1784 else return;
1785 if (rn2(3)) return;
1786 } else if (mon->data == &mons[PM_ARCTIC_FERN_SPORE]) {
1787 /* arctic ferns can only reproduce on water, ice, or in swamp */
1788 if (ltyp == POOL || ltyp == MOAT || is_ice(mm.x, mm.y) || is_swamp(mm.x, mm.y))
1789 sporetype = 1;
1790 else return;
1791 if (rn2(3)) return;
1792 } else if (mon->data == &mons[PM_BLAZING_FERN_SPORE]) {
1793 /* blazing ferns can only reproduce on lava */
1794 if (is_lava(mm.x, mm.y))
1795 sporetype = 2;
1796 else return;
1797 if (rn2(3)) return;
1798 } else if (mon->data == &mons[PM_SWAMP_FERN_SPORE]) {
1799 /* swamp ferns can only reproduce in swamp */
1800 if (is_swamp(mm.x, mm.y))
1801 sporetype = 3;
1802 else return;
1803 if (rn2(3)) return;
1804 } else {
1805 if (is_ice(mm.x, mm.y) || is_pool(mm.x, mm.y)) {
1806 sporetype = 1;
1807 } else if (is_lava(mm.x, mm.y)) {
1808 sporetype = 2;
1809 } else if (is_swamp(mm.x, mm.y)) {
1810 sporetype = 3;
1811 } else {
1812 sporetype = rn2(4);
1813 }
1814 }
1815 /* when creating a new fern, 5/6 chance of creating
1816 a fern sprout and 1/6 chance of a fully-grown one */
1817 switch (sporetype) {
1818 case 0:
1819 if (!rn2(6)) makemon(&mons[PM_DUNGEON_FERN], mm.x, mm.y, NO_MM_FLAGS);
1820 else makemon(&mons[PM_DUNGEON_FERN_SPROUT], mm.x, mm.y, NO_MM_FLAGS);
1821 break;
1822 case 1:
1823 if (ltyp == POOL || ltyp == MOAT || is_swamp(mm.x, mm.y)) {
1824 levl[mm.x][mm.y].typ = ICE;
1825 You_hear(Hallucination ? "someone selling hot chocolate." : "a crackling sound.");
1826 }
1827 if (!rn2(6)) makemon(&mons[PM_ARCTIC_FERN], mm.x, mm.y, NO_MM_FLAGS);
1828 else makemon(&mons[PM_ARCTIC_FERN_SPROUT], mm.x, mm.y, NO_MM_FLAGS);
1829 break;
1830 case 2:
1831 levl[mm.x][mm.y].typ = ROOM;
1832 if (!rn2(6)) makemon(&mons[PM_BLAZING_FERN], mm.x, mm.y, NO_MM_FLAGS);
1833 else makemon(&mons[PM_BLAZING_FERN_SPROUT], mm.x, mm.y, NO_MM_FLAGS);
1834 break;
1835 case 3:
1836 if (!rn2(6)) makemon(&mons[PM_SWAMP_FERN], mm.x, mm.y, NO_MM_FLAGS);
1837 else makemon(&mons[PM_SWAMP_FERN_SPROUT], mm.x, mm.y, NO_MM_FLAGS);
1838 break;
1839 default:
1840 warning("Unknown spore type: (%d)", sporetype);
1841 break;
1842 }
1843
1844 }
1845 }
1846
1847 /** drop (perhaps) a cadaver and remove monster */
1848 void
mondied(mdef)1849 mondied(mdef)
1850 register struct monst *mdef;
1851 {
1852 mondead(mdef);
1853 if (mdef->mhp > 0) return; /* lifesaved */
1854
1855 if (corpse_chance(mdef, (struct monst *)0, FALSE) &&
1856 (accessible(mdef->mx, mdef->my) || is_pool(mdef->mx, mdef->my)))
1857 (void) make_corpse(mdef);
1858 }
1859
1860 /** monster disappears, not dies */
1861 void
mongone(mdef)1862 mongone(mdef)
1863 register struct monst *mdef;
1864 {
1865 mdef->mhp = 0; /* can skip some inventory bookkeeping */
1866 #ifdef STEED
1867 /* Player is thrown from his steed when it disappears */
1868 if (mdef == u.usteed)
1869 dismount_steed(DISMOUNT_GENERIC);
1870 #endif
1871
1872 /* drop special items like the Amulet so that a dismissed Kop or nurse
1873 can't remove them from the game */
1874 mdrop_special_objs(mdef);
1875 /* release rest of monster's inventory--it is removed from game */
1876 discard_minvent(mdef);
1877 #ifndef GOLDOBJ
1878 mdef->mgold = 0L;
1879 #endif
1880 m_detach(mdef, mdef->data);
1881 }
1882
1883 /** drop a statue or rock and remove monster */
1884 void
monstone(mdef)1885 monstone(mdef)
1886 register struct monst *mdef;
1887 {
1888 struct obj *otmp, *obj, *oldminvent;
1889 xchar x = mdef->mx, y = mdef->my;
1890 boolean wasinside = FALSE;
1891 #ifndef GOLDOBJ
1892 long mgold=0;
1893 #endif
1894
1895 /* we have to make the statue before calling mondead, to be able to
1896 * put inventory in it, and we have to check for lifesaving before
1897 * making the statue....
1898 */
1899 #ifdef WEBB_DISINT
1900 lifesaved_monster(mdef, AD_STON);
1901 #else
1902 lifesaved_monster(mdef);
1903 #endif
1904 if (mdef->mhp > 0) return;
1905
1906 mdef->mtrapped = 0; /* (see m_detach) */
1907
1908 if ((int)mdef->data->msize > MZ_TINY ||
1909 !rn2(2 + ((int) (mdef->data->geno & G_FREQ) > 2))) {
1910 oldminvent = 0;
1911 /* some objects may end up outside the statue */
1912 while ((obj = mdef->minvent) != 0) {
1913 obj_extract_self(obj);
1914 if (obj->owornmask)
1915 update_mon_intrinsics(mdef, obj, FALSE, TRUE);
1916 obj_no_longer_held(obj);
1917 if (obj->owornmask & W_WEP)
1918 setmnotwielded(mdef,obj);
1919 obj->owornmask = 0L;
1920 if (obj->otyp == BOULDER ||
1921 #if 0 /* monsters don't carry statues */
1922 (obj->otyp == STATUE && mons[obj->corpsenm].msize >= mdef->data->msize) ||
1923 #endif
1924 obj_resists(obj, 0, 0)) {
1925 if (flooreffects(obj, x, y, "fall")) continue;
1926 place_object(obj, x, y);
1927 } else {
1928 if (obj->lamplit) end_burn(obj, TRUE);
1929 obj->nobj = oldminvent;
1930 oldminvent = obj;
1931 }
1932 }
1933
1934 #ifndef GOLDOBJ
1935 /* fix SC343-8 and C343-94 */
1936 mgold = mdef->mgold;
1937 mdef->mgold = 0;
1938 #endif
1939 /* defer statue creation until after inventory removal
1940 so that saved monster traits won't retain any stale
1941 item-conferred attributes */
1942 otmp = mkcorpstat(STATUE, KEEPTRAITS(mdef) ? mdef : 0,
1943 mdef->data, x, y, FALSE);
1944 if (mdef->mnamelth) otmp = oname(otmp, NAME(mdef));
1945 while ((obj = oldminvent) != 0) {
1946 oldminvent = obj->nobj;
1947 (void) add_to_container(otmp, obj);
1948 }
1949 #ifndef GOLDOBJ
1950 if (mgold) {
1951 struct obj *au;
1952 au = mksobj(GOLD_PIECE, FALSE, FALSE);
1953 au->quan = mgold;
1954 au->owt = weight(au);
1955 (void) add_to_container(otmp, au);
1956 }
1957 #endif
1958 /* Archeologists should not break unique statues */
1959 if (mdef->data->geno & G_UNIQ)
1960 otmp->spe = 1;
1961 otmp->owt = weight(otmp);
1962 } else
1963 otmp = mksobj_at(ROCK, x, y, TRUE, FALSE);
1964
1965 stackobj(otmp);
1966 /* mondead() already does this, but we must do it before the newsym */
1967 if(glyph_is_invisible(levl[x][y].glyph))
1968 unmap_object(x, y);
1969 if (cansee(x, y)) newsym(x,y);
1970 /* We don't currently trap the hero in the statue in this case but we could */
1971 if (u.uswallow && u.ustuck == mdef) wasinside = TRUE;
1972 mondead(mdef);
1973 if (wasinside) {
1974 if (is_animal(mdef->data))
1975 You("%s through an opening in the new %s.",
1976 locomotion(youmonst.data, "jump"),
1977 xname(otmp));
1978 }
1979 }
1980
1981 /* another monster has killed the monster mdef */
1982 void
monkilled(mdef,fltxt,how)1983 monkilled(mdef, fltxt, how)
1984 register struct monst *mdef;
1985 const char *fltxt;
1986 int how;
1987 {
1988 boolean be_sad = FALSE; /* true if unseen pet is killed */
1989 boolean kenny = (!strcmp(m_monnam(mdef), "Kenny"));
1990
1991 if ((mdef->wormno ? worm_known(mdef) : cansee(mdef->mx, mdef->my))
1992 && fltxt)
1993 pline("%s is %s%s%s!", Monnam(mdef),
1994 nonliving(mdef->data) ? "destroyed" : "killed",
1995 *fltxt ? " by the " : "",
1996 fltxt
1997 );
1998 else
1999 be_sad = (mdef->mtame != 0);
2000
2001 /* no corpses if digested or disintegrated */
2002 if (how == AD_DGST || how == -AD_RBRE
2003 #ifdef WEBB_DISINT
2004 || how == AD_DISN)
2005 mondead_helper(mdef, how);
2006 #else
2007 )
2008 mondead(mdef);
2009 #endif
2010 else
2011 mondied(mdef);
2012
2013 if (mdef->data == &mons[PM_CTHULHU]) {
2014 cthulhu_dies(mdef);
2015 }
2016
2017 if (is_fern_spore(mdef->data)) {
2018 spore_dies(mdef);
2019 }
2020
2021 if (be_sad && mdef->mhp <= 0) {
2022 if (kenny || (Hallucination && !rn2(4))) {
2023 verbalize("Oh my god, they killed Kenny!");
2024 verbalize("You bastards!");
2025 } else {
2026 You("have a %s feeling for a moment, then it passes.",
2027 (Hallucination ? "plaid" : "sad"));
2028 }
2029 }
2030 }
2031
2032 void
unstuck(mtmp)2033 unstuck(mtmp)
2034 register struct monst *mtmp;
2035 {
2036 if(u.ustuck == mtmp) {
2037 if(u.uswallow){
2038 u.ux = mtmp->mx;
2039 u.uy = mtmp->my;
2040 u.uswallow = 0;
2041 u.uswldtim = 0;
2042 if (Punished) placebc();
2043 vision_full_recalc = 1;
2044 docrt();
2045 }
2046 u.ustuck = 0;
2047 }
2048 }
2049
2050 void
killed(mtmp)2051 killed(mtmp)
2052 register struct monst *mtmp;
2053 {
2054 xkilled(mtmp, 1);
2055 }
2056
2057 /* the player has killed the monster mtmp */
2058 void
xkilled(mtmp,dest)2059 xkilled(mtmp, dest)
2060 register struct monst *mtmp;
2061 /*
2062 * Dest=1, normal; dest=0, don't print message; dest=2, don't drop corpse
2063 * either; dest=3, message but no corpse
2064 */
2065 int dest;
2066 {
2067 register int tmp, x = mtmp->mx, y = mtmp->my;
2068 register struct permonst *mdat;
2069 int mndx;
2070 register struct obj *otmp;
2071 register struct trap *t;
2072 boolean redisp = FALSE;
2073 boolean wasinside = u.uswallow && (u.ustuck == mtmp);
2074
2075
2076 /* KMH, conduct */
2077 violated(CONDUCT_PACIFISM);
2078
2079 if (dest & 1) {
2080 const char *verb = nonliving(mtmp->data) ? "destroy" : "kill";
2081
2082 if (!wasinside && !canspotmon(mtmp))
2083 You("%s it!", verb);
2084 else {
2085 You("%s %s!", verb,
2086 !mtmp->mtame ? mon_nam(mtmp) :
2087 x_monnam(mtmp,
2088 mtmp->mnamelth ? ARTICLE_NONE : ARTICLE_THE,
2089 "poor",
2090 mtmp->mnamelth ? SUPPRESS_SADDLE : 0,
2091 FALSE));
2092 }
2093 }
2094
2095 if (mtmp->mtrapped && (t = t_at(x, y)) != 0 &&
2096 (t->ttyp == PIT || t->ttyp == SPIKED_PIT) &&
2097 sobj_at(BOULDER, x, y))
2098 dest |= 2; /*
2099 * Prevent corpses/treasure being created "on top"
2100 * of the boulder that is about to fall in. This is
2101 * out of order, but cannot be helped unless this
2102 * whole routine is rearranged.
2103 */
2104
2105 /* your pet knows who just killed it...watch out */
2106 if (mtmp->mtame && !mtmp->isminion) EDOG(mtmp)->killed_by_u = 1;
2107
2108 /* dispose of monster and make cadaver */
2109 if(stoned) monstone(mtmp);
2110 else mondead(mtmp);
2111
2112 if (mtmp->mhp > 0) { /* monster lifesaved */
2113 /* Cannot put the non-visible lifesaving message in
2114 * lifesaved_monster() since the message appears only when you
2115 * kill it (as opposed to visible lifesaving which always
2116 * appears).
2117 */
2118 stoned = FALSE;
2119 if (!cansee(x,y)) pline("Maybe not...");
2120 return;
2121 }
2122
2123 mdat = mtmp->data; /* note: mondead can change mtmp->data */
2124 mndx = monsndx(mdat);
2125
2126 if (mdat == &mons[PM_CTHULHU]) {
2127 cthulhu_dies(mtmp);
2128 }
2129
2130 if (is_fern_spore(mdat)) {
2131 spore_dies(mtmp);
2132 }
2133
2134 if (stoned) {
2135 stoned = FALSE;
2136 goto cleanup;
2137 }
2138
2139 if((dest & 2) || LEVEL_SPECIFIC_NOCORPSE(mdat))
2140 goto cleanup;
2141
2142 #ifdef MAIL
2143 if(mdat == &mons[PM_MAIL_DAEMON]) {
2144 stackobj(mksobj_at(SCR_MAIL, x, y, FALSE, FALSE));
2145 redisp = TRUE;
2146 }
2147 #endif
2148 if((!accessible(x, y) && !is_pool(x, y)) ||
2149 (x == u.ux && y == u.uy)) {
2150 /* might be mimic in wall or corpse in lava or on player's spot */
2151 redisp = TRUE;
2152 if(wasinside) spoteffects(TRUE);
2153 } else if(x != u.ux || y != u.uy) {
2154 /* might be here after swallowed */
2155 if (!flags.deathdropless && !rn2(6) &&
2156 !(mvitals[mndx].mvflags & G_NOCORPSE)
2157 /* disable death drop for puddings */
2158 && mdat->mlet != S_PUDDING
2159 #ifdef KOPS
2160 && mdat->mlet != S_KOP
2161 #endif
2162 ) {
2163 int typ;
2164
2165 otmp = mkobj_at(RANDOM_CLASS, x, y, TRUE);
2166 /* Don't create large objects from small monsters */
2167 typ = otmp->otyp;
2168 if (mdat->msize < MZ_HUMAN && typ != FOOD_RATION
2169 && typ != LEASH
2170 && typ != FIGURINE
2171 && (otmp->owt > 3 ||
2172 objects[typ].oc_big /*oc_bimanual/oc_bulky*/ ||
2173 is_spear(otmp) || is_pole(otmp) ||
2174 typ == MORNING_STAR)) {
2175 delobj(otmp);
2176 } else redisp = TRUE;
2177 }
2178 /* Whether or not it always makes a corpse is, in theory,
2179 * different from whether or not the corpse is "special";
2180 * if we want both, we have to specify it explicitly.
2181 */
2182 if (corpse_chance(mtmp, (struct monst *)0, FALSE))
2183 (void) make_corpse(mtmp);
2184 }
2185 if(redisp) newsym(x,y);
2186 cleanup:
2187 /* punish bad behaviour */
2188 if(is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0) &&
2189 (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD) &&
2190 u.ualign.type != A_CHAOTIC) {
2191 HTelepat &= ~INTRINSIC;
2192 change_luck(-2);
2193 You("murderer!");
2194 if (Blind && !Blind_telepat)
2195 see_monsters(); /* Can't sense monsters any more. */
2196 }
2197 if((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame) change_luck(-1);
2198 if (is_unicorn(mdat) &&
2199 sgn(u.ualign.type) == sgn(mdat->maligntyp)) {
2200 change_luck(-5);
2201 You_feel("guilty...");
2202 }
2203
2204 /* give experience points */
2205 int nr_killed = (int)mvitals[mndx].died;
2206 tmp = experience(mtmp, nr_killed);
2207 more_experienced(tmp, max(tmp/nr_killed,1), 0);
2208 newexplevel(); /* will decide if you go up */
2209
2210 /* adjust alignment points */
2211 if (mtmp->m_id == quest_status.leader_m_id) { /* REAL BAD! */
2212 adjalign(-(u.ualign.record+(int)ALIGNLIM/2));
2213 pline("That was %sa bad idea...",
2214 u.uevent.qcompleted ? "probably " : "");
2215 } else if (mdat->msound == MS_NEMESIS) /* Real good! */
2216 adjalign((int)(ALIGNLIM/4));
2217 else if (mdat->msound == MS_GUARDIAN) { /* Bad */
2218 adjalign(-(int)(ALIGNLIM/8));
2219 if (!Hallucination) pline("That was probably a bad idea...");
2220 else pline("Whoopsie-daisy!");
2221 }else if (mtmp->ispriest) {
2222 adjalign((p_coaligned(mtmp)) ? -2 : 2);
2223 /* cancel divine protection for killing your priest */
2224 if (p_coaligned(mtmp)) u.ublessed = 0;
2225 if (mdat->maligntyp == A_NONE)
2226 adjalign((int)(ALIGNLIM / 4)); /* BIG bonus */
2227 } else if (mtmp->mtame) {
2228 adjalign(-15); /* bad!! */
2229 /* your god is mighty displeased... */
2230 if (!Hallucination) You_hear("the rumble of distant thunder...");
2231 else You_hear("the studio audience applaud!");
2232 } else if (mtmp->mpeaceful)
2233 adjalign(-5);
2234
2235 /* malign was already adjusted for u.ualign.type and randomization */
2236 adjalign(mtmp->malign);
2237
2238 #ifdef LIVELOG_BONES_KILLER
2239 livelog_bones_killed(mtmp);
2240 #endif
2241 }
2242
2243 /* changes the monster into a stone monster of the same type */
2244 /* this should only be called when poly_when_stoned() is true */
2245 void
mon_to_stone(mtmp)2246 mon_to_stone(mtmp)
2247 register struct monst *mtmp;
2248 {
2249 if(mtmp->data->mlet == S_GOLEM) {
2250 /* it's a golem, and not a stone golem */
2251 if(canseemon(mtmp))
2252 pline("%s solidifies...", Monnam(mtmp));
2253 if (newcham(mtmp, &mons[PM_STONE_GOLEM], FALSE, FALSE)) {
2254 if(canseemon(mtmp))
2255 pline("Now it's %s.", an(mtmp->data->mname));
2256 } else {
2257 if(canseemon(mtmp))
2258 pline("... and returns to normal.");
2259 }
2260 } else
2261 impossible("Can't polystone %s!", a_monnam(mtmp));
2262 }
2263
2264 void
mnexto(mtmp)2265 mnexto(mtmp) /* Make monster mtmp next to you (if possible) */
2266 struct monst *mtmp;
2267 {
2268 coord mm;
2269
2270 #ifdef STEED
2271 if (mtmp == u.usteed) {
2272 /* Keep your steed in sync with you instead */
2273 mtmp->mx = u.ux;
2274 mtmp->my = u.uy;
2275 return;
2276 }
2277 #endif
2278
2279 if(!enexto(&mm, u.ux, u.uy, mtmp->data)) return;
2280 rloc_to(mtmp, mm.x, mm.y);
2281 return;
2282 }
2283
2284 /* mnearto()
2285 * Put monster near (or at) location if possible.
2286 * Returns:
2287 * 1 - if a monster was moved from x, y to put mtmp at x, y.
2288 * 0 - in most cases.
2289 */
2290 boolean
mnearto(mtmp,x,y,move_other)2291 mnearto(mtmp,x,y,move_other)
2292 register struct monst *mtmp;
2293 xchar x, y;
2294 boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
2295 {
2296 struct monst *othermon = (struct monst *)0;
2297 xchar newx, newy;
2298 coord mm;
2299
2300 if ((mtmp->mx == x) && (mtmp->my == y)) return(FALSE);
2301
2302 if (move_other && (othermon = m_at(x, y))) {
2303 if (othermon->wormno)
2304 remove_worm(othermon);
2305 else
2306 remove_monster(x, y);
2307 }
2308
2309 newx = x;
2310 newy = y;
2311
2312 if (!goodpos(newx, newy, mtmp, 0)) {
2313 /* actually we have real problems if enexto ever fails.
2314 * migrating_mons that need to be placed will cause
2315 * no end of trouble.
2316 */
2317 if (!enexto(&mm, newx, newy, mtmp->data)) return(FALSE);
2318 newx = mm.x; newy = mm.y;
2319 }
2320
2321 rloc_to(mtmp, newx, newy);
2322
2323 if (move_other && othermon) {
2324 othermon->mx = othermon->my = 0;
2325 (void) mnearto(othermon, x, y, FALSE);
2326 if ((othermon->mx != x) || (othermon->my != y))
2327 return(TRUE);
2328 }
2329
2330 return(FALSE);
2331 }
2332
2333
2334 static const char *poiseff[] = {
2335
2336 " feel weaker", "r brain is on fire",
2337 "r judgement is impaired", "r muscles won't obey you",
2338 " feel very sick", " break out in hives"
2339 };
2340
2341 void
poisontell(typ)2342 poisontell(typ)
2343
2344 int typ;
2345 {
2346 pline("You%s.", poiseff[typ]);
2347 }
2348
2349 void
poisoned(string,typ,pname,fatal)2350 poisoned(string, typ, pname, fatal)
2351 const char *string, *pname;
2352 int typ, fatal;
2353 {
2354 int i, plural, kprefix = KILLED_BY_AN;
2355 boolean thrown_weapon = (fatal < 0);
2356 int how;
2357
2358 if (thrown_weapon) fatal = -fatal;
2359 if(strcmp(string, "blast") && !thrown_weapon) {
2360 /* 'blast' has already given a 'poison gas' message */
2361 /* so have "poison arrow", "poison dart", etc... */
2362 plural = (string[strlen(string) - 1] == 's')? 1 : 0;
2363 /* avoid "The" Orcus's sting was poisoned... */
2364 pline("%s%s %s poisoned!", isupper(*string) ? "" : "The ",
2365 string, plural ? "were" : "was");
2366 }
2367
2368 if(Poison_resistance) {
2369 if(!strcmp(string, "blast")) shieldeff(u.ux, u.uy);
2370 pline_The("poison doesn't seem to affect you.");
2371 return;
2372 }
2373 /* suppress killer prefix if it already has one */
2374 if ((i = name_to_mon(pname)) >= LOW_PM && mons[i].geno & G_UNIQ) {
2375 kprefix = KILLED_BY;
2376 if (!type_is_pname(&mons[i])) pname = the(pname);
2377 } else if (!strncmpi(pname, "the ", 4) ||
2378 !strncmpi(pname, "an ", 3) ||
2379 !strncmpi(pname, "a ", 2)) {
2380 /*[ does this need a plural check too? ]*/
2381 kprefix = KILLED_BY;
2382 }
2383
2384 how = strstri(pname, "poison") ? DIED : POISONING;
2385 i = rn2(fatal + 20*thrown_weapon);
2386 if(i == 0 && typ != A_CHA) {
2387 /* used to be instantly fatal; now just gongs your maxhp for (3d6)/2
2388 * ...which is probably pretty close to fatal anyway for low-levels */
2389 pline_The("poison was extremely toxic!");
2390 i = d(4,6);
2391 u.uhpmax -= i / 2;
2392 losehp_how(i,pname,kprefix,how);
2393 } else if(i <= 5) {
2394 /* Check that a stat change was made */
2395 if (adjattrib(typ, thrown_weapon ? -1 : -rn1(3,3), 1))
2396 pline("You%s!", poiseff[typ]);
2397 } else {
2398 i = thrown_weapon ? rnd(6) : rn1(10,6);
2399 if(Half_physical_damage) i = (i+1) / 2;
2400 losehp(i, pname, kprefix);
2401 }
2402 if(u.uhp < 1) {
2403 killer_format = kprefix;
2404 killer = pname;
2405 /* "Poisoned by a poisoned ___" is redundant */
2406 done(how);
2407 }
2408 (void) encumber_msg();
2409 }
2410
2411 /* monster responds to player action; not the same as a passive attack */
2412 /* assumes reason for response has been tested, and response _must_ be made */
2413 void
m_respond(mtmp)2414 m_respond(mtmp)
2415 register struct monst *mtmp;
2416 {
2417 if(mtmp->data->msound == MS_SHRIEK) {
2418 if(flags.soundok) {
2419 pline("%s shrieks.", Monnam(mtmp));
2420 stop_occupation();
2421 }
2422 if (!rn2(10)) {
2423 if (!rn2(13))
2424 (void) makemon(&mons[PM_PURPLE_WORM], 0, 0, NO_MM_FLAGS);
2425 else
2426 (void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS);
2427
2428 }
2429 aggravate();
2430 }
2431 if(mtmp->data == &mons[PM_MEDUSA]) {
2432 register int i;
2433 for(i = 0; i < NATTK; i++)
2434 if(mtmp->data->mattk[i].aatyp == AT_GAZE) {
2435 (void) gazemu(mtmp, &mtmp->data->mattk[i]);
2436 break;
2437 }
2438 }
2439 }
2440
2441 void
setmangry(mtmp)2442 setmangry(mtmp)
2443 register struct monst *mtmp;
2444 {
2445 mtmp->mstrategy &= ~STRAT_WAITMASK;
2446 #ifdef BLACKMARKET
2447 /* Even if the black marketeer is already angry he may not have called
2448 * for his assistants if he or his staff have not been assaulted yet.
2449 */
2450 if (is_blkmktstaff(mtmp->data) && !mtmp->mpeaceful)
2451 blkmar_guards(mtmp);
2452 #endif /* BLACKMARKET */
2453 if(!mtmp->mpeaceful) return;
2454 if(mtmp->mtame) return;
2455 mtmp->mpeaceful = 0;
2456 if(mtmp->ispriest) {
2457 if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
2458 else adjalign(2);
2459 } else
2460 adjalign(-1); /* attacking peaceful monsters is bad */
2461 if (couldsee(mtmp->mx, mtmp->my)) {
2462 if (humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
2463 pline("%s gets angry!", Monnam(mtmp));
2464 else if (flags.verbose && flags.soundok) growl(mtmp);
2465 }
2466
2467 #ifdef BLACKMARKET
2468 /* Don't misbehave in the Black Market or else... */
2469 if (Is_blackmarket(&u.uz)) {
2470 if (is_blkmktstaff(mtmp->data) ||
2471 /* non-tame named monsters are presumably
2472 * black marketeer's assistants */
2473 (NAME(mtmp) && *NAME(mtmp))) {
2474 blkmar_guards(mtmp);
2475 }
2476 }
2477 #endif /* BLACKMARKET */
2478
2479 /* attacking your own quest leader will anger his or her guardians */
2480 if (!flags.mon_moving && /* should always be the case here */
2481 mtmp->data == &mons[quest_info(MS_LEADER)]) {
2482 struct monst *mon;
2483 struct permonst *q_guardian = &mons[quest_info(MS_GUARDIAN)];
2484 int got_mad = 0;
2485
2486 /* guardians will sense this attack even if they can't see it */
2487 for (mon = fmon; mon; mon = mon->nmon)
2488 if (!DEADMONSTER(mon) && mon->data == q_guardian && mon->mpeaceful) {
2489 mon->mpeaceful = 0;
2490 if (canseemon(mon)) ++got_mad;
2491 }
2492 if (got_mad && !Hallucination)
2493 pline_The("%s appear%s to be angry too...",
2494 got_mad == 1 ? q_guardian->mname :
2495 makeplural(q_guardian->mname),
2496 got_mad == 1 ? "s" : "");
2497 }
2498 }
2499
2500 void
wakeup(mtmp)2501 wakeup(mtmp)
2502 register struct monst *mtmp;
2503 {
2504 mtmp->msleeping = 0;
2505 mtmp->meating = 0; /* assume there's no salvagable food left */
2506 setmangry(mtmp);
2507 if(mtmp->m_ap_type) seemimic(mtmp);
2508 else if (flags.forcefight && !flags.mon_moving && mtmp->mundetected) {
2509 mtmp->mundetected = 0;
2510 newsym(mtmp->mx, mtmp->my);
2511 }
2512 }
2513
2514 /* Wake up nearby monsters. */
2515 void
wake_nearby()2516 wake_nearby()
2517 {
2518 register struct monst *mtmp;
2519
2520 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2521 if (!DEADMONSTER(mtmp) && distu(mtmp->mx,mtmp->my) < u.ulevel*20) {
2522 mtmp->msleeping = 0;
2523 if (mtmp->mtame && !mtmp->isminion)
2524 EDOG(mtmp)->whistletime = moves;
2525 }
2526 }
2527 }
2528
2529 /* Wake up monsters near some particular location. */
2530 void
wake_nearto(x,y,distance)2531 wake_nearto(x, y, distance)
2532 register int x, y, distance;
2533 {
2534 register struct monst *mtmp;
2535
2536 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2537 if (!DEADMONSTER(mtmp) && mtmp->msleeping && (distance == 0 ||
2538 dist2(mtmp->mx, mtmp->my, x, y) < distance))
2539 mtmp->msleeping = 0;
2540 }
2541 }
2542
2543 /* NOTE: we must check for mimicry before calling this routine */
2544 void
seemimic(mtmp)2545 seemimic(mtmp)
2546 register struct monst *mtmp;
2547 {
2548 unsigned old_app = mtmp->mappearance;
2549 uchar old_ap_type = mtmp->m_ap_type;
2550
2551 mtmp->m_ap_type = M_AP_NOTHING;
2552 mtmp->mappearance = 0;
2553
2554 /*
2555 * Discovered mimics don't block light.
2556 */
2557 if (((old_ap_type == M_AP_FURNITURE &&
2558 (old_app == S_hcdoor || old_app == S_vcdoor)) ||
2559 (old_ap_type == M_AP_OBJECT && old_app == BOULDER)) &&
2560 !does_block(mtmp->mx, mtmp->my, &levl[mtmp->mx][mtmp->my]))
2561 unblock_point(mtmp->mx, mtmp->my);
2562
2563 newsym(mtmp->mx,mtmp->my);
2564 }
2565
2566 /* force all chameleons to become normal */
2567 void
rescham()2568 rescham()
2569 {
2570 register struct monst *mtmp;
2571 int mcham;
2572
2573 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2574 if (DEADMONSTER(mtmp)) continue;
2575 mcham = (int) mtmp->cham;
2576 if (mcham) {
2577 mtmp->cham = CHAM_ORDINARY;
2578 (void) newcham(mtmp, &mons[cham_to_pm[mcham]],
2579 FALSE, FALSE);
2580 }
2581 if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
2582 new_were(mtmp);
2583 if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
2584 seemimic(mtmp);
2585 /* we pretend that the mimic doesn't */
2586 /* know that it has been unmasked. */
2587 mtmp->msleeping = 1;
2588 }
2589 }
2590 }
2591
2592 /* Let the chameleons change again -dgk */
2593 void
restartcham()2594 restartcham()
2595 {
2596 register struct monst *mtmp;
2597
2598 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
2599 if (DEADMONSTER(mtmp)) continue;
2600 mtmp->cham = pm_to_cham(monsndx(mtmp->data));
2601 if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping &&
2602 cansee(mtmp->mx, mtmp->my)) {
2603 set_mimic_sym(mtmp);
2604 newsym(mtmp->mx,mtmp->my);
2605 }
2606 }
2607 }
2608
2609 /* called when restoring a monster from a saved level; protection
2610 against shape-changing might be different now than it was at the
2611 time the level was saved. */
2612 void
restore_cham(mon)2613 restore_cham(mon)
2614 struct monst *mon;
2615 {
2616 int mcham;
2617
2618 if (Protection_from_shape_changers) {
2619 mcham = (int) mon->cham;
2620 if (mcham) {
2621 mon->cham = CHAM_ORDINARY;
2622 (void) newcham(mon, &mons[cham_to_pm[mcham]], FALSE, FALSE);
2623 } else if (is_were(mon->data) && !is_human(mon->data)) {
2624 new_were(mon);
2625 }
2626 } else if (mon->cham == CHAM_ORDINARY) {
2627 mon->cham = pm_to_cham(monsndx(mon->data));
2628 }
2629 }
2630
2631 /* unwatched hiders may hide again; if so, a 1 is returned. */
2632 STATIC_OVL boolean
restrap(mtmp)2633 restrap(mtmp)
2634 register struct monst *mtmp;
2635 {
2636 if(mtmp->cham || mtmp->mcan || mtmp->m_ap_type ||
2637 cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck) ||
2638 (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
2639 return(FALSE);
2640
2641 if(mtmp->data->mlet == S_MIMIC) {
2642 set_mimic_sym(mtmp);
2643 return(TRUE);
2644 } else
2645 if(levl[mtmp->mx][mtmp->my].typ == ROOM) {
2646 mtmp->mundetected = 1;
2647 return(TRUE);
2648 }
2649
2650 return(FALSE);
2651 }
2652
2653 short *animal_list = 0; /* list of PM values for animal monsters */
2654 int animal_list_count;
2655
2656 void
mon_animal_list(construct)2657 mon_animal_list(construct)
2658 boolean construct;
2659 {
2660 if (construct) {
2661 short animal_temp[SPECIAL_PM];
2662 int i, n;
2663
2664 /* if (animal_list) impossible("animal_list already exists"); */
2665
2666 for (n = 0, i = LOW_PM; i < SPECIAL_PM; i++)
2667 if (is_animal(&mons[i])) animal_temp[n++] = i;
2668 /* if (n == 0) animal_temp[n++] = NON_PM; */
2669
2670 animal_list = (short *)alloc(n * sizeof *animal_list);
2671 (void) memcpy((genericptr_t)animal_list,
2672 (genericptr_t)animal_temp,
2673 n * sizeof *animal_list);
2674 animal_list_count = n;
2675 } else { /* release */
2676 if (animal_list) free((genericptr_t)animal_list), animal_list = 0;
2677 animal_list_count = 0;
2678 }
2679 }
2680
2681 STATIC_OVL int
pick_animal()2682 pick_animal()
2683 {
2684 if (!animal_list) mon_animal_list(TRUE);
2685
2686 return animal_list[rn2(animal_list_count)];
2687 }
2688
2689 int
select_newcham_form(mon)2690 select_newcham_form(mon)
2691 struct monst *mon;
2692 {
2693 int mndx = NON_PM;
2694
2695 switch (mon->cham) {
2696 case CHAM_SANDESTIN:
2697 if (rn2(7)) mndx = pick_nasty();
2698 break;
2699 case CHAM_DOPPELGANGER:
2700 if (!rn2(7)) mndx = pick_nasty();
2701 else if (rn2(3)) mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1,
2702 PM_ARCHEOLOGIST);
2703 break;
2704 case CHAM_CHAMELEON:
2705 if (!rn2(3)) mndx = pick_animal();
2706 break;
2707 case CHAM_ORDINARY:
2708 {
2709 struct obj *m_armr = which_armor(mon, W_ARM);
2710
2711 if (m_armr && Is_dragon_scales(m_armr->otyp))
2712 mndx = Dragon_scales_to_pm(m_armr) - mons;
2713 else if (m_armr && Is_dragon_mail(m_armr->otyp))
2714 mndx = Dragon_mail_to_pm(m_armr) - mons;
2715 }
2716 break;
2717 }
2718 #ifdef WIZARD
2719 /* For debugging only: allow control of polymorphed monster; not saved */
2720 if (wizard && iflags.mon_polycontrol) {
2721 char pprompt[BUFSZ], buf[BUFSZ];
2722 int tries = 0;
2723 do {
2724 Sprintf(pprompt,
2725 "Change %s into what kind of monster? [type the name]",
2726 mon_nam(mon));
2727 getlin(pprompt,buf);
2728 mndx = name_to_mon(buf);
2729 if (mndx < LOW_PM)
2730 You("cannot polymorph %s into that.", mon_nam(mon));
2731 else break;
2732 } while(++tries < 5);
2733 if (tries==5) pline("%s", thats_enough_tries);
2734 }
2735 #endif /*WIZARD*/
2736 if (mndx == NON_PM) mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
2737 return mndx;
2738 }
2739
2740 /* make a chameleon look like a new monster; returns 1 if it actually changed */
2741 int
newcham(mtmp,mdat,polyspot,msg)2742 newcham(mtmp, mdat, polyspot, msg)
2743 struct monst *mtmp;
2744 struct permonst *mdat;
2745 boolean polyspot; /* change is the result of wand or spell of polymorph */
2746 boolean msg; /* "The oldmon turns into a newmon!" */
2747 {
2748 int mhp, hpn, hpd;
2749 int mndx, tryct;
2750 struct permonst *olddata = mtmp->data;
2751 char oldname[BUFSZ];
2752
2753 if (msg) {
2754 /* like Monnam() but never mention saddle */
2755 Strcpy(oldname, x_monnam(mtmp, ARTICLE_THE, (char *)0,
2756 SUPPRESS_SADDLE, FALSE));
2757 oldname[0] = highc(oldname[0]);
2758 }
2759
2760 /* mdat = 0 -> caller wants a random monster shape */
2761 tryct = 0;
2762 if (mdat == 0) {
2763 while (++tryct <= 100) {
2764 mndx = select_newcham_form(mtmp);
2765 mdat = &mons[mndx];
2766 if ((mvitals[mndx].mvflags & G_GENOD) != 0 ||
2767 is_placeholder(mdat)) continue;
2768 /* polyok rules out all M2_PNAME and M2_WERE's;
2769 select_newcham_form might deliberately pick a player
2770 character type, so we can't arbitrarily rule out all
2771 human forms any more */
2772 if (is_mplayer(mdat) || (!is_human(mdat) && polyok(mdat)))
2773 break;
2774 }
2775 if (tryct > 100) return 0; /* Should never happen */
2776 } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
2777 return(0); /* passed in mdat is genocided */
2778
2779 if(is_male(mdat)) {
2780 if(mtmp->female) mtmp->female = FALSE;
2781 } else if (is_female(mdat)) {
2782 if(!mtmp->female) mtmp->female = TRUE;
2783 } else if (!is_neuter(mdat)) {
2784 if(!rn2(10)) mtmp->female = !mtmp->female;
2785 }
2786
2787 if (In_endgame(&u.uz) && is_mplayer(olddata)) {
2788 /* mplayers start out as "Foo the Bar", but some of the
2789 * titles are inappropriate when polymorphed, particularly
2790 * into the opposite sex. players don't use ranks when
2791 * polymorphed, so dropping the rank for mplayers seems
2792 * reasonable.
2793 */
2794 char *p = index(NAME(mtmp), ' ');
2795 if (p) {
2796 *p = '\0';
2797 mtmp->mnamelth = p - NAME(mtmp) + 1;
2798 }
2799 }
2800
2801 if(mdat == mtmp->data) return(0); /* still the same monster */
2802
2803 if(mtmp->wormno) { /* throw tail away */
2804 wormgone(mtmp);
2805 place_monster(mtmp, mtmp->mx, mtmp->my);
2806 }
2807
2808 hpn = mtmp->mhp;
2809 hpd = (mtmp->m_lev < 50) ? ((int)mtmp->m_lev)*8 : mdat->mlevel;
2810 if(!hpd) hpd = 4;
2811
2812 mtmp->m_lev = adj_lev(mdat); /* new monster level */
2813
2814 mhp = (mtmp->m_lev < 50) ? ((int)mtmp->m_lev)*8 : mdat->mlevel;
2815 if(!mhp) mhp = 4;
2816
2817 /* new hp: same fraction of max as before */
2818 #ifndef LINT
2819 mtmp->mhp = (int)(((long)hpn*(long)mhp)/(long)hpd);
2820 #endif
2821 if(mtmp->mhp < 0) mtmp->mhp = hpn; /* overflow */
2822 /* Unlikely but not impossible; a 1HD creature with 1HP that changes into a
2823 0HD creature will require this statement */
2824 if (!mtmp->mhp) mtmp->mhp = 1;
2825
2826 /* and the same for maximum hit points */
2827 hpn = mtmp->mhpmax;
2828 #ifndef LINT
2829 mtmp->mhpmax = (int)(((long)hpn*(long)mhp)/(long)hpd);
2830 #endif
2831 if(mtmp->mhpmax < 0) mtmp->mhpmax = hpn; /* overflow */
2832 if (!mtmp->mhpmax) mtmp->mhpmax = 1;
2833
2834 /* take on the new form... */
2835 set_mon_data(mtmp, mdat, 0);
2836
2837 if (emits_light(olddata) != emits_light(mtmp->data)) {
2838 /* used to give light, now doesn't, or vice versa,
2839 or light's range has changed */
2840 if (emits_light(olddata))
2841 del_light_source(LS_MONSTER, (genericptr_t)mtmp);
2842 if (emits_light(mtmp->data))
2843 new_light_source(mtmp->mx, mtmp->my, emits_light(mtmp->data),
2844 LS_MONSTER, (genericptr_t)mtmp);
2845 }
2846 if (!mtmp->perminvis || pm_invisible(olddata))
2847 mtmp->perminvis = pm_invisible(mdat);
2848 mtmp->minvis = mtmp->invis_blkd ? 0 : mtmp->perminvis;
2849 if (!(hides_under(mdat) && OBJ_AT(mtmp->mx, mtmp->my)) &&
2850 !(mdat->mlet == S_EEL && is_pool(mtmp->mx, mtmp->my)))
2851 mtmp->mundetected = 0;
2852 if (u.ustuck == mtmp) {
2853 if(u.uswallow) {
2854 if(!attacktype(mdat,AT_ENGL)) {
2855 /* Does mdat care? */
2856 if (!noncorporeal(mdat) && !amorphous(mdat) &&
2857 !is_whirly(mdat) &&
2858 (mdat != &mons[PM_YELLOW_LIGHT])) {
2859 You("break out of %s%s!", mon_nam(mtmp),
2860 (is_animal(mdat)?
2861 "'s stomach" : ""));
2862 mtmp->mhp = 1; /* almost dead */
2863 }
2864 expels(mtmp, olddata, FALSE);
2865 } else {
2866 /* update swallow glyphs for new monster */
2867 swallowed(0);
2868 }
2869 } else if (!sticks(mdat) && !sticks(youmonst.data))
2870 unstuck(mtmp);
2871 }
2872
2873 #ifndef DCC30_BUG
2874 if (mdat == &mons[PM_LONG_WORM] && (mtmp->wormno = get_wormno()) != 0) {
2875 #else
2876 /* DICE 3.0 doesn't like assigning and comparing mtmp->wormno in the
2877 * same expression.
2878 */
2879 if (mdat == &mons[PM_LONG_WORM] &&
2880 (mtmp->wormno = get_wormno(), mtmp->wormno != 0)) {
2881 #endif
2882 /* we can now create worms with tails - 11/91 */
2883 initworm(mtmp, rn2(5));
2884 if (count_wsegs(mtmp))
2885 place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my);
2886 }
2887
2888 newsym(mtmp->mx,mtmp->my);
2889
2890 if (msg) {
2891 uchar save_mnamelth = mtmp->mnamelth;
2892 mtmp->mnamelth = 0;
2893 pline("%s turns into %s!", oldname,
2894 mdat == &mons[PM_GREEN_SLIME] ? "slime" :
2895 x_monnam(mtmp, ARTICLE_A, (char*)0, SUPPRESS_SADDLE, FALSE));
2896 mtmp->mnamelth = save_mnamelth;
2897 }
2898
2899 possibly_unwield(mtmp, polyspot); /* might lose use of weapon */
2900 mon_break_armor(mtmp, polyspot);
2901 if (!(mtmp->misc_worn_check & W_ARMG))
2902 mselftouch(mtmp, "No longer petrify-resistant, ",
2903 !flags.mon_moving);
2904 m_dowear(mtmp, FALSE);
2905
2906 /* This ought to re-test can_carry() on each item in the inventory
2907 * rather than just checking ex-giants & boulders, but that'd be
2908 * pretty expensive to perform. If implemented, then perhaps
2909 * minvent should be sorted in order to drop heaviest items first.
2910 */
2911 /* former giants can't continue carrying boulders */
2912 if (mtmp->minvent && !throws_rocks(mdat)) {
2913 register struct obj *otmp, *otmp2;
2914
2915 for (otmp = mtmp->minvent; otmp; otmp = otmp2) {
2916 otmp2 = otmp->nobj;
2917 if (otmp->otyp == BOULDER) {
2918 /* this keeps otmp from being polymorphed in the
2919 same zap that the monster that held it is polymorphed */
2920 if (polyspot) bypass_obj(otmp);
2921 obj_extract_self(otmp);
2922 /* probably ought to give some "drop" message here */
2923 if (flooreffects(otmp, mtmp->mx, mtmp->my, "")) continue;
2924 place_object(otmp, mtmp->mx, mtmp->my);
2925 }
2926 }
2927 }
2928
2929 return(1);
2930 }
2931
2932 /* sometimes an egg will be special */
2933 #define BREEDER_EGG (!rn2(77))
2934
2935 /*
2936 * Determine if the given monster number can be hatched from an egg.
2937 * Return the monster number to use as the egg's corpsenm. Return
2938 * NON_PM if the given monster can't be hatched.
2939 */
2940 int
can_be_hatched(mnum)2941 can_be_hatched(mnum)
2942 int mnum;
2943 {
2944 /* ranger quest nemesis has the oviparous bit set, making it
2945 be possible to wish for eggs of that unique monster; turn
2946 such into ordinary eggs rather than forbidding them outright */
2947 if (mnum == PM_SCORPIUS) mnum = PM_SCORPION;
2948
2949 mnum = little_to_big(mnum);
2950 /*
2951 * Queen bees lay killer bee eggs (usually), but killer bees don't
2952 * grow into queen bees. Ditto for [winged-]gargoyles.
2953 */
2954 if (mnum == PM_KILLER_BEE || mnum == PM_GARGOYLE ||
2955 (lays_eggs(&mons[mnum]) && (BREEDER_EGG ||
2956 (mnum != PM_QUEEN_BEE && mnum != PM_WINGED_GARGOYLE))))
2957 return mnum;
2958 return NON_PM;
2959 }
2960
2961 /* type of egg laid by #sit; usually matches parent */
2962 int
egg_type_from_parent(mnum,force_ordinary)2963 egg_type_from_parent(mnum, force_ordinary)
2964 int mnum; /* parent monster; caller must handle lays_eggs() check */
2965 boolean force_ordinary;
2966 {
2967 if (force_ordinary || !BREEDER_EGG) {
2968 if (mnum == PM_QUEEN_BEE) mnum = PM_KILLER_BEE;
2969 else if (mnum == PM_WINGED_GARGOYLE) mnum = PM_GARGOYLE;
2970 }
2971 return mnum;
2972 }
2973
2974 /* decide whether an egg of the indicated monster type is viable; */
2975 /* also used to determine whether an egg or tin can be created... */
2976 boolean
dead_species(m_idx,egg)2977 dead_species(m_idx, egg)
2978 int m_idx;
2979 boolean egg;
2980 {
2981 /*
2982 * For monsters with both baby and adult forms, genociding either
2983 * form kills all eggs of that monster. Monsters with more than
2984 * two forms (small->large->giant mimics) are more or less ignored;
2985 * fortunately, none of them have eggs. Species extinction due to
2986 * overpopulation does not kill eggs.
2987 */
2988 return (boolean)
2989 (m_idx >= LOW_PM &&
2990 ((mvitals[m_idx].mvflags & G_GENOD) != 0 ||
2991 (egg &&
2992 (mvitals[big_to_little(m_idx)].mvflags & G_GENOD) != 0)));
2993 }
2994
2995 /* kill off any eggs of genocided monsters */
2996 STATIC_OVL void
kill_eggs(obj_list)2997 kill_eggs(obj_list)
2998 struct obj *obj_list;
2999 {
3000 struct obj *otmp;
3001
3002 for (otmp = obj_list; otmp; otmp = otmp->nobj)
3003 if (otmp->otyp == EGG) {
3004 if (dead_species(otmp->corpsenm, TRUE)) {
3005 /*
3006 * It seems we could also just catch this when
3007 * it attempted to hatch, so we wouldn't have to
3008 * search all of the objlists.. or stop all
3009 * hatch timers based on a corpsenm.
3010 */
3011 kill_egg(otmp);
3012 }
3013 #if 0 /* not used */
3014 } else if (otmp->otyp == TIN) {
3015 if (dead_species(otmp->corpsenm, FALSE))
3016 otmp->corpsenm = NON_PM; /* empty tin */
3017 } else if (otmp->otyp == CORPSE) {
3018 if (dead_species(otmp->corpsenm, FALSE))
3019 ; /* not yet implemented... */
3020 #endif
3021 } else if (Has_contents(otmp)) {
3022 kill_eggs(otmp->cobj);
3023 }
3024 }
3025
3026 /** kill all members of genocided species */
3027 void
kill_genocided_monsters()3028 kill_genocided_monsters()
3029 {
3030 struct monst *mtmp, *mtmp2;
3031 boolean kill_cham[CHAM_MAX_INDX+1];
3032 int mndx;
3033
3034 kill_cham[CHAM_ORDINARY] = FALSE; /* (this is mndx==0) */
3035 for (mndx = 1; mndx <= CHAM_MAX_INDX; mndx++)
3036 kill_cham[mndx] = (mvitals[cham_to_pm[mndx]].mvflags & G_GENOD) != 0;
3037 /*
3038 * Called during genocide, and again upon level change. The latter
3039 * catches up with any migrating monsters as they finally arrive at
3040 * their intended destinations, so possessions get deposited there.
3041 *
3042 * Chameleon handling:
3043 * 1) if chameleons have been genocided, destroy them
3044 * regardless of current form;
3045 * 2) otherwise, force every chameleon which is imitating
3046 * any genocided species to take on a new form.
3047 */
3048 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
3049 mtmp2 = mtmp->nmon;
3050 if (DEADMONSTER(mtmp)) continue;
3051 mndx = monsndx(mtmp->data);
3052 if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham[mtmp->cham]) {
3053 if (mtmp->cham && !kill_cham[mtmp->cham])
3054 (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
3055 else
3056 mondead(mtmp);
3057 }
3058 if (mtmp->minvent) kill_eggs(mtmp->minvent);
3059 }
3060
3061 kill_eggs(invent);
3062 kill_eggs(fobj);
3063 kill_eggs(level.buriedobjlist);
3064 }
3065
3066 /**
3067 * Kills every member of the specified monster species on the current
3068 * level.
3069 */
3070 void
kill_monster_on_level(mndx)3071 kill_monster_on_level(mndx)
3072 int mndx; /**< Monster index number */
3073 {
3074 struct monst *mtmp;
3075 struct monst *mtmp2;
3076 int tmp_mndx;
3077
3078 for (mtmp = fmon; mtmp; mtmp = mtmp2) {
3079 mtmp2 = mtmp->nmon;
3080 if (DEADMONSTER(mtmp)) continue;
3081 tmp_mndx = monsndx(mtmp->data);
3082 if (mndx == tmp_mndx) {
3083 mondead(mtmp);
3084 }
3085 }
3086 }
3087
3088 void
golemeffects(mon,damtype,dam)3089 golemeffects(mon, damtype, dam)
3090 register struct monst *mon;
3091 int damtype, dam;
3092 {
3093 int heal = 0, slow = 0;
3094
3095 if (mon->data == &mons[PM_FLESH_GOLEM]) {
3096 if (damtype == AD_ELEC) heal = dam / 6;
3097 else if (damtype == AD_FIRE || damtype == AD_COLD) slow = 1;
3098 } else if (mon->data == &mons[PM_IRON_GOLEM]) {
3099 if (damtype == AD_ELEC) slow = 1;
3100 else if (damtype == AD_FIRE) heal = dam;
3101 } else {
3102 return;
3103 }
3104 if (slow) {
3105 if (mon->mspeed != MSLOW)
3106 mon_adjust_speed(mon, -1, (struct obj *)0);
3107 }
3108 if (heal) {
3109 if (mon->mhp < mon->mhpmax) {
3110 mon->mhp += dam;
3111 if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
3112 if (cansee(mon->mx, mon->my))
3113 pline("%s seems healthier.", Monnam(mon));
3114 }
3115 }
3116 }
3117
3118 boolean
angry_guards(silent)3119 angry_guards(silent)
3120 register boolean silent;
3121 {
3122 register struct monst *mtmp;
3123 register int ct = 0, nct = 0, sct = 0, slct = 0;
3124
3125 for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
3126 if (DEADMONSTER(mtmp)) continue;
3127 if((mtmp->data == &mons[PM_WATCHMAN] ||
3128 mtmp->data == &mons[PM_WATCH_CAPTAIN])
3129 && mtmp->mpeaceful) {
3130 ct++;
3131 if(cansee(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
3132 if (distu(mtmp->mx, mtmp->my) == 2) nct++;
3133 else sct++;
3134 }
3135 if (mtmp->msleeping || mtmp->mfrozen) {
3136 slct++;
3137 mtmp->msleeping = mtmp->mfrozen = 0;
3138 }
3139 mtmp->mpeaceful = 0;
3140 }
3141 }
3142 if(ct) {
3143 if(!silent) { /* do we want pline msgs? */
3144 if(slct) pline_The("guard%s wake%s up!",
3145 slct > 1 ? "s" : "", slct == 1 ? "s" : "");
3146 if(nct || sct) {
3147 if(nct) pline_The("guard%s get%s angry!",
3148 nct == 1 ? "" : "s", nct == 1 ? "s" : "");
3149 else if(!Blind)
3150 You("see %sangry guard%s approaching!",
3151 sct == 1 ? "an " : "", sct > 1 ? "s" : "");
3152 } else if(flags.soundok)
3153 You_hear("the shrill sound of a guard's whistle.");
3154 }
3155 return(TRUE);
3156 }
3157 return(FALSE);
3158 }
3159
3160 void
pacify_guards()3161 pacify_guards()
3162 {
3163 register struct monst *mtmp;
3164
3165 for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
3166 if (DEADMONSTER(mtmp)) continue;
3167 if (mtmp->data == &mons[PM_WATCHMAN] ||
3168 mtmp->data == &mons[PM_WATCH_CAPTAIN])
3169 mtmp->mpeaceful = 1;
3170 }
3171 }
3172
3173 void
mimic_hit_msg(mtmp,otyp)3174 mimic_hit_msg(mtmp, otyp)
3175 struct monst *mtmp;
3176 short otyp;
3177 {
3178 short ap = mtmp->mappearance;
3179
3180 switch(mtmp->m_ap_type) {
3181 case M_AP_NOTHING:
3182 case M_AP_FURNITURE:
3183 case M_AP_MONSTER:
3184 break;
3185 case M_AP_OBJECT:
3186 if (otyp == SPE_HEALING || otyp == SPE_EXTRA_HEALING) {
3187 pline("%s seems a more vivid %s than before.",
3188 The(simple_typename(ap)),
3189 c_obj_colors[objects[ap].oc_color]);
3190 }
3191 break;
3192 }
3193 }
3194
3195 /*mon.c*/
3196