📄 be_ai_chat.c
字号:
{
while(*ptr && IsWhiteSpace(*ptr)) ptr++;
if (ptr > oldptr)
{
//if not at the start and not at the end of the string
//write only one space
if (oldptr > string && *ptr) *oldptr++ = ' ';
//remove all other white spaces
if (ptr > oldptr) memmove(oldptr, ptr, strlen(ptr)+1);
} //end if
while(*ptr && !IsWhiteSpace(*ptr)) ptr++;
} //end while
} //end of the function UnifyWhiteSpaces
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int StringContains(char *str1, char *str2, int casesensitive)
{
int len, i, j, index;
if (str1 == NULL || str2 == NULL) return -1;
len = strlen(str1) - strlen(str2);
index = 0;
for (i = 0; i <= len; i++, str1++, index++)
{
for (j = 0; str2[j]; j++)
{
if (casesensitive)
{
if (str1[j] != str2[j]) break;
} //end if
else
{
if (toupper(str1[j]) != toupper(str2[j])) break;
} //end else
} //end for
if (!str2[j]) return index;
} //end for
return -1;
} //end of the function StringContains
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
char *StringContainsWord(char *str1, char *str2, int casesensitive)
{
int len, i, j;
len = strlen(str1) - strlen(str2);
for (i = 0; i <= len; i++, str1++)
{
//if not at the start of the string
if (i)
{
//skip to the start of the next word
while(*str1 && *str1 != ' ' && *str1 != '.' && *str1 != ',' && *str1 != '!') str1++;
if (!*str1) break;
str1++;
} //end for
//compare the word
for (j = 0; str2[j]; j++)
{
if (casesensitive)
{
if (str1[j] != str2[j]) break;
} //end if
else
{
if (toupper(str1[j]) != toupper(str2[j])) break;
} //end else
} //end for
//if there was a word match
if (!str2[j])
{
//if the first string has an end of word
if (!str1[j] || str1[j] == ' ' || str1[j] == '.' || str1[j] == ',' || str1[j] == '!') return str1;
} //end if
} //end for
return NULL;
} //end of the function StringContainsWord
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void StringReplaceWords(char *string, char *synonym, char *replacement)
{
char *str, *str2;
//find the synonym in the string
str = StringContainsWord(string, synonym, qfalse);
//if the synonym occured in the string
while(str)
{
//if the synonym isn't part of the replacement which is already in the string
//usefull for abreviations
str2 = StringContainsWord(string, replacement, qfalse);
while(str2)
{
if (str2 <= str && str < str2 + strlen(replacement)) break;
str2 = StringContainsWord(str2+1, replacement, qfalse);
} //end while
if (!str2)
{
memmove(str + strlen(replacement), str+strlen(synonym), strlen(str+strlen(synonym))+1);
//append the synonum replacement
Com_Memcpy(str, replacement, strlen(replacement));
} //end if
//find the next synonym in the string
str = StringContainsWord(str+strlen(replacement), synonym, qfalse);
} //end if
} //end of the function StringReplaceWords
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotDumpSynonymList(bot_synonymlist_t *synlist)
{
FILE *fp;
bot_synonymlist_t *syn;
bot_synonym_t *synonym;
fp = Log_FilePointer();
if (!fp) return;
for (syn = synlist; syn; syn = syn->next)
{
fprintf(fp, "%ld : [", syn->context);
for (synonym = syn->firstsynonym; synonym; synonym = synonym->next)
{
fprintf(fp, "(\"%s\", %1.2f)", synonym->string, synonym->weight);
if (synonym->next) fprintf(fp, ", ");
} //end for
fprintf(fp, "]\n");
} //end for
} //end of the function BotDumpSynonymList
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bot_synonymlist_t *BotLoadSynonyms(char *filename)
{
int pass, size, contextlevel, numsynonyms;
unsigned long int context, contextstack[32];
char *ptr = NULL;
source_t *source;
token_t token;
bot_synonymlist_t *synlist, *lastsyn, *syn;
bot_synonym_t *synonym, *lastsynonym;
size = 0;
synlist = NULL; //make compiler happy
syn = NULL; //make compiler happy
synonym = NULL; //make compiler happy
//the synonyms are parsed in two phases
for (pass = 0; pass < 2; pass++)
{
//
if (pass && size) ptr = (char *) GetClearedHunkMemory(size);
//
PC_SetBaseFolder(BOTFILESBASEFOLDER);
source = LoadSourceFile(filename);
if (!source)
{
botimport.Print(PRT_ERROR, "counldn't load %s\n", filename);
return NULL;
} //end if
//
context = 0;
contextlevel = 0;
synlist = NULL; //list synonyms
lastsyn = NULL; //last synonym in the list
//
while(PC_ReadToken(source, &token))
{
if (token.type == TT_NUMBER)
{
context |= token.intvalue;
contextstack[contextlevel] = token.intvalue;
contextlevel++;
if (contextlevel >= 32)
{
SourceError(source, "more than 32 context levels");
FreeSource(source);
return NULL;
} //end if
if (!PC_ExpectTokenString(source, "{"))
{
FreeSource(source);
return NULL;
} //end if
} //end if
else if (token.type == TT_PUNCTUATION)
{
if (!strcmp(token.string, "}"))
{
contextlevel--;
if (contextlevel < 0)
{
SourceError(source, "too many }");
FreeSource(source);
return NULL;
} //end if
context &= ~contextstack[contextlevel];
} //end if
else if (!strcmp(token.string, "["))
{
size += sizeof(bot_synonymlist_t);
if (pass)
{
syn = (bot_synonymlist_t *) ptr;
ptr += sizeof(bot_synonymlist_t);
syn->context = context;
syn->firstsynonym = NULL;
syn->next = NULL;
if (lastsyn) lastsyn->next = syn;
else synlist = syn;
lastsyn = syn;
} //end if
numsynonyms = 0;
lastsynonym = NULL;
while(1)
{
if (!PC_ExpectTokenString(source, "(") ||
!PC_ExpectTokenType(source, TT_STRING, 0, &token))
{
FreeSource(source);
return NULL;
} //end if
StripDoubleQuotes(token.string);
if (strlen(token.string) <= 0)
{
SourceError(source, "empty string", token.string);
FreeSource(source);
return NULL;
} //end if
size += sizeof(bot_synonym_t) + strlen(token.string) + 1;
if (pass)
{
synonym = (bot_synonym_t *) ptr;
ptr += sizeof(bot_synonym_t);
synonym->string = ptr;
ptr += strlen(token.string) + 1;
strcpy(synonym->string, token.string);
//
if (lastsynonym) lastsynonym->next = synonym;
else syn->firstsynonym = synonym;
lastsynonym = synonym;
} //end if
numsynonyms++;
if (!PC_ExpectTokenString(source, ",") ||
!PC_ExpectTokenType(source, TT_NUMBER, 0, &token) ||
!PC_ExpectTokenString(source, ")"))
{
FreeSource(source);
return NULL;
} //end if
if (pass)
{
synonym->weight = token.floatvalue;
syn->totalweight += synonym->weight;
} //end if
if (PC_CheckTokenString(source, "]")) break;
if (!PC_ExpectTokenString(source, ","))
{
FreeSource(source);
return NULL;
} //end if
} //end while
if (numsynonyms < 2)
{
SourceError(source, "synonym must have at least two entries\n");
FreeSource(source);
return NULL;
} //end if
} //end else
else
{
SourceError(source, "unexpected %s", token.string);
FreeSource(source);
return NULL;
} //end if
} //end else if
} //end while
//
FreeSource(source);
//
if (contextlevel > 0)
{
SourceError(source, "missing }");
return NULL;
} //end if
} //end for
botimport.Print(PRT_MESSAGE, "loaded %s\n", filename);
//
//BotDumpSynonymList(synlist);
//
return synlist;
} //end of the function BotLoadSynonyms
//===========================================================================
// replace all the synonyms in the string
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotReplaceSynonyms(char *string, unsigned long int context)
{
bot_synonymlist_t *syn;
bot_synonym_t *synonym;
for (syn = synonyms; syn; syn = syn->next)
{
if (!(syn->context & context)) continue;
for (synonym = syn->firstsynonym->next; synonym; synonym = synonym->next)
{
StringReplaceWords(string, synonym->string, syn->firstsynonym->string);
} //end for
} //end for
} //end of the function BotReplaceSynonyms
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotReplaceWeightedSynonyms(char *string, unsigned long int context)
{
bot_synonymlist_t *syn;
bot_synonym_t *synonym, *replacement;
float weight, curweight;
for (syn = synonyms; syn; syn = syn->next)
{
if (!(syn->context & context)) continue;
//choose a weighted random replacement synonym
weight = random() * syn->totalweight;
if (!weight) continue;
curweight = 0;
for (replacement = syn->firstsynonym; replacement; replacement = replacement->next)
{
curweight += replacement->weight;
if (weight < curweight) break;
} //end for
if (!replacement) continue;
//replace all synonyms with the replacement
for (synonym = syn->firstsynonym; synonym; synonym = synonym->next)
{
if (synonym == replacement) continue;
StringReplaceWords(string, synonym->string, replacement->string);
} //end for
} //end for
} //end of the function BotReplaceWeightedSynonyms
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void BotReplaceReplySynonyms(char *string, unsigned long int context)
{
char *str1, *str2, *replacement;
bot_synonymlist_t *syn;
bot_synonym_t *synonym;
for (str1 = string; *str1; )
{
//go to the start of the next word
while(*str1 && *str1 <= ' ') str1++;
if (!*str1) break;
//
for (syn = synonyms; syn; syn = syn->next)
{
if (!(syn->context & context)) continue;
for (synonym = syn->firstsynonym->next; synonym; synonym = synonym->next)
{
str2 = synonym->string;
//if the synonym is not at the front of the string continue
str2 = StringContainsWord(str1, synonym->string, qfalse);
if (!str2 || str2 != str1) continue;
//
replacement = syn->firstsynonym->string;
//if the replacement IS in front of the string continue
str2 = StringContainsWord(str1, replacement, qfalse);
if (str2 && str2 == str1) continue;
//
memmove(str1 + strlen(replacement), str1+strlen(synonym->string),
strlen(str1+strlen(synonym->string)) + 1);
//append the synonum replacement
Com_Memcpy(str1, replacement, strlen(replacement));
//
break;
} //end for
//if a synonym has been replaced
if (synonym) break;
} //end for
//skip over this word
while(*str1 && *str1 > ' ') str1++;
if (!*str1) break;
} //end while
} //end of the function BotReplaceReplySynonyms
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int BotLoadChatMessage(source_t *source, char *chatmessagestring)
{
char *ptr;
token_t token;
ptr = chatmessagestring;
*ptr = 0;
//
while(1)
{
if (!PC_ExpectAnyToken(source, &token)) return qfalse;
//fixed string
if (token.type == TT_STRING)
{
StripDoubleQuotes(token.string);
if (strlen(ptr) + strlen(token.string) + 1 > MAX_MESSAGE_SIZE)
{
SourceError(source, "chat message too long\n");
return qfalse;
} //end if
strcat(ptr, token.string);
} //end else if
//variable string
else if (token.type == TT_NUMBER && (token.subtype & TT_INTEGER))
{
if (strlen(ptr) + 7 > MAX_MESSAGE_SIZE)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -