Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

be_ai_chat.c File Reference

#include "../game/q_shared.h"
#include "l_memory.h"
#include "l_libvar.h"
#include "l_script.h"
#include "l_precomp.h"
#include "l_struct.h"
#include "l_utils.h"
#include "l_log.h"
#include "aasfile.h"
#include "../game/botlib.h"
#include "../game/be_aas.h"
#include "be_aas_funcs.h"
#include "be_interface.h"
#include "../game/be_ea.h"
#include "../game/be_ai_chat.h"

Include dependency graph for be_ai_chat.c:

Include dependency graph

Go to the source code of this file.

Data Structures

struct  bot_chat_s
struct  bot_chatmessage_s
struct  bot_chatstate_s
struct  bot_chattype_s
struct  bot_ichatdata_t
struct  bot_matchpiece_s
struct  bot_matchstring_s
struct  bot_matchtemplate_s
struct  bot_randomlist_s
struct  bot_randomstring_s
struct  bot_replychat_s
struct  bot_replychatkey_s
struct  bot_stringlist_s
struct  bot_synonym_s
struct  bot_synonymlist_s

Defines

#define CHATMESSAGE_RECENTTIME   20
#define ESCAPE_CHAR   0x01
#define MT_STRING   2
#define MT_VARIABLE   1
#define RCKFL_AND   1
#define RCKFL_BOTNAMES   32
#define RCKFL_GENDERFEMALE   64
#define RCKFL_GENDERLESS   256
#define RCKFL_GENDERMALE   128
#define RCKFL_NAME   4
#define RCKFL_NOT   2
#define RCKFL_STRING   8
#define RCKFL_VARIABLES   16

Typedefs

typedef bot_chat_s bot_chat_t
typedef bot_chatmessage_s bot_chatmessage_t
typedef bot_chatstate_s bot_chatstate_t
typedef bot_chattype_s bot_chattype_t
typedef bot_matchpiece_s bot_matchpiece_t
typedef bot_matchstring_s bot_matchstring_t
typedef bot_matchtemplate_s bot_matchtemplate_t
typedef bot_randomlist_s bot_randomlist_t
typedef bot_randomstring_s bot_randomstring_t
typedef bot_replychat_s bot_replychat_t
typedef bot_replychatkey_s bot_replychatkey_t
typedef bot_stringlist_s bot_stringlist_t
typedef bot_synonym_s bot_synonym_t
typedef bot_synonymlist_s bot_synonymlist_t

Functions

bot_consolemessage_tAllocConsoleMessage (void)
int BotAllocChatState (void)
int BotChatLength (int chatstate)
bot_chatstate_tBotChatStateFromHandle (int handle)
bot_stringlist_tBotCheckChatMessageIntegrety (char *message, bot_stringlist_t *stringlist)
void BotCheckInitialChatIntegrety (bot_chat_t *chat)
void BotCheckReplyChatIntegrety (bot_replychat_t *replychat)
void BotCheckValidReplyChatKeySet (source_t *source, bot_replychatkey_t *keys)
char * BotChooseInitialChatMessage (bot_chatstate_t *cs, char *type)
void BotConstructChatMessage (bot_chatstate_t *chatstate, char *message, unsigned long mcontext, bot_match_t *match, unsigned long vcontext, int reply)
void BotDumpInitialChat (bot_chat_t *chat)
void BotDumpMatchTemplates (bot_matchtemplate_t *matches)
void BotDumpRandomStringList (bot_randomlist_t *randomlist)
void BotDumpReplyChat (bot_replychat_t *replychat)
void BotDumpSynonymList (bot_synonymlist_t *synlist)
void BotEnterChat (int chatstate, int clientto, int sendto)
int BotExpandChatMessage (char *outmessage, char *message, unsigned long mcontext, bot_match_t *match, unsigned long vcontext, int reply)
int BotFindMatch (char *str, bot_match_t *match, unsigned long int context)
bot_stringlist_tBotFindStringInList (bot_stringlist_t *list, char *string)
void BotFreeChatFile (int chatstate)
void BotFreeChatState (int handle)
void BotFreeMatchPieces (bot_matchpiece_t *matchpieces)
void BotFreeMatchTemplates (bot_matchtemplate_t *mt)
void BotFreeReplyChat (bot_replychat_t *replychat)
void BotGetChatMessage (int chatstate, char *buf, int size)
void BotInitialChat (int chatstate, char *type, int mcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7)
int BotLoadChatFile (int chatstate, char *chatfile, char *chatname)
int BotLoadChatMessage (source_t *source, char *chatmessagestring)
bot_chat_tBotLoadInitialChat (char *chatfile, char *chatname)
bot_matchpiece_tBotLoadMatchPieces (source_t *source, char *endtoken)
bot_matchtemplate_tBotLoadMatchTemplates (char *matchfile)
bot_randomlist_tBotLoadRandomStrings (char *filename)
bot_replychat_tBotLoadReplyChat (char *filename)
bot_synonymlist_tBotLoadSynonyms (char *filename)
void BotMatchVariable (bot_match_t *match, int variable, char *buf, int size)
int BotNextConsoleMessage (int chatstate, bot_consolemessage_t *cm)
int BotNumConsoleMessages (int chatstate)
int BotNumInitialChats (int chatstate, char *type)
void BotPrintReplyChatKeys (bot_replychat_t *replychat)
void BotQueueConsoleMessage (int chatstate, int type, char *message)
void BotRemoveConsoleMessage (int chatstate, int handle)
void BotRemoveTildes (char *message)
void BotReplaceReplySynonyms (char *string, unsigned long int context)
void BotReplaceSynonyms (char *string, unsigned long int context)
void BotReplaceWeightedSynonyms (char *string, unsigned long int context)
int BotReplyChat (int chatstate, char *message, int mcontext, int vcontext, char *var0, char *var1, char *var2, char *var3, char *var4, char *var5, char *var6, char *var7)
void BotResetChatAI (void)
void BotSetChatGender (int chatstate, int gender)
void BotSetChatName (int chatstate, char *name, int client)
int BotSetupChatAI (void)
void BotShutdownChatAI (void)
void FreeConsoleMessage (bot_consolemessage_t *message)
void InitConsoleMessageHeap (void)
int IsWhiteSpace (char c)
char * RandomString (char *name)
int StringContains (char *str1, char *str2, int casesensitive)
char * StringContainsWord (char *str1, char *str2, int casesensitive)
void StringReplaceWords (char *string, char *synonym, char *replacement)
int StringsMatch (bot_matchpiece_t *pieces, bot_match_t *match)
void UnifyWhiteSpaces (char *string)

Variables

bot_chatstate_tbotchatstates [MAX_CLIENTS+1]
bot_consolemessage_tconsolemessageheap = NULL
bot_consolemessage_tfreeconsolemessages = NULL
bot_ichatdata_tichatdata [MAX_CLIENTS]
bot_matchtemplate_tmatchtemplates = NULL
bot_randomlist_trandomstrings = NULL
bot_replychat_treplychats = NULL
bot_synonymlist_tsynonyms = NULL


Define Documentation

#define CHATMESSAGE_RECENTTIME   20
 

Definition at line 71 of file be_ai_chat.c.

#define ESCAPE_CHAR   0x01
 

Definition at line 50 of file be_ai_chat.c.

Referenced by BotLoadChatMessage().

#define MT_STRING   2
 

Definition at line 59 of file be_ai_chat.c.

#define MT_VARIABLE   1
 

Definition at line 58 of file be_ai_chat.c.

#define RCKFL_AND   1
 

Definition at line 61 of file be_ai_chat.c.

Referenced by BotCheckValidReplyChatKeySet().

#define RCKFL_BOTNAMES   32
 

Definition at line 66 of file be_ai_chat.c.

#define RCKFL_GENDERFEMALE   64
 

Definition at line 67 of file be_ai_chat.c.

#define RCKFL_GENDERLESS   256
 

Definition at line 69 of file be_ai_chat.c.

#define RCKFL_GENDERMALE   128
 

Definition at line 68 of file be_ai_chat.c.

#define RCKFL_NAME   4
 

Definition at line 63 of file be_ai_chat.c.

#define RCKFL_NOT   2
 

Definition at line 62 of file be_ai_chat.c.

#define RCKFL_STRING   8
 

Definition at line 64 of file be_ai_chat.c.

#define RCKFL_VARIABLES   16
 

Definition at line 65 of file be_ai_chat.c.


Typedef Documentation

typedef struct bot_chat_s bot_chat_t
 

Referenced by BotCheckInitialChatIntegrety(), BotChooseInitialChatMessage(), BotDumpInitialChat(), and BotLoadInitialChat().

typedef struct bot_chatmessage_s bot_chatmessage_t
 

Referenced by BotCheckInitialChatIntegrety(), BotCheckReplyChatIntegrety(), BotChooseInitialChatMessage(), BotDumpInitialChat(), BotDumpReplyChat(), BotFreeReplyChat(), BotLoadInitialChat(), BotLoadReplyChat(), BotReplyChat(), and BotResetChatAI().

typedef struct bot_chatstate_s bot_chatstate_t
 

Referenced by BotAllocChatState(), BotChatLength(), BotChatStateFromHandle(), BotChooseInitialChatMessage(), BotConstructChatMessage(), BotEnterChat(), BotFreeChatFile(), BotFreeChatState(), BotGetChatMessage(), BotInitialChat(), BotLoadChatFile(), BotNextConsoleMessage(), BotNumConsoleMessages(), BotNumInitialChats(), BotQueueConsoleMessage(), BotRemoveConsoleMessage(), BotReplyChat(), BotSetChatGender(), and BotSetChatName().

typedef struct bot_chattype_s bot_chattype_t
 

Referenced by BotCheckInitialChatIntegrety(), BotChooseInitialChatMessage(), BotDumpInitialChat(), BotLoadInitialChat(), and BotNumInitialChats().

typedef struct bot_matchpiece_s bot_matchpiece_t
 

Referenced by BotCheckValidReplyChatKeySet(), BotDumpMatchTemplates(), BotDumpReplyChat(), BotFreeMatchPieces(), BotLoadMatchPieces(), BotPrintReplyChatKeys(), and StringsMatch().

typedef struct bot_matchstring_s bot_matchstring_t
 

Referenced by BotCheckValidReplyChatKeySet(), BotDumpMatchTemplates(), BotFreeMatchPieces(), BotLoadMatchPieces(), and StringsMatch().

typedef struct bot_matchtemplate_s bot_matchtemplate_t
 

Referenced by BotDumpMatchTemplates(), BotFindMatch(), BotFreeMatchTemplates(), and BotLoadMatchTemplates().

typedef struct bot_randomlist_s bot_randomlist_t
 

Referenced by BotDumpRandomStringList(), BotLoadRandomStrings(), and RandomString().

typedef struct bot_randomstring_s bot_randomstring_t
 

Referenced by BotDumpRandomStringList(), BotLoadRandomStrings(), and RandomString().

typedef struct bot_replychat_s bot_replychat_t
 

Referenced by BotCheckReplyChatIntegrety(), BotDumpReplyChat(), BotFreeReplyChat(), BotLoadReplyChat(), BotPrintReplyChatKeys(), BotReplyChat(), and BotResetChatAI().

typedef struct bot_replychatkey_s bot_replychatkey_t
 

Referenced by BotCheckValidReplyChatKeySet(), BotDumpReplyChat(), BotFreeReplyChat(), BotLoadReplyChat(), BotPrintReplyChatKeys(), and BotReplyChat().

typedef struct bot_stringlist_s bot_stringlist_t
 

Referenced by BotCheckChatMessageIntegrety(), BotCheckInitialChatIntegrety(), BotCheckReplyChatIntegrety(), and BotFindStringInList().

typedef struct bot_synonym_s bot_synonym_t
 

Referenced by BotDumpSynonymList(), BotLoadSynonyms(), BotReplaceReplySynonyms(), BotReplaceSynonyms(), and BotReplaceWeightedSynonyms().

typedef struct bot_synonymlist_s bot_synonymlist_t
 

Referenced by BotDumpSynonymList(), BotLoadSynonyms(), BotReplaceReplySynonyms(), BotReplaceSynonyms(), and BotReplaceWeightedSynonyms().


Function Documentation

bot_consolemessage_t* AllocConsoleMessage void   ) 
 

Definition at line 268 of file be_ai_chat.c.

References bot_consolemessage_t, freeconsolemessages, bot_consolemessage_s::next, and bot_consolemessage_s::prev.

Referenced by BotQueueConsoleMessage().

00269 {
00270     bot_consolemessage_t *message;
00271     message = freeconsolemessages;
00272     if (freeconsolemessages) freeconsolemessages = freeconsolemessages->next;
00273     if (freeconsolemessages) freeconsolemessages->prev = NULL;
00274     return message;
00275 } //end of the function AllocConsoleMessage

int BotAllocChatState void   ) 
 

Definition at line 2895 of file be_ai_chat.c.

References bot_chatstate_t, botchatstates, GetClearedMemory(), and i.

02896 {
02897     int i;
02898 
02899     for (i = 1; i <= MAX_CLIENTS; i++)
02900     {
02901         if (!botchatstates[i])
02902         {
02903             botchatstates[i] = GetClearedMemory(sizeof(bot_chatstate_t));
02904             return i;
02905         } //end if
02906     } //end for
02907     return 0;
02908 } //end of the function BotAllocChatState

Here is the call graph for this function:

int BotChatLength int  chatstate  ) 
 

Definition at line 2771 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), bot_chatstate_s::chatmessage, and strlen().

02772 {
02773     bot_chatstate_t *cs;
02774 
02775     cs = BotChatStateFromHandle(chatstate);
02776     if (!cs) return 0;
02777     return strlen(cs->chatmessage);
02778 } //end of the function BotChatLength

Here is the call graph for this function:

bot_chatstate_t* BotChatStateFromHandle int  handle  ) 
 

Definition at line 219 of file be_ai_chat.c.

References bot_chatstate_t, botchatstates, botimport, and PRT_FATAL.

Referenced by BotChatLength(), BotEnterChat(), BotFreeChatFile(), BotGetChatMessage(), BotInitialChat(), BotLoadChatFile(), BotNextConsoleMessage(), BotNumConsoleMessages(), BotNumInitialChats(), BotQueueConsoleMessage(), BotRemoveConsoleMessage(), BotReplyChat(), BotSetChatGender(), and BotSetChatName().

00220 {
00221     if (handle <= 0 || handle > MAX_CLIENTS)
00222     {
00223         botimport.Print(PRT_FATAL, "chat state handle %d out of range\n", handle);
00224         return NULL;
00225     } //end if
00226     if (!botchatstates[handle])
00227     {
00228         botimport.Print(PRT_FATAL, "invalid chat state %d\n", handle);
00229         return NULL;
00230     } //end if
00231     return botchatstates[handle];
00232 } //end of the function BotChatStateFromHandle

bot_stringlist_t* BotCheckChatMessageIntegrety char *  message,
bot_stringlist_t stringlist
 

Definition at line 1513 of file be_ai_chat.c.

References bot_stringlist_t, BotFindStringInList(), botimport, GetClearedMemory(), i, Log_Write(), bot_stringlist_s::next, PRT_FATAL, RandomString(), s, strcpy(), bot_stringlist_s::string, and strlen().

Referenced by BotCheckInitialChatIntegrety(), and BotCheckReplyChatIntegrety().

01514 {
01515     int i;
01516     char *msgptr;
01517     char temp[MAX_MESSAGE_SIZE];
01518     bot_stringlist_t *s;
01519 
01520     msgptr = message;
01521     //
01522     while(*msgptr)
01523     {
01524         if (*msgptr == ESCAPE_CHAR)
01525         {
01526             msgptr++;
01527             switch(*msgptr)
01528             {
01529                 case 'v': //variable
01530                 {
01531                     //step over the 'v'
01532                     msgptr++;
01533                     while(*msgptr && *msgptr != ESCAPE_CHAR) msgptr++;
01534                     //step over the trailing escape char
01535                     if (*msgptr) msgptr++;
01536                     break;
01537                 } //end case
01538                 case 'r': //random
01539                 {
01540                     //step over the 'r'
01541                     msgptr++;
01542                     for (i = 0; (*msgptr && *msgptr != ESCAPE_CHAR); i++)
01543                     {
01544                         temp[i] = *msgptr++;
01545                     } //end while
01546                     temp[i] = '\0';
01547                     //step over the trailing escape char
01548                     if (*msgptr) msgptr++;
01549                     //find the random keyword
01550                     if (!RandomString(temp))
01551                     {
01552                         if (!BotFindStringInList(stringlist, temp))
01553                         {
01554                             Log_Write("%s = {\"%s\"} //MISSING RANDOM\r\n", temp, temp);
01555                             s = GetClearedMemory(sizeof(bot_stringlist_t) + strlen(temp) + 1);
01556                             s->string = (char *) s + sizeof(bot_stringlist_t);
01557                             strcpy(s->string, temp);
01558                             s->next = stringlist;
01559                             stringlist = s;
01560                         } //end if
01561                     } //end if
01562                     break;
01563                 } //end case
01564                 default:
01565                 {
01566                     botimport.Print(PRT_FATAL, "BotCheckChatMessageIntegrety: message \"%s\" invalid escape char\n", message);
01567                     break;
01568                 } //end default
01569             } //end switch
01570         } //end if
01571         else
01572         {
01573             msgptr++;
01574         } //end else
01575     } //end while
01576     return stringlist;
01577 } //end of the function BotCheckChatMessageIntegrety

