Extend map name text matching code into a function

This commit is contained in:
James R 2019-02-23 21:25:53 -08:00
parent bb65e8d72f
commit 70df5242a3
3 changed files with 206 additions and 84 deletions

View File

@ -1719,25 +1719,6 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
}
}
/*
Return the number of times a series of keywords, delimited by spaces, matched.
*/
static int measurekeywords(const char *s, const char *q)
{
int r = 0;
char *qp;
for (qp = strtok(va("%s", q), " ");
qp;
qp = strtok(0, " "))
{
if (strcasestr(s, qp))
{
r++;
}
}
return r;
}
/*
Easy macro; declare parm_*id* and define acceptableargc; put in the parameter
to match as a string as *name*. Set *argn* to the number of extra arguments
@ -1768,16 +1749,10 @@ static void Command_Map_f(void)
boolean usemapcode = false;
INT32 newmapnum;
INT32 apromapnum = 0;
const char *mapname;
size_t mapnamelen;
char *realmapname = NULL;
char *apromapname = NULL;
/* Keyword matching */
UINT8 *freq;
UINT8 freqc;
INT32 newgametype = gametype;
@ -1877,65 +1852,7 @@ static void Command_Map_f(void)
}
else
{
freq = ZZ_Calloc(NUMMAPS * sizeof (UINT8));
for (i = 0, newmapnum = 1; i < NUMMAPS; ++i, ++newmapnum)
if (mapheaderinfo[i])
{
if (!( realmapname = G_BuildMapTitle(newmapnum) ))
continue;
/* Now that we found a perfect match no need to fucking guess. */
if (strnicmp(realmapname, mapname, mapnamelen) == 0)
{
Z_Free(apromapname);
break;
}
if (apromapnum == 0)
{
/* LEVEL 1--match keywords verbatim */
if (strcasestr(realmapname, mapname))
{
apromapnum = newmapnum;
apromapname = realmapname;
realmapname = 0;
}
else/* ...match individual keywords */
{
freq[i] += measurekeywords(realmapname, mapname);
freq[i] += measurekeywords(mapheaderinfo[i]->keyword,
mapname);
}
}
Z_Free(realmapname);/* leftover old name */
}
if (newmapnum == NUMMAPS+1)/* no perfect match--try a substring */
{
newmapnum = apromapnum;
realmapname = apromapname;
}
if (newmapnum == 0)/* calculate most queries met! */
{
freqc = 0;
for (i = 0; i < NUMMAPS; ++i)
{
if (freq[i] > freqc)
{
freqc = freq[i];
newmapnum = i + 1;
}
}
if (newmapnum)
{
realmapname = G_BuildMapTitle(newmapnum);
}
}
Z_Free(freq);
newmapnum = G_FindMap(mapname, &realmapname, NULL, NULL);
}
}

View File

