Skip to content

Commit

Permalink
GAME: ai chat preparations
Browse files Browse the repository at this point in the history
  • Loading branch information
mgerhardy committed Jun 5, 2022
1 parent a6f0494 commit 8c06ff0
Show file tree
Hide file tree
Showing 17 changed files with 8,564 additions and 30 deletions.
17 changes: 1 addition & 16 deletions code/botlib/be_ai_chat.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,6 @@ static void BotDumpSynonymList(bot_synonymlist_t *synlist) {
}
#endif

#if 0
static bot_synonymlist_t *BotLoadSynonyms(const char *filename) {
int pass, size, contextlevel, numsynonyms;
unsigned long int context, contextstack[32];
Expand Down Expand Up @@ -632,7 +631,6 @@ static bot_synonymlist_t *BotLoadSynonyms(const char *filename) {

return synlist;
}
#endif

//===========================================================================
// replace all the synonyms in the string
Expand Down Expand Up @@ -793,7 +791,6 @@ static void BotDumpRandomStringList(bot_randomlist_t *randomlist) {
}
}
#endif
#if 0

static bot_randomlist_t *BotLoadRandomStrings(const char *filename) {
int pass, size;
Expand Down Expand Up @@ -887,7 +884,6 @@ static bot_randomlist_t *BotLoadRandomStrings(const char *filename) {

return randomlist;
}
#endif

static const char *RandomString(const char *name) {
bot_randomlist_t *random;
Expand Down Expand Up @@ -1332,7 +1328,6 @@ static void BotCheckInitialChatIntegrity(bot_chat_t *chat) {
}
}

#if 0
static void BotCheckReplyChatIntegrity(bot_replychat_t *replychat) {
bot_replychat_t *rp;
bot_chatmessage_t *cm;
Expand All @@ -1349,7 +1344,6 @@ static void BotCheckReplyChatIntegrity(bot_replychat_t *replychat) {
FreeMemory(s);
}
}
#endif

#if 0
static void BotDumpReplyChat(bot_replychat_t *replychat) {
Expand Down Expand Up @@ -1430,7 +1424,6 @@ static void BotFreeReplyChat(bot_replychat_t *replychat) {
}
}

#if 0
static void BotCheckValidReplyChatKeySet(source_t *source, bot_replychatkey_t *keys) {
int allprefixed, hasvariableskey, hasstringkey;
bot_matchpiece_t *m;
Expand Down Expand Up @@ -1514,9 +1507,7 @@ static void BotCheckValidReplyChatKeySet(source_t *source, bot_replychatkey_t *k
"invalid when outputting one of the chat messages");
}
}
#endif