Here is the call graph for this function:

void BotCheckInitialChatIntegrety bot_chat_t chat  ) 
 

Definition at line 1584 of file be_ai_chat.c.

References bot_chat_t, bot_chatmessage_t, bot_chattype_t, bot_stringlist_t, BotCheckChatMessageIntegrety(), cm, bot_chattype_s::firstchatmessage, FreeMemory(), bot_stringlist_s::next, bot_chattype_s::next, s, t, and bot_chat_s::types.

Referenced by BotLoadInitialChat().

01585 {
01586     bot_chattype_t *t;
01587     bot_chatmessage_t *cm;
01588     bot_stringlist_t *stringlist, *s, *nexts;
01589 
01590     stringlist = NULL;
01591     for (t = chat->types; t; t = t->next)
01592     {
01593         for (cm = t->firstchatmessage; cm; cm = cm->next)
01594         {
01595             stringlist = BotCheckChatMessageIntegrety(cm->chatmessage, stringlist);
01596         } //end for
01597     } //end for
01598     for (s = stringlist; s; s = nexts)
01599     {
01600         nexts = s->next;
01601         FreeMemory(s);
01602     } //end for
01603 } //end of the function BotCheckInitialChatIntegrety

Here is the call graph for this function:

void BotCheckReplyChatIntegrety bot_replychat_t replychat  ) 
 

Definition at line 1610 of file be_ai_chat.c.

References bot_chatmessage_t, bot_replychat_t, bot_stringlist_t, BotCheckChatMessageIntegrety(), cm, bot_replychat_s::firstchatmessage, FreeMemory(), bot_stringlist_s::next, bot_replychat_s::next, and s.

Referenced by BotLoadReplyChat().

01611 {
01612     bot_replychat_t *rp;
01613     bot_chatmessage_t *cm;
01614     bot_stringlist_t *stringlist, *s, *nexts;
01615 
01616     stringlist = NULL;
01617     for (rp = replychat; rp; rp = rp->next)
01618     {
01619         for (cm = rp->firstchatmessage; cm; cm = cm->next)
01620         {
01621             stringlist = BotCheckChatMessageIntegrety(cm->chatmessage, stringlist);
01622         } //end for
01623     } //end for
01624     for (s = stringlist; s; s = nexts)
01625     {
01626         nexts = s->next;
01627         FreeMemory(s);
01628     } //end for
01629 } //end of the function BotCheckReplyChatIntegrety

Here is the call graph for this function:

void BotCheckValidReplyChatKeySet source_t source,
bot_replychatkey_t keys
 

Definition at line 1721 of file be_ai_chat.c.

References bot_matchpiece_t, bot_matchstring_t, bot_replychatkey_t, bot_matchpiece_s::firststring, bot_replychatkey_s::flags, m, bot_replychatkey_s::match, bot_matchstring_s::next, bot_matchpiece_s::next, bot_replychatkey_s::next, qfalse, RCKFL_AND, source, source_t, SourceWarning(), bot_replychatkey_s::string, bot_matchstring_s::string, StringContains(), and bot_matchpiece_s::type.

Referenced by BotLoadReplyChat().

01722 {
01723     int allprefixed, hasvariableskey, hasstringkey;
01724     bot_matchpiece_t *m;
01725     bot_matchstring_t *ms;
01726     bot_replychatkey_t *key, *key2;
01727 
01728     //
01729     allprefixed = qtrue;
01730     hasvariableskey = hasstringkey = qfalse;
01731     for (key = keys; key; key = key->next)
01732     {
01733         if (!(key->flags & (RCKFL_AND|RCKFL_NOT)))
01734         {
01735             allprefixed = qfalse;
01736             if (key->flags & RCKFL_VARIABLES)
01737             {
01738                 for (m = key->match; m; m = m->next)
01739                 {
01740                     if (m->type == MT_VARIABLE) hasvariableskey = qtrue;
01741                 } //end for
01742             } //end if
01743             else if (key->flags & RCKFL_STRING)
01744             {
01745                 hasstringkey = qtrue;
01746             } //end else if
01747         } //end if
01748         else if ((key->flags & RCKFL_AND) && (key->flags & RCKFL_STRING))
01749         {
01750             for (key2 = keys; key2; key2 = key2->next)
01751             {
01752                 if (key2 == key) continue;
01753                 if (key2->flags & RCKFL_NOT) continue;
01754                 if (key2->flags & RCKFL_VARIABLES)
01755                 {
01756                     for (m = key2->match; m; m = m->next)
01757                     {
01758                         if (m->type == MT_STRING)
01759                         {
01760                             for (ms = m->firststring; ms; ms = ms->next)
01761                             {
01762                                 if (StringContains(ms->string, key->string, qfalse) != -1)
01763                                 {
01764                                     break;
01765                                 } //end if
01766                             } //end for
01767                             if (ms) break;
01768                         } //end if
01769                         else if (m->type == MT_VARIABLE)
01770                         {
01771                             break;
01772                         } //end if
01773                     } //end for
01774                     if (!m)
01775                     {
01776                         SourceWarning(source, "one of the match templates does not "
01777                                         "leave space for the key %s with the & prefix", key->string);
01778                     } //end if
01779                 } //end if
01780             } //end for
01781         } //end else
01782         if ((key->flags & RCKFL_NOT) && (key->flags & RCKFL_STRING))
01783         {
01784             for (key2 = keys; key2; key2 = key2->next)
01785             {
01786                 if (key2 == key) continue;
01787                 if (key2->flags & RCKFL_NOT) continue;
01788                 if (key2->flags & RCKFL_STRING)
01789                 {
01790                     if (StringContains(key2->string, key->string, qfalse) != -1)
01791                     {
01792                         SourceWarning(source, "the key %s with prefix ! is inside the key %s", key->string, key2->string);
01793                     } //end if
01794                 } //end if
01795                 else if (key2->flags & RCKFL_VARIABLES)
01796                 {
01797                     for (m = key2->match; m; m = m->next)
01798                     {
01799                         if (m->type == MT_STRING)
01800                         {
01801                             for (ms = m->firststring; ms; ms = ms->next)
01802                             {
01803                                 if (StringContains(ms->string, key->string, qfalse) != -1)
01804                                 {
01805                                     SourceWarning(source, "the key %s with prefix ! is inside "
01806                                                 "the match template string %s", key->string, ms->string);
01807                                 } //end if
01808                             } //end for
01809                         } //end if
01810                     } //end for
01811                 } //end else if
01812             } //end for
01813         } //end if
01814     } //end for
01815     if (allprefixed) SourceWarning(source, "all keys have a & or ! prefix");
01816     if (hasvariableskey && hasstringkey)
01817     {
01818         SourceWarning(source, "variables from the match template(s) could be "
01819                                 "invalid when outputting one of the chat messages");
01820     } //end if
01821 } //end of the function BotCheckValidReplyChatKeySet

Here is the call graph for this function:

char* BotChooseInitialChatMessage bot_chatstate_t cs,
char *  type
 

Definition at line 2407 of file be_ai_chat.c.

References AAS_Time(), bot_chat_t, bot_chatmessage_t, bot_chatstate_t, bot_chattype_t, bot_chatstate_s::chat, bot_chatmessage_s::chatmessage, bot_chattype_s::firstchatmessage, m, n, bot_chattype_s::name, bot_chatmessage_s::next, bot_chattype_s::next, Q_stricmp(), random, t, bot_chatmessage_s::time, type, and bot_chat_s::types.

Referenced by BotInitialChat().

02408 {
02409     int n, numchatmessages;
02410     float besttime;
02411     bot_chattype_t *t;
02412     bot_chatmessage_t *m, *bestchatmessage;
02413     bot_chat_t *chat;
02414 
02415     chat = cs->chat;
02416     for (t = chat->types; t; t = t->next)
02417     {
02418         if (!Q_stricmp(t->name, type))
02419         {
02420             numchatmessages = 0;
02421             for (m = t->firstchatmessage; m; m = m->next)
02422             {
02423                 if (m->time > AAS_Time()) continue;
02424                 numchatmessages++;
02425             } //end if
02426             //if all chat messages have been used recently
02427             if (numchatmessages <= 0)
02428             {
02429                 besttime = 0;
02430                 bestchatmessage = NULL;
02431                 for (m = t->firstchatmessage; m; m = m->next)
02432                 {
02433                     if (!besttime || m->time < besttime)
02434                     {
02435                         bestchatmessage = m;
02436                         besttime = m->time;
02437                     } //end if
02438                 } //end for
02439                 if (bestchatmessage) return bestchatmessage->chatmessage;
02440             } //end if
02441             else //choose a chat message randomly
02442             {
02443                 n = random() * numchatmessages;
02444                 for (m = t->firstchatmessage; m; m = m->next)
02445                 {
02446                     if (m->time > AAS_Time()) continue;
02447                     if (--n < 0)
02448                     {
02449                         m->time = AAS_Time() + CHATMESSAGE_RECENTTIME;
02450                         return m->chatmessage;
02451                     } //end if
02452                 } //end for
02453             } //end else
02454             return NULL;
02455         } //end if
02456     } //end for
02457     return NULL;
02458 } //end of the function BotChooseInitialChatMessage

Here is the call graph for this function:

void BotConstructChatMessage bot_chatstate_t chatstate,
char *  message,
unsigned long  mcontext,
bot_match_t match,
unsigned long  vcontext,
int  reply
 

Definition at line 2379 of file be_ai_chat.c.

References bot_chatstate_t, bot_match_t, BotExpandChatMessage(), botimport, bot_chatstate_s::chatmessage, i, match(), PRT_WARNING, and strcpy().

Referenced by BotInitialChat(), and BotReplyChat().

02381 {
02382     int i;
02383     char srcmessage[MAX_MESSAGE_SIZE];
02384 
02385     strcpy(srcmessage, message);
02386     for (i = 0; i < 10; i++)
02387     {
02388         if (!BotExpandChatMessage(chatstate->chatmessage, srcmessage, mcontext, match, vcontext, reply))
02389         {
02390             break;
02391         } //end if
02392         strcpy(srcmessage, chatstate->chatmessage);
02393     } //end for
02394     if (i >= 10)
02395     {
02396         botimport.Print(PRT_WARNING, "too many expansions in chat message\n");
02397         botimport.Print(PRT_WARNING, "%s\n", chatstate->chatmessage);
02398     } //end if
02399 } //end of the function BotConstructChatMessage

Here is the call graph for this function:

void BotDumpInitialChat bot_chat_t chat  ) 
 

Definition at line 1988 of file be_ai_chat.c.

References bot_chat_t, bot_chatmessage_t, bot_chattype_t, bot_chatmessage_s::chatmessage, bot_chattype_s::firstchatmessage, Log_Write(), m, bot_chattype_s::name, bot_chatmessage_s::next, bot_chattype_s::next, bot_chattype_s::numchatmessages, t, and bot_chat_s::types.

01989 {
01990     bot_chattype_t *t;
01991     bot_chatmessage_t *m;
01992 
01993     Log_Write("{");
01994     for (t = chat->types; t; t = t->next)
01995     {
01996         Log_Write(" type \"%s\"", t->name);
01997         Log_Write(" {");
01998         Log_Write("  numchatmessages = %d", t->numchatmessages);
01999         for (m = t->firstchatmessage; m; m = m->next)
02000         {
02001             Log_Write("  \"%s\"", m->chatmessage);
02002         } //end for
02003         Log_Write(" }");
02004     } //end for
02005     Log_Write("}");
02006 } //end of the function BotDumpInitialChat

Here is the call graph for this function:

void BotDumpMatchTemplates bot_matchtemplate_t matches  ) 
 

Definition at line 1077 of file be_ai_chat.c.

References bot_matchpiece_t, bot_matchstring_t, bot_matchtemplate_t, bot_matchtemplate_s::first, bot_matchpiece_s::firststring, fp, fprintf(), Log_FilePointer(), bot_matchstring_s::next, bot_matchpiece_s::next, bot_matchtemplate_s::next, bot_matchstring_s::string, bot_matchtemplate_s::subtype, bot_matchtemplate_s::type, bot_matchpiece_s::type, and bot_matchpiece_s::variable.

01078 {
01079     FILE *fp;
01080     bot_matchtemplate_t *mt;
01081     bot_matchpiece_t *mp;
01082     bot_matchstring_t *ms;
01083 
01084     fp = Log_FilePointer();
01085     if (!fp) return;
01086     for (mt = matches; mt; mt = mt->next)
01087     {
01088             fprintf(fp, "{ " );
01089         for (mp = mt->first; mp; mp = mp->next)
01090         {
01091             if (mp->type == MT_STRING)
01092             {
01093                 for (ms = mp->firststring; ms; ms = ms->next)
01094                 {
01095                     fprintf(fp, "\"%s\"", ms->string);
01096                     if (ms->next) fprintf(fp, "|");
01097                 } //end for
01098             } //end if
01099             else if (mp->type == MT_VARIABLE)
01100             {
01101                 fprintf(fp, "%d", mp->variable);
01102             } //end else if
01103             if (mp->next) fprintf(fp, ", ");
01104         } //end for
01105         fprintf(fp, " = (%d, %d);}\n", mt->type, mt->subtype);
01106     } //end for
01107 } //end of the function BotDumpMatchTemplates

Here is the call graph for this function:

void BotDumpRandomStringList bot_randomlist_t randomlist  ) 
 

Definition at line 921 of file be_ai_chat.c.

References bot_randomlist_t, bot_randomstring_t, bot_randomlist_s::firstrandomstring, fp, fprintf(), Log_FilePointer(), bot_randomstring_s::next, bot_randomlist_s::next, random, bot_randomstring_s::string, and bot_randomlist_s::string.

00922 {
00923     FILE *fp;
00924     bot_randomlist_t *random;
00925     bot_randomstring_t *rs;
00926 
00927     fp = Log_FilePointer();
00928     if (!fp) return;
00929     for (random = randomlist; random; random = random->next)
00930     {
00931         fprintf(fp, "%s = {", random->string);
00932         for (rs = random->firstrandomstring; rs; rs = rs->next)
00933         {
00934             fprintf(fp, "\"%s\"", rs->string);
00935             if (rs->next) fprintf(fp, ", ");
00936             else fprintf(fp, "}\n");
00937         } //end for
00938     } //end for
00939 } //end of the function BotDumpRandomStringList

Here is the call graph for this function:

void BotDumpReplyChat bot_replychat_t replychat  ) 
 

Definition at line 1636 of file be_ai_chat.c.

References bot_chatmessage_t, bot_matchpiece_t, bot_replychat_t, bot_replychatkey_t, cm, bot_replychat_s::firstchatmessage, bot_matchpiece_s::firststring, bot_replychatkey_s::flags, fp, fprintf(), bot_replychat_s::keys, Log_FilePointer(), bot_replychatkey_s::match, bot_matchpiece_s::next, bot_replychatkey_s::next, bot_replychat_s::next, bot_replychat_s::priority, bot_replychatkey_s::string, bot_matchstring_s::string, bot_matchpiece_s::type, and bot_matchpiece_s::variable.

