shopping objects, unpaid and no_charge, what else?
Revise sanity_check to acknowledge that buried objects might be unpaid or no_charge. (For unpaid, drop shop-owned object in a gap in the shop wall or in the free spot; for no_charge, drop something the shk doesn't care about, or drop any hero-owned item and decline to sell. Dig a pit. Push or drop a boulder to fill the pit.) Change 'I' to look for unpaid objects on the floor and for buried ones when deciding when to include 'u' in the list of candidate object classes and pseudo-classes. Change 'Iu' to mention buried unpaid objects as well as floor ones. For both non-invent categories, show a combined count without cost info. Have sanity_check of monster inventory test for unpaid and no_charge. When a monster (including pet) picks up an item that's marked unpaid (so one dropped on shop boundary, not an ordinary for-sale one), take it off hero's shopping bill. If dropped--pet behavior or monster death--inside the shop, it will become for-sale rather than no_charge or back on bill. [Removal from bill is needed to prevent an unpaid object ending up outside the shop if a monster carries it out, and current sanity_check complains about an unpaid item in mon->minvent.]
This commit is contained in:
+43
-24
@@ -30,7 +30,7 @@ static char display_pickinv(const char *, const char *, const char *,
|
|||||||
boolean, long *);
|
boolean, long *);
|
||||||
static char display_used_invlets(char);
|
static char display_used_invlets(char);
|
||||||
static boolean this_type_only(struct obj *);
|
static boolean this_type_only(struct obj *);
|
||||||
static void dounpaid(int);
|
static void dounpaid(int, int, int);
|
||||||
static struct obj *find_unpaid(struct obj *, struct obj **);
|
static struct obj *find_unpaid(struct obj *, struct obj **);
|
||||||
static void menu_identify(int);
|
static void menu_identify(int);
|
||||||
static boolean tool_being_used(struct obj *);
|
static boolean tool_being_used(struct obj *);
|
||||||
@@ -3732,19 +3732,22 @@ count_contents(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dounpaid(int floorcount)
|
dounpaid(
|
||||||
|
int count, /* unpaid items in inventory */
|
||||||
|
int floorcount, /* unpaid items on floor (rare) */
|
||||||
|
int buriedcount) /* unpaid items under the floor (extremely rare) */
|
||||||
{
|
{
|
||||||
winid win;
|
winid win;
|
||||||
struct obj *otmp, *marker, *contnr;
|
struct obj *otmp, *marker, *contnr;
|
||||||
char ilet;
|
char ilet;
|
||||||
char *invlet = flags.inv_order;
|
char *invlet = flags.inv_order;
|
||||||
int classcount, count, num_so_far;
|
int classcount, num_so_far, xtracount;
|
||||||
long cost, totcost;
|
long cost, totcost;
|
||||||
|
|
||||||
count = count_unpaid(gi.invent);
|
|
||||||
otmp = marker = contnr = (struct obj *) 0;
|
otmp = marker = contnr = (struct obj *) 0;
|
||||||
|
xtracount = floorcount + buriedcount;
|
||||||
|
|
||||||
if (count == 1 && !floorcount) {
|
if (count == 1 && !xtracount) {
|
||||||
otmp = find_unpaid(gi.invent, &marker);
|
otmp = find_unpaid(gi.invent, &marker);
|
||||||
contnr = unknwn_contnr_contents(otmp);
|
contnr = unknwn_contnr_contents(otmp);
|
||||||
}
|
}
|
||||||
@@ -3831,18 +3834,31 @@ dounpaid(int floorcount)
|
|||||||
xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
|
xprname((struct obj *) 0, "Total:", '*', FALSE, totcost, 0L));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (floorcount > 0) {
|
/* an unpaid item can be on the floor if dropped on the shop boundary
|
||||||
|
(then possibly moved all the way into the shop during wall repair);
|
||||||
|
one can be buried if it started that way and a pit was dug at its
|
||||||
|
spot then filled by a boulder (or perhaps a theme room with a pool
|
||||||
|
and an unpaid item moved into that by wall repair, then freezing) */
|
||||||
|
if (xtracount > 0) { /* floorcount + buriedcount > 0 */
|
||||||
char buf[BUFSZ];
|
char buf[BUFSZ];
|
||||||
const char *floorverb = (floorcount > 1) ? "are" : "is";
|
const char
|
||||||
|
*floorverb = (xtracount > 1) ? "are" : "is",
|
||||||
|
/* "under the floor" might actually be "under the floor
|
||||||
|
beneath a wall" when shop repair is involved but that seems
|
||||||
|
too nit-picky to bother trying to handle here (even more
|
||||||
|
extreme description-wise: "under the floor beneath the
|
||||||
|
door/doorway") */
|
||||||
|
*where = (buriedcount == 0) ? "on the floor"
|
||||||
|
: (floorcount == 0) ? "under the floor"
|
||||||
|
: "on or under the floor";
|
||||||
|
|
||||||
if (!count) {
|
if (!count) {
|
||||||
You(
|
You("aren't carrying any unpaid items but there %s %d %s.",
|
||||||
"aren't carrying any unpaid items but there %s %d on the floor.",
|
floorverb, xtracount, where);
|
||||||
floorverb, floorcount);
|
|
||||||
} else {
|
} else {
|
||||||
putstr(win, 0, "");
|
putstr(win, 0, "");
|
||||||
Sprintf(buf, "(There %s %d more unpaid object%s on the floor.)",
|
Sprintf(buf, "(There %s %d more unpaid object%s %s.)",
|
||||||
floorverb, floorcount, plur(floorcount));
|
floorverb, xtracount, plur(xtracount), where);
|
||||||
putstr(win, 0, buf);
|
putstr(win, 0, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3850,6 +3866,7 @@ dounpaid(int floorcount)
|
|||||||
if (count > 0)
|
if (count > 0)
|
||||||
display_nhwindow(win, FALSE);
|
display_nhwindow(win, FALSE);
|
||||||
destroy_nhwindow(win);
|
destroy_nhwindow(win);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3896,7 +3913,8 @@ dotypeinv(void)
|
|||||||
int n, i = 0;
|
int n, i = 0;
|
||||||
char *extra_types, types[BUFSZ], title[QBUFSZ];
|
char *extra_types, types[BUFSZ], title[QBUFSZ];
|
||||||
const char *before = "", *after = "";
|
const char *before = "", *after = "";
|
||||||
int class_count, oclass, unpaid_count, itemcount;
|
int class_count, oclass, itemcount,
|
||||||
|
any_unpaid, u_carried, u_floor, u_buried;
|
||||||
int bcnt, ccnt, ucnt, xcnt, ocnt, jcnt;
|
int bcnt, ccnt, ucnt, xcnt, ocnt, jcnt;
|
||||||
boolean billx = *u.ushops && doinvbill(0);
|
boolean billx = *u.ushops && doinvbill(0);
|
||||||
menu_item *pick_list;
|
menu_item *pick_list;
|
||||||
@@ -3909,7 +3927,10 @@ dotypeinv(void)
|
|||||||
goto doI_done;
|
goto doI_done;
|
||||||
}
|
}
|
||||||
title[0] = '\0';
|
title[0] = '\0';
|
||||||
unpaid_count = count_unpaid(gi.invent);
|
u_carried = count_unpaid(gi.invent);
|
||||||
|
u_floor = count_unpaid(fobj);
|
||||||
|
u_buried = count_unpaid(gl.level.buriedobjlist);
|
||||||
|
any_unpaid = u_carried + u_floor + u_buried;
|
||||||
tally_BUCX(gi.invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt, &jcnt);
|
tally_BUCX(gi.invent, FALSE, &bcnt, &ucnt, &ccnt, &xcnt, &ocnt, &jcnt);
|
||||||
|
|
||||||
if (flags.menu_style != MENU_TRADITIONAL) {
|
if (flags.menu_style != MENU_TRADITIONAL) {
|
||||||
@@ -3943,9 +3964,9 @@ dotypeinv(void)
|
|||||||
class_count = collect_obj_classes(types, gi.invent, FALSE,
|
class_count = collect_obj_classes(types, gi.invent, FALSE,
|
||||||
(boolean (*)(OBJ_P)) 0,
|
(boolean (*)(OBJ_P)) 0,
|
||||||
&itemcount);
|
&itemcount);
|
||||||
if (unpaid_count || billx || (bcnt + ccnt + ucnt + xcnt) != 0 || jcnt)
|
if (any_unpaid || billx || (bcnt + ccnt + ucnt + xcnt) != 0 || jcnt)
|
||||||
types[class_count++] = ' ';
|
types[class_count++] = ' ';
|
||||||
if (unpaid_count)
|
if (any_unpaid)
|
||||||
types[class_count++] = 'u';
|
types[class_count++] = 'u';
|
||||||
if (billx)
|
if (billx)
|
||||||
types[class_count++] = 'x';
|
types[class_count++] = 'x';
|
||||||
@@ -3963,7 +3984,7 @@ dotypeinv(void)
|
|||||||
/* add everything not already included; user won't see these */
|
/* add everything not already included; user won't see these */
|
||||||
extra_types = eos(types);
|
extra_types = eos(types);
|
||||||
*extra_types++ = '\033';
|
*extra_types++ = '\033';
|
||||||
if (!unpaid_count)
|
if (!any_unpaid)
|
||||||
*extra_types++ = 'u';
|
*extra_types++ = 'u';
|
||||||
if (!billx)
|
if (!billx)
|
||||||
*extra_types++ = 'x';
|
*extra_types++ = 'x';
|
||||||
@@ -3992,7 +4013,7 @@ dotypeinv(void)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* only one thing to itemize */
|
/* only one thing to itemize */
|
||||||
if (unpaid_count)
|
if (any_unpaid)
|
||||||
c = 'u';
|
c = 'u';
|
||||||
else if (billx)
|
else if (billx)
|
||||||
c = 'x';
|
c = 'x';
|
||||||
@@ -4005,14 +4026,12 @@ dotypeinv(void)
|
|||||||
(void) doinvbill(1);
|
(void) doinvbill(1);
|
||||||
else
|
else
|
||||||
pline("No used-up objects%s.",
|
pline("No used-up objects%s.",
|
||||||
unpaid_count ? " on your shopping bill" : "");
|
any_unpaid ? " on your shopping bill" : "");
|
||||||
goto doI_done;
|
goto doI_done;
|
||||||
}
|
}
|
||||||
if (c == 'u' || (c == 'U' && unpaid_count && !ucnt)) {
|
if (c == 'u' || (c == 'U' && any_unpaid && !ucnt)) {
|
||||||
int floorcount = count_unpaid(fobj);
|
if (any_unpaid)
|
||||||
|
dounpaid(u_carried, u_floor, u_buried);
|
||||||
if (unpaid_count || floorcount)
|
|
||||||
dounpaid(floorcount);
|
|
||||||
else
|
else
|
||||||
You("are not carrying any unpaid objects.");
|
You("are not carrying any unpaid objects.");
|
||||||
goto doI_done;
|
goto doI_done;
|
||||||
|
|||||||
+20
-11
@@ -2131,10 +2131,7 @@ place_object(struct obj *otmp, coordxy x, coordxy y)
|
|||||||
here without display code needing to traverse pile chain to find one */
|
here without display code needing to traverse pile chain to find one */
|
||||||
if (otmp2 && otmp2->otyp == BOULDER && otmp->otyp != BOULDER) {
|
if (otmp2 && otmp2->otyp == BOULDER && otmp->otyp != BOULDER) {
|
||||||
/* 3.6.3: put otmp under last consecutive boulder rather than under
|
/* 3.6.3: put otmp under last consecutive boulder rather than under
|
||||||
just the first one; multiple boulders at same spot in new games
|
just the first one */
|
||||||
will be consecutive due to this, ones in old games saved before
|
|
||||||
this change might not be; can affect the map display if the top
|
|
||||||
boulder is moved/removed by some means other than pushing */
|
|
||||||
while (otmp2->nexthere && otmp2->nexthere->otyp == BOULDER)
|
while (otmp2->nexthere && otmp2->nexthere->otyp == BOULDER)
|
||||||
otmp2 = otmp2->nexthere;
|
otmp2 = otmp2->nexthere;
|
||||||
otmp->nexthere = otmp2->nexthere;
|
otmp->nexthere = otmp2->nexthere;
|
||||||
@@ -2145,11 +2142,16 @@ place_object(struct obj *otmp, coordxy x, coordxy y)
|
|||||||
gl.level.objects[x][y] = otmp;
|
gl.level.objects[x][y] = otmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set the new object's location */
|
/* set the object's new location */
|
||||||
otmp->ox = x;
|
otmp->ox = x;
|
||||||
otmp->oy = y;
|
otmp->oy = y;
|
||||||
otmp->where = OBJ_FLOOR;
|
otmp->where = OBJ_FLOOR;
|
||||||
|
|
||||||
|
/* if placed outside of shop, no_charge is no longer applicable */
|
||||||
|
if (otmp->no_charge && !costly_spot(x, y)
|
||||||
|
&& !costly_adjacent(find_objowner(otmp, x, y), x, y))
|
||||||
|
otmp->no_charge = 0;
|
||||||
|
|
||||||
/* add to floor chain */
|
/* add to floor chain */
|
||||||
otmp->nobj = fobj;
|
otmp->nobj = fobj;
|
||||||
fobj = otmp;
|
fobj = otmp;
|
||||||
@@ -2819,10 +2821,11 @@ shop_obj_sanity(struct obj *obj, const char *mesg)
|
|||||||
billobjs list, and for floor items outside the shop proper
|
billobjs list, and for floor items outside the shop proper
|
||||||
but within the shop boundary (walls, door, "free spot") and
|
but within the shop boundary (walls, door, "free spot") and
|
||||||
for objects moved from such spots into the shop proper by
|
for objects moved from such spots into the shop proper by
|
||||||
repair of shop walls */
|
repair of shop walls or items buried while on boundary */
|
||||||
if (otop->where != OBJ_INVENT
|
if (otop->where != OBJ_INVENT
|
||||||
&& obj->where != OBJ_ONBILL /* when on bill, obj==otop */
|
&& obj->where != OBJ_ONBILL /* when on bill, obj==otop */
|
||||||
&& (otop->where != OBJ_FLOOR || (!costly && !costlytoo)))
|
&& ((otop->where != OBJ_FLOOR && obj->where != OBJ_BURIED)
|
||||||
|
|| !(costly || costlytoo)))
|
||||||
why = "%s unpaid obj not carried! %s %s: %s";
|
why = "%s unpaid obj not carried! %s %s: %s";
|
||||||
else if (!costly && !costlytoo)
|
else if (!costly && !costlytoo)
|
||||||
why = "%s unpaid obj not inside tended shop! %s %s: %s";
|
why = "%s unpaid obj not inside tended shop! %s %s: %s";
|
||||||
@@ -2831,9 +2834,12 @@ shop_obj_sanity(struct obj *obj, const char *mesg)
|
|||||||
else if (!onshopbill(obj, shkp, TRUE))
|
else if (!onshopbill(obj, shkp, TRUE))
|
||||||
why = "%s unpaid obj not on shop bill! %s %s: %s";
|
why = "%s unpaid obj not on shop bill! %s %s: %s";
|
||||||
} else if (obj->no_charge) {
|
} else if (obj->no_charge) {
|
||||||
/* no_charge is only applicable for floor objects in shops
|
/* no_charge is only applicable for floor objects in shops, for
|
||||||
and for objects inside floor containers in shops */
|
objects inside floor containers in shops, and for objects buried
|
||||||
if (otop->where != OBJ_FLOOR)
|
beneath the shop floor or carried by a monster (usually pet) */
|
||||||
|
if (otop->where != OBJ_FLOOR
|
||||||
|
&& otop->where != OBJ_BURIED
|
||||||
|
&& otop->where != OBJ_MINVENT)
|
||||||
why = "%s no_charge obj not on floor! %s %s: %s";
|
why = "%s no_charge obj not on floor! %s %s: %s";
|
||||||
else if (!costly && !costlytoo)
|
else if (!costly && !costlytoo)
|
||||||
why = "%s no_charge obj not inside tended shop! %s %s: %s";
|
why = "%s no_charge obj not inside tended shop! %s %s: %s";
|
||||||
@@ -2843,7 +2849,8 @@ shop_obj_sanity(struct obj *obj, const char *mesg)
|
|||||||
why = "%s no_charge obj on shop bill! %s %s: %s";
|
why = "%s no_charge obj on shop bill! %s %s: %s";
|
||||||
}
|
}
|
||||||
if (why)
|
if (why)
|
||||||
insane_object(obj, why, mesg, (struct monst *) 0);
|
insane_object(obj, why, mesg,
|
||||||
|
mcarried(otop) ? otop->ocarry : (struct monst *) 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2872,6 +2879,8 @@ mon_obj_sanity(struct monst *monlist, const char *mesg)
|
|||||||
if (obj->globby)
|
if (obj->globby)
|
||||||
check_glob(obj, mesg);
|
check_glob(obj, mesg);
|
||||||
check_contained(obj, mesg);
|
check_contained(obj, mesg);
|
||||||
|
if (obj->unpaid || obj->no_charge)
|
||||||
|
shop_obj_sanity(obj, mesg);
|
||||||
if (obj->in_use || obj->bypass || obj->nomerge
|
if (obj->in_use || obj->bypass || obj->nomerge
|
||||||
|| (obj->otyp == BOULDER && obj->next_boulder))
|
|| (obj->otyp == BOULDER && obj->next_boulder))
|
||||||
insane_obj_bits(obj, mon);
|
insane_obj_bits(obj, mon);
|
||||||
|
|||||||
@@ -510,6 +510,11 @@ mpickobj(struct monst *mtmp, struct obj *otmp)
|
|||||||
gt.thrownobj = 0;
|
gt.thrownobj = 0;
|
||||||
else if (otmp == gk.kickedobj)
|
else if (otmp == gk.kickedobj)
|
||||||
gk.kickedobj = 0;
|
gk.kickedobj = 0;
|
||||||
|
/* an unpaid item can be on the floor; if a monster picks it up, take
|
||||||
|
it off the shop bill */
|
||||||
|
if (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp->cobj))) {
|
||||||
|
subfrombill(otmp, find_objowner(otmp, otmp->ox, otmp->oy));
|
||||||
|
}
|
||||||
/* don't want hidden light source inside the monster; assumes that
|
/* don't want hidden light source inside the monster; assumes that
|
||||||
engulfers won't have external inventories; whirly monsters cause
|
engulfers won't have external inventories; whirly monsters cause
|
||||||
the light to be extinguished rather than letting it shine thru */
|
the light to be extinguished rather than letting it shine thru */
|
||||||
|
|||||||
Reference in New Issue
Block a user