last? singular/plural update (trunk only)

Move some common code from makeplural & makeingular into a separate
routine.  Also, add ``candelabrum <-> candelabra''.  Wizard mode wishing
for "candelabra" now works; "Candelabra of Invocation" does not--not due
to case but because the " of " isn't preceded by 's' in the plural form.
This commit is contained in:
nethack.rankin
2007-05-08 02:01:08 +00:00
parent cb5504b38e
commit 6df91448c1

View File

@@ -15,6 +15,8 @@ STATIC_DCL char *NDECL(nextobuf);
STATIC_DCL void FDECL(releaseobuf, (char *));
STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
STATIC_DCL boolean FDECL(singplur_lookup, (char *,char *,BOOLEAN_P,
const char *const *));
struct Jitem {
int item;
@@ -1642,6 +1644,7 @@ static struct sing_plur one_off[] = {
{ "foot", "feet" },
{ "fungus", "fungi" },
{ "knife", "knives" },
{ "labrum", "labra" }, /* candelabrum */
{ "louse", "lice" },
{ "mouse", "mice" },
{ "mumak", "mumakil" },
@@ -1673,6 +1676,47 @@ static const char *const as_is[] = {
variant instead of attempting to support both. */
};
/* singularize/pluralize decisiions common to both makesingular & makeplural */
STATIC_OVL boolean
singplur_lookup(basestr, endstring, to_plural, alt_as_is)
char *basestr, *endstring; /* base string, pointer to eos(string) */
boolean to_plural; /* true => makeplural, false => makesingular */
const char *const *alt_as_is; /* another set like as_is[] */
{
const struct sing_plur *sp;
const char *same, *other, *const *as;
int al;
for (as = as_is; *as; ++as) {
al = (int)strlen(*as);
if (!BSTRCMPI(basestr, endstring - al, *as))
return TRUE;
}
if (alt_as_is) {
for (as = alt_as_is; *as; ++as) {
al = (int)strlen(*as);
if (!BSTRCMPI(basestr, endstring - al, *as))
return TRUE;
}
}
for (sp = one_off; sp->sing; sp++) {
/* check whether endstring already matches */
same = to_plural ? sp->plur : sp->sing;
al = (int)strlen(same);
if (!BSTRCMPI(basestr, endstring - al, same))
return TRUE; /* use as-is */
/* check whether it matches the inverse; if so, transform it */
other = to_plural ? sp->sing : sp->plur;
al = (int)strlen(other);
if (!BSTRCMPI(basestr, endstring - al, other)) {
Strcasecpy(endstring - al, same);
return TRUE; /* one_off[] transformation */
}
}
return FALSE;
}
/* Plural routine; chiefly used for user-defined fruits. We have to try to
* account for everything reasonable the player has; something unreasonable
* can still break the code. However, it's still a lot more accurate than
@@ -1759,37 +1803,16 @@ const char *oldstr;
"matzot",
0,
};
const struct sing_plur *sp;
const char *const *as;
int al;
for (as = as_is; *as; ++as) {
al = (int)strlen(*as);
if (len >= al && !strcmpi(spot - (al - 1), *as))
/* spot+1: synch up with makesingular's usage */
if (singplur_lookup(str, spot + 1, TRUE, already_plural))
goto bottom;
}
for (as = already_plural; *as; ++as) {
al = (int)strlen(*as);
if (len >= al && !strcmpi(spot - (al - 1), *as))
goto bottom;
}
/* more of same, but not suitable for blanket loop checking */
if ((len == 2 && !strcmpi(str, "ya")) ||
(len >= 2 && !strcmpi(spot-1, "ai")) || /* samurai, Uruk-hai */
(len >= 3 && !strcmpi(spot-2, " ya")))
goto bottom;
for (sp = one_off; sp->plur; sp++) {
al = (int)strlen(sp->plur);
if (len >= al && !strcmpi(spot - (al - 1), sp->plur))
goto bottom; /* already plural */
al = (int)strlen(sp->sing);
if (len >= al && !strcmpi(spot - (al - 1), sp->sing)) {
Strcasecpy(spot - (al - 1), sp->plur);
goto bottom; /* one_off[] plural */
}
}
}
/* man/men ("Wiped out all cavemen.") */
@@ -1883,7 +1906,7 @@ const char *oldstr;
* for which help is sought.
*
* "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
* Its inclusion in special_subj[] makes it get treated as the former.
* Its inclusion in as_is[]/special_subj[] makes it get treated as the former.
*
* A lot of unique monsters have names ending in s; plural, or singular
* from plural, doesn't make much sense for them so we don't bother trying.
@@ -1928,33 +1951,8 @@ const char *oldstr;
p = eos(bp);
/* dispense with some words which don't need singularization */
{
const struct sing_plur *sp;
const char *const *as;
int al;
for (as = as_is; *as; ++as) {
al = (int)strlen(*as);
if (!BSTRCMPI(bp, p - al, *as))
if (singplur_lookup(bp, p, FALSE, special_subjs))
return bp;
}
for (as = special_subjs; *as; ++as) {
al = (int)strlen(*as);
if (!BSTRCMPI(bp, p - al, *as))
return bp;
}
for (sp = one_off; sp->sing; sp++) {
al = (int)strlen(sp->sing);
if (!BSTRCMPI(bp, p - al, sp->sing))
return bp; /* already singular */
al = (int)strlen(sp->plur);
if (!BSTRCMPI(bp, p - al, sp->plur)) {
Strcasecpy(p - al, sp->sing);
return bp; /* one_off[] singular */
}
}
}
/* remove -s or -es (boxes) or -ies (rubies) */
if (p >= bp+1 && lowc(p[-1]) == 's') {