diff --git a/doc/fixes34.4 b/doc/fixes34.4 index 07e14ca59..18e408055 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -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 don't give a speed change message when an immobile monster is seen to be hit 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 diff --git a/include/extern.h b/include/extern.h index f83c83e2b..fd80d6d69 100644 --- a/include/extern.h +++ b/include/extern.h @@ -122,6 +122,7 @@ E void NDECL(drag_down); /* ### bones.c ### */ +E void FDECL(drop_upon_death, (struct monst *,struct obj *,int,int)); E boolean NDECL(can_make_bones); E void FDECL(savebones, (struct obj *)); E int NDECL(getbones); diff --git a/src/bones.c b/src/bones.c index 7573a7aab..c27346f04 100644 --- a/src/bones.c +++ b/src/bones.c @@ -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. */ /* 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 void FDECL(goodfruit, (int)); STATIC_DCL void FDECL(resetobjs,(struct obj *,BOOLEAN_P)); -STATIC_DCL void FDECL(drop_upon_death, (struct monst *, struct obj *)); STATIC_OVL boolean no_bones_level(lev) @@ -164,14 +163,16 @@ boolean restore; } } -STATIC_OVL void -drop_upon_death(mtmp, cont) +/* called by savebones(); also by finish_paybill(shk.c) */ +void +drop_upon_death(mtmp, cont, x, y) struct monst *mtmp; struct obj *cont; +int x, y; { 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) { obj_extract_self(otmp); obj_no_longer_held(otmp); @@ -189,14 +190,15 @@ struct obj *cont; else if (cont) (void) add_to_container(cont, otmp); else - place_object(otmp, u.ux, u.uy); + place_object(otmp, x, y); } #ifndef GOLDOBJ if(u.ugold) { long ugold = u.ugold; + if (mtmp) mtmp->mgold = 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 */ } #endif @@ -299,12 +301,12 @@ struct obj *corpse; otmp = mk_named_object(STATUE, &mons[u.umonnum], 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 */ mtmp = (struct monst *)0; } else if (u.ugrave_arise < LOW_PM) { /* 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 * on your location */ @@ -321,7 +323,8 @@ struct obj *corpse; mtmp = makemon(&mons[u.ugrave_arise], u.ux, u.uy, NO_MM_FLAGS); in_mklev = FALSE; 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; } mtmp = christen_monst(mtmp, plname); @@ -332,7 +335,7 @@ struct obj *corpse; Your("body rises from the dead as %s...", an(mons[u.ugrave_arise].mname)); 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); } if (mtmp) { diff --git a/src/shk.c b/src/shk.c index a6dfbea00..07a9c2e75 100644 --- a/src/shk.c +++ b/src/shk.c @@ -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. */ /* 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 *)); STATIC_DCL struct obj *FDECL(bp_to_obj, (struct bill_x *)); 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 void FDECL(rile_shk, (struct monst *)); STATIC_DCL void FDECL(rouse_shk, (struct monst *,BOOLEAN_P)); @@ -1549,7 +1549,10 @@ boolean itemize; 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) */ 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 level teleports out of the dungeon and manages not to die */ 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 */ - repo_location.x = repo_location.y = 0; + repo.location.x = repo.location.y = 0; + repo.shopkeeper = 0; /* give shopkeeper first crack */ if ((mtmp = shop_keeper(*u.ushops)) && inhishop(mtmp)) { @@ -1631,10 +1638,11 @@ int croaked; if(roomno == eshkp->shoproom && inhishop(shkp) && !eshkp->billct && !eshkp->robbed && !eshkp->debit && NOTANGRY(shkp) && !eshkp->following) { - if (invent) + taken = (invent != 0); + if (taken) pline("%s gratefully inherits all your possessions.", shkname(shkp)); - set_repo_loc(eshkp); + set_repo_loc(shkp); goto clear; } @@ -1676,7 +1684,7 @@ int croaked; shkname(shkp), takes); taken = TRUE; /* where to put player's invent (after disclosure) */ - set_repo_loc(eshkp); + set_repo_loc(shkp); } else { #ifndef GOLDOBJ shkp->mgold += loss; @@ -1709,10 +1717,11 @@ clear: } STATIC_OVL void -set_repo_loc(eshkp) -struct eshk *eshkp; +set_repo_loc(shkp) +struct monst *shkp; { 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 or entry spot, then your gear gets dumped all the way inside */ @@ -1731,31 +1740,37 @@ struct eshk *eshkp; oy = u.uy; } /* finish_paybill will deposit invent here */ - repo_location.x = ox; - repo_location.y = oy; + repo.location.x = ox; + repo.location.y = oy; + repo.shopkeeper = shkp; } /* called at game exit, after inventory disclosure but before making bones */ void finish_paybill() { - register struct obj *otmp; - int ox = repo_location.x, - oy = repo_location.y; + struct monst *shkp = repo.shopkeeper; + int ox = repo.location.x, + oy = repo.location.y; #if 0 /* don't bother */ if (ox == 0 && oy == 0) impossible("finish_paybill: no location"); #endif /* normally done by savebones(), but that's too late in this case */ unleash_all(); - /* transfer all of the character's inventory to the shop floor */ - while ((otmp = invent) != 0) { - otmp->owornmask = 0L; /* perhaps we should call setnotworn? */ - otmp->lamplit = 0; /* avoid "goes out" msg from freeinv */ - if (rn2(5)) curse(otmp); /* normal bones treatment for invent */ - obj_extract_self(otmp); - place_object(otmp, ox, oy); + /* if hero has any gold left, take it into shopkeeper's possession */ + if (shkp) { +#ifdef GOLDOBJ + long umoney = money_cnt(invent); + + if (umoney) money2mon(shkp, umoney); +#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 */