void shkdead(struct monst *mtmp) /* called in mon.c */ { struct eshk *eshk = ESHK(mtmp); if (eshk->shoplevel == dlevel) rooms[eshk->shoproom].rtype = 0; if (mtmp == shopkeeper) { setpaid(); shopkeeper = NULL; bill = (struct bill_x *) - 1000; /* dump core when referenced */ } }
/* called in mon.c */ void shkdead(monst_t *mtmp) { eshk_t *eshk = ESHK(mtmp); if (eshk->shoplevel == dlevel) rooms[eshk->shoproom].rtype = 0; if (mtmp == shopkeeper) { setpaid(); shopkeeper = NULL; //bill = (bill_t *) -1000; /* dump core when referenced */ // XXXXX !!! bill = NULL; // this seems like a better idea to me } }
/* -1 if object could not be found (but was paid) */ static int dopayobj(struct bill_x *bp) { 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) { 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(obj); } return (1); }
/* -1 if object could not be found (but was paid) */ static Short dopayobj(bill_t *bp) { obj_t *obj; Long ltmp; /* find the object on one of the lists */ obj = bp_to_obj(bp); if (!obj) { message("BUG: Shopkeeper administration out of order."); setpaid(); /* be nice to the player */ return 0; } if (!(obj->bitflags & O_IS_UNPAID) && !bp->useup) { message("BUG: Paid object on bill??"); return 1; } obj->bitflags &= ~O_IS_UNPAID; ltmp = bp->price * bp->bquantity; if (ANGRY(shopkeeper)) ltmp += ltmp/3; if (you.ugold < ltmp) { StrPrintF(ScratchBuffer, "You don't have gold enough to pay %s.", doname(obj)); message(ScratchBuffer); obj->bitflags |= O_IS_UNPAID; return 0; } pay(ltmp, shopkeeper); StrPrintF(ScratchBuffer, "You bought %s for %ld gold piece%s", doname(obj), ltmp, (ltmp == 1 ? "." : "s.")); message(ScratchBuffer); if (bp->useup) { obj_t *otmp = billobjs; if (obj == billobjs) billobjs = obj->nobj; else { while (otmp && otmp->nobj != obj) otmp = otmp->nobj; if (otmp) otmp->nobj = obj->nobj; else message("BUG: Error in shopkeeper administration."); } free_me((VoidPtr) obj); } return 1; }
/* routine called after dying (or quitting) with nonempty bill */ void paybill(void) { 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 */ } }
/* routine called after dying (or quitting) with nonempty bill */ void paybill() { if (shlevel == dlevel && shopkeeper && ESHK(shopkeeper)->billct) { addupbill(); if (total > you.ugold){ shopkeeper->mgold += you.ugold; you.ugold = 0; StrPrintF(ScratchBuffer, "%s comes and takes all your possessions.", Monnam(shopkeeper)); message(ScratchBuffer); } else { you.ugold -= total; shopkeeper->mgold += total; StrPrintF(ScratchBuffer, "%s comes and takes the %ld zorkmids you owed him.", Monnam(shopkeeper), total); message(ScratchBuffer); } setpaid(); /* in case we create bones */ } }
int dopay(void) { long ltmp; struct bill_x *bp; struct monst *shkp; int pass, tmp; multi = 0; 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); }
int inshop(void) { int roomno = inroom(u.ux, u.uy); /* 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 = NULL; shlevel = 0; } u.uinshop = 0; } /* Did we just enter a zoo of some kind? */ if (roomno >= 0) { int rt = rooms[roomno].rtype; 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; 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); }
// What does the return value indicate?? Boolean dopay() { Long ltmp; bill_t *bp; monst_t *shkp; Short pass, tmp; multi = 0; inshop(); for (shkp = fmon ; shkp ; shkp = shkp->nmon) if ((shkp->bitflags & M_IS_SHOPKEEPER) && dist(shkp->mx,shkp->my) < 3) break; if (!shkp && you.uinshop && inroom(shopkeeper->mx,shopkeeper->my) == ESHK(shopkeeper)->shoproom) shkp = shopkeeper; if (!shkp) { message("There is nobody here to receive your payment."); return false; } ltmp = ESHK(shkp)->robbed; if (shkp != shopkeeper && NOTANGRY(shkp)) { if (!ltmp) { StrPrintF(ScratchBuffer, "You do not owe %s anything.", monnam(shkp)); message(ScratchBuffer); } else if (!you.ugold) { message("You have no money."); } else { Long ugold = you.ugold; if (you.ugold > ltmp) { StrPrintF(ScratchBuffer, "You give %s the %ld gold pieces he asked for.", monnam(shkp), ltmp); message(ScratchBuffer); pay(ltmp, shkp); } else { StrPrintF(ScratchBuffer, "You give %s all your gold.", monnam(shkp)); message(ScratchBuffer); pay(you.ugold, shkp); } if (ugold < ltmp/2) { message("Unfortunately, he doesn't look satisfied."); } else { ESHK(shkp)->robbed = 0; ESHK(shkp)->following = false; if (ESHK(shkp)->shoplevel != dlevel) { /* For convenience's sake, let him disappear */ shkp->minvent = NULL; /* %% */ // xxx leak? shkp->mgold = 0; mondead(shkp); } } } return true; } if (!ESHK(shkp)->billct) { StrPrintF(ScratchBuffer, "You do not owe %s anything.", monnam(shkp)); message(ScratchBuffer); if (!you.ugold) { message("Moreover, you have no money."); return true; } if (ESHK(shkp)->robbed) { message("But since his shop has been robbed recently,"); StrPrintF(ScratchBuffer, "you%srepay %s's expenses.", (you.ugold < ESHK(shkp)->robbed) ? " partially " : " ", monnam(shkp)); message(ScratchBuffer); pay(min(you.ugold, ESHK(shkp)->robbed), shkp); ESHK(shkp)->robbed = 0; return true; } if (ANGRY(shkp)) { StrPrintF(ScratchBuffer, "But in order to appease %s,", amonnam(shkp, "angry")); message(ScratchBuffer); if (you.ugold >= 1000) { ltmp = 1000; message(" you give him 1000 gold pieces."); } else { ltmp = you.ugold; message(" you give him all your money."); } pay(ltmp, shkp); if (StrNCompare(ESHK(shkp)->customer, plname, PL_NSIZ) || rund(3)){ StrPrintF(ScratchBuffer, "%s calms down.", Monnam(shkp)); message(ScratchBuffer); shkp->bitflags |= M_IS_PEACEFUL; // NOTANGRY(shopkeeper) = 1; } else { StrPrintF(ScratchBuffer, "%s is as angry as ever.", Monnam(shkp)); message(ScratchBuffer); } } return true; } if (shkp != shopkeeper) { message("BUG: dopay: not to shopkeeper?"); if (shopkeeper) setpaid(); return false; } 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 true; bill[tmp] = bill[--ESHK(shopkeeper)->billct]; } } StrPrintF(ScratchBuffer, "Thank you for shopping in %s's %s store!", shkname(shopkeeper), shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]); shopkeeper->bitflags |= M_IS_PEACEFUL; // NOTANGRY(shopkeeper) = 1; return true; }
UInt inshop() { Short roomno = inroom(you.ux,you.uy); /* Did we just leave a shop? */ if (you.uinshop && (you.uinshop != roomno + 1 || shlevel != dlevel || !shopkeeper)) { if (shopkeeper) { if (ESHK(shopkeeper)->billct) { if (inroom(shopkeeper->mx, shopkeeper->my) == you.uinshop - 1) /* ab@unido */ message("Somehow you escaped the shop without paying!"); addupbill(); StrPrintF(ScratchBuffer,"You stole for a total worth of %ld zorkmids.", total); message(ScratchBuffer); ESHK(shopkeeper)->robbed += total; setpaid(); if ((rooms[ESHK(shopkeeper)->shoproom].rtype == GENERAL) == (rund(3) == 0)) ESHK(shopkeeper)->following = true; } shopkeeper = NULL; shlevel = 0; } you.uinshop = 0; } /* Did we just enter a zoo of some kind? */ if (roomno >= 0) { Short rt = rooms[roomno].rtype; monst_t *mtmp; if (rt == ZOO) { message("Welcome to David's treasure zoo!"); } else if (rt == SWAMP) { message("It looks rather muddy down here."); } else if (rt == MORGUE) { if (midnight()) message("Go away! Go away!"); else message("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 || !rund(3)) mtmp->bitflags &= ~M_IS_ASLEEP; } } /* 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; you.uinshop = 0; } else if (!you.uinshop) { if (!ESHK(shopkeeper)->visitct || StrNCompare(ESHK(shopkeeper)->customer, plname, PL_NSIZ)) { /* He seems to be new here */ ESHK(shopkeeper)->visitct = 0; ESHK(shopkeeper)->following = false; StrNCopy(ESHK(shopkeeper)->customer, plname, PL_NSIZ); shopkeeper->bitflags |= M_IS_PEACEFUL; // NOTANGRY(shopkeeper) = 1; } if (!ESHK(shopkeeper)->following) { Boolean box, pick; StrPrintF(ScratchBuffer, "Hello %s! Welcome%sto %s's %s shop!", plname, ESHK(shopkeeper)->visitct++ ? " again " : " ", shkname(shopkeeper), shopnam[rooms[ESHK(shopkeeper)->shoproom].rtype - 8] ); message(ScratchBuffer); box = carrying(ICE_BOX); pick = carrying(PICK_AXE); if (box || pick) { if (do_chug(shopkeeper)) { you.uinshop = 0; /* he died moving */ return 0; } StrPrintF(ScratchBuffer, "Will you please leave your %s outside?", (box && pick) ? "box and pick-axe" : box ? "box" : "pick-axe"); message(ScratchBuffer); } } you.uinshop = roomno + 1; // (0 is "not in shop") } } return you.uinshop; }