01637 {
01638     FILE *fp;
01639     bot_replychat_t *rp;
01640     bot_replychatkey_t *key;
01641     bot_chatmessage_t *cm;
01642     bot_matchpiece_t *mp;
01643 
01644     fp = Log_FilePointer();
01645     if (!fp) return;
01646     fprintf(fp, "BotDumpReplyChat:\n");
01647     for (rp = replychat; rp; rp = rp->next)
01648     {
01649         fprintf(fp, "[");
01650         for (key = rp->keys; key; key = key->next)
01651         {
01652             if (key->flags & RCKFL_AND) fprintf(fp, "&");
01653             else if (key->flags & RCKFL_NOT) fprintf(fp, "!");
01654             //
01655             if (key->flags & RCKFL_NAME) fprintf(fp, "name");
01656             else if (key->flags & RCKFL_GENDERFEMALE) fprintf(fp, "female");
01657             else if (key->flags & RCKFL_GENDERMALE) fprintf(fp, "male");
01658             else if (key->flags & RCKFL_GENDERLESS) fprintf(fp, "it");
01659             else if (key->flags & RCKFL_VARIABLES)
01660             {
01661                 fprintf(fp, "(");
01662                 for (mp = key->match; mp; mp = mp->next)
01663                 {
01664                     if (mp->type == MT_STRING) fprintf(fp, "\"%s\"", mp->firststring->string);
01665                     else fprintf(fp, "%d", mp->variable);
01666                     if (mp->next) fprintf(fp, ", ");
01667                 } //end for
01668                 fprintf(fp, ")");
01669             } //end if
01670             else if (key->flags & RCKFL_STRING)
01671             {
01672                 fprintf(fp, "\"%s\"", key->string);
01673             } //end if
01674             if (key->next) fprintf(fp, ", ");
01675             else fprintf(fp, "] = %1.0f\n", rp->priority);
01676         } //end for
01677         fprintf(fp, "{\n");
01678         for (cm = rp->firstchatmessage; cm; cm = cm->next)
01679         {
01680             fprintf(fp, "\t\"%s\";\n", cm->chatmessage);
01681         } //end for
01682         fprintf(fp, "}\n");
01683     } //end for
01684 } //end of the function BotDumpReplyChat

Here is the call graph for this function:

void BotDumpSynonymList bot_synonymlist_t synlist  ) 
 

Definition at line 570 of file be_ai_chat.c.

References bot_synonym_t, bot_synonymlist_t, bot_synonymlist_s::context, bot_synonymlist_s::firstsynonym, fp, fprintf(), Log_FilePointer(), bot_synonym_s::next, bot_synonymlist_s::next, bot_synonym_s::string, and bot_synonym_s::weight.

00571 {
00572     FILE *fp;
00573     bot_synonymlist_t *syn;
00574     bot_synonym_t *synonym;
00575 
00576     fp = Log_FilePointer();
00577     if (!fp) return;
00578     for (syn = synlist; syn; syn = syn->next)
00579     {
00580             fprintf(fp, "%ld : [", syn->context);
00581         for (synonym = syn->firstsynonym; synonym; synonym = synonym->next)
00582         {
00583             fprintf(fp, "(\"%s\", %1.2f)", synonym->string, synonym->weight);
00584             if (synonym->next) fprintf(fp, ", ");
00585         } //end for
00586         fprintf(fp, "]\n");
00587     } //end for
00588 } //end of the function BotDumpSynonymList

Here is the call graph for this function:

void BotEnterChat int  chatstate,
int  clientto,
int  sendto
 

Definition at line 2785 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), botimport, BotRemoveTildes(), CHAT_TEAM, CHAT_TELL, bot_chatstate_s::chatmessage, bot_chatstate_s::client, EA_Command(), LibVarGetValue(), PRT_MESSAGE, strcpy(), strlen(), and va().

02786 {
02787     bot_chatstate_t *cs;
02788 
02789     cs = BotChatStateFromHandle(chatstate);
02790     if (!cs) return;
02791 
02792     if (strlen(cs->chatmessage))
02793     {
02794         BotRemoveTildes(cs->chatmessage);
02795         if (LibVarGetValue("bot_testichat")) {
02796             botimport.Print(PRT_MESSAGE, "%s\n", cs->chatmessage);
02797         }
02798         else {
02799             switch(sendto) {
02800                 case CHAT_TEAM:
02801                     EA_Command(cs->client, va("say_team %s", cs->chatmessage));
02802                     break;
02803                 case CHAT_TELL:
02804                     EA_Command(cs->client, va("tell %d %s", clientto, cs->chatmessage));
02805                     break;
02806                 default: //CHAT_ALL
02807                     EA_Command(cs->client, va("say %s", cs->chatmessage));
02808                     break;
02809             }
02810         }
02811         //clear the chat message from the state
02812         strcpy(cs->chatmessage, "");
02813     } //end if
02814 } //end of the function BotEnterChat

Here is the call graph for this function:

int BotExpandChatMessage char *  outmessage,
char *  message,
unsigned long  mcontext,
bot_match_t match,
unsigned long  vcontext,
int  reply
 

Definition at line 2258 of file be_ai_chat.c.

References assert, bot_match_t, botimport, BotReplaceReplySynonyms(), BotReplaceSynonyms(), BotReplaceWeightedSynonyms(), i, bot_matchvariable_s::length, match(), bot_matchvariable_s::offset, PRT_ERROR, PRT_FATAL, ptr(), RandomString(), strcpy(), bot_match_s::string, strlen(), and bot_match_s::variables.

Referenced by BotConstructChatMessage().

02260 {
02261     int num, len, i, expansion;
02262     char *outputbuf, *ptr, *msgptr;
02263     char temp[MAX_MESSAGE_SIZE];
02264 
02265     expansion = qfalse;
02266     msgptr = message;
02267     outputbuf = outmessage;
02268     len = 0;
02269     //
02270     while(*msgptr)
02271     {
02272         if (*msgptr == ESCAPE_CHAR)
02273         {
02274             msgptr++;
02275             switch(*msgptr)
02276             {
02277                 case 'v': //variable
02278                 {
02279                     msgptr++;
02280                     num = 0;
02281                     while(*msgptr && *msgptr != ESCAPE_CHAR)
02282                     {
02283                         num = num * 10 + (*msgptr++) - '0';
02284                     } //end while
02285                     //step over the trailing escape char
02286                     if (*msgptr) msgptr++;
02287                     if (num > MAX_MATCHVARIABLES)
02288                     {
02289                         botimport.Print(PRT_ERROR, "BotConstructChat: message %s variable %d out of range\n", message, num);
02290                         return qfalse;
02291                     } //end if
02292                     if (match->variables[num].offset >= 0)
02293                     {
02294                             assert( match->variables[num].offset >= 0 ); // bk001204
02295                         ptr = &match->string[ (int) match->variables[num].offset];
02296                         for (i = 0; i < match->variables[num].length; i++)
02297                         {
02298                             temp[i] = ptr[i];
02299                         } //end for
02300                         temp[i] = 0;
02301                         //if it's a reply message
02302                         if (reply)
02303                         {
02304                             //replace the reply synonyms in the variables
02305                             BotReplaceReplySynonyms(temp, vcontext);
02306                         } //end if
02307                         else 
02308                         {
02309                             //replace synonyms in the variable context
02310                             BotReplaceSynonyms(temp, vcontext);
02311                         } //end else
02312                         //
02313                         if (len + strlen(temp) >= MAX_MESSAGE_SIZE)
02314                         {
02315                             botimport.Print(PRT_ERROR, "BotConstructChat: message %s too long\n", message);
02316                             return qfalse;
02317                         } //end if
02318                         strcpy(&outputbuf[len], temp);
02319                         len += strlen(temp);
02320                     } //end if
02321                     break;
02322                 } //end case
02323                 case 'r': //random
02324                 {
02325                     msgptr++;
02326                     for (i = 0; (*msgptr && *msgptr != ESCAPE_CHAR); i++)
02327                     {
02328                         temp[i] = *msgptr++;
02329                     } //end while
02330                     temp[i] = '\0';
02331                     //step over the trailing escape char
02332                     if (*msgptr) msgptr++;
02333                     //find the random keyword
02334                     ptr = RandomString(temp);
02335                     if (!ptr)
02336                     {
02337                         botimport.Print(PRT_ERROR, "BotConstructChat: unknown random string %s\n", temp);
02338                         return qfalse;
02339                     } //end if
02340                     if (len + strlen(ptr) >= MAX_MESSAGE_SIZE)
02341                     {
02342                         botimport.Print(PRT_ERROR, "BotConstructChat: message \"%s\" too long\n", message);
02343                         return qfalse;
02344                     } //end if
02345                     strcpy(&outputbuf[len], ptr);
02346                     len += strlen(ptr);
02347                     expansion = qtrue;
02348                     break;
02349                 } //end case
02350                 default:
02351                 {
02352                     botimport.Print(PRT_FATAL, "BotConstructChat: message \"%s\" invalid escape char\n", message);
02353                     break;
02354                 } //end default
02355             } //end switch
02356         } //end if
02357         else
02358         {
02359             outputbuf[len++] = *msgptr++;
02360             if (len >= MAX_MESSAGE_SIZE)
02361             {
02362                 botimport.Print(PRT_ERROR, "BotConstructChat: message \"%s\" too long\n", message);
02363                 break;
02364             } //end if
02365         } //end else
02366     } //end while
02367     outputbuf[len] = '\0';
02368     //replace synonyms weighted in the message context
02369     BotReplaceWeightedSynonyms(outputbuf, mcontext);
02370     //return true if a random was expanded
02371     return expansion;
02372 } //end of the function BotExpandChatMessage

Here is the call graph for this function:

int BotFindMatch char *  str,
bot_match_t match,
unsigned long int  context
 

Definition at line 1434 of file be_ai_chat.c.

References bot_match_t, bot_matchtemplate_t, bot_matchtemplate_s::context, bot_matchtemplate_s::first, i, match(), MAX_MESSAGE_SIZE, bot_matchtemplate_s::next, bot_matchvariable_s::offset, bot_match_s::string, StringsMatch(), strlen(), strncpy(), bot_match_s::subtype, bot_matchtemplate_s::subtype, bot_match_s::type, bot_matchtemplate_s::type, and bot_match_s::variables.

01435 {
01436     int i;
01437     bot_matchtemplate_t *ms;
01438 
01439     strncpy(match->string, str, MAX_MESSAGE_SIZE);
01440     //remove any trailing enters
01441     while(strlen(match->string) &&
01442             match->string[strlen(match->string)-1] == '\n')
01443     {
01444         match->string[strlen(match->string)-1] = '\0';
01445     } //end while
01446     //compare the string with all the match strings
01447     for (ms = matchtemplates; ms; ms = ms->next)
01448     {
01449         if (!(ms->context & context)) continue;
01450         //reset the match variable offsets
01451         for (i = 0; i < MAX_MATCHVARIABLES; i++) match->variables[i].offset = -1;
01452         //
01453         if (StringsMatch(ms->first, match))
01454         {
01455             match->type = ms->type;
01456             match->subtype = ms->subtype;
01457             return qtrue;
01458         } //end if
01459     } //end for
01460     return qfalse;
01461 } //end of the function BotFindMatch

Here is the call graph for this function:

bot_stringlist_t* BotFindStringInList bot_stringlist_t list,
char *  string
 

Definition at line 1497 of file be_ai_chat.c.

References bot_stringlist_t, bot_stringlist_s::next, s, strcmp(), string(), and bot_stringlist_s::string.

Referenced by BotCheckChatMessageIntegrety().

01498 {
01499     bot_stringlist_t *s;
01500 
01501     for (s = list; s; s = s->next)
01502     {
01503         if (!strcmp(s->string, string)) return s;
01504     } //end for
01505     return NULL;
01506 } //end of the function BotFindStringInList

Here is the call graph for this function:

void BotFreeChatFile int  chatstate  ) 
 

Definition at line 2185 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), bot_chatstate_s::chat, and FreeMemory().

Referenced by BotFreeChatState(), and BotLoadChatFile().

02186 {
02187     bot_chatstate_t *cs;
02188 
02189     cs = BotChatStateFromHandle(chatstate);
02190     if (!cs) return;
02191     if (cs->chat) FreeMemory(cs->chat);
02192     cs->chat = NULL;
02193 } //end of the function BotFreeChatFile

Here is the call graph for this function:

void BotFreeChatState int  handle  ) 
 

Definition at line 2915 of file be_ai_chat.c.

References bot_chatstate_t, bot_consolemessage_t, botchatstates, BotFreeChatFile(), botimport, BotNextConsoleMessage(), BotRemoveConsoleMessage(), FreeMemory(), h(), LibVarGetValue(), m, and PRT_FATAL.

Referenced by BotShutdownChatAI().

02916 {
02917     bot_chatstate_t *cs;
02918     bot_consolemessage_t m;
02919     int h;
02920 
02921     if (handle <= 0 || handle > MAX_CLIENTS)
02922     {
02923         botimport.Print(PRT_FATAL, "chat state handle %d out of range\n", handle);
02924         return;
02925     } //end if
02926     if (!botchatstates[handle])
02927     {
02928         botimport.Print(PRT_FATAL, "invalid chat state %d\n", handle);
02929         return;
02930     } //end if
02931     cs = botchatstates[handle];
02932     if (LibVarGetValue("bot_reloadcharacters"))
02933     {
02934         BotFreeChatFile(handle);
02935     } //end if
02936     //free all the console messages left in the chat state
02937     for (h = BotNextConsoleMessage(handle, &m); h; h = BotNextConsoleMessage(handle, &m))
02938     {
02939         //remove the console message
02940         BotRemoveConsoleMessage(handle, h);
02941     } //end for
02942     FreeMemory(botchatstates[handle]);
02943     botchatstates[handle] = NULL;
02944 } //end of the function BotFreeChatState

Here is the call graph for this function:

void BotFreeMatchPieces bot_matchpiece_t matchpieces  ) 
 

Definition at line 1114 of file be_ai_chat.c.

References bot_matchpiece_t, bot_matchstring_t, bot_matchpiece_s::firststring, FreeMemory(), bot_matchstring_s::next, bot_matchpiece_s::next, and bot_matchpiece_s::type.

Referenced by BotFreeMatchTemplates(), BotFreeReplyChat(), and BotLoadMatchPieces().

01115 {
01116     bot_matchpiece_t *mp, *nextmp;
01117     bot_matchstring_t *ms, *nextms;
01118 
01119     for (mp = matchpieces; mp; mp = nextmp)
01120     {
01121         nextmp = mp->next;
01122         if (mp->type == MT_STRING)
01123         {
01124             for (ms = mp->firststring; ms; ms = nextms)
01125             {
01126                 nextms = ms->next;
01127                 FreeMemory(ms);
01128             } //end for
01129         } //end if
01130         FreeMemory(mp);
01131     } //end for
01132 } //end of the function BotFreeMatchPieces

Here is the call graph for this function:

void BotFreeMatchTemplates bot_matchtemplate_t mt  ) 
 

Definition at line 1241 of file be_ai_chat.c.

References bot_matchtemplate_t, BotFreeMatchPieces(), bot_matchtemplate_s::first, FreeMemory(), and bot_matchtemplate_s::next.

Referenced by BotLoadMatchTemplates(), and BotShutdownChatAI().

01242 {
01243     bot_matchtemplate_t *nextmt;
01244 
01245     for (; mt; mt = nextmt)
01246     {
01247         nextmt = mt->next;
01248         BotFreeMatchPieces(mt->first);
01249         FreeMemory(mt);
01250     } //end for
01251 } //end of the function BotFreeMatchTemplates

Here is the call graph for this function:

void BotFreeReplyChat bot_replychat_t replychat  ) 
 

Definition at line 1691 of file be_ai_chat.c.

References bot_chatmessage_t, bot_replychat_t, bot_replychatkey_t, BotFreeMatchPieces(), cm, bot_replychat_s::firstchatmessage, FreeMemory(), bot_replychat_s::keys, bot_replychatkey_s::match, bot_replychatkey_s::next, bot_replychat_s::next, and bot_replychatkey_s::string.

Referenced by BotLoadReplyChat(), and BotShutdownChatAI().

01692 {
01693     bot_replychat_t *rp, *nextrp;
01694     bot_replychatkey_t *key, *nextkey;
01695     bot_chatmessage_t *cm, *nextcm;
01696 
01697     for (rp = replychat; rp; rp = nextrp)
01698     {
01699         nextrp = rp->next;
01700         for (key = rp->keys; key; key = nextkey)
01701         {
01702             nextkey = key->next;
01703             if (key->match) BotFreeMatchPieces(key->match);
01704             if (key->string) FreeMemory(key->string);
01705             FreeMemory(key);
01706         } //end for
01707         for (cm = rp->firstchatmessage; cm; cm = nextcm)
01708         {
01709             nextcm = cm->next;
01710             FreeMemory(cm);
01711         } //end for
01712         FreeMemory(rp);
01713     } //end for
01714 } //end of the function BotFreeReplyChat

Here is the call graph for this function:

void BotGetChatMessage int  chatstate,
char *  buf,
int  size
 

Definition at line 2821 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), BotRemoveTildes(), bot_chatstate_s::chatmessage, strcpy(), and strncpy().

02822 {
02823     bot_chatstate_t *cs;
02824 
02825     cs = BotChatStateFromHandle(chatstate);
02826     if (!cs) return;
02827 
02828     BotRemoveTildes(cs->chatmessage);
02829     strncpy(buf, cs->chatmessage, size-1);
02830     buf[size-1] = '\0';
02831     //clear the chat message from the state
02832     strcpy(cs->chatmessage, "");
02833 } //end of the function BotGetChatMessage

Here is the call graph for this function:

void BotInitialChat int  chatstate,
char *  type,
int  mcontext,
char *  var0,
char *  var1,
char *  var2,
char *  var3,
char *  var4,
char *  var5,
char *  var6,
char *  var7
 

Definition at line 2492 of file be_ai_chat.c.

References bot_chatstate_t, bot_match_t, BotChatStateFromHandle(), BotChooseInitialChatMessage(), BotConstructChatMessage(), botimport, bot_chatstate_s::chat, Com_Memset(), match(), PRT_MESSAGE, qfalse, strcat(), strlen(), and type.

02493 {
02494     char *message;
02495     int index;
02496     bot_match_t match;
02497     bot_chatstate_t *cs;
02498 
02499     cs = BotChatStateFromHandle(chatstate);
02500     if (!cs) return;
02501     //if no chat file is loaded
02502     if (!cs->chat) return;
02503     //choose a chat message randomly of the given type
02504     message = BotChooseInitialChatMessage(cs, type);
02505     //if there's no message of the given type
02506     if (!message)
02507     {
02508 #ifdef DEBUG
02509         botimport.Print(PRT_MESSAGE, "no chat messages of type %s\n", type);
02510 #endif //DEBUG
02511         return;
02512     } //end if
02513     //
02514     Com_Memset(&match, 0, sizeof(match));
02515     index = 0;
02516     if( var0 ) {
02517         strcat(match.string, var0);
02518         match.variables[0].offset = index;
02519         match.variables[0].length = strlen(var0);
02520         index += strlen(var0);
02521     }
02522     if( var1 ) {
02523         strcat(match.string, var1);
02524         match.variables[1].offset = index;
02525         match.variables[1].length = strlen(var1);
02526         index += strlen(var1);
02527     }
02528     if( var2 ) {
02529         strcat(match.string, var2);
02530         match.variables[2].offset = index;
02531         match.variables[2].length = strlen(var2);
02532         index += strlen(var2);
02533     }
02534     if( var3 ) {
02535         strcat(match.string, var3);
02536         match.variables[3].offset = index;
02537         match.variables[3].length = strlen(var3);
02538         index += strlen(var3);
02539     }
02540     if( var4 ) {
02541         strcat(match.string, var4);
02542         match.variables[4].offset = index;
02543         match.variables[4].length = strlen(var4);
02544         index += strlen(var4);
02545     }
02546     if( var5 ) {
02547         strcat(match.string, var5);
02548         match.variables[5].offset = index;
02549         match.variables[5].length = strlen(var5);
02550         index += strlen(var5);
02551     }
02552     if( var6 ) {
02553         strcat(match.string, var6);
02554         match.variables[6].offset = index;
02555         match.variables[6].length = strlen(var6);
02556         index += strlen(var6);
02557     }
02558     if( var7 ) {
02559         strcat(match.string, var7);
02560         match.variables[7].offset = index;
02561         match.variables[7].length = strlen(var7);
02562         index += strlen(var7);
02563     }
02564     //
02565     BotConstructChatMessage(cs, message, mcontext, &match, 0, qfalse);
02566 } //end of the function BotInitialChat

Here is the call graph for this function:

int BotLoadChatFile int  chatstate,
char *  chatfile,
char *  chatname
 

Definition at line 2200 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), BotFreeChatFile(), botimport, BotLoadInitialChat(), bot_chatstate_s::chat, bot_ichatdata_t::chat, GetClearedMemory(), ichatdata, LibVarGetValue(), n, PRT_FATAL, Q_strncpyz(), and strcmp().

02201 {
02202     bot_chatstate_t *cs;
02203     int n, avail = 0;
02204 
02205     cs = BotChatStateFromHandle(chatstate);
02206     if (!cs) return BLERR_CANNOTLOADICHAT;
02207     BotFreeChatFile(chatstate);
02208 
02209     if (!LibVarGetValue("bot_reloadcharacters"))
02210     {
02211         avail = -1;
02212         for( n = 0; n < MAX_CLIENTS; n++ ) {
02213             if( !ichatdata[n] ) {
02214                 if( avail == -1 ) {
02215                     avail = n;
02216                 }
02217                 continue;
02218             }
02219             if( strcmp( chatfile, ichatdata[n]->filename ) != 0 ) { 
02220                 continue;
02221             }
02222             if( strcmp( chatname, ichatdata[n]->chatname ) != 0 ) { 
02223                 continue;
02224             }
02225             cs->chat = ichatdata[n]->chat;
02226         //      botimport.Print( PRT_MESSAGE, "retained %s from %s\n", chatname, chatfile );
02227             return BLERR_NOERROR;
02228         }
02229 
02230         if( avail == -1 ) {
02231             botimport.Print(PRT_FATAL, "ichatdata table full; couldn't load chat %s from %s\n", chatname, chatfile);
02232             return BLERR_CANNOTLOADICHAT;
02233         }
02234     }
02235 
02236     cs->chat = BotLoadInitialChat(chatfile, chatname);
02237     if (!cs->chat)
02238     {
02239         botimport.Print(PRT_FATAL, "couldn't load chat %s from %s\n", chatname, chatfile);
02240         return BLERR_CANNOTLOADICHAT;
02241     } //end if
02242     if (!LibVarGetValue("bot_reloadcharacters"))
02243     {
02244         ichatdata[avail] = GetClearedMemory( sizeof(bot_ichatdata_t) );
02245         ichatdata[avail]->chat = cs->chat;
02246         Q_strncpyz( ichatdata[avail]->chatname, chatname, sizeof(ichatdata[avail]->chatname) );
02247         Q_strncpyz( ichatdata[avail]->filename, chatfile, sizeof(ichatdata[avail]->filename) );
02248     } //end if
02249 
02250     return BLERR_NOERROR;
02251 } //end of the function BotLoadChatFile

Here is the call graph for this function:

int BotLoadChatMessage source_t source,
char *  chatmessagestring
 

Definition at line 862 of file be_ai_chat.c.

References ESCAPE_CHAR, token_s::intvalue, PC_CheckTokenString(), PC_ExpectAnyToken(), PC_ExpectTokenString(), ptr(), source, source_t, SourceError(), sprintf(), strcat(), token_s::string, StripDoubleQuotes(), strlen(), token_s::subtype, token, token_t, TT_NUMBER, and token_s::type.

Referenced by BotLoadInitialChat(), BotLoadRandomStrings(), and BotLoadReplyChat().

00863 {
00864     char *ptr;
00865     token_t token;
00866 
00867     ptr = chatmessagestring;
00868     *ptr = 0;
00869     //
00870     while(1)
00871     {
00872         if (!PC_ExpectAnyToken(source, &token)) return qfalse;
00873         //fixed string
00874         if (token.type == TT_STRING)
00875         {
00876             StripDoubleQuotes(token.string);
00877             if (strlen(ptr) + strlen(token.string) + 1 > MAX_MESSAGE_SIZE)
00878             {
00879                 SourceError(source, "chat message too long\n");
00880                 return qfalse;
00881             } //end if
00882             strcat(ptr, token.string);
00883         } //end else if
00884         //variable string
00885         else if (token.type == TT_NUMBER && (token.subtype & TT_INTEGER))
00886         {
00887             if (strlen(ptr) + 7 > MAX_MESSAGE_SIZE)
00888             {
00889                 SourceError(source, "chat message too long\n");
00890                 return qfalse;
00891             } //end if
00892             sprintf(&ptr[strlen(ptr)], "%cv%ld%c", ESCAPE_CHAR, token.intvalue, ESCAPE_CHAR);
00893         } //end if
00894         //random string
00895         else if (token.type == TT_NAME)
00896         {
00897             if (strlen(ptr) + 7 > MAX_MESSAGE_SIZE)
00898             {
00899                 SourceError(source, "chat message too long\n");
00900                 return qfalse;
00901             } //end if
00902             sprintf(&ptr[strlen(ptr)], "%cr%s%c", ESCAPE_CHAR, token.string, ESCAPE_CHAR);
00903         } //end else if
00904         else
00905         {
00906             SourceError(source, "unknown message component %s\n", token.string);
00907             return qfalse;
00908         } //end else
00909         if (PC_CheckTokenString(source, ";")) break;
00910         if (!PC_ExpectTokenString(source, ",")) return qfalse;
00911     } //end while
00912     //
00913     return qtrue;
00914 } //end of the function BotLoadChatMessage

Here is the call graph for this function:

bot_chat_t* BotLoadInitialChat char *  chatfile,
char *  chatname
 

Definition at line 2013 of file be_ai_chat.c.

References bot_chat_t, bot_chatmessage_t, bot_chattype_t, BotCheckInitialChatIntegrety(), BOTFILESBASEFOLDER, botimport, BotLoadChatMessage(), bot_chatmessage_s::chatmessage, bot_chattype_s::firstchatmessage, FreeSource(), GetClearedMemory(), LoadSourceFile(), MAX_CHATTYPE_NAME, bot_chattype_s::name, bot_chatmessage_s::next, bot_chattype_s::next, bot_chattype_s::numchatmessages, PC_CheckTokenString(), PC_ExpectAnyToken(), PC_ExpectTokenString(), PC_ExpectTokenType(), PC_ReadToken(), PC_SetBaseFolder(), PRT_ERROR, PRT_MESSAGE, ptr(), Q_stricmp(), source, source_t, SourceError(), strcmp(), strcpy(), token_s::string, StripDoubleQuotes(), strlen(), strncpy(), Sys_MilliSeconds(), bot_chatmessage_s::time, token, token_t, TT_STRING, and bot_chat_s::types.

Referenced by BotLoadChatFile().

02014 {
02015     int pass, foundchat, indent, size;
02016     char *ptr = NULL;
02017     char chatmessagestring[MAX_MESSAGE_SIZE];
02018     source_t *source;
02019     token_t token;
02020     bot_chat_t *chat = NULL;
02021     bot_chattype_t *chattype = NULL;
02022     bot_chatmessage_t *chatmessage = NULL;
02023 #ifdef DEBUG
02024     int starttime;
02025 
02026     starttime = Sys_MilliSeconds();
02027 #endif //DEBUG
02028     //
02029     size = 0;
02030     foundchat = qfalse;
02031     //a bot chat is parsed in two phases
02032     for (pass = 0; pass < 2; pass++)
02033     {
02034         //allocate memory
02035         if (pass && size) ptr = (char *) GetClearedMemory(size);
02036         //load the source file
02037         PC_SetBaseFolder(BOTFILESBASEFOLDER);
02038         source = LoadSourceFile(chatfile);
02039         if (!source)
02040         {
02041             botimport.Print(PRT_ERROR, "counldn't load %s\n", chatfile);
02042             return NULL;
02043         } //end if
02044         //chat structure
02045         if (pass)
02046         {
02047             chat = (bot_chat_t *) ptr;
02048             ptr += sizeof(bot_chat_t);
02049         } //end if
02050         size = sizeof(bot_chat_t);
02051         //
02052         while(PC_ReadToken(source, &token))
02053         {
02054             if (!strcmp(token.string, "chat"))
02055             {
02056                 if (!PC_ExpectTokenType(source, TT_STRING, 0, &token))
02057                 {
02058                     FreeSource(source);
02059                     return NULL;
02060                 } //end if
02061                 StripDoubleQuotes(token.string);
02062                 //after the chat name we expect a opening brace
02063                 if (!PC_ExpectTokenString(source, "{"))
02064                 {
02065                     FreeSource(source);
02066                     return NULL;
02067                 } //end if
02068                 //if the chat name is found
02069                 if (!Q_stricmp(token.string, chatname))
02070                 {
02071                     foundchat = qtrue;
02072                     //read the chat types
02073                     while(1)
02074                     {
02075                         if (!PC_ExpectAnyToken(source, &token))
02076                         {
02077                             FreeSource(source);
02078                             return NULL;
02079                         } //end if
02080                         if (!strcmp(token.string, "}")) break;
02081                         if (strcmp(token.string, "type"))
02082                         {
02083                             SourceError(source, "expected type found %s\n", token.string);
02084                             FreeSource(source);
02085                             return NULL;
02086                         } //end if
02087                         //expect the chat type name
02088                         if (!PC_ExpectTokenType(source, TT_STRING, 0, &token) ||
02089                             !PC_ExpectTokenString(source, "{"))
02090                         {
02091                             FreeSource(source);
02092                             return NULL;
02093                         } //end if
02094                         StripDoubleQuotes(token.string);
02095                         if (pass)
02096                         {
02097                             chattype = (bot_chattype_t *) ptr;
02098                             strncpy(chattype->name, token.string, MAX_CHATTYPE_NAME);
02099                             chattype->firstchatmessage = NULL;
02100                             //add the chat type to the chat
02101                             chattype->next = chat->types;
02102                             chat->types = chattype;
02103                             //
02104                             ptr += sizeof(bot_chattype_t);
02105                         } //end if
02106                         size += sizeof(bot_chattype_t);
02107                         //read the chat messages
02108                         while(!PC_CheckTokenString(source, "}"))
02109                         {
02110                             if (!BotLoadChatMessage(source, chatmessagestring))
02111                             {
02112                                 FreeSource(source);
02113                                 return NULL;
02114                             } //end if
02115                             if (pass)
02116                             {
02117                                 chatmessage = (bot_chatmessage_t *) ptr;
02118                                 chatmessage->time = -2*CHATMESSAGE_RECENTTIME;
02119                                 //put the chat message in the list
02120                                 chatmessage->next = chattype->firstchatmessage;
02121                                 chattype->firstchatmessage = chatmessage;
02122                                 //store the chat message
02123                                 ptr += sizeof(bot_chatmessage_t);
02124                                 chatmessage->chatmessage = ptr;
02125                                 strcpy(chatmessage->chatmessage, chatmessagestring);
02126                                 ptr += strlen(chatmessagestring) + 1;
02127                                 //the number of chat messages increased
02128                                 chattype->numchatmessages++;
02129                             } //end if
02130                             size += sizeof(bot_chatmessage_t) + strlen(chatmessagestring) + 1;
02131                         } //end if
02132                     } //end while
02133                 } //end if
02134                 else //skip the bot chat
02135                 {
02136                     indent = 1;
02137                     while(indent)
02138                     {
02139                         if (!PC_ExpectAnyToken(source, &token))
02140                         {
02141                             FreeSource(source);
02142                             return NULL;
02143                         } //end if
02144                         if (!strcmp(token.string, "{")) indent++;
02145                         else if (!strcmp(token.string, "}")) indent--;
02146                     } //end while
02147                 } //end else
02148             } //end if
02149             else
02150             {
02151                 SourceError(source, "unknown definition %s\n", token.string);
02152                 FreeSource(source);
02153                 return NULL;
02154             } //end else
02155         } //end while
02156         //free the source
02157         FreeSource(source);
02158         //if the requested character is not found
02159         if (!foundchat)
02160         {
02161             botimport.Print(PRT_ERROR, "couldn't find chat %s in %s\n", chatname, chatfile);
02162             return NULL;
02163         } //end if
02164     } //end for
02165     //
02166     botimport.Print(PRT_MESSAGE, "loaded %s from %s\n", chatname, chatfile);
02167     //
02168     //BotDumpInitialChat(chat);
02169     if (bot_developer)
02170     {
02171         BotCheckInitialChatIntegrety(chat);
02172     } //end if
02173 #ifdef DEBUG
02174     botimport.Print(PRT_MESSAGE, "initial chats loaded in %d msec\n", Sys_MilliSeconds() - starttime);
02175 #endif //DEBUG
02176     //character was read succesfully
02177     return chat;
02178 } //end of the function BotLoadInitialChat

Here is the call graph for this function:

bot_matchpiece_t* BotLoadMatchPieces source_t source,
char *  endtoken
 

Definition at line 1139 of file be_ai_chat.c.

References bot_matchpiece_t, bot_matchstring_t, BotFreeMatchPieces(), emptystring, bot_matchpiece_s::firststring, FreeSource(), GetClearedHunkMemory(), token_s::intvalue, MAX_MATCHVARIABLES, bot_matchstring_s::next, bot_matchpiece_s::next, PC_CheckTokenString(), PC_ExpectTokenString(), PC_ExpectTokenType(), PC_ReadToken(), source, source_t, SourceError(), strcpy(), bot_matchstring_s::string, token_s::string, StripDoubleQuotes(), strlen(), token_s::subtype, token, token_t, TT_NUMBER, TT_STRING, bot_matchpiece_s::type, token_s::type, and bot_matchpiece_s::variable.

Referenced by BotLoadMatchTemplates(), and BotLoadReplyChat().

