From 70df5242a3d75817a157b13cb20108c225f2a64a Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 23 Feb 2019 21:25:53 -0800 Subject: [PATCH] Extend map name text matching code into a function --- src/d_netcmd.c | 85 +---------------------- src/g_game.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++ src/g_game.h | 21 ++++++ 3 files changed, 206 insertions(+), 84 deletions(-) diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 55833d0da..246b509c2 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -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); } } diff --git a/src/g_game.c b/src/g_game.c index e2f43e4f2..bc67ed792 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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 // diff --git a/src/g_game.h b/src/g_game.h index 198cbc396..3aaaf95d5 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -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);