L33TWAR

[Download]
What is L33TWAR?
L33TWAR is a simple game with up to 16 tanks distributed between the red and blue teams. Each team attempts to capture the other team's flag and return it to their own base. Naturally, these tanks have guns and if you are shot, you are temporarily out of service until you respawn.
L33TWAR can be a lot of fun to just play around with, but the really interesting thing about L33TWAR is that you can program the AI for the bots! L33TWAR will load up to two DLLs which can be used for any tank on either team; the set of functions implemented by this DLL will control how it reacts to the environment. That way you can concentrate on interesting AI and tactics without having to write the whole game yourself, as it's already been written.
Visit the Official L33TWAR Website
L33TWAR Information (copied from official site)
GameDev Bots
Download these bots and watch how they play:
How do I create the DLL?
Writing a DLL is not that difficult if you have an example to go from and the right development environment. Here's what you need:
- An IBM-Compatible computer
- Microsoft Visual Studio 6
- Knowledge of C++
- Source Code
Download one of the following L33TWAR bot-sources to get started (create a copy of the source & modify as needed):
First just try to open the AI_Random project in Microsoft Visual Studio and do a Build. Hopefully a DLL will be created in your Debug/ directory; copy that into your L33TWAR installation directory and load it when you run the game (the game will show you a list of valid DLLs--don't type the .dll file extension).
How does the DLL work?
Basic Idea
Okay, first off, up to two DLLs are loaded at the start of the game. Then, after placing bots on teams, a certain number of instances of your bot are created on each team. Then, once the game starts, there is a call to UpdateBot for every bot a large number of times every second. The exact period of time between updates in unknown and it is believed that it varies depending on lag or computer speed.
Inbetween frames, bots (and players) generally keep doing what they were doing at the end of last frame. The whole trick of writing a bot is to decide every millisecond or so, how to react to the environment. Consequently, having some sort of memory or speed optimization can be key to avoiding ridiculous lag.
DLL Functions
The following functions must be implemented in the DLL:
void* AI_CreateBot();
- Called when a new bot is created
void AI_DestroyBot(void*);
- Called when a bot is removed
void AI_ReportMap(const CMapInfo*);
- Called whenever a new map is loaded
void AI_ReportEntities(CBullet**, int bcount, CPowerup**, int pcount);
- Called once a frame to update the entities (powerups, bullets)
void AI_ReportPlayers(CPlayerState**, int count);
- Called once a frame to update the players (the tanks)
void AI_ReportGameInfo(int time, int blue, int red);
- Called every frame; reports score, etc.
int AI_UpdateBot(int playernum, void*);
- Called every frame on every tank; this is where the action happens.
SDebugAIInfo* AI_GetDebugInfo();
- Called after players are updated to display debugging info
Now, as it turns out, these functions are already implemented in the Random and Linebot DLLs, so simply use those and modify as necessary (with care). Typically what happens is that you create a bot class (CRandomBot for example) and the C DLL functions simply create an instance of that class or update it with a member function.
AI_UpdateBot
As mentioned previously, AI_UpdateBot is the most important function call of the whole DLL. It must return an integer; this integer represents the action taken by the tank. Return any meaninful combination of the following:
PFLAG_SHOOTING = 0x1;
- the player is firing his weapon
PFLAG_FORWARD = 0x2;
- the player is moving forward
PFLAG_BACKWARD = 0x4;
- the player is moving backwards
PFLAG_LEFT = 0x8;
- the player is turning left
PFLAG_RIGHT = 0x10;
- the player is turning right
Dll_Globals
The Dll_Globals interface allows you to access every piece of information a bot might need to decide what to do every frame. Basically you use it to call one of the following functions:
The proper way to call these is g_globals.getPlayerStates();
Dll_Debug
The Dll_Debug interface lets you add lines, messages, boxes, and even circles to the screen in an attempt to figure out where your code has gone awry, and provides the following functions:
void clearData();
- clear the debug buffer
void addMessage(float x, float y, unsigned int color, char* message);
- add a debugging string to the screen
void addLine(float x1, float y1, float x2, float y2, unsigned int color);
- add a debugging line to the screen
void addBox(float x, float y, float width, float height, unsigned int color);
- add a debugging box to the screen
void addCircle(float cx, float cy, float radius, unsigned int color);
- add a debugging circle to the screen
unsigned int createColor(unsigned int alpha, unsigned int red, unsigned int green, unsigned int blue);
- create a color for use in debug output
The proper way to call this is g_debug.addLine(50, 50, 100, 100, CAIDebug::createColor(255, 255, 0, 0));
It may prove useful to call clearData() once every frame in AI_ReportPlayers(). This prevents the debug buffer from overflowing and lets you see all your debug info.
AI_Player
For any player, you can get a number of interesting tidbits on that player, with the following functions:
There's no proper way to call these; the playerstates are referenced by the call to g_globals.getPlayerStates().
In addition, there is a public member variable int u_flags with the following possible flags:
PFLAG_SHOOTING = 0x1;
- shooting its weapon
PFLAG_FORWARD = 0x2;
- moving forward
PFLAG_BACKWARD = 0x4;
- moving backward
PFLAG_LEFT = 0x8;
- turning left
PFLAG_RIGHT = 0x10;
- turning right
PFLAG_DEAD = 0x20;
- dead
PFLAG_HASFLAG = 0x100;
- has the flag
PFLAG_W_SHOTGUN = 0x40;
- has a shotgun
PFLAG_W_SPAMGUN = 0x80;
- has a spamgun
PFLAG_W_PONGGUN = 0x400;
- has a ponggun
PFLAG_SHIELD = 0x2000;
- has a shield
PFLAG_REDTEAM = 0x200;
- on the red team (false if blue)
PFLAG_SPECTATE = 0x1000;
- a spectator or not
One note here: Having a shield means that your teammates cannot hurt you, and that it now takes two enemy bullets to kill you.
AI_Map
The current map has the following functions which may be called upon it:
int getBlockWidth();
- Returns the block width
int getBlockHeight();
- Returns the block height
int getPixelWidth();
- Returns the pixel width of the screen
int getPixelHeight();
- Returns the pixel height of the screen
bool isPositionBlocked(int pixelx, int pixely);
- Determines if a pixel location is "blocked"
bool isBlockBlocked(int blockx, int blocky);
- Determines if a row/column location is "blocked"
int getTypeAtPosition(int pixelx, int pixely);
- Gets the area type at a pixel location
int getTypeAtBlock(int blockx, int blocky);
- Gets the area type at a row/column location
In addition, the area types are:
BT_NONE = 0
- open field
BT_BLOCKED
- blocked area
BT_BLUE
- blue base
BT_RED
- red base
BT_BLUEFIELD
- blue "perimiter", blue players have a greater chance to spawn here
BT_REDFIELD
- red "perimiter", red players have a greater chance to spawn here
BT_PUSHUP
- pushing floor, will move players up
BT_PUSHDOWN
- pushing floor, will move players down
BT_PUSHLEFT
- pushing floor, will move players left
BT_PUSHRIGHT
- pushing floor, will move players right
Bullets and Powerups
I could give you that information, but I'm sure that you can figure it out on your own. Seriously.
What kind of cool stuff could I write for my bot?
Here's a list of things that have either been done, or would be really cool to see:
- Bots which pathfind around obstacles using A*, shortest-path, wall-tracing & memory, waypoints, or maybe even a binary-space partition
- Bots which can dodge bullets
- Bots which can predict where another tank is moving to and fire at that location instead of the enemy tank's current location
- Bots which collaborate intelligently or move in packs to get the flag
- Bots which can "snipe" by using the ponggun intelligently
- Bots which "learn" using a neural net or fuzzy logic or other stuff like that
- Bots which can spank the competition
What are some helpful constants?
Q: How fast does a player move?
A: 100 pixels per second
Q: How fast does a bullet move ?
A: 600 pixels per second
Q: When does the bullet hit the player ?
A: The bullet must be within 4 pixels (ie, dx > -4 && dx < 4)
Q: How much do the moving tiles affect the tank speed?
A: The moving tiles affect tank movement by +/- 50 pixels a second
Q: How fast can the tank turn?
A: On average, about 5.06708 radians / second.
Q: How big are the blocks?
A: The blocks are 32x32 pixels each.
Q: What are the weapon firing rates?
A: Delay between firings for Normal, Ponggun, Shotgun, Spamgun is on the ratio of 300:300:500:100 ms (Spamgun is very fast; shotgun is very slow)
Q: What are the fire spreads for the Spamgun and Shotgun?
A: Spamgun spread is +/- 0.05 radians. Shotgun spread is +/- 0.15 radians.
Q: How long do players remain dead?
A: 2 seconds.