Split some parts of getobj into functions
This commit is contained in:
+166
-138
@@ -1464,97 +1464,13 @@ const char *action;
|
|||||||
return !strcmp(action, "wear") || !strcmp(action, "put on");
|
return !strcmp(action, "wear") || !strcmp(action, "put on");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* helper for getobj(), exclude obj if it cannot be used to do word */
|
||||||
* getobj returns:
|
static boolean
|
||||||
* struct obj *xxx: object to do something with.
|
getobj_obj_exclude(word, otmp)
|
||||||
* (struct obj *) 0 error return: no object.
|
const char *word;
|
||||||
* &cg.zeroobj explicitly no object (as in w-).
|
struct obj *otmp;
|
||||||
!!!! test if gold can be used in unusual ways (eaten etc.)
|
|
||||||
!!!! may be able to remove "usegold"
|
|
||||||
*/
|
|
||||||
struct obj *
|
|
||||||
getobj(let, word)
|
|
||||||
register const char *let, *word;
|
|
||||||
{
|
{
|
||||||
register struct obj *otmp;
|
return ((taking_off(word) /* exclude if not worn */
|
||||||
register char ilet = 0;
|
|
||||||
char buf[BUFSZ], qbuf[QBUFSZ];
|
|
||||||
char lets[BUFSZ], altlets[BUFSZ], *ap;
|
|
||||||
register int foo = 0;
|
|
||||||
register char *bp = buf;
|
|
||||||
xchar allowcnt = 0; /* 0, 1 or 2 */
|
|
||||||
boolean usegold = FALSE; /* can't use gold because its illegal */
|
|
||||||
boolean allowall = FALSE;
|
|
||||||
boolean allownone = FALSE;
|
|
||||||
boolean useboulder = FALSE;
|
|
||||||
xchar foox = 0;
|
|
||||||
long cnt;
|
|
||||||
boolean cntgiven = FALSE;
|
|
||||||
boolean msggiven = FALSE;
|
|
||||||
boolean oneloop = FALSE;
|
|
||||||
long dummymask;
|
|
||||||
Loot *sortedinvent, *srtinv;
|
|
||||||
|
|
||||||
if (*let == ALLOW_COUNT)
|
|
||||||
let++, allowcnt = 1;
|
|
||||||
if (*let == COIN_CLASS)
|
|
||||||
let++, usegold = TRUE;
|
|
||||||
|
|
||||||
/* Equivalent of an "ugly check" for gold */
|
|
||||||
if (usegold && !strcmp(word, "eat")
|
|
||||||
&& (!metallivorous(g.youmonst.data)
|
|
||||||
|| g.youmonst.data == &mons[PM_RUST_MONSTER]))
|
|
||||||
usegold = FALSE;
|
|
||||||
|
|
||||||
if (*let == ALL_CLASSES)
|
|
||||||
let++, allowall = TRUE;
|
|
||||||
if (*let == ALLOW_NONE)
|
|
||||||
let++, allownone = TRUE;
|
|
||||||
/* "ugly check" for reading fortune cookies, part 1.
|
|
||||||
* The normal 'ugly check' keeps the object on the inventory list.
|
|
||||||
* We don't want to do that for shirts/cookies, so the check for
|
|
||||||
* them is handled a bit differently (and also requires that we set
|
|
||||||
* allowall in the caller).
|
|
||||||
*/
|
|
||||||
if (allowall && !strcmp(word, "read"))
|
|
||||||
allowall = FALSE;
|
|
||||||
|
|
||||||
/* another ugly check: show boulders (not statues) */
|
|
||||||
if (*let == WEAPON_CLASS && !strcmp(word, "throw")
|
|
||||||
&& throws_rocks(g.youmonst.data))
|
|
||||||
useboulder = TRUE;
|
|
||||||
|
|
||||||
if (allownone)
|
|
||||||
*bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
|
|
||||||
ap = altlets;
|
|
||||||
|
|
||||||
if (!flags.invlet_constant)
|
|
||||||
reassign();
|
|
||||||
|
|
||||||
/* force invent to be in invlet order before collecting candidate
|
|
||||||
inventory letters */
|
|
||||||
sortedinvent = sortloot(&g.invent, SORTLOOT_INVLET, FALSE,
|
|
||||||
(boolean FDECL((*), (OBJ_P))) 0);
|
|
||||||
|
|
||||||
for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
|
|
||||||
if (&bp[foo] == &buf[sizeof buf - 1]
|
|
||||||
|| ap == &altlets[sizeof altlets - 1]) {
|
|
||||||
/* we must have a huge number of NOINVSYM items somehow */
|
|
||||||
impossible("getobj: inventory overflow");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!*let || index(let, otmp->oclass)
|
|
||||||
|| (usegold && otmp->invlet == GOLD_SYM)
|
|
||||||
|| (useboulder && otmp->otyp == BOULDER)) {
|
|
||||||
register int otyp = otmp->otyp;
|
|
||||||
|
|
||||||
bp[foo++] = otmp->invlet;
|
|
||||||
/* clang-format off */
|
|
||||||
/* *INDENT-OFF* */
|
|
||||||
/* ugly check: remove inappropriate things */
|
|
||||||
if (
|
|
||||||
(taking_off(word) /* exclude if not worn */
|
|
||||||
&& !(otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
|
&& !(otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
|
||||||
|| (putting_on(word) /* exclude if already worn */
|
|| (putting_on(word) /* exclude if already worn */
|
||||||
&& (otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
|
&& (otmp->owornmask & (W_ARMOR | W_ACCESSORY)))
|
||||||
@@ -1566,17 +1482,19 @@ register const char *let, *word;
|
|||||||
&& ((otmp == uwep || (otmp == uswapwep && u.twoweap))
|
&& ((otmp == uwep || (otmp == uswapwep && u.twoweap))
|
||||||
&& otmp->quan == 1L)) /* ...unless more than one */
|
&& otmp->quan == 1L)) /* ...unless more than one */
|
||||||
|| ((!strcmp(word, "dip") || !strcmp(word, "grease"))
|
|| ((!strcmp(word, "dip") || !strcmp(word, "grease"))
|
||||||
&& inaccessible_equipment(otmp, (const char *) 0, FALSE))
|
&& inaccessible_equipment(otmp, (const char *) 0, FALSE)));
|
||||||
) {
|
}
|
||||||
foo--;
|
|
||||||
foox++;
|
/* helper for getobj(), exclude obj if it cannot be used to do word */
|
||||||
}
|
static boolean
|
||||||
/* Second ugly check; unlike the first it won't trigger an
|
getobj_obj_exclude_too(word, otmp)
|
||||||
* "else" in "you don't have anything else to ___".
|
const char *word;
|
||||||
*/
|
struct obj *otmp;
|
||||||
else if (
|
{
|
||||||
(putting_on(word)
|
short otyp = otmp->otyp;
|
||||||
&& ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING)
|
|
||||||
|
return ((putting_on(word)
|
||||||
|
&& ((otmp->oclass == FOOD_CLASS && otyp != MEAT_RING)
|
||||||
|| (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD
|
|| (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD
|
||||||
&& otyp != TOWEL && otyp != LENSES)))
|
&& otyp != TOWEL && otyp != LENSES)))
|
||||||
|| (!strcmp(word, "wield")
|
|| (!strcmp(word, "wield")
|
||||||
@@ -1635,26 +1553,28 @@ register const char *let, *word;
|
|||||||
|| !objects[HORN_OF_PLENTY].oc_name_known))
|
|| !objects[HORN_OF_PLENTY].oc_name_known))
|
||||||
|| (!strcmp(word, "charge") && !is_chargeable(otmp))
|
|| (!strcmp(word, "charge") && !is_chargeable(otmp))
|
||||||
|| (!strcmp(word, "open") && otyp != TIN)
|
|| (!strcmp(word, "open") && otyp != TIN)
|
||||||
|| (!strcmp(word, "call") && !objtyp_is_callable(otyp))
|
|| (!strcmp(word, "call") && !objtyp_is_callable(otyp)));
|
||||||
|| (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS
|
}
|
||||||
&& !usegold)
|
|
||||||
) {
|
/* helper for getobj(), obj is acceptable but not listed */
|
||||||
foo--;
|
static boolean
|
||||||
}
|
getobj_obj_acceptable_unlisted(word, otmp, let)
|
||||||
/* Third ugly check: acceptable but not listed as likely
|
const char *word;
|
||||||
* candidates in the prompt or in the inventory subset if
|
struct obj *otmp;
|
||||||
* player responds with '?'.
|
char let;
|
||||||
*/
|
{
|
||||||
else if (
|
long dummymask;
|
||||||
/* ugly check for unworn armor that can't be worn */
|
short otyp = otmp->otyp;
|
||||||
(putting_on(word) && *let == ARMOR_CLASS
|
|
||||||
|
return (/* ugly check for unworn armor that can't be worn */
|
||||||
|
(putting_on(word) && let == ARMOR_CLASS
|
||||||
&& !canwearobj(otmp, &dummymask, FALSE))
|
&& !canwearobj(otmp, &dummymask, FALSE))
|
||||||
/* or armor with 'P' or 'R' or accessory with 'W' or 'T' */
|
/* or armor with 'P' or 'R' or accessory with 'W' or 'T' */
|
||||||
|| ((putting_on(word) || taking_off(word))
|
|| ((putting_on(word) || taking_off(word))
|
||||||
&& ((*let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS)))
|
&& ((let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS)))
|
||||||
/* or unsuitable items rubbed on known touchstone */
|
/* or unsuitable items rubbed on known touchstone */
|
||||||
|| (!strncmp(word, "rub on the stone", 16)
|
|| (!strncmp(word, "rub on the stone", 16)
|
||||||
&& *let == GEM_CLASS && otmp->dknown
|
&& let == GEM_CLASS && otmp->dknown
|
||||||
&& objects[otyp].oc_name_known)
|
&& objects[otyp].oc_name_known)
|
||||||
/* suppress corpses on astral, amulets elsewhere */
|
/* suppress corpses on astral, amulets elsewhere */
|
||||||
|| (!strcmp(word, "sacrifice")
|
|| (!strcmp(word, "sacrifice")
|
||||||
@@ -1669,15 +1589,138 @@ register const char *let, *word;
|
|||||||
(boolean) (otmp->oclass == RING_CLASS)))
|
(boolean) (otmp->oclass == RING_CLASS)))
|
||||||
|| (!strcmp(word, "write on")
|
|| (!strcmp(word, "write on")
|
||||||
&& (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
|
&& (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER)
|
||||||
|| !otmp->dknown || !objects[otyp].oc_name_known))
|
|| !otmp->dknown || !objects[otyp].oc_name_known)));
|
||||||
) {
|
}
|
||||||
/* acceptable but not listed as likely candidate */
|
|
||||||
|
void
|
||||||
|
mime_action(word)
|
||||||
|
const char *word;
|
||||||
|
{
|
||||||
|
char buf[BUFSZ];
|
||||||
|
char *bp = buf;
|
||||||
|
char *suf = (char *) 0;
|
||||||
|
|
||||||
|
strcpy(buf, word);
|
||||||
|
if ((bp = strstr(buf, " on the ")) != 0) {
|
||||||
|
/* rub on the stone[s] */
|
||||||
|
*bp = '\0';
|
||||||
|
suf = (bp + 1);
|
||||||
|
}
|
||||||
|
if ((bp = strstr(buf, " or ")) != 0) {
|
||||||
|
*bp = '\0';
|
||||||
|
bp = (rn2(2) ? buf : (bp + 4));
|
||||||
|
} else
|
||||||
|
bp = buf;
|
||||||
|
You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
|
||||||
|
suf ? suf : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* getobj returns:
|
||||||
|
* struct obj *xxx: object to do something with.
|
||||||
|
* (struct obj *) 0 error return: no object.
|
||||||
|
* &cg.zeroobj explicitly no object (as in w-).
|
||||||
|
!!!! test if gold can be used in unusual ways (eaten etc.)
|
||||||
|
!!!! may be able to remove "usegold"
|
||||||
|
*/
|
||||||
|
struct obj *
|
||||||
|
getobj(let, word)
|
||||||
|
register const char *let, *word;
|
||||||
|
{
|
||||||
|
register struct obj *otmp;
|
||||||
|
register char ilet = 0;
|
||||||
|
char buf[BUFSZ], qbuf[QBUFSZ];
|
||||||
|
char lets[BUFSZ], altlets[BUFSZ], *ap;
|
||||||
|
register int foo = 0;
|
||||||
|
register char *bp = buf;
|
||||||
|
xchar allowcnt = 0; /* 0, 1 or 2 */
|
||||||
|
boolean usegold = FALSE; /* can't use gold because its illegal */
|
||||||
|
boolean allowall = FALSE;
|
||||||
|
boolean allownone = FALSE;
|
||||||
|
boolean useboulder = FALSE;
|
||||||
|
xchar foox = 0;
|
||||||
|
long cnt;
|
||||||
|
boolean cntgiven = FALSE;
|
||||||
|
boolean msggiven = FALSE;
|
||||||
|
boolean oneloop = FALSE;
|
||||||
|
Loot *sortedinvent, *srtinv;
|
||||||
|
|
||||||
|
if (*let == ALLOW_COUNT)
|
||||||
|
let++, allowcnt = 1;
|
||||||
|
if (*let == COIN_CLASS)
|
||||||
|
let++, usegold = TRUE;
|
||||||
|
|
||||||
|
/* Equivalent of an "ugly check" for gold */
|
||||||
|
if (usegold && !strcmp(word, "eat")
|
||||||
|
&& (!metallivorous(g.youmonst.data)
|
||||||
|
|| g.youmonst.data == &mons[PM_RUST_MONSTER]))
|
||||||
|
usegold = FALSE;
|
||||||
|
|
||||||
|
if (*let == ALL_CLASSES)
|
||||||
|
let++, allowall = TRUE;
|
||||||
|
if (*let == ALLOW_NONE)
|
||||||
|
let++, allownone = TRUE;
|
||||||
|
/* "ugly check" for reading fortune cookies, part 1.
|
||||||
|
* The normal 'ugly check' keeps the object on the inventory list.
|
||||||
|
* We don't want to do that for shirts/cookies, so the check for
|
||||||
|
* them is handled a bit differently (and also requires that we set
|
||||||
|
* allowall in the caller).
|
||||||
|
*/
|
||||||
|
if (allowall && !strcmp(word, "read"))
|
||||||
|
allowall = FALSE;
|
||||||
|
|
||||||
|
/* another ugly check: show boulders (not statues) */
|
||||||
|
if (*let == WEAPON_CLASS && !strcmp(word, "throw")
|
||||||
|
&& throws_rocks(g.youmonst.data))
|
||||||
|
useboulder = TRUE;
|
||||||
|
|
||||||
|
if (allownone)
|
||||||
|
*bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
|
||||||
|
ap = altlets;
|
||||||
|
|
||||||
|
if (!flags.invlet_constant)
|
||||||
|
reassign();
|
||||||
|
|
||||||
|
/* force invent to be in invlet order before collecting candidate
|
||||||
|
inventory letters */
|
||||||
|
sortedinvent = sortloot(&g.invent, SORTLOOT_INVLET, FALSE,
|
||||||
|
(boolean FDECL((*), (OBJ_P))) 0);
|
||||||
|
|
||||||
|
for (srtinv = sortedinvent; (otmp = srtinv->obj) != 0; ++srtinv) {
|
||||||
|
if (&bp[foo] == &buf[sizeof buf - 1]
|
||||||
|
|| ap == &altlets[sizeof altlets - 1]) {
|
||||||
|
/* we must have a huge number of NOINVSYM items somehow */
|
||||||
|
impossible("getobj: inventory overflow");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*let || index(let, otmp->oclass)
|
||||||
|
|| (usegold && otmp->invlet == GOLD_SYM)
|
||||||
|
|| (useboulder && otmp->otyp == BOULDER)) {
|
||||||
|
register int otyp = otmp->otyp;
|
||||||
|
|
||||||
|
bp[foo++] = otmp->invlet;
|
||||||
|
/* remove inappropriate things */
|
||||||
|
if (getobj_obj_exclude(word, otmp)) {
|
||||||
|
foo--;
|
||||||
|
foox++;
|
||||||
|
}
|
||||||
|
/* remove inappropriate thing, but unlike the first it won't
|
||||||
|
* trigger an "else" in "you don't have anything else to ___".
|
||||||
|
*/
|
||||||
|
else if (getobj_obj_exclude_too(word, otmp)
|
||||||
|
|| (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS
|
||||||
|
&& !usegold)) {
|
||||||
|
foo--;
|
||||||
|
}
|
||||||
|
else if (getobj_obj_acceptable_unlisted(word, otmp, *let)) {
|
||||||
|
/* acceptable but not listed as likely candidates in the prompt
|
||||||
|
* or in the inventory subset if player responds with '?'.
|
||||||
|
*/
|
||||||
foo--;
|
foo--;
|
||||||
allowall = TRUE;
|
allowall = TRUE;
|
||||||
*ap++ = otmp->invlet;
|
*ap++ = otmp->invlet;
|
||||||
}
|
}
|
||||||
/* *INDENT-ON* */
|
|
||||||
/* clang-format on */
|
|
||||||
} else {
|
} else {
|
||||||
/* "ugly check" for reading fortune cookies, part 2 */
|
/* "ugly check" for reading fortune cookies, part 2 */
|
||||||
if ((!strcmp(word, "read") && is_readable(otmp)))
|
if ((!strcmp(word, "read") && is_readable(otmp)))
|
||||||
@@ -1743,23 +1786,8 @@ register const char *let, *word;
|
|||||||
return (struct obj *) 0;
|
return (struct obj *) 0;
|
||||||
}
|
}
|
||||||
if (ilet == HANDS_SYM) { /* '-' */
|
if (ilet == HANDS_SYM) { /* '-' */
|
||||||
if (!allownone) {
|
if (!allownone)
|
||||||
char *suf = (char *) 0;
|
mime_action(word);
|
||||||
|
|
||||||
strcpy(buf, word);
|
|
||||||
if ((bp = strstr(buf, " on the ")) != 0) {
|
|
||||||
/* rub on the stone[s] */
|
|
||||||
*bp = '\0';
|
|
||||||
suf = (bp + 1);
|
|
||||||
}
|
|
||||||
if ((bp = strstr(buf, " or ")) != 0) {
|
|
||||||
*bp = '\0';
|
|
||||||
bp = (rn2(2) ? buf : (bp + 4));
|
|
||||||
} else
|
|
||||||
bp = buf;
|
|
||||||
You("mime %s something%s%s.", ing_suffix(bp), suf ? " " : "",
|
|
||||||
suf ? suf : "");
|
|
||||||
}
|
|
||||||
return (allownone ? (struct obj *) &cg.zeroobj : (struct obj *) 0);
|
return (allownone ? (struct obj *) &cg.zeroobj : (struct obj *) 0);
|
||||||
}
|
}
|
||||||
redo_menu:
|
redo_menu:
|
||||||
|
|||||||
Reference in New Issue
Block a user