shop bones

Dying at a shop doorway, or at the free spot one step in, while not
owing the shopkeeper anything would yield "<shk> gratefully inherites all
your possessions" but leave those possesions where the next hero could
just pick them up for free.  Move them all the way inside the shop, as
happens when the hero dies while owing the shk.  Also, if hero has gold
left after shopkeeper takes any payment owed, force it to go into shk's
inventory instead of having it end up in the pile of other stuff.

     finish_paybill() duplicated much of drop_upon_death(), but not the
two-weapon hack to avoid curse() causing hero's secondary weapon to be
dropped while in the midst of removing it from inventory (but unlike the
old 3.4.1 panic for that, this one just triggered a warning about nonzero
worn mask).  It also lacked the named fruit fixup, whatever that does.
Make finish_paybill() call drop_upon_death() instead of copying it.
This commit is contained in:
nethack.rankin
2007-03-02 03:28:25 +00:00
parent c5450cbe5e
commit 23eb08a462
4 changed files with 54 additions and 32 deletions
+3
View File
@@ -330,6 +330,9 @@ if hero or monster standing on opened drawbridge survives its destruction,
fall into water or lava instead of remaining on top fall into water or lava instead of remaining on top
don't give a speed change message when an immobile monster is seen to be hit don't give a speed change message when an immobile monster is seen to be hit
by a wand of speed or slow monster by a wand of speed or slow monster
when shopkeeper "gratefully inherits possessions" of hero who dies in shop
doorway without owing the shop, move those items inside shop for bones
dying in a shop while wielding two weapons could cause "Setworn: mask" warning
Platform- and/or Interface-Specific Fixes Platform- and/or Interface-Specific Fixes
+1
View File
@@ -122,6 +122,7 @@ E void NDECL(drag_down);
/* ### bones.c ### */ /* ### bones.c ### */
E void FDECL(drop_upon_death, (struct monst *,struct obj *,int,int));
E boolean NDECL(can_make_bones); E boolean NDECL(can_make_bones);
E void FDECL(savebones, (struct obj *)); E void FDECL(savebones, (struct obj *));
E int NDECL(getbones); E int NDECL(getbones);
+14 -11
View File
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)bones.c 3.5 2006/04/14 */ /* SCCS Id: @(#)bones.c 3.5 2007/03/01 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985,1993. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -13,7 +13,6 @@ extern long bytes_counted;
STATIC_DCL boolean FDECL(no_bones_level, (d_level *)); STATIC_DCL boolean FDECL(no_bones_level, (d_level *));
STATIC_DCL void FDECL(goodfruit, (int)); STATIC_DCL void FDECL(goodfruit, (int));
STATIC_DCL void FDECL(resetobjs,(struct obj *,BOOLEAN_P)); STATIC_DCL void FDECL(resetobjs,(struct obj *,BOOLEAN_P));
STATIC_DCL void FDECL(drop_upon_death, (struct monst *, struct obj *));
STATIC_OVL boolean STATIC_OVL boolean
no_bones_level(lev) no_bones_level(lev)
@@ -164,14 +163,16 @@ boolean restore;
} }
} }
STATIC_OVL void /* called by savebones(); also by finish_paybill(shk.c) */
drop_upon_death(mtmp, cont) void
drop_upon_death(mtmp, cont, x, y)
struct monst *mtmp; struct monst *mtmp;
struct obj *cont; struct obj *cont;
int x, y;
{ {
struct obj *otmp; struct obj *otmp;
uswapwep = 0; /* ensure curse() won't cause swapwep to drop twice */ u.twoweap = 0; /* ensure curse() won't cause swapwep to drop twice */
while ((otmp = invent) != 0) { while ((otmp = invent) != 0) {
obj_extract_self(otmp); obj_extract_self(otmp);
obj_no_longer_held(otmp); obj_no_longer_held(otmp);
@@ -189,14 +190,15 @@ struct obj *cont;
else if (cont) else if (cont)
(void) add_to_container(cont, otmp); (void) add_to_container(cont, otmp);
else else
place_object(otmp, u.ux, u.uy); place_object(otmp, x, y);
} }
#ifndef GOLDOBJ #ifndef GOLDOBJ
if(u.ugold) { if(u.ugold) {
long ugold = u.ugold; long ugold = u.ugold;
if (mtmp) mtmp->mgold = ugold; if (mtmp) mtmp->mgold = ugold;
else if (cont) (void) add_to_container(cont, mkgoldobj(ugold)); else if (cont) (void) add_to_container(cont, mkgoldobj(ugold));
else (void)mkgold(ugold, u.ux, u.uy); else (void)mkgold(ugold, x, y);
u.ugold = ugold; /* undo mkgoldobj()'s removal */ u.ugold = ugold; /* undo mkgoldobj()'s removal */
} }
#endif #endif
@@ -299,12 +301,12 @@ struct obj *corpse;
otmp = mk_named_object(STATUE, &mons[u.umonnum], otmp = mk_named_object(STATUE, &mons[u.umonnum],
u.ux, u.uy, plname); u.ux, u.uy, plname);
drop_upon_death((struct monst *)0, otmp); drop_upon_death((struct monst *)0, otmp, u.ux, u.uy);
if (!otmp) return; /* couldn't make statue */ if (!otmp) return; /* couldn't make statue */
mtmp = (struct monst *)0; mtmp = (struct monst *)0;
} else if (u.ugrave_arise < LOW_PM) { } else if (u.ugrave_arise < LOW_PM) {
/* drop everything */ /* drop everything */
drop_upon_death((struct monst *)0, (struct obj *)0); drop_upon_death((struct monst *)0, (struct obj *)0, u.ux, u.uy);
/* trick makemon() into allowing monster creation /* trick makemon() into allowing monster creation
* on your location * on your location
*/ */
@@ -321,7 +323,8 @@ struct obj *corpse;
mtmp = makemon(&mons[u.ugrave_arise], u.ux, u.uy, NO_MM_FLAGS); mtmp = makemon(&mons[u.ugrave_arise], u.ux, u.uy, NO_MM_FLAGS);
in_mklev = FALSE; in_mklev = FALSE;
if (!mtmp) { if (!mtmp) {
drop_upon_death((struct monst *)0, (struct obj *)0); drop_upon_death((struct monst *)0, (struct obj *)0,
u.ux, u.uy);
return; return;
} }
mtmp = christen_monst(mtmp, plname); mtmp = christen_monst(mtmp, plname);
@@ -332,7 +335,7 @@ struct obj *corpse;
Your("body rises from the dead as %s...", Your("body rises from the dead as %s...",
an(mons[u.ugrave_arise].mname)); an(mons[u.ugrave_arise].mname));
display_nhwindow(WIN_MESSAGE, FALSE); display_nhwindow(WIN_MESSAGE, FALSE);
drop_upon_death(mtmp, (struct obj *)0); drop_upon_death(mtmp, (struct obj *)0, u.ux, u.uy);
m_dowear(mtmp, TRUE); m_dowear(mtmp, TRUE);
} }
if (mtmp) { if (mtmp) {
+36 -21
View File
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)shk.c 3.5 2006/10/30 */ /* SCCS Id: @(#)shk.c 3.5 2007/03/01 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -57,7 +57,7 @@ STATIC_DCL void FDECL(shk_names_obj,
(struct monst *,struct obj *,const char *,long,const char *)); (struct monst *,struct obj *,const char *,long,const char *));
STATIC_DCL struct obj *FDECL(bp_to_obj, (struct bill_x *)); STATIC_DCL struct obj *FDECL(bp_to_obj, (struct bill_x *));
STATIC_DCL boolean FDECL(inherits, (struct monst *,int,int)); STATIC_DCL boolean FDECL(inherits, (struct monst *,int,int));
STATIC_DCL void FDECL(set_repo_loc, (struct eshk *)); STATIC_DCL void FDECL(set_repo_loc, (struct monst *));
STATIC_DCL boolean NDECL(angry_shk_exists); STATIC_DCL boolean NDECL(angry_shk_exists);
STATIC_DCL void FDECL(rile_shk, (struct monst *)); STATIC_DCL void FDECL(rile_shk, (struct monst *));
STATIC_DCL void FDECL(rouse_shk, (struct monst *,BOOLEAN_P)); STATIC_DCL void FDECL(rouse_shk, (struct monst *,BOOLEAN_P));
@@ -1549,7 +1549,10 @@ boolean itemize;
return buy; return buy;
} }
static coord repo_location; /* repossession context */ static struct repo { /* repossession context */
struct monst *shopkeeper;
coord location;
} repo;
/* routine called after dying (or quitting) */ /* routine called after dying (or quitting) */
boolean boolean
@@ -1564,9 +1567,13 @@ int croaked; /* -1: escaped dungeon; 0: quit; 1: died */
shops don't occur on level 1, but this could happen if hero shops don't occur on level 1, but this could happen if hero
level teleports out of the dungeon and manages not to die */ level teleports out of the dungeon and manages not to die */
if (croaked < 0) return FALSE; if (croaked < 0) return FALSE;
/* [should probably also return false when dead hero has been
petrified since shk shouldn't be able to grab inventory
which has been shut inside a statue] */
/* this is where inventory will end up if any shk takes it */ /* this is where inventory will end up if any shk takes it */
repo_location.x = repo_location.y = 0; repo.location.x = repo.location.y = 0;
repo.shopkeeper = 0;
/* give shopkeeper first crack */ /* give shopkeeper first crack */
if ((mtmp = shop_keeper(*u.ushops)) && inhishop(mtmp)) { if ((mtmp = shop_keeper(*u.ushops)) && inhishop(mtmp)) {
@@ -1631,10 +1638,11 @@ int croaked;
if(roomno == eshkp->shoproom && inhishop(shkp) && if(roomno == eshkp->shoproom && inhishop(shkp) &&
!eshkp->billct && !eshkp->robbed && !eshkp->debit && !eshkp->billct && !eshkp->robbed && !eshkp->debit &&
NOTANGRY(shkp) && !eshkp->following) { NOTANGRY(shkp) && !eshkp->following) {
if (invent) taken = (invent != 0);
if (taken)
pline("%s gratefully inherits all your possessions.", pline("%s gratefully inherits all your possessions.",
shkname(shkp)); shkname(shkp));
set_repo_loc(eshkp); set_repo_loc(shkp);
goto clear; goto clear;
} }
@@ -1676,7 +1684,7 @@ int croaked;
shkname(shkp), takes); shkname(shkp), takes);
taken = TRUE; taken = TRUE;
/* where to put player's invent (after disclosure) */ /* where to put player's invent (after disclosure) */
set_repo_loc(eshkp); set_repo_loc(shkp);
} else { } else {
#ifndef GOLDOBJ #ifndef GOLDOBJ
shkp->mgold += loss; shkp->mgold += loss;
@@ -1709,10 +1717,11 @@ clear:
} }
STATIC_OVL void STATIC_OVL void
set_repo_loc(eshkp) set_repo_loc(shkp)
struct eshk *eshkp; struct monst *shkp;
{ {
register xchar ox, oy; register xchar ox, oy;
struct eshk *eshkp = ESHK(shkp);
/* if you're not in this shk's shop room, or if you're in its doorway /* if you're not in this shk's shop room, or if you're in its doorway
or entry spot, then your gear gets dumped all the way inside */ or entry spot, then your gear gets dumped all the way inside */
@@ -1731,31 +1740,37 @@ struct eshk *eshkp;
oy = u.uy; oy = u.uy;
} }
/* finish_paybill will deposit invent here */ /* finish_paybill will deposit invent here */
repo_location.x = ox; repo.location.x = ox;
repo_location.y = oy; repo.location.y = oy;
repo.shopkeeper = shkp;
} }
/* called at game exit, after inventory disclosure but before making bones */ /* called at game exit, after inventory disclosure but before making bones */
void void
finish_paybill() finish_paybill()
{ {
register struct obj *otmp; struct monst *shkp = repo.shopkeeper;
int ox = repo_location.x, int ox = repo.location.x,
oy = repo_location.y; oy = repo.location.y;
#if 0 /* don't bother */ #if 0 /* don't bother */
if (ox == 0 && oy == 0) impossible("finish_paybill: no location"); if (ox == 0 && oy == 0) impossible("finish_paybill: no location");
#endif #endif
/* normally done by savebones(), but that's too late in this case */ /* normally done by savebones(), but that's too late in this case */
unleash_all(); unleash_all();
/* transfer all of the character's inventory to the shop floor */ /* if hero has any gold left, take it into shopkeeper's possession */
while ((otmp = invent) != 0) { if (shkp) {
otmp->owornmask = 0L; /* perhaps we should call setnotworn? */ #ifdef GOLDOBJ
otmp->lamplit = 0; /* avoid "goes out" msg from freeinv */ long umoney = money_cnt(invent);
if (rn2(5)) curse(otmp); /* normal bones treatment for invent */
obj_extract_self(otmp); if (umoney) money2mon(shkp, umoney);
place_object(otmp, ox, oy); #else
shkp->mgold += u.ugold;
u.ugold = 0L;
#endif
} }
/* transfer rest of the character's inventory to the shop floor */
drop_upon_death((struct monst *)0, (struct obj *)0, ox, oy);
} }
/* find obj on one of the lists */ /* find obj on one of the lists */