Contents:
This document
contains editing information for the Q3A bot. Author: Mr Elusive Last update:
2000-01-04
The Q3A bot is an artificial player for the computer game
Quake III Arena.
Copyright 2000 id Software, Inc.
bot chat
system
The bot chat system has five parts:
The pseudo code
below shows how the different parts of the chat system are used.
if
environmental change then
if
bot wants to chat then
choose
initial chat
use
random strings if referenced
replace
synonyms using chances
output
chat message
endif
endif
if
message appears on the console then
replace
synonyms in the console message
try
to 'understand' message using match
templates
if
match found then
perform
action
else
if
console messages is a chat message then
if
bot wants to reply to this message
find
a reply chat
use
random strings if referenced
replace
synonyms using chances
output
chat message
endif
endif
endif
endif
Synonyms
The synonyms are used to unify strings before processing and also used to create some variation when outputting a message. The synonyms are stored in the file syn.c. The bot uses context dependent synonyms. Every context has a flag that is defined in the file syn.h.
A context with synonyms is constructed as follows:
context
flag
{
[("first
synonym", X), ("second
synonym", Y),
...]
...
}
The X and Y are values in the range [0-1]. These values are chances the synonyms are used in chat messages the bot outputs.
A few
examples:
CONTEXT_NEARBYITEM
{
[("Heavy
Armor",
0),
("red
armor",
0),
("Heavy
Armour",
0),
("red
armour",
0),
("ra",
0)]
}
CONTEXT_NORMAL
{
[("do
not", 1), ("don't", 1), ("dont", 1)]
[("checkpoint", 1), ("check-point", 1), ("cp", 1)]
}
In case some word in a bot chat message should never be replaced by a synonym the tilde character ~ can be placed in front of that word. All tilde characters ~ will be removed from the bot chat messages before a bot outputs them.
Random
strings
The random strings are used in the initial and reply chat messages to add some variation. The random strings are stored in the file rnd.c.
A set of random strings is constructed as follows:
rndname = {"first random string"; "second random string"; ...}
A set of random strings is used in a chat message as follows:
" part of the chat
message ",
rndname,
" part of the
chat message ";
Multiple references to random strings can be used in a chat messages. Multiple references to random strings separated by semi colons can also be used directly after each other.
A set of random strings may also contain references to other sets of random strings.
ferrari = {"F40"; "F50"}
BMW = {"BMW
Z3"; "BMW
Z8"}
cars = {ferrari; BMW; "F1
Mc Laren"}
However make sure there is no recursion when referencing other sets of random strings.
Match
templates
The bot uses the match templates to 'understand' chat- and other console messages. The match templates are stored in the file match.c.
A match template is constructed as follows:
matchtemplate
=
(id,
typeflags);
Fixed strings and variables alternate in a match template and they are separated by commas. For instance: "you are ", 0, " don't you think?" Here the 0 is the index of a variable. Currently a maximum of 8 variables is allowed (index in the range [0-7]). It is not allowed to have two consecutive variables.
The bot will try
to find a match with one of several fixed strings in the template
when they are separated by the |
token. For instance: "you"|"we", "
are ", 0, "
don't you think?"
will match to both "you
are crazy don't you think?"
and "we are
crazy don't you think?".
The bot will try to match the strings separated by the
|
token in the order they are listed. An empty string is also allowed
with the |
token. However make sure the empty string is always the last one in a
sequence of strings separated by |
tokens because the empty string will always match. For instance:
"I am the
",
"team
"|"",
"leader"
will match to both "I
am the team leader"
and "I am the
leader".
The id is used to identify the message. The type flags specify certain characteristics of the message. The id and type flags are defined in the file match.h.
The bot uses context dependent match templates. Every context has a context flag and several match templates can be grouped within a context. The context flags are stored in the file match.h.
context
flag
{
...
}
An example:
MTCONTEXT_INITIALTEAMCHAT
{
"(", NETNAME, "):
", ADDRESSEE, "
camp at ", KEYAREA, "
for ", TIME = (MSG_CAMP, $evalint(ST_ADDRESSED|ST_NEARITEM|ST_TIME));
...
}
The bot uses the
match templates in the order they are listed in the file match.c. The
first match found is used.
Initial
chats
The initial chats are used by the bot to initiate a chat when something in the environment changes or the bot just feels like chatting. Each bot has a personal set of initial chat lines. In the characteristics of a bot there's a reference to the file with the initial chats for that bot. There is also a reference to the "name" of the chats in that file.
The initial chats for a bot are constructed as follows:
chat
"name"
{
type
"type
name"
{
"initial
chat message";
"another
initial chat message";
...
}
type
"type
name"
{
}
...
}
Reply
chats
The bot uses the reply chats to reply to chat messages from other players. All bots use the same reply chats because the number of reply chats tends to grow pretty large. Creating different reply chats for each bot character would be too much work and also take up to much memory.
The reply chats are stored in the file rchats.c. The reply chats in this file have keys, a priority and several reply chat lines.
[key1,
key2,
...] =
priority
{
"reply
chat message";
"another
reply chat message";
...
}
key prefixes:
& key must
be true ! key must
be false
keys:
name key is
true when the name of the bot is found in the chat message
the bot wants to reply to female key is
true when the bot is female male key is
true when the bot is male it key is
true when the bot is not male nor female <"",""> key is
true when the bot has one of these names, any number of
names can be listed between the
<
and > "" key is
true when the string is found in the message to reply to (
) key is
true when the chat message to reply to matches the template
between the (
)
The match templates work in exactly the same way as the
match templates described above. The matched variables can
be used in the reply chat messages. For example:
[("I'm
not ",
0)]
= 4
{
"yes
you are ",
0;
}
The priority is a
floating-point value that is relative to the priorities of other
reply chats.
The bot evaluates
the keys to find out if the reply chat can be used to reply to a
certain chat message from another player. When all the keys with the
prefix &
are true and all the keys with the prefix
!
are not true and there is at least one key without prefix true then
the bot may use the reply chat. When several reply chats can be used
to reply to a message the one with the highest priority is
chosen.
reply chat
examples:
["hate
you",
!"not"]
= 7
{
"why
do you hate me";
"there's
no reason for you to hate me";
}
Bots can use the
above reply chat when someone types the message
"I hate
you". However
if a player types the message "I
don't hate you"
the bot cannot use the above reply chat because of the key
"not"
with the prefix !.
(Note: "don't"
will be replaced by "do
not" because
of the contraction synonyms in the synonym list.)
["love
you",
!"not",
&female]
= 6
{
"am
I the only woman you love?";
"I
love you to";
}
Only female bots
can use the above reply chat.
["camper",
!"not",
&<"Grunt",
"Stripe">]
= 6
{
"I
love camping";
"I'm
the king of all camp grounds";
"camping
with the rocket launcher is what Graeme told me to
do";
"so?..
you got a problem with campers?";
}
Only Grunt and
Stripe can use the above reply chat.
bad reply
chats:
[&"looser",
!"not",
&female]
= 6
{
"I'm
not a looser";
}
All the keys in
the above reply chat have either the !
or &
prefix. No bot will ever use this reply chat because at least one key
without prefix must be true.
[("I
hate ",
0),
"hate
you"] =
7
{
"are
you sure you hate ",
0;
}
In the above reply
chat the variable 0
does not have to be valid when the bot tries to output the message
"are you sure
you hate ",
0;
because the key "hate
you" could be
the only true key. For instance only the key
"hate
you" is true
when the bot tries to reply to the message
"we hate
you".
[("get
lost"),
&name]
= 7
{
"I
never get lost";
}
The above reply chat will never be used because there is no room for the name of the bot in the match template. However the name of the bot is required to be in the chat message to reply to because of the key &name.
[("do
not say ",
0,
" want to
",
1),
!"not"]
= 7
{
"but
",
0,
" really want
to ",
1;
}
The above reply chat will never be used because "not" is a sub-string of "do not say ".
bad reply chat
combination:
["allowed"]
= 7
{
"everything
is allowed.";
}
["not
allowed"]
= 5
{
"why
isn't that allowed?";
}
If both of the
above reply chats are in the rchat.c file then the bot will never
reply with "why
isn't that allowed".
If the bot for instance wants to reply to the message
"cheating is
not allowed"
then the bot figures out it can use both of the above reply chats
according to the keys. The message "cheating
is not allowed"
has the sub-string "not
allowed" and
also the sub-string "allowed".
Because the keys allow the bot to use both reply chats the priority
is used to select one of them. The priority of the reply chat with
the key "allowed"
is higher and will be used. Reversing the priorities will fix the
problem.
Chat
messages
Both the initial chats and reply chats store chat messages. Random strings can be used in these chat messages to add some variation. Variables from match templates in the reply chats or specified in code for initial chats can be used in chat message. The tilde character ~ can be placed in front of words in a chat message to make sure these words will not be replaced with synonyms. Colors can also be used in chat messages. A color is specified with the ^ character followed by a number in the range 0-7.