/* He is digging in the shop. */ void shopdig(int fall) { if(!fall) { if(u.utraptype == TT_PIT) pline("\"Be careful, sir, or you might fall through the floor.\""); else pline("\"Please, do not damage the floor here.\""); } else if(dist(shopkeeper->mx, shopkeeper->my) < 3) { struct obj *obj, *obj2; pline("%s grabs your backpack!", shkname(shopkeeper)); for(obj = invent; obj; obj = obj2) { obj2 = obj->nobj; if(obj->owornmask) continue; freeinv(obj); obj->nobj = shopkeeper->minvent; shopkeeper->minvent = obj; if(obj->unpaid) subfrombill(obj); } } }
/* He is digging in the shop. */ void shopdig(Boolean fall) { if (!fall) { if (you.utraptype == TT_PIT) message("\"Be careful, sir, or you might fall through the floor.\""); else message("\"Please, do not damage the floor here.\""); } else if (dist(shopkeeper->mx, shopkeeper->my) < 3) { obj_t *obj, *obj2; StrPrintF(ScratchBuffer, "%s grabs your backpack!", shkname(shopkeeper)); message(ScratchBuffer); for (obj = invent ; obj ; obj = obj2) { obj2 = obj->nobj; if (obj->owornmask) continue; unlink_inv(obj); //freeinv(obj); obj->nobj = shopkeeper->minvent; shopkeeper->minvent = obj; if (obj->bitflags & O_IS_UNPAID) subfrombill(obj); } } }
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; }
static int ready_weapon(struct obj *wep) { /* Separated function so swapping works easily */ int res = 0; if (!wep) { /* No weapon */ if (uwep) { pline("You are empty %s.", body_part(HANDED)); setuwep(NULL); res++; } else pline("You are already empty %s.", body_part(HANDED)); } else if (!uarmg && !Stone_resistance && wep->otyp == CORPSE && touch_petrifies(&mons[wep->corpsenm])) { /* Prevent wielding cockatrice when not wearing gloves --KAA */ char kbuf[BUFSZ]; pline("You wield the %s corpse in your bare %s.", mons[wep->corpsenm].mname, makeplural(body_part(HAND))); sprintf(kbuf, "%s corpse", an(mons[wep->corpsenm].mname)); instapetrify(kbuf); } else if (uarms && bimanual(wep)) pline("You cannot wield a two-handed %s while wearing a shield.", is_sword(wep) ? "sword" : wep->otyp == BATTLE_AXE ? "axe" : "weapon"); else if (wep->oartifact && !touch_artifact(wep, &youmonst)) { res++; /* takes a turn even though it doesn't get wielded */ } else { /* Weapon WILL be wielded after this point */ res++; if (will_weld(wep)) { const char *tmp = xname(wep), *thestr = "The "; if (strncmp(tmp, thestr, 4) && !strncmp(The(tmp),thestr,4)) tmp = thestr; else tmp = ""; pline("%s%s %s to your %s!", tmp, aobjnam(wep, "weld"), (wep->quan == 1L) ? "itself" : "themselves", /* a3 */ bimanual(wep) ? (const char *)makeplural(body_part(HAND)) : body_part(HAND)); wep->bknown = TRUE; } else { /* The message must be printed before setuwep (since * you might die and be revived from changing weapons), * and the message must be before the death message and * Lifesaved rewielding. Yet we want the message to * say "weapon in hand", thus this kludge. */ long dummy = wep->owornmask; wep->owornmask |= W_WEP; prinv(NULL, wep, 0L); wep->owornmask = dummy; } setuwep(wep); /* KMH -- Talking artifacts are finally implemented */ arti_speak(wep); if (artifact_light(wep) && !wep->lamplit) { begin_burn(wep, FALSE); if (!Blind) pline("%s to glow brilliantly!", Tobjnam(wep, "begin")); } if (wep->unpaid) { struct monst *this_shkp; if ((this_shkp = shop_keeper(level, inside_shop(level, u.ux, u.uy))) != NULL) { pline("%s says \"You be careful with my %s!\"", shkname(this_shkp), xname(wep)); } } } return res; }
/* Bug: if the monster is a priest or shopkeeper, not every one of these * options works, since those are special cases. */ char *x_monnam(const struct monst *mtmp, int article, /* ARTICLE_NONE, ARTICLE_THE, ARTICLE_A: obvious * ARTICLE_YOUR: "your" on pets, "the" on everything * else * If the monster would be referred to as "it" or if the monster has a name * _and_ there is no adjective, "invisible", "saddled", etc., override this * and always use no article. */ const char *adjective, int suppress, /* SUPPRESS_IT, SUPPRESS_INVISIBLE, SUPPRESS_HALLUCINATION, SUPPRESS_SADDLE. * EXACT_NAME: combination of all the above */ boolean called) { static char buf[BUFSZ]; const struct permonst *mdat = mtmp->data; boolean do_hallu, do_invis, do_it, do_saddle; boolean name_at_start, has_adjectives; char *bp; if (program_state.gameover) suppress |= SUPPRESS_HALLUCINATION; if (article == ARTICLE_YOUR && !mtmp->mtame) article = ARTICLE_THE; do_hallu = Hallucination && !(suppress & SUPPRESS_HALLUCINATION); do_invis = mtmp->minvis && !(suppress & SUPPRESS_INVISIBLE); do_it = !canspotmon(mtmp) && article != ARTICLE_YOUR && !program_state.gameover && mtmp != u.usteed && !(u.uswallow && mtmp == u.ustuck) && !(suppress & SUPPRESS_IT); do_saddle = !(suppress & SUPPRESS_SADDLE); buf[0] = 0; /* unseen monsters, etc. Use "it" */ if (do_it) { strcpy(buf, "it"); return buf; } /* priests and minions: don't even use this function */ if (mtmp->ispriest || mtmp->isminion) { struct monst *priestmon = newmonst(mtmp->mxtyp, mtmp->mnamelth); char priestnambuf[BUFSZ]; char *name; long save_prop = EHalluc_resistance; memcpy(priestmon, mtmp, sizeof(struct monst) + mtmp->mxlth + mtmp->mnamelth); /* when true name is wanted, explicitly block Hallucination */ if (!do_hallu) EHalluc_resistance = 1L; if (!do_invis) priestmon->minvis = 0; name = priestname(priestmon, priestnambuf); EHalluc_resistance = save_prop; if (article == ARTICLE_NONE && !strncmp(name, "the ", 4)) name += 4; strcpy(buf, name); free(priestmon); return buf; } /* Shopkeepers: use shopkeeper name. For normal shopkeepers, just * "Asidonhopo"; for unusual ones, "Asidonhopo the invisible * shopkeeper" or "Asidonhopo the blue dragon". If hallucinating, * none of this applies. */ if (mtmp->isshk && !do_hallu) { if (adjective && article == ARTICLE_THE) { /* pathological case: "the angry Asidonhopo the blue dragon" sounds silly */ strcpy(buf, "the "); strcat(strcat(buf, adjective), " "); strcat(buf, shkname(mtmp)); return buf; } strcat(buf, shkname(mtmp)); if (mdat == &mons[PM_SHOPKEEPER] && !do_invis) return buf; strcat(buf, " the "); if (do_invis) strcat(buf, "invisible "); strcat(buf, mdat->mname); return buf; } /* Put the adjectives in the buffer */ if (adjective) strcat(strcat(buf, adjective), " "); if (do_invis) strcat(buf, "invisible "); if (do_saddle && (mtmp->misc_worn_check & W_SADDLE) && !Blind && !Hallucination) strcat(buf, "saddled "); if (buf[0] != 0) has_adjectives = TRUE; else has_adjectives = FALSE; /* Put the actual monster name or type into the buffer now */ /* Be sure to remember whether the buffer starts with a name */ if (do_hallu) { strcat(buf, rndmonnam()); name_at_start = FALSE; } else if (mtmp->mnamelth) { char *name = NAME(mtmp); if (mdat == &mons[PM_GHOST]) { sprintf(eos(buf), "%s ghost", s_suffix(name)); name_at_start = TRUE; } else if (called) { sprintf(eos(buf), "%s called %s", mdat->mname, name); name_at_start = (boolean)type_is_pname(mdat); } else if (is_mplayer(mdat) && (bp = strstri(name, " the ")) != 0) { /* <name> the <adjective> <invisible> <saddled> <rank> */ char pbuf[BUFSZ]; strcpy(pbuf, name); pbuf[bp - name + 5] = '\0'; /* adjectives right after " the " */ if (has_adjectives) strcat(pbuf, buf); strcat(pbuf, bp + 5); /* append the rest of the name */ strcpy(buf, pbuf); article = ARTICLE_NONE; name_at_start = TRUE; } else { strcat(buf, name); name_at_start = TRUE; } } else if (is_mplayer(mdat) && !In_endgame(&u.uz)) { char pbuf[BUFSZ]; strcpy(pbuf, rank_of((int)mtmp->m_lev, monsndx(mdat), (boolean)mtmp->female)); strcat(buf, lcase(pbuf)); name_at_start = FALSE; } else { strcat(buf, mdat->mname); name_at_start = (boolean)type_is_pname(mdat); } if (name_at_start && (article == ARTICLE_YOUR || !has_adjectives)) { if (mdat == &mons[PM_WIZARD_OF_YENDOR]) article = ARTICLE_THE; else article = ARTICLE_NONE; } else if ((mdat->geno & G_UNIQ) && article == ARTICLE_A) { article = ARTICLE_THE; } { char buf2[BUFSZ]; switch(article) { case ARTICLE_YOUR: strcpy(buf2, "your "); strcat(buf2, buf); strcpy(buf, buf2); return buf; case ARTICLE_THE: strcpy(buf2, "the "); strcat(buf2, buf); strcpy(buf, buf2); return buf; case ARTICLE_A: return an(buf); case ARTICLE_NONE: default: return buf; } } }