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:
+48
-50
@@ -15,6 +15,8 @@ STATIC_DCL char *NDECL(nextobuf);
|
|||||||
STATIC_DCL void FDECL(releaseobuf, (char *));
|
STATIC_DCL void FDECL(releaseobuf, (char *));
|
||||||
STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
|
STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
|
||||||
STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
|
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 {
|
struct Jitem {
|
||||||
int item;
|
int item;
|
||||||
@@ -1642,6 +1644,7 @@ static struct sing_plur one_off[] = {
|
|||||||
{ "foot", "feet" },
|
{ "foot", "feet" },
|
||||||
{ "fungus", "fungi" },
|
{ "fungus", "fungi" },
|
||||||
{ "knife", "knives" },
|
{ "knife", "knives" },
|
||||||
|
{ "labrum", "labra" }, /* candelabrum */
|
||||||
{ "louse", "lice" },
|
{ "louse", "lice" },
|
||||||
{ "mouse", "mice" },
|
{ "mouse", "mice" },
|
||||||
{ "mumak", "mumakil" },
|
{ "mumak", "mumakil" },
|
||||||
@@ -1673,6 +1676,47 @@ static const char *const as_is[] = {
|
|||||||
variant instead of attempting to support both. */
|
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
|
/* Plural routine; chiefly used for user-defined fruits. We have to try to
|
||||||
* account for everything reasonable the player has; something unreasonable
|
* account for everything reasonable the player has; something unreasonable
|
||||||
* can still break the code. However, it's still a lot more accurate than
|
* can still break the code. However, it's still a lot more accurate than
|
||||||
@@ -1759,37 +1803,16 @@ const char *oldstr;
|
|||||||
"matzot",
|
"matzot",
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
const struct sing_plur *sp;
|
|
||||||
const char *const *as;
|
|
||||||
int al;
|
|
||||||
|
|
||||||
for (as = as_is; *as; ++as) {
|
/* spot+1: synch up with makesingular's usage */
|
||||||
al = (int)strlen(*as);
|
if (singplur_lookup(str, spot + 1, TRUE, already_plural))
|
||||||
if (len >= al && !strcmpi(spot - (al - 1), *as))
|
|
||||||
goto bottom;
|
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 */
|
/* more of same, but not suitable for blanket loop checking */
|
||||||
if ((len == 2 && !strcmpi(str, "ya")) ||
|
if ((len == 2 && !strcmpi(str, "ya")) ||
|
||||||
(len >= 2 && !strcmpi(spot-1, "ai")) || /* samurai, Uruk-hai */
|
(len >= 2 && !strcmpi(spot-1, "ai")) || /* samurai, Uruk-hai */
|
||||||
(len >= 3 && !strcmpi(spot-2, " ya")))
|
(len >= 3 && !strcmpi(spot-2, " ya")))
|
||||||
goto bottom;
|
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.") */
|
/* man/men ("Wiped out all cavemen.") */
|
||||||
@@ -1883,7 +1906,7 @@ const char *oldstr;
|
|||||||
* for which help is sought.
|
* for which help is sought.
|
||||||
*
|
*
|
||||||
* "Manes" is ambiguous: monster type (keep s), or horse body part (drop s)?
|
* "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
|
* 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.
|
* 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);
|
p = eos(bp);
|
||||||
/* dispense with some words which don't need singularization */
|
/* dispense with some words which don't need singularization */
|
||||||
{
|
if (singplur_lookup(bp, p, FALSE, special_subjs))
|
||||||
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))
|
|
||||||
return bp;
|
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) */
|
/* remove -s or -es (boxes) or -ies (rubies) */
|
||||||
if (p >= bp+1 && lowc(p[-1]) == 's') {
|
if (p >= bp+1 && lowc(p[-1]) == 's') {
|
||||||
|
|||||||
Reference in New Issue
Block a user