📄 hack.shk.c
字号:
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. *//* hack.shk.c - version 1.0.3 */#include "hack.h"#ifdef QUESTint shlevel = 0;struct monst *shopkeeper = 0;struct obj *billobjs = 0;obfree(obj,merge) register struct obj *obj, *merge; { free((char *) obj);}inshop(){ return(0); }shopdig(){}addtobill(){}subfrombill(){}splitbill(){}dopay(){ return(0); }paybill(){}doinvbill(){ return(0); }shkdead(){}shkcatch(){ return(0); }shk_move(){ return(0); }replshk(mtmp,mtmp2) struct monst *mtmp, *mtmp2; {}char *shkname(){ return(""); }#else QUEST#include "hack.mfndpos.h"#include "def.mkroom.h"#include "def.eshk.h"#define ESHK(mon) ((struct eshk *)(&(mon->mextra[0])))#define NOTANGRY(mon) mon->mpeaceful#define ANGRY(mon) !NOTANGRY(mon)extern char plname[], *xname();extern struct obj *o_on(), *bp_to_obj();/* Descriptor of current shopkeeper. Note that the bill need not be per-shopkeeper, since it is valid only when in a shop. */static struct monst *shopkeeper = 0;static struct bill_x *bill;static int shlevel = 0; /* level of this shopkeeper */ struct obj *billobjs; /* objects on bill with bp->useup */ /* only accessed here and by save & restore */static long int total; /* filled by addupbill() */static long int followmsg; /* last time of follow message *//* invariants: obj->unpaid iff onbill(obj) [unless bp->useup] obj->quan <= bp->bquan */char shtypes[] = { /* 8 shoptypes: 7 specialized, 1 mixed */ RING_SYM, WAND_SYM, WEAPON_SYM, FOOD_SYM, SCROLL_SYM, POTION_SYM, ARMOR_SYM, 0};static char *shopnam[] = { "engagement ring", "walking cane", "antique weapon", "delicatessen", "second hand book", "liquor", "used armor", "assorted antiques"};char *shkname(mtmp) /* called in do_name.c */register struct monst *mtmp;{ return(ESHK(mtmp)->shknam);}static void setpaid();shkdead(mtmp) /* called in mon.c */register struct monst *mtmp;{ register struct eshk *eshk = ESHK(mtmp); if(eshk->shoplevel == dlevel) rooms[eshk->shoproom].rtype = 0; if(mtmp == shopkeeper) { setpaid(); shopkeeper = 0; bill = (struct bill_x *) -1000; /* dump core when referenced */ }}replshk(mtmp,mtmp2)register struct monst *mtmp, *mtmp2;{ if(mtmp == shopkeeper) { shopkeeper = mtmp2; bill = &(ESHK(shopkeeper)->bill[0]); }}static voidsetpaid(){ /* caller has checked that shopkeeper exists */ /* either we paid or left the shop or he just died */register struct obj *obj;register struct monst *mtmp; for(obj = invent; obj; obj = obj->nobj) obj->unpaid = 0; for(obj = fobj; obj; obj = obj->nobj) obj->unpaid = 0; for(obj = fcobj; obj; obj = obj->nobj) obj->unpaid = 0; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) for(obj = mtmp->minvent; obj; obj = obj->nobj) obj->unpaid = 0; for(mtmp = fallen_down; mtmp; mtmp = mtmp->nmon) for(obj = mtmp->minvent; obj; obj = obj->nobj) obj->unpaid = 0; while(obj = billobjs){ billobjs = obj->nobj; free((char *) obj); } ESHK(shopkeeper)->billct = 0;}staticaddupbill(){ /* delivers result in total */ /* caller has checked that shopkeeper exists */register ct = ESHK(shopkeeper)->billct;register struct bill_x *bp = bill; total = 0; while(ct--){ total += bp->price * bp->bquan; bp++; }}inshop(){register roomno = inroom(u.ux,u.uy); static void findshk(); /* Did we just leave a shop? */ if(u.uinshop && (u.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { if(shopkeeper) { if(ESHK(shopkeeper)->billct) { if(inroom(shopkeeper->mx, shopkeeper->my) == u.uinshop - 1) /* ab@unido */ pline("Somehow you escaped the shop without paying!"); addupbill(); pline("You stole for a total worth of %ld zorkmids.", total); ESHK(shopkeeper)->robbed += total; setpaid(); if((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL) == (rn2(3) == 0)) ESHK(shopkeeper)->following = 1; } shopkeeper = 0; shlevel = 0; } u.uinshop = 0; } /* Did we just enter a zoo of some kind? */ if(roomno >= 0) { register int rt = rooms[roomno].rtype; register struct monst *mtmp; if(rt == ZOO) { pline("Welcome to David's treasure zoo!"); } else if(rt == SWAMP) { pline("It looks rather muddy down here."); } else if(rt == MORGUE) { if(midnight()) pline("Go away! Go away!"); else pline("You get an uncanny feeling ..."); } else rt = 0; if(rt != 0) { rooms[roomno].rtype = 0; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(rt != ZOO || !rn2(3)) mtmp->msleep = 0; } } /* Did we just enter a shop? */ if(roomno >= 0 && rooms[roomno].rtype >= 8) { if(shlevel != dlevel || !shopkeeper || ESHK(shopkeeper)->shoproom != roomno) findshk(roomno); if(!shopkeeper) { rooms[roomno].rtype = 0; u.uinshop = 0; } else if(!u.uinshop){ if(!ESHK(shopkeeper)->visitct || strncmp(ESHK(shopkeeper)->customer, plname, PL_NSIZ)){ /* He seems to be new here */ ESHK(shopkeeper)->visitct = 0; ESHK(shopkeeper)->following = 0; (void) strncpy(ESHK(shopkeeper)->customer,plname,PL_NSIZ); NOTANGRY(shopkeeper) = 1; } if(!ESHK(shopkeeper)->following) { boolean box, pick; pline("Hello %s! Welcome%s to %s's %s shop!", plname, ESHK(shopkeeper)->visitct++ ? " again" : "", shkname(shopkeeper), shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] ); box = carrying(ICE_BOX); pick = carrying(PICK_AXE); if(box || pick) { if(dochug(shopkeeper)) { u.uinshop = 0; /* he died moving */ return(0); } pline("Will you please leave your %s outside?", (box && pick) ? "box and pick-axe" : box ? "box" : "pick-axe"); } } u.uinshop = roomno + 1; } } return(u.uinshop);}static voidfindshk(roomno)register roomno;{register struct monst *mtmp; for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) if(mtmp->isshk && ESHK(mtmp)->shoproom == roomno && ESHK(mtmp)->shoplevel == dlevel) { shopkeeper = mtmp; bill = &(ESHK(shopkeeper)->bill[0]); shlevel = dlevel; if(ANGRY(shopkeeper) && strncmp(ESHK(shopkeeper)->customer,plname,PL_NSIZ)) NOTANGRY(shopkeeper) = 1; /* billobjs = 0; -- this is wrong if we save in a shop */ /* (and it is harmless to have too many things in billobjs) */ return; } shopkeeper = 0; shlevel = 0; bill = (struct bill_x *) -1000; /* dump core when referenced */}static struct bill_x *onbill(obj) register struct obj *obj; {register struct bill_x *bp; if(!shopkeeper) return(0); for(bp = bill; bp < &bill[ESHK(shopkeeper)->billct]; bp++) if(bp->bo_id == obj->o_id) { if(!obj->unpaid) pline("onbill: paid obj on bill?"); return(bp); } if(obj->unpaid) pline("onbill: unpaid obj not on bill?"); return(0);}/* called with two args on merge */obfree(obj,merge) register struct obj *obj, *merge; {register struct bill_x *bp = onbill(obj);register struct bill_x *bpm; if(bp) { if(!merge){ bp->useup = 1; obj->unpaid = 0; /* only for doinvbill */ obj->nobj = billobjs; billobjs = obj; return; } bpm = onbill(merge); if(!bpm){ /* this used to be a rename */ impossible("obfree: not on bill??"); return; } else { /* this was a merger */ bpm->bquan += bp->bquan; ESHK(shopkeeper)->billct--; *bp = bill[ESHK(shopkeeper)->billct]; } } free((char *) obj);}staticpay(tmp,shkp)long tmp;register struct monst *shkp;{ long robbed = ESHK(shkp)->robbed; u.ugold -= tmp; shkp->mgold += tmp; flags.botl = 1; if(robbed) { robbed -= tmp; if(robbed < 0) robbed = 0; ESHK(shkp)->robbed = robbed; }}dopay(){long ltmp;register struct bill_x *bp;register struct monst *shkp;int pass, tmp; static int dopayobj(); multi = 0; (void) inshop(); for(shkp = fmon; shkp; shkp = shkp->nmon) if(shkp->isshk && dist(shkp->mx,shkp->my) < 3) break; if(!shkp && u.uinshop && inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom) shkp = shopkeeper; if(!shkp) { pline("There is nobody here to receive your payment."); return(0); } ltmp = ESHK(shkp)->robbed; if(shkp != shopkeeper && NOTANGRY(shkp)) { if(!ltmp) { pline("You do not owe %s anything.", monnam(shkp)); } else if(!u.ugold) { pline("You have no money."); } else { long ugold = u.ugold; if(u.ugold > ltmp) { pline("You give %s the %ld gold pieces he asked for.", monnam(shkp), ltmp); pay(ltmp, shkp); } else { pline("You give %s all your gold.", monnam(shkp)); pay(u.ugold, shkp); } if(ugold < ltmp/2) { pline("Unfortunately, he doesn't look satisfied."); } else { ESHK(shkp)->robbed = 0; ESHK(shkp)->following = 0; if(ESHK(shkp)->shoplevel != dlevel) { /* For convenience's sake, let him disappear */ shkp->minvent = 0; /* %% */ shkp->mgold = 0; mondead(shkp); } } } return(1); } if(!ESHK(shkp)->billct){ pline("You do not owe %s anything.", monnam(shkp)); if(!u.ugold){ pline("Moreover, you have no money."); return(1); } if(ESHK(shkp)->robbed){#define min(a,b) ((a<b)?a:b) pline("But since his shop has been robbed recently,"); pline("you %srepay %s's expenses.", (u.ugold < ESHK(shkp)->robbed) ? "partially " : "", monnam(shkp)); pay(min(u.ugold, ESHK(shkp)->robbed), shkp); ESHK(shkp)->robbed = 0; return(1); } if(ANGRY(shkp)){ pline("But in order to appease %s,", amonnam(shkp, "angry")); if(u.ugold >= 1000){ ltmp = 1000; pline(" you give him 1000 gold pieces."); } else { ltmp = u.ugold; pline(" you give him all your money."); } pay(ltmp, shkp); if(strncmp(ESHK(shkp)->customer, plname, PL_NSIZ) || rn2(3)){ pline("%s calms down.", Monnam(shkp)); NOTANGRY(shkp) = 1; } else pline("%s is as angry as ever.", Monnam(shkp)); } return(1); } if(shkp != shopkeeper) { impossible("dopay: not to shopkeeper?"); if(shopkeeper) setpaid(); return(0); } for(pass = 0; pass <= 1; pass++) { tmp = 0; while(tmp < ESHK(shopkeeper)->billct) { bp = &bill[tmp]; if(!pass && !bp->useup) { tmp++; continue; } if(!dopayobj(bp)) return(1); bill[tmp] = bill[--ESHK(shopkeeper)->billct]; } } pline("Thank you for shopping in %s's %s store!", shkname(shopkeeper), shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]); NOTANGRY(shopkeeper) = 1; return(1);}/* return 1 if paid successfully *//* 0 if not enough money *//* -1 if object could not be found (but was paid) */staticdopayobj(bp) register struct bill_x *bp; {register struct obj *obj;long ltmp; /* find the object on one of the lists */ obj = bp_to_obj(bp); if(!obj) { impossible("Shopkeeper administration out of order."); setpaid(); /* be nice to the player */ return(0); } if(!obj->unpaid && !bp->useup){ impossible("Paid object on bill??"); return(1); } obj->unpaid = 0; ltmp = bp->price * bp->bquan; if(ANGRY(shopkeeper)) ltmp += ltmp/3; if(u.ugold < ltmp){ pline("You don't have gold enough to pay %s.", doname(obj)); obj->unpaid = 1; return(0); } pay(ltmp, shopkeeper); pline("You bought %s for %ld gold piece%s.", doname(obj), ltmp, plur(ltmp)); if(bp->useup) { register struct obj *otmp = billobjs; if(obj == billobjs) billobjs = obj->nobj; else { while(otmp && otmp->nobj != obj) otmp = otmp->nobj; if(otmp) otmp->nobj = obj->nobj; else pline("Error in shopkeeper administration."); } free((char *) obj); } return(1);}/* routine called after dying (or quitting) with nonempty bill */paybill(){ if(shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct){ addupbill(); if(total > u.ugold){ shopkeeper->mgold += u.ugold; u.ugold = 0; pline("%s comes and takes all your possessions.", Monnam(shopkeeper)); } else { u.ugold -= total; shopkeeper->mgold += total; pline("%s comes and takes the %ld zorkmids you owed him.", Monnam(shopkeeper), total); } setpaid(); /* in case we create bones */ }}/* find obj on one of the lists */struct obj *bp_to_obj(bp)register struct bill_x *bp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -