Remember price quotes that have been seen for types of item
These are displayed in discoveries, and a new 'price_quotes' option allows them to be displayed for un-IDed objects in other contexts too (the idea is that you turn on the option while identifying objects and off for general play). Invalidates existing save files.
This commit is contained in:
@@ -51,6 +51,7 @@ null allow nulls to be sent to your terminal [True]
|
||||
perm_invent keep inventory in a permanent window [False]
|
||||
pickup_stolen override pickup_types for stolen objects [True]
|
||||
pickup_thrown override pickup_types for thrown objects [True]
|
||||
price_quotes show remembered price quotes for unIDed items [False]
|
||||
pushweapon when wielding a new weapon, put your previously [False]
|
||||
wielded weapon into the secondary weapon slot
|
||||
quick_farsight usually skip the chance to browse the map when [False]
|
||||
|
||||
@@ -4592,6 +4592,15 @@ user name (on multi-user systems) or specifying a particular character
|
||||
name (on single-user systems) or it might be disabled entirely. Requesting
|
||||
it when not allowed or not possible results in explore mode instead.
|
||||
Default is normal play.
|
||||
.lp price_quotes
|
||||
Whenever the game mentions the name of an object you haven't identified yet,
|
||||
it also mentions the range of buy and sell prices you have seen for that
|
||||
item (to help narrow down what it could be).
|
||||
The price shown is the unit price for one item (even when you are looking at
|
||||
a stack of multiple items).
|
||||
Many players may want to turn this on while identifying objects, and then
|
||||
turn it back off again for general play.
|
||||
Default is off.
|
||||
.lp pushweapon
|
||||
Using the \(oqw\(cq (wield) command when already wielding
|
||||
something pushes the old item into your alternate weapon slot (default off).
|
||||
|
||||
@@ -2901,6 +2901,9 @@ archeologists can identify scrolls by deciphering their labels
|
||||
monster destroy armor -spell first erodes armor
|
||||
iron shoes protect the wearer against certain floor-based traps
|
||||
ring of stealth prevents hero from leaving tracks
|
||||
the game now automatically tracks which sell prices and buy prices you have
|
||||
seen for each type of item; these are visible in the discoveries list,
|
||||
and can also be shown elsewhere using the new 'price_quotes' option
|
||||
|
||||
|
||||
Platform- and/or Interface-Specific New Features
|
||||
|
||||
@@ -40,9 +40,14 @@ To add an entirely new option macro type:
|
||||
iii) an initialization of an element in the allopt[] array, at
|
||||
index opt_xxxx from step ii (xxxx is the option name).
|
||||
|
||||
2. Create the optfn_xxxx() function in options.c. Failure to do that will
|
||||
result in a link error of "undefined function optfn_xxxx." The functions are
|
||||
in options.c in alphabetical sequence by function name.
|
||||
2. If you are adding a boolean option, link it to a global variable
|
||||
(e.g. in flags or iflags) and update optfn_boolean in options.c if
|
||||
necessary.
|
||||
|
||||
3. If you are not adding a boolean option, create the optfn_xxxx()
|
||||
function in options.c. Failure to do that will result in a link error
|
||||
of "undefined function optfn_xxxx." The functions are in options.c in
|
||||
alphabetical sequence by function name.
|
||||
|
||||
The skeletal template for an optn_xxxx() function is:
|
||||
|
||||
@@ -83,7 +88,7 @@ To add an entirely new option macro type:
|
||||
return optn_ok;
|
||||
}
|
||||
|
||||
3. NOTE: If you add (or delete) an option, please update the short
|
||||
4. NOTE: If you add (or delete) an option, please update the short
|
||||
options help (option_help()), the long options help (dat/opthelp)
|
||||
and also the Guidebooks.
|
||||
|
||||
|
||||
@@ -2860,6 +2860,8 @@ extern void bclose(int);
|
||||
/* setpaid() has a conditional code block near the end of the
|
||||
function, where arg1 is tested for NULL, preventing NONNULLARG1 */
|
||||
extern void setpaid(struct monst *) NO_NNARGS;
|
||||
extern void record_price_quote(int, unsigned long, boolean);
|
||||
extern void append_price_quote(char *, char **, int) NONNULLARG12;
|
||||
extern long money2mon(struct monst *, long) NONNULLARG1;
|
||||
extern void money2u(struct monst *, long) NONNULLARG1;
|
||||
extern void shkgone(struct monst *) NONNULLARG1;
|
||||
|
||||
@@ -330,6 +330,7 @@ struct instance_flags {
|
||||
boolean num_pad; /* use numbers for movement commands */
|
||||
boolean perm_invent; /* display persistent inventory window */
|
||||
boolean perm_invent_pending; /* need to try again */
|
||||
boolean pricequotes; /* display price quotes on unIDd objects */
|
||||
boolean renameallowed; /* can change hero name during role selection */
|
||||
boolean renameinprogress; /* we are changing hero name */
|
||||
boolean sounds; /* master on/off switch for using soundlib */
|
||||
|
||||
@@ -104,6 +104,11 @@ struct objclass {
|
||||
#define oc_level oc_oc2 /* books: spell level */
|
||||
|
||||
unsigned short oc_nutrition; /* food value */
|
||||
|
||||
unsigned long oc_sell_minseen;
|
||||
unsigned long oc_sell_maxseen;
|
||||
unsigned long oc_buy_minseen;
|
||||
unsigned long oc_buy_maxseen;
|
||||
};
|
||||
|
||||
struct class_sym {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
#define OBJECT(obj,bits,prp,sym,prob,dly,wt, \
|
||||
cost,sdam,ldam,oc1,oc2,nut,color,sn) \
|
||||
{ 0, 0, (char *) 0, bits, prp, sym, dly, color, prob, wt, \
|
||||
cost, sdam, ldam, oc1, oc2, nut }
|
||||
cost, sdam, ldam, oc1, oc2, nut, -1UL, 0, -1UL, 0 }
|
||||
#define MARKER(tag,sn) /*empty*/
|
||||
|
||||
#elif defined(OBJECTS_ENUM)
|
||||
|
||||
@@ -589,6 +589,9 @@ static int optfn_##a(int, int, boolean, char *, char *);
|
||||
NHOPTB(preload_tiles, Advanced, 0, opt_out, set_in_config, /* MSDOS only */
|
||||
On, Yes, No, No, NoAlias, &iflags.wc_preload_tiles, Term_False,
|
||||
(char *)0)
|
||||
NHOPTB(price_quotes, General, 0, opt_in, set_in_game,
|
||||
Off, Yes, No, No, NoAlias, &iflags.pricequotes, Term_False,
|
||||
"display prices you have seen for unidentified objects")
|
||||
NHOPTB(pushweapon, Behavior, 0, opt_in, set_in_game,
|
||||
Off, Yes, No, No, NoAlias, &flags.pushweapon, Term_False,
|
||||
"previous weapon goes to secondary slot")
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Incrementing EDITLEVEL can be used to force invalidation of old bones
|
||||
* and save files.
|
||||
*/
|
||||
#define EDITLEVEL 132
|
||||
#define EDITLEVEL 133
|
||||
|
||||
/*
|
||||
* Development status possibilities.
|
||||
|
||||
20
src/o_init.c
20
src/o_init.c
@@ -688,16 +688,20 @@ disco_typename(int otyp)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* append typename(dis) to buf[], possibly truncating in the process */
|
||||
/* append typename(dis) to buf[], possibly truncating in the process;
|
||||
also append price quote information if it fits */
|
||||
staticfn void
|
||||
disco_append_typename(char *buf, int dis)
|
||||
{
|
||||
unsigned len = (unsigned) strlen(buf);
|
||||
size_t len = strlen(buf);
|
||||
char *p, *typnm = disco_typename(dis);
|
||||
size_t typnm_len = strlen(typnm);
|
||||
char *eos;
|
||||
|
||||
if (len + (unsigned) strlen(typnm) < BUFSZ) {
|
||||
if (len + typnm_len < BUFSZ) {
|
||||
/* ordinary */
|
||||
Strcat(buf, typnm);
|
||||
eos = buf + len + typnm_len;
|
||||
} else if ((p = strrchr(typnm, '(')) != 0
|
||||
&& p > typnm && p[-1] == ' ' && strchr(p, ')') != 0) {
|
||||
/* typename() returned "really long user-applied name (actual type)"
|
||||
@@ -706,10 +710,14 @@ disco_append_typename(char *buf, int dis)
|
||||
--p; /* back up to space in front of open paren */
|
||||
(void) strncat(buf, typnm, BUFSZ - 1 - (len + (unsigned) strlen(p)));
|
||||
Strcat(buf, p);
|
||||
eos = buf + strlen(buf);
|
||||
} else {
|
||||
/* unexpected; just truncate from end of typename */
|
||||
(void) strncat(buf, typnm, BUFSZ - 1 - len);
|
||||
eos = buf + strlen(buf);
|
||||
}
|
||||
|
||||
append_price_quote(buf, &eos, dis);
|
||||
}
|
||||
|
||||
/* minor fixup for Book of the Dead needed in more than one place */
|
||||
@@ -1125,6 +1133,7 @@ rename_disco(void)
|
||||
anything any;
|
||||
menu_item *selected = 0;
|
||||
int clr = NO_COLOR;
|
||||
char buf[BUFSZ];
|
||||
|
||||
any = cg.zeroany;
|
||||
tmpwin = create_nhwindow(NHW_MENU);
|
||||
@@ -1158,9 +1167,10 @@ rename_disco(void)
|
||||
prev_class = oclass;
|
||||
}
|
||||
any.a_int = dis;
|
||||
*buf = '\0';
|
||||
disco_append_typename(buf, dis);
|
||||
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
||||
ATR_NONE, clr,
|
||||
disco_typename(dis), MENU_ITEMFLAGS_NONE);
|
||||
ATR_NONE, clr, buf, MENU_ITEMFLAGS_NONE);
|
||||
}
|
||||
}
|
||||
if (ct == 0) {
|
||||
|
||||
@@ -1659,6 +1659,8 @@ doname_base(
|
||||
Sprintf(pricebuf, "%ld %s", quotedprice, currency(quotedprice));
|
||||
ConcatF2(bp, 0, " (%s, %s)",
|
||||
obj->unpaid ? "unpaid" : "contents", pricebuf);
|
||||
|
||||
record_price_quote(obj->otyp, quotedprice / obj->quan, TRUE);
|
||||
} else if (with_price) { /* on floor or in container on floor */
|
||||
int nochrg = 0;
|
||||
long price = get_cost_of_shop_item(obj, &nochrg);
|
||||
@@ -1672,6 +1674,11 @@ doname_base(
|
||||
} else if (nochrg > 0) {
|
||||
Concat(bp, 0, " (no charge)");
|
||||
}
|
||||
|
||||
if (price)
|
||||
record_price_quote(obj->otyp, price / obj->quan, TRUE);
|
||||
} else if (iflags.pricequotes && !objects[obj->otyp].oc_name_known) {
|
||||
append_price_quote(bp, &bp_eos, obj->otyp);
|
||||
}
|
||||
|
||||
if (!strncmp(prefix, "a ", 2)) {
|
||||
|
||||
@@ -5334,6 +5334,7 @@ optfn_boolean(
|
||||
disp.botl = TRUE;
|
||||
break;
|
||||
case opt_fixinv:
|
||||
case opt_price_quotes:
|
||||
case opt_sortpack:
|
||||
case opt_implicit_uncursed:
|
||||
case opt_wizweight:
|
||||
|
||||
67
src/shk.c
67
src/shk.c
@@ -433,6 +433,65 @@ setpaid(struct monst *shkp)
|
||||
}
|
||||
}
|
||||
|
||||
/* Remembers that a shopkeeper has quoted a particular price for a
|
||||
particular type of object. */
|
||||
void
|
||||
record_price_quote(int otyp, unsigned long price, boolean buyprice) {
|
||||
struct objclass *oc = &objects[otyp];
|
||||
if (buyprice) {
|
||||
if (price > oc->oc_buy_maxseen) oc->oc_buy_maxseen = price;
|
||||
if (price < oc->oc_buy_minseen) oc->oc_buy_minseen = price;
|
||||
} else {
|
||||
if (price > oc->oc_sell_maxseen) oc->oc_sell_maxseen = price;
|
||||
if (price < oc->oc_sell_minseen) oc->oc_sell_minseen = price;
|
||||
}
|
||||
}
|
||||
|
||||
/* Appends price-quote information to the given buffer, updating the
|
||||
given end of string position. *eos mut be buf + strlen(buf). If the
|
||||
update would make bug longer than BUFSZ, instead does nothing. */
|
||||
void
|
||||
append_price_quote(char *buf, char **eos, int otyp) {
|
||||
char buf2[BUFSZ];
|
||||
char *eos2 = buf2;
|
||||
const char *sep = "";
|
||||
size_t len = *eos - buf;
|
||||
size_t len2;
|
||||
|
||||
if (objects[otyp].oc_sell_minseen > objects[otyp].oc_sell_maxseen &&
|
||||
objects[otyp].oc_buy_minseen > objects[otyp].oc_buy_maxseen)
|
||||
return;
|
||||
|
||||
eos2 += sprintf(eos2, " {");
|
||||
|
||||
if (objects[otyp].oc_buy_minseen < objects[otyp].oc_buy_maxseen) {
|
||||
eos2 += sprintf(eos2, "buy %lu-%lu",
|
||||
objects[otyp].oc_buy_minseen,
|
||||
objects[otyp].oc_buy_maxseen);
|
||||
sep = " ";
|
||||
} else if (objects[otyp].oc_buy_minseen == objects[otyp].oc_buy_maxseen) {
|
||||
eos2 += sprintf(eos2, "buy %lu",
|
||||
objects[otyp].oc_buy_minseen);
|
||||
sep = " ";
|
||||
}
|
||||
|
||||
if (objects[otyp].oc_sell_minseen < objects[otyp].oc_sell_maxseen) {
|
||||
eos2 += sprintf(eos2, "%ssell %lu-%lu", sep,
|
||||
objects[otyp].oc_sell_minseen,
|
||||
objects[otyp].oc_sell_maxseen);
|
||||
} else if (objects[otyp].oc_sell_minseen == objects[otyp].oc_sell_maxseen) {
|
||||
eos2 += sprintf(eos2, "%ssell %lu", sep,
|
||||
objects[otyp].oc_sell_minseen);
|
||||
}
|
||||
|
||||
eos2 += sprintf(eos2, "}");
|
||||
len2 = eos2 - buf2;
|
||||
if (len2 < BUFSZ - len - 1) {
|
||||
Strcpy(*eos, buf2);
|
||||
*eos += len2;
|
||||
}
|
||||
}
|
||||
|
||||
staticfn long
|
||||
addupbill(struct monst *shkp)
|
||||
{
|
||||
@@ -3285,7 +3344,7 @@ add_one_tobill(
|
||||
bp->bo_id = obj->o_id;
|
||||
bp->bquan = obj->quan;
|
||||
if (dummy) { /* a dummy object must be inserted into */
|
||||
bp->useup = TRUE; /* the gb.billobjs chain here. crucial for */
|
||||
bp->useup = TRUE; /* the gb.billobjs chain here. crucial for */
|
||||
add_to_billobjs(obj); /* eating floorfood in shop. see eat.c */
|
||||
} else
|
||||
bp->useup = FALSE;
|
||||
@@ -3300,6 +3359,7 @@ add_one_tobill(
|
||||
}
|
||||
eshkp->billct++;
|
||||
obj->unpaid = 1;
|
||||
record_price_quote(obj->otyp, bp->price, TRUE);
|
||||
}
|
||||
|
||||
staticfn void
|
||||
@@ -3492,6 +3552,9 @@ addtobill(
|
||||
if (!Deaf && !muteshk(shkp) && !silent) {
|
||||
char buf[BUFSZ];
|
||||
|
||||
/* no need to update price quotes here; it was done by
|
||||
add_one_tobill above */
|
||||
|
||||
if (!ltmp) {
|
||||
pline("%s has no interest in %s.", Shknam(shkp), the(xname(obj)));
|
||||
return;
|
||||
@@ -3991,6 +4054,7 @@ sellobj(
|
||||
pline("%s cannot pay you at present.", Shknam(shkp));
|
||||
Sprintf(qbuf, "Will you accept %ld %s in credit for ", tmpcr,
|
||||
currency(tmpcr));
|
||||
record_price_quote(obj->otyp, tmpcr / obj->quan, FALSE);
|
||||
c = ynaq(safe_qbuf(qbuf, qbuf, "?", obj, doname, thesimpleoname,
|
||||
(obj->quan == 1L) ? "that" : "those"));
|
||||
if (c == 'a') {
|
||||
@@ -4086,6 +4150,7 @@ sellobj(
|
||||
: and_its_contents)
|
||||
: "",
|
||||
one ? "it" : "them");
|
||||
record_price_quote(obj->otyp, offer / obj->quan, FALSE);
|
||||
(void) safe_qbuf(qbuf, qbuf, qsfx, obj, xname, simpleonames,
|
||||
one ? "that" : "those");
|
||||
} else
|
||||
|
||||
Reference in New Issue
Block a user