/* release a monster from a bag of tricks; return number of monsters created */
int
-bagotricks(bag, tipping)
+bagotricks(bag, tipping, seencount)
struct obj *bag;
boolean tipping; /* caller emptying entire contents; affects shop handling */
+int *seencount; /* secondary output */
{
int moncount = 0;
if (bag->dknown && objects[bag->otyp].oc_name_known) bag->cknown = 1;
} else {
struct monst *mtmp;
- boolean sawone = FALSE;
- int creatcnt = 1;
+ int creatcnt = 1, seecount = 0;
consume_obj_charge(bag, !tipping);
mtmp = makemon((struct permonst *)0, u.ux, u.uy, NO_MM_FLAGS);
if (mtmp) {
++moncount;
- if (canspotmon(mtmp)) sawone = TRUE;
+ if (canspotmon(mtmp)) ++seecount;
}
} while (--creatcnt > 0);
- if (sawone) {
+ if (seecount) {
+ if (seencount) *seencount += seecount;
/* don't set contents-known flag if we just used last charge
(such suppression doesn't actually gain us much since
player can now deduce that the bag has become empty) */
if (bag->spe > 0) bag->cknown = 1;
if (bag->dknown) makeknown(BAG_OF_TRICKS);
- } else {
- /* #tip while blind can trigger this successive times */
- Norep("Nothing seems to happen.");
+ } else if (!tipping) {
+ pline(!moncount ? nothing_happens : "Nothing seems to happen.");
}
}
return moncount;
tipcontainer(box)
struct obj *box; /* or bag */
{
- boolean empty_it = FALSE;
+ xchar ox = u.ux, oy = u.uy; /* #tip only works at hero's location */
+ boolean empty_it = FALSE,
+ /* Shop handling: can't rely on the container's own unpaid
+ or no_charge status because contents might differ with it.
+ A carried container's contents will be flagged as unpaid
+ or not, as appropriate, and need no special handling here.
+ Items owned by the hero get sold to the shop without
+ confirmation as with other uncontrolled drops. A floor
+ container's contents will be marked no_charge if owned by
+ hero, otherwise they're owned by the shop. By passing
+ the contents through shop billing, they end up getting
+ treated the same as in the carried case. We do so one
+ item at a time instead of doing whole container at once
+ to reduce the chance of exhausting shk's billing capacity. */
+ maybeshopgoods = !carried(box) && costly_spot(ox, oy);
/* caveat: this assumes that cknown, lknown, olocked, and otrapped
fields haven't been overloaded to mean something special for the
}
} else if (box->otyp == BAG_OF_TRICKS || box->otyp == HORN_OF_PLENTY) {
boolean bag = box->otyp == BAG_OF_TRICKS;
- int old_spe = box->spe;
+ int old_spe = box->spe, seen = 0;
+ if (maybeshopgoods && !box->no_charge)
+ addtobill(box, FALSE, FALSE, TRUE);
/* apply this bag/horn until empty or monster/object creation fails
(if the latter occurs, force the former...) */
do {
- if (!(bag ? bagotricks(box, TRUE) : hornoplenty(box, TRUE)))
+ if (!(bag ? bagotricks(box, TRUE, &seen) : hornoplenty(box, TRUE)))
break;
} while (box->spe > 0);
if (box->spe < old_spe) {
+ if (bag) pline((seen == 0) ? "Nothing seems to happen." :
+ (seen == 1) ? "A monster appears." :
+ "Monsters appear!");
/* check_unpaid wants to see a non-zero charge count */
box->spe = old_spe;
check_unpaid_usage(box, TRUE);
box->spe = 0; /* empty */
box->cknown = 1;
}
+ if (maybeshopgoods && !box->no_charge)
+ subfrombill(box, shop_keeper(*in_rooms(ox, oy, SHOPBASE)));
} else if (box->spe) {
char yourbuf[BUFSZ];
struct obj *otmp, *nobj;
boolean verbose = FALSE,
highdrop = !can_reach_floor(TRUE),
- altarizing = IS_ALTAR(levl[u.ux][u.uy].typ),
+ altarizing = IS_ALTAR(levl[ox][oy].typ),
cursed_mbag = (Is_mbag(box) && box->cursed);
int held = carried(box);
long loss = 0L;
loss += mbag_item_gone(held, otmp);
/* abbreviated drop format is no longer appropriate */
verbose = TRUE;
- } else if (highdrop) {
+ continue;
+ }
+
+ if (maybeshopgoods) {
+ addtobill(otmp, FALSE, FALSE, TRUE);
+ iflags.suppress_price++; /* doname formatting */
+ }
+
+ if (highdrop) {
/* might break or fall down stairs; handles altars itself */
hitfloor(otmp);
} else {
doaltarobj(otmp);
else if (verbose)
pline("%s %s to the %s.", Doname2(otmp),
- otense(otmp, "drop"), surface(u.ux, u.uy));
+ otense(otmp, "drop"), surface(ox, oy));
else
pline("%s%c", doname(otmp), nobj ? ',' : '.');
dropy(otmp);
}
+ if (maybeshopgoods) iflags.suppress_price--; /* reset */
}
if (loss) /* magic bag lost some shop goods */
You("owe %ld %s for lost merchandise.", loss, currency(loss));