01140 {
01141     int lastwasvariable, emptystring;
01142     token_t token;
01143     bot_matchpiece_t *matchpiece, *firstpiece, *lastpiece;
01144     bot_matchstring_t *matchstring, *lastmatchstring;
01145 
01146     firstpiece = NULL;
01147     lastpiece = NULL;
01148     //
01149     lastwasvariable = qfalse;
01150     //
01151     while(PC_ReadToken(source, &token))
01152     {
01153         if (token.type == TT_NUMBER && (token.subtype & TT_INTEGER))
01154         {
01155             if (token.intvalue < 0 || token.intvalue >= MAX_MATCHVARIABLES)
01156             {
01157                 SourceError(source, "can't have more than %d match variables\n", MAX_MATCHVARIABLES);
01158                 FreeSource(source);
01159                 BotFreeMatchPieces(firstpiece);
01160                 return NULL;
01161             } //end if
01162             if (lastwasvariable)
01163             {
01164                 SourceError(source, "not allowed to have adjacent variables\n");
01165                 FreeSource(source);
01166                 BotFreeMatchPieces(firstpiece);
01167                 return NULL;
01168             } //end if
01169             lastwasvariable = qtrue;
01170             //
01171             matchpiece = (bot_matchpiece_t *) GetClearedHunkMemory(sizeof(bot_matchpiece_t));
01172             matchpiece->type = MT_VARIABLE;
01173             matchpiece->variable = token.intvalue;
01174             matchpiece->next = NULL;
01175             if (lastpiece) lastpiece->next = matchpiece;
01176             else firstpiece = matchpiece;
01177             lastpiece = matchpiece;
01178         } //end if
01179         else if (token.type == TT_STRING)
01180         {
01181             //
01182             matchpiece = (bot_matchpiece_t *) GetClearedHunkMemory(sizeof(bot_matchpiece_t));
01183             matchpiece->firststring = NULL;
01184             matchpiece->type = MT_STRING;
01185             matchpiece->variable = 0;
01186             matchpiece->next = NULL;
01187             if (lastpiece) lastpiece->next = matchpiece;
01188             else firstpiece = matchpiece;
01189             lastpiece = matchpiece;
01190             //
01191             lastmatchstring = NULL;
01192             emptystring = qfalse;
01193             //
01194             do
01195             {
01196                 if (matchpiece->firststring)
01197                 {
01198                     if (!PC_ExpectTokenType(source, TT_STRING, 0, &token))
01199                     {
01200                         FreeSource(source);
01201                         BotFreeMatchPieces(firstpiece);
01202                         return NULL;
01203                     } //end if
01204                 } //end if
01205                 StripDoubleQuotes(token.string);
01206                 matchstring = (bot_matchstring_t *) GetClearedHunkMemory(sizeof(bot_matchstring_t) + strlen(token.string) + 1);
01207                 matchstring->string = (char *) matchstring + sizeof(bot_matchstring_t);
01208                 strcpy(matchstring->string, token.string);
01209                 if (!strlen(token.string)) emptystring = qtrue;
01210                 matchstring->next = NULL;
01211                 if (lastmatchstring) lastmatchstring->next = matchstring;
01212                 else matchpiece->firststring = matchstring;
01213                 lastmatchstring = matchstring;
01214             } while(PC_CheckTokenString(source, "|"));
01215             //if there was no empty string found
01216             if (!emptystring) lastwasvariable = qfalse;
01217         } //end if
01218         else
01219         {
01220             SourceError(source, "invalid token %s\n", token.string);
01221             FreeSource(source);
01222             BotFreeMatchPieces(firstpiece);
01223             return NULL;
01224         } //end else
01225         if (PC_CheckTokenString(source, endtoken)) break;
01226         if (!PC_ExpectTokenString(source, ","))
01227         {
01228             FreeSource(source);
01229             BotFreeMatchPieces(firstpiece);
01230             return NULL;
01231         } //end if
01232     } //end while
01233     return firstpiece;
01234 } //end of the function BotLoadMatchPieces

Here is the call graph for this function:

bot_matchtemplate_t* BotLoadMatchTemplates char *  matchfile  ) 
 

Definition at line 1258 of file be_ai_chat.c.

References bot_matchtemplate_t, BOTFILESBASEFOLDER, BotFreeMatchTemplates(), botimport, BotLoadMatchPieces(), bot_matchtemplate_s::context, bot_matchtemplate_s::first, FreeSource(), GetClearedHunkMemory(), token_s::intvalue, LoadSourceFile(), bot_matchtemplate_s::next, PC_ExpectTokenString(), PC_ExpectTokenType(), PC_ReadToken(), PC_SetBaseFolder(), PC_UnreadLastToken(), PRT_ERROR, PRT_MESSAGE, source, source_t, SourceError(), strcmp(), token_s::string, bot_matchtemplate_s::subtype, token_s::subtype, token, token_t, TT_INTEGER, TT_NUMBER, bot_matchtemplate_s::type, and token_s::type.

Referenced by BotSetupChatAI().

01259 {
01260     source_t *source;
01261     token_t token;
01262     bot_matchtemplate_t *matchtemplate, *matches, *lastmatch;
01263     unsigned long int context;
01264 
01265     PC_SetBaseFolder(BOTFILESBASEFOLDER);
01266     source = LoadSourceFile(matchfile);
01267     if (!source)
01268     {
01269         botimport.Print(PRT_ERROR, "counldn't load %s\n", matchfile);
01270         return NULL;
01271     } //end if
01272     //
01273     matches = NULL; //list with matches
01274     lastmatch = NULL; //last match in the list
01275 
01276     while(PC_ReadToken(source, &token))
01277     {
01278         if (token.type != TT_NUMBER || !(token.subtype & TT_INTEGER))
01279         {
01280             SourceError(source, "expected integer, found %s\n", token.string);
01281             BotFreeMatchTemplates(matches);
01282             FreeSource(source);
01283             return NULL;
01284         } //end if
01285         //the context
01286         context = token.intvalue;
01287         //
01288         if (!PC_ExpectTokenString(source, "{"))
01289         {
01290             BotFreeMatchTemplates(matches);
01291             FreeSource(source);
01292             return NULL;
01293         } //end if
01294         //
01295         while(PC_ReadToken(source, &token))
01296         {
01297             if (!strcmp(token.string, "}")) break;
01298             //
01299             PC_UnreadLastToken(source);
01300             //
01301             matchtemplate = (bot_matchtemplate_t *) GetClearedHunkMemory(sizeof(bot_matchtemplate_t));
01302             matchtemplate->context = context;
01303             matchtemplate->next = NULL;
01304             //add the match template to the list
01305             if (lastmatch) lastmatch->next = matchtemplate;
01306             else matches = matchtemplate;
01307             lastmatch = matchtemplate;
01308             //load the match template
01309             matchtemplate->first = BotLoadMatchPieces(source, "=");
01310             if (!matchtemplate->first)
01311             {
01312                 BotFreeMatchTemplates(matches);
01313                 return NULL;
01314             } //end if
01315             //read the match type
01316             if (!PC_ExpectTokenString(source, "(") ||
01317                 !PC_ExpectTokenType(source, TT_NUMBER, TT_INTEGER, &token))
01318             {
01319                 BotFreeMatchTemplates(matches);
01320                 FreeSource(source);
01321                 return NULL;
01322             } //end if
01323             matchtemplate->type = token.intvalue;
01324             //read the match subtype
01325             if (!PC_ExpectTokenString(source, ",") ||
01326                 !PC_ExpectTokenType(source, TT_NUMBER, TT_INTEGER, &token))
01327             {
01328                 BotFreeMatchTemplates(matches);
01329                 FreeSource(source);
01330                 return NULL;
01331             } //end if
01332             matchtemplate->subtype = token.intvalue;
01333             //read trailing punctuations
01334             if (!PC_ExpectTokenString(source, ")") ||
01335                 !PC_ExpectTokenString(source, ";"))
01336             {
01337                 BotFreeMatchTemplates(matches);
01338                 FreeSource(source);
01339                 return NULL;
01340             } //end if
01341         } //end while
01342     } //end while
01343     //free the source
01344     FreeSource(source);
01345     botimport.Print(PRT_MESSAGE, "loaded %s\n", matchfile);
01346     //
01347     //BotDumpMatchTemplates(matches);
01348     //
01349     return matches;
01350 } //end of the function BotLoadMatchTemplates

Here is the call graph for this function:

bot_randomlist_t* BotLoadRandomStrings char *  filename  ) 
 

Definition at line 946 of file be_ai_chat.c.

References bot_randomlist_t, bot_randomstring_t, BOTFILESBASEFOLDER, botimport, BotLoadChatMessage(), bot_randomlist_s::firstrandomstring, FreeSource(), GetClearedHunkMemory(), LoadSourceFile(), bot_randomstring_s::next, bot_randomlist_s::next, bot_randomlist_s::numstrings, PC_CheckTokenString(), PC_ExpectTokenString(), PC_ReadToken(), PC_SetBaseFolder(), PRT_ERROR, PRT_MESSAGE, ptr(), random, source, source_t, SourceError(), strcpy(), bot_randomstring_s::string, bot_randomlist_s::string, token_s::string, strlen(), Sys_MilliSeconds(), token, token_t, and token_s::type.

Referenced by BotSetupChatAI().

00947 {
00948     int pass, size;
00949     char *ptr = NULL, chatmessagestring[MAX_MESSAGE_SIZE];
00950     source_t *source;
00951     token_t token;
00952     bot_randomlist_t *randomlist, *lastrandom, *random;
00953     bot_randomstring_t *randomstring;
00954 
00955 #ifdef DEBUG
00956     int starttime = Sys_MilliSeconds();
00957 #endif //DEBUG
00958 
00959     size = 0;
00960     randomlist = NULL;
00961     random = NULL;
00962     //the synonyms are parsed in two phases
00963     for (pass = 0; pass < 2; pass++)
00964     {
00965         //
00966         if (pass && size) ptr = (char *) GetClearedHunkMemory(size);
00967         //
00968         PC_SetBaseFolder(BOTFILESBASEFOLDER);
00969         source = LoadSourceFile(filename);
00970         if (!source)
00971         {
00972             botimport.Print(PRT_ERROR, "counldn't load %s\n", filename);
00973             return NULL;
00974         } //end if
00975         //
00976         randomlist = NULL; //list
00977         lastrandom = NULL; //last
00978         //
00979         while(PC_ReadToken(source, &token))
00980         {
00981             if (token.type != TT_NAME)
00982             {
00983                 SourceError(source, "unknown random %s", token.string);
00984                 FreeSource(source);
00985                 return NULL;
00986             } //end if
00987             size += sizeof(bot_randomlist_t) + strlen(token.string) + 1;
00988             if (pass)
00989             {
00990                 random = (bot_randomlist_t *) ptr;
00991                 ptr += sizeof(bot_randomlist_t);
00992                 random->string = ptr;
00993                 ptr += strlen(token.string) + 1;
00994                 strcpy(random->string, token.string);
00995                 random->firstrandomstring = NULL;
00996                 random->numstrings = 0;
00997                 //
00998                 if (lastrandom) lastrandom->next = random;
00999                 else randomlist = random;
01000                 lastrandom = random;
01001             } //end if
01002             if (!PC_ExpectTokenString(source, "=") ||
01003                 !PC_ExpectTokenString(source, "{"))
01004             {
01005                 FreeSource(source);
01006                 return NULL;
01007             } //end if
01008             while(!PC_CheckTokenString(source, "}"))
01009             {
01010                 if (!BotLoadChatMessage(source, chatmessagestring))
01011                 {
01012                     FreeSource(source);
01013                     return NULL;
01014                 } //end if
01015                 size += sizeof(bot_randomstring_t) + strlen(chatmessagestring) + 1;
01016                 if (pass)
01017                 {
01018                     randomstring = (bot_randomstring_t *) ptr;
01019                     ptr += sizeof(bot_randomstring_t);
01020                     randomstring->string = ptr;
01021                     ptr += strlen(chatmessagestring) + 1;
01022                     strcpy(randomstring->string, chatmessagestring);
01023                     //
01024                     random->numstrings++;
01025                     randomstring->next = random->firstrandomstring;
01026                     random->firstrandomstring = randomstring;
01027                 } //end if
01028             } //end while
01029         } //end while
01030         //free the source after one pass
01031         FreeSource(source);
01032     } //end for
01033     botimport.Print(PRT_MESSAGE, "loaded %s\n", filename);
01034     //
01035 #ifdef DEBUG
01036     botimport.Print(PRT_MESSAGE, "random strings %d msec\n", Sys_MilliSeconds() - starttime);
01037     //BotDumpRandomStringList(randomlist);
01038 #endif //DEBUG
01039     //
01040     return randomlist;
01041 } //end of the function BotLoadRandomStrings

Here is the call graph for this function:

bot_replychat_t* BotLoadReplyChat char *  filename  ) 
 

Definition at line 1828 of file be_ai_chat.c.

References bot_chatmessage_t, bot_replychat_t, bot_replychatkey_t, BotCheckReplyChatIntegrety(), BotCheckValidReplyChatKeySet(), BOTFILESBASEFOLDER, BotFreeReplyChat(), botimport, BotLoadChatMessage(), BotLoadMatchPieces(), bot_chatmessage_s::chatmessage, bot_replychat_s::firstchatmessage, bot_replychatkey_s::flags, token_s::floatvalue, FreeSource(), GetClearedHunkMemory(), bot_replychat_s::keys, LoadSourceFile(), bot_replychatkey_s::match, bot_chatmessage_s::next, bot_replychatkey_s::next, bot_replychat_s::next, bot_replychat_s::numchatmessages, PC_CheckTokenString(), PC_ExpectTokenString(), PC_ExpectTokenType(), PC_ReadToken(), PC_SetBaseFolder(), bot_replychat_s::priority, PRT_ERROR, PRT_MESSAGE, source, source_t, SourceError(), strcat(), strcmp(), strcpy(), bot_replychatkey_s::string, token_s::string, StripDoubleQuotes(), strlen(), bot_chatmessage_s::time, token, token_t, TT_NUMBER, and TT_STRING.

Referenced by BotSetupChatAI().

01829 {
01830     char chatmessagestring[MAX_MESSAGE_SIZE];
01831     char namebuffer[MAX_MESSAGE_SIZE];
01832     source_t *source;
01833     token_t token;
01834     bot_chatmessage_t *chatmessage = NULL;
01835     bot_replychat_t *replychat, *replychatlist;
01836     bot_replychatkey_t *key;
01837 
01838     PC_SetBaseFolder(BOTFILESBASEFOLDER);
01839     source = LoadSourceFile(filename);
01840     if (!source)
01841     {
01842         botimport.Print(PRT_ERROR, "counldn't load %s\n", filename);
01843         return NULL;
01844     } //end if
01845     //
01846     replychatlist = NULL;
01847     //
01848     while(PC_ReadToken(source, &token))
01849     {
01850         if (strcmp(token.string, "["))
01851         {
01852             SourceError(source, "expected [, found %s", token.string);
01853             BotFreeReplyChat(replychatlist);
01854             FreeSource(source);
01855             return NULL;
01856         } //end if
01857         //
01858         replychat = GetClearedHunkMemory(sizeof(bot_replychat_t));
01859         replychat->keys = NULL;
01860         replychat->next = replychatlist;
01861         replychatlist = replychat;
01862         //read the keys, there must be at least one key
01863         do
01864         {
01865             //allocate a key
01866             key = (bot_replychatkey_t *) GetClearedHunkMemory(sizeof(bot_replychatkey_t));
01867             key->flags = 0;
01868             key->string = NULL;
01869             key->match = NULL;
01870             key->next = replychat->keys;
01871             replychat->keys = key;
01872             //check for MUST BE PRESENT and MUST BE ABSENT keys
01873             if (PC_CheckTokenString(source, "&")) key->flags |= RCKFL_AND;
01874             else if (PC_CheckTokenString(source, "!")) key->flags |= RCKFL_NOT;
01875             //special keys
01876             if (PC_CheckTokenString(source, "name")) key->flags |= RCKFL_NAME;
01877             else if (PC_CheckTokenString(source, "female")) key->flags |= RCKFL_GENDERFEMALE;
01878             else if (PC_CheckTokenString(source, "male")) key->flags |= RCKFL_GENDERMALE;
01879             else if (PC_CheckTokenString(source, "it")) key->flags |= RCKFL_GENDERLESS;
01880             else if (PC_CheckTokenString(source, "(")) //match key
01881             {
01882                 key->flags |= RCKFL_VARIABLES;
01883                 key->match = BotLoadMatchPieces(source, ")");
01884                 if (!key->match)
01885                 {
01886                     BotFreeReplyChat(replychatlist);
01887                     return NULL;
01888                 } //end if
01889             } //end else if
01890             else if (PC_CheckTokenString(source, "<")) //bot names
01891             {
01892                 key->flags |= RCKFL_BOTNAMES;
01893                 strcpy(namebuffer, "");
01894                 do
01895                 {
01896                     if (!PC_ExpectTokenType(source, TT_STRING, 0, &token))
01897                     {
01898                         BotFreeReplyChat(replychatlist);
01899                         FreeSource(source);
01900                         return NULL;
01901                     } //end if
01902                     StripDoubleQuotes(token.string);
01903                     if (strlen(namebuffer)) strcat(namebuffer, "\\");
01904                     strcat(namebuffer, token.string);
01905                 } while(PC_CheckTokenString(source, ","));
01906                 if (!PC_ExpectTokenString(source, ">"))
01907                 {
01908                     BotFreeReplyChat(replychatlist);
01909                     FreeSource(source);
01910                     return NULL;
01911                 } //end if
01912                 key->string = (char *) GetClearedHunkMemory(strlen(namebuffer) + 1);
01913                 strcpy(key->string, namebuffer);
01914             } //end else if
01915             else //normal string key
01916             {
01917                 key->flags |= RCKFL_STRING;
01918                 if (!PC_ExpectTokenType(source, TT_STRING, 0, &token))
01919                 {
01920                     BotFreeReplyChat(replychatlist);
01921                     FreeSource(source);
01922                     return NULL;
01923                 } //end if
01924                 StripDoubleQuotes(token.string);
01925                 key->string = (char *) GetClearedHunkMemory(strlen(token.string) + 1);
01926                 strcpy(key->string, token.string);
01927             } //end else
01928             //
01929             PC_CheckTokenString(source, ",");
01930         } while(!PC_CheckTokenString(source, "]"));
01931         //
01932         BotCheckValidReplyChatKeySet(source, replychat->keys);
01933         //read the = sign and the priority
01934         if (!PC_ExpectTokenString(source, "=") ||
01935             !PC_ExpectTokenType(source, TT_NUMBER, 0, &token))
01936         {
01937             BotFreeReplyChat(replychatlist);
01938             FreeSource(source);
01939             return NULL;
01940         } //end if
01941         replychat->priority = token.floatvalue;
01942         //read the leading {
01943         if (!PC_ExpectTokenString(source, "{"))
01944         {
01945             BotFreeReplyChat(replychatlist);
01946             FreeSource(source);
01947             return NULL;
01948         } //end if
01949         replychat->numchatmessages = 0;
01950         //while the trailing } is not found
01951         while(!PC_CheckTokenString(source, "}"))
01952         {
01953             if (!BotLoadChatMessage(source, chatmessagestring))
01954             {
01955                 BotFreeReplyChat(replychatlist);
01956                 FreeSource(source);
01957                 return NULL;
01958             } //end if
01959             chatmessage = (bot_chatmessage_t *) GetClearedHunkMemory(sizeof(bot_chatmessage_t) + strlen(chatmessagestring) + 1);
01960             chatmessage->chatmessage = (char *) chatmessage + sizeof(bot_chatmessage_t);
01961             strcpy(chatmessage->chatmessage, chatmessagestring);
01962             chatmessage->time = -2*CHATMESSAGE_RECENTTIME;
01963             chatmessage->next = replychat->firstchatmessage;
01964             //add the chat message to the reply chat
01965             replychat->firstchatmessage = chatmessage;
01966             replychat->numchatmessages++;
01967         } //end while
01968     } //end while
01969     FreeSource(source);
01970     botimport.Print(PRT_MESSAGE, "loaded %s\n", filename);
01971     //
01972     //BotDumpReplyChat(replychatlist);
01973     if (bot_developer)
01974     {
01975         BotCheckReplyChatIntegrety(replychatlist);
01976     } //end if
01977     //
01978     if (!replychatlist) botimport.Print(PRT_MESSAGE, "no rchats\n");
01979     //
01980     return replychatlist;
01981 } //end of the function BotLoadReplyChat

Here is the call graph for this function:

bot_synonymlist_t* BotLoadSynonyms char *  filename  ) 
 

Definition at line 595 of file be_ai_chat.c.

References bot_synonym_t, bot_synonymlist_t, BOTFILESBASEFOLDER, botimport, bot_synonymlist_s::context, bot_synonymlist_s::firstsynonym, token_s::floatvalue, FreeSource(), GetClearedHunkMemory(), token_s::intvalue, LoadSourceFile(), bot_synonym_s::next, bot_synonymlist_s::next, PC_CheckTokenString(), PC_ExpectTokenString(), PC_ExpectTokenType(), PC_ReadToken(), PC_SetBaseFolder(), PRT_ERROR, PRT_MESSAGE, ptr(), source, source_t, SourceError(), strcmp(), strcpy(), bot_synonym_s::string, token_s::string, StripDoubleQuotes(), strlen(), token, token_t, bot_synonymlist_s::totalweight, TT_NUMBER, TT_STRING, token_s::type, and bot_synonym_s::weight.

Referenced by BotSetupChatAI().

00596 {
00597     int pass, size, contextlevel, numsynonyms;
00598     unsigned long int context, contextstack[32];
00599     char *ptr = NULL;
00600     source_t *source;
00601     token_t token;
00602     bot_synonymlist_t *synlist, *lastsyn, *syn;
00603     bot_synonym_t *synonym, *lastsynonym;
00604 
00605     size = 0;
00606     synlist = NULL; //make compiler happy
00607     syn = NULL; //make compiler happy
00608     synonym = NULL; //make compiler happy
00609     //the synonyms are parsed in two phases
00610     for (pass = 0; pass < 2; pass++)
00611     {
00612         //
00613         if (pass && size) ptr = (char *) GetClearedHunkMemory(size);
00614         //
00615         PC_SetBaseFolder(BOTFILESBASEFOLDER);
00616         source = LoadSourceFile(filename);
00617         if (!source)
00618         {
00619             botimport.Print(PRT_ERROR, "counldn't load %s\n", filename);
00620             return NULL;
00621         } //end if
00622         //
00623         context = 0;
00624         contextlevel = 0;
00625         synlist = NULL; //list synonyms
00626         lastsyn = NULL; //last synonym in the list
00627         //
00628         while(PC_ReadToken(source, &token))
00629         {
00630             if (token.type == TT_NUMBER)
00631             {
00632                 context |= token.intvalue;
00633                 contextstack[contextlevel] = token.intvalue;
00634                 contextlevel++;
00635                 if (contextlevel >= 32)
00636                 {
00637                     SourceError(source, "more than 32 context levels");
00638                     FreeSource(source);
00639                     return NULL;
00640                 } //end if
00641                 if (!PC_ExpectTokenString(source, "{"))
00642                 {
00643                     FreeSource(source);
00644                     return NULL;
00645                 } //end if
00646             } //end if
00647             else if (token.type == TT_PUNCTUATION)
00648             {
00649                 if (!strcmp(token.string, "}"))
00650                 {
00651                     contextlevel--;
00652                     if (contextlevel < 0)
00653                     {
00654                         SourceError(source, "too many }");
00655                         FreeSource(source);
00656                         return NULL;
00657                     } //end if
00658                     context &= ~contextstack[contextlevel];
00659                 } //end if
00660                 else if (!strcmp(token.string, "["))
00661                 {
00662                     size += sizeof(bot_synonymlist_t);
00663                     if (pass)
00664                     {
00665                         syn = (bot_synonymlist_t *) ptr;
00666                         ptr += sizeof(bot_synonymlist_t);
00667                         syn->context = context;
00668                         syn->firstsynonym = NULL;
00669                         syn->next = NULL;
00670                         if (lastsyn) lastsyn->next = syn;
00671                         else synlist = syn;
00672                         lastsyn = syn;
00673                     } //end if
00674                     numsynonyms = 0;
00675                     lastsynonym = NULL;
00676                     while(1)
00677                     {
00678                         if (!PC_ExpectTokenString(source, "(") ||
00679                             !PC_ExpectTokenType(source, TT_STRING, 0, &token))
00680                         {
00681                             FreeSource(source);
00682                             return NULL;
00683                         } //end if
00684                         StripDoubleQuotes(token.string);
00685                         if (strlen(token.string) <= 0)
00686                         {
00687                             SourceError(source, "empty string", token.string);
00688                             FreeSource(source);
00689                             return NULL;
00690                         } //end if
00691                         size += sizeof(bot_synonym_t) + strlen(token.string) + 1;
00692                         if (pass)
00693                         {
00694                             synonym = (bot_synonym_t *) ptr;
00695                             ptr += sizeof(bot_synonym_t);
00696                             synonym->string = ptr;
00697                             ptr += strlen(token.string) + 1;
00698                             strcpy(synonym->string, token.string);
00699                             //
00700                             if (lastsynonym) lastsynonym->next = synonym;
00701                             else syn->firstsynonym = synonym;
00702                             lastsynonym = synonym;
00703                         } //end if
00704                         numsynonyms++;
00705                         if (!PC_ExpectTokenString(source, ",") ||
00706                             !PC_ExpectTokenType(source, TT_NUMBER, 0, &token) ||
00707                             !PC_ExpectTokenString(source, ")"))
00708                         {
00709                             FreeSource(source);
00710                             return NULL;
00711                         } //end if
00712                         if (pass)
00713                         {
00714                             synonym->weight = token.floatvalue;
00715                             syn->totalweight += synonym->weight;
00716                         } //end if
00717                         if (PC_CheckTokenString(source, "]")) break;
00718                         if (!PC_ExpectTokenString(source, ","))
00719                         {
00720                             FreeSource(source);
00721                             return NULL;
00722                         } //end if
00723                     } //end while
00724                     if (numsynonyms < 2)
00725                     {
00726                         SourceError(source, "synonym must have at least two entries\n");
00727                         FreeSource(source);
00728                         return NULL;
00729                     } //end if
00730                 } //end else
00731                 else
00732                 {
00733                     SourceError(source, "unexpected %s", token.string);
00734                     FreeSource(source);
00735                     return NULL;
00736                 } //end if
00737             } //end else if
00738         } //end while
00739         //
00740         FreeSource(source);
00741         //
00742         if (contextlevel > 0)
00743         {
00744             SourceError(source, "missing }");
00745             return NULL;
00746         } //end if
00747     } //end for
00748     botimport.Print(PRT_MESSAGE, "loaded %s\n", filename);
00749     //
00750     //BotDumpSynonymList(synlist);
00751     //
00752     return synlist;
00753 } //end of the function BotLoadSynonyms

Here is the call graph for this function:

void BotMatchVariable bot_match_t match,
int  variable,
char *  buf,
int  size
 

Definition at line 1468 of file be_ai_chat.c.

References assert, bot_match_t, botimport, bot_matchvariable_s::length, match(), bot_matchvariable_s::offset, PRT_FATAL, strcpy(), bot_match_s::string, strncpy(), and bot_match_s::variables.

01469 {
01470     if (variable < 0 || variable >= MAX_MATCHVARIABLES)
01471     {
01472         botimport.Print(PRT_FATAL, "BotMatchVariable: variable out of range\n");
01473         strcpy(buf, "");
01474         return;
01475     } //end if
01476 
01477     if (match->variables[variable].offset >= 0)
01478     {
01479         if (match->variables[variable].length < size)
01480             size = match->variables[variable].length+1;
01481         assert( match->variables[variable].offset >= 0 ); // bk001204
01482         strncpy(buf, &match->string[ (int) match->variables[variable].offset], size-1);
01483         buf[size-1] = '\0';
01484     } //end if
01485     else
01486     {
01487         strcpy(buf, "");
01488     } //end else
01489     return;
01490 } //end of the function BotMatchVariable

Here is the call graph for this function:

int BotNextConsoleMessage int  chatstate,
bot_consolemessage_t cm
 

Definition at line 367 of file be_ai_chat.c.

References bot_chatstate_t, bot_consolemessage_t, BotChatStateFromHandle(), cm, Com_Memcpy(), and bot_chatstate_s::firstmessage.

Referenced by BotFreeChatState().

00368 {
00369     bot_chatstate_t *cs;
00370 
00371     cs = BotChatStateFromHandle(chatstate);
00372     if (!cs) return 0;
00373     if (cs->firstmessage)
00374     {
00375         Com_Memcpy(cm, cs->firstmessage, sizeof(bot_consolemessage_t));
00376         cm->next = cm->prev = NULL;
00377         return cm->handle;
00378     } //end if
00379     return 0;
00380 } //end of the function BotConsoleMessage

Here is the call graph for this function:

int BotNumConsoleMessages int  chatstate  ) 
 

Definition at line 387 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), and bot_chatstate_s::numconsolemessages.

00388 {
00389     bot_chatstate_t *cs;
00390 
00391     cs = BotChatStateFromHandle(chatstate);
00392     if (!cs) return 0;
00393     return cs->numconsolemessages;
00394 } //end of the function BotNumConsoleMessages

Here is the call graph for this function:

int BotNumInitialChats int  chatstate,
char *  type
 

Definition at line 2465 of file be_ai_chat.c.

References bot_chatstate_t, bot_chattype_t, BotChatStateFromHandle(), botimport, bot_chatstate_s::chat, LibVarGetValue(), bot_chattype_s::name, bot_chattype_s::next, bot_chattype_s::numchatmessages, PRT_MESSAGE, Q_stricmp(), t, type, and bot_chat_s::types.

02466 {
02467     bot_chatstate_t *cs;
02468     bot_chattype_t *t;
02469 
02470     cs = BotChatStateFromHandle(chatstate);
02471     if (!cs) return 0;
02472 
02473     for (t = cs->chat->types; t; t = t->next)
02474     {
02475         if (!Q_stricmp(t->name, type))
02476         {
02477             if (LibVarGetValue("bot_testichat")) {
02478                 botimport.Print(PRT_MESSAGE, "%s has %d chat lines\n", type, t->numchatmessages);
02479                 botimport.Print(PRT_MESSAGE, "-------------------\n");
02480             }
02481             return t->numchatmessages;
02482         } //end if
02483     } //end for
02484     return 0;
02485 } //end of the function BotNumInitialChats

Here is the call graph for this function:

void BotPrintReplyChatKeys bot_replychat_t replychat  ) 
 

Definition at line 2573 of file be_ai_chat.c.

References bot_matchpiece_t, bot_replychat_t, bot_replychatkey_t, botimport, bot_matchpiece_s::firststring, bot_replychatkey_s::flags, bot_replychat_s::keys, bot_replychatkey_s::match, bot_matchpiece_s::next, bot_replychatkey_s::next, bot_replychat_s::priority, PRT_MESSAGE, bot_replychatkey_s::string, bot_matchstring_s::string, bot_matchpiece_s::type, and bot_matchpiece_s::variable.

02574 {
02575     bot_replychatkey_t *key;
02576     bot_matchpiece_t *mp;
02577 
02578     botimport.Print(PRT_MESSAGE, "[");
02579     for (key = replychat->keys; key; key = key->next)
02580     {
02581         if (key->flags & RCKFL_AND) botimport.Print(PRT_MESSAGE, "&");
02582         else if (key->flags & RCKFL_NOT) botimport.Print(PRT_MESSAGE, "!");
02583         //
02584         if (key->flags & RCKFL_NAME) botimport.Print(PRT_MESSAGE, "name");
02585         else if (key->flags & RCKFL_GENDERFEMALE) botimport.Print(PRT_MESSAGE, "female");
02586         else if (key->flags & RCKFL_GENDERMALE) botimport.Print(PRT_MESSAGE, "male");
02587         else if (key->flags & RCKFL_GENDERLESS) botimport.Print(PRT_MESSAGE, "it");
02588         else if (key->flags & RCKFL_VARIABLES)
02589         {
02590             botimport.Print(PRT_MESSAGE, "(");
02591             for (mp = key->match; mp; mp = mp->next)
02592             {
02593                 if (mp->type == MT_STRING) botimport.Print(PRT_MESSAGE, "\"%s\"", mp->firststring->string);
02594                 else botimport.Print(PRT_MESSAGE, "%d", mp->variable);
02595                 if (mp->next) botimport.Print(PRT_MESSAGE, ", ");
02596             } //end for
02597             botimport.Print(PRT_MESSAGE, ")");
02598         } //end if
02599         else if (key->flags & RCKFL_STRING)
02600         {
02601             botimport.Print(PRT_MESSAGE, "\"%s\"", key->string);
02602         } //end if
02603         if (key->next) botimport.Print(PRT_MESSAGE, ", ");
02604         else botimport.Print(PRT_MESSAGE, "] = %1.0f\n", replychat->priority);
02605     } //end for
02606     botimport.Print(PRT_MESSAGE, "{\n");
02607 } //end of the function BotPrintReplyChatKeys

void BotQueueConsoleMessage int  chatstate,
int  type,
char *  message
 

Definition at line 326 of file be_ai_chat.c.

References AAS_Time(), AllocConsoleMessage(), bot_chatstate_t, bot_consolemessage_t, BotChatStateFromHandle(), botimport, bot_chatstate_s::firstmessage, bot_chatstate_s::handle, bot_consolemessage_s::handle, bot_chatstate_s::lastmessage, m, MAX_MESSAGE_SIZE, bot_consolemessage_s::message, bot_consolemessage_s::next, bot_chatstate_s::numconsolemessages, bot_consolemessage_s::prev, PRT_ERROR, strncpy(), bot_consolemessage_s::time, and bot_consolemessage_s::type.

00327 {
00328     bot_consolemessage_t *m;
00329     bot_chatstate_t *cs;
00330 
00331     cs = BotChatStateFromHandle(chatstate);
00332     if (!cs) return;
00333 
00334     m = AllocConsoleMessage();
00335     if (!m)
00336     {
00337         botimport.Print(PRT_ERROR, "empty console message heap\n");
00338         return;
00339     } //end if
00340     cs->handle++;
00341     if (cs->handle <= 0 || cs->handle > 8192) cs->handle = 1;
00342     m->handle = cs->handle;
00343     m->time = AAS_Time();
00344     m->type = type;
00345     strncpy(m->message, message, MAX_MESSAGE_SIZE);
00346     m->next = NULL;
00347     if (cs->lastmessage)
00348     {
00349         cs->lastmessage->next = m;
00350         m->prev = cs->lastmessage;
00351         cs->lastmessage = m;
00352     } //end if
00353     else
00354     {
00355         cs->lastmessage = m;
00356         cs->firstmessage = m;
00357         m->prev = NULL;
00358     } //end if
00359     cs->numconsolemessages++;
00360 } //end of the function BotQueueConsoleMessage

Here is the call graph for this function:

void BotRemoveConsoleMessage int  chatstate,
int  handle
 

Definition at line 296 of file be_ai_chat.c.

References bot_chatstate_t, bot_consolemessage_t, BotChatStateFromHandle(), bot_chatstate_s::firstmessage, FreeConsoleMessage(), bot_consolemessage_s::handle, bot_chatstate_s::lastmessage, m, bot_consolemessage_s::next, bot_chatstate_s::numconsolemessages, and bot_consolemessage_s::prev.

Referenced by BotFreeChatState().

00297 {
00298     bot_consolemessage_t *m, *nextm;
00299     bot_chatstate_t *cs;
00300 
00301     cs = BotChatStateFromHandle(chatstate);
00302     if (!cs) return;
00303 
00304     for (m = cs->firstmessage; m; m = nextm)
00305     {
00306         nextm = m->next;
00307         if (m->handle == handle)
00308         {
00309             if (m->next) m->next->prev = m->prev;
00310             else cs->lastmessage = m->prev;
00311             if (m->prev) m->prev->next = m->next;
00312             else cs->firstmessage = m->next;
00313 
00314             FreeConsoleMessage(m);
00315             cs->numconsolemessages--;
00316             break;
00317         } //end if
00318     } //end for
00319 } //end of the function BotRemoveConsoleMessage

Here is the call graph for this function:

void BotRemoveTildes char *  message  ) 
 

Definition at line 421 of file be_ai_chat.c.

References i, memmove(), and strlen().

Referenced by BotEnterChat(), BotGetChatMessage(), and BotReplyChat().

00422 {
00423     int i;
00424 
00425     //remove all tildes from the chat message
00426     for (i = 0; message[i]; i++)
00427     {
00428         if (message[i] == '~')
00429         {
00430             memmove(&message[i], &message[i+1], strlen(&message[i+1])+1);
00431         } //end if
00432     } //end for
00433 } //end of the function BotRemoveTildes

Here is the call graph for this function:

void BotReplaceReplySynonyms char *  string,
unsigned long int  context
 

Definition at line 814 of file be_ai_chat.c.

References bot_synonym_t, bot_synonymlist_t, Com_Memcpy(), bot_synonymlist_s::context, bot_synonymlist_s::firstsynonym, memmove(), bot_synonym_s::next, bot_synonymlist_s::next, qfalse, bot_synonym_s::string, StringContainsWord(), and strlen().

Referenced by BotExpandChatMessage().

00815 {
00816     char *str1, *str2, *replacement;
00817     bot_synonymlist_t *syn;
00818     bot_synonym_t *synonym;
00819 
00820     for (str1 = string; *str1; )
00821     {
00822         //go to the start of the next word
00823         while(*str1 && *str1 <= ' ') str1++;
00824         if (!*str1) break;
00825         //
00826         for (syn = synonyms; syn; syn = syn->next)
00827         {
00828             if (!(syn->context & context)) continue;
00829             for (synonym = syn->firstsynonym->next; synonym; synonym = synonym->next)
00830             {
00831                 str2 = synonym->string;
00832                 //if the synonym is not at the front of the string continue
00833                 str2 = StringContainsWord(str1, synonym->string, qfalse);
00834                 if (!str2 || str2 != str1) continue;
00835                 //
00836                 replacement = syn->firstsynonym->string;
00837                 //if the replacement IS in front of the string continue
00838                 str2 = StringContainsWord(str1, replacement, qfalse);
00839                 if (str2 && str2 == str1) continue;
00840                 //
00841                 memmove(str1 + strlen(replacement), str1+strlen(synonym->string),
00842                             strlen(str1+strlen(synonym->string)) + 1);
00843                 //append the synonum replacement
00844                 Com_Memcpy(str1, replacement, strlen(replacement));
00845                 //
00846                 break;
00847             } //end for
00848             //if a synonym has been replaced
00849             if (synonym) break;
00850         } //end for
00851         //skip over this word
00852         while(*str1 && *str1 > ' ') str1++;
00853         if (!*str1) break;
00854     } //end while
00855 } //end of the function BotReplaceReplySynonyms

Here is the call graph for this function:

void BotReplaceSynonyms char *  string,
unsigned long int  context
 

Definition at line 761 of file be_ai_chat.c.

References bot_synonym_t, bot_synonymlist_t, bot_synonymlist_s::context, bot_synonymlist_s::firstsynonym, bot_synonymlist_s::next, bot_synonym_s::next, string(), bot_synonym_s::string, and StringReplaceWords().

Referenced by BotExpandChatMessage().

00762 {
00763     bot_synonymlist_t *syn;
00764     bot_synonym_t *synonym;
00765 
00766     for (syn = synonyms; syn; syn = syn->next)
00767     {
00768         if (!(syn->context & context)) continue;
00769         for (synonym = syn->firstsynonym->next; synonym; synonym = synonym->next)
00770         {
00771             StringReplaceWords(string, synonym->string, syn->firstsynonym->string);
00772         } //end for
00773     } //end for
00774 } //end of the function BotReplaceSynonyms

Here is the call graph for this function:

void BotReplaceWeightedSynonyms char *  string,
unsigned long int  context
 

Definition at line 781 of file be_ai_chat.c.

References bot_synonym_t, bot_synonymlist_t, bot_synonymlist_s::context, bot_synonymlist_s::firstsynonym, bot_synonym_s::next, bot_synonymlist_s::next, random, bot_synonym_s::string, string(), StringReplaceWords(), bot_synonymlist_s::totalweight, and bot_synonym_s::weight.

Referenced by BotExpandChatMessage().

00782 {
00783     bot_synonymlist_t *syn;
00784     bot_synonym_t *synonym, *replacement;
00785     float weight, curweight;
00786 
00787     for (syn = synonyms; syn; syn = syn->next)
00788     {
00789         if (!(syn->context & context)) continue;
00790         //choose a weighted random replacement synonym
00791         weight = random() * syn->totalweight;
00792         if (!weight) continue;
00793         curweight = 0;
00794         for (replacement = syn->firstsynonym; replacement; replacement = replacement->next)
00795         {
00796             curweight += replacement->weight;
00797             if (weight < curweight) break;
00798         } //end for
00799         if (!replacement) continue;
00800         //replace all synonyms with the replacement
00801         for (synonym = syn->firstsynonym; synonym; synonym = synonym->next)
00802         {
00803             if (synonym == replacement) continue;
00804             StringReplaceWords(string, synonym->string, replacement->string);
00805         } //end for
00806     } //end for
00807 } //end of the function BotReplaceWeightedSynonyms

Here is the call graph for this function:

int BotReplyChat int  chatstate,
char *  message,
int  mcontext,
int  vcontext,
char *  var0,
char *  var1,
char *  var2,
char *  var3,
char *  var4,
char *  var5,
char *  var6,
char *  var7
 

Definition at line 2614 of file be_ai_chat.c.

References AAS_Time(), bot_chatmessage_t, bot_chatstate_t, bot_match_t, bot_replychat_t, bot_replychatkey_t, BotChatStateFromHandle(), BotConstructChatMessage(), botimport, BotRemoveTildes(), bot_chatmessage_s::chatmessage, bot_chatstate_s::chatmessage, Com_Memcpy(), Com_Memset(), bot_replychat_s::firstchatmessage, bot_replychatkey_s::flags, bot_chatstate_s::gender, bot_replychat_s::keys, bot_matchvariable_s::length, LibVarGetValue(), m, match(), bot_replychatkey_s::match, bot_chatstate_s::name, bot_replychat_s::next, bot_replychatkey_s::next, bot_chatmessage_s::next, bot_matchvariable_s::offset, bot_replychat_s::priority, PRT_MESSAGE, qfalse, qtrue, random, strcat(), strcpy(), bot_match_s::string, bot_replychatkey_s::string, StringContains(), StringContainsWord(), StringsMatch(), strlen(), bot_chatmessage_s::time, and bot_match_s::variables.

02615 {
02616     bot_replychat_t *rchat, *bestrchat;
02617     bot_replychatkey_t *key;
02618     bot_chatmessage_t *m, *bestchatmessage;
02619     bot_match_t match, bestmatch;
02620     int bestpriority, num, found, res, numchatmessages, index;
02621     bot_chatstate_t *cs;
02622 
02623     cs = BotChatStateFromHandle(chatstate);
02624     if (!cs) return qfalse;
02625     Com_Memset(&match, 0, sizeof(bot_match_t));
02626     strcpy(match.string, message);
02627     bestpriority = -1;
02628     bestchatmessage = NULL;
02629     bestrchat = NULL;
02630     //go through all the reply chats
02631     for (rchat = replychats; rchat; rchat = rchat->next)
02632     {
02633         found = qfalse;
02634         for (key = rchat->keys; key; key = key->next)
02635         {
02636             res = qfalse;
02637             //get the match result
02638             if (key->flags & RCKFL_NAME) res = (StringContains(message, cs->name, qfalse) != -1);
02639             else if (key->flags & RCKFL_BOTNAMES) res = (StringContains(key->string, cs->name, qfalse) != -1);
02640             else if (key->flags & RCKFL_GENDERFEMALE) res = (cs->gender == CHAT_GENDERFEMALE);
02641             else if (key->flags & RCKFL_GENDERMALE) res = (cs->gender == CHAT_GENDERMALE);
02642             else if (key->flags & RCKFL_GENDERLESS) res = (cs->gender == CHAT_GENDERLESS);
02643             else if (key->flags & RCKFL_VARIABLES) res = StringsMatch(key->match, &match);
02644             else if (key->flags & RCKFL_STRING) res = (StringContainsWord(message, key->string, qfalse) != NULL);
02645             //if the key must be present
02646             if (key->flags & RCKFL_AND)
02647             {
02648                 if (!res)
02649                 {
02650                     found = qfalse;
02651                     break;
02652                 } //end if
02653             } //end else if
02654             //if the key must be absent
02655             else if (key->flags & RCKFL_NOT)
02656             {
02657                 if (res)
02658                 {
02659                     found = qfalse;
02660                     break;
02661                 } //end if
02662             } //end if
02663             else if (res)
02664             {
02665                 found = qtrue;
02666             } //end else
02667         } //end for
02668         //
02669         if (found)
02670         {
02671             if (rchat->priority > bestpriority)
02672             {
02673                 numchatmessages = 0;
02674                 for (m = rchat->firstchatmessage; m; m = m->next)
02675                 {
02676                     if (m->time > AAS_Time()) continue;
02677                     numchatmessages++;
02678                 } //end if
02679                 num = random() * numchatmessages;
02680                 for (m = rchat->firstchatmessage; m; m = m->next)
02681                 {
02682                     if (--num < 0) break;
02683                     if (m->time > AAS_Time()) continue;
02684                 } //end for
02685                 //if the reply chat has a message
02686                 if (m)
02687                 {
02688                     Com_Memcpy(&bestmatch, &match, sizeof(bot_match_t));
02689                     bestchatmessage = m;
02690                     bestrchat = rchat;
02691                     bestpriority = rchat->priority;
02692                 } //end if
02693             } //end if
02694         } //end if
02695     } //end for
02696     if (bestchatmessage)
02697     {
02698         index = strlen(bestmatch.string);
02699         if( var0 ) {
02700             strcat(bestmatch.string, var0);
02701             bestmatch.variables[0].offset = index;
02702             bestmatch.variables[0].length = strlen(var0);
02703             index += strlen(var0);
02704         }
02705         if( var1 ) {
02706             strcat(bestmatch.string, var1);
02707             bestmatch.variables[1].offset = index;
02708             bestmatch.variables[1].length = strlen(var1);
02709             index += strlen(var1);
02710         }
02711         if( var2 ) {
02712             strcat(bestmatch.string, var2);
02713             bestmatch.variables[2].offset = index;
02714             bestmatch.variables[2].length = strlen(var2);
02715             index += strlen(var2);
02716         }
02717         if( var3 ) {
02718             strcat(bestmatch.string, var3);
02719             bestmatch.variables[3].offset = index;
02720             bestmatch.variables[3].length = strlen(var3);
02721             index += strlen(var3);
02722         }
02723         if( var4 ) {
02724             strcat(bestmatch.string, var4);
02725             bestmatch.variables[4].offset = index;
02726             bestmatch.variables[4].length = strlen(var4);
02727             index += strlen(var4);
02728         }
02729         if( var5 ) {
02730             strcat(bestmatch.string, var5);
02731             bestmatch.variables[5].offset = index;
02732             bestmatch.variables[5].length = strlen(var5);
02733             index += strlen(var5);
02734         }
02735         if( var6 ) {
02736             strcat(bestmatch.string, var6);
02737             bestmatch.variables[6].offset = index;
02738             bestmatch.variables[6].length = strlen(var6);
02739             index += strlen(var6);
02740         }
02741         if( var7 ) {
02742             strcat(bestmatch.string, var7);
02743             bestmatch.variables[7].offset = index;
02744             bestmatch.variables[7].length = strlen(var7);
02745             index += strlen(var7);
02746         }
02747         if (LibVarGetValue("bot_testrchat"))
02748         {
02749             for (m = bestrchat->firstchatmessage; m; m = m->next)
02750             {
02751                 BotConstructChatMessage(cs, m->chatmessage, mcontext, &bestmatch, vcontext, qtrue);
02752                 BotRemoveTildes(cs->chatmessage);
02753                 botimport.Print(PRT_MESSAGE, "%s\n", cs->chatmessage);
02754             } //end if
02755         } //end if
02756         else
02757         {
02758             bestchatmessage->time = AAS_Time() + CHATMESSAGE_RECENTTIME;
02759             BotConstructChatMessage(cs, bestchatmessage->chatmessage, mcontext, &bestmatch, vcontext, qtrue);
02760         } //end else
02761         return qtrue;
02762     } //end if
02763     return qfalse;
02764 } //end of the function BotReplyChat

Here is the call graph for this function:

void BotResetChatAI void   ) 
 

Definition at line 2876 of file be_ai_chat.c.

References bot_chatmessage_t, bot_replychat_t, bot_replychat_s::firstchatmessage, m, bot_chatmessage_s::next, bot_replychat_s::next, and bot_chatmessage_s::time.

02877 {
02878     bot_replychat_t *rchat;
02879     bot_chatmessage_t *m;
02880 
02881     for (rchat = replychats; rchat; rchat = rchat->next)
02882     {
02883         for (m = rchat->firstchatmessage; m; m = m->next)
02884         {
02885             m->time = 0;
02886         } //end for
02887     } //end for
02888 } //end of the function BotResetChatAI

void BotSetChatGender int  chatstate,
int  gender
 

Definition at line 2840 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), CHAT_GENDERFEMALE, CHAT_GENDERMALE, and bot_chatstate_s::gender.

02841 {
02842     bot_chatstate_t *cs;
02843 
02844     cs = BotChatStateFromHandle(chatstate);
02845     if (!cs) return;
02846     switch(gender)
02847     {
02848         case CHAT_GENDERFEMALE: cs->gender = CHAT_GENDERFEMALE; break;
02849         case CHAT_GENDERMALE: cs->gender = CHAT_GENDERMALE; break;
02850         default: cs->gender = CHAT_GENDERLESS; break;
02851     } //end switch
02852 } //end of the function BotSetChatGender

Here is the call graph for this function:

void BotSetChatName int  chatstate,
char *  name,
int  client
 

Definition at line 2859 of file be_ai_chat.c.

