From 15e79e99b9b8790cc723936db5bdca4b1704ac90 Mon Sep 17 00:00:00 2001 From: "nethack.rankin" Date: Thu, 3 May 2007 01:17:46 +0000 Subject: [PATCH] more plural/singular (trunk only) Extend makeplural/makesingular case-insensitivity to vtense() and to wizard mode wishing for dungeon features. And the previous set of fixes missed one: makesingular("zombies") was producing "zomby". Plus a bit of groundwork for a likely second overhaul of makeplural/makesingular. --- include/extern.h | 3 +- src/hacklib.c | 51 +++++++++++++------------- src/objnam.c | 94 +++++++++++++++++++++++------------------------- 3 files changed, 74 insertions(+), 74 deletions(-) diff --git a/include/extern.h b/include/extern.h index 67df9d746..28d4acc97 100644 --- a/include/extern.h +++ b/include/extern.h @@ -812,7 +812,8 @@ E char *FDECL(mungspaces, (char *)); E char *FDECL(eos, (char *)); E char *FDECL(strkitten, (char *,CHAR_P)); E void FDECL(copynchars, (char *,const char *,int)); -E void FDECL(Strcasecpy, (char *,const char *)); +E char FDECL(chrcasecpy, (int,int)); +E char *FDECL(strcasecpy, (char *,const char *)); E char *FDECL(s_suffix, (const char *)); E char *FDECL(xcrypt, (const char *,char *)); E boolean FDECL(onlyspace, (const char *)); diff --git a/src/hacklib.c b/src/hacklib.c index 8c5234152..7a0128fc9 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -20,7 +20,8 @@ NetHack, except that rounddiv may call panic(). char * eos (char *) char * strkitten (char *,char) void copynchars (char *,const char *,int) - void Strcasecpy (char *,const char *) + char chrcasecpy (int,int) + char * strcasecpy (char *,const char *) char * s_suffix (const char *) char * xcrypt (const char *, char *) boolean onlyspace (const char *) @@ -157,19 +158,33 @@ copynchars(dst, src, n) /* truncating string copy */ *dst = '\0'; } -/* this assumes ASCII; someday we'll have to switch over to */ -#define nh_islower(c) ((c) >= 'a' && (c) <= 'z') -#define nh_isupper(c) ((c) >= 'A' && (c) <= 'Z') -#define nh_tolower(c) lowc(c) -#define nh_toupper(c) highc(c) +/* mostly used by strcasecpy */ +char +chrcasecpy(oc, nc) /* convert char nc into oc's case */ + int oc, nc; +{ +#if 0 /* this will be necessary if we switch to */ + oc = (int)(unsigned char)oc; + nc = (int)(unsigned char)nc; +#endif + if ('a' <= oc && oc <= 'z') { + /* old char is lower case; if new char is upper case, downcase it */ + if ('A' <= nc && nc <= 'Z') nc += 'a' - 'A'; /* lowc(nc) */ + } else if ('A' <= oc && oc <= 'Z') { + /* old char is upper case; if new char is lower case, upcase it */ + if ('a' <= nc && nc <= 'z') nc += 'A' - 'a'; /* highc(nc) */ + } + return (char)nc; +} /* for case-insensitive editions of makeplural() and makesingular(); src might be shorter, same length, or longer than dst */ -void -Strcasecpy(dst, src) /* overwrite string, preserving old chars' case */ +char * +strcasecpy(dst, src) /* overwrite string, preserving old chars' case */ char *dst; const char *src; { + char *result = dst; int ic, oc, dst_exhausted = 0; /* while dst has characters, replace each one with corresponding @@ -177,27 +192,15 @@ Strcasecpy(dst, src) /* overwrite string, preserving old chars' case */ once dst runs out, propagate the case of its last character to any remaining src; if dst starts empty, it must be a pointer to the tail of some other string because we examine the char at dst[-1] */ - while ((ic = (int)(unsigned char)*src++) != '\0') { + while ((ic = (int)*src++) != '\0') { if (!dst_exhausted && !*dst) dst_exhausted = 1; - /* fetch old character */ - oc = (int)(unsigned char)*(dst - dst_exhausted); - /* possibly convert new character */ - if (nh_islower(oc)) { /* the usual case... */ - if (nh_isupper(ic)) ic = nh_tolower(ic); - } else if (nh_isupper(oc)) { - if (nh_islower(ic)) ic = nh_toupper(ic); - } - /* store new character */ - *dst++ = (char)ic; + oc = (int)*(dst - dst_exhausted); + *dst++ = chrcasecpy(oc, ic); } *dst = '\0'; + return result; } -#undef nh_islower -#undef nh_isupper -#undef nh_tolower -#undef nh_toupper - char * s_suffix(s) /* return a name converted to possessive */ const char *s; diff --git a/src/objnam.c b/src/objnam.c index 626088559..4237ea169 100644 --- a/src/objnam.c +++ b/src/objnam.c @@ -21,6 +21,10 @@ struct Jitem { const char *name; }; +#define BSTRCMPI(base,ptr,str) ((ptr) < base || strcmpi((ptr),str)) +#define BSTRNCMPI(base,ptr,str,num) ((ptr) < base || strncmpi((ptr),str,num)) +#define Strcasecpy(dst,src) (void)strcasecpy(dst,src) + /* true for gems/rocks that should have " stone" appended to their names */ #define GemStone(typ) (typ == FLINT || \ (objects[typ].oc_material == GEMSTONE && \ @@ -1386,7 +1390,7 @@ vtense(subj, verb) register const char *subj; register const char *verb; { - char *buf = nextobuf(); + char *buf = nextobuf(), *bspot; int len, ltmp; const char *sp, *spot; const char * const *spec; @@ -1406,11 +1410,11 @@ register const char *verb; goto sing; spot = (const char *)0; for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) { - if (!strncmp(sp, " of ", 4) || - !strncmp(sp, " from ", 6) || - !strncmp(sp, " called ", 8) || - !strncmp(sp, " named ", 7) || - !strncmp(sp, " labeled ", 9)) { + if (!strncmpi(sp, " of ", 4) || + !strncmpi(sp, " from ", 6) || + !strncmpi(sp, " called ", 8) || + !strncmpi(sp, " named ", 7) || + !strncmpi(sp, " labeled ", 9)) { if (sp != subj) spot = sp - 1; break; } @@ -1422,12 +1426,12 @@ register const char *verb; * plural: anything that ends in 's', but not '*us' or '*ss'. * Guess at a few other special cases that makeplural creates. */ - if ((*spot == 's' && spot != subj && - (*(spot-1) != 'u' && *(spot-1) != 's')) || - ((spot - subj) >= 4 && !strncmp(spot-3, "eeth", 4)) || - ((spot - subj) >= 3 && !strncmp(spot-3, "feet", 4)) || - ((spot - subj) >= 2 && !strncmp(spot-1, "ia", 2)) || - ((spot - subj) >= 2 && !strncmp(spot-1, "ae", 2))) { + if ((lowc(*spot) == 's' && spot != subj && + !index("us", lowc(*(spot-1)))) || + BSTRNCMPI(subj, spot-3, "eeth", 4) || + BSTRNCMPI(subj, spot-3, "feet", 4) || + BSTRNCMPI(subj, spot-1, "ia", 2) || + BSTRNCMPI(subj, spot-1, "ae", 2)) { /* check for special cases to avoid false matches */ len = (int)(spot - subj) + 1; for (spec = special_subjs; *spec; spec++) { @@ -1450,26 +1454,25 @@ register const char *verb; } sing: - len = strlen(verb); - spot = verb + len - 1; - - if (!strcmp(verb, "are")) - Strcpy(buf, "is"); - else if (!strcmp(verb, "have")) - Strcpy(buf, "has"); - else if (index("zxs", *spot) || - (len >= 2 && *spot=='h' && index("cs", *(spot-1))) || - (len == 2 && *spot == 'o')) { + Strcpy(buf, verb); + len = (int)strlen(buf); + bspot = buf + len - 1; + + if (!strcmpi(buf, "are")) { + Strcasecpy(buf, "is"); + } else if (!strcmpi(buf, "have")) { + Strcasecpy(bspot-1, "s"); + } else if (index("zxs", lowc(*bspot)) || + (len >= 2 && lowc(*bspot) == 'h' && + index("cs", lowc(*(bspot-1)))) || + (len == 2 && lowc(*bspot) == 'o')) { /* Ends in z, x, s, ch, sh; add an "es" */ - Strcpy(buf, verb); - Strcat(buf, "es"); - } else if (*spot == 'y' && (!index(vowels, *(spot-1)))) { + Strcasecpy(bspot+1, "es"); + } else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot-1)))) { /* like "y" case in makeplural */ - Strcpy(buf, verb); - Strcpy(buf + len - 1, "ies"); + Strcasecpy(bspot, "ies"); } else { - Strcpy(buf, verb); - Strcat(buf, "s"); + Strcasecpy(bspot+1, "s"); } return buf; @@ -1895,11 +1898,6 @@ STATIC_OVL NEARDATA const struct o_range o_ranges[] = { { "grey stone", GEM_CLASS, LUCKSTONE, FLINT }, }; -#define BSTRCMP(base,ptr,string) ((ptr) < base || strcmp((ptr),string)) -#define BSTRCMPI(base,ptr,string) ((ptr) < base || strcmpi((ptr),string)) -#define BSTRNCMP(base,ptr,string,num) ((ptr) [wo]man-at-arms; takes "not end in s" exit */ - if (!BSTRNCMPI(bp, p-3, "men", 3)) { - char c = *p; /* Strcasecpy will clobber *p with '\0' */ - Strcasecpy(p-2, "an"); - *p = c; - } + if (!BSTRNCMPI(bp, p-3, "men", 3)) p[-2] = chrcasecpy(p[-2], 'a'); if (BSTRNCMPI(bp, p-1, "s", 1)) return bp; /* wasn't plural */ --p; /* back up to the 's' */ @@ -1959,6 +1953,7 @@ const char *oldstr; if (p >= bp+3 && lowc(p[-3]) == 'i') { /* "ies" */ if (!BSTRCMPI(bp, p-7, "cookies") || !BSTRCMPI(bp, p-4, "pies") || + !BSTRCMPI(bp, p-5, "mbies") || /* zombie */ !BSTRCMPI(bp, p-5, "yries")) /* valkyrie */ goto mins; Strcasecpy(p-3, "y"); /* ies -> y */ @@ -2826,7 +2821,7 @@ srch: /* furniture and terrain */ lev = &levl[x][y]; p = eos(bp); - if(!BSTRCMP(bp, p-8, "fountain")) { + if (!BSTRCMPI(bp, p-8, "fountain")) { lev->typ = FOUNTAIN; level.flags.nfountains++; if(!strncmpi(bp, "magic ", 6)) lev->blessedftn = 1; @@ -2834,14 +2829,14 @@ srch: newsym(x, y); return(&zeroobj); } - if(!BSTRCMP(bp, p-6, "throne")) { + if (!BSTRCMPI(bp, p-6, "throne")) { lev->typ = THRONE; pline("A throne."); newsym(x, y); return(&zeroobj); } # ifdef SINKS - if(!BSTRCMP(bp, p-4, "sink")) { + if (!BSTRCMPI(bp, p-4, "sink")) { lev->typ = SINK; level.flags.nsinks++; pline("A sink."); @@ -2850,8 +2845,8 @@ srch: } # endif /* ("water" matches "potion of water" rather than terrain) */ - if (!BSTRCMP(bp, p-4, "pool") || !BSTRCMP(bp, p-4, "moat")) { - lev->typ = !BSTRCMP(bp, p-4, "pool") ? POOL : MOAT; + if (!BSTRCMPI(bp, p-4, "pool") || !BSTRCMPI(bp, p-4, "moat")) { + lev->typ = !BSTRCMPI(bp, p-4, "pool") ? POOL : MOAT; del_engr_at(x, y); pline("A %s.", (lev->typ == POOL) ? "pool" : "moat"); /* Must manually make kelp! */ @@ -2859,7 +2854,7 @@ srch: newsym(x, y); return &zeroobj; } - if (!BSTRCMP(bp, p-4, "lava")) { /* also matches "molten lava" */ + if (!BSTRCMPI(bp, p-4, "lava")) { /* also matches "molten lava" */ lev->typ = LAVAPOOL; del_engr_at(x, y); pline("A pool of molten lava."); @@ -2868,7 +2863,7 @@ srch: return &zeroobj; } - if(!BSTRCMP(bp, p-5, "altar")) { + if (!BSTRCMPI(bp, p-5, "altar")) { aligntyp al; lev->typ = ALTAR; @@ -2888,7 +2883,8 @@ srch: return(&zeroobj); } - if(!BSTRCMP(bp, p-5, "grave") || !BSTRCMP(bp, p-9, "headstone")) { + if (!BSTRCMPI(bp, p-5, "grave") || + !BSTRCMPI(bp, p-9, "headstone")) { make_grave(x, y, (char *)0); pline("%s.", IS_GRAVE(lev->typ) ? "A grave" : "Can't place a grave here"); @@ -2896,7 +2892,7 @@ srch: return(&zeroobj); } - if(!BSTRCMP(bp, p-4, "tree")) { + if (!BSTRCMPI(bp, p-4, "tree")) { lev->typ = TREE; pline("A tree."); newsym(x, y); @@ -2904,7 +2900,7 @@ srch: return &zeroobj; } - if(!BSTRCMP(bp, p-4, "bars")) { + if (!BSTRCMPI(bp, p-4, "bars")) { lev->typ = IRONBARS; pline("Iron bars."); newsym(x, y); -- 2.40.0