give player an inkling of why corpses didn't stack
When corpses haven't stacked, and there is no player-discernable reason why, provide some additional information in some cases, but only when it is required. Gender variance is the supported case in this commit. Related to GitHub issue #1607. This commit doesn't change the underlying mechanics to allow the corpses to stack, but it does help the player understand why that's the case in this instance.
This commit is contained in:
@@ -803,6 +803,9 @@ struct instance_globals_p {
|
||||
int poly_zapped;
|
||||
|
||||
/* new stuff */
|
||||
int puzzling_critera;
|
||||
char puzzling_ilets[invlet_basic + 1];
|
||||
|
||||
boolean havestate;
|
||||
};
|
||||
|
||||
|
||||
@@ -1404,6 +1404,7 @@ extern void perm_invent_toggled(boolean negated);
|
||||
extern void prepare_perminvent(winid window);
|
||||
extern struct obj *carrying_stoning_corpse(void);
|
||||
extern void repopulate_perminvent(void);
|
||||
extern int check_for_puzzling_nonmerge(struct obj *);
|
||||
|
||||
/* ### ioctl.c ### */
|
||||
|
||||
@@ -2236,6 +2237,8 @@ extern boolean the_unique_pm(struct permonst *) NONNULLARG1;
|
||||
extern boolean erosion_matters(struct obj *) NONNULLARG1;
|
||||
extern char *doname(struct obj *) NONNULLARG1;
|
||||
extern char *doname_with_price(struct obj *) NONNULLARG1;
|
||||
extern char *doname_with_cgender(struct obj *) NONNULLARG1;
|
||||
extern char *doname_with_price_and_cgender(struct obj *) NONNULLARG1;
|
||||
extern char *doname_vague_quan(struct obj *) NONNULLARG1;
|
||||
extern boolean not_fully_identified(struct obj *) NONNULLARG1;
|
||||
extern char *corpse_xname(struct obj *, const char *, unsigned) NONNULLARG1;
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
#define CXN_PFX_THE 4 /* prefix with "the " (unless pname) */
|
||||
#define CXN_ARTICLE 8 /* include a/an/the prefix */
|
||||
#define CXN_NOCORPSE 16 /* suppress " corpse" suffix */
|
||||
#define CXN_ADDGNDR 32 /* include a gender */
|
||||
|
||||
/* number of turns it takes for vault guard to show up */
|
||||
#define VAULT_GUARD_TIME 30
|
||||
|
||||
@@ -648,6 +648,13 @@ static const struct instance_globals_p g_init_p = {
|
||||
UNDEFINED_PTR, /* propellor */
|
||||
/* zap.c */
|
||||
UNDEFINED_VALUE, /* poly_zap */
|
||||
0, /* puzzling_criteria */
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
}, /* puzzling_ilets[] */
|
||||
|
||||
TRUE, /* havestate*/
|
||||
};
|
||||
|
||||
|
||||
+60
-4
@@ -2701,6 +2701,51 @@ count_unidentified(struct obj *objchn)
|
||||
return unid_cnt;
|
||||
}
|
||||
|
||||
/* mark the puzzling items */
|
||||
int
|
||||
check_for_puzzling_nonmerge(struct obj *objchn)
|
||||
{
|
||||
int i, k, idx, puzzling_cnt = 0, ilet, mnums[invlet_basic + 1],
|
||||
gndr[invlet_basic + 1];
|
||||
struct obj *obj;
|
||||
boolean at_least_one = FALSE;
|
||||
|
||||
for (i = 0; i < invlet_basic + 1; ++i)
|
||||
gp.puzzling_ilets[i] = mnums[i] = gndr[i] = 0;
|
||||
|
||||
|
||||
for (obj = objchn; obj; obj = obj->nobj) {
|
||||
if (obj->otyp == CORPSE
|
||||
&& obj->corpsenm >= 0 && obj->corpsenm < NUMMONS) {
|
||||
ilet = obj->invlet;
|
||||
idx = (ilet >= 'A' && ilet <= 'Z') ? ilet - 'A'
|
||||
: (ilet >= 'a' && ilet <= 'z') ? ilet - 'a' + 26
|
||||
: 53;
|
||||
if (idx < 53) {
|
||||
mnums[idx] = obj->corpsenm;
|
||||
gndr[idx] = (obj->spe & CORPSTAT_MALE) ? CORPSTAT_MALE
|
||||
: CORPSTAT_FEMALE;
|
||||
at_least_one = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (at_least_one) {
|
||||
for (i = 0; i < invlet_basic; ++i) {
|
||||
for (k = i + 1; k < invlet_basic; ++k) {
|
||||
if (k == i)
|
||||
continue;
|
||||
if (mnums[k] == mnums[i] && gndr[k] != gndr[i]) {
|
||||
++puzzling_cnt;
|
||||
gp.puzzling_ilets[i] = gp.puzzling_ilets[k] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (puzzling_cnt)
|
||||
gp.puzzling_critera = 411;
|
||||
}
|
||||
return puzzling_cnt;
|
||||
}
|
||||
|
||||
/* dialog with user to identify a given number of items; 0 means all */
|
||||
void
|
||||
identify_pack(
|
||||
@@ -3064,7 +3109,7 @@ display_pickinv(
|
||||
struct obj *otmp, wizid_fakeobj, inuse_fakeobj;
|
||||
char ilet, ret, *formattedobj;
|
||||
const char *invlet = flags.inv_order;
|
||||
int n, classcount, inusecount = 0;
|
||||
int n, classcount, inusecount = 0, puzzling_count = 0;
|
||||
winid win; /* windows being used */
|
||||
anything any;
|
||||
menu_item *selected;
|
||||
@@ -3212,6 +3257,9 @@ display_pickinv(
|
||||
sortedinvent[0].obj = (struct obj *) 0;
|
||||
}
|
||||
|
||||
|
||||
puzzling_count = check_for_puzzling_nonmerge(gi.invent);
|
||||
|
||||
start_menu(win, menu_behavior);
|
||||
any = cg.zeroany;
|
||||
if (wizid) {
|
||||
@@ -3314,7 +3362,9 @@ display_pickinv(
|
||||
/* normal inventory item */
|
||||
tmpglyph = obj_to_glyph(otmp, rn2_on_display_rng);
|
||||
map_glyphinfo(0, 0, tmpglyph, 0U, &tmpglyphinfo);
|
||||
formattedobj = doname(otmp);
|
||||
formattedobj = !puzzling_count
|
||||
? doname(otmp)
|
||||
: doname_with_cgender(otmp);
|
||||
add_menu(win, &tmpglyphinfo, &any, ilet,
|
||||
wizid ? def_oc_syms[(int) otmp->oclass].sym : 0,
|
||||
ATR_NONE, clr, formattedobj, MENU_ITEMFLAGS_NONE);
|
||||
@@ -4110,6 +4160,7 @@ look_here(
|
||||
picked_some = (lookhere_flags & LOOKHERE_PICKED_SOME) != 0,
|
||||
/* skip 'dfeature' if caller used describe_decor() to show it */
|
||||
skip_dfeature = (lookhere_flags & LOOKHERE_SKIP_DFEATURE) != 0;
|
||||
int puzzling_count = 0;
|
||||
|
||||
/* default pile_limit is 5; a value of 0 means "never skip"
|
||||
(and 1 effectively forces "always skip") */
|
||||
@@ -4173,6 +4224,7 @@ look_here(
|
||||
}
|
||||
|
||||
otmp = svl.level.objects[u.ux][u.uy];
|
||||
puzzling_count = check_for_puzzling_nonmerge(otmp);
|
||||
dfeature = dfeature_at(u.ux, u.uy, fbuf2);
|
||||
if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
|
||||
dfeature = 0;
|
||||
@@ -4294,11 +4346,15 @@ look_here(
|
||||
for (; otmp; otmp = otmp->nexthere) {
|
||||
if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
|
||||
felt_cockatrice = TRUE;
|
||||
Sprintf(buf, "%s...", doname(otmp));
|
||||
Sprintf(buf, "%s...",
|
||||
(puzzling_count) ? doname_with_cgender(otmp)
|
||||
: doname(otmp));
|
||||
putstr(tmpwin, 0, buf);
|
||||
break;
|
||||
}
|
||||
putstr(tmpwin, 0, doname_with_price(otmp));
|
||||
putstr(tmpwin, 0,
|
||||
(puzzling_count) ? doname_with_price_and_cgender(otmp)
|
||||
: doname_with_price(otmp));
|
||||
}
|
||||
display_nhwindow(tmpwin, TRUE);
|
||||
destroy_nhwindow(tmpwin);
|
||||
|
||||
+36
-7
@@ -1214,9 +1214,10 @@ erosion_matters(struct obj *obj)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define DONAME_WITH_PRICE 1
|
||||
#define DONAME_VAGUE_QUAN 2
|
||||
#define DONAME_FOR_MENU 4 /* [not used anywhere yet] */
|
||||
#define DONAME_WITH_PRICE 1
|
||||
#define DONAME_VAGUE_QUAN 2
|
||||
#define DONAME_FOR_MENU 4 /* [not used anywhere yet] */
|
||||
#define DONAME_FORCE_GENDER 8 /* always add male or female */
|
||||
|
||||
/* core of doname() */
|
||||
staticfn char *
|
||||
@@ -1227,7 +1228,8 @@ doname_base(
|
||||
boolean ispoisoned = FALSE,
|
||||
with_price = (doname_flags & DONAME_WITH_PRICE) != 0,
|
||||
vague_quan = (doname_flags & DONAME_VAGUE_QUAN) != 0,
|
||||
for_menu = (doname_flags & DONAME_FOR_MENU) != 0;
|
||||
for_menu = (doname_flags & DONAME_FOR_MENU) != 0,
|
||||
with_corpse_genders = (doname_flags & DONAME_FORCE_GENDER) != 0;
|
||||
boolean known, dknown, cknown, bknown, lknown,
|
||||
fake_arti, force_the;
|
||||
char prefix[PREFIX];
|
||||
@@ -1511,7 +1513,15 @@ doname_base(
|
||||
unsigned cxarg = (((obj->quan != 1L) ? 0 : CXN_ARTICLE)
|
||||
| CXN_NOCORPSE);
|
||||
char *cxstr, *save_xnamep;
|
||||
int puzzidx = (obj->invlet >= 'A' && obj->invlet <= 'Z')
|
||||
? obj->invlet - 'A'
|
||||
: (obj->invlet >= 'a' && obj->invlet <= 'z')
|
||||
? obj->invlet - 'a' + 26
|
||||
: 53; /* valid index, but always holds zero */
|
||||
|
||||
if (with_corpse_genders && puzzidx < 53
|
||||
&& gp.puzzling_critera == 411 && gp.puzzling_ilets[puzzidx])
|
||||
cxarg |= CXN_ADDGNDR;
|
||||
/* corpse_xname() sets xnamep; callers other than doname_base()
|
||||
itself shouldn't care about xnamep (pointer to start of
|
||||
current obuf[]) but keep it accurate anyway */
|
||||
@@ -1763,6 +1773,20 @@ doname_with_price(struct obj *obj)
|
||||
return doname_base(obj, DONAME_WITH_PRICE);
|
||||
}
|
||||
|
||||
/* Name of object including corpse genders. */
|
||||
char *
|
||||
doname_with_cgender(struct obj *obj)
|
||||
{
|
||||
return doname_base(obj, DONAME_FORCE_GENDER);
|
||||
}
|
||||
|
||||
/* doname with both price and corpse gender */
|
||||
char *
|
||||
doname_with_price_and_cgender(struct obj *obj)
|
||||
{
|
||||
return doname_base(obj, DONAME_WITH_PRICE | DONAME_FORCE_GENDER);
|
||||
}
|
||||
|
||||
/* "some" instead of precise quantity if obj->dknown not set */
|
||||
char *
|
||||
doname_vague_quan(struct obj *obj)
|
||||
@@ -1837,9 +1861,10 @@ corpse_xname(
|
||||
any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
|
||||
/* leave off suffix (do_name() appends "corpse" itself) */
|
||||
omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
|
||||
gndr_prefix = (cxn_flags & CXN_ADDGNDR) != 0,
|
||||
possessive = FALSE,
|
||||
glob = (otmp->otyp != CORPSE && otmp->globby);
|
||||
const char *mnam;
|
||||
const char *mnam, *gndr;
|
||||
|
||||
/* some callers [aobjnam()] rely on prefix area that xname() sets aside */
|
||||
gx.xnamep = nextobuf();
|
||||
@@ -1879,15 +1904,19 @@ corpse_xname(
|
||||
into the code, so the() has been modified to deal with capitalized
|
||||
monster names; we could switch to using it below like an() */
|
||||
|
||||
gndr = (gndr_prefix && otmp->spe & CORPSTAT_MALE) != 0 ? "male "
|
||||
: (gndr_prefix && otmp->spe & CORPSTAT_FEMALE) != 0 ? "female "
|
||||
: "";
|
||||
if (!adjective || !*adjective) {
|
||||
Strcat(nambuf, gndr);
|
||||
/* normal case: newt corpse */
|
||||
Strcat(nambuf, mnam);
|
||||
} else {
|
||||
/* adjective positioning depends upon format of monster name */
|
||||
if (possessive) /* Medusa's cursed partly eaten corpse */
|
||||
Sprintf(eos(nambuf), "%s %s", mnam, adjective);
|
||||
Sprintf(eos(nambuf), "%s %s%s", mnam, gndr, adjective);
|
||||
else /* cursed partly eaten troll corpse */
|
||||
Sprintf(eos(nambuf), "%s %s", adjective, mnam);
|
||||
Sprintf(eos(nambuf), "%s %s%s", adjective, gndr, mnam);
|
||||
/* in case adjective has a trailing space, squeeze it out */
|
||||
mungspaces(nambuf);
|
||||
/* doname() might include a count in the adjective argument;
|
||||
|
||||
+6
-2
@@ -1041,7 +1041,7 @@ query_objlist(const char *qstr, /* query string */
|
||||
unsigned sortflags;
|
||||
glyph_info tmpglyphinfo = nul_glyphinfo;
|
||||
Loot *sortedolist, *srtoli;
|
||||
int clr = NO_COLOR;
|
||||
int clr = NO_COLOR, puzzling_count = 0;
|
||||
|
||||
*pick_list = (menu_item *) 0;
|
||||
if (!olist && !engulfer)
|
||||
@@ -1076,6 +1076,8 @@ query_objlist(const char *qstr, /* query string */
|
||||
return 1;
|
||||
}
|
||||
|
||||
puzzling_count = check_for_puzzling_nonmerge(olist);
|
||||
|
||||
sortflags = (((flags.sortloot == 'f'
|
||||
|| (flags.sortloot == 'l' && !(qflags & USE_INVLET)))
|
||||
? SORTLOOT_LOOT
|
||||
@@ -1134,7 +1136,9 @@ query_objlist(const char *qstr, /* query string */
|
||||
(qflags & USE_INVLET) ? curr->invlet
|
||||
: (first && curr->oclass == COIN_CLASS) ? '$' : 0,
|
||||
def_oc_syms[(int) objects[curr->otyp].oc_class].sym,
|
||||
ATR_NONE, clr, doname_with_price(curr),
|
||||
ATR_NONE, clr,
|
||||
(puzzling_count) ? doname_with_price_and_cgender(curr)
|
||||
: doname_with_price(curr),
|
||||
MENU_ITEMFLAGS_NONE);
|
||||
first = FALSE;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user