References bot_chatstate_t, BotChatStateFromHandle(), bot_chatstate_s::client, Com_Memset(), bot_chatstate_s::name, name, and strncpy().

02860 {
02861     bot_chatstate_t *cs;
02862 
02863     cs = BotChatStateFromHandle(chatstate);
02864     if (!cs) return;
02865     cs->client = client;
02866     Com_Memset(cs->name, 0, sizeof(cs->name));
02867     strncpy(cs->name, name, sizeof(cs->name));
02868     cs->name[sizeof(cs->name)-1] = '\0';
02869 } //end of the function BotSetChatName

Here is the call graph for this function:

int BotSetupChatAI void   ) 
 

Definition at line 2951 of file be_ai_chat.c.

References botimport, BotLoadMatchTemplates(), BotLoadRandomStrings(), BotLoadReplyChat(), BotLoadSynonyms(), file, InitConsoleMessageHeap(), LibVarString(), LibVarValue(), matchtemplates, PRT_MESSAGE, randomstrings, replychats, synonyms, and Sys_MilliSeconds().

Referenced by Export_BotLibSetup().

02952 {
02953     char *file;
02954 
02955 #ifdef DEBUG
02956     int starttime = Sys_MilliSeconds();
02957 #endif //DEBUG
02958 
02959     file = LibVarString("synfile", "syn.c");
02960     synonyms = BotLoadSynonyms(file);
02961     file = LibVarString("rndfile", "rnd.c");
02962     randomstrings = BotLoadRandomStrings(file);
02963     file = LibVarString("matchfile", "match.c");
02964     matchtemplates = BotLoadMatchTemplates(file);
02965     //
02966     if (!LibVarValue("nochat", "0"))
02967     {
02968         file = LibVarString("rchatfile", "rchat.c");
02969         replychats = BotLoadReplyChat(file);
02970     } //end if
02971 
02972     InitConsoleMessageHeap();
02973 
02974 #ifdef DEBUG
02975     botimport.Print(PRT_MESSAGE, "setup chat AI %d msec\n", Sys_MilliSeconds() - starttime);
02976 #endif //DEBUG
02977     return BLERR_NOERROR;
02978 } //end of the function BotSetupChatAI

Here is the call graph for this function:

void BotShutdownChatAI void   ) 
 

Definition at line 2985 of file be_ai_chat.c.

References botchatstates, BotFreeChatState(), BotFreeMatchTemplates(), BotFreeReplyChat(), consolemessageheap, FreeMemory(), i, ichatdata, matchtemplates, randomstrings, replychats, and synonyms.

Referenced by Export_BotLibShutdown().

02986 {
02987     int i;
02988 
02989     //free all remaining chat states
02990     for(i = 0; i < MAX_CLIENTS; i++)
02991     {
02992         if (botchatstates[i])
02993         {
02994             BotFreeChatState(i);
02995         } //end if
02996     } //end for
02997     //free all cached chats
02998     for(i = 0; i < MAX_CLIENTS; i++)
02999     {
03000         if (ichatdata[i])
03001         {
03002             FreeMemory(ichatdata[i]->chat);
03003             FreeMemory(ichatdata[i]);
03004             ichatdata[i] = NULL;
03005         } //end if
03006     } //end for
03007     if (consolemessageheap) FreeMemory(consolemessageheap);
03008     consolemessageheap = NULL;
03009     if (matchtemplates) BotFreeMatchTemplates(matchtemplates);
03010     matchtemplates = NULL;
03011     if (randomstrings) FreeMemory(randomstrings);
03012     randomstrings = NULL;
03013     if (synonyms) FreeMemory(synonyms);
03014     synonyms = NULL;
03015     if (replychats) BotFreeReplyChat(replychats);
03016     replychats = NULL;
03017 } //end of the function BotShutdownChatAI

Here is the call graph for this function:

void FreeConsoleMessage bot_consolemessage_t message  ) 
 

Definition at line 283 of file be_ai_chat.c.

References bot_consolemessage_t, freeconsolemessages, bot_consolemessage_s::next, and bot_consolemessage_s::prev.

Referenced by BotRemoveConsoleMessage().

00284 {
00285     if (freeconsolemessages) freeconsolemessages->prev = message;
00286     message->prev = NULL;
00287     message->next = freeconsolemessages;
00288     freeconsolemessages = message;
00289 } //end of the function FreeConsoleMessage

void InitConsoleMessageHeap void   ) 
 

Definition at line 240 of file be_ai_chat.c.

References bot_consolemessage_t, consolemessageheap, freeconsolemessages, FreeMemory(), GetClearedHunkMemory(), i, LibVarValue(), bot_consolemessage_s::next, and bot_consolemessage_s::prev.

Referenced by BotSetupChatAI().

00241 {
00242     int i, max_messages;
00243 
00244     if (consolemessageheap) FreeMemory(consolemessageheap);
00245     //
00246     max_messages = (int) LibVarValue("max_messages", "1024");
00247     consolemessageheap = (bot_consolemessage_t *) GetClearedHunkMemory(max_messages *
00248                                                 sizeof(bot_consolemessage_t));
00249     consolemessageheap[0].prev = NULL;
00250     consolemessageheap[0].next = &consolemessageheap[1];
00251     for (i = 1; i < max_messages-1; i++)
00252     {
00253         consolemessageheap[i].prev = &consolemessageheap[i - 1];
00254         consolemessageheap[i].next = &consolemessageheap[i + 1];
00255     } //end for
00256     consolemessageheap[max_messages-1].prev = &consolemessageheap[max_messages-2];
00257     consolemessageheap[max_messages-1].next = NULL;
00258     //pointer to the free console messages
00259     freeconsolemessages = consolemessageheap;
00260 } //end of the function InitConsoleMessageHeap

Here is the call graph for this function:

int IsWhiteSpace char  c  ) 
 

Definition at line 401 of file be_ai_chat.c.

References c.

Referenced by UnifyWhiteSpaces().

00402 {
00403     if ((c >= 'a' && c <= 'z')
00404         || (c >= 'A' && c <= 'Z')
00405         || (c >= '0' && c <= '9')
00406         || c == '(' || c == ')'
00407         || c == '?' || c == ':'
00408         || c == '\''|| c == '/'
00409         || c == ',' || c == '.'
00410         || c == '[' || c == ']'
00411         || c == '-' || c == '_'
00412         || c == '+' || c == '=') return qfalse;
00413     return qtrue;
00414 } //end of the function IsWhiteSpace

char* RandomString char *  name  ) 
 

Definition at line 1048 of file be_ai_chat.c.

References bot_randomlist_t, bot_randomstring_t, bot_randomlist_s::firstrandomstring, i, name, bot_randomstring_s::next, bot_randomlist_s::next, bot_randomlist_s::numstrings, random, strcmp(), bot_randomstring_s::string, and bot_randomlist_s::string.

Referenced by BotCheckChatMessageIntegrety(), and BotExpandChatMessage().

01049 {
01050     bot_randomlist_t *random;
01051     bot_randomstring_t *rs;
01052     int i;
01053 
01054     for (random = randomstrings; random; random = random->next)
01055     {
01056         if (!strcmp(random->string, name))
01057         {
01058             i = random() * random->numstrings;
01059             for (rs = random->firstrandomstring; rs; rs = rs->next)
01060             {
01061                 if (--i < 0) break;
01062             } //end for
01063             if (rs)
01064             {
01065                 return rs->string;
01066             } //end if
01067         } //end for
01068     } //end for
01069     return NULL;
01070 } //end of the function RandomString

Here is the call graph for this function:

int StringContains char *  str1,
char *  str2,
int  casesensitive
 

Definition at line 464 of file be_ai_chat.c.

00465 {
00466     int len, i, j, index;
00467 
00468     if (str1 == NULL || str2 == NULL) return -1;
00469 
00470     len = strlen(str1) - strlen(str2);
00471     index = 0;
00472     for (i = 0; i <= len; i++, str1++, index++)
00473     {
00474         for (j = 0; str2[j]; j++)
00475         {
00476             if (casesensitive)
00477             {
00478                 if (str1[j] != str2[j]) break;
00479             } //end if
00480             else
00481             {
00482                 if (toupper(str1[j]) != toupper(str2[j])) break;
00483             } //end else
00484         } //end for
00485         if (!str2[j]) return index;
00486     } //end for
00487     return -1;
00488 } //end of the function StringContains

char* StringContainsWord char *  str1,
char *  str2,
int  casesensitive
 

Definition at line 495 of file be_ai_chat.c.

References i, j, strlen(), and toupper().

Referenced by BotReplaceReplySynonyms(), BotReplyChat(), and StringReplaceWords().

00496 {
00497     int len, i, j;
00498 
00499     len = strlen(str1) - strlen(str2);
00500     for (i = 0; i <= len; i++, str1++)
00501     {
00502         //if not at the start of the string
00503         if (i)
00504         {
00505             //skip to the start of the next word
00506             while(*str1 && *str1 != ' ' && *str1 != '.' && *str1 != ',' && *str1 != '!') str1++;
00507             if (!*str1) break;
00508             str1++;
00509         } //end for
00510         //compare the word
00511         for (j = 0; str2[j]; j++)
00512         {
00513             if (casesensitive)
00514             {
00515                 if (str1[j] != str2[j]) break;
00516             } //end if
00517             else
00518             {
00519                 if (toupper(str1[j]) != toupper(str2[j])) break;
00520             } //end else
00521         } //end for
00522         //if there was a word match
00523         if (!str2[j])
00524         {
00525             //if the first string has an end of word
00526             if (!str1[j] || str1[j] == ' ' || str1[j] == '.' || str1[j] == ',' || str1[j] == '!') return str1;
00527         } //end if
00528     } //end for
00529     return NULL;
00530 } //end of the function StringContainsWord

Here is the call graph for this function:

void StringReplaceWords char *  string,
char *  synonym,
char *  replacement
 

Definition at line 537 of file be_ai_chat.c.

References Com_Memcpy(), memmove(), qfalse, string(), StringContainsWord(), and strlen().

Referenced by BotReplaceSynonyms(), and BotReplaceWeightedSynonyms().

00538 {
00539     char *str, *str2;
00540 
00541     //find the synonym in the string
00542     str = StringContainsWord(string, synonym, qfalse);
00543     //if the synonym occured in the string
00544     while(str)
00545     {
00546         //if the synonym isn't part of the replacement which is already in the string
00547         //usefull for abreviations
00548         str2 = StringContainsWord(string, replacement, qfalse);
00549         while(str2)
00550         {
00551             if (str2 <= str && str < str2 + strlen(replacement)) break;
00552             str2 = StringContainsWord(str2+1, replacement, qfalse);
00553         } //end while
00554         if (!str2)
00555         {
00556             memmove(str + strlen(replacement), str+strlen(synonym), strlen(str+strlen(synonym))+1);
00557             //append the synonum replacement
00558             Com_Memcpy(str, replacement, strlen(replacement));
00559         } //end if
00560         //find the next synonym in the string
00561         str = StringContainsWord(str+strlen(replacement), synonym, qfalse);
00562     } //end if
00563 } //end of the function StringReplaceWords

Here is the call graph for this function:

int StringsMatch bot_matchpiece_t pieces,
bot_match_t match
 

Definition at line 1357 of file be_ai_chat.c.

References assert, bot_match_t, bot_matchpiece_t, bot_matchstring_t, bot_matchpiece_s::firststring, bot_matchvariable_s::length, match(), bot_matchstring_s::next, bot_matchpiece_s::next, bot_matchvariable_s::offset, qfalse, bot_matchstring_s::string, bot_match_s::string, StringContains(), strlen(), bot_matchpiece_s::type, bot_matchpiece_s::variable, and bot_match_s::variables.

Referenced by BotFindMatch(), and BotReplyChat().

01358 {
01359     int lastvariable, index;
01360     char *strptr, *newstrptr;
01361     bot_matchpiece_t *mp;
01362     bot_matchstring_t *ms;
01363 
01364     //no last variable
01365     lastvariable = -1;
01366     //pointer to the string to compare the match string with
01367     strptr = match->string;
01368     //Log_Write("match: %s", strptr);
01369     //compare the string with the current match string
01370     for (mp = pieces; mp; mp = mp->next)
01371     {
01372         //if it is a piece of string
01373         if (mp->type == MT_STRING)
01374         {
01375             newstrptr = NULL;
01376             for (ms = mp->firststring; ms; ms = ms->next)
01377             {
01378                 if (!strlen(ms->string))
01379                 {
01380                     newstrptr = strptr;
01381                     break;
01382                 } //end if
01383                 //Log_Write("MT_STRING: %s", mp->string);
01384                 index = StringContains(strptr, ms->string, qfalse);
01385                 if (index >= 0)
01386                 {
01387                     newstrptr = strptr + index;
01388                     if (lastvariable >= 0)
01389                     {
01390                         match->variables[lastvariable].length =
01391                                 (newstrptr - match->string) - match->variables[lastvariable].offset;
01392                                 //newstrptr - match->variables[lastvariable].ptr;
01393                         lastvariable = -1;
01394                         break;
01395                     } //end if
01396                     else if (index == 0)
01397                     {
01398                         break;
01399                     } //end else
01400                     newstrptr = NULL;
01401                 } //end if
01402             } //end for
01403             if (!newstrptr) return qfalse;
01404             strptr = newstrptr + strlen(ms->string);
01405         } //end if
01406         //if it is a variable piece of string
01407         else if (mp->type == MT_VARIABLE)
01408         {
01409             //Log_Write("MT_VARIABLE");
01410             match->variables[mp->variable].offset = strptr - match->string;
01411             lastvariable = mp->variable;
01412         } //end else if
01413     } //end for
01414     //if a match was found
01415     if (!mp && (lastvariable >= 0 || !strlen(strptr)))
01416     {
01417         //if the last piece was a variable string
01418         if (lastvariable >= 0)
01419         {
01420                 assert( match->variables[lastvariable].offset >= 0 ); // bk001204
01421             match->variables[lastvariable].length =
01422                 strlen(&match->string[ (int) match->variables[lastvariable].offset]);
01423         } //end if
01424         return qtrue;
01425     } //end if
01426     return qfalse;
01427 } //end of the function StringsMatch

Here is the call graph for this function:

void UnifyWhiteSpaces char *  string  ) 
 

Definition at line 440 of file be_ai_chat.c.

References IsWhiteSpace(), memmove(), ptr(), string(), and strlen().

00441 {
00442     char *ptr, *oldptr;
00443 
00444     for (ptr = oldptr = string; *ptr; oldptr = ptr)
00445     {
00446         while(*ptr && IsWhiteSpace(*ptr)) ptr++;
00447         if (ptr > oldptr)
00448         {
00449             //if not at the start and not at the end of the string
00450             //write only one space
00451             if (oldptr > string && *ptr) *oldptr++ = ' ';
00452             //remove all other white spaces
00453             if (ptr > oldptr) memmove(oldptr, ptr, strlen(ptr)+1);
00454         } //end if
00455         while(*ptr && !IsWhiteSpace(*ptr)) ptr++;
00456     } //end while
00457 } //end of the function UnifyWhiteSpaces

Here is the call graph for this function:


Variable Documentation

bot_chatstate_t* botchatstates[MAX_CLIENTS+1]
 

Definition at line 200 of file be_ai_chat.c.

Referenced by BotAllocChatState(), BotChatStateFromHandle(), BotFreeChatState(), and BotShutdownChatAI().

bot_consolemessage_t* consolemessageheap = NULL
 

Definition at line 202 of file be_ai_chat.c.

Referenced by BotShutdownChatAI(), and InitConsoleMessageHeap().

bot_consolemessage_t* freeconsolemessages = NULL
 

Definition at line 203 of file be_ai_chat.c.

Referenced by AllocConsoleMessage(), FreeConsoleMessage(), and InitConsoleMessageHeap().

bot_ichatdata_t* ichatdata[MAX_CLIENTS]
 

Definition at line 198 of file be_ai_chat.c.

Referenced by BotLoadChatFile(), and BotShutdownChatAI().

bot_matchtemplate_t* matchtemplates = NULL
 

Definition at line 205 of file be_ai_chat.c.

Referenced by BotSetupChatAI(), and BotShutdownChatAI().

bot_randomlist_t* randomstrings = NULL
 

Definition at line 209 of file be_ai_chat.c.

Referenced by BotSetupChatAI(), and BotShutdownChatAI().

bot_replychat_t* replychats = NULL
 

Definition at line 211 of file be_ai_chat.c.

Referenced by BotSetupChatAI(), and BotShutdownChatAI().

bot_synonymlist_t* synonyms = NULL
 

Definition at line 207 of file be_ai_chat.c.

Referenced by BotSetupChatAI(), and BotShutdownChatAI().


Generated on Thu Aug 25 12:41:15 2005 for Quake III Arena by  doxygen 1.3.9.1