From cefd9a0c0a2f6924f66ee59f74441c29873872e2 Mon Sep 17 00:00:00 2001 From: PatR Date: Mon, 12 Dec 2022 14:53:07 -0800 Subject: [PATCH] 'generic username' checking Don't require the list of generic usernames in sysconf to need to be ordered to guard against false substring matches. If the list was "nethacker nethack" and the tentative character name was "nethack", it wouldn't be recognized as generic. The old code forced the list to be "nethack nethacker" for the matching to work correctly because it only checked the first matching substring. Either order works now. It also failed to recognize a generic name if the player used |nethack -u nethack-samurai-human-male-lawful because it checked for generic names before stripping off the role aspects. Now that will at least recognize the name as generic and prompt with "who are you?", but the role/race/&c info gets discarded. --- include/extern.h | 1 + src/hacklib.c | 25 +++++++++++++++++++++++++ src/role.c | 26 +++++++++++++++++--------- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/include/extern.h b/include/extern.h index 7b10a786b..8a88f5abc 100644 --- a/include/extern.h +++ b/include/extern.h @@ -1021,6 +1021,7 @@ extern char *tabexpand(char *); extern char *visctrl(char); extern char *strsubst(char *, const char *, const char *); extern int strNsubst(char *, const char *, const char *, int); +extern const char *findword(const char *, const char *, int, boolean); extern const char *ordin(int); extern char *sitoa(int); extern int sgn(int); diff --git a/src/hacklib.c b/src/hacklib.c index 38fd5a9c2..48dca9344 100644 --- a/src/hacklib.c +++ b/src/hacklib.c @@ -41,6 +41,7 @@ char * visctrl (char) char * strsubst (char *, const char *, const char *) int strNsubst (char *,const char *,const char *,int) + const char * findword (const char *,const char *,int,boolean) const char * ordin (int) char * sitoa (int) int sgn (int) @@ -615,6 +616,30 @@ strNsubst( return rcount; } +/* search for a word in a space-separated list; returns non-Null if found */ +const char * +findword( + const char *list, /* string of space-separated words */ + const char *word, /* word to try to find */ + int wordlen, /* so that it isn't required to be \0 terminated */ + boolean ignorecase) /* T: case-blind, F: case-sensitive */ +{ + const char *p = list; + + while (p) { + while (*p == ' ') + ++p; + if (!*p) + break; + if ((ignorecase ? !strncmpi(p, word, wordlen) + : !strncmp(p, word, wordlen)) + && (p[wordlen] == '\0' || p[wordlen] == ' ')) + return p; + p = strchr(p + 1, ' '); + } + return (const char *) 0; +} + /* return the ordinal suffix of a number */ const char * ordin(int n) /* note: should be non-negative */ diff --git a/src/role.c b/src/role.c index 6496c3ec8..e1d6a183e 100644 --- a/src/role.c +++ b/src/role.c @@ -819,6 +819,9 @@ str2race(const char *str) /* Does it match the noun? */ if (!strncmpi(str, races[i].noun, len)) return i; + /* check adjective too */ + if (races[i].adj && !strncmpi(str, races[i].adj, len)) + return i; /* Or the filecode? */ if (!strcmpi(str, races[i].filecode)) return i; @@ -1603,20 +1606,25 @@ plnamesuffix(void) /* some generic user names will be ignored in favor of prompting */ if (sysopt.genericusers) { if (*sysopt.genericusers == '*') { - *gp.plname = '\0'; + gp.plname[0] = '\0'; } else { - i = (int) strlen(gp.plname); - if ((sptr = strstri(sysopt.genericusers, gp.plname)) != 0 - && (sptr == sysopt.genericusers || sptr[-1] == ' ') - && (sptr[i] == ' ' || sptr[i] == '\0')) - *gp.plname = '\0'; /* call askname() */ + /* need to ignore appended '-role-race-gender-alignment'; + 'plnamelen' is non-zero when dealing with plname[] value that + contains a username with dash(es) in it and is usually 0 */ + i = ((eptr = strchr(gp.plname + gp.plnamelen, '-')) != 0) + ? (int) (eptr - gp.plname) + : Strlen(gp.plname); + /* look for plname[] in the 'genericusers' space-separated list */ + if (findword(sysopt.genericusers, gp.plname, i, FALSE)) + /* it's generic; remove it so that askname() will be called */ + gp.plname[0] = '\0'; } - if (!*gp.plname) + if (!gp.plname[0]) gp.plnamelen = 0; } do { - if (!*gp.plname) { + if (!gp.plname[0]) { askname(); /* fill gp.plname[] if necessary, or set defer_plname */ gp.plnamelen = 0; /* plname[] might have -role-race-&c attached */ } @@ -1641,7 +1649,7 @@ plnamesuffix(void) else if ((i = str2align(sptr)) != ROLE_NONE) flags.initalign = i; } - } while (!*gp.plname && !iflags.defer_plname); + } while (!gp.plname[0] && !iflags.defer_plname); /* commas in the gp.plname confuse the record file, convert to spaces */ (void) strNsubst(gp.plname, ",", " ", 0);