home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
games
/
volume7
/
nethack3
/
part02
< prev
next >
Wrap
Internet Message Format
|
1989-07-31
|
56KB
Path: uunet!zephyr.ens.tek.com!tektronix!tekgen!tekred!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v07i057: NetHack3 - display oriented dungeons & dragons (Ver. 3.0), Part02/38
Message-ID: <4331@tekred.CNA.TEK.COM>
Date: 24 Jul 89 19:00:56 GMT
Sender: nobody@tekred.CNA.TEK.COM
Lines: 2269
Approved: billr@saab.CNA.TEK.COM
Submitted-by: Izchak Miller <izchak@linc.cis.upenn.edu>
Posting-number: Volume 7, Issue 57
Archive-name: NetHack3/Part02
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 2 (of 38)."
# Contents: src/o_init.c src/zap.c
# Wrapped by billr@saab on Sun Jul 23 21:32:46 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/o_init.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/o_init.c'\"
else
echo shar: Extracting \"'src/o_init.c'\" \(7223 characters\)
sed "s/^X//" >'src/o_init.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)o_init.c 3.0 88/07/06
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h" /* for typedefs */
X
X/* note that NROFOBJECTS is the number of legal objects, which does not count
X * the strange object and null object that take up positions 0 and NROFOBJECTS+1
X * in the objects array
X */
X#define TOTAL_OBJS (NROFOBJECTS+2)
X
Xconst char obj_symbols[] = {
X ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,
X BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM,
X POTION_SYM, SCROLL_SYM, WAND_SYM,
X#ifdef SPELLS
X SPBOOK_SYM,
X#endif
X RING_SYM, GEM_SYM, 0 };
X
Xint bases[sizeof(obj_symbols)] = DUMMY;
Xstatic int disco[TOTAL_OBJS] = DUMMY;
X
Xint
Xletindex(let) register char let; {
Xregister int i = 0;
Xregister char ch;
X while((ch = obj_symbols[i++]) != 0)
X if(ch == let) return(i);
X return(0);
X}
X
Xstatic void
Xsetgemprobs()
X{
X register int j,first;
X#ifdef STRONGHOLD
X int level = (dlevel > MAXLEVEL) ? MAXLEVEL : dlevel;
X#endif
X
X first = bases[letindex(GEM_SYM)];
X
X#ifdef STRONGHOLD
X for(j = 0; j < 9-level/3; j++)
X#else
X for(j = 0; j < 9-dlevel/3; j++)
X#endif
X objects[first+j].oc_prob = 0;
X first += j;
X if(first >= LAST_GEM || first > NROFOBJECTS ||
X objects[first].oc_olet != GEM_SYM ||
X objects[first].oc_name == NULL)
X Printf("Not enough gems? - first=%d j=%d LAST_GEM=%d\n",
X first, j, LAST_GEM);
X for(j = first; j < LAST_GEM; j++)
X objects[j].oc_prob = (180+j-first)/(LAST_GEM-first);
X}
X
X/* shuffle descriptions on objects o_low to o_high */
Xstatic void
Xshuffle(o_low, o_high, domaterial)
X
X register int o_low, o_high;
X register boolean domaterial;
X{
X register int i, j;
X char *desc;
X int tmp;
X
X for(j=o_low; j <= o_high; j++) {
X i = o_low + rn2(j+1-o_low);
X desc = objects[j].oc_descr;
X objects[j].oc_descr = objects[i].oc_descr;
X objects[i].oc_descr = desc;
X /* shuffle discovery list */
X tmp = disco[j];
X disco[j] = disco[i];
X disco[i] = tmp;
X /* shuffle material */
X if(domaterial) {
X tmp = objects[j].oc_material;
X objects[j].oc_material = objects[i].oc_material;
X objects[i].oc_material = tmp;
X }
X }
X}
X
Xvoid
Xinit_objects(){
Xregister int i, j, first, last, sum, end;
Xregister char let;
X
X /* bug fix to prevent "initialization error" abort on Intel Xenix.
X * reported by mikew@semike
X */
X for(i = 0; i != sizeof(obj_symbols); i++)
X bases[i] = 0;
X for(i = 0; i != TOTAL_OBJS; i++)
X disco[i] = i;
X
X /* init base; if probs given check that they add up to 1000,
X otherwise compute probs; shuffle descriptions */
X end = TOTAL_OBJS;
X first = 0;
X while( first < end ) {
X let = objects[first].oc_olet;
X last = first+1;
X while(last < end && objects[last].oc_olet == let
X && objects[last].oc_name != NULL) last++;
X i = letindex(let);
X if((!i && let != ILLOBJ_SYM && let != '.') || bases[i] != 0)
X error("initialization error for %c", let);
X bases[i] = first;
X
X if(let == GEM_SYM) setgemprobs();
X check:
X sum = 0;
X for(j = first; j < last; j++) sum += objects[j].oc_prob;
X if(sum == 0) {
X for(j = first; j < last; j++)
X objects[j].oc_prob = (1000+j-first)/(last-first);
X goto check;
X }
X if(sum != 1000)
X error("init-prob error for %c (%d%%)", let, sum);
X
X if(objects[first].oc_descr != NULL &&
X let != TOOL_SYM && let != WEAPON_SYM && let != ARMOR_SYM) {
X
X /* shuffle, also some additional descriptions */
X while(last < end && objects[last].oc_olet == let)
X last++;
X j = last;
X if (let == GEM_SYM) {
X while(--j > first)
X /* NOTE: longest color name must be default */
X if(!strcmp(objects[j].oc_name,"turquoise")) {
X if(rn2(2)) /* change from green? */
X Strcpy(objects[j].oc_descr, blue);
X } else if (!strcmp(objects[j].oc_name,"aquamarine")) {
X if(rn2(2)) /* change from green? */
X Strcpy(objects[j].oc_descr, blue);
X } else if (!strcmp(objects[j].oc_name,"fluorite")) {
X switch (rn2(4)) { /* change from violet? */
X case 0: break;
X case 1:
X Strcpy(objects[j].oc_descr, blue);
X break;
X case 2:
X Strcpy(objects[j].oc_descr, white);
X break;
X case 3:
X Strcpy(objects[j].oc_descr, green);
X break;
X }
X }
X } else {
X if (let == AMULET_SYM || let == POTION_SYM)
X j--; /* THE amulet doesn't have description */
X /* and water is always "clear" - 3. */
X shuffle(first, --j, TRUE);
X }
X }
X first = last;
X }
X
X /* shuffle the helmets */
X shuffle(HELMET, HELM_OF_TELEPATHY, FALSE);
X
X /* shuffle the gloves */
X shuffle(LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY, FALSE);
X
X /* shuffle the cloaks */
X shuffle(CLOAK_OF_PROTECTION, CLOAK_OF_DISPLACEMENT, FALSE);
X
X /* shuffle the boots */
X shuffle(SPEED_BOOTS, LEVITATION_BOOTS, FALSE);
X}
X
Xvoid
Xoinit() /* level dependent initialization */
X{
X setgemprobs();
X}
X
Xvoid
Xsavenames(fd)
Xregister int fd;
X{
X register int i;
X unsigned int len;
X struct objclass *now = &objects[0];
X bwrite(fd, (genericptr_t)&now, sizeof now);
X bwrite(fd, (genericptr_t)bases, sizeof bases);
X bwrite(fd, (genericptr_t)disco, sizeof disco);
X bwrite(fd, (genericptr_t)objects, sizeof(struct objclass) * TOTAL_OBJS);
X /* as long as we use only one version of Hack we
X need not save oc_name and oc_descr, but we must save
X oc_uname for all objects */
X for(i=0; i < TOTAL_OBJS; i++) {
X if(objects[i].oc_uname) {
X len = strlen(objects[i].oc_uname)+1;
X bwrite(fd, (genericptr_t)&len, sizeof len);
X bwrite(fd, (genericptr_t)objects[i].oc_uname, len);
X }
X }
X}
X
Xvoid
Xrestnames(fd)
Xregister int fd;
X{
X register int i;
X unsigned int len;
X struct objclass *then;
X long differ;
X mread(fd, (genericptr_t) &then, sizeof then);
X mread(fd, (genericptr_t) bases, sizeof bases);
X mread(fd, (genericptr_t) disco, sizeof disco);
X mread(fd, (genericptr_t) objects, sizeof(struct objclass) * TOTAL_OBJS);
X#ifndef MSDOS
X differ = (genericptr_t)&objects[0] - (genericptr_t)then;
X#else
X differ = (long)&objects[0] - (long)then;
X#endif
X for(i=0; i < TOTAL_OBJS; i++) {
X if (objects[i].oc_name) {
X#ifndef MSDOS
X objects[i].oc_name += differ;
X#else
X objects[i].oc_name =
X (char *)((long)(objects[i].oc_name) + differ);
X#endif
X }
X if (objects[i].oc_descr) {
X#ifndef MSDOS
X objects[i].oc_descr += differ;
X#else
X objects[i].oc_descr =
X (char *)((long)(objects[i].oc_descr) + differ);
X#endif
X }
X if (objects[i].oc_uname) {
X mread(fd, (genericptr_t) &len, sizeof len);
X objects[i].oc_uname = (char *) alloc(len);
X mread(fd, (genericptr_t)objects[i].oc_uname, len);
X }
X }
X}
X
Xstatic boolean
Xinteresting_to_discover(i)
Xregister int i;
X{
X return objects[i].oc_uname != NULL ||
X (objects[i].oc_name_known && objects[i].oc_descr != NULL);
X}
X
Xint
Xdodiscovered() /* free after Robert Viduya */
X{
X register int i, dis;
X int ct = 0;
X char class = -1;
X
X cornline(0, "Discoveries");
X
X for (i = 0; i <= NROFOBJECTS; i++) {
X if (interesting_to_discover(dis = disco[i])) {
X ct++;
X if (objects[dis].oc_olet != class) {
X class = objects[dis].oc_olet;
X cornline(1, let_to_name(class));
X }
X cornline(1, typename(dis));
X }
X }
X if (ct == 0) {
X You("haven't discovered anything yet...");
X cornline(3, NULL);
X } else
X cornline(2, NULL);
X
X return 0;
X}
END_OF_FILE
if test 7223 -ne `wc -c <'src/o_init.c'`; then
echo shar: \"'src/o_init.c'\" unpacked with wrong size!
fi
# end of 'src/o_init.c'
fi
if test -f 'src/zap.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/zap.c'\"
else
echo shar: Extracting \"'src/zap.c'\" \(44087 characters\)
sed "s/^X//" >'src/zap.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)zap.c 3.0 88/10/25
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X
X#if defined(ALTARS) && defined(THEOLOGY)
Xstatic boolean priesthit = FALSE;
X#endif
X
Xconst char *fl[]= {
X "magic missile", /* Wands must be 0-9 */
X "bolt of fire",
X "sleep ray",
X "bolt of cold",
X "death ray",
X "bolt of lightning",
X "",
X "",
X "",
X "",
X
X "magic missile", /* Spell equivalents must be 10-19 */
X "fireball",
X "sleep ray",
X "cone of cold",
X "finger of death",
X "bolt of lightning",
X "",
X "",
X "",
X "",
X
X "blast of missiles", /* Dragon breath equivalents 20-29*/
X "blast of fire",
X "blast of sleeping gas",
X "blast of frost",
X "blast of disintegration",
X "blast of lightning",
X "blast of poison gas",
X "blast of acid",
X "",
X ""
X};
X
X/* Routines for IMMEDIATE wands and spells. */
X/* bhitm: monster mtmp was hit by the effect of wand or spell otmp */
Xstatic int
Xbhitm(mtmp, otmp)
Xregister struct monst *mtmp;
Xregister struct obj *otmp;
X{
X wakeup(mtmp);
X switch(otmp->otyp) {
X case WAN_STRIKING:
X#ifdef SPELLS
X case SPE_FORCE_BOLT:
X#endif
X if(u.uswallow || rnd(20) < 10+mtmp->data->ac) {
X register int tmp = d(2,12);
X hit((otmp->otyp == WAN_STRIKING) ? "wand" : "spell", mtmp, exclam(tmp));
X (void) resist(mtmp, otmp->olet, tmp, TELL);
X } else miss((otmp->otyp == WAN_STRIKING) ? "wand" : "spell", mtmp);
X break;
X case WAN_SLOW_MONSTER:
X#ifdef SPELLS
X case SPE_SLOW_MONSTER:
X#endif
X if(! resist(mtmp, otmp->olet, 0, NOTELL))
X if (mtmp->mspeed == MFAST) mtmp->mspeed = 0;
X else mtmp->mspeed = MSLOW;
X break;
X case WAN_SPEED_MONSTER:
X if (!resist(mtmp, otmp->olet, 0, NOTELL))
X if (mtmp->mspeed == MSLOW) mtmp->mspeed = 0;
X else mtmp->mspeed = MFAST;
X break;
X case WAN_UNDEAD_TURNING:
X#ifdef SPELLS
X case SPE_TURN_UNDEAD:
X#endif
X if(is_undead(mtmp->data)) {
X
X if(!resist(mtmp, otmp->olet, rnd(8), NOTELL))
X mtmp->mflee = 1;
X }
X break;
X case WAN_POLYMORPH:
X#ifdef SPELLS
X case SPE_POLYMORPH:
X#endif
X if(!resist(mtmp, otmp->olet, 0, NOTELL))
X if( newcham(mtmp, (struct permonst *)0) )
X if (!Hallucination)
X makeknown(otmp->otyp);
X break;
X case WAN_CANCELLATION:
X#ifdef SPELLS
X case SPE_CANCELLATION:
X#endif
X if(!resist(mtmp, otmp->olet, 0, NOTELL)) {
X if (is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
X were_change(mtmp);
X#ifdef GOLEMS
X if (mtmp->data == &mons[PM_CLAY_GOLEM]) {
X if (!Blind)
X pline("Some writing vanishes from %s's head!",
X mon_nam(mtmp));
X killed(mtmp);
X }
X else
X#endif /* GOLEMS */
X mtmp->mcan = 1;
X }
X break;
X case WAN_TELEPORTATION:
X#ifdef SPELLS
X case SPE_TELEPORT_AWAY:
X#endif
X#if defined(ALTARS) && defined(THEOLOGY)
X if(mtmp->ispriest && in_temple(mtmp->mx, mtmp->my)) {
X kludge("%s resists your magic!", Monnam(mtmp));
X wakeup(mtmp);
X break;
X }
X#endif
X rloc(mtmp);
X break;
X case WAN_MAKE_INVISIBLE:
X mtmp->minvis = 1;
X break;
X case WAN_NOTHING:
X break;
X#ifdef PROBING
X case WAN_PROBING:
X makeknown(otmp->otyp);
X mstatusline(mtmp);
X break;
X#endif
X case WAN_OPENING:
X case WAN_LOCKING:
X#ifdef SPELLS
X case SPE_KNOCK:
X case SPE_WIZARD_LOCK:
X#endif
X break;
X default:
X impossible("What an interesting effect (%u)", otmp->otyp);
X }
X return 0;
X}
X
Xstruct monst *
Xrevive(obj,ininv)
Xregister struct obj *obj;
Xboolean ininv;
X{
X register struct monst *mtmp;
X
X if(obj->otyp == CORPSE) {
X int montype,x,y,nl;
X char buf[BUFSZ];
X
X if (nl = obj->onamelth) Strcpy(buf, ONAME(obj));
X montype = obj->corpsenm;
X if (ininv) {
X x = u.ux; y = u.uy;
X useup(obj);
X } else {
X x = obj->ox; y = obj->oy;
X useupf(obj);
X }
X if (cant_create(&montype)) { /* will make zombie instead */
X mtmp = makemon(&mons[PM_HUMAN_ZOMBIE], x, y);
X if (mtmp) {
X mtmp->mhp = mtmp->mhpmax = 100;
X mtmp->mspeed = MFAST;
X }
X } else {
X#ifdef ARMY
X if (is_mercenary(&mons[montype]))
X montype = PM_UNARMORED_SOLDIER;
X#endif
X mons[montype].pxlth += nl;
X mtmp = mkmon_at(mons[montype].mname, x, y);
X mons[montype].pxlth -= nl;
X if (mtmp) {
X /* Monster retains its name */
X mtmp->mnamelth = nl;
X if (nl) Strcpy(NAME(mtmp), buf);
X /* No inventory for newly revived monsters */
X while(obj = (mtmp->minvent)) {
X mtmp->minvent = obj->nobj;
X free((genericptr_t)obj);
X }
X }
X }
X }
X return mtmp;
X}
X
Xstatic const char charged_objs[] = { WAND_SYM, WEAPON_SYM, ARMOR_SYM, 0 };
X
Xstatic void
Xcancel_item(obj)
Xregister struct obj *obj;
X{
X if(obj->spe &&
X !(obj->otyp == AMULET_OF_YENDOR ||
X obj->otyp == WAN_CANCELLATION || /* can't cancel cancellation */
X obj->otyp == TIN || obj->otyp == EGG ||
X obj->otyp == STATUE ||
X#ifdef MAIL
X obj->otyp == SCR_MAIL ||
X#endif
X obj->otyp == KEY || obj->otyp == SKELETON_KEY ||
X obj->otyp == LARGE_BOX || obj->otyp == CHEST))
X obj->spe = (obj->olet == WAND_SYM) ? -1 : 0;
X if (obj->olet == SCROLL_SYM
X#ifdef MAIL
X && obj->otyp != SCR_MAIL
X#endif
X )
X obj->otyp = SCR_BLANK_PAPER;
X if (obj->olet == POTION_SYM && obj->otyp > POT_BOOZE)
X obj->otyp = (obj->otyp==POT_SICKNESS) ? POT_FRUIT_JUICE : POT_WATER;
X /* sickness is "biologically contaminated" fruit juice; cancel it
X * and it just becomes fruit juice...
X */
X obj->blessed = obj->cursed = FALSE;
X}
X
Xstatic int
Xbhito(obj, otmp) /* object obj was hit by the effect of wand otmp */
Xregister struct obj *obj, *otmp; /* returns TRUE if sth was done */
X{
X register int res = 1;
X struct obj *otmp2;
X
X if(obj == uball || obj == uchain)
X res = 0;
X else
X switch(otmp->otyp) {
X case WAN_POLYMORPH:
X#ifdef SPELLS
X case SPE_POLYMORPH:
X#endif
X#ifdef MAIL
X /* You can't send yourself 100 mail messages and then
X * polymorph them into useful scrolls
X */
X if (obj->otyp == SCR_MAIL) obj->spe = 1;
X#endif
X /* preserve symbol and quantity */
X otmp2 = mkobj_at(obj->olet, obj->ox, obj->oy);
X otmp2->quan = obj->quan;
X
X /* keep special fields (including charges on wands) */
X if (index(charged_objs, otmp2->olet)) otmp2->spe = obj->spe;
X
X /* Amulet gets cheap stewr 870807 */
X if (obj->otyp == AMULET_OF_YENDOR) otmp2->spe = -1;
X
X /* Wands of wishing max 3 stewr 870808 */
X if ((otmp2->otyp == WAN_WISHING)
X && (obj->spe > 3)) otmp2->spe = 3;
X
X otmp2->cursed = obj->cursed;
X otmp2->blessed = obj->blessed;
X otmp2->rustfree = obj->rustfree;
X
X /* Keep chest/box traps and poisoned ammo if we may */
X if (obj->otrapped && Is_box(otmp2))
X otmp2->otrapped = 1;
X if (obj->opoisoned &&
X (otmp2->olet == WEAPON_SYM && otmp2->otyp <= SHURIKEN))
X otmp2->opoisoned = 1;
X
X /* Turn dragon corpses into dragon armors */
X if (obj->otyp == CORPSE && obj->corpsenm >= PM_GREY_DRAGON
X && obj->corpsenm <= PM_YELLOW_DRAGON) {
X if (!rn2(10)) { /* Random failure */
X otmp2->otyp = TIN;
X otmp2->known = otmp2->dknown = 1;
X } else {
X otmp2->otyp = DRAGON_SCALE_MAIL;
X otmp2->olet = ARMOR_SYM;
X otmp2->spe = 0;
X otmp2->rustfree = 1;
X otmp2->quan = 1;
X otmp2->cursed = 0;
X }
X otmp2->corpsenm = obj->corpsenm;
X }
X
X /* update the weight */
X otmp2->owt = weight(otmp2);
X delobj(obj);
X break;
X case WAN_STRIKING:
X#ifdef SPELLS
X case SPE_FORCE_BOLT:
X#endif
X if(obj->otyp == BOULDER)
X fracture_rock(obj);
X else if(obj->otyp == STATUE)
X (void) break_statue(obj);
X else
X res = 0;
X break;
X case WAN_CANCELLATION:
X#ifdef SPELLS
X case SPE_CANCELLATION:
X#endif
X cancel_item(obj);
X break;
X case WAN_TELEPORTATION:
X#ifdef SPELLS
X case SPE_TELEPORT_AWAY:
X#endif
X rloco(obj);
X break;
X case WAN_MAKE_INVISIBLE:
X obj->oinvis = 1;
X break;
X case WAN_UNDEAD_TURNING:
X#ifdef SPELLS
X case SPE_TURN_UNDEAD:
X#endif
X res = !!revive(obj,FALSE);
X break;
X case WAN_OPENING:
X case WAN_LOCKING:
X#ifdef SPELLS
X case SPE_KNOCK:
X case SPE_WIZARD_LOCK:
X#endif
X if(Is_box(obj))
X res = boxlock(obj, otmp);
X else
X res = 0;
X if (res /* && obj->olet == WAND_SYM */)
X makeknown(obj->otyp);
X break;
X case WAN_SLOW_MONSTER: /* no effect on objects */
X#ifdef SPELLS
X case SPE_SLOW_MONSTER:
X#endif
X case WAN_SPEED_MONSTER:
X case WAN_NOTHING:
X#ifdef PROBING
X case WAN_PROBING:
X#endif
X res = 0;
X break;
X default:
X impossible("What an interesting effect (%u)", otmp->otyp);
X }
X return(res);
X}
X
X/*
X * zappable - returns 1 if zap is available, 0 otherwise.
X * it removes a charge from the wand if zappable.
X * added by GAN 11/03/86
X */
Xint
Xzappable(wand)
Xregister struct obj *wand;
X{
X if(wand->spe < 0 || (wand->spe == 0 && rn2(121)))
X return 0;
X if(wand->spe == 0)
X You("wrest one more spell from the worn-out wand.");
X wand->spe--;
X return 1;
X}
X
X/*
X * zapnodir - zaps an NODIR wand.
X * added by GAN 11/03/86
X */
Xvoid
Xzapnodir(wand)
Xregister struct obj *wand;
X{
X switch(wand->otyp){
X case WAN_LIGHT:
X litroom(TRUE);
X break;
X case WAN_SECRET_DOOR_DETECTION:
X if(!findit()) return;
X break;
X case WAN_CREATE_MONSTER:
X { register int cnt = 1;
X if(!rn2(23)) cnt += rn2(7) + 1;
X while(cnt--)
X (void) makemon((struct permonst *) 0, u.ux, u.uy);
X }
X break;
X case WAN_WISHING:
X
X if(u.uluck + rn2(5) < 0) {
X pline("Unfortunately, nothing happens.");
X break;
X }
X makewish();
X break;
X }
X if(!objects[wand->otyp].oc_name_known) {
X makeknown(wand->otyp);
X more_experienced(0,10);
X }
X}
X
Xstatic void
Xbackfire(otmp)
X
X register struct obj * otmp;
X{
X pline("The %s suddenly explodes!", xname(otmp));
X losehp(d(otmp->spe+2,6), "exploding wand");
X useup(otmp);
X}
X
Xstatic const char zap_syms[] = { WAND_SYM, 0 };
X
Xint
Xdozap()
X{
X register struct obj *obj;
X int damage;
X
X obj = getobj(zap_syms, "zap");
X if(!obj) return(0);
X
X check_unpaid(obj);
X
X /* zappable addition done by GAN 11/03/86 */
X if(!zappable(obj)) pline(nothing_happens);
X else if(obj->cursed && !rn2(100)) {
X backfire(obj); /* the wand blows up in your face! */
X return(1);
X } else if(!(objects[obj->otyp].bits & NODIR) && !getdir(1)) {
X if (!Blind)
X pline("The %s glows and fades.", xname(obj));
X /* make him pay for knowing !NODIR */
X } else if(!u.dx && !u.dy && !u.dz && !(objects[obj->otyp].bits & NODIR)) {
X if((damage = zapyourself(obj)))
X losehp(damage,"self-inflicted injury");
X }
X else {
X weffects(obj);
X#if defined(ALTARS) && defined(THEOLOGY)
X if(priesthit) ghod_hitsu();
X priesthit = FALSE;
X#endif
X }
X if (obj->spe < 0) {
X pline ("The %s %sturns to dust.",
X xname(obj), Blind ? "" : "glows violently, then ");
X useup(obj);
X }
X return(1);
X}
X
Xint
Xzapyourself(obj)
X register struct obj *obj;
X{
X struct obj *otmp;
X int damage = 0;
X
X switch(obj->otyp) {
X case WAN_STRIKING:
X#ifdef SPELLS
X case SPE_FORCE_BOLT:
X#endif
X if(Antimagic) {
X shieldeff(u.ux, u.uy);
X pline("Boing!");
X } else {
X You("magically bash yourself!");
X damage=d(8,6);
X }
X break;
X case WAN_LIGHTNING:
X makeknown(WAN_LIGHTNING);
X if (!Shock_resistance) {
X pline("Idiot! You've shocked yourself!");
X damage = d(12,6);
X } else {
X shieldeff(u.ux, u.uy);
X You("zap yourself, but seem unharmed.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X ugolemeffects(AD_ELEC, d(12,6));
X#endif /* GOLEMS */
X#endif
X }
X if(!Blind) {
X You("are blinded by the flash!");
X make_blinded((long)rnd(100),FALSE);
X }
X break;
X case WAN_FIRE:
X makeknown(WAN_FIRE);
X#ifdef SPELLS
X case SPE_FIREBALL:
X#endif
X#ifdef MUSIC
X case FIRE_HORN:
X#endif
X pline("You've set light to yourself!");
X if (Fire_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel mildly hot.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X ugolemeffects(AD_FIRE, d(12,6));
X#endif /* GOLEMS */
X#endif
X } else
X damage = d(12,6);
X destroy_item(SCROLL_SYM, AD_FIRE);
X destroy_item(POTION_SYM, AD_FIRE);
X#ifdef SPELLS
X destroy_item(SPBOOK_SYM, AD_FIRE);
X#endif
X break;
X case WAN_COLD:
X makeknown(WAN_COLD);
X#ifdef SPELLS
X case SPE_CONE_OF_COLD:
X#endif
X#ifdef MUSIC
X case FROST_HORN:
X#endif
X if (Cold_resistance) {
X shieldeff(u.ux, u.uy);
X You("feel mildly chilly.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X ugolemeffects(AD_COLD, d(12,6));
X#endif /* GOLEMS */
X#endif
X } else {
X You("imitate a popsicle!");
X damage = d(12,6);
X }
X destroy_item(POTION_SYM, AD_COLD);
X break;
X case WAN_MAGIC_MISSILE:
X makeknown(WAN_MAGIC_MISSILE);
X#ifdef SPELLS
X case SPE_MAGIC_MISSILE:
X#endif
X if(Antimagic) {
X shieldeff(u.ux, u.uy);
X pline("The missiles bounce!");
X } else {
X damage = d(4,6);
X pline("Idiot! You've shot yourself!");
X }
X break;
X case WAN_POLYMORPH:
X#ifdef POLYSELF
X makeknown(WAN_POLYMORPH);
X#endif
X#ifdef SPELLS
X case SPE_POLYMORPH:
X#endif
X#ifdef POLYSELF
X polyself();
X#else
X You("shudder for a moment.");
X#endif
X break;
X case WAN_CANCELLATION:
X#ifdef SPELLS
X case SPE_CANCELLATION:
X#endif
X#ifdef POLYSELF
X#ifdef GOLEMS
X if (u.umonnum == PM_CLAY_GOLEM) {
X if (!Blind)
X pline("Some writing vanishes from your head!");
X rehumanize();
X break;
X }
X#endif /* GOLEMS */
X#endif
X for(otmp = invent; otmp; otmp = otmp->nobj)
X cancel_item(otmp);
X#ifdef POLYSELF
X if(u.mtimedone) rehumanize();
X#endif
X flags.botl = 1; /* because of potential AC change */
X find_ac();
X break;
X case WAN_MAKE_INVISIBLE:
X if (!Invisible) makeknown(WAN_MAKE_INVISIBLE);
X HInvis |= INTRINSIC;
X if (!See_invisible) newsym(u.ux, u.uy);
X break;
X case WAN_SPEED_MONSTER:
X if (!(Fast & INTRINSIC)) {
X Fast |= INTRINSIC;
X You("seem to be moving faster.");
X makeknown(WAN_SPEED_MONSTER);
X }
X break;
X case WAN_SLEEP:
X makeknown(WAN_SLEEP);
X#ifdef SPELLS
X case SPE_SLEEP:
X#endif
X if(Sleep_resistance) {
X shieldeff(u.ux, u.uy);
X You("don't feel sleepy!");
X } else {
X pline("The sleep ray hits you!");
X nomul(-rn2(50));
X }
X break;
X case WAN_SLOW_MONSTER:
X#ifdef SPELLS
X case SPE_SLOW_MONSTER:
X#endif
X if(Fast & (TIMEOUT | INTRINSIC)) {
X Fast &= ~(TIMEOUT | INTRINSIC);
X You("seem to be moving slower.");
X }
X break;
X case WAN_TELEPORTATION:
X#ifdef SPELLS
X case SPE_TELEPORT_AWAY:
X#endif
X tele();
X break;
X case WAN_DEATH:
X#ifdef SPELLS
X case SPE_FINGER_OF_DEATH:
X#endif
X#ifdef POLYSELF
X if (is_undead(uasmon)) {
X pline((obj->otyp == WAN_DEATH) ?
X "The wand shoots an apparently harmless beam at you."
X : "You seem no deader than before.");
X break;
X }
X#endif
X killer = "death ray";
X You("irradiate yourself with pure energy!");
X You("die.");
X makeknown(WAN_DEATH);
X /* They might survive with an amulet of life saving */
X done("died");
X break;
X#ifdef SPELLS
X case SPE_TURN_UNDEAD:
X#endif
X case WAN_UNDEAD_TURNING:
X#ifdef POLYSELF
X if (is_undead(uasmon)) {
X Printf("You feel frightened and %sstunned.",
X Stunned ? "even more " : "");
X make_stunned(HStun + rnd(30), FALSE);
X }
X#endif
X break;
X#ifdef SPELLS
X case SPE_DIG:
X case SPE_DETECT_UNSEEN:
X#endif
X case WAN_DIGGING:
X case WAN_NOTHING:
X case WAN_OPENING:
X case WAN_LOCKING:
X#ifdef SPELLS
X case SPE_KNOCK:
X case SPE_WIZARD_LOCK:
X#endif
X break;
X#ifdef PROBING
X case WAN_PROBING:
X makeknown(WAN_PROBING);
X ustatusline();
X break;
X#endif
X default: impossible("object %d used?",obj->otyp);
X }
X return(damage);
X}
X
X/* called for various wand and spell effects - M. Stephenson */
Xvoid
Xweffects(obj)
Xregister struct obj *obj;
X{
X xchar zx,zy;
X
X if(objects[obj->otyp].bits & IMMEDIATE) {
X if(u.uswallow) (void)bhitm(u.ustuck, obj);
X else if(u.dz) {
X if(u.dz > 0 && levl[u.ux][u.uy].omask) {
X register struct obj *otmp,*otmp2;
X
X /* changed by GAN to hit all objects there */
X for(otmp = fobj; otmp ; otmp = otmp2) {
X otmp2 = otmp->nobj;
X /* save pointer as bhito may destroy otmp */
X if(otmp->ox == u.ux && otmp->oy == u.uy)
X (void) bhito(otmp, obj);
X }
X }
X } else if((obj->otyp == WAN_OPENING) ||
X#ifdef SPELLS
X (obj->otyp == SPE_KNOCK) ||
X (obj->otyp == SPE_WIZARD_LOCK) ||
X#endif
X (obj->otyp == WAN_LOCKING)) {
X (void)bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj);
X#ifdef STRONGHOLD
X } else if(obj->otyp == WAN_STRIKING
X#ifdef SPELLS
X || obj->otyp == SPE_FORCE_BOLT
X#endif /* SPELLS /**/
X ) {
X int x,y;
X x = u.ux + u.dx;
X y = u.uy + u.dy;
X if (find_drawbridge(&x,&y))
X destroy_drawbridge(x,y);
X
X else (void) bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj);
X#endif /* STRONGHOLD /**/
X } else (void) bhit(u.dx,u.dy,rn1(8,6),0,bhitm,bhito,obj);
X } else {
X switch(obj->otyp){
X case WAN_LIGHT:
X#ifdef SPELLS
X case SPE_LIGHT:
X#endif
X litroom(TRUE);
X break;
X case WAN_SECRET_DOOR_DETECTION:
X#ifdef SPELLS
X case SPE_DETECT_UNSEEN:
X#endif
X if(!findit()) return;
X break;
X case WAN_CREATE_MONSTER:
X { register int cnt = 1;
X if(!rn2(23)) cnt += rn2(7) + 1;
X while(cnt--)
X (void) makemon((struct permonst *) 0, u.ux, u.uy);
X }
X break;
X case WAN_WISHING:
X if(u.uluck + rn2(5) < 0) {
X pline("Unfortunately, nothing happens.");
X break;
X }
X makewish();
X break;
X case WAN_DIGGING:
X#ifdef SPELLS
X case SPE_DIG:
X#endif
X /* Original effect (approximately):
X * from CORR: dig until we pierce a wall
X * from ROOM: piece wall and dig until we reach
X * an ACCESSIBLE place.
X * Currently: dig for digdepth positions;
X * also down on request of Lennart Augustsson.
X */
X { register struct rm *room;
X register int digdepth,dlx,dly;
X register boolean shopdoor = FALSE;
X if(u.uswallow) {
X register struct monst *mtmp = u.ustuck;
X
X You("pierce %s's stomach wall!",
X mon_nam(mtmp));
X mtmp->mhp = 1; /* almost dead */
X unstuck(mtmp);
X mnexto(mtmp);
X break;
X }
X if(u.dz) {
X if(u.dz < 0) {
X You("loosen a rock from the ceiling.");
X pline("It falls on your %s!",
X body_part(HEAD));
X losehp(1, "falling rock");
X (void) mksobj_at((int)ROCK, u.ux, u.uy);
X fobj->quan = 1;
X stackobj(fobj);
X if(Invisible) newsym(u.ux, u.uy);
X } else {
X dighole();
X }
X break;
X }
X zx = u.ux+u.dx;
X zy = u.uy+u.dy;
X digdepth = 8 + rn2(18);
X Tmp_at2(-1, '*'); /* open call */
X while(--digdepth >= 0) {
X if(!isok(zx,zy)) break;
X room = &levl[zx][zy];
X Tmp_at2(zx,zy);
X if(is_maze_lev) {
X if(IS_WALL(room->typ)) {
X if(room->diggable == W_DIGGABLE)
X room->typ = ROOM;
X else if(!Blind)
X pline("The wall glows then fades.");
X break;
X }
X if(room->typ == STONE) {
X if(room->diggable == W_DIGGABLE)
X room->typ = CORR;
X else if (!Blind)
X pline("The rock glows then fades.");
X break;
X }
X } else
X if(IS_ROCK(room->typ))
X if(may_dig(zx,zy))
X if(IS_WALL(room->typ) ||
X room->typ == SDOOR) {
X room->typ = DOOR;
X room->doormask = D_NODOOR;
X if(in_shop(zx,zy)) {
X shopdoor = TRUE;
X dlx = zx;
X dly = zy;
X }
X digdepth -= 2;
X } else {
X room->typ = CORR;
X digdepth--;
X }
X else
X break;
X else if(room->typ == DOOR &&
X (room->doormask & (D_LOCKED | D_CLOSED))) {
X room->doormask = D_NODOOR;
X if(in_shop(zx,zy)) {
X shopdoor = TRUE;
X dlx = zx;
X dly = zy;
X }
X digdepth -= 2;
X }
X mnewsym(zx,zy);
X zx += u.dx;
X zy += u.dy;
X }
X mnewsym(zx,zy); /* not always necessary */
X Tmp_at2(-1,-1); /* closing call */
X if(shopdoor && !in_shop(u.ux, u.uy))
X pay_for_door(dlx, dly, "destroy");
X break;
X }
X default:
X#ifdef SPELLS
X if((int) obj->otyp >= SPE_MAGIC_MISSILE) {
X
X buzz((int) obj->otyp - SPE_MAGIC_MISSILE + 10,
X (int)u.ulevel / 2 + 1, u.ux, u.uy, u.dx, u.dy);
X } else
X#endif
X
X buzz((int) obj->otyp - WAN_MAGIC_MISSILE, 6,
X u.ux, u.uy, u.dx, u.dy);
X break;
X }
X if(!objects[obj->otyp].oc_name_known) {
X makeknown(obj->otyp);
X more_experienced(0,10);
X }
X }
X return;
X}
X
Xchar *
Xexclam(force)
Xregister int force;
X{
X /* force == 0 occurs e.g. with sleep ray */
X /* note that large force is usual with wands so that !! would
X require information about hand/weapon/wand */
X return( (force < 0) ? "?" : (force <= 4) ? "." : "!" );
X}
X
Xvoid
Xhit(str,mtmp,force)
Xregister char *str;
Xregister struct monst *mtmp;
Xregister char *force; /* usually either "." or "!" */
X{
X if(!cansee(mtmp->mx,mtmp->my) || !flags.verbose) pline("The %s hits it.", str);
X else pline("The %s hits %s%s", str, mon_nam(mtmp), force);
X}
X
Xvoid
Xmiss(str,mtmp)
Xregister char *str;
Xregister struct monst *mtmp;
X{
X pline("The %s misses %s.", str,
X (cansee(mtmp->mx,mtmp->my) && flags.verbose) ? mon_nam(mtmp) : "it");
X}
X
X/* bhit: called when a weapon is thrown (sym = obj->olet) or when an
X IMMEDIATE wand is zapped (sym = 0); the weapon falls down at end of
X range or when a monster is hit; the monster is returned, and bhitpos
X is set to the final position of the weapon thrown; the ray of a wand
X may affect several objects and monsters on its path - for each of
X these an argument function is called. */
X/* check !u.uswallow before calling bhit() */
X
Xstruct monst *
Xbhit(ddx,ddy,range,sym,fhitm,fhito,obj)
Xregister int ddx,ddy,range; /* direction and range */
Xchar sym; /* symbol displayed on path */
Xint (*fhitm)(), (*fhito)(); /* fns called when mon/obj hit */
Xstruct obj *obj; /* 2nd arg to fhitm/fhito */
X{
X register struct monst *mtmp;
X register struct obj *otmp;
X register int typ;
X
X bhitpos.x = u.ux;
X bhitpos.y = u.uy;
X
X if(sym) {
X tmp_at(-1, sym); /* open call */
X tmp_at(-3, (int)AT_OBJ);
X }
X while(range-- > 0) {
X bhitpos.x += ddx;
X bhitpos.y += ddy;
X typ = levl[bhitpos.x][bhitpos.y].typ;
X#ifdef STRONGHOLD
X if(IS_DRAWBRIDGE(typ))
X switch (obj->otyp) {
X case WAN_OPENING:
X# ifdef SPELLS
X case SPE_KNOCK:
X# endif
X (void) open_drawbridge(bhitpos.x,bhitpos.y);
X break;
X case WAN_LOCKING:
X# ifdef SPELLS
X case SPE_WIZARD_LOCK:
X# endif
X (void) close_drawbridge(bhitpos.x,bhitpos.y);
X }
X#endif /* STRONGHOLD /**/
X if(levl[bhitpos.x][bhitpos.y].mmask){
X mtmp = m_at(bhitpos.x,bhitpos.y);
X if(sym) {
X tmp_at(-1, -1); /* close call */
X return(mtmp);
X }
X (*fhitm)(mtmp, obj);
X range -= 3;
X }
X /* modified by GAN to hit all objects */
X if(fhito && levl[bhitpos.x][bhitpos.y].omask){
X int hitanything = 0;
X otmp = fobj;
X /* Fix for polymorph bug, Tim Wright */
X while(otmp) { /* was a "for" loop. */
X register struct obj *next_obj;
X
X next_obj = otmp->nobj;
X if(otmp->ox == bhitpos.x && otmp->oy == bhitpos.y)
X hitanything += (*fhito)(otmp, obj);
X otmp = next_obj;
X }
X if(hitanything) range--;
X }
X if(IS_DOOR(typ) || typ == SDOOR) {
X switch (obj->otyp) {
X case WAN_OPENING:
X case WAN_LOCKING:
X#ifdef SPELLS
X case SPE_KNOCK:
X case SPE_WIZARD_LOCK:
X#endif
X if (doorlock(obj,bhitpos.x,bhitpos.y))
X makeknown(obj->otyp);
X break;
X }
X }
X if(!ZAP_POS(typ) || (IS_DOOR(typ) &&
X (levl[bhitpos.x][bhitpos.y].doormask & (D_LOCKED | D_CLOSED)))
X ) {
X bhitpos.x -= ddx;
X bhitpos.y -= ddy;
X break;
X }
X if(sym) tmp_at(bhitpos.x, bhitpos.y);
X#ifdef SINKS
X if(sym && IS_SINK(typ))
X break; /* physical objects fall onto sink */
X#endif
X }
X
X /* leave last symbol unless in a pool */
X if(sym)
X tmp_at(-1, is_pool(bhitpos.x,bhitpos.y) ? -1 : 0);
X return (struct monst *)0;
X}
X
Xstruct monst *
Xboomhit(dx, dy)
Xint dx, dy;
X{
X register int i, ct;
X char sym = ')';
X
X bhitpos.x = u.ux;
X bhitpos.y = u.uy;
X
X for(i=0; i<8; i++) if(xdir[i] == dx && ydir[i] == dy) break;
X tmp_at(-1, sym); /* open call */
X tmp_at(-3, (int)AT_OBJ);
X for(ct=0; ct<10; ct++) {
X if(i == 8) i = 0;
X sym = ')' + '(' - sym;
X tmp_at(-2, sym); /* change let call */
X dx = xdir[i];
X dy = ydir[i];
X bhitpos.x += dx;
X bhitpos.y += dy;
X if(levl[bhitpos.x][bhitpos.y].mmask){
X tmp_at(-1,-1);
X return(m_at(bhitpos.x,bhitpos.y));
X }
X if(!ZAP_POS(levl[bhitpos.x][bhitpos.y].typ)) {
X bhitpos.x -= dx;
X bhitpos.y -= dy;
X break;
X }
X if(bhitpos.x == u.ux && bhitpos.y == u.uy) { /* ct == 9 */
X if(rn2(20) >= ACURR(A_DEX)){ /* we hit ourselves */
X (void) thitu(10, rnd(10), "boomerang");
X break;
X } else { /* we catch it */
X tmp_at(-1,-1);
X pline("Skillfully, you catch the boomerang.");
X return(&youmonst);
X }
X }
X tmp_at(bhitpos.x, bhitpos.y);
X if(ct % 5 != 0) i++;
X#ifdef SINKS
X if(IS_SINK(levl[bhitpos.x][bhitpos.y].typ))
X break; /* boomerang falls on sink */
X#endif
X }
X tmp_at(-1, -1); /* do not leave last symbol */
X return (struct monst *)0;
X}
X
Xstatic uchar
Xdirlet(dx, dy)
Xregister int dx, dy;
X{
X return
X (dx == dy) ? LSLANT_SYM :
X (dx && dy) ? RSLANT_SYM :
X dx ? HBEAM_SYM : VBEAM_SYM;
X}
X
Xstatic int
Xzhit(mon, type, nd) /* returns damage to mon */
Xregister struct monst *mon;
Xregister int type, nd;
X{
X register int tmp = 0;
X register int abstype = abs(type) % 10;
X
X switch(abstype) {
X case 0: /* magic missile */
X tmp = d(nd,6);
X break;
X case 1: /* fire */
X if(resists_fire(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X if(resists_cold(mon->data)) tmp += 7;
X break;
X case 2: /* sleep */
X tmp = 0;
X if(resists_sleep(mon->data) ||
X resist(mon, (type == 2) ? WAND_SYM : '\0', 0, NOTELL))
X shieldeff(mon->mx, mon->my);
X else mon->mfroz = 1;
X break;
X case 3: /* cold */
X if(resists_cold(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X if(resists_fire(mon->data)) tmp += d(nd, 3);
X break;
X case 4: /* death/disintegration */
X if(abs(type) != 24) { /* death */
X if(is_undead(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X type = 0; /* so they don't get saving throws */
X }
X tmp = mon->mhp+1;
X break;
X case 5: /* lightning */
X if(resists_elec(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X {
X register unsigned rnd_tmp = rnd(50);
X mon->mcansee = 0;
X if((mon->mblinded + rnd_tmp) > 127)
X mon->mblinded = 127;
X else mon->mblinded += rnd_tmp;
X }
X break;
X case 6: /* poison */
X if(resists_poison(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X break;
X case 7: /* acid */
X if(resists_acid(mon->data)) {
X shieldeff(mon->mx, mon->my);
X break;
X }
X tmp = d(nd,6);
X break;
X }
X if (type >= 0)
X if (resist(mon, (type < 10) ? WAND_SYM : '\0', 0, NOTELL)) tmp /= 2;
X mon->mhp -= tmp;
X return(tmp);
X}
X
X/*
X * burn scrolls on floor at position x,y
X * return the number of scrolls burned
X */
Xstatic int
Xburn_floor_scrolls(x, y)
Xint x, y;
X{
X register struct obj *obj, *obj2;
X register int scrquan, i, cnt = 0;
X
X if(levl[x][y].omask)
X for(obj = fobj; obj; obj = obj2) {
X obj2 = obj->nobj;
X /* Bug fix - KAA */
X if(obj->ox == x && obj->oy == y && obj->olet == SCROLL_SYM) {
X scrquan = obj->quan;
X for(i = 1; i <= scrquan ; i++)
X if(!rn2(3)) {
X cnt++;
X if(in_shop(u.ux, u.uy))
X addtobill(obj, FALSE);
X useupf(obj);
X }
X }
X }
X return(cnt);
X}
X
X/* type == 0 to 9 : you shooting a wand */
X/* type == 10 to 19 : you casting a spell */
X/* type == 20 to 29 : you breathing as a monster */
X/* type == -10 to -19 : monster casting spell */
X/* type == -20 to -29 : monster breathing at you */
X/* called with dx = dy = 0 with vertical bolts */
Xvoid
Xbuzz(type,nd,sx,sy,dx,dy)
Xregister int type, nd;
Xregister xchar sx,sy;
Xregister int dx,dy;
X{
X int abstype = abs(type) % 10;
X register char *fltxt = fl[abs(type)];
X struct rm *lev;
X xchar range, olx, oly;
X struct monst *mon;
X register boolean bodyhit = FALSE;
X register boolean shopdoor = FALSE;
X
X if(u.uswallow) {
X register int tmp;
X
X if(type < 0) return;
X tmp = zhit(u.ustuck, type, nd);
X if(!u.ustuck) u.uswallow = 0;
X else pline("The %s rips into %s%s",
X fltxt, mon_nam(u.ustuck), exclam(tmp));
X if (u.ustuck->mhp < 1)
X killed(u.ustuck);
X return;
X }
X if(type < 0) pru();
X range = rn1(7,7);
X Tmp_at2(-1, (int) dirlet(dx,dy)); /* open call */
X#ifdef MSDOSCOLOR
X Tmp_at2(-3, (int)(abstype == 1 ? AT_RED : /* fire */
X abstype == 3 || abstype == 5 ? AT_WHITE : /* cold/elec */
X AT_ZAP);
X#endif
X while(range-- > 0) {
X sx += dx;
X sy += dy;
X if((lev = &levl[sx][sy])->typ) Tmp_at2(sx,sy);
X else {
X int bounce = 0;
X if(cansee(sx-dx,sy-dy))
X pline("The %s bounces!", fltxt);
X if(ZAP_POS(levl[sx][sy-dy].typ))
X bounce = 1;
X if(ZAP_POS(levl[sx-dx][sy].typ)) {
X if(!bounce || rn2(2)) bounce = 2;
X }
X switch(bounce){
X case 0:
X dx = -dx;
X dy = -dy;
X continue;
X case 1:
X dy = -dy;
X sx -= dx;
X break;
X case 2:
X dx = -dx;
X sy -= dy;
X break;
X }
X Tmp_at2(-2,(int) dirlet(dx,dy));
X continue;
X }
X if(is_pool(sx,sy) && abstype == 1 /* fire */) {
X#ifdef STRONGHOLD
X if(lev->typ != POOL) { /* MOAT or DRAWBRIDGE_UP */
X if(cansee(sx,sy))
X pline("Some water evaporates.");
X else if(flags.soundok)
X You("hear a hissing sound.");
X } else {
X#endif
X register struct trap *ttmp;
X
X range -= 3;
X lev->typ = ROOM;
X mnewsym(sx,sy);
X if(cansee(sx,sy)) pline("The water evaporates.");
X else if(flags.soundok)
X You("hear a hissing sound.");
X ttmp = maketrap(sx, sy, PIT);
X ttmp->tseen = 1;
X#ifdef STRONGHOLD
X }
X#endif
X }
X if(is_pool(sx,sy) && abstype == 3 /* cold */) {
X boolean moat = (lev->typ != POOL);
X
X range -= 3;
X#ifdef STRONGHOLD
X if(lev->typ == DRAWBRIDGE_UP)
X lev->drawbridgemask |= DB_FLOOR;
X else
X#endif
X lev->typ = ROOM;
X mnewsym(sx,sy);
X if(cansee(sx,sy)) {
X if(moat)
X pline("The moat is bridged with ice!");
X else pline("The water freezes.");
X } else if(flags.soundok)
X You("hear a crackling sound.");
X }
X if(IS_DOOR(lev->typ) && (lev->doormask & (D_LOCKED | D_CLOSED))) {
X range = 0;
X switch(abstype) {
X case 1:
X lev->doormask = D_NODOOR;
X if(cansee(sx,sy))
X pline("The door is consumed in flames!");
X else You("smell smoke.");
X if(type >= 0 && in_shop(sx, sy)) {
X shopdoor = TRUE;
X olx = sx;
X oly = sy;
X }
X break;
X case 3:
X lev->doormask = D_NODOOR;
X if(cansee(sx,sy))
X pline("The door freezes and shatters!");
X else You("feel cold.");
X if(type >= 0 && in_shop(sx, sy)) {
X shopdoor = TRUE;
X olx = sx;
X oly = sy;
X }
X break;
X case 4:
X lev->doormask = D_NODOOR;
X if(cansee(sx,sy))
X pline("The door disintegrates!");
X else if(flags.soundok)
X You("hear a crashing sound.");
X if(type >= 0 && in_shop(sx, sy)) {
X shopdoor = TRUE;
X olx = sx;
X oly = sy;
X }
X break;
X case 5:
X lev->doormask = D_BROKEN;
X if(cansee(sx,sy))
X pline("The door splinters!");
X else if(flags.soundok)
X You("hear a crackling sound.");
X if(type >= 0 && in_shop(sx, sy)) {
X shopdoor = TRUE;
X olx = sx;
X oly = sy;
X }
X break;
X default:
X if(cansee(sx,sy)) {
X if (type >= 0 && type <= 9)
X pline("The door absorbs your bolt!");
X else if (type >= 10 && type <= 19)
X pline("The door absorbs your spell!");
X#ifdef POLYSELF
X else if (type >= 20 && type <= 29)
X pline("The door absorbs your blast!");
X#endif
X else if (type >= -19 && type <= -10)
X pline("The door absorbs the spell!");
X else
X pline("The door absorbs the blast!");
X } else You("feel vibrations.");
X break;
X }
X }
X if(levl[sx][sy].omask && abstype == 1)
X if(burn_floor_scrolls(sx,sy) && cansee(sx,sy)) {
X mnewsym(sx,sy);
X if(!Blind)
X You("see a puff of smoke.");
X }
X if(levl[sx][sy].mmask){
X mon = m_at(sx,sy);
X /* Cannot use wakeup() which also angers the monster */
X mon->msleep = 0;
X if(mon->mimic) seemimic(mon);
X if(type >= 0) {
X setmangry(mon);
X#if defined(ALTARS) && defined(THEOLOGY)
X if(mon->ispriest && in_temple(mon->mx, mon->my))
X priesthit = TRUE;
X#endif
X }
X if(rnd(20) < 18 + mon->data->ac) {
X register int tmp = zhit(mon, type, nd);
X if(mon->mhp < 1) {
X if(type < 0) {
X if(cansee(mon->mx,mon->my))
X pline("%s is killed by the %s!",
X Monnam(mon), fltxt);
X mondied(mon);
X } else
X killed(mon);
X } else
X hit(fltxt, mon, exclam(tmp));
X range -= 2;
X } else
X miss(fltxt,mon);
X } else if(sx == u.ux && sy == u.uy) {
X nomul(0);
X if(rnd(20) < 18+u.uac) {
X register int dam = 0;
X range -= 2;
X pline("The %s hits you!",fltxt);
X if (Reflecting) {
X if (!Blind) {
X if(Reflecting & WORN_AMUL)
X makeknown(AMULET_OF_REFLECTION);
X else
X makeknown(SHIELD_OF_REFLECTION);
X pline("But it reflects from your %s!",
X (Reflecting & W_AMUL) ? "amulet" : "shield");
X } else
X pline("For some reason you are not affected!");
X if (dx) dx = -dx;
X if (dy) dy = -dy;
X shieldeff(sx, sy);
X }
X else switch(abstype) {
X case 0: /* magic missile */
X if(Antimagic) {
X shieldeff(sx, sy);
X pline("The missiles bounce off!");
X } else dam = d(nd,6);
X break;
X case 1: /* fire */
X if(Fire_resistance) {
X shieldeff(sx, sy);
X You("don't feel hot!");
X#ifdef POLYSELF
X#ifdef GOLEMS
X ugolemeffects(AD_FIRE, d(nd, 6));
X#endif /* GOLEMS */
X#endif
X } else dam = d(nd, 6);
X while (1) {
X switch(rn2(5)) {
X case 0:
X if (!rust_dmg(uarmh, "leather helmet", 0, FALSE)) continue;
X break;
X case 1:
X bodyhit = TRUE;
X if (uarmc) break;
X (void)(rust_dmg(uarm, "leather armor", 0, FALSE));
X break;
X case 2:
X if (!rust_dmg(uarms, "wooden shield", 0, FALSE)) continue;
X break;
X case 3:
X if (!rust_dmg(uarmg, "gloves", 0, FALSE)) continue;
X break;
X case 4:
X if (!rust_dmg(uarmf, "boots", 0, FALSE)) continue;
X break;
X }
X break; /* Out of while loop */
X }
X if(!rn2(3) && bodyhit)
X destroy_item(POTION_SYM, AD_FIRE);
X if(!rn2(3) && bodyhit)
X destroy_item(SCROLL_SYM, AD_FIRE);
X#ifdef SPELLS
X if(!rn2(5) && bodyhit)
X destroy_item(SPBOOK_SYM, AD_FIRE);
X#endif
X break;
X case 2: /* sleep */
X if(Sleep_resistance) {
X shieldeff(u.ux, u.uy);
X You("don't feel sleepy.");
X } else nomul(-d(nd,25)); /* sleep ray */
X break;
X case 3: /* cold */
X if(Cold_resistance) {
X shieldeff(sx, sy);
X You("don't feel cold.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X ugolemeffects(AD_COLD, d(nd, 6));
X#endif /* GOLEMS */
X#endif
X } else
X dam = d(nd, 6);
X if(!rn2(3))
X destroy_item(POTION_SYM, AD_COLD);
X break;
X case 4: /* death */
X if(type == -24) { /* disintegration */
X if(uarms) {
X (void) destroy_arm(uarms);
X } else if (uarm) {
X if (Disint_resistance & WORN_ARMOR)
X Your("armor absorbs the blast!");
X else (void) destroy_arm(uarm);
X }
X break;
X }
X#ifdef POLYSELF
X else if(is_undead(uasmon)) {
X shieldeff(sx, sy);
X You("seem unaffected.");
X break;
X }
X#endif
X u.uhp = -1;
X break;
X case 5: /* lightning */
X if (Shock_resistance) {
X shieldeff(sx, sy);
X You("aren't affected.");
X#ifdef POLYSELF
X#ifdef GOLEMS
X ugolemeffects(AD_ELEC, d(nd, 6));
X#endif /* GOLEMS */
X#endif
X } else
X dam = d(nd, 6);
X break;
X case 6: /* poison */
X poisoned("blast", A_DEX, "poisoned blast");
X break;
X case 7: /* acid */
X pline("The acid burns!");
X dam = d(nd,6);
X if(!rn2(6)) corrode_weapon();
X if(!rn2(6)) corrode_armor();
X break;
X }
X losehp(dam,fltxt);
X } else pline("The %s whizzes by you!",fltxt);
X if (abstype == 5 && !Blind) { /* LIGHTNING */
X You("are blinded by the flash!");
X make_blinded((long)d(nd,50),FALSE);
X seeoff(0);
X }
X stop_occupation();
X }
X if(!ZAP_POS(lev->typ)) {
X int bounce = 0, rmn;
X if(cansee(sx,sy)) pline("The %s bounces!", fltxt);
X range--;
X if(!dx || !dy || !rn2(20)){
X dx = -dx;
X dy = -dy;
X } else {
X if(ZAP_POS(rmn = levl[sx][sy-dy].typ) &&
X (IS_ROOM(rmn) || ZAP_POS(levl[sx+dx][sy-dy].typ)))
X bounce = 1;
X if(ZAP_POS(rmn = levl[sx-dx][sy].typ) &&
X (IS_ROOM(rmn) || ZAP_POS(levl[sx-dx][sy+dy].typ)))
X if(!bounce || rn2(2))
X bounce = 2;
X
X switch(bounce){
X case 0:
X dy = -dy;
X dx = -dx;
X break;
X case 1:
X dy = -dy;
X break;
X case 2:
X dx = -dx;
X break;
X }
X Tmp_at2(-2, (int) dirlet(dx,dy));
X }
X }
X }
X Tmp_at2(-1,-1);
X if(shopdoor && !in_shop(u.ux, u.uy))
X pay_for_door(olx, oly, abstype == 1 ? "burn away" :
X abstype == 3 ? "shatter" :
X abstype == 4 ? "disintegrate" :
X "destroy");
X}
X
Xvoid
Xrloco(obj)
Xregister struct obj *obj;
X{
X register int tx, ty, otx, oty;
X
X otx = obj->ox;
X oty = obj->oy;
X do {
X tx = rn1(COLNO-3,2);
X ty = rn2(ROWNO);
X } while(!goodpos(tx,ty));
X obj->ox = tx;
X obj->oy = ty;
X set_omask(otx,oty);
X if(cansee(otx,oty))
X newsym(otx,oty);
X levl[tx][ty].omask = 1;
X if(cansee(tx,ty))
X newsym(tx,ty);
X}
X
Xvoid
Xfracture_rock(obj) /* fractured by pick-axe or wand of striking */
Xregister struct obj *obj; /* no texts here! */
X{
X /* unpobj(obj); */
X obj->otyp = ROCK;
X obj->blessed = FALSE;
X obj->quan = 7 + rn2(60);
X obj->owt = weight(obj);
X obj->olet = GEM_SYM;
X obj->known = FALSE;
X if(cansee(obj->ox,obj->oy))
X prl(obj->ox,obj->oy);
X}
X
Xboolean
Xbreak_statue(obj)
Xregister struct obj *obj;
X{
X struct trap *trap;
X
X if(trap = t_at(obj->ox,obj->oy))
X if(obj->corpsenm == trap->pm)
X if(makemon(&mons[trap->pm], obj->ox, obj->oy)) {
X pline("Instead of shattering, the statue suddenly comes alive!");
X delobj(obj);
X deltrap(trap);
X return FALSE;
X }
X if (obj->spe) {
X struct obj *magazine;
X#ifdef SPELLS
X magazine = mkobj_at(SPBOOK_SYM, obj->ox, obj->oy);
X#else
X magazine = mkobj_at(SCROLL_SYM, obj->ox, obj->oy);
X#endif
X magazine->blessed = obj->blessed;
X magazine->cursed = obj->cursed;
X }
X fracture_rock(obj);
X return TRUE;
X}
X
Xconst char *destroy_strings[] = {
X "freezes and shatters", "freeze and shatter", "shattered potion",
X "boils and explodes", "boil and explode", "boiling potion",
X "catches fire and burns", "catch fire and burn", "burning scroll",
X "catches fire and burns", "catch fire and burn", "burning book",
X "turns to dust and vanishes", "turn to dust and vanish", "",
X "breaks apart and explodes", "break apart and explode", "exploding wand"
X};
X
Xvoid
Xdestroy_item(osym, dmgtyp)
Xregister int osym, dmgtyp;
X{
X register struct obj *obj, *obj2;
X register int quan, i, cnt, dmg, xresist, skip;
X register int dindx;
X char *mult;
X
X for(obj = invent; obj; obj = obj2) {
X
X obj2 = obj->nobj;
X if(obj->olet != osym) continue; /* test only objs of type osym */
X xresist = skip = 0;
X
X switch(dmgtyp) {
X case AD_COLD:
X if(osym == POTION_SYM) {
X quan = obj->quan;
X dindx = 0;
X dmg = rnd(4);
X } else skip++;
X break;
X case AD_FIRE:
X xresist = (Fire_resistance && obj->olet != POTION_SYM);
X
X /* Let's say scrolls of fire are fire resistant */
X
X if (obj->otyp == SCR_FIRE)
X skip++;
X quan = obj->quan;
X switch(osym) {
X case POTION_SYM:
X dindx = 1;
X dmg = rnd(6);
X break;
X case SCROLL_SYM:
X dindx = 2;
X dmg = 1;
X break;
X#ifdef SPELLS
X case SPBOOK_SYM:
X dindx = 3;
X dmg = 1;
X break;
X#endif
X default:
X skip++;
X break;
X }
X break;
X case AD_ELEC:
X xresist = (Shock_resistance && obj->olet != RING_SYM);
X quan = obj->quan;
X switch(osym) {
X case RING_SYM:
X if(obj->otyp == RIN_SHOCK_RESISTANCE)
X { skip++; break; }
X dindx = 4;
X dmg = 0;
X break;
X case WAND_SYM:
X if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
X dindx = 5;
X dmg = rnd(10);
X break;
X default:
X skip++;
X break;
X }
X break;
X default:
X skip++;
X break;
X }
X if(!skip) {
X for(i = cnt = 0; i < quan; i++)
X if(!rn2(3)) cnt++;
X
X if(!cnt) continue;
X if(cnt == quan) mult = "Your";
X else mult = (cnt == 1) ? "One of your" : "Some of your";
X pline("%s %s %s!", mult, xname(obj),
X (cnt > 1) ? destroy_strings[dindx*3 + 1]
X : destroy_strings[dindx*3]);
X if(osym == POTION_SYM && dmgtyp != AD_COLD)
X potionbreathe(obj);
X for(i = 0; i < cnt; i++) useup(obj);
X if(dmg) {
X if(xresist) You("aren't hurt!");
X else losehp(dmg, destroy_strings[dindx*3 + 2]);
X }
X }
X }
X return;
X}
X
Xint
Xdestroy_mitem(mtmp, osym, dmgtyp)
Xregister struct monst *mtmp;
Xregister int osym, dmgtyp;
X{
X register struct obj *obj, *obj2;
X register int quan, i, cnt, skip, tmp = 0;
X register int dindx;
X
X for(obj = mtmp->minvent; obj; obj = obj2) {
X
X obj2 = obj->nobj;
X if(obj->olet != osym) continue; /* test only objs of type osym */
X skip = 0;
X
X switch(dmgtyp) {
X case AD_COLD:
X if(osym == POTION_SYM) {
X quan = obj->quan;
X dindx = 0;
X tmp++;
X } else skip++;
X break;
X case AD_FIRE:
X /* Let's say scrolls of fire are fire resistant */
X
X if (obj->otyp == SCR_FIRE)
X skip++;
X quan = obj->quan;
X switch(osym) {
X case POTION_SYM:
X dindx = 1;
X tmp++;
X break;
X case SCROLL_SYM:
X dindx = 2;
X tmp++;
X break;
X#ifdef SPELLS
X case SPBOOK_SYM:
X dindx = 3;
X tmp++;
X break;
X#endif
X default:
X skip++;
X break;
X }
X break;
X case AD_ELEC:
X quan = obj->quan;
X switch(osym) {
X case RING_SYM:
X if(obj->otyp == RIN_SHOCK_RESISTANCE)
X { skip++; break; }
X dindx = 4;
X break;
X case WAND_SYM:
X if(obj->otyp == WAN_LIGHTNING) { skip++; break; }
X dindx = 5;
X tmp++;
X break;
X default:
X skip++;
X break;
X }
X break;
X default:
X skip++;
X break;
X }
X if(!skip) {
X for(i = cnt = 0; i < quan; i++)
X if(!rn2(3)) cnt++;
X
X if(!cnt) continue;
X pline("%s's %s %s!", Monnam(mtmp), xname(obj),
X (cnt > 1) ? destroy_strings[dindx*3 + 1]
X : destroy_strings[dindx*3]);
X for(i = 0; i < cnt; i++) m_useup(mtmp, obj);
X }
X }
X return(tmp);
X}
X
X/*ARGSUSED*/
Xint
Xresist(mtmp, olet, damage, tell)
Xregister struct monst *mtmp;
Xregister char olet;
Xregister int damage, tell;
X{
X register int resisted = 0;
X#ifdef HARD
X register int level;
X
X switch(olet) {
X
X case WAND_SYM:
X level = 8;
X break;
X
X case SCROLL_SYM:
X level = 6;
X break;
X
X case POTION_SYM:
X level = 5;
X break;
X
X default: level = u.ulevel;
X break;
X }
X
X resisted = (rn2(100) - mtmp->m_lev + level) < mtmp->data->mr;
X if(resisted) {
X
X if(tell) {
X shieldeff(mtmp->mx, mtmp->my);
X pline("%s resists!", canseemon(mtmp) ? Monnam(mtmp) : "It");
X }
X mtmp->mhp -= damage/2;
X } else
X#endif
X mtmp->mhp -= damage;
X
X if(mtmp->mhp < 1) killed(mtmp);
X return(resisted);
X}
X
Xvoid
Xmakewish()
X{
X char buf[BUFSZ];
X register struct obj *otmp;
X int wishquan, mergquan;
X register boolean dropit = (inv_cnt() >= 52);
X int tries = 0;
X
Xretry:
X You("may wish for an object. What do you want? ");
X getlin(buf);
X if(buf[0] == '\033') buf[0] = 0;
X/* Note: if they wished for and got a non-object successfully, such as gold,
X * otmp = &zeroobj
X */
X otmp = readobjnam(buf);
X if (!otmp) {
X pline("Nothing fitting that description exists in the game.");
X if (++tries < 5) goto retry;
X pline(thats_enough_tries);
X if (!(otmp = readobjnam((char *)0)))
X return; /* for safety; should never happen */
X }
X if (otmp != &zeroobj) {
X if(dropit) {
X pline("Oops! The %s drop%s to the floor!", xname(otmp),
X otmp->quan > 1 ? "" : "s");
X dropy(otmp);
X } else {
X wishquan = otmp->quan;
X otmp = addinv(otmp);
X mergquan = otmp->quan;
X otmp->quan = wishquan; /* to fool prinv() */
X prinv(otmp);
X otmp->quan = mergquan;
X }
X#ifdef WIZARD
X if (!wizard)
X#endif
X if(otmp->otyp == WAN_WISHING) otmp->recharged = 1;
X
X#ifdef THEOLOGY
X u.ublesscnt += rn1(100,50); /* the gods take notice */
X#endif
X }
X}
END_OF_FILE
if test 44087 -ne `wc -c <'src/zap.c'`; then
echo shar: \"'src/zap.c'\" unpacked with wrong size!
fi
# end of 'src/zap.c'
fi
echo shar: End of archive 2 \(of 38\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 38 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0