static void findshk(int roomno) { 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 = NULL; shlevel = 0; bill = (struct bill_x *) - 1000; /* dump core when referenced */ }
void subfrombill(struct obj *obj) { long ltmp; int tmp; struct obj *otmp; struct bill_x *bp; if (!inshop() || (u.ux == ESHK(shopkeeper)->shk.x && u.uy == ESHK(shopkeeper)->shk.y) || (u.ux == ESHK(shopkeeper)->shd.x && u.uy == ESHK(shopkeeper)->shd.y)) return; if ((bp = onbill(obj)) != NULL) { obj->unpaid = 0; if (bp->bquan > obj->quan) { otmp = newobj(0); *otmp = *obj; bp->bo_id = otmp->o_id = flags.ident++; otmp->quan = (bp->bquan -= obj->quan); otmp->owt = 0; /* superfluous */ otmp->onamelth = 0; bp->useup = 1; otmp->nobj = billobjs; billobjs = otmp; return; } ESHK(shopkeeper)->billct--; *bp = bill[ESHK(shopkeeper)->billct]; return; } if (obj->unpaid) { pline("%s didn't notice.", Monnam(shopkeeper)); obj->unpaid = 0; return; /* %% */ } /* he dropped something of his own - probably wants to sell it */ if (shopkeeper->msleep || shopkeeper->mfroz || inroom(shopkeeper->mx, shopkeeper->my) != ESHK(shopkeeper)->shoproom) return; if (ESHK(shopkeeper)->billct == BILLSZ || ((tmp = shtypes[rooms[ESHK(shopkeeper)->shoproom].rtype - 8]) && tmp != obj->olet) || strchr("_0", obj->olet)) { pline("%s seems not interested.", Monnam(shopkeeper)); return; } ltmp = getprice(obj) * obj->quan; if (ANGRY(shopkeeper)) { ltmp /= 3; NOTANGRY(shopkeeper) = 1; } else ltmp /= 2; if (ESHK(shopkeeper)->robbed) { if ((ESHK(shopkeeper)->robbed -= ltmp) < 0) ESHK(shopkeeper)->robbed = 0; pline("Thank you for your contribution to restock this recently plundered shop."); return; } if (ltmp > shopkeeper->mgold) ltmp = shopkeeper->mgold; pay(-ltmp, shopkeeper); if (!ltmp) pline("%s gladly accepts %s but cannot pay you at present.", Monnam(shopkeeper), doname(obj)); else pline("You sold %s and got %ld gold piece%s.", doname(obj), ltmp, plur(ltmp)); }
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; }