#if 0
static bot_replychat_t *BotLoadReplyChat(const char *filename) {
char chatmessagestring[MAX_MESSAGE_SIZE];
char namebuffer[MAX_MESSAGE_SIZE];
Expand Down Expand Up @@ -1662,7 +1653,6 @@ static bot_replychat_t *BotLoadReplyChat(const char *filename) {

return replychatlist;
}
#endif

#if 0
static void BotDumpInitialChat(bot_chat_t *chat) {
Expand Down Expand Up @@ -2005,7 +1995,7 @@ static void BotConstructChatMessage(bot_chatstate_t *chatstate, const char *mess
if (!BotExpandChatMessage(chatstate->chatmessage, srcmessage, mcontext, match, vcontext, reply)) {
break;
}
strcpy(srcmessage, chatstate->chatmessage);
Q_strncpyz(srcmessage, chatstate->chatmessage, sizeof(srcmessage));
}
if (i >= 10) {
botimport.Print(PRT_WARNING, "too many expansions in chat message\n");
Expand Down Expand Up @@ -2479,7 +2469,6 @@ int BotSetupChatAI(void) {
int starttime = Sys_MilliSeconds();
#endif // DEBUG

#if 0
file = LibVarString("synfile", "syn.c");
synonyms = BotLoadSynonyms(file);

Expand All @@ -2493,10 +2482,6 @@ int BotSetupChatAI(void) {
file = LibVarString("rchatfile", "rchat.c");
replychats = BotLoadReplyChat(file);
}
#else
file = LibVarString("matchfile", "match.c");
matchtemplates = BotLoadMatchTemplates(file);
#endif

InitConsoleMessageHeap();

Expand Down
2 changes: 1 addition & 1 deletion code/game/ai_chat.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ static int BotVisibleEnemies(bot_state_t *bs) {
BotValidChatPosition
==================
*/
static int BotValidChatPosition(bot_state_t *bs) {
int BotValidChatPosition(bot_state_t *bs) {
vec3_t point, start, end, mins, maxs;
bsp_trace_t trace;

Expand Down
2 changes: 2 additions & 0 deletions code/game/ai_chat.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,7 @@ int BotChat_EnemySuicide(bot_state_t *bs);
int BotChat_Random(bot_state_t *bs);
// time the selected chat takes to type in
float BotChatTime(bot_state_t *bs);
// returns true if the bot can chat at the current position
int BotValidChatPosition(bot_state_t *bs);
// test the initial bot chats
void BotChatTest(const bot_state_t *bs);
21 changes: 15 additions & 6 deletions code/game/ai_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ int NumPlayersOnSameTeam(bot_state_t *bs) {
BotAddressedToBot
==================
*/
int BotAddressedToBot(bot_state_t *bs, bot_match_t *match) {
static int BotAddressedToBot(bot_state_t *bs, bot_match_t *match) {
char addressedto[MAX_MESSAGE_SIZE];
char netname[MAX_MESSAGE_SIZE];
// char name[MAX_MESSAGE_SIZE];
Expand Down Expand Up @@ -269,12 +269,21 @@ int BotAddressedToBot(bot_state_t *bs, bot_match_t *match) {
}

return qfalse;
} else {
bot_match_t tellmatch;

tellmatch.type = 0;
// if this message wasn't directed solely to this bot
if (!trap_BotFindMatch(match->string, &tellmatch, MTCONTEXT_REPLYCHAT) || tellmatch.type != MSG_CHATTELL) {
// make sure not everyone reacts to this message
if (random() > (float)1.0 / (NumPlayersOnSameTeam(bs) - 1))
return qfalse;
}
}
// not addressed, take it
return qtrue;
}

void BotMatch_WrongWall(bot_state_t *bs, bot_match_t *match) {
static void BotMatch_WrongWall(bot_state_t *bs, bot_match_t *match) {
char netname[MAX_MESSAGE_SIZE];
char buf[MAX_INFO_STRING];
int client;
Expand Down Expand Up @@ -382,7 +391,7 @@ static void BotMatch_GoForBalloon(bot_state_t *bs, bot_match_t *match) {
#endif
}

void BotMatch_CatchMe(bot_state_t *bs, bot_match_t *match) {
static void BotMatch_CatchMe(bot_state_t *bs, bot_match_t *match) {
char netname[MAX_MESSAGE_SIZE];
int client;

Expand Down Expand Up @@ -414,7 +423,7 @@ void BotMatch_CatchMe(bot_state_t *bs, bot_match_t *match) {
BotMatch_GetItem
==================
*/
void BotMatch_GetItem(bot_state_t *bs, bot_match_t *match) {
static void BotMatch_GetItem(bot_state_t *bs, bot_match_t *match) {
char itemname[MAX_MESSAGE_SIZE];
char netname[MAX_MESSAGE_SIZE];
int client;
Expand Down Expand Up @@ -593,7 +602,7 @@ int BotMatchMessage(bot_state_t *bs, const char *message) {
BotMatch_WrongWall(bs, &match);
break;
}
case MSG_GOFORBALLOON:{ //someone calling for company
case MSG_GOFORBALLOON: { //someone calling for company
BotMatch_GoForBalloon(bs, &match);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion code/game/ai_dmnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1500,7 +1500,7 @@ static void AIEnter_Observer(bot_state_t *bs, const char *s) {
AINode_Stand
==================
*/
static int AINode_Stand(bot_state_t *bs) {
int AINode_Stand(bot_state_t *bs) {
// if the bot's health decreased
if (bs->lastframe_health > bs->inventory[INVENTORY_HEALTH]) {
if (BotChat_HitTalking(bs)) {
Expand Down
1 change: 1 addition & 0 deletions code/game/ai_dmnet.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ void AIEnter_Battle_Retreat(bot_state_t *bs, char *s);
void AIEnter_Battle_NBG(bot_state_t *bs, char *s);
void AIEnter_Respawn(bot_state_t *bs, char *s);
int AINode_Respawn(bot_state_t *bs);
int AINode_Stand(bot_state_t *bs);
int AINode_Seek_ActivateEntity(bot_state_t *bs);
int AINode_Seek_NBG(bot_state_t *bs);
int AINode_Seek_LTG(bot_state_t *bs);
Expand Down
103 changes: 100 additions & 3 deletions code/game/ai_dmq3.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ qboolean IsBoomie(int ent) {
BotTeam
==================
*/
int BotTeam(bot_state_t *bs) {
int BotTeam(const bot_state_t *bs) {
gclient_t *client;

if (bs->client < 0 || bs->client >= MAX_CLIENTS) {
Expand Down Expand Up @@ -1231,6 +1231,24 @@ char *EasyClientName(int client, char *buf, int size) {
return buf;
}

/*
==================
BotSynonymContext
==================
*/
int BotSynonymContext(const bot_state_t *bs) {
int context;

context = CONTEXT_NORMAL | CONTEXT_NEARBYITEM | CONTEXT_NAMES;
if (gametype == GT_CTF) {
if (BotTeam(bs) == TEAM_RED)
context |= CONTEXT_CTFREDTEAM;
else
context |= CONTEXT_CTFBLUETEAM;
}
return context;
}

/*
==================
BotChooseWeapon
Expand Down Expand Up @@ -4053,11 +4071,90 @@ BotCheckConsoleMessages
==================
*/
static void BotCheckConsoleMessages(bot_state_t *bs) {
int handle;
char botname[MAX_NETNAME], message[MAX_MESSAGE_SIZE], netname[MAX_NETNAME], *ptr;
float chat_reply;
int context, handle;
bot_consolemessage_t m;
bot_match_t match;

// the name of this bot
ClientName(bs->client, botname, sizeof(botname));

while ((handle = trap_BotNextConsoleMessage(bs->cs, &m)) != 0) {
BotMatchMessage(bs, m.message);
// if the chat state is flooded with messages the bot will read them quickly
if (trap_BotNumConsoleMessages(bs->cs) < 10) {
// if it is a chat message the bot needs some time to read it
if (m.type == CMS_CHAT && m.time > FloatTime() - (1 + random()))
break;
}

ptr = m.message;
// if it is a chat message then don't unify white spaces and don't
// replace synonyms in the netname
if (m.type == CMS_CHAT) {
if (trap_BotFindMatch(m.message, &match, MTCONTEXT_REPLYCHAT)) {
ptr = m.message + match.variables[MESSAGE].offset;
}
}
// unify the white spaces in the message
trap_UnifyWhiteSpaces(ptr);
// replace synonyms in the right context
context = BotSynonymContext(bs);
trap_BotReplaceSynonyms(ptr, context);
// if there's no match
if (!BotMatchMessage(bs, m.message)) {
// if it is a chat message
if (m.type == CMS_CHAT && !bot_nochat.integer) {
if (!trap_BotFindMatch(m.message, &match, MTCONTEXT_REPLYCHAT)) {
trap_BotRemoveConsoleMessage(bs->cs, handle);
continue;
}
// don't use eliza chats with team messages
if (match.subtype & ST_TEAM) {
trap_BotRemoveConsoleMessage(bs->cs, handle);
continue;
}

trap_BotMatchVariable(&match, NETNAME, netname, sizeof(netname));
trap_BotMatchVariable(&match, MESSAGE, message, sizeof(message));
// if this is a message from the bot self
if (bs->client == ClientFromName(netname)) {
trap_BotRemoveConsoleMessage(bs->cs, handle);
continue;
}
// unify the message
trap_UnifyWhiteSpaces(message);

trap_Cvar_Update(&bot_testrchat);
if (bot_testrchat.integer) {
trap_BotLibVarSet("bot_testrchat", "1");
// if bot replies with a chat message
if (trap_BotReplyChat(bs->cs, message, context, CONTEXT_REPLY, NULL, NULL, NULL, NULL, NULL, NULL,
botname, netname)) {
BotAI_Print(PRT_MESSAGE, "------------------------\n");
} else {
BotAI_Print(PRT_MESSAGE, "**** no valid reply ****\n");
}
}
// if at a valid chat position and not chatting already and not in teamplay
else if (bs->ainode != AINode_Stand && BotValidChatPosition(bs) && !TeamPlayIsOn()) {
chat_reply = trap_Characteristic_BFloat(bs->character, CHARACTERISTIC_CHAT_REPLY, 0, 1);
if (random() < 1.5 / (NumBots() + 1) && random() < chat_reply) {
// if bot replies with a chat message
if (trap_BotReplyChat(bs->cs, message, context, CONTEXT_REPLY, NULL, NULL, NULL, NULL, NULL,
NULL, botname, netname)) {
// remove the console message
trap_BotRemoveConsoleMessage(bs->cs, handle);
bs->stand_time = FloatTime() + BotChatTime(bs);
AIEnter_Stand(bs, "BotCheckConsoleMessages: reply chat");
// EA_Say(bs->client, bs->cs.chatmessage);
break;
}
}
}
}
}
// remove the console message
trap_BotRemoveConsoleMessage(bs->cs, handle);
}
}
Expand Down
4 changes: 3 additions & 1 deletion code/game/ai_dmq3.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ char *ClientName(int client, char *name, int size);
char *EasyClientName(int client, char *name, int size);
// returns the skin used by the client
char *ClientSkin(int client, char *skin, int size);
// returns the appropriate synonym context for the current game type and situation
int BotSynonymContext(const bot_state_t *bs);
// selection of goals for teamplay
void BotTeamGoals(bot_state_t *bs, int retreat);
// returns the aggression of the bot in the range [0, 100]
Expand Down Expand Up @@ -113,7 +115,7 @@ int BotPopFromActivateGoalStack(bot_state_t *bs);
// clear the activate goal stack
void BotClearActivateGoalStack(bot_state_t *bs);
// returns the team the bot is in
int BotTeam(bot_state_t *bs);
int BotTeam(const bot_state_t *bs);
// retuns the opposite team of the bot
int BotOppositeTeam(bot_state_t *bs);
// remember the last ordered task
Expand Down
11 changes: 10 additions & 1 deletion code/game/ai_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ void QDECL BotAI_BotInitialChat(const bot_state_t *bs, const char *type, ...) {
}
va_end(ap);

mcontext = CONTEXT_NORMAL | CONTEXT_NEARBYITEM | CONTEXT_NAMES;
mcontext = BotSynonymContext(bs);

trap_BotInitialChat(bs->cs, type, mcontext, vars[0], vars[1], vars[2], vars[3], vars[4], vars[5], vars[6], vars[7]);
}
Expand Down Expand Up @@ -1127,6 +1127,15 @@ void BotEntityInfo(int entnum, aas_entityinfo_t *info) {
trap_AAS_EntityInfo(entnum, info);
}

/*
==============
NumBots
==============
*/
int NumBots(void) {
return numbots;
}

/*
==============
AngleDifference
Expand Down
2 changes: 2 additions & 0 deletions code/game/ai_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ typedef struct bot_state_s {
float AngleDifference(float ang1, float ang2);
// resets the whole bot state
void BotResetState(bot_state_t *bs);
//returns the number of bots in the game
int NumBots(void);
// returns info about the entity
void BotEntityInfo(int entnum, aas_entityinfo_t *info);

Expand Down
Loading

0 comments on commit 8c06ff0

Please sign in to comment.