From 3e28b6a164a97c890e4708f7bcf0a920bd2fa1a3 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Sun, 16 Jan 2011 00:31:28 +0000 Subject: [PATCH] monsters taking possession of shop items Noticed while looking through steal.c: theft that takes multiple turns uses stealarm() callback which removes stolen armor from hero's shopping bill, but theft that happened without delay did not. So theft of an unpaid non-armor or non-worn item while in a shop left it on the bill where it wouldn't show up for either ``I u'' or ``I x'', hiding the charge from the player ('$' did disclose the total amount that the shk was owed though), and the shopkeeper would persist in blocking the door. This makes immediate theft behave the same as delayed theft; the stolen item is removed from shop's bill when the thieving monster takes it away from the hero. Dropped items that a shopkeeper doesn't want have their no_charge bit set; that's only supposed to be used for floor items inside shops. But no_charge would stick when an object was picked up by a monster, so the object would stay free for player if that monster was subsequently killed in another shop which stocked that kind of item. Probably never noticed because most monsters won't pick up items off of shop floors, also most levels don't have other shops dealing with alternate types of stuff. This clears no_charge, except when the monster picking up the item is tame (so that a pet picking up and then dropping a no_change object in the same shop won't cause the shk to silently take possession, which would certainly lead to reports of a bug...). --- doc/fixes34.4 | 1 + src/steal.c | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/fixes34.4 b/doc/fixes34.4 index 16f539ae1..6ee51cc27 100644 --- a/doc/fixes34.4 +++ b/doc/fixes34.4 @@ -393,6 +393,7 @@ blanking items in pools while blind shouldn't reveal new obj description for ones which had been seen before becoming blind avoid infinite loop in topten output when killed by long-named monster grid bug could move diagonally 1 step using travel command +unpaid shop items stolen from hero by a monster remained on hero's shop bill Platform- and/or Interface-Specific Fixes diff --git a/src/steal.c b/src/steal.c index a85263398..fa1f49a32 100644 --- a/src/steal.c +++ b/src/steal.c @@ -1,5 +1,4 @@ /* NetHack 3.5 steal.c $Date$ $Revision$ */ -/* SCCS Id: @(#)steal.c 3.5 2008/11/02 */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */ /* NetHack may be freely redistributed. See license for details. */ @@ -469,6 +468,8 @@ gotobj: */ mtmp->mavenge = 1; + if(otmp->unpaid) + subfrombill(otmp, shop_keeper(*u.ushops)); freeinv(otmp); pline("%s stole %s.", named ? "She" : Monnam(mtmp), doname(otmp)); could_petrify = (otmp->otyp == CORPSE && @@ -508,6 +509,9 @@ register struct obj *otmp; pline("%s out.", Tobjnam(otmp, "go")); snuff_otmp = TRUE; } + /* for hero owned object on shop floor, mtmp is taking possession + and if it's eventually dropped in a shop, shk will claim it */ + if (!mtmp->mtame) otmp->no_charge = 0; /* Must do carrying effects on object prior to add_to_minv() */ carry_obj_effects(otmp); /* add_to_minv() might free otmp [if merged with something else], @@ -555,6 +559,8 @@ struct monst *mtmp; if (otmp) { /* we have something to snatch */ if (otmp->owornmask) remove_worn_item(otmp, TRUE); + if(otmp->unpaid) + subfrombill(otmp, shop_keeper(*u.ushops)); freeinv(otmp); /* mpickobj wont merge otmp because none of the above things to steal are mergable */