home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 January
/
usenetsourcesnewsgroupsinfomagicjanuary1994.iso
/
sources
/
games
/
volume16
/
nethack31
/
part33
< prev
next >
Wrap
Internet Message Format
|
1993-02-01
|
60KB
Path: uunet!news.tek.com!master!saab!billr
From: billr@saab.CNA.TEK.COM (Bill Randle)
Newsgroups: comp.sources.games
Subject: v16i033: nethack31 - display oriented dungeons & dragons (Ver. 3.1), Part33/108
Message-ID: <4321@master.CNA.TEK.COM>
Date: 29 Jan 93 20:46:50 GMT
Sender: news@master.CNA.TEK.COM
Lines: 2191
Approved: billr@saab.CNA.TEK.COM
Xref: uunet comp.sources.games:1590
Submitted-by: izchak@linc.cis.upenn.edu (Izchak Miller)
Posting-number: Volume 16, Issue 33
Archive-name: nethack31/Part33
Supersedes: nethack3p9: Volume 10, Issue 46-102
Environment: Amiga, Atari, Mac, MS-DOS, OS2, Unix, VMS, X11
#! /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 33 (of 108)."
# Contents: src/dog.c src/shk.c2
# Wrapped by billr@saab on Wed Jan 27 16:08:59 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'src/dog.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/dog.c'\"
else
echo shar: Extracting \"'src/dog.c'\" \(13007 characters\)
sed "s/^X//" >'src/dog.c' <<'END_OF_FILE'
X/* SCCS Id: @(#)dog.c 3.1 92/10/18 */
X/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
X/* NetHack may be freely redistributed. See license for details. */
X
X#include "hack.h"
X#include "edog.h"
X
X#define domestic(mtmp) (mtmp->data->msound == MS_BARK || \
X mtmp->data->msound == MS_MEW)
X
X#ifdef OVLB
X
Xstatic int NDECL(pet_type);
X
Xvoid
Xinitedog(mtmp)
Xregister struct monst *mtmp;
X{
X mtmp->mtame = domestic(mtmp) ? 10 : 5;
X mtmp->mpeaceful = 1;
X set_malign(mtmp); /* recalc alignment now that it's tamed */
X mtmp->mleashed = 0;
X mtmp->meating = 0;
X EDOG(mtmp)->droptime = 0;
X EDOG(mtmp)->dropdist = 10000;
X EDOG(mtmp)->apport = 10;
X EDOG(mtmp)->whistletime = 0;
X EDOG(mtmp)->hungrytime = 1000 + moves;
X}
X
Xstatic int
Xpet_type()
X{
X register int pettype;
X
X switch (pl_character[0]) {
X /* some character classes have restricted ideas of pets */
X case 'C':
X case 'S':
X pettype = PM_LITTLE_DOG;
X break;
X case 'W':
X pettype = PM_KITTEN;
X break;
X /* otherwise, see if the player has a preference */
X default:
X if (preferred_pet == 'c')
X pettype = PM_KITTEN;
X else if (preferred_pet == 'd')
X pettype = PM_LITTLE_DOG;
X else pettype = rn2(2) ? PM_KITTEN : PM_LITTLE_DOG;
X break;
X }
X return pettype;
X}
X
Xvoid
Xmake_familiar(otmp,x,y)
Xregister struct obj *otmp;
Xxchar x, y;
X{
X register struct monst *mtmp;
X register struct permonst *pm;
X
Xtop:
X if (otmp) pm = &mons[otmp->corpsenm]; /* Figurine; otherwise spell */
X else if (rn2(3)) {
X if (!(pm = rndmonst())) {
X pline("There seems to be nothing available for a familiar.");
X return;
X }
X }
X else pm = &mons[pet_type()];
X
X pm->pxlth += sizeof(struct edog);
X mtmp = makemon(pm, x, y);
X pm->pxlth -= sizeof(struct edog);
X if (!mtmp) { /* monster was genocided */
X if (otmp)
X pline("The figurine writhes and then shatters into pieces!");
X else goto top;
X /* rndmonst() returns something not genocided always, so this
X * means it was a cat or dog; loop back to try again until
X * either rndmonst() is called, or if only one of cat/dog
X * was genocided, they get the other.
X */
X return;
X }
X initedog(mtmp);
X mtmp->msleep = 0;
X if (otmp && otmp->cursed) { /* cursed figurine */
X You("get a bad feeling about this.");
X mtmp->mtame = mtmp->mpeaceful = 0;
X newsym(mtmp->mx, mtmp->my);
X }
X set_malign(mtmp); /* more alignment changes */
X}
X
Xstruct monst *
Xmakedog()
X{
X register struct monst *mtmp;
X char *petname;
X int pettype;
X static int petname_used = 0;
X
X pettype = pet_type();
X if (pettype == PM_LITTLE_DOG)
X petname = dogname;
X else
X petname = catname;
X
X mons[pettype].pxlth = sizeof(struct edog);
X mtmp = makemon(&mons[pettype], u.ux, u.uy);
X mons[pettype].pxlth = 0;
X
X if(!mtmp) return((struct monst *) 0); /* pets were genocided */
X
X if (!petname_used++ && *petname)
X mtmp = christen_monst(mtmp, petname);
X
X initedog(mtmp);
X return(mtmp);
X}
X
Xvoid
Xlosedogs()
X{
X register struct monst *mtmp,*mtmp0,*mtmp2;
X int num_segs;
X
X while(mtmp = mydogs){
X mydogs = mtmp->nmon;
X mtmp->nmon = fmon;
X fmon = mtmp;
X if (mtmp->isshk)
X set_residency(mtmp, FALSE);
X
X num_segs = mtmp->wormno;
X /* baby long worms have no tail so don't use is_longworm() */
X if ( (mtmp->data == &mons[PM_LONG_WORM]) &&
X (mtmp->wormno = get_wormno()) ) {
X initworm(mtmp, num_segs);
X /* tail segs are not yet initialized or displayed */
X } else mtmp->wormno = 0;
X mnexto(mtmp);
X }
X
X#if defined(LINT) || defined(GCC_WARN)
X mtmp0 = (struct monst *)0;
X#endif
X for(mtmp = migrating_mons; mtmp; mtmp = mtmp2) {
X mtmp2 = mtmp->nmon;
X if(mtmp->mx == u.uz.dnum && mtmp->mux == u.uz.dlevel) {
X mtmp->mx = 0; /* save xyloc in mtmp->my */
X mtmp->mux = u.ux; mtmp->muy = u.uy; /* not really req'd */
X if(mtmp == migrating_mons)
X migrating_mons = mtmp->nmon;
X else
X mtmp0->nmon = mtmp->nmon;
X mtmp->nmon = fmon;
X fmon = mtmp;
X num_segs = mtmp->wormno;
X if ( (mtmp->data == &mons[PM_LONG_WORM]) &&
X (mtmp->wormno = get_wormno()) ) {
X initworm(mtmp, num_segs);
X /* tail segs are not yet initialized or displayed */
X } else mtmp->wormno = 0;
X
X if(mtmp->mlstmv < monstermoves-1) {
X /* heal monster for time spent in limbo */
X long nmv = monstermoves - mtmp->mlstmv - 1;
X
X /* might stop being afraid, blind or frozen */
X /* set to 1 and allow final decrement in movemon() */
X if(nmv >= (long)mtmp->mblinded) mtmp->mblinded = 1;
X else mtmp->mblinded -= nmv;
X if(nmv >= (long)mtmp->mfrozen) mtmp->mfrozen = 1;
X else mtmp->mfrozen -= nmv;
X if(nmv >= (long)mtmp->mfleetim) mtmp->mfleetim = 1;
X else mtmp->mfleetim -= nmv;
X
X /* might be able to use special ability again */
X if(nmv > (long)mtmp->mspec_used) mtmp->mspec_used = 0;
X else mtmp->mspec_used -= nmv;
X
X if(!regenerates(mtmp->data)) nmv /= 20;
X if((long)mtmp->mhp + nmv >= (long)mtmp->mhpmax)
X mtmp->mhp = mtmp->mhpmax;
X else mtmp->mhp += nmv;
X mtmp->mlstmv = monstermoves-1;
X }
X
X if (mtmp->data->geno & G_GENOD) {
X#ifdef KOPS
X allow_kops = FALSE;
X#endif
X mondead(mtmp); /* must put in fmon list first */
X#ifdef KOPS
X allow_kops = TRUE;
X#endif
X } else if (mtmp->isshk && mtmp->mpeaceful)
X home_shk(mtmp, TRUE);
X else switch(mtmp->my) {
X xchar *xlocale, *ylocale;
X
X case 1: xlocale = &xupstair; ylocale = &yupstair;
X goto common;
X case 2: xlocale = &xdnstair; ylocale = &ydnstair;
X goto common;
X case 3: xlocale = &xupladder; ylocale = &yupladder;
X goto common;
X case 4: xlocale = &xdnladder; ylocale = &ydnladder;
X goto common;
X case 5: xlocale = &sstairs.sx; ylocale = &sstairs.sy;
X goto common;
Xcommon:
X if (*xlocale && *ylocale) {
X (void) mnearto(mtmp, *xlocale, *ylocale, FALSE);
X break;
X } /* else fall through */
X default:
X rloc(mtmp);
X break;
X }
X } else
X mtmp0 = mtmp;
X if (mtmp->isshk)
X set_residency(mtmp, FALSE);
X }
X}
X
X#endif /* OVLB */
X#ifdef OVL2
X
Xvoid
Xkeepdogs()
X{
X register struct monst *mtmp;
X register struct obj *obj;
X int num_segs = 0;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
X if(((monnear(mtmp, u.ux, u.uy) && levl_follower(mtmp)) ||
X /* the wiz will level t-port from anywhere to chase
X the amulet; if you don't have it, will chase you
X only if in range. -3. */
X (u.uhave.amulet && mtmp->iswiz))
X && !mtmp->msleep && mtmp->mcanmove) {
X
X /* long worms can now change levels! - Norm */
X
X if (mtmp->mtame && mtmp->meating && canseemon(mtmp)) {
X pline("%s is still eating.", Monnam(mtmp));
X goto merge;
X }
X if (mon_has_amulet(mtmp)) {
X pline("%s seems very disoriented for a moment.",
X Monnam(mtmp));
X merge:
X#ifdef WALKIES
X if (mtmp->mleashed) {
X pline("%s leash suddenly comes loose.",
X humanoid(mtmp->data)
X ? (mtmp->female ? "Her" : "His")
X : "Its");
X m_unleash(mtmp);
X }
X#endif
X continue;
X }
X if (mtmp->isshk)
X set_residency(mtmp, TRUE);
X
X if (mtmp->wormno) {
X /* NOTE: worm is truncated to # segs = max wormno size */
X num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1);
X wormgone(mtmp);
X }
X
X /* set minvent's obj->no_charge to 0 */
X for(obj = mtmp->minvent; obj; obj = obj->nobj) {
X if(Is_container(obj))
X picked_container(obj); /* does the right thing */
X obj->no_charge = 0;
X }
X
X relmon(mtmp);
X newsym(mtmp->mx,mtmp->my);
X mtmp->mx = mtmp->my = 0; /* avoid mnexto()/MON_AT() problem */
X mtmp->wormno = num_segs;
X mtmp->nmon = mydogs;
X mydogs = mtmp;
X keepdogs(); /* we destroyed the link, so use recursion */
X return; /* (admittedly somewhat primitive) */
X }
X}
X
X#endif /* OVL2 */
X#ifdef OVLB
X
Xvoid
Xmigrate_to_level(mtmp, tolev, xyloc)
X register struct monst *mtmp;
X xchar tolev; /* destination level */
X xchar xyloc; /* destination xy location: */
X /* 0: rnd,
X * 1: <,
X * 2: >,
X * 3: < ladder,
X * 4: > ladder,
X * 5: sstairs
X */
X{
X register struct obj *obj;
X int num_segs = 0; /* count of worm segments */
X
X if (mtmp->isshk)
X set_residency(mtmp, TRUE);
X
X if (mtmp->wormno) {
X /* **** NOTE: worm is truncated to # segs = max wormno size **** */
X num_segs = min(count_wsegs(mtmp), MAX_NUM_WORMS - 1);
X wormgone(mtmp);
X }
X
X /* set minvent's obj->no_charge to 0 */
X for(obj = mtmp->minvent; obj; obj = obj->nobj) {
X if(Is_container(obj))
X picked_container(obj); /* does the right thing */
X obj->no_charge = 0;
X }
X
X relmon(mtmp);
X mtmp->nmon = migrating_mons;
X migrating_mons = mtmp;
X#ifdef WALKIES
X if (mtmp->mleashed) {
X pline("The leash comes off!");
X m_unleash(mtmp);
X }
X#endif
X mtmp->mtame = 0;
X newsym(mtmp->mx,mtmp->my);
X /* make sure to reset mtmp->[mx,my] to 0 when releasing, */
X /* so rloc() on next level doesn't affect MON_AT() state */
X mtmp->mx = ledger_to_dnum((xchar)tolev);
X mtmp->mux = ledger_to_dlev((xchar)tolev);
X mtmp->my = xyloc;
X mtmp->muy = 0;
X mtmp->wormno = num_segs;
X mtmp->mlstmv = monstermoves;
X}
X
X#endif /* OVLB */
X#ifdef OVL1
X
X/* return quality of food; the lower the better */
X/* fungi will eat even tainted food */
Xint
Xdogfood(mon,obj)
Xstruct monst *mon;
Xregister struct obj *obj;
X{
X boolean carni = carnivorous(mon->data);
X boolean herbi = herbivorous(mon->data);
X struct permonst *fptr = &mons[obj->corpsenm];
X
X switch(obj->oclass) {
X case FOOD_CLASS:
X if (obj->otyp == CORPSE &&
X ((obj->corpsenm == PM_COCKATRICE && !resists_ston(mon->data))
X || is_rider(fptr)))
X return TABU;
X
X if (!carni && !herbi)
X return (obj->cursed ? UNDEF : APPORT);
X
X switch (obj->otyp) {
X case TRIPE_RATION:
X return (carni ? DOGFOOD : MANFOOD);
X case EGG:
X if (obj->corpsenm == PM_COCKATRICE &&
X !resists_ston(mon->data))
X return POISON;
X return (carni ? CADAVER : MANFOOD);
X case CORPSE:
X if ((obj->age+50 <= monstermoves
X && obj->corpsenm != PM_LIZARD
X && mon->data->mlet != S_FUNGUS) ||
X (acidic(&mons[obj->corpsenm]) &&
X !resists_acid(mon->data)) ||
X (poisonous(&mons[obj->corpsenm]) &&
X !resists_poison(mon->data)))
X return POISON;
X else if (fptr->mlet == S_FUNGUS)
X return (herbi ? CADAVER : MANFOOD);
X else if (is_meaty(fptr))
X return (carni ? CADAVER : MANFOOD);
X else return (carni ? ACCFOOD : MANFOOD);
X case CLOVE_OF_GARLIC:
X return (is_undead(mon->data) ? TABU :
X (herbi ? ACCFOOD : MANFOOD));
X case TIN:
X return (metallivorous(mon->data) ? ACCFOOD : MANFOOD);
X case APPLE:
X case CARROT:
X return (herbi ? DOGFOOD : MANFOOD);
X case BANANA:
X return ((mon->data->mlet == S_YETI) ? DOGFOOD :
X (herbi ? ACCFOOD : MANFOOD));
X default:
X#ifdef TUTTI_FRUTTI
X return (obj->otyp > SLIME_MOLD ?
X#else
X return (obj->otyp > CLOVE_OF_GARLIC ?
X#endif
X (carni ? ACCFOOD : MANFOOD) :
X (herbi ? ACCFOOD : MANFOOD));
X }
X default:
X if (hates_silver(mon->data) &&
X objects[obj->otyp].oc_material == SILVER)
X return(TABU);
X if (mon->data == &mons[PM_GELATINOUS_CUBE] && is_organic(obj))
X return(ACCFOOD);
X if (metallivorous(mon->data) && is_metallic(obj))
X /* Ferrous based metals are preferred. */
X return(objects[obj->otyp].oc_material == IRON ? DOGFOOD :
X ACCFOOD);
X if(!obj->cursed && obj->oclass != BALL_CLASS &&
X obj->oclass != CHAIN_CLASS)
X return(APPORT);
X /* fall into next case */
X case ROCK_CLASS:
X return(UNDEF);
X }
X}
X
X#endif /* OVL1 */
X#ifdef OVLB
X
Xstruct monst *
Xtamedog(mtmp, obj)
Xregister struct monst *mtmp;
Xregister struct obj *obj;
X{
X register struct monst *mtmp2;
X
X /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */
X if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA]
X#ifdef MULDGN
X || (mtmp->data->mflags3 & M3_WANTSARTI)
X#endif
X )
X return((struct monst *)0);
X
X /* worst case, at least he'll be peaceful. */
X mtmp->mpeaceful = 1;
X set_malign(mtmp);
X if(flags.moonphase == FULL_MOON && night() && rn2(6) && obj
X && mtmp->data->mlet == S_DOG)
X return((struct monst *)0);
X
X /* If we cannot tame him, at least he's no longer afraid. */
X mtmp->mflee = 0;
X mtmp->mfleetim = 0;
X if(mtmp->mtame || !mtmp->mcanmove ||
X /* monsters with conflicting structures cannot be tamed */
X mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion ||
X#ifdef POLYSELF
X is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(uasmon))
X#else
X is_human(mtmp->data) || is_demon(mtmp->data)
X#endif
X || (mtmp->data->mflags3 &
X (M3_WANTSAMUL|M3_WANTSBELL|M3_WANTSBOOK|M3_WANTSCAND))
X )
X return((struct monst *)0);
X if(obj) {
X if(dogfood(mtmp, obj) >= MANFOOD) return((struct monst *)0);
X if(cansee(mtmp->mx,mtmp->my))
X pline("%s devours the %s.", Monnam(mtmp), xname(obj));
X obfree(obj, (struct obj *)0);
X }
X if (u.uswallow && mtmp == u.ustuck)
X expels(mtmp, mtmp->data, TRUE);
X mtmp2 = newmonst(sizeof(struct edog) + mtmp->mnamelth);
X *mtmp2 = *mtmp;
X mtmp2->mxlth = sizeof(struct edog);
X if(mtmp->mnamelth) Strcpy(NAME(mtmp2), NAME(mtmp));
X initedog(mtmp2);
X replmon(mtmp,mtmp2);
X newsym(mtmp2->mx, mtmp2->my);
X return(mtmp2);
X}
X
X#endif /* OVLB */
X
X/*dog.c*/
END_OF_FILE
if test 13007 -ne `wc -c <'src/dog.c'`; then
echo shar: \"'src/dog.c'\" unpacked with wrong size!
fi
# end of 'src/dog.c'
fi
if test -f 'src/shk.c2' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'src/shk.c2'\"
else
echo shar: Extracting \"'src/shk.c2'\" \(41942 characters\)
sed "s/^X//" >'src/shk.c2' <<'END_OF_FILE'
Xstatic void
Xadd_one_tobill(obj, dummy)
Xregister struct obj *obj;
Xregister boolean dummy;
X{
X register struct monst *shkp;
X register struct bill_x *bp;
X register int bct;
X register char roomno = *u.ushops;
X
X if(!*u.ushops) return;
X
X if(!(shkp = shop_keeper(roomno))) return;
X
X if(!inhishop(shkp)) return;
X
X if(onbill(obj, shkp, FALSE) || /* perhaps thrown away earlier */
X (obj->oclass == FOOD_CLASS && obj->oeaten))
X return;
X
X if(ESHK(shkp)->billct == BILLSZ) {
X You("got that for free!");
X return;
X }
X
X /* To recognize objects the shopkeeper is not interested in. -dgk
X */
X if (obj->no_charge) {
X obj->no_charge = 0;
X return;
X }
X
X bct = ESHK(shkp)->billct;
X bp = &(ESHK(shkp)->bill_p[bct]);
X bp->bo_id = obj->o_id;
X bp->bquan = obj->quan;
X if(dummy) { /* a dummy object must be inserted into */
X bp->useup = 1; /* the billobjs chain here. crucial for */
X obj->nobj = billobjs; /* eating floorfood in shop. see eat.c */
X billobjs = obj;
X } else bp->useup = 0;
X bp->price = get_cost(obj, shkp);
X ESHK(shkp)->billct++;
X obj->unpaid = 1;
X}
X
X/* recursive billing of objects within containers. */
Xstatic void
Xbill_box_content(obj, ininv, dummy, shkp)
Xregister struct obj *obj;
Xregister boolean ininv, dummy;
Xregister struct monst *shkp;
X{
X register struct obj *otmp;
X
X for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
X
X if(obj->otyp == GOLD_PIECE) continue;
X /* the "top" box is added in addtobill() */
X if(!otmp->no_charge)
X add_one_tobill(otmp, dummy);
X if(Is_container(otmp))
X bill_box_content(otmp, ininv, dummy, shkp);
X }
X
X}
X
Xvoid
Xaddtobill(obj, ininv, dummy, silent)
Xregister struct obj *obj;
Xregister boolean ininv, dummy, silent;
X{
X register struct monst *shkp;
X register char roomno = *u.ushops;
X long ltmp = 0L, cltmp = 0L, gltmp = 0L;
X register boolean container = Is_container(obj);
X
X if(!*u.ushops) return;
X
X if(!(shkp = shop_keeper(roomno))) return;
X
X if(!inhishop(shkp)) return;
X
X if(/* perhaps we threw it away earlier */
X onbill(obj, shkp, FALSE) ||
X (obj->oclass == FOOD_CLASS && obj->oeaten)
X ) return;
X
X if(ESHK(shkp)->billct == BILLSZ) {
X You("got that for free!");
X return;
X }
X
X if(obj->oclass == GOLD_CLASS) {
X costly_gold(obj->ox, obj->oy, obj->quan);
X return;
X }
X
X if(!obj->no_charge) ltmp = get_cost(obj, shkp);
X
X if (obj->no_charge && !container) {
X obj->no_charge = 0;
X return;
X }
X
X if(container) {
X if(obj->cobj == (struct obj *)0) {
X if(obj->no_charge) {
X obj->no_charge = 0;
X return;
X } else {
X add_one_tobill(obj, dummy);
X goto speak;
X }
X } else {
X cltmp += contained_cost(obj, shkp, cltmp, FALSE);
X gltmp += contained_gold(obj);
X }
X
X if(ltmp) add_one_tobill(obj, dummy);
X if(cltmp) bill_box_content(obj, ininv, dummy, shkp);
X picked_container(obj); /* reset contained obj->no_charge */
X
X ltmp += cltmp;
X
X if(gltmp) {
X costly_gold(obj->ox, obj->oy, gltmp);
X if(!ltmp) return;
X }
X
X if(obj->no_charge)
X obj->no_charge = 0;
X
X } else /* i.e., !container */
X add_one_tobill(obj, dummy);
Xspeak:
X if(!shkp->msleep && !shkp->mfrozen && !silent) {
X char buf[BUFSZ];
X
X if(!ltmp) {
X pline("%s has no interest in %s.", Monnam(shkp),
X the(xname(obj)));
X return;
X }
X Strcpy(buf, "\"For you, ");
X if (ANGRY(shkp)) Strcat(buf, "scum ");
X else {
X switch(rnd(4) + u.uevent.udemigod) {
X case 1: Strcat(buf, "good");
X break;
X case 2: Strcat(buf, "honored");
X break;
X case 3: Strcat(buf, "most gracious");
X break;
X case 4: Strcat(buf, "esteemed");
X break;
X case 5: Strcat(buf, "most renowned and sacred");
X break;
X }
X#ifdef POLYSELF
X if(!is_human(uasmon)) Strcat(buf, " creature");
X else
X#endif
X Strcat(buf, (flags.female) ? " lady" : " sir");
X }
X /* after all, the shk is telling you what it is */
X obj->dknown = 1;
X exercise(A_WIS, TRUE);
X if(ininv) {
X long quan = obj->quan;
X obj->quan = 1L; /* fool xname() into giving singular */
X pline("%s; only %ld %s %s.\"", buf, ltmp,
X (quan > 1L) ? "per" : "for this", xname(obj));
X obj->quan = quan;
X } else
X pline("%s will cost you %ld zorkmid%s%s.",
X The(xname(obj)), ltmp, plur(ltmp),
X (obj->quan > 1L) ? " each" : "");
X } else if(!silent) {
X if(ltmp) pline("The list price of %s is %ld zorkmid%s%s.",
X the(xname(obj)), ltmp, plur(ltmp),
X (obj->quan > 1L) ? " each" : "");
X else pline("%s does not notice.", Monnam(shkp));
X }
X}
X
Xvoid
Xsplitbill(obj, otmp)
Xregister struct obj *obj, *otmp;
X{
X /* otmp has been split off from obj */
X register struct bill_x *bp;
X register long tmp;
X register struct monst *shkp = shop_keeper(*u.ushops);
X
X if(!shkp || !inhishop(shkp)) {
X impossible("splitbill: no resident shopkeeper??");
X return;
X }
X bp = onbill(obj, shkp, FALSE);
X if(!bp) {
X impossible("splitbill: not on bill?");
X return;
X }
X if(bp->bquan < otmp->quan) {
X impossible("Negative quantity on bill??");
X }
X if(bp->bquan == otmp->quan) {
X impossible("Zero quantity on bill??");
X }
X bp->bquan -= otmp->quan;
X
X if(ESHK(shkp)->billct == BILLSZ) otmp->unpaid = 0;
X else {
X tmp = bp->price;
X bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
X bp->bo_id = otmp->o_id;
X bp->bquan = otmp->quan;
X bp->useup = 0;
X bp->price = tmp;
X ESHK(shkp)->billct++;
X }
X}
X
Xstatic void
Xsub_one_frombill(obj, shkp)
Xregister struct obj *obj;
Xregister struct monst *shkp;
X{
X register struct bill_x *bp;
X
X if((bp = onbill(obj, shkp, FALSE)) != 0) {
X register struct obj *otmp;
X
X obj->unpaid = 0;
X if(bp->bquan > obj->quan){
X otmp = newobj(0);
X *otmp = *obj;
X bp->bo_id = otmp->o_id = flags.ident++;
X otmp->quan = (bp->bquan -= obj->quan);
X otmp->owt = 0; /* superfluous */
X otmp->onamelth = 0;
X bp->useup = 1;
X otmp->nobj = billobjs;
X billobjs = otmp;
X return;
X }
X ESHK(shkp)->billct--;
X#ifdef DUMB
X {
X /* DRS/NS 2.2.6 messes up -- Peter Kendell */
X int indx = ESHK(shkp)->billct;
X *bp = ESHK(shkp)->bill_p[indx];
X }
X#else
X *bp = ESHK(shkp)->bill_p[ESHK(shkp)->billct];
X#endif
X return;
X } else if (obj->unpaid) {
X impossible("sub_one_frombill: unpaid object not on bill");
X obj->unpaid = 0;
X }
X}
X
X/* recursive check of unpaid objects within nested containers. */
Xvoid
Xsubfrombill(obj, shkp)
Xregister struct obj *obj;
Xregister struct monst *shkp;
X{
X register struct obj *otmp;
X
X sub_one_frombill(obj, shkp);
X
X if(Is_container(obj))
X for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
X if(otmp->otyp == GOLD_PIECE) continue;
X
X if(Is_container(otmp))
X subfrombill(otmp, shkp);
X else
X sub_one_frombill(otmp, shkp);
X }
X}
X
Xstatic long
Xstolen_container(obj, shkp, price, ininv)
Xregister struct obj *obj;
Xregister struct monst *shkp;
Xlong price;
Xregister boolean ininv;
X{
X register struct obj *otmp;
X
X if(ininv && obj->unpaid)
X price += get_cost(obj, shkp);
X else {
X if(!obj->no_charge)
X price += get_cost(obj, shkp);
X obj->no_charge = 0;
X }
X
X /* the price of contained objects, if any */
X for(otmp = obj->cobj; otmp; otmp = otmp->nobj) {
X
X if(otmp->otyp == GOLD_PIECE) continue;
X
X if(!Is_container(otmp)) {
X if(ininv) {
X if(otmp->unpaid)
X price += get_cost(otmp, shkp);
X } else {
X if(!otmp->no_charge) {
X if(!(otmp->oclass == BALL_CLASS ||
X (otmp->oclass == FOOD_CLASS && otmp->oeaten) ||
X (Is_candle(otmp) && otmp->age <
X 20L * (long)objects[otmp->otyp].oc_cost))
X ) price += get_cost(otmp, shkp);
X }
X otmp->no_charge = 0;
X }
X } else
X price += stolen_container(otmp, shkp, price, ininv);
X }
X
X return(price);
X}
X
Xlong
Xstolen_value(obj, x, y, peaceful, silent)
Xregister struct obj *obj;
Xregister xchar x, y;
Xregister boolean peaceful, silent;
X{
X register long value = 0L, gvalue = 0L;
X register struct monst *shkp;
X register boolean goods;
X
X shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
X
X if (!shkp || !inhishop(shkp))
X return (0L);
X
X goods = saleable(rooms[ESHK(shkp)->shoproom -
X ROOMOFFSET].rtype-SHOPBASE, obj);
X goods = (goods && !obj->no_charge);
X
X if(obj->otyp == GOLD_PIECE) {
X gvalue += obj->quan;
X } else if(Is_container(obj)) {
X register boolean ininv = !!count_unpaid(obj->cobj);
X
X value += stolen_container(obj, shkp, value, ininv);
X if(!ininv) gvalue += contained_gold(obj);
X } else if(goods) {
X value += get_cost(obj, shkp);
X }
X
X if(gvalue + value == 0L) return(0L);
X
X value += gvalue;
X
X if(peaceful) {
X value = check_credit(value, shkp);
X ESHK(shkp)->debit += value;
X
X if(!silent) {
X if(obj->otyp == GOLD_PIECE)
X You("owe %s %ld zorkmids!", mon_nam(shkp), value);
X else You("owe %s %ld zorkmids for %s!",
X mon_nam(shkp),
X value,
X obj->quan > 1L ? "them" : "it");
X }
X } else {
X ESHK(shkp)->robbed += value;
X
X if(!silent) {
X if(cansee(shkp->mx, shkp->my)) {
X if(ESHK(shkp)->customer[0] == 0)
X (void) strncpy(ESHK(shkp)->customer,plname,PL_NSIZ);
X Norep("%s booms: \"%s, you are a thief!\"",
X Monnam(shkp), plname);
X } else Norep("You hear a scream, \"Thief!\"");
X }
X hot_pursuit(shkp);
X (void) angry_guards(FALSE);
X }
X return(value);
X}
X
X/* auto-response flag for/from "sell foo?" 'a' => 'y', 'q' => 'n' */
Xstatic char sell_response = 'a';
X
Xvoid
Xsellobj_state(deliberate) /* called from dodrop(do.c) and doddrop() */
Xregister boolean deliberate;
X{
X /* If we're deliberately dropping something, there's no automatic
X response to the shopkeeper's "want to sell" query; however, if we
X accidentally drop anything, the shk will buy it/them without asking.
X This retains the old pre-query risk that slippery fingers while in
X shops entailed: you drop it, you've lost it.
X */
X sell_response = deliberate ? '\0' : 'a';
X}
X
Xvoid
Xsellobj(obj, x, y)
Xregister struct obj *obj;
Xregister xchar x, y;
X{
X register struct monst *shkp;
X register struct eshk *eshkp;
X register long ltmp = 0L, cltmp = 0L, gltmp = 0L, offer;
X boolean saleitem, cgold = FALSE, container = Is_container(obj);
X boolean isgold = (obj->oclass == GOLD_CLASS);
X
X if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) ||
X !inhishop(shkp)) return;
X if(!costly_spot(x, y)) return;
X if(!*u.ushops) return;
X
X saleitem = saleable(rooms[ESHK(shkp)->shoproom -
X ROOMOFFSET].rtype-SHOPBASE, obj);
X
X if(obj->unpaid && !container && !isgold) {
X sub_one_frombill(obj, shkp);
X return;
X }
X if(container) {
X if(obj->cobj == (struct obj *)0) {
X if(obj->unpaid) {
X sub_one_frombill(obj, shkp);
X return;
X }
X } else {
X /* find the price of content before subfrombill */
X cltmp += contained_cost(obj, shkp, cltmp, TRUE);
X /* find the value of contained gold */
X gltmp += contained_gold(obj);
X cgold = (gltmp > 0L);
X }
X }
X
X if(!isgold && !obj->unpaid && saleitem)
X ltmp = set_cost(obj, shkp);
X
X offer = ltmp + cltmp;
X
X if(!isgold && (offer + gltmp) == 0L) {
X register boolean unpaid = (obj->unpaid ||
X (container && count_unpaid(obj->cobj)));
X
X if(container) {
X if(obj->cobj != (struct obj *)0) {
X dropped_container(obj);
X if(obj->unpaid || count_unpaid(obj->cobj))
X subfrombill(obj, shkp);
X } else obj->no_charge = 1;
X } else obj->no_charge = 1;
X
X if(!unpaid)
X pline("%s seems uninterested.", Monnam(shkp));
X return;
X }
X
X /* you dropped something of your own - probably want to sell it */
X if(shkp->msleep || !shkp->mcanmove) {
X if(container && obj->cobj != (struct obj *)0) {
X dropped_container(obj);
X }
X if(!shkp->mcanmove) {
X if(ANGRY(shkp) && !rn2(4))
X pline("%s utters a curse.", Monnam(shkp));
X else pline("%s is indisposed.", Monnam(shkp));
X } else if(!rn2(3)) {
X pline("%s snores indifferently.", Monnam(shkp));
X }
X subfrombill(obj, shkp);
X return;
X }
X
X eshkp = ESHK(shkp);
X
X if(isgold || cgold) {
X if(ANGRY(shkp)) {
X if(!offer) {
X pline("%s is not appeased.", Monnam(shkp));
X if(cgold) subfrombill(obj, shkp);
X return;
X } else goto move_on;
X }
X
X if(!cgold) gltmp = obj->quan;
X
X if(eshkp->debit >= gltmp) {
X if(eshkp->loan) { /* you carry shop's gold */
X if(eshkp->loan >= gltmp)
X eshkp->loan -= gltmp;
X else eshkp->loan = 0L;
X }
X eshkp->debit -= gltmp;
X Your("debt is %spaid off.",
X eshkp->debit ? "partially " : "");
X } else {
X long delta = gltmp - eshkp->debit;
X
X eshkp->credit += delta;
X if(eshkp->debit) {
X eshkp->debit = 0L;
X eshkp->loan = 0L;
X Your("debt is paid off.");
X }
X pline("%ld zorkmid%s added to your credit.",
X delta, delta > 1L ? "s are" : " is");
X }
X if(offer) goto move_on;
X else {
X if(container && obj->cobj != (struct obj *)0) {
X dropped_container(obj);
X }
X subfrombill(obj, shkp);
X obj->no_charge = 1;
X return;
X }
X }
Xmove_on:
X if (ANGRY(shkp)) { /* they become shop-objects, no pay */
X pline("Thank you, scum!");
X subfrombill(obj, shkp);
X return;
X }
X
X if((!saleitem && !(container && cltmp > 0L))
X || eshkp->billct == BILLSZ
X || obj->oclass == BALL_CLASS || offer == 0L
X || (obj->oclass == FOOD_CLASS && obj->oeaten)
X || (Is_candle(obj) &&
X obj->age < 20L * (long)objects[obj->otyp].oc_cost)) {
X pline("%s seems not interested%s.", Monnam(shkp),
X cgold ? " in the rest" : "");
X if(container && obj->cobj != (struct obj *)0) {
X dropped_container(obj);
X }
X obj->no_charge = 1;
X return;
X }
X
X if(eshkp->robbed) { /* shkp is not angry? */
X if((eshkp->robbed -= offer < 0L))
X eshkp->robbed = 0L;
X verbalize(
X "Thank you for your contribution to restock this recently plundered shop.");
X subfrombill(obj, shkp);
X return;
X }
X
X if(!shkp->mgold) {
X long tmpcr = (ltmp + cltmp) * 2L;
X
X pline("%s cannot pay you at present.", Monnam(shkp));
X pline("Will you accept %ld zorkmids in credit for %s? ",
X tmpcr, doname(obj));
X /* cannot use a yn function here */
X if (readchar() == 'y') {
X You("have %ld zorkmids in %scredit.", tmpcr,
X ESHK(shkp)->credit > 0L ? "additional " : "");
X ESHK(shkp)->credit += tmpcr;
X subfrombill(obj, shkp);
X } else {
X if(container && obj->cobj != (struct obj *)0) {
X dropped_container(obj);
X }
X subfrombill(obj, shkp);
X obj->no_charge = 1;
X }
X } else {
X int qlen;
X char qbuf[BUFSZ];
X boolean short_funds = (offer > shkp->mgold);
X
X if (short_funds) offer = shkp->mgold;
X
X if (!sell_response) {
X Sprintf(qbuf,
X "%s offers%s %ld gold piece%s for%s your %s.",
X Monnam(shkp), short_funds ? " only" : "",
X offer, plur(offer),
X (!ltmp && cltmp) ? " the contents of" : "",
X xname(obj));
X qlen = strlen(qbuf);
X /* Will the prompt fit on the topline? (or would
X * "--more--" force line wrap anyway?) If so, combine
X * the message and prompt; otherwise, flush message
X * and prompt separately.
X */
X if (qlen > COLNO - 24 && qlen <= COLNO - 8)
X pline(qbuf), qbuf[0] = '\0';
X else Strcat(qbuf, " ");
X Strcat(strcat(qbuf, "Sell "),
X (obj->quan == 1L ? "it?" : "them?"));
X } else qbuf[0] = '\0'; /* just to pacify lint */
X
X switch (sell_response ? sell_response : ynaq(qbuf)) {
X case 'q': sell_response = 'n';
X case 'n': if(container && obj->cobj != (struct obj *)0) {
X dropped_container(obj);
X }
X subfrombill(obj, shkp);
X obj->no_charge = 1;
X break;
X case 'a': sell_response = 'y';
X case 'y': subfrombill(obj, shkp);
X pay(-offer, shkp);
X You("sold %s for %ld gold piece%s.", doname(obj),
X offer, plur(offer));
X break;
X default: impossible("invalid sell response");
X }
X }
X}
X
Xint
Xdoinvbill(mode)
Xint mode; /* 0: deliver count 1: paged */
X{
X register struct monst* shkp;
X register struct bill_x *bp, *end_bp;
X register struct obj *obj;
X long totused;
X char *buf_p;
X winid datawin;
X
X shkp = shop_keeper(*u.ushops);
X
X if(mode == 0) {
X register int cnt = 0;
X
X if(shkp && inhishop(shkp))
X for (bp = ESHK(shkp)->bill_p,
X end_bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
X bp < end_bp; bp++)
X if(bp->useup ||
X ((obj = bp_to_obj(bp)) && obj->quan < bp->bquan))
X cnt++;
X return(cnt);
X }
X
X if(!shkp || !inhishop(shkp)) {
X impossible("doinvbill: no shopkeeper?");
X return(0);
X }
X
X datawin = create_nhwindow(NHW_MENU);
X putstr(datawin, 0, "Unpaid articles already used up:");
X putstr(datawin, 0, "");
X
X totused = 0L;
X for (bp = ESHK(shkp)->bill_p,
X end_bp = &(ESHK(shkp)->bill_p[ESHK(shkp)->billct]);
X bp < end_bp; bp++) {
X obj = bp_to_obj(bp);
X if(!obj) {
X impossible("Bad shopkeeper administration.");
X goto quit;
X }
X if(bp->useup || bp->bquan > obj->quan) {
X register long oquan, uquan;
X long thisused;
X
X oquan = obj->quan;
X uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
X thisused = bp->price * uquan;
X totused += thisused;
X obj->quan = uquan; /* cheat doname */
X buf_p = xprname(obj, ' ', FALSE, thisused);
X obj->quan = oquan; /* restore value */
X putstr(datawin, 0, buf_p);
X }
X }
X buf_p = xprname((struct obj *)0, '*', FALSE, totused);
X putstr(datawin, 0, "");
X putstr(datawin, 0, buf_p);
X display_nhwindow(datawin, FALSE);
X quit:
X destroy_nhwindow(datawin);
X return(0);
X}
X
X#define HUNGRY 2
X
Xstatic long
Xgetprice(obj)
Xregister struct obj *obj;
X{
X register long tmp = (long) objects[obj->otyp].oc_cost;
X
X switch(obj->oclass) {
X case FOOD_CLASS:
X /* simpler hunger check, (2-4)*cost */
X if (u.uhs >= HUNGRY) tmp *= (long) u.uhs;
X if (obj->oeaten) tmp = 0L;
X break;
X case WAND_CLASS:
X if (obj->spe == -1) tmp = 0L;
X break;
X case POTION_CLASS:
X if (obj->otyp == POT_WATER && !obj->blessed && !obj->cursed)
X tmp = 0L;
X break;
X case ARMOR_CLASS:
X case WEAPON_CLASS:
X if (obj->spe > 0) tmp += 10L * (long) obj->spe;
X break;
X case CHAIN_CLASS:
X pline("Strange... carrying a chain?");
X break;
X case TOOL_CLASS:
X if (Is_candle(obj) &&
X obj->age < 20L * (long)objects[obj->otyp].oc_cost)
X tmp /= 2L;
X break;
X }
X if (obj->oartifact) tmp *= 25L;
X return tmp;
X}
X
Xint
Xshkcatch(obj, x, y)
Xregister struct obj *obj;
Xregister xchar x, y;
X{
X register struct monst *shkp;
X
X if (!(shkp = shop_keeper(inside_shop(x, y))) ||
X !inhishop(shkp)) return(0);
X
X if (shkp->mcanmove && !shkp->msleep &&
X (*u.ushops != ESHK(shkp)->shoproom || !inside_shop(u.ux, u.uy)) &&
X dist2(shkp->mx, shkp->my, x, y) < 3 &&
X /* if it is the shk's pos, you hit and anger him */
X (shkp->mx != x || shkp->my != y)) {
X if (mnearto(shkp, x, y, TRUE))
X verbalize("Out of my way, scum!");
X pline("%s nimbly catches %s.", Monnam(shkp), the(xname(obj)));
X mpickobj(shkp, obj);
X subfrombill(obj, shkp);
X return(1);
X }
X return(0);
X}
X
Xvoid
Xadd_damage(x, y, cost)
Xregister xchar x, y;
Xlong cost;
X{
X struct damage *tmp_dam;
X char *shops;
X
X if (IS_DOOR(levl[x][y].typ))
X /* Don't schedule for repair unless it's a real shop entrance */
X for (shops = in_rooms(x, y, SHOPBASE); *shops; shops++) {
X struct monst *mtmp = shop_keeper(*shops);
X
X if (!mtmp)
X continue;
X if ((x != ESHK(mtmp)->shd.x) || (y != ESHK(mtmp)->shd.y))
X return;
X }
X tmp_dam = (struct damage *)alloc((unsigned)sizeof(struct damage));
X tmp_dam->when = monstermoves;
X tmp_dam->place.x = x;
X tmp_dam->place.y = y;
X tmp_dam->cost = cost;
X tmp_dam->typ = levl[x][y].typ;
X tmp_dam->next = level.damagelist;
X level.damagelist = tmp_dam;
X /* If player saw damage, display as a wall forever */
X if (cansee(x, y))
X levl[x][y].seen = 1;
X}
X
X/*
X * Do something about damage. Either (!croaked) try to repair it, or
X * (croaked) just discard damage structs for non-shared locations, since
X * they'll never get repaired. Assume that shared locations will get
X * repaired eventually by the other shopkeeper(s). This might be an erroneous
X * assumption (they might all be dead too), but we have no reasonable way of
X * telling that.
X */
Xstatic
Xvoid
Xremove_damage(shkp, croaked)
Xregister struct monst *shkp;
Xregister boolean croaked;
X{
X register struct damage *tmp_dam, *tmp2_dam;
X register boolean did_repair = FALSE, saw_door = FALSE;
X register boolean saw_floor = FALSE, stop_picking = FALSE;
X uchar saw_walls = 0;
X
X tmp_dam = level.damagelist;
X tmp2_dam = 0;
X while (tmp_dam) {
X register xchar x = tmp_dam->place.x, y = tmp_dam->place.y;
X char shops[5];
X uchar disposition;
X
X disposition = 0;
X Strcpy(shops, in_rooms(x, y, SHOPBASE));
X if (index(shops, ESHK(shkp)->shoproom)) {
X if (croaked)
X disposition = (shops[1])? 0 : 1;
X else if (stop_picking)
X disposition = repair_damage(shkp, tmp_dam);
X else {
X /* Defer the stop_occupation() until after repair msgs */
X if (closed_door(x, y))
X stop_picking = picking_at(x, y);
X disposition = repair_damage(shkp, tmp_dam);
X if (!disposition)
X stop_picking = FALSE;
X }
X }
X
X if (!disposition) {
X tmp2_dam = tmp_dam;
X tmp_dam = tmp_dam->next;
X continue;
X }
X
X if (disposition > 1) {
X did_repair = TRUE;
X if (cansee(x, y)) {
X if (IS_WALL(levl[x][y].typ))
X saw_walls++;
X else if (IS_DOOR(levl[x][y].typ))
X saw_door = TRUE;
X else
X saw_floor = TRUE;
X }
X }
X
X tmp_dam = tmp_dam->next;
X if (!tmp2_dam) {
X free((genericptr_t)level.damagelist);
X level.damagelist = tmp_dam;
X } else {
X free((genericptr_t)tmp2_dam->next);
X tmp2_dam->next = tmp_dam;
X }
X }
X if (!did_repair)
X return;
X if (saw_walls) {
X pline("Suddenly, %s section%s of wall close%s up!",
X (saw_walls == 1) ? "a" : (saw_walls <= 3) ?
X "some" : "several",
X (saw_walls == 1) ? "" : "s", (saw_walls == 1) ? "s" : "");
X if (saw_door)
X pline("The shop door reappears!");
X if (saw_floor)
X pline("The floor is repaired!");
X } else {
X if (saw_door)
X pline("Suddenly, the shop door reappears!");
X else if (saw_floor)
X pline("Suddenly, the floor damage is gone!");
X else if (inside_shop(u.ux, u.uy) == ESHK(shkp)->shoproom)
X You("feel more claustrophobic than before.");
X else if (flags.soundok && !rn2(10))
X Norep("The dungeon acoustics noticeably change.");
X }
X if (stop_picking)
X stop_occupation();
X}
X
X/*
X * 0: repair postponed, 1: silent repair (no messages), 2: normal repair
X */
Xchar
Xrepair_damage(shkp, tmp_dam)
Xregister struct monst *shkp;
Xregister struct damage *tmp_dam;
X{
X register xchar x, y, i;
X xchar litter[9];
X register struct monst *mtmp;
X register struct obj *otmp;
X register struct trap *ttmp;
X
X if ((monstermoves - tmp_dam->when) < REPAIR_DELAY)
X return(0);
X if (ESHK(shkp)->following)
X return(0);
X x = tmp_dam->place.x;
X y = tmp_dam->place.y;
X if (!IS_ROOM(tmp_dam->typ)) {
X if ((x == u.ux) && (y == u.uy))
X#ifdef POLYSELF
X if (!passes_walls(uasmon))
X#endif
X return(0);
X if ((x == shkp->mx) && (y == shkp->my))
X return(0);
X if ((mtmp = m_at(x, y)) && (!passes_walls(mtmp->data)))
X return(0);
X }
X if ((ttmp = t_at(x, y)) != 0)
X deltrap(ttmp);
X if (IS_ROOM(tmp_dam->typ)) {
X /* No messages if player already filled trapdoor */
X if (!ttmp)
X return(1);
X newsym(x, y);
X return(2);
X }
X if (!ttmp && (tmp_dam->typ == levl[x][y].typ) &&
X (!IS_DOOR(tmp_dam->typ) || (levl[x][y].doormask > D_BROKEN)))
X /* No messages if player already replaced shop door */
X return(1);
X levl[x][y].typ = tmp_dam->typ;
X (void) memset((genericptr_t)litter, 0, sizeof(litter));
X if ((otmp = level.objects[x][y]) != 0) {
X /* Scatter objects haphazardly into the shop */
X#define NEED_UPDATE 1
X#define OPEN 2
X#define INSHOP 4
X#define horiz(i) ((i%3)-1)
X#define vert(i) ((i/3)-1)
X for (i = 0; i < 9; i++) {
X if ((i == 4) || (!ZAP_POS(levl[x+horiz(i)][y+vert(i)].typ)))
X continue;
X litter[i] = OPEN;
X if (inside_shop(x+horiz(i),
X y+vert(i)) == ESHK(shkp)->shoproom)
X litter[i] |= INSHOP;
X }
X if (Punished && ((uchain->ox == x && uchain->oy == y) ||
X (uball->ox == x && uball->oy == y))) {
X /*
X * Either the ball or chain is in the repair location.
X *
X * Take the easy way out and put ball&chain under hero.
X */
X verbalize("Get your junk out of my wall!");
X unplacebc(); /* pick 'em up */
X placebc(); /* put 'em down */
X }
X while ((otmp = level.objects[x][y]) != 0)
X /* Don't mess w/ boulders -- just merge into wall */
X if ((otmp->otyp == BOULDER) || (otmp->otyp == ROCK)) {
X freeobj(otmp);
X obfree(otmp, (struct obj *)0);
X } else {
X while (!(litter[i = rn2(9)] & INSHOP));
X remove_object(otmp);
X place_object(otmp, x+horiz(i), y+vert(i));
X litter[i] |= NEED_UPDATE;
X }
X }
X block_point(x, y);
X if(IS_DOOR(tmp_dam->typ)) {
X levl[x][y].doormask = D_CLOSED; /* arbitrary */
X newsym(x, y);
X } else {
X levl[x][y].doormask = D_NODOOR;
X if (IS_WALL(tmp_dam->typ) && cansee(x, y)) {
X /* Player sees actual repair process, so they KNOW it's a wall */
X levl[x][y].seen = 1;
X newsym(x, y);
X } else if (levl[x][y].seen) {
X /* Force a display update */
X levl[x][y].diggable |= W_REPAIRED;
X }
X }
X for (i = 0; i < 9; i++)
X if (litter[i] & NEED_UPDATE)
X newsym(x+horiz(i), y+vert(i));
X return(2);
X#undef NEED_UPDATE
X#undef OPEN
X#undef INSHOP
X#undef vert
X#undef horiz
X}
X
X/*
X * shk_move: return 1: moved 0: didn't -1: let m_move do it -2: died
X */
Xint
Xshk_move(shkp)
Xregister struct monst *shkp;
X{
X register xchar gx,gy,omx,omy;
X register int udist;
X register schar appr;
X register struct eshk *eshkp = ESHK(shkp);
X int z;
X boolean uondoor = FALSE, satdoor, avoid = FALSE, badinv;
X
X omx = shkp->mx;
X omy = shkp->my;
X
X if (inhishop(shkp))
X remove_damage(shkp, FALSE);
X
X if((udist = distu(omx,omy)) < 3 &&
X (shkp->data != &mons[PM_GRID_BUG] || (omx==u.ux || omy==u.uy))) {
X if(ANGRY(shkp) ||
X (Conflict && !resist(shkp, RING_CLASS, 0, 0))) {
X if(Displaced)
X Your("displaced image doesn't fool %s!",
X mon_nam(shkp));
X (void) mattacku(shkp);
X return(0);
X }
X if(eshkp->following) {
X if(strncmp(eshkp->customer, plname, PL_NSIZ)) {
X verbalize("Hello, %s! I was looking for %s.",
X plname, eshkp->customer);
X eshkp->following = 0;
X return(0);
X }
X if(moves > followmsg+4) {
X verbalize("Hello, %s! Didn't you forget to pay?",
X plname);
X followmsg = moves;
X if (!rn2(4)) {
X pline ("%s doesn't like customers who don't pay.", Monnam(shkp));
X rile_shk(shkp);
X }
X }
X if(udist < 2)
X return(0);
X }
X }
X
X appr = 1;
X gx = eshkp->shk.x;
X gy = eshkp->shk.y;
X satdoor = (gx == omx && gy == omy);
X if(eshkp->following || ((z = holetime()) >= 0 && z*z <= udist)){
X if(udist > 4)
X return(-1); /* leave it to m_move */
X gx = u.ux;
X gy = u.uy;
X } else if(ANGRY(shkp)) {
X /* Move towards the hero if the shopkeeper can see him. */
X if(shkp->mcansee && m_canseeu(shkp)) {
X gx = u.ux;
X gy = u.uy;
X }
X avoid = FALSE;
X } else {
X#define GDIST(x,y) (dist2(x,y,gx,gy))
X if(Invis) {
X avoid = FALSE;
X } else {
X uondoor = (u.ux == eshkp->shd.x && u.uy == eshkp->shd.y);
X if(uondoor) {
X badinv = (!!carrying(PICK_AXE));
X if(satdoor && badinv)
X return(0);
X avoid = !badinv;
X } else {
X avoid = (*u.ushops && distu(gx,gy) > 8);
X badinv = FALSE;
X }
X
X if(((!eshkp->robbed && !eshkp->billct && !eshkp->debit)
X || avoid) && GDIST(omx,omy) < 3) {
X if (!badinv && !onlineu(omx,omy))
X return(0);
X if(satdoor)
X appr = gx = gy = 0;
X }
X }
X }
X
X return(move_special(shkp,inhishop(shkp),
X appr,uondoor,avoid,omx,omy,gx,gy));
X}
X
X/* for use in levl_follower (mondata.c) */
Xboolean
Xis_fshk(mtmp)
Xregister struct monst *mtmp;
X{
X return(mtmp->isshk && ESHK(mtmp)->following);
X}
X
X/* You are digging in the shop. */
Xvoid
Xshopdig(fall)
Xregister int fall;
X{
X register struct monst *shkp = shop_keeper(*u.ushops);
X
X if(!shkp) return;
X
X if(!inhishop(shkp)) {
X if (pl_character[0] == 'K') adjalign(-sgn(u.ualign.type));
X return;
X }
X
X if(!fall) {
X if(u.utraptype == TT_PIT)
X verbalize("Be careful, %s, or you might fall through the floor.",
X flags.female ? "madam" : "sir");
X else
X verbalize("%s, do not damage the floor here!",
X flags.female ? "Madam" : "Sir");
X if (pl_character[0] == 'K') adjalign(-sgn(u.ualign.type));
X } else if(!um_dist(shkp->mx, shkp->my, 5) &&
X !shkp->msleep && shkp->mcanmove &&
X (ESHK(shkp)->billct || ESHK(shkp)->debit)) {
X register struct obj *obj, *obj2;
X
X if (distu(shkp->mx, shkp->my) > 2) {
X mnexto(shkp);
X /* for some reason the shopkeeper can't come next to you */
X if (distu(shkp->mx, shkp->my) > 2) {
X pline("%s curses you in anger and frustration!",
X shkname(shkp));
X rile_shk(shkp);
X return;
X } else pline("%s leaps, and grabs your backpack!",
X shkname(shkp));
X } else pline("%s grabs your backpack!", shkname(shkp));
X
X for(obj = invent; obj; obj = obj2) {
X obj2 = obj->nobj;
X if(obj->owornmask) continue;
X#ifdef WALKIES
X if(obj->otyp == LEASH && obj->leashmon) continue;
X#endif
X freeinv(obj);
X obj->nobj = shkp->minvent;
X shkp->minvent = obj;
X subfrombill(obj, shkp);
X }
X }
X}
X
X#ifdef KOPS
XSTATIC_OVL void
Xmakekops(mm) /* returns the number of (all types of) Kops made */
Xcoord *mm;
X{
X register int cnt = depth(&u.uz) + rnd(5);
X register int scnt = (cnt / 3) + 1; /* at least one sarge */
X register int lcnt = (cnt / 6); /* maybe a lieutenant */
X register int kcnt = (cnt / 9); /* and maybe a kaptain */
X
X if (!(mons[PM_KEYSTONE_KOP].geno & G_EXTINCT)) {
X while(cnt--) {
X if (enexto(mm, mm->x, mm->y, &mons[PM_KEYSTONE_KOP]))
X (void) makemon(&mons[PM_KEYSTONE_KOP], mm->x, mm->y);
X }
X }
X if (!(mons[PM_KOP_SERGEANT].geno & G_EXTINCT)) {
X while(scnt--) {
X if (enexto(mm, mm->x, mm->y, &mons[PM_KOP_SERGEANT]))
X (void) makemon(&mons[PM_KOP_SERGEANT], mm->x, mm->y);
X }
X }
X if (!(mons[PM_KOP_LIEUTENANT].geno & G_EXTINCT)) {
X while(lcnt--) {
X if (enexto(mm, mm->x, mm->y, &mons[PM_KOP_LIEUTENANT]))
X (void) makemon(&mons[PM_KOP_LIEUTENANT], mm->x, mm->y);
X }
X }
X if (!(mons[PM_KOP_KAPTAIN].geno & G_EXTINCT)) {
X while(kcnt--) {
X if (enexto(mm, mm->x, mm->y, &mons[PM_KOP_KAPTAIN]))
X (void) makemon(&mons[PM_KOP_KAPTAIN], mm->x, mm->y);
X }
X }
X}
X#endif /* KOPS */
X
Xvoid
Xpay_for_damage(dmgstr)
Xconst char *dmgstr;
X{
X register struct monst *shkp = (struct monst *)0;
X char shops_affected[5];
X register boolean uinshp = (*u.ushops != '\0');
X char qbuf[80];
X register xchar x, y;
X register boolean dugwall = !strcmp(dmgstr, "dig into");
X struct damage *tmp_dam, *appear_here = 0;
X /* any number >= (80*80)+(24*24) would do, actually */
X long cost_of_damage = 0L;
X unsigned int nearest_shk = 7000, nearest_damage = 7000;
X int picks = 0;
X
X for (tmp_dam = level.damagelist;
X (tmp_dam && (tmp_dam->when == monstermoves));
X tmp_dam = tmp_dam->next) {
X char *shp;
X
X if (!tmp_dam->cost)
X continue;
X cost_of_damage += tmp_dam->cost;
X Strcpy(shops_affected,
X in_rooms(tmp_dam->place.x, tmp_dam->place.y, SHOPBASE));
X for (shp = shops_affected; *shp; shp++) {
X struct monst *tmp_shk;
X unsigned int shk_distance;
X
X if (!(tmp_shk = shop_keeper(*shp)))
X continue;
X if (tmp_shk == shkp) {
X unsigned int damage_distance =
X distu(tmp_dam->place.x, tmp_dam->place.y);
X
X if (damage_distance < nearest_damage) {
X nearest_damage = damage_distance;
X appear_here = tmp_dam;
X }
X continue;
X }
X if (!inhishop(tmp_shk))
X continue;
X shk_distance = distu(tmp_shk->mx, tmp_shk->my);
X if (shk_distance > nearest_shk)
X continue;
X if ((shk_distance == nearest_shk) && picks) {
X if (rn2(++picks))
X continue;
X } else
X picks = 1;
X shkp = tmp_shk;
X nearest_shk = shk_distance;
X appear_here = tmp_dam;
X nearest_damage = distu(tmp_dam->place.x, tmp_dam->place.y);
X }
X }
X
X if (!cost_of_damage || !shkp)
X return;
X
X x = appear_here->place.x;
X y = appear_here->place.y;
X
X /* not the best introduction to the shk... */
X (void) strncpy(ESHK(shkp)->customer,plname,PL_NSIZ);
X
X /* if the shk is already on the war path, be sure it's all out */
X if(ANGRY(shkp) || ESHK(shkp)->following) {
X hot_pursuit(shkp);
X return;
X }
X
X /* if the shk is not in their shop.. */
X if(!*in_rooms(shkp->mx,shkp->my,SHOPBASE)) {
X if(!cansee(shkp->mx, shkp->my))
X return;
X goto getcad;
X }
X
X if(uinshp) {
X if(um_dist(shkp->mx, shkp->my, 1) &&
X !um_dist(shkp->mx, shkp->my, 3)) {
X pline("%s leaps towards you!", shkname(shkp));
X mnexto(shkp);
X }
X if(um_dist(shkp->mx, shkp->my, 1)) goto getcad;
X } else {
X /*
X * Make shkp show up at the door. Effect: If there is a monster
X * in the doorway, have the hero hear the shopkeeper yell a bit,
X * pause, then have the shopkeeper appear at the door, having
X * yanked the hapless critter out of the way.
X */
X if (MON_AT(x, y)) {
X if(flags.soundok) {
X You("hear an angry voice:");
X verbalize("Out of my way, scum!");
X wait_synch();
X#if defined(UNIX) || defined(VMS)
X# if defined(SYSV) || defined(ULTRIX) || defined(VMS)
X (void)
X# endif
X sleep(1);
X#endif
X }
X }
X (void) mnearto(shkp, x, y, TRUE);
X }
X
X if((um_dist(x, y, 1) && !uinshp) ||
X (u.ugold + ESHK(shkp)->credit) < cost_of_damage
X || !rn2(50)) {
X if(um_dist(x, y, 1) && !uinshp) {
X pline("%s shouts:", shkname(shkp));
X verbalize("Who dared %s my %s?", dmgstr,
X dugwall ? "shop" : "door");
X } else {
Xgetcad:
X verbalize("How dare you %s my %s?", dmgstr,
X dugwall ? "shop" : "door");
X }
X hot_pursuit(shkp);
X return;
X }
X
X if(Invis) Your("invisibility does not fool %s!", shkname(shkp));
X Sprintf(qbuf,"\"Cad! You did %ld zorkmids worth of damage!\" Pay? ",
X cost_of_damage);
X if(yn(qbuf) != 'n') {
X cost_of_damage = check_credit(cost_of_damage, shkp);
X u.ugold -= cost_of_damage;
X shkp->mgold += cost_of_damage;
X flags.botl = 1;
X pline("Mollified, %s accepts your restitution.",
X shkname(shkp));
X /* move shk back to his home loc */
X home_shk(shkp, FALSE);
X pacify_shk(shkp);
X } else {
X verbalize("Oh, yes! You'll pay!");
X hot_pursuit(shkp);
X adjalign(-sgn(u.ualign.type));
X }
X}
X
X/* called in dokick.c when we kick an object that might be in a store */
Xboolean
Xcostly_spot(x, y)
Xregister xchar x, y;
X{
X register struct monst *shkp;
X
X if (!level.flags.has_shop) return FALSE;
X shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
X if(!shkp || !inhishop(shkp)) return(FALSE);
X
X return(inside_shop(x, y) &&
X !(x == ESHK(shkp)->shk.x &&
X y == ESHK(shkp)->shk.y));
X}
X
X/* called by dotalk(sounds.c) when #chatting; returns obj if location
X contains shop goods and shopkeeper is willing & able to speak */
Xstruct obj *
Xshop_object(x, y)
Xregister xchar x, y;
X{
X register struct obj *otmp;
X register struct monst *shkp;
X
X if(!(shkp = shop_keeper(*in_rooms(x, y, SHOPBASE))) || !inhishop(shkp))
X return(struct obj *)0;
X
X for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
X if (otmp->otyp != GOLD_PIECE)
X break;
X /* note: otmp might have ->no_charge set, but that's ok */
X return (otmp && costly_spot(x, y) && NOTANGRY(shkp)
X && !shkp->msleep && !shkp->mfrozen)
X ? otmp : (struct obj *)0;
X}
X
X/* give price quotes for all objects linked to this one (ie, on this spot) */
Xvoid
Xprice_quote(first_obj)
Xregister struct obj *first_obj;
X{
X register struct obj *otmp;
X char buf[BUFSZ], price[40];
X long cost;
X int cnt = 0;
X winid tmpwin;
X
X tmpwin = create_nhwindow(NHW_MENU);
X putstr(tmpwin, 0, "Fine goods for sale:");
X putstr(tmpwin, 0, "");
X for (otmp = first_obj; otmp; otmp = otmp->nexthere) {
X if (otmp->otyp == GOLD_PIECE) {
X /* if (otmp == first_obj) first_obj = otmp->nexthere; */
X continue; /* don't quote a price on this */
X } else if (otmp->no_charge) {
X Strcpy(price, "no charge");
X } else {
X cost = get_cost(otmp, (struct monst *)0);
X Sprintf(price, "%ld zorkmid%s%s", cost, plur(cost),
X otmp->quan > 1L ? " each" : "");
X }
X Sprintf(buf, "%s, %s", doname(otmp), price);
X putstr(tmpwin, 0, buf), cnt++;
X }
X if (cnt > 1) {
X display_nhwindow(tmpwin, TRUE);
X } else if (cnt == 1) {
X cost = get_cost(first_obj, (struct monst *)0);
X pline("%s, price %ld zorkmid%s%s%s", doname(first_obj),
X cost, plur(cost), first_obj->quan > 1L ? " each" : "",
X shk_embellish(first_obj, cost));
X }
X destroy_nhwindow(tmpwin);
X}
X
Xstatic const char *
Xshk_embellish(itm, cost)
Xregister struct obj *itm;
Xlong cost;
X{
X if (!rn2(3)) {
X register int o, choice = rn2(5);
X if (choice == 0) choice = (cost < 100L ? 1 : cost < 500L ? 2 : 3);
X switch (choice) {
X case 4:
X if (cost < 10L) break; else o = itm->oclass;
X if (o == FOOD_CLASS) return ", gourmets' delight!";
X if (objects[itm->otyp].oc_name_known
X ? objects[itm->otyp].oc_magic
X : (o == AMULET_CLASS || o == RING_CLASS ||
X o == WAND_CLASS || o == POTION_CLASS ||
X o == SCROLL_CLASS || o == SPBOOK_CLASS))
X return ", painstakingly developed!";
X return ", superb craftsmanship!";
X case 3: return ", finest quality.";
X case 2: return ", an excellent choice.";
X case 1: return ", a real bargain.";
X default: break;
X }
X } else if (itm->oartifact) {
X return ", one of a kind!";
X }
X return ".";
X}
X
X#ifdef KOPS
Xstatic void
Xkops_gone(silent)
Xregister boolean silent;
X{
X register int cnt = 0;
X register struct monst *mtmp, *mtmp2;
X
X /* turn off automatic resurrection of kops */
X allow_kops = FALSE;
X
X for(mtmp = fmon; mtmp; mtmp = mtmp2) {
X mtmp2 = mtmp->nmon;
X if(mtmp->data->mlet == S_KOP) {
X mongone(mtmp);
X cnt++;
X }
X }
X if(cnt && !silent)
X pline("The Kops (disappointed) disappear into thin air.");
X allow_kops = TRUE;
X}
X#endif /* KOPS */
X
Xstatic long
Xcost_per_charge(otmp)
Xregister struct obj *otmp;
X{
X register long tmp = 0L;
X register struct monst *shkp = shop_keeper(*u.ushops);
X
X if(!shkp || !inhishop(shkp)) return(0L); /* insurance */
X tmp = get_cost(otmp, shkp);
X
X /* The idea is to make the exhaustive use of */
X /* an unpaid item more expensive than buying */
X /* it outright. */
X if(otmp->otyp == MAGIC_LAMP) { /* 1 */
X tmp += tmp / 3L;
X } else if(otmp->otyp == MAGIC_MARKER) { /* 70 - 100 */
X /* no way to determine in advance */
X /* how many charges will be wasted. */
X /* so, arbitrarily, one half of the */
X /* price per use. */
X tmp /= 2L;
X } else if(otmp->otyp == BAG_OF_TRICKS || /* 1 - 20 */
X otmp->otyp == HORN_OF_PLENTY) {
X tmp /= 5L;
X } else if(otmp->otyp == CRYSTAL_BALL || /* 1 - 5 */
X otmp->otyp == OIL_LAMP || /* 1 - 10 */
X otmp->otyp == BRASS_LANTERN ||
X (otmp->otyp >= MAGIC_FLUTE &&
X otmp->otyp <= DRUM_OF_EARTHQUAKE) || /* 5 - 9 */
X otmp->oclass == WAND_CLASS) { /* 3 - 11 */
X if (otmp->spe > 1) tmp /= 4L;
X } else if (otmp->oclass == SPBOOK_CLASS) {
X tmp -= tmp / 5L;
X }
X return(tmp);
X}
X
X/* for using charges of unpaid objects */
Xvoid
Xcheck_unpaid(otmp)
Xregister struct obj *otmp;
X{
X if(!*u.ushops) return;
X
X if(otmp->oclass != SPBOOK_CLASS && otmp->spe <= 0) return;
X
X if(otmp->unpaid) {
X register long tmp = cost_per_charge(otmp);
X register struct monst *shkp = shop_keeper(*u.ushops);
X
X if(!shkp || !inhishop(shkp)) return;
X
X if(otmp->oclass == SPBOOK_CLASS && tmp > 0L)
X pline("\"%sYou owe%s %ld zorkmids.\"",
X rn2(2) ? "This is no free library, cad! " : "",
X ESHK(shkp)->debit > 0L ? " additional" : "", tmp);
X ESHK(shkp)->debit += tmp;
X exercise(A_WIS, TRUE); /* you just got info */
X }
X}
X
Xvoid
Xcostly_gold(x, y, amount)
Xregister xchar x, y;
Xregister long amount;
X{
X register long delta;
X register struct monst *shkp;
X register struct eshk *eshkp;
X
X if(!costly_spot(x, y)) return;
X /* shkp now guaranteed to exist by costly_spot() */
X shkp = shop_keeper(*in_rooms(x, y, SHOPBASE));
X
X eshkp = ESHK(shkp);
X if(eshkp->credit >= amount) {
X if(eshkp->credit > amount)
X Your("credit is reduced by %ld zorkmid%s.",
X amount, plur(amount));
X else Your("credit is erased.");
X eshkp->credit -= amount;
X } else {
X delta = amount - eshkp->credit;
X if(eshkp->credit)
X Your("credit is erased.");
X if(eshkp->debit)
X Your("debt increases by %ld zorkmid%s.",
X delta, plur(delta));
X else You("owe %s %ld zorkmid%s.",
X shkname(shkp), delta, plur(delta));
X eshkp->debit += delta;
X eshkp->loan += delta;
X eshkp->credit = 0L;
X }
X}
X
X/* used in domove to block diagonal shop-exit */
X/* x,y should always be a door */
Xboolean
Xblock_door(x,y)
Xregister xchar x, y;
X{
X register int roomno = *in_rooms(x, y, SHOPBASE);
X register struct monst *shkp;
X
X if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE);
X if(!IS_DOOR(levl[x][y].typ)) return(FALSE);
X if(roomno != *u.ushops) return(FALSE);
X
X if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp))
X return(FALSE);
X
X if(shkp->mx == ESHK(shkp)->shk.x && shkp->my == ESHK(shkp)->shk.y
X /* Actually, the shk should be made to block _any_
X * door, including a door the player digs, if the
X * shk is within a 'jumping' distance.
X */
X && ESHK(shkp)->shd.x == x && ESHK(shkp)->shd.y == y
X && shkp->mcanmove && !shkp->msleep
X && (ESHK(shkp)->debit || ESHK(shkp)->billct ||
X ESHK(shkp)->robbed)) {
X pline("%s%s blocks your way!", shkname(shkp),
X Invis ? " senses your motion and" : "");
X return(TRUE);
X }
X return(FALSE);
X}
X
X/* used in domove to block diagonal shop-entry */
X/* u.ux, u.uy should always be a door */
Xboolean
Xblock_entry(x,y)
Xregister xchar x, y;
X{
X register xchar sx, sy;
X register int roomno;
X register struct monst *shkp;
X
X if(!(IS_DOOR(levl[u.ux][u.uy].typ) &&
X levl[u.ux][u.uy].doormask == D_BROKEN)) return(FALSE);
X
X roomno = *in_rooms(x, y, SHOPBASE);
X if(roomno < 0 || !IS_SHOP(roomno)) return(FALSE);
X if(!(shkp = shop_keeper((char)roomno)) || !inhishop(shkp))
X return(FALSE);
X
X if(ESHK(shkp)->shd.x != u.ux || ESHK(shkp)->shd.y != u.uy)
X return(FALSE);
X
X sx = ESHK(shkp)->shk.x;
X sy = ESHK(shkp)->shk.y;
X
X if(shkp->mx == sx && shkp->my == sy
X && shkp->mcanmove && !shkp->msleep
X && (x == sx-1 || x == sx+1 || y == sy-1 || y == sy+1)
X && (Invis || carrying(PICK_AXE))
X ) {
X pline("%s%s blocks your way!", shkname(shkp),
X Invis ? " senses your motion and" : "");
X return(TRUE);
X }
X return(FALSE);
X}
X
X#endif /* OVLB */
X
X/*shk.c*/
END_OF_FILE
if test 41942 -ne `wc -c <'src/shk.c2'`; then
echo shar: \"'src/shk.c2'\" unpacked with wrong size!
fi
# end of 'src/shk.c2'
fi
echo shar: End of archive 33 \(of 108\).
cp /dev/null ark33isdone
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 39 40 \
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 \
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 \
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 \
101 102 103 104 105 106 107 108 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 108 archives.
echo "Now execute 'rebuild.sh'"
rm -f ark10[0-8]isdone 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