@ -4040,6 +4040,190 @@ char *G_BuildMapTitle(INT32 mapnum)
return title;
}
static void measurekeywords(mapsearchfreq_t *fr,
struct searchdim **dimp, UINT8 *cuntp,
const char *s, const char *q, boolean wanttable)
{
char *qp;
char *sp;
if (wanttable)
(*dimp) = Z_Realloc((*dimp), 255 * sizeof (struct searchdim),
PU_STATIC, NULL);
for (qp = strtok(va("%s", q), " ");
qp && fr->total < 255;
qp = strtok(0, " "))
{
if (( sp = strcasestr(s, qp) ))
{
if (wanttable)
{
(*dimp)[(*cuntp)].pos = sp - s;
(*dimp)[(*cuntp)].siz = strlen(qp);
}
(*cuntp)++;
fr->total++;
}
}
if (wanttable)
(*dimp) = Z_Realloc((*dimp), (*cuntp) * sizeof (struct searchdim),
PU_STATIC, NULL);
}
void writesimplefreq(mapsearchfreq_t *fr, INT32 *frc,
INT32 mapnum, UINT8 pos, UINT8 siz)
{
fr[(*frc)].mapnum = mapnum;
fr[(*frc)].matchd = ZZ_Alloc(sizeof (struct searchdim));
fr[(*frc)].matchd[0].pos = pos;
fr[(*frc)].matchd[0].siz = siz;
fr[(*frc)].matchc = 1;
fr[(*frc)].total = 1;
(*frc)++;
}
INT32 G_FindMap(const char *mapname, char **foundmapnamep,
mapsearchfreq_t **freqp, INT32 *freqcp)
{
INT32 newmapnum = 0;
INT32 mapnum;
INT32 apromapnum = 0;
size_t mapnamelen;
char *realmapname = NULL;
char *newmapname = NULL;
char *apromapname = NULL;
char *aprop = NULL;
mapsearchfreq_t *freq;
boolean wanttable;
INT32 freqc;
UINT8 frequ;
INT32 i;
mapnamelen = strlen(mapname);
/* Count available maps; how ugly. */
for (i = 0, freqc = 0; i < NUMMAPS; ++i)
{
if (mapheaderinfo[i])
freqc++;
}
freq = ZZ_Calloc(freqc * sizeof (mapsearchfreq_t));
wanttable = !!( freqp );
freqc = 0;
for (i = 0, mapnum = 1; i < NUMMAPS; ++i, ++mapnum)
if (mapheaderinfo[i])
{
if (!( realmapname = G_BuildMapTitle(mapnum) ))
continue;
aprop = realmapname;
/* Now that we found a perfect match no need to fucking guess. */
if (strnicmp(realmapname, mapname, mapnamelen) == 0)
{
if (wanttable)
{
writesimplefreq(freq, &freqc, mapnum, 0, mapnamelen);
}
if (newmapnum == 0)
{
newmapnum = mapnum;
newmapname = realmapname;
realmapname = 0;
Z_Free(apromapname);
if (!wanttable)
break;
}
}
else
if (apromapnum == 0 || wanttable)
{
/* LEVEL 1--match keywords verbatim */
if (( aprop = strcasestr(realmapname, mapname) ))
{
if (wanttable)
{
writesimplefreq(freq, &freqc,
mapnum, aprop - realmapname, mapnamelen);
}
if (apromapnum == 0)
{
apromapnum = mapnum;
apromapname = realmapname;
realmapname = 0;
}
}
else/* ...match individual keywords */
{
freq[freqc].mapnum = mapnum;
measurekeywords(&freq[freqc],
&freq[freqc].matchd, &freq[freqc].matchc,
realmapname, mapname, wanttable);
measurekeywords(&freq[freqc],
&freq[freqc].keywhd, &freq[freqc].keywhc,
mapheaderinfo[i]->keyword, mapname, wanttable);
if (freq[freqc].total)
freqc++;
}
}
Z_Free(realmapname);/* leftover old name */
}
if (newmapnum == 0)/* no perfect match--try a substring */
{
newmapnum = apromapnum;
newmapname = apromapname;
}
if (newmapnum == 0)/* calculate most queries met! */
{
frequ = 0;
for (i = 0; i < freqc; ++i)
{
if (freq[i].total > frequ)
{
frequ = freq[i].total;
newmapnum = freq[i].mapnum;
}
}
if (newmapnum)
{
newmapname = G_BuildMapTitle(newmapnum);
}
}
if (freqp)
(*freqp) = freq;
else
Z_Free(freq);
if (freqcp)
(*freqcp) = freqc;
if (foundmapnamep)
(*foundmapnamep) = newmapname;
else
Z_Free(newmapname);
return newmapnum;
}
void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc)
{
INT32 i;
for (i = 0; i < freqc; ++i)
{
Z_Free(freq[i].matchd);
}
Z_Free(freq);
}
//
// DEMO RECORDING
//

View File

@ -107,6 +107,27 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer,
boolean skipprecutscene, boolean FLS);
char *G_BuildMapTitle(INT32 mapnum);
struct searchdim
{
UINT8 pos;
UINT8 siz;
};
typedef struct
{
INT16 mapnum;
UINT8 matchc;
struct searchdim *matchd;/* offset that a pattern was matched */
UINT8 keywhc;
struct searchdim *keywhd;/* ...in KEYWORD */
UINT8 total;/* total hits */
}
mapsearchfreq_t;
INT32 G_FindMap(const char *query, char **foundmapnamep,
mapsearchfreq_t **freqp, INT32 *freqc);
void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc);
// XMOD spawning
mapthing_t *G_FindCTFStart(INT32 playernum);
mapthing_t *G_FindMatchStart(INT32 playernum);