From: Pasi Kallinen Date: Fri, 27 Nov 2020 16:10:47 +0000 (+0200) Subject: Split some parts of getobj into functions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2a7cb3c4b615b06b68fca85c78359e1a95288814;p=nethack Split some parts of getobj into functions --- diff --git a/src/invent.c b/src/invent.c index 16d6ff01f..67f1bfa43 100644 --- a/src/invent.c +++ b/src/invent.c @@ -1464,6 +1464,157 @@ const char *action; return !strcmp(action, "wear") || !strcmp(action, "put on"); } +/* helper for getobj(), exclude obj if it cannot be used to do word */ +static boolean +getobj_obj_exclude(word, otmp) +const char *word; +struct obj *otmp; +{ + return ((taking_off(word) /* exclude if not worn */ + && !(otmp->owornmask & (W_ARMOR | W_ACCESSORY))) + || (putting_on(word) /* exclude if already worn */ + && (otmp->owornmask & (W_ARMOR | W_ACCESSORY))) +#if 0 /* 3.4.1 -- include currently wielded weapon among 'wield' choices */ + || (!strcmp(word, "wield") + && (otmp->owornmask & W_WEP)) +#endif + || (!strcmp(word, "ready") /* exclude when wielded... */ + && ((otmp == uwep || (otmp == uswapwep && u.twoweap)) + && otmp->quan == 1L)) /* ...unless more than one */ + || ((!strcmp(word, "dip") || !strcmp(word, "grease")) + && inaccessible_equipment(otmp, (const char *) 0, FALSE))); +} + +/* helper for getobj(), exclude obj if it cannot be used to do word */ +static boolean +getobj_obj_exclude_too(word, otmp) +const char *word; +struct obj *otmp; +{ + short otyp = otmp->otyp; + + return ((putting_on(word) + && ((otmp->oclass == FOOD_CLASS && otyp != MEAT_RING) + || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD + && otyp != TOWEL && otyp != LENSES))) + || (!strcmp(word, "wield") + && (otmp->oclass == TOOL_CLASS && !is_weptool(otmp))) + || (!strcmp(word, "eat") && !is_edible(otmp)) + || (!strcmp(word, "sacrifice") + && (otyp != CORPSE && otyp != AMULET_OF_YENDOR + && otyp != FAKE_AMULET_OF_YENDOR)) + || (!strcmp(word, "write with") + && (otmp->oclass == TOOL_CLASS + && otyp != MAGIC_MARKER && otyp != TOWEL)) + || (!strcmp(word, "tin") + && (otyp != CORPSE || !tinnable(otmp))) + || (!strcmp(word, "rub") + && ((otmp->oclass == TOOL_CLASS && otyp != OIL_LAMP + && otyp != MAGIC_LAMP && otyp != BRASS_LANTERN) + || (otmp->oclass == GEM_CLASS && !is_graystone(otmp)) + || (otmp->oclass == FOOD_CLASS + && otmp->otyp != LUMP_OF_ROYAL_JELLY))) + || (!strcmp(word, "use or apply") + /* Picks, axes, pole-weapons, bullwhips */ + && ((otmp->oclass == WEAPON_CLASS + && !is_pick(otmp) && !is_axe(otmp) + && !is_pole(otmp) && otyp != BULLWHIP) + || (otmp->oclass == POTION_CLASS + /* only applicable potion is oil, and it will only + be offered as a choice when already discovered */ + && (otyp != POT_OIL || !otmp->dknown + || !objects[POT_OIL].oc_name_known)) + || (otmp->oclass == FOOD_CLASS + && otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF + && otyp != LUMP_OF_ROYAL_JELLY) + || (otmp->oclass == GEM_CLASS && !is_graystone(otmp)))) + || (!strcmp(word, "rub the royal jelly on") && otmp->otyp != EGG) + || (!strcmp(word, "invoke") + && !otmp->oartifact + && !objects[otyp].oc_unique + && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) + && otyp != CRYSTAL_BALL /* synonym for apply */ + /* note: presenting the possibility of invoking non-artifact + mirrors and/or lamps is simply a cruel deception... */ + && otyp != MIRROR + && otyp != MAGIC_LAMP + && (otyp != OIL_LAMP /* don't list known oil lamp */ + || (otmp->dknown && objects[OIL_LAMP].oc_name_known))) + || (!strcmp(word, "untrap with") + && ((otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE) + || (otmp->oclass == POTION_CLASS + /* only applicable potion is oil, and it will only + be offered as a choice when already discovered */ + && (otyp != POT_OIL || !otmp->dknown + || !objects[POT_OIL].oc_name_known)))) + || (!strcmp(word, "tip") && !Is_container(otmp) + /* include horn of plenty if sufficiently discovered */ + && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown + || !objects[HORN_OF_PLENTY].oc_name_known)) + || (!strcmp(word, "charge") && !is_chargeable(otmp)) + || (!strcmp(word, "open") && otyp != TIN) + || (!strcmp(word, "call") && !objtyp_is_callable(otyp))); +} + +/* helper for getobj(), obj is acceptable but not listed */ +static boolean +getobj_obj_acceptable_unlisted(word, otmp, let) +const char *word; +struct obj *otmp; +char let; +{ + long dummymask; + short otyp = otmp->otyp; + + return (/* ugly check for unworn armor that can't be worn */ + (putting_on(word) && let == ARMOR_CLASS + && !canwearobj(otmp, &dummymask, FALSE)) + /* or armor with 'P' or 'R' or accessory with 'W' or 'T' */ + || ((putting_on(word) || taking_off(word)) + && ((let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS))) + /* or unsuitable items rubbed on known touchstone */ + || (!strncmp(word, "rub on the stone", 16) + && let == GEM_CLASS && otmp->dknown + && objects[otyp].oc_name_known) + /* suppress corpses on astral, amulets elsewhere */ + || (!strcmp(word, "sacrifice") + /* (!astral && amulet) || (astral && !amulet) */ + && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS))) + /* suppress container being stashed into */ + || (!strcmp(word, "stash") && !ck_bag(otmp)) + /* worn armor (shirt, suit) covered by worn armor (suit, cloak) + or accessory (ring) covered by cursed worn armor (gloves) */ + || (taking_off(word) + && inaccessible_equipment(otmp, (const char *) 0, + (boolean) (otmp->oclass == RING_CLASS))) + || (!strcmp(word, "write on") + && (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER) + || !otmp->dknown || !objects[otyp].oc_name_known))); +} + +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. @@ -1492,7 +1643,6 @@ register const char *let, *word; boolean cntgiven = FALSE; boolean msggiven = FALSE; boolean oneloop = FALSE; - long dummymask; Loot *sortedinvent, *srtinv; if (*let == ALLOW_COUNT) @@ -1550,134 +1700,27 @@ register const char *let, *word; 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))) - || (putting_on(word) /* exclude if already worn */ - && (otmp->owornmask & (W_ARMOR | W_ACCESSORY))) -#if 0 /* 3.4.1 -- include currently wielded weapon among 'wield' choices */ - || (!strcmp(word, "wield") - && (otmp->owornmask & W_WEP)) -#endif - || (!strcmp(word, "ready") /* exclude when wielded... */ - && ((otmp == uwep || (otmp == uswapwep && u.twoweap)) - && otmp->quan == 1L)) /* ...unless more than one */ - || ((!strcmp(word, "dip") || !strcmp(word, "grease")) - && inaccessible_equipment(otmp, (const char *) 0, FALSE)) - ) { + /* remove inappropriate things */ + if (getobj_obj_exclude(word, otmp)) { foo--; foox++; } - /* Second ugly check; unlike the first it won't trigger an - * "else" in "you don't have anything else to ___". + /* remove inappropriate thing, but unlike the first it won't + * trigger an "else" in "you don't have anything else to ___". */ - else if ( - (putting_on(word) - && ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) - || (otmp->oclass == TOOL_CLASS && otyp != BLINDFOLD - && otyp != TOWEL && otyp != LENSES))) - || (!strcmp(word, "wield") - && (otmp->oclass == TOOL_CLASS && !is_weptool(otmp))) - || (!strcmp(word, "eat") && !is_edible(otmp)) - || (!strcmp(word, "sacrifice") - && (otyp != CORPSE && otyp != AMULET_OF_YENDOR - && otyp != FAKE_AMULET_OF_YENDOR)) - || (!strcmp(word, "write with") - && (otmp->oclass == TOOL_CLASS - && otyp != MAGIC_MARKER && otyp != TOWEL)) - || (!strcmp(word, "tin") - && (otyp != CORPSE || !tinnable(otmp))) - || (!strcmp(word, "rub") - && ((otmp->oclass == TOOL_CLASS && otyp != OIL_LAMP - && otyp != MAGIC_LAMP && otyp != BRASS_LANTERN) - || (otmp->oclass == GEM_CLASS && !is_graystone(otmp)) - || (otmp->oclass == FOOD_CLASS - && otmp->otyp != LUMP_OF_ROYAL_JELLY))) - || (!strcmp(word, "use or apply") - /* Picks, axes, pole-weapons, bullwhips */ - && ((otmp->oclass == WEAPON_CLASS - && !is_pick(otmp) && !is_axe(otmp) - && !is_pole(otmp) && otyp != BULLWHIP) - || (otmp->oclass == POTION_CLASS - /* only applicable potion is oil, and it will only - be offered as a choice when already discovered */ - && (otyp != POT_OIL || !otmp->dknown - || !objects[POT_OIL].oc_name_known)) - || (otmp->oclass == FOOD_CLASS - && otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF - && otyp != LUMP_OF_ROYAL_JELLY) - || (otmp->oclass == GEM_CLASS && !is_graystone(otmp)))) - || (!strcmp(word, "rub the royal jelly on") && otmp->otyp != EGG) - || (!strcmp(word, "invoke") - && !otmp->oartifact - && !objects[otyp].oc_unique - && (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) - && otyp != CRYSTAL_BALL /* synonym for apply */ - /* note: presenting the possibility of invoking non-artifact - mirrors and/or lamps is simply a cruel deception... */ - && otyp != MIRROR - && otyp != MAGIC_LAMP - && (otyp != OIL_LAMP /* don't list known oil lamp */ - || (otmp->dknown && objects[OIL_LAMP].oc_name_known))) - || (!strcmp(word, "untrap with") - && ((otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE) - || (otmp->oclass == POTION_CLASS - /* only applicable potion is oil, and it will only - be offered as a choice when already discovered */ - && (otyp != POT_OIL || !otmp->dknown - || !objects[POT_OIL].oc_name_known)))) - || (!strcmp(word, "tip") && !Is_container(otmp) - /* include horn of plenty if sufficiently discovered */ - && (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown - || !objects[HORN_OF_PLENTY].oc_name_known)) - || (!strcmp(word, "charge") && !is_chargeable(otmp)) - || (!strcmp(word, "open") && otyp != TIN) - || (!strcmp(word, "call") && !objtyp_is_callable(otyp)) - || (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS - && !usegold) - ) { + else if (getobj_obj_exclude_too(word, otmp) + || (!strcmp(word, "adjust") && otmp->oclass == COIN_CLASS + && !usegold)) { foo--; } - /* Third ugly check: acceptable but not listed as likely - * candidates in the prompt or in the inventory subset if - * player responds with '?'. - */ - else if ( - /* ugly check for unworn armor that can't be worn */ - (putting_on(word) && *let == ARMOR_CLASS - && !canwearobj(otmp, &dummymask, FALSE)) - /* or armor with 'P' or 'R' or accessory with 'W' or 'T' */ - || ((putting_on(word) || taking_off(word)) - && ((*let == ARMOR_CLASS) ^ (otmp->oclass == ARMOR_CLASS))) - /* or unsuitable items rubbed on known touchstone */ - || (!strncmp(word, "rub on the stone", 16) - && *let == GEM_CLASS && otmp->dknown - && objects[otyp].oc_name_known) - /* suppress corpses on astral, amulets elsewhere */ - || (!strcmp(word, "sacrifice") - /* (!astral && amulet) || (astral && !amulet) */ - && (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS))) - /* suppress container being stashed into */ - || (!strcmp(word, "stash") && !ck_bag(otmp)) - /* worn armor (shirt, suit) covered by worn armor (suit, cloak) - or accessory (ring) covered by cursed worn armor (gloves) */ - || (taking_off(word) - && inaccessible_equipment(otmp, (const char *) 0, - (boolean) (otmp->oclass == RING_CLASS))) - || (!strcmp(word, "write on") - && (!(otyp == SCR_BLANK_PAPER || otyp == SPE_BLANK_PAPER) - || !otmp->dknown || !objects[otyp].oc_name_known)) - ) { - /* acceptable but not listed as likely candidate */ + 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--; allowall = TRUE; *ap++ = otmp->invlet; } -/* *INDENT-ON* */ -/* clang-format on */ } else { /* "ugly check" for reading fortune cookies, part 2 */ if ((!strcmp(word, "read") && is_readable(otmp))) @@ -1743,23 +1786,8 @@ register const char *let, *word; return (struct obj *) 0; } if (ilet == HANDS_SYM) { /* '-' */ - if (!allownone) { - 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 : ""); - } + if (!allownone) + mime_action(word); return (allownone ? (struct obj *) &cg.zeroobj : (struct obj *) 0); } redo_menu: