You are on page 1of 30

Matbots Manual

Official Manual and Bot Programming Guide

Michael Abraham and Christopher Wellons


Copyright
c 2007 Michael Abraham and Christopher Wellons
Copying, modification, and distribution of this document is permitted world-
wide, without royalty, in any medium, provided this notice is preserved.
i

Table of Contents

Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1 Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1 Invocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Engine Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.1 World Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2.2 Display Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.3 Player Settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.3 Directories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

2 Programming Basics . . . . . . . . . . . . . . . . . . . . . . . 5
2.1 Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Bot Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.1 Rifle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.2 Mine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.3 Grenade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.4 Health to Energy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3.5 Self Destruct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4 Requests. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4.1 Clean and Preclean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4.2 Selfplot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.5 Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.5.1 Rifle Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.5.2 Mine Object. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.5.3 Grenade Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.5.4 Destruct Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3 Creating a Bot . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.1 Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.2 Handling Requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.3 Moving and Shooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.4 Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.5 Targeting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4 Bot Behavior . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.1 Well Behaved Bots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2 Useful Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2.1 drawface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2.2 drawghost . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
4.2.3 drawhand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.2.4 drawenterprise . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
ii

4.2.5 dodge bullets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18


4.3 Bot Plotting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
4.4 Existing Bots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.4.1 Target Dummies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.4.2 Team Bots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.4.3 Evasion Bots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

5 Human Interface. . . . . . . . . . . . . . . . . . . . . . . . . . 21

Appendix A Simple Example . . . . . . . . . . . . . . . 22

Appendix B Targeting Bot . . . . . . . . . . . . . . . . . 23

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
Preface 1

Preface
Matbots, not originally under any name, began as a small project to pass the time. It was
a throw away program meant to try out an automated chasing algorithm. A circle traveled
chaotically around a plot while an asterisk limited only by speed, chased this poor circle.
The circle did not care, of course, what the asterisk was doing. It was thinking of nothing
in particular. According to Jerry Seinfeld, this circle was just a typical man: “We’re not
thinking anything. We’re just walking around, looking around. [...] just kinda check stuff
out.”
It was later suggested by an onlooker that this circle should be concerned about the
asterisk. Who wants an asterisk following them around all day? Later on the circle gets
home and an asterisk follows it in the front door. Asterisks are rude. The circle needed
some defense.
To make this work, the circle was given its own personal function! It was granted
autonomy by way of its own address space and scope. Also, as seen all throughout history,
the circle was given a gun to protect this new freedom from the invading asterisk.
But what fun is that if the asterisk doesn’t get a gun as well?
Eventually the asterisk became a circle and more “bots”, with new and unique behavior,
began to join the game. Over time they gained new abilities, such as dropping mines and
high fiving each other. Some bots were better than other bots, which lead to escalation of
skills (and CPU time!). Counter-bots were written to counter these bots. Counter-counter
bots were written to counter these counter-bots ... ad infinitum.
By having these bots written in Matlab, all of Matlab’s tools are at the programmer’s
disposal. A bot could also be written in other languages and interfaced with the Matbots
engine (this is how the human interface works).
Writing a matbot is an exercise in programming as well as mathematics, as the game
area is not discrete. Matbot positions are floating point values. Writing a good targeting
algorithm involves calculus (determining a bot’s future position) and statistics (evaluating
past game data). Writing a successful bot has become more complicated than we (the
Matbot authors) had ever imagined, but it is a lot of fun to stretch our minds around the
puzzles of programming one.
Enjoy programming Matbots!
Chapter 1: Setup 2

1 Setup

1.1 Invocation
To set up a game, edit the file called ‘player_list.txt’. This file should contain a bot
name and a bot team name on each line separated by space. For example,
sniper red_team
sniper red_team
sniper red_team
goose blue_team
goose blue_team
goose blue_team
The above ‘player_list.txt’ file would set up a game of three sniper bots on team
"red team" against three goose bots on team "blue team". Any combination of bots and
teams is allowed.
The game options and settings are stored in ‘engine_settings.m’. This file is executed
by the engine to obtain all in-game values. Bots may also use this to obtain the same
information for use in its programming. See Section 1.2 [Engine Settings], page 2.
To start a game, simply execute the file ‘engine.m’,
>> engine

1.2 Engine Settings


The file engine_settings.m stores all of the game settings and options that affect the
gameplay, logging, and display. The following explains these different settings found in the
above file.

1.2.1 World Settings


The size of the game map is given in a 1 by 4 vector called world,
world = [minX maxX minY maxY];
All activity, weapons, and bots must happen within this boundary. Nothing can exist
outside these bounds.
The time step of the engine is defined in the ts variable. A lower number will give more
precision to the game but result in greater processing time to simulate the game.
friendly_fire enables friendly fire for the game. With friendly fire turned on, bullets
and mines will hurt fellow teammates in the game. Grenades will hurt everyone, including
the bot that shot the grenade.
player_hide is a vector of integers that masks values in the player state vector (see
Section 2.1 [Data Structures], page 5) Changing this can severely break many bots. It is
suggested to leave this as [8 10], which will mask other player’s headings and bot function
handles.
group_teams decides how players are initially placed in the world. When enabled, players
are grouped with their teams and the teams are placed evenly around the outside of the
world.
Chapter 1: Setup 3

