This is zap.c in view mode; [Download] [Up]
/* SCCS Id: @(#)zap.c 3.0 89/11/08 /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ #include "hack.h" #if defined(ALTARS) && defined(THEOLOGY) static boolean priesthit = FALSE; #endif static int FDECL(burn_floor_paper,(int,int)); #ifndef OVERLAY static int FDECL(bhitm,(struct monst *,struct obj *)); #endif static void FDECL(cancel_item,(struct obj *)); static int FDECL(bhitgold,(struct gold *,struct obj *)); #ifndef OVERLAY static int FDECL(bhito,(struct obj *,struct obj *)); #endif static void FDECL(backfire,(struct obj *)); static uchar FDECL(dirlet,(int,int)); static int FDECL(zhit,(struct monst *,int,int)); const char *fl[]= { "magic missile", /* Wands must be 0-9 */ "bolt of fire", "sleep ray", "bolt of cold", "death ray", "bolt of lightning", "", "", "", "", "magic missile", /* Spell equivalents must be 10-19 */ "fireball", "sleep ray", "cone of cold", "finger of death", "bolt of lightning", "", "", "", "", "blast of missiles", /* Dragon breath equivalents 20-29*/ "blast of fire", "blast of sleep gas", "blast of frost", "blast of disintegration", "blast of lightning", "blast of poison gas", "blast of acid", "", "" }; #ifdef TEXTCOLOR static const int zapcolor[10] = { AT_ZAP, RED|BRIGHT, AT_ZAP, WHITE|BRIGHT, AT_ZAP, WHITE|BRIGHT, AT_ZAP, AT_ZAP, AT_ZAP, AT_ZAP }; #endif /* Routines for IMMEDIATE wands and spells. */ /* bhitm: monster mtmp was hit by the effect of wand or spell otmp */ #ifndef OVERLAY static #endif int bhitm(mtmp, otmp) register struct monst *mtmp; register struct obj *otmp; { wakeup(mtmp); switch(otmp->otyp) { case WAN_STRIKING: #ifdef SPELLS case SPE_FORCE_BOLT: #endif if(u.uswallow || rnd(20) < 10+mtmp->data->ac) { register int tmp = d(2,12); hit((otmp->otyp == WAN_STRIKING) ? "wand" : "spell", mtmp, exclam(tmp)); (void) resist(mtmp, otmp->olet, tmp, TELL); } else miss((otmp->otyp == WAN_STRIKING) ? "wand" : "spell", mtmp); break; case WAN_SLOW_MONSTER: #ifdef SPELLS case SPE_SLOW_MONSTER: #endif if(! resist(mtmp, otmp->olet, 0, NOTELL)) { if (mtmp->mspeed == MFAST) mtmp->mspeed = 0; else mtmp->mspeed = MSLOW; if (u.uswallow && (mtmp == u.ustuck) && is_whirly(mtmp->data)) { You("disrupt %s!", mon_nam(mtmp)); pline("A huge hole opens up..."); expels(mtmp, mtmp->data, TRUE); } } break; case WAN_SPEED_MONSTER: if (!resist(mtmp, otmp->olet, 0, NOTELL)) if (mtmp->mspeed == MSLOW) mtmp->mspeed = 0; else mtmp->mspeed = MFAST; break; case WAN_UNDEAD_TURNING: #ifdef SPELLS case SPE_TURN_UNDEAD: #endif if(is_undead(mtmp->data)) { if(!resist(mtmp, otmp->olet, rnd(8), NOTELL)) mtmp->mflee = 1; } break; case WAN_POLYMORPH: #ifdef SPELLS case SPE_POLYMORPH: #endif if(!resist(mtmp, otmp->olet, 0, NOTELL)) if( newcham(mtmp, (struct permonst *)0) ) if (!Hallucination) makeknown(otmp->otyp); break; case WAN_CANCELLATION: #ifdef SPELLS case SPE_CANCELLATION: #endif if(!resist(mtmp, otmp->olet, 0, NOTELL)) { if (is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN) were_change(mtmp); #ifdef GOLEMS if (mtmp->data == &mons[PM_CLAY_GOLEM]) { if (!Blind) pline("Some writing vanishes from %s's head!", mon_nam(mtmp)); killed(mtmp); } else #endif /* GOLEMS */ mtmp->mcan = 1; } break; case WAN_TELEPORTATION: #ifdef SPELLS case SPE_TELEPORT_AWAY: #endif #if defined(ALTARS) && defined(THEOLOGY) if(mtmp->ispriest && in_temple(mtmp->mx, mtmp->my)) { kludge("%s resists your magic!", Monnam(mtmp)); wakeup(mtmp); break; } #endif rloc(mtmp); break; case WAN_MAKE_INVISIBLE: mtmp->minvis = 1; break; case WAN_NOTHING: break; #ifdef PROBING case WAN_PROBING: makeknown(otmp->otyp); mstatusline(mtmp); break; #endif case WAN_OPENING: if(u.uswallow && mtmp == u.ustuck) { if (is_animal(mtmp->data)) { if (Blind) pline("Its mouth opens!"); else pline("%s opens its mouth!", Monnam(mtmp)); } expels(mtmp, mtmp->data, TRUE); break; } case WAN_LOCKING: #ifdef SPELLS case SPE_KNOCK: case SPE_WIZARD_LOCK: #endif break; default: impossible("What an interesting effect (%u)", otmp->otyp); } return 0; } struct monst * revive(obj,ininv) register struct obj *obj; boolean ininv; { register struct monst *mtmp = (struct monst *)0; if(obj->otyp == CORPSE) { int montype = obj->corpsenm; int x = ininv ? u.ux : obj->ox; int y = ininv ? u.uy : obj->oy; if (cant_create(&montype)) { /* will make zombie instead */ mtmp = makemon(&mons[PM_HUMAN_ZOMBIE], x, y); if (mtmp) { mtmp->mhp = mtmp->mhpmax = 100; mtmp->mspeed = MFAST; } } else { struct obj *otmp; #ifdef ARMY if (is_mercenary(&mons[montype])) montype = PM_UNARMORED_SOLDIER; #endif mtmp = makemon(&mons[montype], x, y); if (mtmp) { /* Monster retains its name */ if (obj->onamelth) mtmp = christen_monst(mtmp, ONAME(obj)); /* No inventory for newly revived monsters */ while(otmp = (mtmp->minvent)) { mtmp->minvent = otmp->nobj; free((genericptr_t)otmp); } } } if (mtmp && obj->oeaten) mtmp->mhp = eaten_stat(mtmp->mhp, obj); if (ininv) useup(obj); else { /* not useupf(), which charges */ if (obj->quan > 1) obj->quan--; else delobj(obj); } if (x != u.ux || y != u.uy || Invisible) newsym(x, y); } return mtmp; } static const char charged_objs[] = { WAND_SYM, WEAPON_SYM, ARMOR_SYM, 0 }; static void cancel_item(obj) register struct obj *obj; { switch(obj->otyp) { case RIN_GAIN_STRENGTH: ABON(A_STR) -= obj->spe; flags.botl = 1; break; case RIN_ADORNMENT: ABON(A_CHA) -= obj->spe; flags.botl = 1; break; case RIN_INCREASE_DAMAGE: u.udaminc -= obj->spe; break; case GAUNTLETS_OF_DEXTERITY: ABON(A_DEX) -= obj->spe; flags.botl = 1; break; case HELM_OF_BRILLIANCE: ABON(A_INT) -= obj->spe; ABON(A_WIS) -= obj->spe; flags.botl = 1; break; /* case RIN_PROTECTION: /* not needed */ } if(obj->spe && !(obj->otyp == AMULET_OF_YENDOR || obj->otyp == WAN_CANCELLATION || /* can't cancel cancellation */ obj->otyp == TIN || obj->otyp == EGG || obj->otyp == STATUE || #ifdef MAIL obj->otyp == SCR_MAIL || #endif #ifdef TUTTI_FRUTTI obj->otyp == SLIME_MOLD || #endif obj->otyp == KEY || obj->otyp == SKELETON_KEY || obj->otyp == LARGE_BOX || obj->otyp == CHEST)) obj->spe = (obj->olet == WAND_SYM) ? -1 : 0; if (obj->olet == SCROLL_SYM #ifdef MAIL && obj->otyp != SCR_MAIL #endif ) obj->otyp = SCR_BLANK_PAPER; if (obj->olet == POTION_SYM && obj->otyp > POT_BOOZE) obj->otyp = (obj->otyp==POT_SICKNESS) ? POT_FRUIT_JUICE : POT_WATER; /* sickness is "biologically contaminated" fruit juice; cancel it * and it just becomes fruit juice... */ obj->blessed = obj->cursed = FALSE; } static int bhitgold(gold, otmp) register struct gold *gold; register struct obj *otmp; { switch(otmp->otyp) { case WAN_TELEPORTATION: #ifdef SPELLS case SPE_TELEPORT_AWAY: #endif rlocgold(gold); break; } return 1; } #ifndef OVERLAY static #endif int bhito(obj, otmp) /* object obj was hit by the effect of wand otmp */ register struct obj *obj, *otmp; /* returns TRUE if sth was done */ { register int res = 1; struct obj *otmp2; if(obj == uball || obj == uchain) res = 0; else switch(otmp->otyp) { case WAN_POLYMORPH: #ifdef SPELLS case SPE_POLYMORPH: #endif /* preserve symbol and quantity */ otmp2 = mkobj_at(obj->olet, obj->ox, obj->oy); otmp2->quan = obj->quan; #ifdef MAIL /* You can't send yourself 100 mail messages and then * polymorph them into useful scrolls */ if (obj->otyp == SCR_MAIL) { otmp2->otyp = SCR_MAIL; otmp2->spe = 1; } #endif /* keep special fields (including charges on wands) */ if (index(charged_objs, otmp2->olet)) otmp2->spe = obj->spe; /* Amulet gets cheap stewr 870807 */ if (obj->otyp == AMULET_OF_YENDOR) otmp2->spe = -1; /* Wands of wishing max 3 stewr 870808 */ if ((otmp2->otyp == WAN_WISHING) && (obj->spe > 3)) otmp2->spe = 3; otmp2->cursed = obj->cursed; otmp2->blessed = obj->blessed; otmp2->rustfree = obj->rustfree; /* Keep chest/box traps and poisoned ammo if we may */ if (obj->otrapped && Is_box(otmp2)) otmp2->otrapped = 1; if (obj->opoisoned && (otmp2->olet == WEAPON_SYM && otmp2->otyp <= SHURIKEN)) otmp2->opoisoned = 1; if (obj->otyp == CORPSE){ /* Turn dragon corpses into dragon armors */ if (obj->corpsenm >= PM_GRAY_DRAGON && obj->corpsenm <= PM_YELLOW_DRAGON) { if (!rn2(10)) { /* Random failure */ otmp2->otyp = TIN; otmp2->known = otmp2->dknown = 1; } else { otmp2->otyp = DRAGON_SCALE_MAIL; otmp2->olet = ARMOR_SYM; otmp2->spe = 0; otmp2->rustfree = 1; otmp2->quan = 1; otmp2->cursed = 0; } otmp2->corpsenm = obj->corpsenm; /* and croc corpses into shoes */ } else if (obj->corpsenm == PM_CROCODILE) { otmp2->otyp = LOW_BOOTS; otmp2->olet = ARMOR_SYM; otmp2->spe = 0; otmp2->rustfree = 1; otmp2->quan = 1; otmp2->cursed = 0; } } /* no named weapons --KAA */ if (otmp2->onamelth) { otmp2 = oname(otmp2, "", 0); fobj = otmp2; /* cannot use place_object() */ level.objects[otmp2->ox][otmp2->oy] = otmp2; } /* no box contents --KAA */ if (Is_container(otmp2)) delete_contents(otmp2); /* update the weight */ otmp2->owt = weight(otmp2); delobj(obj); break; case WAN_STRIKING: #ifdef SPELLS case SPE_FORCE_BOLT: #endif if(obj->otyp == BOULDER) fracture_rock(obj); else if(obj->otyp == STATUE) (void) break_statue(obj); else res = 0; break; case WAN_CANCELLATION: #ifdef SPELLS case SPE_CANCELLATION: #endif cancel_item(obj); break; case WAN_TELEPORTATION: #ifdef SPELLS case SPE_TELEPORT_AWAY: #endif rloco(obj); break; case WAN_MAKE_INVISIBLE: obj->oinvis = 1; break; case WAN_UNDEAD_TURNING: #ifdef SPELLS case SPE_TURN_UNDEAD: #endif res = !!revive(obj,FALSE); break; case WAN_OPENING: case WAN_LOCKING: #ifdef SPELLS case SPE_KNOCK: case SPE_WIZARD_LOCK: #endif if(Is_box(obj)) res = boxlock(obj, otmp); else res = 0; if (res /* && obj->olet == WAND_SYM */) makeknown(obj->otyp); break; case WAN_SLOW_MONSTER: /* no effect on objects */ #ifdef SPELLS case SPE_SLOW_MONSTER: #endif case WAN_SPEED_MONSTER: case WAN_NOTHING: #ifdef PROBING case WAN_PROBING: #endif res = 0; break; default: impossible("What an interesting effect (%u)", otmp->otyp); } return(res); } /* * zappable - returns 1 if zap is available, 0 otherwise. * it removes a charge from the wand if zappable. * added by GAN 11/03/86 */ int zappable(wand) register struct obj *wand; { if(wand->spe < 0 || (wand->spe == 0 && rn2(121))) return 0; if(wand->spe == 0) You("wrest one more spell from the worn-out wand."); wand->spe--; return 1; } /* * zapnodir - zaps an NODIR wand. * added by GAN 11/03/86 */ void zapnodir(wand) register struct obj *wand; { switch(wand->otyp){ case WAN_LIGHT: litroom(TRUE); break; case WAN_SECRET_DOOR_DETECTION: if(!findit()) return; break; case WAN_CREATE_MONSTER: { register int cnt = 1; if(!rn2(23)) cnt += rn2(7) + 1; while(cnt--) (void) makemon((struct permonst *) 0, u.ux, u.uy); } break; case WAN_WISHING: if(Luck + rn2(5) < 0) { pline("Unfortunately, nothing happens."); break; } makewish(); break; } if(!objects[wand->otyp].oc_name_known) { makeknown(wand->otyp); more_experienced(0,10); } } static void backfire(otmp) register struct obj * otmp; { pline("The %s suddenly explodes!", xname(otmp)); losehp(d(otmp->spe+2,6), "exploding wand", KILLED_BY_AN); useup(otmp); } static const char zap_syms[] = { WAND_SYM, 0 }; int dozap() { register struct obj *obj; int damage; obj = getobj(zap_syms, "zap"); if(!obj) return(0); check_unpaid(obj); /* zappable addition done by GAN 11/03/86 */ if(!zappable(obj)) pline(nothing_happens); else if(obj->cursed && !rn2(100)) { backfire(obj); /* the wand blows up in your face! */ return(1); } else if(!(objects[obj->otyp].bits & NODIR) && !getdir(1)) { if (!Blind) pline("The %s glows and fades.", xname(obj)); /* make him pay for knowing !NODIR */ } else if(!u.dx && !u.dy && !u.dz && !(objects[obj->otyp].bits & NODIR)) { if((damage = zapyourself(obj))) losehp(damage, self_pronoun("zapped %sself with a wand", "him"), NO_KILLER_PREFIX); } else { weffects(obj); #if defined(ALTARS) && defined(THEOLOGY) if(priesthit) ghod_hitsu(); priesthit = FALSE; #endif } if (obj->spe < 0) { pline ("The %s %sturns to dust.", xname(obj), Blind ? "" : "glows violently, then "); useup(obj); } return(1); } int zapyourself(obj) register struct obj *obj; { struct obj *otmp; int damage = 0; switch(obj->otyp) { case WAN_STRIKING: #ifdef SPELLS case SPE_FORCE_BOLT: #endif if(Antimagic) { shieldeff(u.ux, u.uy); pline("Boing!"); } else { You("magically bash yourself!"); damage=d(8,6); } break; case WAN_LIGHTNING: makeknown(WAN_LIGHTNING); if (!Shock_resistance) { pline("Idiot! You've shocked yourself!"); damage = d(12,6); } else { shieldeff(u.ux, u.uy); You("zap yourself, but seem unharmed."); #ifdef POLYSELF #ifdef GOLEMS ugolemeffects(AD_ELEC, d(12,6)); #endif /* GOLEMS */ #endif } if(!Blind) { You("are blinded by the flash!"); make_blinded((long)rnd(100),FALSE); } break; case WAN_FIRE: makeknown(WAN_FIRE); #ifdef SPELLS case SPE_FIREBALL: #endif #ifdef MUSIC case FIRE_HORN: #endif pline("You've set light to yourself!"); if (Fire_resistance) { shieldeff(u.ux, u.uy); You("feel mildly hot."); #ifdef POLYSELF #ifdef GOLEMS ugolemeffects(AD_FIRE, d(12,6)); #endif /* GOLEMS */ #endif } else damage = d(12,6); destroy_item(SCROLL_SYM, AD_FIRE); destroy_item(POTION_SYM, AD_FIRE); #ifdef SPELLS destroy_item(SPBOOK_SYM, AD_FIRE); #endif break; case WAN_COLD: makeknown(WAN_COLD); #ifdef SPELLS case SPE_CONE_OF_COLD: #endif #ifdef MUSIC case FROST_HORN: #endif if (Cold_resistance) { shieldeff(u.ux, u.uy); You("feel mildly chilly."); #ifdef POLYSELF #ifdef GOLEMS ugolemeffects(AD_COLD, d(12,6)); #endif /* GOLEMS */ #endif } else { You("imitate a popsicle!"); damage = d(12,6); } destroy_item(POTION_SYM, AD_COLD); break; case WAN_MAGIC_MISSILE: makeknown(WAN_MAGIC_MISSILE); #ifdef SPELLS case SPE_MAGIC_MISSILE: #endif if(Antimagic) { shieldeff(u.ux, u.uy); pline("The missiles bounce!"); } else { damage = d(4,6); pline("Idiot! You've shot yourself!"); } break; case WAN_POLYMORPH: #ifdef POLYSELF makeknown(WAN_POLYMORPH); #endif #ifdef SPELLS case SPE_POLYMORPH: #endif #ifdef POLYSELF polyself(); #else newman(); #endif break; case WAN_CANCELLATION: #ifdef SPELLS case SPE_CANCELLATION: #endif #ifdef POLYSELF #ifdef GOLEMS if (u.umonnum == PM_CLAY_GOLEM) { if (!Blind) pline("Some writing vanishes from your head!"); rehumanize(); break; } #endif /* GOLEMS */ #endif for(otmp = invent; otmp; otmp = otmp->nobj) cancel_item(otmp); #ifdef POLYSELF if(u.mtimedone) rehumanize(); #endif flags.botl = 1; /* because of potential AC change */ find_ac(); break; case WAN_MAKE_INVISIBLE: if (!Invisible) makeknown(WAN_MAKE_INVISIBLE); HInvis |= INTRINSIC; if (!See_invisible) newsym(u.ux, u.uy); break; case WAN_SPEED_MONSTER: if (!(Fast & INTRINSIC)) { Fast |= INTRINSIC; You("seem to be moving faster."); makeknown(WAN_SPEED_MONSTER); } break; case WAN_SLEEP: makeknown(WAN_SLEEP); #ifdef SPELLS case SPE_SLEEP: #endif if(Sleep_resistance) { shieldeff(u.ux, u.uy); You("don't feel sleepy!"); } else { pline("The sleep ray hits you!"); nomul(-rn2(50)); } break; case WAN_SLOW_MONSTER: #ifdef SPELLS case SPE_SLOW_MONSTER: #endif if(Fast & (TIMEOUT | INTRINSIC)) { Fast &= ~(TIMEOUT | INTRINSIC); You("seem to be moving slower."); } break; case WAN_TELEPORTATION: #ifdef SPELLS case SPE_TELEPORT_AWAY: #endif tele(); break; case WAN_DEATH: #ifdef SPELLS case SPE_FINGER_OF_DEATH: #endif #ifdef POLYSELF if (is_undead(uasmon)) { pline((obj->otyp == WAN_DEATH) ? "The wand shoots an apparently harmless beam at you." : "You seem no deader than before."); break; } #endif killer_format = NO_KILLER_PREFIX; killer = self_pronoun("shot %sself with a death ray","him"); You("irradiate yourself with pure energy!"); You("die."); makeknown(WAN_DEATH); /* They might survive with an amulet of life saving */ done(DIED); break; #ifdef SPELLS case SPE_TURN_UNDEAD: #endif case WAN_UNDEAD_TURNING: #ifdef POLYSELF if (is_undead(uasmon)) { You("feel frightened and %sstunned.", Stunned ? "even more " : ""); make_stunned(HStun + rnd(30), FALSE); } #endif break; #ifdef SPELLS case SPE_DIG: case SPE_DETECT_UNSEEN: #endif case WAN_DIGGING: case WAN_NOTHING: case WAN_OPENING: case WAN_LOCKING: #ifdef SPELLS case SPE_KNOCK: case SPE_WIZARD_LOCK: #endif break; #ifdef PROBING case WAN_PROBING: makeknown(WAN_PROBING); ustatusline(); break; #endif default: impossible("object %d used?",obj->otyp); } return(damage); } /* called for various wand and spell effects - M. Stephenson */ void weffects(obj) register struct obj *obj; { xchar zx,zy; if(objects[obj->otyp].bits & IMMEDIATE) { if(u.uswallow) (void)bhitm(u.ustuck, obj); else if(u.dz) { if(u.dz > 0) { #ifdef STRONGHOLD if(levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN && (obj->otyp == WAN_LOCKING # ifdef SPELLS || obj->otyp == SPE_WIZARD_LOCK # endif )) (void)close_drawbridge(u.ux, u.uy); else #endif { register struct obj *otmp, *otmp2; if(levl[u.ux][u.uy].gmask) (void) bhitgold(g_at(u.ux, u.uy), obj); for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) { /* changed by GAN to hit all objects there */ otmp2 = otmp->nexthere; /* save pointer as bhito may destroy otmp */ (void) bhito(otmp, obj); } } } } else (void) bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj); } else { switch(obj->otyp){ case WAN_LIGHT: #ifdef SPELLS case SPE_LIGHT: #endif litroom(TRUE); break; case WAN_SECRET_DOOR_DETECTION: #ifdef SPELLS case SPE_DETECT_UNSEEN: #endif if(!findit()) return; break; case WAN_CREATE_MONSTER: { register int cnt = 1; if(!rn2(23)) cnt += rn2(7) + 1; while(cnt--) (void) makemon((struct permonst *) 0, u.ux, u.uy); } break; case WAN_WISHING: if(Luck + rn2(5) < 0) { pline("Unfortunately, nothing happens."); break; } makewish(); break; case WAN_DIGGING: #ifdef SPELLS case SPE_DIG: #endif /* Original effect (approximately): * from CORR: dig until we pierce a wall * from ROOM: piece wall and dig until we reach * an ACCESSIBLE place. * Currently: dig for digdepth positions; * also down on request of Lennart Augustsson. */ { register struct rm *room; register int digdepth,dlx,dly; register boolean shopdoor = FALSE; #ifdef __GNULINT__ dlx = dly = 0; #endif if(u.uswallow) { register struct monst *mtmp = u.ustuck; if (!is_whirly(mtmp->data)) { if (is_animal(mtmp->data)) if (Blind) You("pierce its stomach wall!"); else You("pierce %s's stomach wall!", mon_nam(mtmp)); mtmp->mhp = 1; /* almost dead */ expels(mtmp, mtmp->data, !is_animal(mtmp->data)); } break; } if(u.dz) { if(u.dz < 0) { You("loosen a rock from the ceiling."); pline("It falls on your %s!", body_part(HEAD)); losehp(1, "falling rock", KILLED_BY_AN); (void) mksobj_at((int)ROCK, u.ux, u.uy); fobj->quan = 1; stackobj(fobj); if(Invisible) newsym(u.ux, u.uy); } else { dighole(); } break; } zx = u.ux+u.dx; zy = u.uy+u.dy; digdepth = 8 + rn2(18); Tmp_at2(-1, '*'); /* open call */ while(--digdepth >= 0) { if(!isok(zx,zy)) break; room = &levl[zx][zy]; Tmp_at2(zx,zy); if(is_maze_lev) { if(IS_WALL(room->typ)) { if(room->diggable == W_DIGGABLE) room->typ = ROOM; else if(!Blind) pline("The wall glows then fades."); break; } if(room->typ == STONE) { if(room->diggable == W_DIGGABLE) room->typ = CORR; else if (!Blind) pline("The rock glows then fades."); break; } } else if(IS_ROCK(room->typ)) if(may_dig(zx,zy)) if(IS_WALL(room->typ) || room->typ == SDOOR) { room->typ = DOOR; room->doormask = D_NODOOR; mnewsym(zx, zy); if (cansee(zx,zy)) prl(zx, zy); digdepth -= 2; } else { room->typ = CORR; digdepth--; } else break; else if(closed_door(zx, zy)) { room->doormask = D_NODOOR; mnewsym(zx, zy); if (cansee(zx,zy)) prl(zx, zy); if(in_shop(zx,zy)) { shopdoor = TRUE; dlx = zx; dly = zy; } digdepth -= 2; } mnewsym(zx,zy); zx += u.dx; zy += u.dy; } mnewsym(zx,zy); /* not always necessary */ Tmp_at2(-1,-1); /* closing call */ if(!Blind) prl(u.ux+u.dx, u.uy+u.dy); if(shopdoor) pay_for_door(dlx, dly, "destroy"); break; } default: #ifdef SPELLS if((int) obj->otyp >= SPE_MAGIC_MISSILE) { buzz((int) obj->otyp - SPE_MAGIC_MISSILE + 10, (int)u.ulevel / 2 + 1, u.ux, u.uy, u.dx, u.dy); } else #endif buzz((int) obj->otyp - WAN_MAGIC_MISSILE, 6, u.ux, u.uy, u.dx, u.dy); break; } if(!objects[obj->otyp].oc_name_known) { makeknown(obj->otyp); more_experienced(0,10); } } return; } const char * exclam(force) register int force; { /* force == 0 occurs e.g. with sleep ray */ /* note that large force is usual with wands so that !! would require information about hand/weapon/wand */ return (const char *)((force < 0) ? "?" : (force <= 4) ? "." : "!"); } void hit(str,mtmp,force) register const char *str; register struct monst *mtmp; register const char *force; /* usually either "." or "!" */ { if(!cansee(mtmp->mx,mtmp->my) || !flags.verbose) pline("The %s hits it.", str); else pline("The %s hits %s%s", str, mon_nam(mtmp), force); } void miss(str,mtmp) register const char *str; register struct monst *mtmp; { pline("The %s misses %s.", str, (cansee(mtmp->mx,mtmp->my) && flags.verbose) ? mon_nam(mtmp) : "it"); } /* bhit: called when a weapon is thrown (sym = obj->olet) or when an IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of range or when a monster is hit; the monster is returned, and bhitpos is set to the final position of the weapon thrown; the ray of a wand may affect several objects and monsters on its path - for each of these an argument function is called. */ /* check !u.uswallow before calling bhit() */ struct monst * bhit(ddx,ddy,range,sym,fhitm,fhito,obj) register int ddx,ddy,range; /* direction and range */ char sym; /* symbol displayed on path */ int FDECL((*fhitm), (struct monst *, struct obj *)), FDECL((*fhito), (struct obj *, struct obj *)); /* fns called when mon/obj hit */ struct obj *obj; /* 2nd arg to fhitm/fhito */ { register struct monst *mtmp; register struct obj *otmp; register uchar typ; boolean shopdoor = FALSE; #ifdef __GNULINT__ xchar dlx=0, dly=0; #else xchar dlx, dly; #endif bhitpos.x = u.ux; bhitpos.y = u.uy; if(sym) { tmp_at(-1, sym); /* open call */ #ifdef TEXTCOLOR tmp_at(-3, (int)objects[obj->otyp].oc_color); #else tmp_at(-3, (int)AT_OBJ); #endif } while(range-- > 0) { #ifdef STRONGHOLD int x,y; #endif bhitpos.x += ddx; bhitpos.y += ddy; #ifdef STRONGHOLD x = bhitpos.x; y = bhitpos.y; if (find_drawbridge(&x,&y) && !sym) switch (obj->otyp) { case WAN_OPENING: # ifdef SPELLS case SPE_KNOCK: # endif (void) open_drawbridge(x,y); break; case WAN_LOCKING: # ifdef SPELLS case SPE_WIZARD_LOCK: # endif (void) close_drawbridge(x,y); break; case WAN_STRIKING: # ifdef SPELLS case SPE_FORCE_BOLT: # endif destroy_drawbridge(x,y); } #endif /* STRONGHOLD /**/ if(MON_AT(bhitpos.x, bhitpos.y)){ mtmp = m_at(bhitpos.x,bhitpos.y); if(sym) { tmp_at(-1, -1); /* close call */ return(mtmp); } (*fhitm)(mtmp, obj); range -= 3; } /* modified by GAN to hit all objects */ if(fhito){ int hitanything = 0; register struct obj *next_obj; if((fhito == bhito) && levl[bhitpos.x][bhitpos.y].gmask) hitanything += bhitgold(g_at(bhitpos.x,bhitpos.y),obj); for(otmp = level.objects[bhitpos.x][bhitpos.y]; otmp; otmp = next_obj) { /* Fix for polymorph bug, Tim Wright */ next_obj = otmp->nexthere; hitanything += (*fhito)(otmp, obj); } if(hitanything) range--; } typ = levl[bhitpos.x][bhitpos.y].typ; if((IS_DOOR(typ) || typ == SDOOR) && !sym) { switch (obj->otyp) { case WAN_OPENING: case WAN_LOCKING: case WAN_STRIKING: #ifdef SPELLS case SPE_KNOCK: case SPE_WIZARD_LOCK: case SPE_FORCE_BOLT: #endif if (doorlock(obj, bhitpos.x, bhitpos.y)) { makeknown(obj->otyp); if (levl[bhitpos.x][bhitpos.y].doormask == D_BROKEN && in_shop(bhitpos.x, bhitpos.y)) { shopdoor = TRUE; dlx = bhitpos.x; dly = bhitpos.y; } } break; } } if(!ZAP_POS(typ) || closed_door(bhitpos.x, bhitpos.y)) { bhitpos.x -= ddx; bhitpos.y -= ddy; break; } if(sym) tmp_at(bhitpos.x, bhitpos.y); #ifdef SINKS if(sym && IS_SINK(typ)) break; /* physical objects fall onto sink */ #endif } /* leave last symbol unless in a pool */ if(sym) tmp_at(-1, is_pool(bhitpos.x,bhitpos.y) ? -1 : 0); if(shopdoor) pay_for_door(dlx, dly, "destroy"); return (struct monst *)0; } struct monst * boomhit(dx, dy) int dx, dy; { register int i, ct; char sym = ')'; bhitpos.x = u.ux; bhitpos.y = u.uy; for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break; tmp_at(-1, sym); /* open call */ #ifndef TEXTCOLOR tmp_at(-3, (int)AT_OBJ); #else tmp_at(-3, HI_METAL); #endif for(ct=0; ct<10; ct++) { if(i == 8) i = 0; sym = ')' + '(' - sym; tmp_at(-2, sym); /* change let call */ dx = xdir[i]; dy = ydir[i]; bhitpos.x += dx; bhitpos.y += dy; if(MON_AT(bhitpos.x, bhitpos.y)){ tmp_at(-1,-1); return(m_at(bhitpos.x,bhitpos.y)); } if(!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)) { bhitpos.x -= dx; bhitpos.y -= dy; break; } if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */ if(Fumbling || rn2(20) >= ACURR(A_DEX)){ /* we hit ourselves */ (void) thitu(10, rnd(10), (struct obj *)0, "boomerang"); break; } else { /* we catch it */ tmp_at(-1,-1); pline("Skillfully, you catch the boomerang."); return(&youmonst); } } tmp_at(bhitpos.x, bhitpos.y); if(ct % 5 != 0) i++; #ifdef SINKS if(IS_SINK(levl[bhitpos.x][bhitpos.y].typ)) break; /* boomerang falls on sink */ #endif } tmp_at(-1, -1); /* do not leave last symbol */ return (struct monst *)0; } static uchar dirlet(dx, dy) register int dx, dy; { return (dx == dy) ? LSLANT_SYM : (dx && dy) ? RSLANT_SYM : dx ? HBEAM_SYM : VBEAM_SYM; } static int zhit(mon, type, nd) /* returns damage to mon */ register struct monst *mon; register int type, nd; { register int tmp = 0; register int abstype = abs(type) % 10; switch(abstype) { case 0: /* magic missile */ tmp = d(nd,6); break; case 1: /* fire */ if(resists_fire(mon->data)) { shieldeff(mon->mx, mon->my); break; } tmp = d(nd,6); if(resists_cold(mon->data)) tmp += 7; break; case 2: /* sleep */ tmp = 0; if(resists_sleep(mon->data) || resist(mon, (type == 2) ? WAND_SYM : '\0', 0, NOTELL)) shieldeff(mon->mx, mon->my); else if (mon->mcanmove) { int tmp2 = d(nd,25); mon->mcanmove = 0; if (mon->mfrozen + tmp2 > 127) mon->mfrozen = 127; else mon->mfrozen += tmp2; } break; case 3: /* cold */ if(resists_cold(mon->data)) { shieldeff(mon->mx, mon->my); break; } tmp = d(nd,6); if(resists_fire(mon->data)) tmp += d(nd, 3); break; case 4: /* death/disintegration */ if(abs(type) != 24) { /* death */ if(is_undead(mon->data)) { shieldeff(mon->mx, mon->my); break; } type = -1; /* so they don't get saving throws */ } else if (resists_disint(mon->data)) { shieldeff(mon->mx, mon->my); break; } tmp = mon->mhp+1; break; case 5: /* lightning */ if(resists_elec(mon->data)) { shieldeff(mon->mx, mon->my); break; } tmp = d(nd,6); { register unsigned rnd_tmp = rnd(50); mon->mcansee = 0; if((mon->mblinded + rnd_tmp) > 127) mon->mblinded = 127; else mon->mblinded += rnd_tmp; } break; case 6: /* poison */ if(resists_poison(mon->data)) { shieldeff(mon->mx, mon->my); break; } tmp = d(nd,6); break; case 7: /* acid */ if(resists_acid(mon->data)) { shieldeff(mon->mx, mon->my); break; } tmp = d(nd,6); break; } if (type >= 0) if (resist(mon, (type < 10) ? WAND_SYM : '\0', 0, NOTELL)) tmp /= 2; mon->mhp -= tmp; return(tmp); } /* * burn scrolls and spell books on floor at position x,y * return the number of scrolls and spell books burned */ static int burn_floor_paper(x, y) int x, y; { register struct obj *obj, *obj2; register int scrquan, i, cnt = 0; for(obj = level.objects[x][y]; obj; obj = obj2) { obj2 = obj->nexthere; /* Bug fix - KAA */ #ifdef SPELLS if((obj->olet == SCROLL_SYM || obj->olet == SPBOOK_SYM)) { #else if(obj->olet == SCROLL_SYM) { #endif if (obj->otyp == SCR_FIRE #ifdef SPELLS || obj->otyp == SPE_FIREBALL) #endif continue; scrquan = obj->quan; for(i = 1; i <= scrquan ; i++) if(!rn2(3)) { cnt++; /* not useupf(), which charges */ if (obj->quan > 1) obj->quan--; else delobj(obj); } } } return(cnt); } /* type == 0 to 9 : you shooting a wand */ /* type == 10 to 19 : you casting a spell */ /* type == 20 to 29 : you breathing as a monster */ /* type == -10 to -19 : monster casting spell */ /* type == -20 to -29 : monster breathing at you */ /* called with dx = dy = 0 with vertical bolts */ void buzz(type,nd,sx,sy,dx,dy) register int type, nd; register xchar sx,sy; register int dx,dy; { int abstype = abs(type) % 10; register const char *fltxt = fl[abs(type)]; struct rm *lev; register xchar lsx, lsy; #ifdef __GNULINT__ xchar range, olx=0, oly=0; #else xchar range, olx, oly; #endif struct monst *mon; register boolean bodyhit = FALSE; register boolean shopdoor = FALSE; if(u.uswallow) { register int tmp; if(type < 0) return; tmp = zhit(u.ustuck, type, nd); if(!u.ustuck) u.uswallow = 0; else pline("The %s rips into %s%s", fltxt, mon_nam(u.ustuck), exclam(tmp)); if (u.ustuck->mhp < 1) killed(u.ustuck); return; } if(type < 0) pru(); range = rn1(7,7); Tmp_at2(-1, (int) dirlet(dx,dy)); /* open call */ #ifdef TEXTCOLOR Tmp_at2(-3, zapcolor[abstype]); #endif while(range-- > 0) { lsx = sx; sx += dx; lsy = sy; sy += dy; if((lev = &levl[sx][sy])->typ) { if((cansee(lsx,lsy) && cansee(sx,sy)) || (!cansee(lsx,lsy) && cansee(sx,sy) && (IS_DOOR(lev->typ) || IS_ROOM(lev->typ)))) Tmp_at2(sx,sy); } else { int bounce = 0; if(cansee(sx-dx,sy-dy)) pline("The %s bounces!", fltxt); if(ZAP_POS(levl[sx][sy-dy].typ)) bounce = 1; if(ZAP_POS(levl[sx-dx][sy].typ)) { if(!bounce || rn2(2)) bounce = 2; } switch(bounce){ case 0: dx = -dx; dy = -dy; continue; case 1: dy = -dy; sx -= dx; break; case 2: dx = -dx; sy -= dy; break; } Tmp_at2(-2,(int) dirlet(dx,dy)); continue; } if(abstype == 1 /* fire */ && (is_pool(sx,sy) || (lev->typ == ROOM && lev->icedpool))) { if(lev->typ == ROOM) { lev->typ = (lev->icedpool == ICED_POOL ? POOL : MOAT); lev->icedpool = 0; pline("The ice crackles and melts."); mnewsym(sx,sy); } else { #ifdef STRONGHOLD if(lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */ if(cansee(sx,sy)) pline("Some water evaporates."); else if(flags.soundok) You("hear a hissing sound."); } else { #endif register struct trap *ttmp; range -= 3; lev->typ = ROOM; mnewsym(sx,sy); if(cansee(sx,sy)) pline("The water evaporates."); else if(flags.soundok) You("hear a hissing sound."); ttmp = maketrap(sx, sy, PIT); ttmp->tseen = 1; #ifdef STRONGHOLD } #endif } } if(abstype == 3 /* cold */ && is_pool(sx,sy)) { boolean moat = (lev->typ != POOL); range -= 3; #ifdef STRONGHOLD if(lev->typ == DRAWBRIDGE_UP) { lev->drawbridgemask |= DB_ICE; } else { #endif lev->typ = ROOM; lev->icedpool = (moat ? ICED_MOAT : ICED_POOL); #ifdef STRONGHOLD } #endif mnewsym(sx,sy); if(cansee(sx,sy)) { if(moat) pline("The moat is bridged with ice!"); else pline("The water freezes."); } else if(flags.soundok) You("hear a crackling sound."); } if(closed_door(sx, sy)) { range = 0; switch(abstype) { case 1: lev->doormask = D_NODOOR; mnewsym(sx,sy); if(cansee(sx,sy)) { pline("The door is consumed in flames!"); prl(sx,sy); } else You("smell smoke."); if(type >= 0 && in_shop(sx, sy)) { shopdoor = TRUE; olx = sx; oly = sy; } break; case 3: lev->doormask = D_NODOOR; mnewsym(sx,sy); if(cansee(sx,sy)) { pline("The door freezes and shatters!"); prl(sx,sy); } else You("feel cold."); if(type >= 0 && in_shop(sx, sy)) { shopdoor = TRUE; olx = sx; oly = sy; } break; case 4: lev->doormask = D_NODOOR; mnewsym(sx,sy); if(cansee(sx,sy)) { pline("The door disintegrates!"); prl(sx,sy); } else if(flags.soundok) You("hear a crashing sound."); if(type >= 0 && in_shop(sx, sy)) { shopdoor = TRUE; olx = sx; oly = sy; } break; case 5: lev->doormask = D_BROKEN; mnewsym(sx,sy); if(cansee(sx,sy)) { pline("The door splinters!"); prl(sx,sy); } else if(flags.soundok) You("hear a crackling sound."); if(type >= 0 && in_shop(sx, sy)) { shopdoor = TRUE; olx = sx; oly = sy; } break; default: if(cansee(sx,sy)) { if (type >= 0 && type <= 9) pline("The door absorbs your bolt!"); else if (type >= 10 && type <= 19) pline("The door absorbs your spell!"); #ifdef POLYSELF else if (type >= 20 && type <= 29) pline("The door absorbs your blast!"); #endif else if (type >= -19 && type <= -10) pline("The door absorbs the spell!"); else pline("The door absorbs the blast!"); } else You("feel vibrations."); break; } } if(OBJ_AT(sx, sy) && abstype == 1) if(burn_floor_paper(sx,sy) && cansee(sx,sy)) { mnewsym(sx,sy); if(!Blind) You("see a puff of smoke."); } if(MON_AT(sx, sy)){ mon = m_at(sx,sy); /* Cannot use wakeup() which also angers the monster */ mon->msleep = 0; if(mon->mimic) seemimic(mon); if(type >= 0) { setmangry(mon); #if defined(ALTARS) && defined(THEOLOGY) if(mon->ispriest && in_temple(mon->mx, mon->my)) priesthit = TRUE; #endif } if(rnd(20) < 18 + mon->data->ac) { register int tmp = zhit(mon, type, nd); if(mon->mhp < 1) { if(type < 0) { if(cansee(mon->mx,mon->my)) pline("%s is killed by the %s!", Monnam(mon), fltxt); mondied(mon); } else killed(mon); } else hit(fltxt, mon, exclam(tmp)); range -= 2; } else miss(fltxt,mon); } else if(sx == u.ux && sy == u.uy) { nomul(0); if(rnd(20) < 18+u.uac) { register int dam = 0; range -= 2; pline("The %s hits you!",fltxt); if (Reflecting) { if (!Blind) { if(Reflecting & WORN_AMUL) makeknown(AMULET_OF_REFLECTION); else makeknown(SHIELD_OF_REFLECTION); pline("But it reflects from your %s!", (Reflecting & W_AMUL) ? "amulet" : "shield"); } else pline("For some reason you are not affected!"); if (dx) dx = -dx; if (dy) dy = -dy; shieldeff(sx, sy); } else switch(abstype) { case 0: /* magic missile */ if(Antimagic) { shieldeff(sx, sy); pline("The missiles bounce off!"); } else dam = d(nd,6); break; case 1: /* fire */ if(Fire_resistance) { shieldeff(sx, sy); You("don't feel hot!"); #ifdef POLYSELF #ifdef GOLEMS ugolemeffects(AD_FIRE, d(nd, 6)); #endif /* GOLEMS */ #endif } else dam = d(nd, 6); while (1) { switch(rn2(5)) { case 0: if (!rust_dmg(uarmh, "leather helmet", 0, FALSE)) continue; break; case 1: bodyhit = TRUE; if (uarmc) break; if (uarm) (void)(rust_dmg(uarm, xname(uarm), 0, FALSE)); break; case 2: if (!rust_dmg(uarms, "wooden shield", 0, FALSE)) continue; break; case 3: if (!rust_dmg(uarmg, "gloves", 0, FALSE)) continue; break; case 4: if (!rust_dmg(uarmf, "boots", 0, FALSE)) continue; break; } break; /* Out of while loop */ } if(!rn2(3) && bodyhit) destroy_item(POTION_SYM, AD_FIRE); if(!rn2(3) && bodyhit) destroy_item(SCROLL_SYM, AD_FIRE); #ifdef SPELLS if(!rn2(5) && bodyhit) destroy_item(SPBOOK_SYM, AD_FIRE); #endif break; case 2: /* sleep */ if(Sleep_resistance) { shieldeff(u.ux, u.uy); You("don't feel sleepy."); } else nomul(-d(nd,25)); /* sleep ray */ break; case 3: /* cold */ if(Cold_resistance) { shieldeff(sx, sy); You("don't feel cold."); #ifdef POLYSELF #ifdef GOLEMS ugolemeffects(AD_COLD, d(nd, 6)); #endif /* GOLEMS */ #endif } else dam = d(nd, 6); if(!rn2(3)) destroy_item(POTION_SYM, AD_COLD); break; case 4: /* death */ if(type == -24) { /* disintegration */ if (Disint_resistance) { You("are not disintegrated."); break; } else if(uarms) { (void) destroy_arm(uarms); break; } else if (uarm) { (void) destroy_arm(uarm); break; } } #ifdef POLYSELF else if(is_undead(uasmon)) { shieldeff(sx, sy); You("seem unaffected."); break; } #endif u.uhp = -1; break; case 5: /* lightning */ if (Shock_resistance) { shieldeff(sx, sy); You("aren't affected."); #ifdef POLYSELF #ifdef GOLEMS ugolemeffects(AD_ELEC, d(nd, 6)); #endif /* GOLEMS */ #endif } else dam = d(nd, 6); break; case 6: /* poison */ poisoned("blast", A_DEX, "poisoned blast", 15); break; case 7: /* acid */ pline("The acid burns!"); dam = d(nd,6); if(!rn2(6)) corrode_weapon(); if(!rn2(6)) corrode_armor(); break; } losehp(dam,fltxt, KILLED_BY_AN); } else pline("The %s whizzes by you!",fltxt); if (abstype == 5 && !Blind) { /* LIGHTNING */ You("are blinded by the flash!"); make_blinded((long)d(nd,50),FALSE); seeoff(0); } stop_occupation(); } if(!ZAP_POS(lev->typ)) { int bounce = 0; uchar rmn; if(cansee(sx,sy)) pline("The %s bounces!", fltxt); range--; if(!dx || !dy || !rn2(20)){ dx = -dx; dy = -dy; } else { if(ZAP_POS(rmn = levl[sx][sy-dy].typ) && (IS_ROOM(rmn) || ZAP_POS(levl[sx+dx][sy-dy].typ))) bounce = 1; if(ZAP_POS(rmn = levl[sx-dx][sy].typ) && (IS_ROOM(rmn) || ZAP_POS(levl[sx-dx][sy+dy].typ))) if(!bounce || rn2(2)) bounce = 2; switch(bounce){ case 0: dy = -dy; dx = -dx; break; case 1: dy = -dy; break; case 2: dx = -dx; break; } Tmp_at2(-2, (int) dirlet(dx,dy)); } } } Tmp_at2(-1,-1); if(shopdoor) pay_for_door(olx, oly, abstype == 1 ? "burn away" : abstype == 3 ? "shatter" : abstype == 4 ? "disintegrate" : "destroy"); } void rlocgold(gold) register struct gold *gold; { register int tx, ty, otx, oty; long val = gold->amount; otx = gold->gx; oty = gold->gy; do { tx = rn1(COLNO-3,2); ty = rn2(ROWNO); } while(!goodpos(tx,ty,(struct permonst *)0)); freegold(g_at(otx,oty)); mkgold(val, tx, ty); if(cansee(otx,oty)) newsym(otx,oty); if(cansee(tx,ty)) newsym(tx,ty); } void rloco(obj) register struct obj *obj; { register int tx, ty, otx, oty; otx = obj->ox; oty = obj->oy; do { tx = rn1(COLNO-3,2); ty = rn2(ROWNO); } while(!goodpos(tx,ty,(struct permonst *)0)); move_object(obj, tx, ty); if(cansee(otx,oty)) newsym(otx,oty); if(cansee(tx,ty)) newsym(tx,ty); } void fracture_rock(obj) /* fractured by pick-axe or wand of striking */ register struct obj *obj; /* no texts here! */ { /* unpobj(obj); */ obj->otyp = ROCK; obj->quan = 7 + rn2(60); obj->owt = weight(obj); obj->olet = GEM_SYM; obj->known = FALSE; if(cansee(obj->ox,obj->oy)) prl(obj->ox,obj->oy); } boolean break_statue(obj) register struct obj *obj; { struct trap *trap; if(trap = t_at(obj->ox,obj->oy)) if(obj->corpsenm == trap->pm) if(makemon(&mons[trap->pm], obj->ox, obj->oy)) { pline("Instead of shattering, the statue suddenly comes alive!"); delobj(obj); deltrap(trap); return FALSE; } if (obj->spe) { struct obj *magazine; #ifdef SPELLS magazine = mkobj_at(SPBOOK_SYM, obj->ox, obj->oy); #else magazine = mkobj_at(SCROLL_SYM, obj->ox, obj->oy); #endif magazine->blessed = obj->blessed; magazine->cursed = obj->cursed; } fracture_rock(obj); return TRUE; } const char *destroy_strings[] = { "freezes and shatters", "freeze and shatter", "shattered potion", "boils and explodes", "boil and explode", "boiling potion", "catches fire and burns", "catch fire and burn", "burning scroll", "catches fire and burns", "catch fire and burn", "burning book", "turns to dust and vanishes", "turn to dust and vanish", "", "breaks apart and explodes", "break apart and explode", "exploding wand" }; void destroy_item(osym, dmgtyp) register int osym, dmgtyp; { register struct obj *obj, *obj2; register int quan, i, cnt, dmg, xresist, skip; register int dindx; const char *mult; for(obj = invent; obj; obj = obj2) { obj2 = obj->nobj; if(obj->olet != osym) continue; /* test only objs of type osym */ xresist = skip = 0; #ifdef __GNULINT__ quan = dmg = dindx = 0; #endif switch(dmgtyp) { case AD_COLD: if(osym == POTION_SYM) { quan = obj->quan; dindx = 0; dmg = rnd(4); } else skip++; break; case AD_FIRE: xresist = (Fire_resistance && obj->olet != POTION_SYM); if (obj->otyp == SCR_FIRE #ifdef SPELLS || obj->otyp == SPE_FIREBALL #endif ) skip++; quan = obj->quan; switch(osym) { case POTION_SYM: dindx = 1; dmg = rnd(6); break; case SCROLL_SYM: dindx = 2; dmg = 1; break; #ifdef SPELLS case SPBOOK_SYM: dindx = 3; dmg = 1; break; #endif default: skip++; break; } break; case AD_ELEC: xresist = (Shock_resistance && obj->olet != RING_SYM); quan = obj->quan; switch(osym) { case RING_SYM: if(obj->otyp == RIN_SHOCK_RESISTANCE) { skip++; break; } dindx = 4; dmg = 0; break; case WAND_SYM: if(obj->otyp == WAN_LIGHTNING) { skip++; break; } dindx = 5; dmg = rnd(10); break; default: skip++; break; } break; default: skip++; break; } if(!skip) { for(i = cnt = 0; i < quan; i++) if(!rn2(3)) cnt++; if(!cnt) continue; if(cnt == quan) mult = "Your"; else mult = (cnt == 1) ? "One of your" : "Some of your"; pline("%s %s %s!", mult, xname(obj), (cnt > 1) ? destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]); if(osym == POTION_SYM && dmgtyp != AD_COLD) potionbreathe(obj); for(i = 0; i < cnt; i++) useup(obj); if(dmg) { if(xresist) You("aren't hurt!"); else losehp(dmg, (cnt==1) ? destroy_strings[dindx*3 + 2] : (const char *)makeplural(destroy_strings[dindx*3 + 2]), (cnt==1) ? KILLED_BY_AN : KILLED_BY); } } } return; } int destroy_mitem(mtmp, osym, dmgtyp) register struct monst *mtmp; register int osym, dmgtyp; { register struct obj *obj, *obj2; register int quan, i, cnt, skip, tmp = 0; register int dindx; for(obj = mtmp->minvent; obj; obj = obj2) { obj2 = obj->nobj; if(obj->olet != osym) continue; /* test only objs of type osym */ skip = 0; #ifdef __GNULINT__ quan = dindx = 0; #endif switch(dmgtyp) { case AD_COLD: if(osym == POTION_SYM) { quan = obj->quan; dindx = 0; tmp++; } else skip++; break; case AD_FIRE: if (obj->otyp == SCR_FIRE #ifdef SPELLS || obj->otyp == SPE_FIREBALL #endif ) skip++; quan = obj->quan; switch(osym) { case POTION_SYM: dindx = 1; tmp++; break; case SCROLL_SYM: dindx = 2; tmp++; break; #ifdef SPELLS case SPBOOK_SYM: dindx = 3; tmp++; break; #endif default: skip++; break; } break; case AD_ELEC: quan = obj->quan; switch(osym) { case RING_SYM: if(obj->otyp == RIN_SHOCK_RESISTANCE) { skip++; break; } dindx = 4; break; case WAND_SYM: if(obj->otyp == WAN_LIGHTNING) { skip++; break; } dindx = 5; tmp++; break; default: skip++; break; } break; default: skip++; break; } if(!skip) { for(i = cnt = 0; i < quan; i++) if(!rn2(3)) cnt++; if(!cnt) continue; pline("%s's %s %s!", Monnam(mtmp), xname(obj), (cnt > 1) ? destroy_strings[dindx*3 + 1] : destroy_strings[dindx*3]); for(i = 0; i < cnt; i++) m_useup(mtmp, obj); } } return(tmp); } /*ARGSUSED*/ int resist(mtmp, olet, damage, tell) register struct monst *mtmp; register char olet; register int damage, tell; { register int resisted = 0; #ifdef HARD register int lev; switch(olet) { case WAND_SYM: lev = 8; break; case SCROLL_SYM: lev = 6; break; case POTION_SYM: lev = 5; break; default: lev = u.ulevel; break; } resisted = (rn2(100) - mtmp->m_lev + lev) < mtmp->data->mr; if(resisted) { if(tell) { shieldeff(mtmp->mx, mtmp->my); pline("%s resists!", canseemon(mtmp) ? Monnam(mtmp) : "It"); } mtmp->mhp -= damage/2; } else #endif mtmp->mhp -= damage; if(mtmp->mhp < 1) killed(mtmp); return(resisted); } void makewish() { char buf[BUFSZ]; register struct obj *otmp; int wishquan, mergquan; register boolean dropit = (inv_cnt() >= 52); int tries = 0; retry: You("may wish for an object. What do you want? "); getlin(buf); if(buf[0] == '\033') buf[0] = 0; /* Note: if they wished for and got a non-object successfully, such as gold, * otmp = &zeroobj */ otmp = readobjnam(buf); if (!otmp) { pline("Nothing fitting that description exists in the game."); if (++tries < 5) goto retry; pline(thats_enough_tries); if (!(otmp = readobjnam((char *)0))) return; /* for safety; should never happen */ } if (otmp != &zeroobj) { if(dropit) { pline("Oops! The %s to the floor!", aobjnam(otmp, "drop")); dropy(otmp); } else { wishquan = otmp->quan; otmp = addinv(otmp); mergquan = otmp->quan; otmp->quan = wishquan; /* to fool prinv() */ prinv(otmp); otmp->quan = mergquan; } #ifdef THEOLOGY u.ublesscnt += rn1(100,50); /* the gods take notice */ #endif } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.