This is mhitu.c in view mode; [Download] [Up]
/* SCCS Id: @(#)mhitu.c 3.0 89/11/27 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" #ifdef NAMED_ITEMS # include "artifact.h" #endif VSTATIC struct obj *otmp; #ifdef POLYSELF OSTATIC void FDECL(urustm, (struct monst *, struct obj *)); static int FDECL(passiveum, (struct permonst *,struct monst *,struct attack *)); #endif #ifdef SEDUCE static void FDECL(mayberem, (struct obj *, const char *)); #endif OSTATIC int FDECL(hitmu, (struct monst *,struct attack *)); OSTATIC int FDECL(gulpmu, (struct monst *,struct attack *)); OSTATIC int FDECL(explmu, (struct monst *,struct attack *)); OSTATIC int FDECL(gazemu, (struct monst *,struct attack *)); static void FDECL(hitmsg,(struct monst *,struct attack *)); OSTATIC void FDECL(missmu,(struct monst *,BOOLEAN_P,struct attack *)); OSTATIC void FDECL(mswings,(struct monst *,struct obj *)); OSTATIC void FDECL(wildmiss,(struct monst *)); OSTATIC void FDECL(hurtarmor,(struct permonst *,int)); #ifdef OVL1 static void hitmsg(mtmp, mattk) register struct monst *mtmp; register struct attack *mattk; { int compat; /* Note: if opposite gender, "seductively" */ /* If same gender, "engagingly" for nymph, normal msg for others */ if((compat = could_seduce(mtmp, &youmonst, mattk)) && !mtmp->mcan && !mtmp->mspec_used) { kludge("%s %s you %s.", Monnam(mtmp), Blind ? "talks to" : "smiles at", compat == 2 ? "engagingly" : "seductively"); } else switch (mattk->aatyp) { case AT_BITE: kludge("%s bites!", Monnam(mtmp)); break; case AT_KICK: #ifdef POLYSELF kludge("%s kicks%c", Monnam(mtmp), thick_skinned(uasmon) ? '.' : '!'); #else kludge("%s kicks!", Monnam(mtmp)); #endif break; case AT_STNG: kludge("%s stings!", Monnam(mtmp)); break; case AT_BUTT: kludge("%s butts!", Monnam(mtmp)); break; case AT_TUCH: kludge("%s touches you!", Monnam(mtmp)); break; default: kludge("%s hits!", Monnam(mtmp)); } } #endif /* OVL1 */ #ifdef OVLB XSTATIC void missmu(mtmp, nearmiss, mattk) /* monster missed you */ register struct monst *mtmp; register boolean nearmiss; register struct attack *mattk; { if(could_seduce(mtmp, &youmonst, mattk) && !mtmp->mcan) kludge("%s pretends to be friendly.", Monnam(mtmp)); else { if (!flags.verbose || !nearmiss) kludge("%s misses.", Monnam(mtmp)); else kludge("%s just misses!", Monnam(mtmp)); } } XSTATIC void mswings(mtmp, otemp) /* monster swings obj */ register struct monst *mtmp; register struct obj *otemp; { if (!flags.verbose || Blind || otemp->olet != WEAPON_SYM) return; pline("%s %s %s %s.", Monnam(mtmp), ((otemp->otyp >= SPEAR && otemp->otyp <= LANCE) || (otemp->otyp >= PARTISAN && otemp->otyp <= SPETUM) || otemp->otyp == TRIDENT) ? "thrusts" : "swings", is_female(mtmp) ? "her" : is_human(mtmp->data) ? "his" : "its", xname(otemp)); } XSTATIC void wildmiss(mtmp) /* monster attacked your displaced image */ register struct monst *mtmp; { int compat; if (!flags.verbose) return; if (!cansee(mtmp->mx, mtmp->my)) return; /* maybe it's attacking an image around the corner? */ compat = could_seduce(mtmp, &youmonst, (struct attack *)0); /* we really want to have the attack here to pass -- * the previous code checked whether mtmp was a nymph, * which was not correct either since the attack type of * succubi/incubi varies with SEDUCE */ if(Invis && !perceives(mtmp->data)) { if(compat) kludge("%s tries to touch you and misses!", Monnam(mtmp)); else switch(rn2(3)) { case 0: kludge("%s swings wildly and misses!", Monnam(mtmp)); break; case 1: kludge("%s attacks a spot beside you.", Monnam(mtmp)); break; case 2: kludge("%s strikes at thin air!", Monnam(mtmp)); break; default:kludge("%s swings wildly!", Monnam(mtmp)); break; } } else if(Displaced) { if(compat) kludge("%s smiles %s at your %sdisplaced image...", Monnam(mtmp), compat == 2 ? "engagingly" : "seductively", Invis ? "invisible " : ""); else kludge("%s strikes at your %sdisplaced image and misses you!", /* Note: if you're both invisible and displaced, * only monsters which see invisible will attack your * displaced image, since the displaced image is also * invisible. */ Monnam(mtmp), Invis ? "invisible " : ""); } else impossible("%s attacks you without knowing your location?", Monnam(mtmp)); } void expels(mtmp, mdat, message) register struct monst *mtmp; register struct permonst *mdat; /* if mtmp is polymorphed, mdat != mtmp->data */ boolean message; { if (message) if (is_animal(mdat)) You("get regurgitated!"); else { char blast[40]; register int i; blast[0] = '\0'; for(i = 0; i < NATTK; i++) if(mdat->mattk[i].aatyp == AT_ENGL) break; if (mdat->mattk[i].aatyp != AT_ENGL) impossible("Swallower has no engulfing attack?"); else { if (is_whirly(mdat)) { switch (mdat->mattk[i].adtyp) { case AD_ELEC: Strcpy(blast, " in a shower of sparks"); break; case AD_COLD: Strcpy(blast, " in a blast of frost"); break; } } else Strcpy(blast, " with a squelch"); You("get expelled from %s%s!", mon_nam(mtmp), blast); } } unstuck(mtmp); mnexto(mtmp); prme(); spoteffects(); /* to cover for a case where mtmp is not in a next square */ if(um_dist(mtmp->mx,mtmp->my,1)) pline("Brrooaa... You land hard at some distance."); } #endif /* OVLB */ #ifdef OVL0 /* * mattacku: monster attacks you * returns 1 if monster dies (e.g. "yellow light"), 0 otherwise * Note: if you're displaced or invisible the monster might attack the * wrong position... * Assumption: it's attacking you or an empty square; if there's another * monster which it attacks by mistake, the caller had better * take care of it... */ int mattacku(mtmp) register struct monst *mtmp; { struct attack *mattk; int i, j, tmp, sum[NATTK]; struct permonst *mdat = mtmp->data; boolean ranged = (dist(mtmp->mx, mtmp->my) > 3); /* Is it near you? Affects your actions */ boolean range2 = !monnear(mtmp, mtmp->mux, mtmp->muy); /* Does it think it's near you? Affects its actions */ boolean foundyou = (mtmp->mux==u.ux && mtmp->muy==u.uy); /* Is it attacking you or your image? */ boolean youseeit = (cansee(mtmp->mx, mtmp->my)); /* Necessary since if it's attacking your image around a * corner, you might not see it */ if(!ranged) nomul(0); if(mtmp->mhp <= 0) return(0); /* If swallowed, can only be affected by u.ustuck */ if(u.uswallow) { if(mtmp != u.ustuck) return(0); u.ustuck->mux = u.ux; u.ustuck->muy = u.uy; range2 = 0; foundyou = 1; /* This is not impossible! */ /* If the swallowing monster changes into a monster * that is not capable of swallowing you, you get * regurgitated - dgk * * This code is obsolete: newcham() will handle this contingency * as soon as it occurs in the course of a round. - kcd * * for(i = 0; i < NATTK; i++) * if(mdat->mattk[i].aatyp == AT_ENGL) goto doattack; * * You("get regurgitated!"); * regurgitates(mtmp); * return(0); */ } /* doattack: use commented out above */ #ifdef POLYSELF if (u.uundetected && !range2 && foundyou && !u.uswallow) { u.uundetected = 0; if (u.usym == S_PIERCER) { coord cc; /* maybe we need a unexto() function? */ unpmon(mtmp); remove_monster(mtmp->mx, mtmp->my); place_monster(mtmp, u.ux, u.uy); pmon(mtmp); enexto(&cc, u.ux, u.uy, &playermon); teleds(cc.x, cc.y); You("fall from the ceiling!"); if (is_mercenary(mtmp->data) && m_carrying(mtmp,HELMET)) { kludge("Your blow glances off %s's helmet.", mon_nam(mtmp)); } else { if (3 + mtmp->data->ac <= rnd(20)) { kludge("%s is hit by a falling piercer (you)!", Monnam(mtmp)); if ((mtmp->mhp -= d(3,6)) < 1) killed(mtmp); } else kludge("%s is almost hit by a falling piercer (you)!", Monnam(mtmp)); } } else { if (Blind) pline("It tries to move where you are hiding."); else pline("Wait, %s! There's a %s named %s hiding under %s!", mtmp->mnamelth ? NAME(mtmp) : mtmp->data->mname, uasmon->mname, plname, OBJ_AT(u.ux,u.uy) ? doname(level.objects[u.ux][u.uy]) : "some gold"); prme(); } return(0); } if (u.usym == S_MIMIC_DEF && !range2 && foundyou && !u.uswallow) { if (Blind) pline("It gets stuck on you."); else pline("Wait, %s! That's a %s named %s!", mtmp->mnamelth ? NAME(mtmp) : mtmp->data->mname, uasmon->mname, plname); u.ustuck = mtmp; u.usym = S_MIMIC; prme(); return(0); } #endif /* Work out the armor class differential */ tmp = u.uac + 10; /* tmp ~= 0 - 20 */ /* give people with Ac < -9 at least some vulnerability */ /* negative AC gives an actual AC of somewhere from -1 to the AC */ if (tmp < 10) tmp = 10 - rnd(10-tmp); tmp += mtmp->m_lev; if(multi < 0) tmp += 4; if((Invis && !perceives(mdat)) || !mtmp->mcansee) tmp -= 2; if(mtmp->mtrapped) tmp -= 2; if(tmp <= 0) tmp = 1; /* make eels visible the moment they hit/miss us */ if(mdat->mlet == S_EEL && mtmp->minvis && cansee(mtmp->mx,mtmp->my)) { mtmp->minvis = 0; pmon(mtmp); } /* Special demon handling code */ if(!mtmp->cham && is_demon(mdat) && !range2 #ifdef INFERNO && mtmp->data != &mons[PM_BALROG] && mtmp->data != &mons[PM_SUCCUBUS] && mtmp->data != &mons[PM_INCUBUS] #endif ) if(!mtmp->mcan && !rn2(13)) dsummon(mdat); /* Special lycanthrope handling code */ if(!mtmp->cham && is_were(mdat) && !range2) { if(is_human(mdat)) { if(!rn2(5 - (night() * 2)) && !mtmp->mcan) new_were(mtmp); } else if(!rn2(30) && !mtmp->mcan) new_were(mtmp); if(!rn2(10) && !mtmp->mcan) { if(!Blind) { pline("%s summons help!",youseeit ? Monnam(mtmp) : "It"); } else You("feel hemmed in."); /* Technically wrong; we really should check if you can see the * help, but close enough... */ if (!were_summon(mdat,FALSE) && !Blind) pline("But none comes."); } } for(i = 0; i < NATTK; i++) { sum[i] = 0; mattk = &(mdat->mattk[i]); if (u.uswallow && (mattk->aatyp != AT_ENGL)) continue; switch(mattk->aatyp) { case AT_CLAW: /* "hand to hand" attacks */ case AT_KICK: case AT_BITE: case AT_STNG: case AT_TUCH: case AT_BUTT: if(!range2) { if (foundyou) { if(tmp > (j = rnd(20+i))) { #ifdef POLYSELF if (mattk->aatyp != AT_KICK || !thick_skinned(uasmon)) #endif sum[i] = hitmu(mtmp, mattk); } else missmu(mtmp, (tmp == j), mattk); } else wildmiss(mtmp); } break; case AT_HUGS: /* automatic if prev two attacks succeed */ /* Note: if displaced, prev attacks never succeeded */ if((!range2 && i>=2 && sum[i-1] && sum[i-2]) || mtmp == u.ustuck) sum[i]= hitmu(mtmp, mattk); break; case AT_GAZE: /* can affect you either ranged or not */ if (youseeit) /* not displaced around a corner so not visible */ sum[i] = gazemu(mtmp, mattk); break; case AT_EXPL: /* automatic hit if next to, and aimed at you */ if(!range2) { if (foundyou) sum[i] = explmu(mtmp, mattk); else { if (!mtmp->mcan) { pline("%s explodes at a spot in thin air!", youseeit ? Monnam(mtmp) : "It"); mondead(mtmp); sum[i] = 2; } } } break; case AT_ENGL: if (!range2) { if(foundyou) { if(u.uswallow || tmp > (j = rnd(20+i))) { /* Force swallowing monster to be * displayed even when player is * moving away */ nscr(); sum[i] = gulpmu(mtmp, mattk); } else { missmu(mtmp, (tmp == j), mattk); } } else if (is_animal(mtmp->data)) pline("%s gulps some air!", youseeit ? Monnam(mtmp) : "It"); else if (youseeit) pline("%s lunges forward and recoils!", Monnam(mtmp)); else You("hear a %s nearby.", is_whirly(mtmp->data)? "rushing noise" : "\"splat!\""); } break; case AT_BREA: if(range2) sum[i] = breamu(mtmp, mattk); /* Note: breamu takes care of displacement */ break; case AT_SPIT: if(range2) sum[i] = spitmu(mtmp, mattk); /* Note: spitmu takes care of displacement */ break; case AT_WEAP: if(range2) { #ifdef REINCARNATION if (dlevel != rogue_level) #endif sum[i] = thrwmu(mtmp); } else if (foundyou) { set_uasmon(); otmp = select_hwep(mtmp); if(otmp) { tmp += hitval(otmp, uasmon); mswings(mtmp, otmp); } if(tmp > (j = rnd(20+i))) sum[i] = hitmu(mtmp, mattk); else missmu(mtmp, (tmp == j), mattk); } else wildmiss(mtmp); break; case AT_MAGC: if (range2) sum[i] = buzzmu(mtmp, mattk); else if (foundyou) sum[i] = castmu(mtmp, mattk); else pline("%s casts a spell at thin air!", youseeit ? Monnam(mtmp) : "It"); /* Not totally right since castmu allows other * spells, such as the monster healing itself, * that should work even when not next to you-- * but the previous code was just as wrong. * --KAA */ break; default: /* no attack */ break; } if(flags.botl) bot(); if(sum[i] == 2) return(1); /* attacker dead */ if(sum[i] == 3) break; /* attacker teleported, no more attacks */ /* sum[i] == 1: successful attack */ /* sum[i] == 0: unsuccessful attack */ } return(0); } #endif /* OVL0 */ #ifdef OVLB /* * helper function for some compilers that have trouble with hitmu */ XSTATIC void hurtarmor(mdat, attk) struct permonst *mdat; int attk; { boolean getbronze, rusting; int hurt; rusting = (attk == AD_RUST); if (rusting) { hurt = 1; getbronze = (mdat == &mons[PM_BLACK_PUDDING] && uarm && is_corrodeable(uarm)); } else { hurt=2; getbronze = FALSE; } /* What the following code does: it keeps looping until it * finds a target for the rust monster. * Head, feet, etc... not covered by metal, or covered by * rusty metal, are not targets. However, your body always * is, no matter what covers it. */ while (1) { switch(rn2(5)) { case 0: if (!rust_dmg(uarmh, rusting ? "helmet" : "leather helmet", hurt, FALSE)) continue; break; case 1: if (uarmc) break; /* Note the difference between break and continue; * break means it was hit and didn't rust; continue * means it wasn't a target and though it didn't rust * something else did. */ if (getbronze) (void)rust_dmg(uarm, "bronze armor", 3, TRUE); else if (uarm) (void)rust_dmg(uarm, xname(uarm), hurt, TRUE); break; case 2: if (!rust_dmg(uarms, rusting ? "shield" : "wooden shield", hurt, FALSE)) continue; break; case 3: if (!rust_dmg(uarmg, rusting ? "metal gauntlets" : "gloves", hurt, FALSE)) continue; break; case 4: if (!rust_dmg(uarmf, rusting ? "metal boots" : "boots", hurt, FALSE)) continue; break; } break; /* Out of while loop */ } } #endif /* OVLB */ #ifdef OVL1 /* * hitmu: monster hits you * returns 2 if monster dies (e.g. "yellow light"), 1 otherwise * 3 if the monster lives but teleported/paralyzed, so it can't keep * attacking you */ XSTATIC int hitmu(mtmp, mattk) register struct monst *mtmp; register struct attack *mattk; { register struct permonst *mdat = mtmp->data; register int dmg, ctmp, ptmp; char buf[BUFSZ]; #ifdef POLYSELF struct permonst *olduasmon = uasmon; int res; #endif /* If the monster is undetected & hits you. You should know where * the attack came from. */ if(mtmp->mhide && mtmp->mundetected) { mtmp->mundetected = 0; if(!(Blind ? Telepat : (HTelepat & WORN_HELMET))) { register struct obj *obj; if(OBJ_AT(mtmp->mx, mtmp->my)) { if(obj = level.objects[mtmp->mx][mtmp->my]) pline("%s was hidden under %s!", Xmonnam(mtmp), doname(obj)); } else if (levl[mtmp->mx][mtmp->my].gmask == 1) pline("%s was hidden under some gold!", Xmonnam(mtmp)); } } /* First determine the base damage done */ dmg = d((int)mattk->damn, (int)mattk->damd); if(is_undead(mdat) && midnight()) dmg += d((int)mattk->damn, (int)mattk->damd); /* extra damage */ /* Next a cancellation factor */ /* Use ctmp when the cancellation factor takes into account certain * armor's special magic protection. Otherwise just use !mtmp->mcan. */ ctmp = !mtmp->mcan && (!uarm || (rn2(3) >= objects[uarm->otyp].a_can) || !rn2(50)) && (!uarmc || (rn2(3) >= objects[uarmc->otyp].a_can) || !rn2(50)); /* Now, adjust damages via resistances or specific attacks */ switch(mattk->adtyp) { case AD_PHYS: if(mattk->aatyp == AT_HUGS #ifdef POLYSELF && !sticks(uasmon) #endif ) { if(!u.ustuck && rn2(2)) { u.ustuck = mtmp; kludge("%s grabs you!", Monnam(mtmp)); } else if(u.ustuck == mtmp) You("are being %s.", #ifdef GOLEMS (mtmp->data == &mons[PM_ROPE_GOLEM]) ? "choked" : #endif /* GOLEMS */ "crushed"); } else { /* hand to hand weapon */ hitmsg(mtmp, mattk); if(mattk->aatyp == AT_WEAP && otmp) { dmg += dmgval(otmp, uasmon); if (dmg <= 0) dmg = 1; #ifdef NAMED_ITEMS if (spec_ability(otmp, SPFX_DRLI) # ifdef POLYSELF && !resists_drli(uasmon) # endif ) { if (Blind) You("feel an unholy blade drain your life!"); else pline("The %s blade drains your life!", Hallucination ? hcolor() : black); losexp(); } #endif #ifdef POLYSELF if (u.mh > 1 && u.mh > ((u.uac>0) ? dmg : dmg+u.uac) && (u.umonnum==PM_BLACK_PUDDING || u.umonnum==PM_BROWN_PUDDING)) { /* This redundancy necessary because you have to * take the damage _before_ being cloned. */ if (u.uac < 0) dmg += u.uac; if (dmg < 1) dmg = 1; u.mh -= dmg; flags.botl = 1; dmg = 0; if(cloneu()) kludge("You divide as %s hits you!",mon_nam(mtmp)); } urustm(mtmp, otmp); #endif } } break; case AD_DISE: hitmsg(mtmp, mattk); #ifdef POLYSELF if (u.usym == S_FUNGUS) You("feel a slight illness."); else #endif You("feel very sick."); make_sick((long)rn1(25-ACURR(A_CON),15),FALSE); u.usick_cause = mdat->mname; break; case AD_FIRE: hitmsg(mtmp, mattk); if(ctmp) { pline("You're on fire!"); if (Fire_resistance) { pline("The fire doesn't feel hot!"); dmg = 0; } if(mtmp->m_lev > rn2(20)) destroy_item(SCROLL_SYM, AD_FIRE); if(mtmp->m_lev > rn2(20)) destroy_item(POTION_SYM, AD_FIRE); #ifdef SPELLS if(mtmp->m_lev > rn2(25)) destroy_item(SPBOOK_SYM, AD_FIRE); #endif } else dmg = 0; break; case AD_COLD: hitmsg(mtmp, mattk); if(ctmp) { pline("You're covered in frost!"); if (Cold_resistance) { pline("The frost doesn't seem cold!"); dmg = 0; } if(mtmp->m_lev > rn2(20)) destroy_item(POTION_SYM, AD_COLD); } else dmg = 0; break; case AD_ELEC: hitmsg(mtmp, mattk); if(ctmp) { You("get zapped!"); if (Shock_resistance) { pline("The zap doesn't shock you!"); dmg = 0; } if(mtmp->m_lev > rn2(20)) destroy_item(WAND_SYM, AD_ELEC); if(mtmp->m_lev > rn2(20)) destroy_item(RING_SYM, AD_ELEC); } else dmg = 0; break; case AD_SLEE: hitmsg(mtmp, mattk); if(ctmp && multi >= 0 && !rn2(5)) { if (Sleep_resistance) break; nomul(-rnd(10)); if (Blind) You("are put to sleep!"); else You("are put to sleep by %s!",mon_nam(mtmp)); } break; case AD_DRST: ptmp = A_STR; goto dopois; case AD_DRDX: ptmp = A_DEX; goto dopois; case AD_DRCO: ptmp = A_CON; dopois: hitmsg(mtmp, mattk); if(ctmp && !rn2(8)) { Sprintf(buf, "%s's %s", Hallucination ? rndmonnam() : mdat->mname, (mattk->aatyp == AT_BITE) ? "bite" : "sting"); poisoned(buf, ptmp, mdat->mname, 30); } break; case AD_PLYS: hitmsg(mtmp, mattk); if(ctmp && multi >= 0 && !rn2(3)) { if (Blind) You("are frozen!"); else You("are frozen by %s!", mon_nam(mtmp)); nomul(-rnd(10)); } break; case AD_DRLI: hitmsg(mtmp, mattk); if (ctmp && !rn2(3) #ifdef POLYSELF && !resists_drli(uasmon) #endif #ifdef NAMED_ITEMS && !defends(AD_DRLI, uwep) #endif ) losexp(); break; case AD_LEGS: { register long side = rn2(2) ? RIGHT_SIDE : LEFT_SIDE; if (mtmp->mcan) { kludge("%s nuzzles against your %s %s!", Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left", body_part(LEG)); } else { if (uarmf) { kludge("%s scratches your %s boot!", Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left"); break; } kludge("%s pricks your %s %s!", Monnam(mtmp), (side == RIGHT_SIDE) ? "right" : "left", body_part(LEG)); set_wounded_legs(side, rnd(60-ACURR(A_DEX))); } break; } case AD_STON: /* at present only a cockatrice */ hitmsg(mtmp, mattk); if(!rn2(3) && !Stoned) { if (mtmp->mcan) { if (flags.soundok) You("hear a cough from %s!", Blind ? "it" : mon_nam(mtmp)); } else { if (flags.soundok) if (Blind) You("hear its hissing!"); else You("hear %s's hissing!", mon_nam(mtmp)); if((!rn2(10) || (flags.moonphase == NEW_MOON && !have_lizard())) #ifdef POLYSELF && !resists_ston(uasmon) #endif ) { Stoned = 5; return(1); /* You("turn to stone..."); */ /* done_in_by(mtmp); */ } } } break; case AD_STCK: hitmsg(mtmp, mattk); if(ctmp && !u.ustuck #ifdef POLYSELF && !sticks(uasmon) #endif ) u.ustuck = mtmp; break; case AD_WRAP: if(ctmp #ifdef POLYSELF && !sticks(uasmon) #endif ) { if(!u.ustuck && !rn2(10)) { kludge("%s swings itself around you!", Monnam(mtmp)); u.ustuck = mtmp; } else if(u.ustuck == mtmp) { if (is_pool(mtmp->mx,mtmp->my) #ifdef POLYSELF && !is_swimmer(uasmon) #endif ) { kludge("%s drowns you...", Monnam(mtmp)); done(DROWNING); } else if(mattk->aatyp == AT_HUGS) You("are being crushed."); } else dmg = 0; } else dmg = 0; break; case AD_WERE: hitmsg(mtmp, mattk); #ifdef POLYSELF if (ctmp && !rn2(4) && u.ulycn == -1 && !Protection_from_shape_changers # ifdef NAMED_ITEMS && !defends(AD_WERE,uwep) # endif ) { You("feel feverish."); u.ulycn = monsndx(mdat); } #endif break; case AD_SGLD: hitmsg(mtmp, mattk); #ifdef POLYSELF if (u.usym == mdat->mlet) break; #endif if(!mtmp->mcan) stealgold(mtmp); break; case AD_SITM: /* for now these are the same */ case AD_SEDU: #ifdef POLYSELF if (dmgtype(uasmon, AD_SEDU) # ifdef SEDUCE || dmgtype(uasmon, AD_SSEX) # endif ) { if (mtmp->minvent) kludge("%s brags about the goods some dungeon explorer provided.", Monnam(mtmp)); else kludge("%s makes some remarks about how difficult theft is lately.", Monnam(mtmp)); rloc(mtmp); return 3; } else #endif if(mtmp->mcan) { if (!Blind) { pline("%s tries to %s you, but you seem %s.", Amonnam(mtmp, "plain"), flags.female ? "charm" : "seduce", flags.female ? "unaffected" : "uninterested"); } if(rn2(3)) { rloc(mtmp); return 3; } } else { switch (steal(mtmp)) { case -1: return 2; case 0: break; default: rloc(mtmp); mtmp->mflee = 1; return 3; } } break; #ifdef SEDUCE case AD_SSEX: if(could_seduce(mtmp, &youmonst, mattk) == 1 && !mtmp->mcan) if (doseduce(mtmp)) return 3; break; #endif case AD_SAMU: hitmsg(mtmp, mattk); /* when the Wiz hits, 1/20 steals the amulet */ if (!carrying(AMULET_OF_YENDOR)) break; if (!rn2(20)) stealamulet(mtmp); break; case AD_TLPT: hitmsg(mtmp, mattk); if(ctmp) { if(flags.verbose) Your("position suddenly seems very uncertain!"); tele(); } break; case AD_RUST: hitmsg(mtmp, mattk); if (mtmp->mcan) break; #if defined(POLYSELF) && defined(GOLEMS) if (u.umonnum == PM_IRON_GOLEM) { You("rust!"); rehumanize(); break; } #endif hurtarmor(mdat, AD_RUST); break; case AD_DCAY: hitmsg(mtmp, mattk); if (mtmp->mcan) break; #if defined(POLYSELF) && defined(GOLEMS) if (u.umonnum == PM_WOOD_GOLEM || u.umonnum == PM_LEATHER_GOLEM) { You("rot!"); rehumanize(); break; } #endif hurtarmor(mdat, AD_DCAY); break; case AD_HEAL: if(!uwep #ifdef SHIRT && !uarmu #endif && !uarm && !uarmh && !uarms && !uarmg && !uarmc && !uarmf) { kludge("%s hits! (I hope you don't mind.)", Monnam(mtmp)); #ifdef POLYSELF if (u.mtimedone) { u.mh += rnd(7); if(!rn2(7)) u.mhmax++; if(u.mh > u.mhmax) u.mh = u.mhmax; if(u.mh == u.mhmax && !rn2(50)) mongone(mtmp); } else { #endif u.uhp += rnd(7); if(!rn2(7)) u.uhpmax++; if(u.uhp > u.uhpmax) u.uhp = u.uhpmax; if(u.uhp == u.uhpmax && !rn2(50)) mongone(mtmp); #ifdef POLYSELF } #endif flags.botl = 1; if(!rn2(50)) rloc(mtmp); dmg = 0; } else if(pl_character[0] == 'H') { if (flags.soundok && !(moves % 5)) verbalize("Doc, I can't help you unless you cooperate."); dmg = 0; } else hitmsg(mtmp, mattk); break; case AD_CURS: hitmsg(mtmp, mattk); if(!night() && mdat == &mons[PM_GREMLIN]) break; if(!mtmp->mcan && !rn2(10)) { if (flags.soundok) if (Blind) You("hear laughter."); else pline("%s chuckles.", Monnam(mtmp)); #ifdef POLYSELF #ifdef GOLEMS if (u.umonnum == PM_CLAY_GOLEM) { pline("Some writing vanishes from your head!"); rehumanize(); break; } #endif /* GOLEMS */ #endif attrcurse(); } break; case AD_STUN: hitmsg(mtmp, mattk); if(!mtmp->mcan && !rn2(4)) { make_stunned(HStun + dmg, TRUE); dmg /= 2; } break; case AD_ACID: hitmsg(mtmp, mattk); if(!mtmp->mcan && !rn2(3)) #ifdef POLYSELF if (resists_acid(uasmon)) { pline("You're covered in acid, but it seems harmless."); dmg = 0; } else #endif pline("You're covered in acid! It burns!"); else dmg = 0; break; case AD_SLOW: hitmsg(mtmp, mattk); if(!ctmp && (Fast & (INTRINSIC|TIMEOUT)) && !rn2(4)) { Fast &= ~(INTRINSIC|TIMEOUT); You("feel yourself slowing down."); } break; case AD_DREN: hitmsg(mtmp, mattk); #ifdef SPELLS if(!ctmp && !rn2(4)) drain_en(dmg); #endif dmg = 0; break; #ifdef INFERNO /* a non-gaze AD_CONF exists only for one of the demons */ case AD_CONF: hitmsg(mtmp, mattk); if(!mtmp->mcan && !rn2(4) && !mtmp->mspec_used) { mtmp->mspec_used += (dmg + rn2(6)); if(Confusion) You("are getting even more confused."); else You("are getting confused."); make_confused(HConfusion + dmg, FALSE); } #endif /* fall through to next case */ default: dmg = 0; break; } if(u.uhp < 1) done_in_by(mtmp); /* Negative armor class reduces damage done instead of fully protecting * against hits. */ if (dmg && u.uac < 0) { dmg -= rnd(-u.uac); if (dmg < 1) dmg = 1; } if(dmg) mdamageu(mtmp, dmg); #ifdef POLYSELF res = passiveum(olduasmon, mtmp, mattk); stop_occupation(); return res; #else stop_occupation(); return 1; #endif } #endif /* OVL1 */ #ifdef OVLB XSTATIC int gulpmu(mtmp, mattk) /* monster swallows you, or damage if u.uswallow */ register struct monst *mtmp; register struct attack *mattk; { int tmp = d((int)mattk->damn, (int)mattk->damd); int tim_tmp; #ifdef WALKIES int i; #endif if(!u.uswallow) { /* swallows you */ #ifdef POLYSELF if (uasmon->msize >= MZ_HUGE) return(0); #endif remove_monster(mtmp->mx, mtmp->my); place_monster(mtmp, u.ux, u.uy); u.ustuck = mtmp; pmon(mtmp); kludge("%s engulfs you!", Monnam(mtmp)); stop_occupation(); if (u.utrap) { You("are released from the trap!"); u.utrap = 0; } #ifdef WALKIES if((i = number_leashed()) > 0) { pline("The leash%s snap%s loose...", (i > 1) ? "es" : "", (i > 1) ? "" : "s"); unleash_all(); } #endif #ifdef POLYSELF if (u.umonnum==PM_COCKATRICE && !resists_ston(mtmp->data)) { kludge("%s turns to stone!", Monnam(mtmp)); stoned = 1; xkilled(mtmp, 0); return 2; } #endif more(); seeoff(1); u.uswallow = 1; /*assume that u.uswldtim always set >=0*/ u.uswldtim = (tim_tmp = (-u.uac + 10 + rnd(25 - (int)mtmp->m_lev)) >> 1) > 0 ? tim_tmp : 0; swallowed(1); } else { if(mtmp != u.ustuck) return(0); switch(mattk->adtyp) { case AD_DGST: if(!u.uswldtim) { /* a3 *//*no cf unsigned <=0*/ kludge("%s totally digests you!", Monnam(mtmp)); tmp = u.uhp; } else { kludge("%s digests you!", Monnam(mtmp)); } break; case AD_PHYS: You("are pummeled with debris!"); break; case AD_ACID: #ifdef POLYSELF if (resists_acid(uasmon)) { You("are covered with a seemingly harmless goo."); tmp = 0; } else #endif if (Hallucination) pline("Ouch! You've been slimed!"); else You("are covered in slime! It burns!"); break; case AD_BLND: if(!Blind) { You("can't see in here!"); make_blinded((long)tmp,FALSE); } else make_blinded(Blinded+1,FALSE); /* keep him blind until disgorged */ tmp = 0; break; case AD_ELEC: if(!mtmp->mcan && rn2(2)) { pline("The air around you crackles with electricity."); if (Shock_resistance) { shieldeff(u.ux, u.uy); You("seem unhurt."); #if defined(POLYSELF) && defined(GOLEMS) ugolemeffects(AD_ELEC,tmp); #endif tmp = 0; } } else tmp = 0; break; case AD_COLD: if(!mtmp->mcan && rn2(2)) { if (Cold_resistance) { shieldeff(u.ux, u.uy); You("feel mildly chilly."); #if defined(POLYSELF) && defined(GOLEMS) ugolemeffects(AD_COLD,tmp); #endif tmp = 0; } else You("are freezing to death!"); } else tmp = 0; break; case AD_FIRE: if(!mtmp->mcan && rn2(2)) { if (Fire_resistance) { shieldeff(u.ux, u.uy); You("feel mildly hot."); #if defined(POLYSELF) && defined(GOLEMS) ugolemeffects(AD_FIRE,tmp); #endif tmp = 0; } else You("are burning to a crisp!"); } else tmp = 0; break; #ifdef INFERNO case AD_DISE: if (!Sick) You("feel very sick."); make_sick(Sick + (long)rn1(25-ACURR(A_CON),15),FALSE); u.usick_cause = mtmp->data->mname; break; #endif default: tmp = 0; break; } } mdamageu(mtmp, tmp); if(tmp) stop_occupation(); if(u.uswldtim) --u.uswldtim; if(!u.uswldtim #ifdef POLYSELF || u.umonnum==PM_COCKATRICE || uasmon->msize >= MZ_HUGE #endif ) { #ifdef POLYSELF if (u.umonnum == PM_COCKATRICE) { kludge("%s very hurriedly %s you!", Monnam(mtmp), is_animal(mtmp->data)? "regurgitates" : "expels"); u.uswldtim = 0; } else { #endif You("get %s!", is_animal(mtmp->data)? "regurgitated" : "expelled"); if(flags.verbose && is_animal(mtmp->data)) kludge("Obviously %s doesn't like your taste.", mon_nam(mtmp)); #ifdef POLYSELF } #endif expels(mtmp, mtmp->data, FALSE); } return(1); } XSTATIC int explmu(mtmp, mattk) /* monster explodes in your face */ register struct monst *mtmp; register struct attack *mattk; { register int tmp = d((int)mattk->damn, (int)mattk->damd); if(mtmp->mcan) return(0); if(!Blind) kludge("%s explodes!", Monnam(mtmp)); else pline("It explodes!"); switch(mattk->adtyp) { case AD_COLD: if(Cold_resistance) { You("seem unaffected by it."); #if defined(POLYSELF) && defined(GOLEMS) ugolemeffects(AD_COLD,tmp); #endif tmp = 0; } else { if(ACURR(A_DEX) > rnd(20)) { if (flags.verbose) You("get blasted!"); } else { You("duck the blast..."); tmp /= 2; } } break; case AD_BLND: if(!Blind #ifdef POLYSELF && u.usym != S_YLIGHT #endif ) { You("are blinded by a blast of light!"); make_blinded((long)tmp,FALSE); } tmp = 0; break; default: break; } mdamageu(mtmp, tmp); mondead(mtmp); return(2); /* it dies */ } XSTATIC int gazemu(mtmp, mattk) /* monster gazes at you */ register struct monst *mtmp; register struct attack *mattk; { switch(mattk->adtyp) { #ifdef MEDUSA case AD_STON: if (mtmp->mcan) { You("notice that %s isn't all that ugly.",mon_nam(mtmp)); break; } if (canseemon(mtmp)) { You("look upon %s.", mon_nam(mtmp)); # ifdef POLYSELF if (resists_ston(uasmon)) { pline("So what?"); break; } # endif You("turn to stone..."); killer_format = KILLED_BY_AN; killer = mons[PM_MEDUSA].mname; done(STONING); } break; #endif case AD_CONF: if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { int conf = d(3,4); mtmp->mspec_used += (conf + rn2(6)); if(!Confusion) pline("%s's gaze confuses you!", Monnam(mtmp)); else You("are getting more and more confused."); make_confused(HConfusion + conf, FALSE); } break; #ifdef INFERNO case AD_STUN: if(!mtmp->mcan && canseemon(mtmp) && mtmp->mcansee && !mtmp->mspec_used && rn2(5)) { int stun = d(2,6); pline("%s stares piercingly at you!", Monnam(mtmp)); mtmp->mspec_used += (stun + rn2(6)); make_stunned(HStun + stun, TRUE); } break; #endif default: impossible("Gaze attack %d?", mattk->adtyp); break; } return(1); } #endif /* OVLB */ #ifdef OVL1 void mdamageu(mtmp, n) /* mtmp hits you for n points damage */ register struct monst *mtmp; register int n; { #ifdef POLYSELF if (u.mtimedone) { u.mh -= n; flags.botl = 1; if (u.mh < 1) rehumanize(); return; } #endif u.uhp -= n; flags.botl = 1; if(u.uhp < 1) done_in_by(mtmp); } #endif /* OVL1 */ #ifdef OVLB #ifdef POLYSELF XSTATIC void urustm(mon, obj) register struct monst *mon; register struct obj *obj; { boolean vis = cansee(mon->mx, mon->my); if (!mon || !obj) return; /* just in case */ if (u.umonnum == PM_RUST_MONSTER && objects[obj->otyp].oc_material == METAL && obj->spe > -2) { if(obj->rustfree) { if (vis) pline("The rust vanishes from %s's weapon!", mon_nam(mon)); } else if(obj->blessed && rn2(3)) { if (vis) pline("Somehow, %s's weapon is not affected!", mon_nam(mon)); } else { if (vis) pline("%s's %s!", Monnam(mon), aobjnam(obj,"corrode")); obj->spe--; } } } #endif #endif /* OVLB */ #ifdef OVL1 int could_seduce(magr,mdef,mattk) struct monst *magr, *mdef; struct attack *mattk; /* returns 0 if seduction impossible, * 1 if fine, * 2 if wrong gender for nymph */ { register struct permonst *pagr, *pdef; boolean agrinvis, defperc; xchar genagr, gendef; if(magr == &youmonst) { pagr = uasmon; agrinvis = (Invis != 0); genagr = poly_gender(); } else { pagr = magr->data; agrinvis = magr->minvis; genagr = gender(magr); } if(mdef == &youmonst) { pdef = uasmon; defperc = (See_invisible != 0); gendef = poly_gender(); } else { pdef = mdef->data; defperc = perceives(pdef); gendef = gender(mdef); } if(agrinvis && !defperc #ifdef SEDUCE && mattk && mattk->adtyp != AD_SSEX #endif ) return 0; if(pagr->mlet != S_NYMPH #ifdef INFERNO && ((pagr != &mons[PM_INCUBUS] && pagr != &mons[PM_SUCCUBUS]) # ifdef SEDUCE || (mattk && mattk->adtyp != AD_SSEX) # endif ) #endif ) return 0; if(genagr == 1 - gendef) return 1; else return (pagr->mlet == S_NYMPH) ? 2 : 0; } #endif /* OVL1 */ #ifdef OVLB #ifdef SEDUCE /* Returns 1 if monster teleported */ int doseduce(mon) register struct monst *mon; { register struct obj *ring; boolean fem = (mon->data == &mons[PM_SUCCUBUS]); /* otherwise incubus */ if (mon->mcan || mon->mspec_used) { pline("%s acts as though %s has got a %sheadache.", Blind ? "It" : Monnam(mon), Blind ? "it" : fem ? "she" : "he", mon->mcan ? "severe " : ""); return 0; } if (unconscious()) { kludge("%s seems dismayed at your lack of response.", Monnam(mon)); return 0; } if (Blind) pline("It caresses you..."); else You("feel very attracted to %s.", mon_nam(mon)); for(ring = invent; ring; ring = ring->nobj) { if (ring->otyp != RIN_ADORNMENT) continue; if (fem) { if (rn2(20) < ACURR(A_CHA)) { pline("\"That %s looks pretty. May I have it?\" ", xname(ring)); makeknown(RIN_ADORNMENT); if (yn() == 'n') continue; } else pline("%s decides she'd like your %s, and takes it.", Blind ? "She" : Monnam(mon), xname(ring)); makeknown(RIN_ADORNMENT); if (ring==uleft || ring==uright) Ring_gone(ring); if (ring==uwep) setuwep((struct obj *)0); freeinv(ring); mpickobj(mon,ring); } else { char buf[BUFSZ]; if (uleft && uright && uleft->otyp == RIN_ADORNMENT && uright->otyp==RIN_ADORNMENT) break; if (ring==uleft || ring==uright) continue; if (rn2(20) < ACURR(A_CHA)) { pline("\"That %s looks pretty. Would you wear it for me?\" ", xname(ring)); makeknown(RIN_ADORNMENT); if (yn() == 'n') continue; } else { pline("%s decides you'd look prettier wearing your %s,", Blind ? "He" : Monnam(mon), xname(ring)); pline("and puts it on your finger."); } makeknown(RIN_ADORNMENT); if (!uright) { pline("%s puts the %s on your right hand.", Blind ? "He" : Monnam(mon), xname(ring)); setworn(ring, RIGHT_RING); } else if (!uleft) { pline("%s puts the %s on your left hand.", Blind ? "He" : Monnam(mon), xname(ring)); setworn(ring, LEFT_RING); } else if (uright && uright->otyp != RIN_ADORNMENT) { Strcpy(buf, xname(uright)); pline("%s replaces your %s with your %s.", Blind ? "He" : Monnam(mon), buf, xname(ring)); Ring_gone(uright); setworn(ring, RIGHT_RING); } else if (uleft && uleft->otyp != RIN_ADORNMENT) { Strcpy(buf, xname(uleft)); pline("%s replaces your %s with your %s.", Blind ? "He" : Monnam(mon), buf, xname(ring)); Ring_gone(uleft); setworn(ring, LEFT_RING); } else impossible("ring replacement"); Ring_on(ring); prinv(ring); } } pline("%s murmurs in your ear, while helping you undress.", Blind ? (fem ? "She" : "He") : Monnam(mon)); mayberem(uarmc, "cloak"); if(!uarmc) mayberem(uarm, "suit"); mayberem(uarmf, "boots"); mayberem(uarmg, "gloves"); mayberem(uarms, "shield"); mayberem(uarmh, "helmet"); #ifdef SHIRT if(!uarmc && !uarm) mayberem(uarmu, "shirt"); #endif if (uarm || uarmc) { pline("\"You're such a %s; I wish...\"", flags.female ? "sweet lady" : "nice guy"); rloc(mon); return 1; } #define ALIGNLIM (5L + (moves/200L)) /* from pray.c */ if (u.ualigntyp == U_CHAOTIC && u.ualign < ALIGNLIM) u.ualign++; /* by this point you have discovered mon's identity, blind or not... */ pline("Time stands still while you and %s lie in each other's arms...", mon_nam(mon)); if (rn2(35) > ACURR(A_CHA) + ACURR(A_INT)) { /* Don't bother with mspec_used here... it didn't get tired! */ pline("%s seems to have enjoyed it more than you...", Monnam(mon)); #ifdef SPELLS switch (rn2(5)) { case 0: You("feel drained of energy."); u.uen = 0; u.uenmax -= rnd(10); if (u.uenmax < 0) u.uenmax = 0; break; #else switch (rnd(4)) { #endif case 1: You("are down in the dumps."); adjattrib(A_CON, -1, TRUE); flags.botl = 1; break; case 2: Your("senses are dulled."); adjattrib(A_WIS, -1, TRUE); flags.botl = 1; break; case 3: #ifdef POLYSELF if (resists_drli(uasmon)) You("have a curious feeling..."); else { #endif You("feel out of shape."); losexp(); if(u.uhp <= 0) { killer_format = KILLED_BY; killer = "overexertion"; done(DIED); } #ifdef POLYSELF } #endif break; case 4: You("feel exhausted."); losehp(5+rnd(10), "exhaustion", KILLED_BY); break; } } else { mon->mspec_used = rnd(100); /* monster is worn out */ You("seem to have enjoyed it more than %s...", mon_nam(mon)); #ifdef SPELLS switch (rn2(5)) { case 0: You("feel raised to your full potential."); u.uen = (u.uenmax += rnd(5)); break; #else switch (rnd(4)) { #endif case 1: You("feel good enough to do it again."); adjattrib(A_CON, 1, TRUE); flags.botl = 1; break; case 2: You("will always remember %s...", mon_nam(mon)); adjattrib(A_WIS, 1, TRUE); flags.botl = 1; break; case 3: pline("That was a very educational experience."); pluslvl(); break; case 4: You("feel restored to health!"); u.uhp = u.uhpmax; #ifdef POLYSELF if (u.mtimedone) u.mh = u.mhmax; #endif flags.botl = 1; break; } } if (mon->mtame) /* don't charge */ ; else if (rn2(20) < ACURR(A_CHA)) { pline("%s demands that you pay %s, but you refuse...", Monnam(mon), (fem ? "her" : "him")); } #ifdef POLYSELF else if (u.umonnum == PM_LEPRECHAUN) pline("%s tries to take your money, but fails...", Monnam(mon)); #endif else { long cost = (long)rnd( (int)(u.ugold > 32767L ? 32767 : u.ugold) +10) + 500; if (mon->mpeaceful) { cost /= 5; if (!cost) cost=1; } if (cost > u.ugold) cost = u.ugold; if (!cost) verbalize("It's on the house!"); else { pline("%s takes %ld zorkmid%s for services rendered!", Monnam(mon), cost, plur(cost)); u.ugold -= cost; mon->mgold += cost; flags.botl = 1; } } if (!rn2(25)) mon->mcan = 1; /* monster is worn out */ rloc(mon); return 1; } static void mayberem(obj, str) register struct obj *obj; const char *str; { if (!obj || !obj->owornmask) return; if (rn2(20) < ACURR(A_CHA)) { pline("\"Shall I remove your %s, %s?\" ", str, (!rn2(2) ? "lover" : !rn2(2) ? "dear" : "sweetheart")); if (yn() == 'n') return; } else pline("\"Take off your %s; %s.\"", str, (obj == uarm) ? "let's get a little closer" : (obj == uarmc || obj == uarms) ? "it's in the way" : (obj == uarmf) ? "let me rub your feet" : (obj == uarmg) ? "they're too clumsy" : #ifdef SHIRT (obj == uarmu) ? "let me massage you" : #endif /* obj == uarmh */ "let me run my fingers through your hair"); if (donning(obj)) cancel_don(); if (obj == uarm) (void) Armor_off(); else if (obj == uarmc) (void) Cloak_off(); else if (obj == uarmf) (void) Boots_off(); else if (obj == uarmg) (void) Gloves_off(); else if (obj == uarmh) (void) Helmet_off(); else setworn((struct obj *)0, obj->owornmask & W_ARMOR); } #endif /* SEDUCE */ #endif /* OVLB */ #ifdef POLYSELF #ifdef OVL1 static int passiveum(olduasmon,mtmp,mattk) struct permonst *olduasmon; register struct monst *mtmp; register struct attack *mattk; { register struct permonst *mdat = mtmp->data; int i; int dam = 0; for(i = 0; ; i++) { if(i >= NATTK) return 1; if(olduasmon->mattk[i].aatyp == AT_NONE) break; } /* These affect the enemy even if you were "killed" (rehumanized) */ switch(olduasmon->mattk[i].adtyp) { case AD_ACID: if (!rn2(2)) { kludge("%s is splashed by your acid!", Monnam(mtmp)); if(!resists_acid(mdat)) dam = d((int)olduasmon->mlevel+1, (int)olduasmon->mattk[i].damd); else pline("%s is not affected.", Monnam(mtmp)); } break; case AD_STON: /* cockatrice */ if (!resists_ston(mdat) && (mattk->aatyp != AT_WEAP || !select_hwep(mtmp)) && mattk->aatyp != AT_GAZE && mattk->aatyp != AT_EXPL && mattk->aatyp != AT_MAGC && (!is_mercenary(mdat) || !m_carrying(mtmp, LEATHER_GLOVES))) { kludge("%s turns to stone!", Monnam(mtmp)); stoned = 1; xkilled(mtmp, 0); return 2; } default: break; } if (!u.mtimedone) return 1; /* These affect the enemy only if you are still a monster */ if (rn2(3)) switch(uasmon->mattk[i].adtyp) { case AD_PLYS: /* Floating eye */ {int tmp = d((int)uasmon->mlevel+1, (int)uasmon->mattk[i].damd); if (u.umonnum == PM_FLOATING_EYE) { if (!rn2(4)) tmp = 120; if (mtmp->mcansee && rn2(3) && (perceives(mdat) || !Invis)) { if (Blind) pline("As a blind %s, you cannot defend yourself.", uasmon->mname); else { pline("%s is frozen by your gaze!", Monnam(mtmp)); mtmp->mcanmove = 0; mtmp->mfrozen = tmp; return 3; } } } else { /* gelatinous cube */ kludge("%s is frozen by you.", Monnam(mtmp)); mtmp->mcanmove = 0; mtmp->mfrozen = tmp; return 3; } break; } case AD_COLD: /* Brown mold or blue jelly */ dam = d((int)uasmon->mlevel+1, (int)uasmon->mattk[i].damd); if(resists_cold(mdat)) { shieldeff(mtmp->mx, mtmp->my); kludge("%s is mildly chilly.", Monnam(mtmp)); #ifdef GOLEMS golemeffects(mtmp, AD_COLD, dam); #endif /* GOLEMS */ dam = 0; break; } kludge("%s is suddenly very cold!", Monnam(mtmp)); u.mh += dam / 2; if (u.mhmax < u.mh) u.mhmax = u.mh; if (u.mhmax > ((uasmon->mlevel+1) * 8)) { register struct monst *mon; if (mon = cloneu()) { mon->mhpmax = u.mhmax /= 2; if (Blind) You("multiply from its heat!"); else You("multiply from %s's heat!", mon_nam(mtmp)); } } break; case AD_STUN: /* Yellow mold */ if (!mtmp->mstun) { mtmp->mstun = 1; kludge("%s staggers.", Monnam(mtmp)); } break; case AD_FIRE: /* Red mold */ dam = d((int)uasmon->mlevel+1, (int)uasmon->mattk[i].damd); if(resists_fire(mdat)) { shieldeff(mtmp->mx, mtmp->my); kludge("%s is mildly warm.", Monnam(mtmp)); #ifdef GOLEMS golemeffects(mtmp, AD_FIRE, dam); #endif /* GOLEMS */ dam = 0; break; } kludge("%s is suddenly very hot!", Monnam(mtmp)); default: break; } if((mtmp->mhp -= dam) <= 0) { kludge("%s dies!", Monnam(mtmp)); xkilled(mtmp,0); return 2; } return 1; } #endif /* OVL1 */ #ifdef OVLB #include "edog.h" struct monst * cloneu() { register struct monst *mon; if (u.mh <= 1) return(struct monst *)0; uasmon->pxlth += sizeof(struct edog); mon = makemon(uasmon, u.ux, u.uy); uasmon->pxlth -= sizeof(struct edog); mon = christen_monst(mon, plname); initedog(mon); mon->m_lev = uasmon->mlevel; mon->mhp = u.mh /= 2; mon->mhpmax = u.mhmax; return(mon); } #endif /* OVLB */ #endif /* POLYSELF */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.