group_teams_radius determines the radius of the circle in which an entire team starts
when group_teams is enabled. If this is set to 0, all team members will be exactly on top
of each other.

1.2.2 Display Settings


This section contains settings that effect the display of the world during the game as well as
the recordings from that game. Changing these have no effect on the game, except perhaps
to make take longer to play out.
heading_length is the length of the line that shows a bot’s heading. This only applies
when a bot does not draw itself.
display_game determines whether or not the game is displayed during the run. When
disabled, the game will still run the same way but there will be no visual output.
The next two settings, record_game and script_game, involve game recordings. These
are two ways to record a game.
When record_game is enabled, the game is captured using Matlab’s getframe command.
This means that when this option is set, display_game is also set, no matter what. This
can be used to convert a game video into a movie file for play outside of Matlab.
With script_game, the game display is dumped to an m-file by the name stored in
script_file. This works by putting all plot, text, and fill commands to an m-file
along with all the data needed (see Section 4.3 [Bot Plotting], page 18). This m-file can be
played back from any instance of Matlab anywhere without the engine or any bots present.
This means you can share the recording with anyone who has Matlab. Because it records
plot commands, the “video” has infinite resolution and can be played back at any size
without loss of quality.
The scripted game also has built-in recording facilities, allowing it to be easily converted
into a video file. To turn this on, edit the first line of the script to set record_game to 1
instead of 0. All video data will be dumped to a variable called watch.
In-game data can also be logged and this log data is placed into a structure called bots
and stored in the file named by log_file. Information on bot CPU time is stored in
bot_time. Logging is enabled with log_game.
silent_bots will quietly disable bot eplot commands. All bots will be drawn normally
as little circles with heading lines. This is reflected in game recordings as well. Use this if
you want to battle loud and colorful bots with a cleaner looking game.
The game also supports drawing health and energy bars above players. These are con-
trolled by the remaining settings in this section. display_health and display_energy
controls whether these bars are visible or not. The other three settings, bar_length, bar_
offset, and bar_stack_offset controls the look of the bars: length, distance from each
other, distance from player, respectively.

1.2.3 Player Settings


The player settings effect bots directly and are fairly simple settings. These control health,
energy, and movement.
energy_max and health_max control the maximum energy and health respectively. Gen-
erally, increasing health will make games longer and increasing energy will make games
shorter.
Chapter 1: Setup 4

energy_regen and health_regen control the energy and health regeneration rates. Set-
ting these values to zero disables the respective regeneration ability.
move_cost is the energy cost of moving a bot. The actual movement cost is a percentage
of this value based on throttle. 50% throttle will use half of this energy and 100% throttle
will use the entire move_cost amount.
deltaH_max is the maximum amount of angular distance a bot can turn at once. Setting
this to a low value will greatly reduce the movement capabilities of the bots. Setting this
value high will make watching games a boring activity (really!).

1.3 Directories
The Matbots directory should contain three subdirectories and three files: ‘engine.m’,
‘engine_settings.m’, and ‘player_list.txt’. These files were explain previously.
The ‘doc’ subdirectory contains documentation, which should include this document you
are reading now.
The ‘bots’ directory contains all of the bots. Bots can really be thrown anywhere, but
this is where bots should really go. This is where people will look for them.
The ‘func’ directory contains useful functions that some bots use. One such function
is eplot found in ‘eplot.m’. The engine itself uses this function. See Section 4.2 [Useful
Functions], page 17.
The ‘human’ directory contains “bots” that are controlled by human beings (at least in
part) rather than by a program. In it are the needed files to obtain the human input. See
Chapter 5 [Human Interface], page 21.
Chapter 2: Programming Basics 5

2 Programming Basics

2.1 Data Structures


A bot’s current state is completely described by its state vector. The state vector is stored
as a 1 by 10 cell array. The values are stored in this order,
1. X-position (double precision)
2. Y-position (double precision)
3. Health (double precision)
4. Energy (double precision)
5. Team (string)
6. Player number (integer)
7. Bot Function (string)
8. Heading (double precision)
9. Color (integer vector)
10. Bot function handle (function handle)
The x-position and y-position are straightforward: each is a floating point value between
the defined world boundaries, stored in world. These are Cartesian coordinates with the
origin at the bottom left and increasing values going right and up.
The health is a value between 0 and health_max. When a bot’s health is 0, this bot is
dead and is removed from the game. Health slowly regenerates at the rate health_regen.
The bot’s energy is the fuel used to execute most, if not all, actions (depending on
the engine settings): movement, shooting, dropping mines, tossing grenades, self-destruct.
Energy slowly regenerates at the rate stored in energy_regen. If a bot’s energy is zero, the
bot probably cannot do anything but wait for energy to regenerate.
The team is a string that identifies which team a bot is playing on. The team name is
arbitrary and two bots are on the same team if their team names match. Teams share a
common color.
The player number is a unique number assigned to each bot before the game begins.
This number will never change during the course of a game. This means that if a bot dies,
the player numbers are not adjusted. For example, if there are four players at the beginning
of a game each is assigned numbers 1 through 4. When player number 3 dies, the remaining
players will be 1, 2, and 4. Player 4 is not changed into player 3. Confusion on this point
is a cause of many programming errors.
The bot function name is the name of the function that defines the bot. This is used
by the engine to decide what function to call when running the simulation. It can also be
used for organizing teams or targeting particularly dangerous enemies.
The heading is a number between -pi and pi that describes the direction a bot is facing.
A heading of 0 means that a bot is facing to the right, east, or the positive x direction.
The color is simply the color that the engine is using to plot the bot. This is useful for
a bot that is drawing itself (see Section 4.3 [Bot Plotting], page 18).
The bot function handle is the function handle that the engine uses to call the bot. This
is not useful for bots and will generally not be available to bots in the state vectors.
Chapter 2: Programming Basics 6

2.2 Bot Interface


Bots are Matlab functions. They accept four inputs and return three outputs,
function [deltaH throttle action] ...
= botname (state, player, objects, req)
state is a 1 by n cell array. The n cells are state vectors for every other living (or very
recently living) bot in the game. To access the information in a cell array, you will probably
want to use squiggly brackets.
For example, if you were interested in the health of the second bot in the list, you would
want
state{2}{3}
Note the use of squiggly brackets rather than parenthesis. Also note that this is not
necessarily the health of player 2. Rather, this is the health of the second bot in the array.
This could very well be player 13 if several bots have already died and have been removed
from the player list. To get the player number of the second bot in the list, you would want
to use
state{2}{6}
The second argument player is the current bot’s state vector (the 1 by 9 cell array).
This means that player{1} is the current bot’s x-position. player{2} is the current bot’s
y-position, etc.
objects is a cell array containing information about all the various objects that are in
the playing field that are visible to the current bot. Each cell contains a state vector for
an object. The first cell in each object state vector is the name of the type of object. For
details on objects, Section 2.5 [Objects], page 9.
req is a request. The engine uses this input to make requests to the bot. In normal
gameplay, this will be an empty string. If the string is not empty, the bot should either
perform the request action or do nothing at all. The most important requests are preclean
and clean. These are used to tell the bot to clean up files and such before and after the
game. See Section 2.4 [Requests], page 8.
A well behaved bot should always return three values. There are a few times when
returning no values will not cause problems, but returning values will do not harm.
deltaH is a change in heading angle (in radians). This value turns by the given angle.
This angle may only be between -deltaH_max and deltaH_max. Values exceeding these
values will be silently trimmed. For example, if the current heading is pi/3 and the desired
heading is pi/6, the deltaH would need to be -pi/6.
throttle is a commanded speed. A positive throttle value represents motion in the
direction of the heading. throttle should be a value between -1 and 1, where negative
throttle commands the bot backwards. A throttle value of 1 will move the bot at a speed
of 1 world unit per second. The energy per timestep required for a throttle setting of 1 is
move_cost.
action is a string containing the bot action for this turn. See Section 2.3 [Actions],
page 7.
Chapter 2: Programming Basics 7

2.3 Actions
To perform no action at all, simply return ’none’, or empty (’’), for action.

2.3.1 Rifle
’rifle’ fires a bullet along the bot’s next heading (current heading + deltaH). The speed
of the bullet is: rifle_speed, radius of the bullet damage is rifle_radius, damage caused
by a hit is rifle_damage, and the energy required to fire a bullet is rifle_cost.
Currently, the engine models a rifle shot by a straight line of tangent circles. This leaves
significant gaps along the path that a bot may find itself in. This behavior may change in
the future and it is encouraged to treat bullets as rectangular envelopes along the path of
the bullet.
Bullets disappear after leaving the bounds of the world. They will also disappear after
striking a target. If two targets are on top of each other (or both within rifle_radius)
both targets will be damaged. This allows a single rifle shot to damage more than one bot
at a time.

2.3.2 Mine
’mine’ drops a mine at the bot’s current location. The mine explodes and disappears when
a player comes within its detection radius, mine_radius. The blast radius (the distance
where bots receive damage) is equal to the detection radius. The damage caused by a mine
is mine_damage. The energy required to drop a mine is mine_cost.
A mine sits passively on the ground until another bot who can be damaged by the mine
comes too close. If no bot ever approaches the mine, the mine will sit there forever (or until
the game ends). If two bots wander in range at the same time, they will both be hurt.

2.3.3 Grenade
’grenadeD’ will toss a grenade in the direction of the heading to a distance of D, where D is a
floating point value. A negative value for distance will result in a grenade tossed backwards.
The maximum distance a grenade can be tossed is determined by grenade_throw_max.
Grenade toss heading and distance values are both padded with uniform random values
to give them slight inaccuracy. The random padding amount is determined by grenade_
dfuzz (distance) and grenade_rfuzz (heading).
A grenade explodes upon reaching its toss distance. This explosion releases grenade_
bits rifle shots evenly in all directions from the explosion. The explosion itself does no
damage. Note that when team damage is enabled with team_damage, the rifle shots from
the grenade explosion can hurt the player that tossed the grenade.
This code will log a grenade 1.6 units in front of the bot,
% Toss a grenade 1.6 meters
action = [’grenade’ num2str(1.6)];
A grenade costs grenade_cost and travels at a speed of grenade_speed.

2.3.4 Health to Energy


’HtoE’ will convert health to energy. The amount converted is indicated by appending the
amount to convert onto the action string. For example, to convert 10 health to energy, the
Chapter 2: Programming Basics 8

action string would be ’HtoE10’. The conversion rate between health and energy is stored
in health_energy_ratio. You might code it as,
% Convert 10 health to energy
action = [’HtoE’ num2str(10)];
Attempting to convert health into more energy than you can add is safe, i.e. a bot will
not lose health when energy is maxed out. A bot can, however, kill itself by transferring all
health to energy.
This process also works in reverse to convert energy to health. Do this by appending a
negative number. For example, ’HtoE-8’ will convert energy into 8 health.

2.3.5 Self Destruct


’destruct’ will cause the bot to instantly die leaving behind an explosive with blast ra-
dius destruct_radius. This explosive will go off after a length of time destruct_time.
Remember to take the time step into account. This means the explosive will go off in
destruct_time/ts steps.
Note that if the last remaining bot on a team does this, the team will be eliminated
before the explosive goes off. This could mean the end of the game and the self destruct
damage never happens.

2.4 Requests
Currently there are three requests that the engine makes. There may be more in the future,
which means that a bot should always return values and be prepared for unknown requests.
Basically this means a bot should ignore unknown requests by returning empty or zero
values when they come up.

2.4.1 Clean and Preclean


Before every game, the engine will send a ’preclean’ requests to every bot. The state
vector (the first argument) will be empty, which may cause simple bots to declare victory.
The player vector is provided as this may be important in choosing filenames.
Use this to prepare any data files that are needed for the game. More importantly, it
allows the bot to clean up files that may be left over from previous games that may interfere.
At the end of every game, the engine will send a ’clean’ request to each bot, again
with an empty state vector but valid player vector. A well behaved bot removes its game
files.

2.4.2 Selfplot
The ’selfplot’ request is a query to the bot about drawing preference. That is, if the bot
responds with a yes, the bot indicates that it would like to handle its own drawing routines
with eplot (see Section 4.3 [Bot Plotting], page 18).
To reply with a yes, the action field must be equal to ’selfplot’, the same as the
request. The simplest way to respond in the positive is,
if strcmp(req, ’selfplot’)
deltaH = 0;
throttle = 0;
Chapter 2: Programming Basics 9

action = req;
return;
end
The bot’s drawing should generally remain inside of a 0.25 by 0.25 area, or within radius
of 0.125. For visibility purposes, the heading line may extend beyond this limit, just as the
heading_length probably does. But do not let these boundaries interrupt creative juices,
of course!
If the bot’s drawing shape is not going to be radial (like the default circle shape), it
would be wise for the bot to rotate its drawing to match its new heading. This can be done
with a rotation transformation,
rotation_matrix = [ cos(heading) -sin(heading) ; ...
sin(heading) cos(heading) ];
If the bot’s drawing vectors are stored in x and y,
rotated_vectors = rotation_matrix * [ x ; y ];
And then we just plot this,
eplot (rotated_vectors(1,:), rotated_vectors(2,:), ...
’Color’, player{9});
This example will draw a bot as a box with a heading line,
engine_settings;

px = player{1};
py = player{2};

x = [-1 1 1 -1 -1] * .125;


y = [ 1 1 -1 -1 1] * .125;

% new heading
nh = player{8} + deltaH;

rot_mat = [cos(nh) -sin(nh); sin(nh) cos(nh)];


p = rot_mat * [x;y];

% Box
eplot(p(1,:) + px, p(2,:) + py, ’Color’, player{9});

% Heading
eplot( ...
[px, px + cos(nh) * heading_length], ...
[py, py + sin(nh) * heading_length], ...
’Color’, player{9});
The box will rotate to face the same direction as the bot.

2.5 Objects
Currently, all bots can see all objects in the game field, which includes the bullets from
’rifle’ shots. This means a bot can dodge bullets if it is clever enough.
Chapter 2: Programming Basics 10

All object state vectors (see Section 2.1 [Data Structures], page 5) begin with the name
of the object.

2.5.1 Rifle Object


The rifle state vector looks like this,
1. Object name (’rifle’)
2. X position
3. Y position
4. Heading
5. Team
6. Player
7. Color
The bullet is at (x-position, y-position) and moving in direction heading. The shot was
fired by player and belongs to team team. When friendly_fire (see Section 1.2.1 [World
Settings], page 2) is on, the team field is ignored by the engine. The color value may be
useful with eplot (see Section 4.3 [Bot Plotting], page 18).

2.5.2 Mine Object


A mine is basically a bullet that does not move. Or, perhaps, a bullet is a mine that moves.
Here is the state vector,
1. Object name (’mine’)
2. X position
3. Y position
4. Team
5. Player
6. Reserved
7. Color
The mine is located at (x-position, y-position), belongs to team team and bot player. If
friendly_fire (see Section 1.2.1 [World Settings], page 2) is on, the team field is ignored
by the engine. The reserved field was originally reserved as a list of bots that can see the
mine. This is not implemented and this field is empty for now.
The color value may be useful with eplot (see Section 4.3 [Bot Plotting], page 18).

