Purpose of this tutorial is to familiarize you with the timeline functionality of the Pogamut, what is it and how to use it. In order to do that, you will first create a bot that will try to capture the flag in the CTF game of UT2004. After finishing the bot, the functionality of timeline will be demonstrated using the bot. If you are only interested in timeline functionality, create the CTF bot from the Pogamut samples ( second part of the tutorial.
→ → → → → ) and continue to theAt the end of the tutorial, you will have CTF bot that is providing additional data to the Pogamut Netbeans plugin that makes it easier to know what, where, and when was the CTF bot doing.
Before we even start thinking about creation of a bot, we have to know about the CTF game rules, that are little more complicated than free-for-all DeathMatch.
CTF is a two-team game, where each team tries to score points by taking enemy flag and carrying it to its team base. Rules of the Capture The Flag game:
There are at least two teams, each team have flag and home base.
At the start of the game, each flag is located at the respective There are two teams, each team have flag and home base.
Every bot belongs to one team
At the start of the game, flags are located at their respective flag base.
Team member can pick the enemy flag by running over it.
If team member carrying enemy flag is killed, the flag is dropped.
If team member runs over its team dropped flag, the flag returned to its home base.
Team scores, when team member carries enemy flag to its home base, while its team flag is at home base.
Game ends when it is over specified time limit (posted in GameInfo message) or if at least one team achieves score higher than GoalTeamScore (also from GameInfo message).
Every bot can specify the team it belongs to in a team attribute
of the INIT message that is send during handshake of the bot with the Unreal.
The INIT message supplies data necessary for creation of the bot's
avatar in the game (such as initial location, name, skin or team) and
GameBots creates the avatar upon recieving. Bot can get total number of
teams in the game from attribute MaxTeams
of
GameInfo message.
@AgentScoped public class Hunter extends UT2004BotModuleController<UT2004Bot> { // ... @Override public Initialize getInitializeCommand() { int maxTeams = this.game.getMaxTeams(); return new Initialize().setName("NavigationBot").setTeam(1); } // ... }
Valid team number is from 0 to
GameInfo.MaxTeams
-
You should also note, that team's size is not unlimited, the maximal
size of each team is GameInfo.
MaxTeamSize
. If the team is not specified in the
INIT message, GameBots will use team number
255 in DeathMatch and team number 0 in CTF games.
In some situations, you may want to select team of a bot based on number of players per team or some other metric thus balancing number of players in teams. This is useful in many situations, such as running same bot program multiple times and still creating two teams with same number of players (one team may have one player more than the other) or if you want your bot to join the team that has lower score and many other situations.
For further details, consult GameBots documentation.
In CTF game, information about flags is send as synchronous message from the GameBots, so the bot always have up-to-date info about flags. You can retrieve current info from the worldview, e.g. like this:
public FlagInfo getFlag(int team) { Collection<FlagInfo> flags = bot.getWorldView().getAll(FlagInfo.class).values(); for (FlagInfo flagInfo : flags) { if (flagInfo.getTeam() == team) { return flagInfo; } } throw new IllegalStateException("FlagInfo about with seeked team not found."); }
You'll get location and possibly holder if you can
see the flag (and possibly its carrier), other information is always
available. FlagInfo
.
getState()
is probably most useful.
Unfortunately, you can't directly query the worldview for info about the team base, but we know that base is located at navpoint with a specific id. Following code is showing how to find the home for the specified team:
// unreal assigns names to teams by default, team 0 is red, 1 is blue, 2 is green and 3 is gold private static String[] teamColors = new String[] {"Red", "Blue", "Green", "Gold"}; public NavPoint getTeamBase(int team) { String flagBaseStr = "x" + teamColors[team] + "FlagBase0"; for (NavPoint navpoint : bot.getWorldView().getAll(NavPoint.class).values()) { if (navpoint.getId().getStringId().contains(flagBaseStr)) { return navpoint; } } throw new IllegalStateException("Unable to find base for " + teamColors[team] + " team."); }
We are going to create our simple CTF bot using FSM(Finite State Machine), so before we start programming anything, it is necessary to specify how the bot should make decisions. You should always start with planning architecture of a bot's logic, it usually saves a lot of trouble and time. We are going to use work in progress library for FSMs that is currently being developed.
The bot has three different state types and multiple transitions. Bot starts at the hunt state, so it should wander around map, collect add-ons and kill enemies. When he sees enemy's flag he switches to pickup enemy flag and picks it up, and after he picks it up, he switches into go home. Unfortunately, team flag may be missing, because enemy bot got to it, so bot can switch into hunt mode and hoping to find enemy and kill him (NOTE: that won't return flag home, but if level is small enough, there is a good chance bot will accidently move over the dropped flag while in hunt mode). After flag has been delivered home, go back to the hunt mode. The rest of transitions is for events, when something doesn't go in the expected way, e.g. transition from hunt to go home is for case, when bot accidently moves over enemy flag, that he couldn't see before.
As you are aware, FSM consists of list of states, start state and transitions between states. Start state is the state "Hunt," bot will switch into that state when he enters the environment or when he is killed.
States used in the FSMBot library are not exactly states in classical FSM definition, but more like activities the bot is supposed to do. List of states:
Hunt
- in this state bot should
behave like hunter, kill members of enemy team and collect
weapons, and other add-ons.
Pick up enemy flag
- go to the place
where is the enemy's flag and pick it up. This state expects that
bot knows where the enemy's flag is (e.g. bot sees it).
Go home
- return to home base. This
state should be used when bot holds enemy's flag.
There are many shortcoming, e.g. state Hunt should preferably shoot at enemy holding our flag or state "Pick up enemy flag" and "Go home" should shoot at visible enemy while racing for their destination.
Transitions are a little tricky, basically there are two types of transitions that differs by eligibility (under what circumstances are they considered for potential transition from state A to B).
Sequential transition - is eligible only after state has finished(e.g. if bot is supposed to move somewhere, the sequential transition won't be eligible until bot is at the destination). In order for it to be eligible, source state method isFinished must return true.
Interrupt transition - is always eligible and if triggered, it interrupts the activity the state was doing, e.g. if bot is supposed to move somewhere, interrupt transition is eligible while bot is moving and after state has finished.
In order to properly utilize FSMBot library, you need to have an
idea how do states look like, how to program them and how are they
processed. Every state has to implement interface
IFSMState
. Careful, there is an interface
with the same name in afsm library, that is used during communication
with GameBots.
There are basically two paths state can go:
State is not interrupted by interrupt transition during its execution:
init
isReady
, until it returns
true
isFinished
returns
true
cleanup
isCleaned
,
until it returns
truerun
State is interrupted by interrupt transition:
init
isReady
, until it returns
true
interrupt
isInterrupted
, until it returns
truerun
I attemp to make sure that destination state of transition sees the environment same way the transition did, so the condition that triggered the transition itself is still valid even in a destination state (e.g. if transition is supposed to trigger when visible player appears, the destination state will see player at the same position and still visible). This behavior is not guaranteed if state has to loop over any of following methods:
isReady
isInterrupted
isCleaned
In this section we will create the project and set up dependencies necessary for us to build FSM bot.
c:/development
. Click
.