home *** CD-ROM | disk | FTP | other *** search
- 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
-