2.5.3 Grenade Object


The grenade object is thrown by a player (see Section 2.3.3 [Grenade], page 7). It travels a
certain distance and then explodes into grenade_bits rifle shots.
1. Object name (’grenade’)
2. X position
3. Y position
4. Heading
5. Team
Chapter 2: Programming Basics 11

6. Player
7. Color
8. Distance to target
The grenade is located at (x-position, y-position) and traveling in the direction heading
at grenade_speed. When distance to target is 0, the grenade explodes. The resulting rifle
shots will belong to team team and player player.

2.5.4 Destruct Object


The self destruct object is left behind when a player self destructs with action ’destruct’
(see Section 2.3.5 [Self Destruct], page 8).
1. Object name (’destruct’)
2. X position
3. Y position
4. Team
5. Player
6. Timer
7. Color
The destruct object is located at (’x-position’, ’y-position’). It belongs to team team
and player player (now dead). It will explode when the timer reaches zero.
Chapter 3: Creating a Bot 12

3 Creating a Bot

This chapter will go through a step-by-step process of creating a simple seek and destroy
bot that has memory. Even if you think you are ready to get started, you should take a look
at this chapter to see how to avoid making some mistakes. It is also a guide on creating
well behaved bots.

3.1 Initialization
First, you should drop in the function boilerplate (with your bot’s name) at the top of the
file,
function [deltaH throttle action] ...
= bot_name (state, player, objects, req)
Replace bot_name with the name of your bot (and the m-file).
Every non-trivial bot should call engine_settings at the beginning of the bot’s code.
This will provide access to all of the game settings. This will allow you to write a bot that
doesn’t contain magic numbers or is tuned to any particular configuration.
Another good idea is to set all of the outputs in the case that they are not set later
before the function returns.
deltaH = 0;
throttle = 0;
action = ’’;

3.2 Handling Requests


Below is a boilerplate for handling requests,
if isempty(req)
% Continue as normal
elseif strcmp(req, ’preclean’)
% Initialize files and external data
elseif strcmp(req, ’clean’)
% Clean up any created files and external mess
else
% Ignore (unknown request)
deltaH = 0;
throttle = 0;
action = ’’;
return;
end
Putting this near the top of the bot program will allow the bot to handle incoming
requests before doing anything unnecessary. The above example handles ’clean’ and
’preclean’ while ignoring unknown requests.
See Section 2.4 [Requests], page 8.
Chapter 3: Creating a Bot 13

3.3 Moving and Shooting


Moving involves setting throttle to anything but 0. It is limited to values between -1 and
1, but values exceeding these are silently trimmed. This may allow the bot logic to be more
elegant and simple.
throttle = 0.5;
For shooting, we will use the ’rifle’. By setting action to ’rifle’, the bot fire a
single shot along the bot’s heading. If action always equals ’rifle’, the bot will constantly
fire.
action = ’rifle’;
When deciding how to shoot, it is important to note the order in which the engine will
execute the bot actions,
1. Changes heading by deltaH.
2. Executes the action (rifle, mine, etc.).
3. Moves the bot a distance of throttle * ts along the new heading.
4. Moves and evaluates objects, causing damages where necessary.
If the return values are [ -pi/8, 1, ’rifle’ ], the bot will change heading first, fire a
rifle second from the current location along the new heading, and move to a new location
third.
So with the code below, we have a bot that goes in a circle and fires constantly (really
it fires until it is out of energy). Copy any paste this into a new bot function to try it for
yourself.
throttle = 0.5;
deltaH = pi / 8;
action = ’rifle’;
This simple bot is a well behaved bot that will correctly handle all requests.

3.4 Memory
Memory involves saving variables that a bot may need later into a ‘.mat’ file. This mat file
should be unique for the bot, or at least the bot’s team. If it isn’t, the bot may interfere
with enemy bots attempting to use the same file.
Here is an example of memory being used to reduce the fire rate of the bot in the previous
section,
datafile = [’example-bot-’ num2str(player{6}) ’.mat’];

if exist (datafile, ’file’)


load (datafile);
else
rifle_timer = 0;
end

% This code is from before


deltaH = pi / 8;
Chapter 3: Creating a Bot 14

throttle = 0.5;

% Do we shoot now?
if rifle_timer > 20
% reset timer
rifle_timer = 0;

action = ’rifle’;
else
action = ’’;

% increase timer
rifle_timer = rifle_timer + 1;
end

save (datafile, ’rifle_timer’);


The name for the bot will be unique, based on the player number. This will allow many
of these bots in a single game without any of them using the same file. Before the bot
finishes, it saves the data to the ‘.mat’ file for the next turn.
There are two issues with this bot that prevents it from being a well behaved and well
written bot,
• It does not clean up after itself.
• It uses a magic number, 20.
The first issue is resolved by adding a check for the clean request, which should be placed
just after datafile is set,
if strcmp (req, ’clean’) && exist (datafile, ’file’)
delete (datafile);

