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