TDDD63: XPilot-AI project
Computer games have given rise to a huge industry in the latest decade or two. As you are certainly aware of, these games are generally interactive: You – the player – must personally control what happens for a long period of time. In a racing game you must control a car, choosing the right gear and steering in the right direction. In Tetris you must move and rotate colored blocks, and so on. This obviously takes a lot of time. Wouldn't it be nice if you had someone else who could play the games for you, relieving you of this great burden and allowing you to spend more time developing software instead?
Well, maybe not. But it can still be a lot of fun to take a completely different approach to gaming: Trying to write a bot, a software robot, that plays the game for you. This idea is not new and has in fact led to the concept of programming games, where you can measure your programming skills against those of your opponents or simply against the game itself.
Programming games have history of over 50 years, going back at least to the year 1961 when Darwin was invented. In this programming game, players were executed on an IBM 7090, a multi-million-dollar 0.46 MHz 36-bit mainframe (not 32!) with 144 kB of memory that was one of the first generations of computers running on transistors rather than vacuum tubes.
Fortunately for you we do not have such a system available, so you will instead be using Python on the IDA Sun machines. You will also use a different game as the basis for your bots. There is a classic game called XPilot where the players control a spaceship flying around and trying to shoot the enemy. XPilot-AI is an existing project that adds the possibility to write Python programs that control the spaceships using artificial intelligence (AI). The goal of your TDDD63 project, then, will be to write programs that implement intelligent agents (bots) and teams of intelligent agents that control the spaceships.
The official XPilot-AI is maintained at Connecticut College, but over the course of the summer John Litborn, a student at LiU, have forked the code and improved on it. The code is open source and anybody can read the code and report bugs, request features and submit patches. Interested students can contact him at firstname.lastname@example.org or through your assistant.
Start by reading the Wikipedia article about XPilot:
- Wikipedia: http://en.wikipedia.org/wiki/XPilot
To learn how to play XPilot read the tutorial here:
- XPilot tutorial: http://www.j-a-r-n-o.nl/newbie
Here is a list of useful links to browse when you need more information.
- Official XPilot site: http://xpilot.org/
- XPilot-AI fork: https://bitbucket.org/hatten/xpilot-ai-fork/
- List of server options/map settings: http://www.j-a-r-n-o.nl/xpilotserver.html
- Original XPilot-AI: http://xpilot-ai.org
Installation and Running Programs
On Student Sun Systems
The programs needed are already installed on the Sun system for students. The path to the binaries and libraries is:
You have to make sure that the binaries and libraries are found. To do that on the Sun system do the following:
module add /home/TDDD63/modulefiles/xpilot-ai
Or to permanently add it to an init file (you just have to do this once and then the module will be added automatically every time you log in):
module initadd /home/TDDD63/modulefiles/xpilot-ai
On Linux or Mac
If you want to run this on your own Linux computer, download and install the installation script. The script might not work completely out of the box and you might need some previous knowledge of the command-line to get it working.
On your platform you have to make sure that libraries and other files are found. Here is an example of how to do that in the .bashrc file when XPilot-AI is installed in /home/tompe/pkg/xpilot-ai:
# # Place the following three lines at the end of the .bashrc file # export LD_LIBRARY_PATH=/home/tompe/pkg/xpilot-ai/python:$LD_LIBRARY_PATH export PYTHONPATH=/home/tompe/pkg/xpilot-ai/python:$PYTHONPATH export PATH=/home/tompe/pkg/xpilot-ai:$PATH
It is possible to run these programs on a Sun server and still view their graphical user interface on your own computer, at home or at the university. To do this, you need an X Window System server (the standard Unix/Linux window system) on your own computer, where the GUI will be displayed. This is most likely already installed if you are using a Linux machine. If you are using Windows, you can install and use Xming.
If you do have an X Window System Server on your machine, you can
then log in to the
remote-und server at IDA using SSH. If
you are using Linux, you do the following:
ssh -X LiuId123@remote-und.ida.liu.se
This gives you a command prompt on
any graphical program started on that machine will be displayed on
your own computer. If you are using Windows, you will have to find
a suitable SSH client, for
example PuTTY (a PuTTY version
can optionally be installed during the Xming install process) and
configure it for X forwarding.
Virtual Ubuntu Machine
XPilot-AI currently does not work natively on Windows. If you still want to run the project locally on a Windows machine, one possible solution is to install Ubuntu 12.04 in a virtual machine. One way to do that is to install VirtualBox, create an Ubuntu 12.04 virtual machine, and then go through the Linux installation instructions above.
Different Python versions
Here is a list giving the default python3 version on different systems:
- IDA's Sun System: Python 3.2.2
- Ubuntu 12.04: Python 3.2.3
- Mac Mountain Lion 10.8: Seems not to be installed. If installing it yourself: Python 3.3.0
- Windows: No Python installed as default. If installing it yourself: Python 3.3.0
The assistant uses Ubuntu 12.04 and will use this to test against when getting email questions, so the best thing is not to use Python language constructs that only exist in later versions than 3.2.3!
Playing a Game
It is recommended that you play some games of XPilot to become more familiar with it and explore its functionality.
Starting a Server
The first step to take when you want to play a game of XPilot is to start a game server. It is important to know that if you want to start more than one XPilot server on the same computer you have to use different ports for the different servers. This may not be the case if you are working on your own computer, but several SunRay clients in the Sun PULs can connect to the same Sun server and therefore there could be conflicts with other groups, even those working in another PUL. Because of that the XPilot server should start on a unique port for different project groups if you are not running on a private computer. The default port is 15345. Each group has a number n and should use port 15345+n to avoid connecting to each other's servers. For example, group 5 uses the port 15350.
Start the server with the default map (assuming group 1):
xpilots -noQuit +reportToMetaServer -port 15346
+reportToMetaServer means that your locally
started server will NOT report to the central meta server that keeps
track of all currently running XPilot servers across the Internet.
This is to avoid having other players around the world joining your
game. You can also use +reportMeta, which is a shorter alias.
-noQuit will make the server stay alive after
every player quit. This is often convenient but you can remove the
option if that is undesired.
By default you can only connect 2 clients from the same IP number to a server.
To change that use the flag
-maxClientsPerIP. For example:
xpilots -noQuit +reportToMetaServer -port 15346 -maxClientsPerIP 10
Starting a Client
Start a client:
xpilot -join -port 15346
And then start playing (and reading if necessary) until you feel you understand the basic dynamics of the game.
When installing XPilots-AI some standard maps are installed. When starting the XPilot server with a specific map the full path to the map has to be given. On the Sun systems the path to the standard maps is:
For example, to start the XPilot server with the standard map cross.xp (assuming group 1):
xpilots -map /home/TDDD63/projects/xpilot-ai/maps/cross.xp -noQuit \ +reportToMetaServer -port 15346
There are some TDDD63 project specific maps available. Here is a description of some of them:
- simple.xp: A simple map with boundary which spaceships can crash into and die. The shotspeed for this map is set to 21.
- obstacle.xp: A simple map with boundary which spaceships can crash into and die and obstacles that have to be avoided. The friction for this map is set to 0.1.
To use the maps download them using the provided links or use them directly from the file system. On the Unix system these maps can be found in the directory:
To start the XPilot server with a map called simple.xp (assuming group 1).
xpilots -map /home/TDDD63/www-pub/projects/2013/xpilot/maps/simple.xp -noQuit \ +reportToMetaServer -port 15346
There is also a mapeditor
xp-mapedit that can be used
to edit existing maps or creating new maps. This is mostly useful in the project phase
since in the initial phase the provided maps should be used.
It is also possible to edit the map files in a text editor.
Python API for XPilot-AI
Note that if the documentation for example says:
int asteroidX(int i) - Returns the specified enemy's X coordinate.
Then the argument to
asteroidX must be
int. If it is not an
int the call will
throw an exception (signal an error).
int before the function name specifies the type of the value that the
Notice also that i stands for index. The respective count function, in this case
int asteroidCountScreen() - Returns the number of asteroids on the screen.
will give the number of valid items you can access with the index. Note that since the numbering starts at 0 the maximum index is one less than the number returned by the count functions. The API will return an error if you try to access an index that's out of the valid range.
Example Bot Code
The Python interface works in the way that it gets regular callbacks to a specific function that can do useful things. These kind of callbacks are sometimes called "ticks". The system ticks your program one step which usually corresponds to a specific time step.
So the bot code will get a call for each "tick" and you can then decide what to do. Exactly what should be done most probably depends on what has happened before, therefore that information must be stored. One way to do that is to implement the bot code as a state machine where the state in a sense encodes this history information.
Here is code for a minimal example, where the AI simply shoots every tick
import libpyAI as ai def AI_loop(): ai.fireShot() ai.start(AI_loop,["-name","Shooter"])
Here is the code for a stub program that can be used as a starting point for the bots that are going to be written in this project. In the current code the AI doesn't actually do anything, this is just a minimal example.
Running a Bot
If you have used the Python stub given above the bot program is started by using the group flag in the following way (assuming your program is called stub.py):
python3 stub.py --port 15346
Notice that is is possible to use the keyboard to control the spaceship when running the Python bot program.
Project: Introductory Phase
The project tasks for the introductory phase are to write one or more bot programs that do the tasks below. The tasks should be implemented in order. All tasks in the introductory phase have to be finished to pass the course and it is strongly recommended that they are finished before you have to start the main phase.
Shoot stationary targets
Goal: Destroy all targets before they reappear.
Provided code: exc1_code_skeleton.py
Description: In this exercise you will be guided by the skeleton code provided and you should follow the instructions in it. You should only have to enter code where it is said. The skeleton code also provides you with useful functions, if you need to look up how they work you can find links to them in the recommended functions.
Recommended functions: API control, Ship properties, Target, Turn, Angle handling, Shoot and Python's built-in angular conversion and trigonometric functions, especially math.atan2.
Goal: Complete all three laps.
Provided code: stub.py
Description: This exercise introduces a new game mode, race (or timing, as it's also called). Racing consist of flying by several checkpoints, predefined in the map file, completing a set amount of laps. The game restarts when the first person have completed all laps. Different maps have different settings on how close to a checkpoint you have to be to "get" it.
The easiest way to solve this exercise is to:
1. Save the or coordinates of the next checkpoint using nextCheckPoint, checkPointX and checkPointY.
2. Fly towards the checkpoint.
3. When close enough, brake the ship (turn around and thrust).
4. Goto 1
For this you need a minimum of two states, "travel" and "stop", but it can be useful to have more.
Recommended functions: Checkpoint, Movement and those introduced in exercise 1.
Goal: Shoot down all four targets before they respawn.
Description:This exercise is very similar to the first one, except for the map being bigger and the ship being able to move. Shots fired retains the velocity of your ship, so it is much easier to hit the targets if you slow down the ship. With no friction it is almost impossible to stop the ship completely, so your solution should not rely on that.
Recommended functions: All recommended functions have been introduced in earlier exercises.
Goal: Reach 100 points before running out of fuel.
Provided code: stub.py
Description: This exercise introduses asteroids, which are normally implemented as additional hazards on maps, but in this exercise there will only be asteroids, much like the classical game Asteroids.
Fuel is also introduced in this map. You lose fuel when thrusting, shooting and colliding with objects. If you collide with an asteroid with low fuel you will die. Avoiding asteroids is not a part of this exercise, so shoot them before they can reach you. Hint: The function getOption(string option) can be used to get the maps shotspeed.
Recommended reading: PlayTechs explains the math behind hitting a moving target.
Recommended functions: asteroid, radar, fuel and those introduced in earlier exercises.
Goal: Pick up 10 items without crashing.
Provided code: stub.py
Description: This exercise introduces items. These are valueable powerups you either start with or obtain by flying over. In this exercise all items will be fuel, but other maps can support more. On this map you will die if you fly into the wall with the front of the ship, with the backside of the ship you will be unharmed.
Recommended functions: item, wall and those introduced in earlier exercises.
Project Main Phase
You should now have good insight into what is possible to do with xpilot and have been introduced to most of the functionality of it. Now you may choose between one of the three projects described below, or specify your own. If you specify your own main phase it must be approved by the assistant.
As in all TDDD63 projects it is difficult to predict exactly how many tasks you will be able to complete. You might implement all of them and continue with additional extensions, or you may not be able to complete the entire list. To make sure you are progressing at a sufficient pace, keep your assistant up to date on your progress during the progress report sessions!
The tasks are very loosely defined and sometimes doesn't even supply
a map. You are then expected to supply this on your own and decide when you're
finished with it. The assistant will therefore not grade you based on the number
of tasks you have accomplished, but rather on how much time and work your group have
laid down. The easiest way to create maps is to copy the ones supplied and
modify them, either with a text editor or with
You do not need to implement the tasks in order, and you're encouraged to pick and choose the ones you want to do.
Writing a Technical Overview
Though the main focus in this project is on writing code, you will also write a short technical overview of your project. This overview should discuss the overall design of your software, as opposed to the more detailed code documentation that should generally be expressed in the shape of comments in the actual code. For example: How does the project work, how is the implementation structured, and so on?
It is recommended that the technical overview is written incrementally during the project and continuously kept up to date with your current progress in terms of programming and software development. You have the opportunity to send this document to the assistant ahead of each progress report session and get feedback during the report session. If you are uncertain about the proper contents, please make sure you make use of this opportunity to get feedback.
At the end of the course, we would expect the technical overview to be approximately 3-6 pages.
- Fighter bot
- Improve on the bot you wrote in exc. 3, but this time it should fight against enemy ships. In later tasks you add support for walls, dodging enemy bullets, multiple enemies, items, navigation, gravity, fuelstations and many other server options and map features.
- Improve on the bot you wrote in exc. 2 and add support for different maps. Milestones include being able to handle walls, navigation, fuelstations, items, fighting while racing and racing with a ball.
- Bots cooperating in teams
- Implement a bot that works in a team with other instances of the same bot. This project includes inventing your own very simple communication language and implementing the parsing of it.
Project: Fighter bot
By choosing this project you've decided to write the ultimate killer robot. It is not very hard to write a bot capable of beating a human with some specific map options, but a human is much more adaptable and can adjust and learn to play with almost every possible combination of settings and maps. It is also very good to maintain contact with other groups that chooses to write a fighter bot and compete with them.
Try to preserve the support for previous maps when moving onto later. This is best done by using getOption to support as many changing map options as possible. This is entirely optional, and if you find it too hard you can make a separate program for each task. You can also adjust the difficulty by changing options in the maps, making it easier or harder depending on how you're faring.
If you've fallen in love with fighting asteroids you can change almost all of the exercises to include asteroids instead of enemies. To make it harder you can either have very high asteroid density, forcing you to fight for your life, or have very low, forcing you to track them down via the radar.
Patience, young apprentice
Description: If you feel you can still improve on exercise 4, asteroids, go back to it and see if you can beat your old bots highscore, other groups highscore, or maybe even the score you get when playing manually.
The beginning of a Legend
Description: Take your bot from the previous task and replace the asteroid functions with the respective enemy functions. Try it out vs human players, started with the xpilot client, and/or vs other bots. You can either launch several copies of your own bot, invite another group to join your server or launch the server without the reportToMetaServer flag, letting bots and players roaming the internet join. There are always bots on the internet that will join your server, but it is rare to find other humans. You can restrict the number of internet bots by changing maxRobots in the mapfile.
Use yourMaps: simple.xp and obstacle.xp
Description: Fight versus other bots and humans while not crashing into walls, and add some basic reaction-based navigation, by flying towards enemies and adjusting the course to avoid walls.
Recommended functions: wall and map
Description: Add support for dodging enemy bullets. The possibility to dodge depends heavily on map settings such as shipmass, shotspeed and firerepeatrate, you can therefore adjust these options if you find it too easy or too hard. You can test both on the supplied map or vs other humans/bots.
Recommended functions: shot.
Use the tools at your disposal
Description: Start with the map of your choice and edit it to enable items. Use either item*Prob changing how often certain items spawn, or initial* to determine how many you start with. Many other options change the the behaviour of items and modifiers.
It's suggested you start with only mines and/or missiles, and then move on to add more.
You can also disable shooting altogether by setting maxPlayerShots to 0 and forcing players to only use items.
Hunt them down. Every single one.
Description: Make your bot able to navigate to enemies or map features far away on the radar using data gained with mapData.
Suggested maps: obstacle.xp, lifeless.xp, newdarkhell.xp, newdarkhell2.xp and maps you construct on your own.
Be aware of your environment
Description: Add support for map features. You can, among others:
Locate and use fuel stations when low on fuel.
Shoot or avoid hostile cannons.
Use wormholes to travel long distances.
Destroy targets if they are in your way.
Description: Go back to exercise 2, race, and improve on it using what you've learned in later exercises.
No seat belt
Description: On this you will die immediately if you crash into the wall and have limited lives, forcing you to weigh speed vs safety. Start with modifying your bot from the previous task so you no longer crash and then try to make it faster.
Maps: grandprix,xp, RaceInSpace.map and maps you construct on your own.
Description: Similar to Hunt them down, implement an algorithm for navigating to the next checkpoint. This is needed on more complicated maps when the path to the next checkpoint is not always straight on.
Maps: grandprix.xp, RaceInSpace.map and maps you construct on your own.Recommended functions: fuel, fuel station.
Description: On maps with limited amounts of fuel, lives and many laps, you will have to refuel at fuel stations to complete the course. How often you should stop to refuel and for how long depends greatly on the map settings. This is hard to solve in the general case so you may hardcode different values for how much fuel you need for a lap depending on the map.
Description: Add support for enemy ships. Depending on many map settings such as allowPlayerCrashes, allowPlayerBounces and maxUnshieldedWallBounceSpeed it might be a good idea to run over them, avoid them, or try to bump them into walls. Disable shooting and items as that comes later in Grand Theft Auto and Mario Kart.
Description: Add item concentrators and allow different items. It is suggested you start with a few items and gradually add more until you support all the relevant ones. The easiest ones to start with are mines and missiles.
Grand Theft Auto
Description: Enable shooting and combine racing and fighting.
Tow Truck Racing
Description: Enable ballRace and race with a ball.
Project: Bots Cooperating in Teams
If you choose this project, you will implement a bot that works in a team with other instances of the same bot. This project includes inventing your own very simple communication language and implementing the parsing of it.
Here is the code for a stub program that can be used as a starting point for the cooperating bots that are going to be written in this project. This file also shows how to use BotCom.
The tasks should during development at least be tested with a
team size of 3 but the program should work for bigger team sizes so
it is good to test with for example team sizes 5 and 7
sometimes. Remember to start the server with the flag
for example 10 as the maximum.
Fly in formation. Communicate among the leader and members of the team to decide which position a spaceship should assume and so on. Implement different formations and change between them while flying around. Use for example emptyborderlarge.xp map to test with. Note that the way to get the position of the other ships in the team fast enough is to use the BotCom based communication.
Team that shoots down enemies. Design scenarios were cooperation is used. One example of that is to suppose that only one spaceship have a radar to find the enemies and only the other spaceships can fire and destroy the enemy. In this task the enemies can be single ships that do not cooperate and do not fire back.
obstacle.xp is 32x32 in size. Each wall element corresponds to one square. Read in the map file and build up a data structure representing the world with the walls. Use that map to fly the spaceship to specific positions in the world.
Given that all bots in the team have read in the map obstacle.xp. The task here is to have moving and non-moving enemies in the obstacle.xp world and cooperate as a team to decide who will kill who and then kill all the enemies.
Implement the functionallity for team death matchs. Demonstrate by competing with yourself or with other groups bot programs. Implement different strategies that a team can have (for example defensive, aggressive, ...). The bots for one team should not read the other teams talk messages so the messages has to be marked with a team identifier. Feel free to construct your own maps here that suits the functionality that has been implemented.
Build a map of the environment by letting different members of the team explore different parts of the world and communicate the result between the team members continuously. The code should work for the obstacle.xp map but feel free to test it with other maps also. Use the
wallFeeler()function to create the map the environment.
Team death matchs while simultaneously building and using the partial map of the environment.
Python Style Guide: PEP 8
When programming it is good to follow some style guide. On popular guide for Python programs are PEP 8. The example programs in this document does not follow this guide exactly but that is no reason not to read the style guide and follow it.
Here are the most important points of PEP 8 (taken from the Python 3.3 tutorial):
- Use 4-space indentation, and no tabs. 4 spaces are a good compromise between small indentation (allows greater nesting depth) and large indentation (easier to read). Tabs introduce confusion, and are best left out.
- Wrap lines so that they don't exceed 79 characters. This helps users with small displays and makes it possible to have several code files side-by-side on larger displays.
- Use blank lines to separate functions and classes, and larger blocks of code inside functions.
- When possible, put comments on a line of their own.
- Use docstrings.
- Use spaces around operators and after commas, but not directly inside bracketing constructs: a = f(1, 2) + g(3, 4).
- Name your classes and functions consistently; the convention is to use CamelCase for classes and lower_case_with_underscores for functions and methods. Always use self as the name for the first method argument (see A First Look at Classes for more on classes and methods).
- Don't use fancy encodings if your code is meant to be used in international environments. Python's default, UTF-8, or even plain ASCII work best in any case.
- Likewise, don't use non-ASCII characters in identifiers if there is only the slightest chance people speaking a different language will read or maintain the code.
Sidansvarig: Patrick Doherty
Senast uppdaterad: 2013-11-04