% do nothing more
deltaH = 0;
throttle = 0;
action = ’’;
return;
end
The second issue is resolved by using the actual values for the energy regeneration rate,
energy_regen and the rifle energy cost, rifle_cost. We also want to take into account
that we are moving (at cost move_cost) and the energy regeneration rate is lower. First,
the bot needs to obtain these values,
engine_settings;
Now use the values,
if rifle_timer >= rifle_cost / (energy_regen - throttle * move_cost)
...
end
The bot will now fire at the same rate that its energy regenerates, helping ensure that
it will never run out of energy. With certain settings, there may be issues with divide by
Chapter 3: Creating a Bot 15

zero and negative numbers. This is left as an exercise to the reader (because we don’t feel
like writing it out!).
A full listing of this bot’s code is in Appendix A [Simple Example], page 22.

3.5 Targeting
Continuing the use of the above code, we will add targeting to the code. There is no official
targeting interface. A bot just picks an enemy bot and sticks with it.
This example will pick an enemy bot at random, remember that bot as a target, and
pursue the bot until it is dead. The full code for this bot is available in the appendix.
Appendix B [Targeting Bot], page 23.
We want to store our target in memory (the .mat file) so we know who we have targeted
later. We will adjust the save command at the end of the code,
save (datafile, ’rifle_timer’, ’target’);
We also want to initialize the target, so we will put this below the initialization of
rifle_timer,
else
rifle_timer = 0;
target = -1;
end
We set it to -1 because no bot will ever have this number. It will force the bot to choose
a target right away.
Let us now check to see if our current target is alive.
target_index = -1;
for i = 1:length(state)
if state{i}{6} == target
target_index = i;
break;
end
end
If our target is dead, target_index was never set. In this case, let’s choose a new target
at random. To do this, we will need to create a list of enemy bots,
enemy_list = [];
enemy_index = [];
for i = 1:length(state)
if ~strcmp(state{i}{5}, player{5});
enemy_list = [enemy_list state(i)];
enemy_index = [enemy_index i];
end
end
If there are no enemies, we do nothing.
if isempty(enemy_list)
deltaH = 0;
throttle = 0;
Chapter 3: Creating a Bot 16

action = ’’;
return;
end
enemy_list is now a non-empty list of enemies for us to choose from. Choose one at
random,
sel_index = ceil (rand * length(enemy_list));
target = enemy_list{sel_index}{6};
target_index = enemy_index(sel_index);
Now we have a target and know it’s index into the state vector. Let’s turn our bot to
face this enemy at his current position. In this example, we will not attempt to predict
enemy movement and shoot there. This is left up to you, the bot programmer, to solve.
There are many different ways to solve this problem, some better than others.
Calculate the heading required to face the other bot,
target_heading = atan2(state{target_index}{2} - player{2}, ...
state{target_index}{1} - player{1});
Now we set deltaH to this difference, causing the bot to turn in the correct direction,
deltaH = target_heading - player{8};
This completes our search and destroy bot. For the full code, see Appendix B [Targeting
Bot], page 23.
Chapter 4: Bot Behavior 17

4 Bot Behavior

4.1 Well Behaved Bots


To encourage bots that interface well with the engine and other bots, we will define a “well
behaved” bot. A well behaved bot should,
• Be quiet.
• Always return three values.
• Properly handle all requests.
• Not intentionally sabotage other bots.
Now, to detail this information.
A bot should not produce any junk output. This includes both output in the Matlab
command line window as well as putting junk on the game window. Extra plotting on the
game window is allowed, as long as it does not interfere with watching the game, i.e. don’t
fill the plot will garbage.
A bot should always return three values, especially with unknown requests. This leads
us into the next item.
A bot should be able to take any request. If a request is not known, it should do nothing
but return empty or zeroed values.
And finally, a bot should not sabotage another bot. That is, a bot should only compete
with another bot within the game engine. Attempting to modify another bot’s ‘.mat’ file
would be a violation of this rule.
Of course, your bot does not have to be well behaved. This is a just a set of guidelines.
The most interesting bots may not follow these guidelines at all.

4.2 Useful Functions


There are functions that you may find useful in the ‘func’ directory (including eplot).
Many of these are drawing functions that can be called to give a bot a different look.

4.2.1 drawface
This function draws a face,
function drawface (xpos, ypos, heading, radius, color)
The face is drawn at (xpos, ypos) leering in direction heading. Its size is radius and
color is color. Generally, you will want to pass player{9} in as the color.

4.2.2 drawghost
Draws a ghost from the famous game Pacman,
function drawghost (xpos, ypos, heading, radius, color)
The Pacman ghost is drawn at (xpos, ypos) drifting in direction heading. Its size is
radius and color is color. Generally, you will want to pass player{9} in as the color.
Chapter 4: Bot Behavior 18

4.2.3 drawhand
Draws a hand proudly displaying its favorite finger,
function drawhand (xpos, ypos, heading, radius, color)
An offensive drawing is plotted at (xpos, ypos) pointing in direction heading. Its size
is radius and color is color. Generally, you will want to pass player{9} in as the color.

4.2.4 drawenterprise
Draws the starship Enterprise (from Star Trek),
function drawenterprise (xpos, ypos, heading, radius, color)
The Enterprise is drawn at (xpos, ypos) engaging in direction heading. Its size is radius
and color is color. Generally, you will want to pass player{9} in as the color.

4.2.5 dodge bullets


This function tells a bot if it needs to dodge and, if needed, where to dodge. It is simple,
providing adequate dodging abilities, and is much faster than the more complex dodging
algorithms contained in some of the bots.
function [indanger deltaH throttle] = ...
dodge_bullets (player, objects)
If the bot is currently in danger from existing bullets, indanger will be set to true. If the
bot is in danger, deltaH and throttle are the return values the bot should use to escape
the danger.

4.3 Bot Plotting


Bots may draw plots and text in the game area through the eplot interface. eplot auto-
matically checks the engine settings to determine how the plot is handled, if at all. The
plot will also be recorded in the game script recording (see Section 1.2.2 [Display Settings],
page 3).
eplot is able to do any plot that plot can do. eplot can also insert text with the
’text’ argument and do fill with the ’fill’ argument. When using plot, all arguments
to eplot are passed to the plot command when a plot is made. For example,
eplot (cos (0:0.1:2*pi) * 3 + player{1}, ...
sin (0:0.1:2*pi) * 3 + player{2}, ...
’Color’, player{9});
This will plot a circle with the player’s color of radius 3 on top of the bot. This circle
will show up on all recordings and will only be plotted during a game when display_game
is set (see Section 1.2.2 [Display Settings], page 3).
eplot can also handle text information. You can use this to add some personality to a
bot. To use it, the first argument is ’text’ and all remaining arguments are arguments to
text.
eplot (’text’, player{1}, player{2} + 0.3, ’BOOM! HEADSHOT!’);
Will display “BOOM! HEADSHOT!” over the bot.
eplot can also handle fill. To use it, the first argument is ’fill’ and all remaining
arguments are arguments to fill.
Chapter 4: Bot Behavior 19

eplot (’fill’, ...


[-1 -1 1 1 -1] * 0.125 + player{1}, ...
[ 1 -1 -1 1 1] * 0.125 + player{2}, ...
player{9});
Will display a non-rotating filled box of the bot’s color at the bot’s location.

4.4 Existing Bots


Several bots are already be written, some of which should be useful in debugging and testing
the bots that you are writing. Others are good for studying techniques to be used in your
bots.

4.4.1 Target Dummies


This collection of bots is great for testing your bots, especially targeting algorithms. Until
you have polished your bot, these will be often be the enemy.
The zombie bot travels in a straight line until it reaches the edge of the map, where it
will “bounce” off in some other direction. It works well for early target practice to make
sure your bot can hit targets moving in straight lines. They are also useful for testing your
bots against opponents from all around the game area, as these bots will quickly be all over
the place.
The circler does what its name indicates: it goes in circles. Use this bot to test tar-
geting algorithms because circular motion can actually be tricky to hit unless specifically
programmed for it.
The dummy bot is another good bot for target practice. Their movement is completely
erratic, with all return values random. This bot will even shoot randomly.
The minelayer is a zombie that drops mines. Drop in several and the game are will be
filled with mines. They turn into a dummy bot when low on energy. If you are testing your
bot on avoiding mines, use this guy.

4.4.2 Team Bots


These bots communicate with each other and will work together as a group to achieve goals.
The teamsnipe bot does not move. They stand in place, all agree on a common target,
and fire in unison as a team until that target dies.
The fallback bot will “fall back” into formation in the nearest corner of the game area.
Most will act as a defensive shield while the inside bots will concentrate on firing on targets
(just by calling teamsnipe).
The goose bot will fly in formation with the other geese on the team. They gather into
a V (or really a triangle) and attack a common target while closing in. A seek and destroy
group.
The uzi bot is the most deadly bot ever created. These guys will work as a team to
quickly eliminate several other bots in the first few seconds of the game (as long as they
are not evasion bots, Section 4.4.3 [Evasion Bots], page 20).
Chapter 4: Bot Behavior 20

4.4.3 Evasion Bots


Evasion bots tend to work alone. Their main feature is evading bullets fired from other
bots, giving them huge survivability. They can easily take on many of the above bots at
once and win. These are the best bots in the game right now.
The evader bot, being first of its kind, is extremely passive and holds no grudges. It will
quietly dodge anything thrown at it. It does need privacy, however. If someone gets too
close, all hell will break loose as it unloads all of its energy on the rude, offensive bot.
The snitch is currently the number one bot, but it requires immense CPU time compared
to other bots. It will dodge just about anything you can throw at it and can quickly eliminate
other opponents early on. Currently, however, the snitch is no good at close combat.
Chapter 5: Human Interface 21

5 Human Interface
A human interface exists to allow you to control a bot during the gameplay. In situations
where the game has slowed way down, control may become very difficult.
Currently, only joystick input is available. Until other interfaces are figured out, this will
be the only human input. You will need to have Simulink, but no special Simulink packages.
An s-function has been written in C to interface the with joystick. This s-function is placed
inside Simulink where values can be pulled from the joystick inputs.
Adjustments to the “human*.m” bots may be needed to fit your joystick. The values
are obtained in the call,
sim(’getjoy’);
The joystick input is still experimental and has not been tested very much. Getting it
to work may take some effort. Or, it may just work for you.
The axis values are stored in the array joyaxis, buttons in joybutton and the hat
in joyhat. Axis values are between -1 and 1. Buttons are either 0 (unpressed) and 1
(pressed). The hat values are between 0 and 8 inclusive, indicating the 9 possible hat
positions. Experiment to find out what values match what joystick inputs.
“human” is a simple interface for a single stick joystick. Forward and backward control
throttle. Left and right control heading changes.
“human tank” is made for two stick gamepads. Controls work like tank treads. Forward
is both sticks forward. Backward is both sticks backward. Turning is full back on one and
full forward on the other. Combinations in between these lead to circular movement.
“human hdcmd” (heading command) is what many people will find as the most comfort-
able, but it requires three axes. This will work fine on a normal joystick with a “throttle”
axis. The joystick directly commands the heading and the third axis controls the throttle.
This input type allows for maximum control of the bot.
Appendix A: Simple Example 22

Appendix A Simple Example


function [deltaH throttle action] ...
= example_bot (state, player, objects, req)

engine_settings;

datafile = [’example-bot-’ num2str(player{6}) ’.mat’];

if strcmp (req, ’clean’) && exist (datafile, ’file’)


delete (datafile);

% do nothing more
deltaH = 0;
throttle = 0;
action = ’’;
return;
end

if exist (datafile, ’file’)


load (datafile);
else
rifle_timer = 0;
end

% This code is from before


deltaH = pi / 8;
throttle = 0.5;

% Do we shoot now?
if rifle_timer >= rifle_cost / (energy_regen - throttle * move_cost)
% reset timer
rifle_timer = 0;

action = ’rifle’;
else
action = ’’;

% increase timer
rifle_timer = rifle_timer + 1;
end

save (datafile, ’rifle_timer’);


Appendix B: Targeting Bot 23

Appendix B Targeting Bot


function [deltaH throttle action] ...
= target_bot (state, player, objects, req)

engine_settings;

datafile = [’target-bot-’ num2str(player{6}) ’.mat’];

if strcmp (req, ’clean’) && exist (datafile, ’file’)


delete (datafile);

% do nothing more
deltaH = 0;
throttle = 0;
action = ’’;
return;
end

if exist (datafile, ’file’)


load (datafile);
else
rifle_timer = 0;
target = -1;
end

target_index = -1;
for i = 1:length(state)
if state{i}{6} == target
target_index = i;
break;
end
end

if target_index == -1
enemy_list = [];
enemy_index = [];
for i = 1:length(state)
if ~strcmp(state{i}{5}, player{5});
enemy_list = [enemy_list state(i)];
enemy_index = [enemy_index i];
end
end

if isempty(enemy_list)
deltaH = 0;
throttle = 0;
Appendix B: Targeting Bot 24

action = ’’;
return;
end

sel_index = ceil (rand * length(enemy_list));


target = enemy_list{sel_index}{6};
target_index = enemy_index(sel_index);
end

% Now we set deltaH to point to this bot


target_heading = atan2(state{target_index}{2} - player{2}, ...
state{target_index}{1} - player{1});
deltaH = target_heading - player{8};

% Constant throttle
throttle = 0.5;

% Do we shoot now?
if rifle_timer >= rifle_cost / (energy_regen - throttle * move_cost)
% reset timer
rifle_timer = 0;

action = ’rifle’;
else
action = ’’;

% increase timer
rifle_timer = rifle_timer + 1;
end

save (datafile, ’rifle_timer’, ’target’);


Index 25

Index

A I
action . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 initialization. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
actions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

B M
boilerplate . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 magic number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
box . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
mine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
mines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
C movement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4, 13
circle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
clean. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
color . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 O
objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6, 9
order of execution . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
D
deltaH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4, 6
destruct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 P
display settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 player list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
player mask . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
player number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
E player position . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
energy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 5 player settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
energy to health transfer . . . . . . . . . . . . . . . . . . . . . . 7 player list.txt. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
engine settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2, 18 preclean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
engine.m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
engine settings.m . . . . . . . . . . . . . . . . . . . . . . . . . . 2, 12
eplot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8, 18
R
execution order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 radial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
record . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 18
record game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
F requests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6, 8, 12
face . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 rifle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 10
fill . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
friendly fire. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 rotation transformation . . . . . . . . . . . . . . . . . . . . . . . 9
func . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
function handle . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2, 5 S
function name . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
script game. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
self destruct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8, 11
G selfplot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
grenade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7, 10 settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
grouping teams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 shooting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
state vector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 6, 9
suicide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
H
heading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5, 6 T
headshot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 target dummies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
health . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3, 5 targeting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
health to energy transfer . . . . . . . . . . . . . . . . . . . . . . 7 text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
hiding player information . . . . . . . . . . . . . . . . . . . . . . 2 throttle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6, 13
human . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 transfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Index 26

U world . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
unique filename . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 world settings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

W Z
well behaved . . . . . . . . . . . . . . . . . . . . . . . 6, 13, 14, 17 zombie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

You might also like