Difference between revisions of "Programming robots"

From Bitfighter
(Navigation, configuration, and combat)
Line 39: Line 39:
 
WeaponType <b>getWeapon()</b> - Return currently selected weapon<br>
 
WeaponType <b>getWeapon()</b> - Return currently selected weapon<br>
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
weap = bot:getWeapon()            -- Get info about our currently active weapon
 
weap = bot:getWeapon()            -- Get info about our currently active weapon
 
weapInfo = WeaponInfo( weap )    -- Get information about it
 
weapInfo = WeaponInfo( weap )    -- Get information about it
 
bot:logprint( weapInfo:getName().." has a range of "..weapInfo:getRange() )
 
bot:logprint( weapInfo:getName().." has a range of "..weapInfo:getRange() )
</pre>
+
</source>
  
 
void <b>activateModule(ModuleType)</b> - Activate module, specified by ModuleType.  If specified module is not included in the current loadout, this command will have no effect.)
 
void <b>activateModule(ModuleType)</b> - Activate module, specified by ModuleType.  If specified module is not included in the current loadout, this command will have no effect.)
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
-- Note that this line will do nothing if we don't have shields
 
-- Note that this line will do nothing if we don't have shields
 
bot:activateModule( ModuleShield )    -- Shields up!
 
bot:activateModule( ModuleShield )    -- Shields up!
</pre>
+
</source>
  
  
 
void <b>activateModuleIndex(indx)</b> - Activate module, specified by its index (1 or 2)<br>
 
void <b>activateModuleIndex(indx)</b> - Activate module, specified by its index (1 or 2)<br>
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
-- Must specify an index, currently either 1 or 2
 
-- Must specify an index, currently either 1 or 2
 
bot:activateModuleIndex( 1 )          -- Activate first module, whatever it is
 
bot:activateModuleIndex( 1 )          -- Activate first module, whatever it is
</pre>
+
</source>
  
 
void <b>setReqLoadout(Loadout)</b> - Set the requested loadout to Loadout<br>
 
void <b>setReqLoadout(Loadout)</b> - Set the requested loadout to Loadout<br>
Line 102: Line 102:
  
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
if ( bot:hasWeapon( WeaponMine ) ) then
 
if ( bot:hasWeapon( WeaponMine ) ) then
 
   bot:setWeapon( WeaponMine )      -- Make mine layer active, if it's  
 
   bot:setWeapon( WeaponMine )      -- Make mine layer active, if it's  
Line 108: Line 108:
 
   bot:fire()                      -- Lay a mine
 
   bot:fire()                      -- Lay a mine
 
end
 
end
</pre>
+
</source>
  
 
void <b>globalMsg( msg )</b> - Send a message to all players<br>
 
void <b>globalMsg( msg )</b> - Send a message to all players<br>
Line 128: Line 128:
  
 
Example:  
 
Example:  
<pre>ti = bot:findTestItem() -- Function likely to change
+
<source lang="lua">ti = bot:findTestItem() -- Function likely to change
vel = it:getVel()</pre>
+
vel = it:getVel()</source>
  
  
Line 142: Line 142:
  
 
Example:  
 
Example:  
<pre>asteroid = bot:findAsteroid() -- Function likely to change
+
<source lang="lua">asteroid = bot:findAsteroid() -- Function likely to change
target = asteroid:getLoc()</pre>
+
target = asteroid:getLoc()</source>
  
  
Line 155: Line 155:
  
 
Example:
 
Example:
<pre>ri = bot:ResourceItem() -- Function likely to change
+
<source lang="lua">ri = bot:ResourceItem() -- Function likely to change
vel = ri:getVel()</pre>
+
vel = ri:getVel()</source>
  
  
Line 168: Line 168:
  
 
Example:
 
Example:
<pre>ri = bot:findRepairItem() -- Function likely to change
+
<source lang="lua">ri = bot:findRepairItem() -- Function likely to change
vel = ri:getVel()</pre>
+
vel = ri:getVel()</source>
  
 
== Weapon Information ==
 
== Weapon Information ==
Line 175: Line 175:
  
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
weap = bot:getWeapon()            -- Get bot's currently active weapon
 
weap = bot:getWeapon()            -- Get bot's currently active weapon
 
bot:logprint( weap:getName().." has a range of "..weap:getRange() )
 
bot:logprint( weap:getName().." has a range of "..weap:getRange() )
</pre>
+
</source>
  
<pre>
+
<source lang="lua">
 
weap = WeaponInfo( WeaponTurret )  -- Get info about those infernal turrets
 
weap = WeaponInfo( WeaponTurret )  -- Get info about those infernal turrets
 
bot:logprint( weap:getName().." shoots with a speed of "..weap:getProjVel() )
 
bot:logprint( weap:getName().." shoots with a speed of "..weap:getProjVel() )
</pre>
+
</source>
  
  
Line 209: Line 209:
 
== Module Information ==
 
== Module Information ==
 
Example:
 
Example:
<pre>mod = ModuleInfo( ModuleBoost )
+
<source lang="lua">mod = ModuleInfo( ModuleBoost )
bot:logprint( "This is a lame example!" )</pre>
+
bot:logprint( "This is a lame example!" )</source>
  
 
string <b>getName()</b> - Name of module ("Shield", "Turbo", etc.)<br>
 
string <b>getName()</b> - Name of module ("Shield", "Turbo", etc.)<br>
Line 229: Line 229:
  
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
-- Get a new loadout (comes pre-filled with default values)
 
-- Get a new loadout (comes pre-filled with default values)
 
loadout = Loadout()
 
loadout = Loadout()
Line 247: Line 247:
 
   bot:logprintf( "This line always gets printed!" )
 
   bot:logprintf( "This line always gets printed!" )
 
end
 
end
</pre>
+
</source>
  
  
Line 259: Line 259:
 
<br>
 
<br>
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
game = GameInfo()         -- Create the GameInfo object  
 
game = GameInfo()         -- Create the GameInfo object  
 
gameType = game:getGameType()
 
gameType = game:getGameType()
Line 269: Line 269:
 
   bot:logprintf("I just love playing "..gameTypeName.."!")   
 
   bot:logprintf("I just love playing "..gameTypeName.."!")   
 
end
 
end
</pre>
+
</source>
  
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
-- Create the GameInfo object in header:
 
-- Create the GameInfo object in header:
 
game = GameInfo()          
 
game = GameInfo()          
Line 287: Line 287:
 
percent = ( totTime - remTime ) / remTime
 
percent = ( totTime - remTime ) / remTime
 
bot:logprint( "Game is "..percent.."% over )
 
bot:logprint( "Game is "..percent.."% over )
</pre>
+
</source>
  
 
GameType  <b>getGameType()</b> - Return current game typet) <br>
 
GameType  <b>getGameType()</b> - Return current game typet) <br>
Line 300: Line 300:
  
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
-- Create the GameInfo object in header:
 
-- Create the GameInfo object in header:
 
game = GameInfo()          
 
game = GameInfo()          
Line 308: Line 308:
 
team = TeamInfo( leadingTeam )
 
team = TeamInfo( leadingTeam )
 
bot:teamMsg( "Hurry up! Team "..team:getName().." is winning!"  )
 
bot:teamMsg( "Hurry up! Team "..team:getName().." is winning!"  )
</pre>
+
</source>
  
 
string <b>getLevelName()</b> - Gets the level's name<br>
 
string <b>getLevelName()</b> - Gets the level's name<br>
Line 346: Line 346:
  
 
Example:
 
Example:
<pre>
+
<source lang="lua">
 
gameInfo = GameInfo()
 
gameInfo = GameInfo()
 
teams = gameInfo:getTeamCount()
 
teams = gameInfo:getTeamCount()
Line 360: Line 360:
 
       " and has "..team:getPlayerCount().." players" )
 
       " and has "..team:getPlayerCount().." players" )
 
end
 
end
</pre>
+
</source>
  
 
== Misc ==
 
== Misc ==

Revision as of 09:23, 2 May 2009

Starting with release 011, server admins will be able to program their own robots in addition to designing their own levels. Robots will be coded in Lua, and will will have a number of special functions available to them.

Robot coding is still fluid, and everything is subject to change, but here is a list of commands being implemented for the next alpha release (see forums for the URL):


How to read the function notation:

returnType funtionName( argType1, argType2 ) - Description of function


Return types: Unlike most languages, Lua does not differentiate between integers and floating point numbers. Instead, everything is simply a number.


Points to remember in Lua:

  • Lua arrays are 1-based: the first index is 1 rather than 0 as is the case in most programming languages


Navigation, configuration, and combat

getZoneCenterXY( x, y ) - Return point representing center of zone containing point x,y
getGatewayFromZoneToZone( a, b ) - Return point representing fastest way from zone a to zone b. If zones a & b are not neighbors, returns nil
number getZoneCount() - Return number of zones
number getCurrentZone() - Return current zone that robot is in

number getAngle() - Return angle robot is currently facing
Point getPosXY() - Return x, y of robot

void setAngle( ang ) - Point robot at angle
void setAngleXY( x, y ) - Point robot towards point x,y
number getAngleXY( x, y ) - Compute angle to point x, y
boolean hasLosXY( x, y ) - Return whether or not robot can see point x, y

hasFlag() - Return whether or not robot currently has the flag


WeaponType getWeapon() - Return currently selected weapon
Example:

weap = bot:getWeapon()            -- Get info about our currently active weapon
weapInfo = WeaponInfo( weap )     -- Get information about it	
bot:logprint( weapInfo:getName().." has a range of "..weapInfo:getRange() )

void activateModule(ModuleType) - Activate module, specified by ModuleType. If specified module is not included in the current loadout, this command will have no effect.) Example:

-- Note that this line will do nothing if we don't have shields
bot:activateModule( ModuleShield )    -- Shields up!


void activateModuleIndex(indx) - Activate module, specified by its index (1 or 2)
Example:

-- Must specify an index, currently either 1 or 2
bot:activateModuleIndex( 1 )          -- Activate first module, whatever it is

void setReqLoadout(Loadout) - Set the requested loadout to Loadout
Loadout getCurrLoadout() - Returns current loadout
Example:

loadout = bot:getCurrLoadout()       -- Retrieve current bot configuration
 
weapType1 = loadout:getWeapon(1)     -- Get the first weapon
weapType2 = loadout:getWeapon(2)     -- Get the second weapon
weapType3 = loadout:getWeapon(3)     -- Get the third weapon
 
-- Check to see if the first weapon is a phaser
if ( weapType1 == WeaponPhaser ) then
	bot:logprint("First weapon is a phaser!")
end
 
-- Print a list of our three current weapons
bot:logprint( "My three weapons are: "..WeaponInfo(weapType1):getName()..", "
                                      ..WeaponInfo(weapType2):getName()..", and "
                                      ..WeaponInfo(weapType3):getName() )


Loadout getReqLoadout() - Returns requested loadout



Navigation

findObjects(ObjectType)
getWaypoint(x, y)


Ship control
void setThrustAng( vel, angle ) - Set robot's velocity to vel (0-1), at angle
void setThrustXY( vel, x, y ) - Set robot's velocity to vel (0-1), toward coordinates x, y

void fire() - Fires active weapon
void setWeaponIndex( index ) - Activates weapon with index (1, 2, 3)
void setWeapon( WeaponType ) - Activates weapon type specified (does nothing if WeaponType is not in current loadout)
boolean hasWeapon (WeaponType ) - Does current configuation have specified weapon

Example:

if ( bot:hasWeapon( WeaponMine ) ) then
   bot:setWeapon( WeaponMine )      -- Make mine layer active, if it's 
                                    --    part of our current loadout
   bot:fire()                       -- Lay a mine
end

void globalMsg( msg ) - Send a message to all players
void teamMsg( msg ) - Send a message to players on the same team

logprint(msg) - Print msg to game logfile

GameItems

The Lua object structure follows that used by Bitfighter. The GameItems group conisists of RepairItems, Asteroids, ResourceItems, and TestItems. These all share similar properties, and have similar methods. All of these implement the getLoc, getVel, and getRad methods for querying location, velocity, and radius respectively. Some items have additional methods that apply only to them. See below for details on these additional methods.


TestItems

Category: GameItem

Point getLoc() - Center of testItem
number getRad() - Radius of testItem
Point getVel() - Speed of testItem

Example:

ti = bot:findTestItem()	-- Function likely to change
vel = it:getVel()


Asteroids

Category: GameItem

number getSize() - Index of current asteroid size (0 = initial size, 1 = next smaller, 2 = ...)
number getSizeCount() - Number of indexes of size we can have
Point getLoc() - Center of asteroid
number getRad() - Radius of asteroid
Point getVel() - Speed of asteroid

Example:

asteroid = bot:findAsteroid()	-- Function likely to change
target = asteroid:getLoc()


ResourceItems

Category: GameItem

Point getLoc() - Center of ResourceItem
number getRad() - Radius of ResourceItem
Point getVel() - Speed of ResourceItem

Example:

ri = bot:ResourceItem()	-- Function likely to change
vel = ri:getVel()


RepairItems

Category: GameItem

Point getLoc() - Center of RepairItem
number getRad() - Radius of RepairItem
Point getVel() - Speed of RepairItem usually 0,0)
boolean isVis() - Is repair item currently visible?

Example:

ri = bot:findRepairItem()	-- Function likely to change
vel = ri:getVel()

Weapon Information

All the WeaponInfo data will remain constant throughout the game. Therefore, if you need some information about a weapon, it might make sense to retrieve it in the bot's header and store it in a local variable rather than instantiating a new WeaponInfo object during every loop of the robot's getMove() method.

Example:

weap = bot:getWeapon()             -- Get bot's currently active weapon
bot:logprint( weap:getName().." has a range of "..weap:getRange() )
weap = WeaponInfo( WeaponTurret )  -- Get info about those infernal turrets
bot:logprint( weap:getName().." shoots with a speed of "..weap:getProjVel() )


string getName() - Name of weapon ("Phaser", "Triple", etc.)
WeaponType getID() - ID of module (WeaponPhaser, WeaponTriple, etc.)
number getRange() - Get range of weapon (units)
number getFireDelay() - Delay between shots in ms
number getMinEnergy() - Minimum energy needed to use
number getEnergyDrain() - Amount of energy weapon consumes
number getProjVel() - Speed of projectile (units/sec)
number getProjLife() - Time projectile will live (ms) -1 == live forever)
number getDamage() - Damage projectile does (0-1, where 1 = total destruction)
boolean getCanDamageSelf() - Will weapon damage self?
boolean getCanDamageTeammate() - Will weapon damage teammates?

WeaponType constants

WeaponPhaserWeaponBounce
WeaponTripleWeaponBurst
WeaponMineWeaponSpyBug
WeaponTurret

Module Information

Example:

mod = ModuleInfo( ModuleBoost )
bot:logprint( "This is a lame example!" )

string getName() - Name of module ("Shield", "Turbo", etc.)
ModuleType getID() - ID of module (ModuleShield, ModuleBoost, etc.)

ModuleType constants

ModuleShieldModuleBoost
ModuleSensorModuleRepair
ModuleCloakModuleEngineer (maybe someday)

Loadouts

void setWeapon(index, WeaponType) - Set weapon at index
void setModule(index, ModuleType) - Set module at index
WeaponType getWeapon(index) - return weapon at index
ModuleType getModule(index) - return module at index

Example:

-- Get a new loadout (comes pre-filled with default values)
loadout = Loadout()
 
-- Configure the loadout to suit our needs
loadout:setWeapon( 1, WeaponPhaser )
loadout:setWeapon( 2, WeaponBurst )
loadout:setWeapon( 3, WeaponMine )
loadout:setModule( 1, ModuleShield )
loadout:setModule( 2, ModuleCloak )
 
-- Set the loadout, will become active when bot hits loadout zone
-- or spawns, depending on game
bot:setReqLoadout( loadout )     
 
if( loadout:getWeapon(1) == WeaponPhaser) then
   bot:logprintf( "This line always gets printed!" )
end


boolean isValid() - Is loadout config valid?
boolean equals(Loadout) - is loadout the same as Loadout?

GameInfo

You can get information about the current game with the GameInfo object. You only need get this object once, then you can use it as often as you like. It will always reflect the latest data.
Example:

game = GameInfo()	        -- Create the GameInfo object 
gameType = game:getGameType()
 
if( gameType == SoccerGame ) then
   bot:logprint("This bot is not very good at soccer!")
else
   gameTypeName = game:getGameTypeName()
   bot:logprintf("I just love playing "..gameTypeName.."!")   
end

Example:

-- Create the GameInfo object in header:
game = GameInfo()	        
 
...
 
-- Even though we only create our GameInfo once, it is always current
 
...
 
-- Later, in getMove():
remTime = game:getGameTimeReamaining()
totTime = game:getGameTimeTotal()
percent = ( totTime - remTime ) / remTime
bot:logprint( "Game is "..percent.."% over )

GameType getGameType() - Return current game typet)
string getGameTypeName() - Return current game type
number getFlagCount() - Return the number of flags in the game
number getWinningScore() - Returns the score required to win the level
number getGameTimeTotal() - Returns the time (in seconds) that the level will be played for
number getGameTimeRemaining() - Returns the time remaining (in seconds) for this level
number getLeadingScore() - Gets score of the leading team
number getLeadingTeam() - Gets index of leading team
number getTeamCount() - Return number of teams

Example:

-- Create the GameInfo object in header:
game = GameInfo()	        
...
-- Then later...
leadingTeam = game:getLeadingTeam()
team = TeamInfo( leadingTeam )
bot:teamMsg( "Hurry up! Team "..team:getName().." is winning!"  )

string getLevelName() - Gets the level's name
number getGridSize() - Gets the level's gridSize parameter
boolean getIsTeamGame() - Is this a team game?

getEventScore(ScoringEvent)


GameType constants

BitmatchGameCTFGame
HTFGameNexusGame
RabbitGameRetrieveGame
SoccerGameZoneControlGame

ScoringEvent constants

KillEnemyKillSelf
KillTeammateKillEnemyTurret
KillOwnTurretCaptureFlag
CaptureZoneUncaptureZone
HoldFlagInZoneRemoveFlagFromEnemyZone
RabbitHoldsFlagRabbitKilled
RabbitKillsReturnFlagsToNexus
ReturnFlagToZoneLostFlag
ReturnTeamFlagScoreGoalEnemyTeam
ScoreGoalHostileTeamScoreGoalOwnTeam

TeamInfo

string getName() - return team name
number getIndex() - return team's index, index of first team is 1
number getPlayerCount() - return player count
number getScore() - return team score

Example:

gameInfo = GameInfo()
teams = gameInfo:getTeamCount()
 
-- Note that while the number of teams will not change throughout the game,
-- the number of players on each team might.  Also, the robot may be initialized
-- before the players have been added, so if you run this code in the bot header, 
-- it may report some teams having 0 players.
 
for i = 1, teams do        -- First team has an index of 1
   team = TeamInfo( i )
   bot:logprint( "Team "..i.." is called "..team:getName()..
      " and has "..team:getPlayerCount().." players" )
end

Misc

Some constants available in game:

Game Objects
ShipType
BarrierType
MoveableType
BulletType
ItemType
ResourceItemType
EngineeredType
ForceFieldType
LoadoutZoneType
MineType
TestItemType
FlagType
TurretTargetType
SlipZoneType
HeatSeekerType
SpyBugType
NexusType
BotNavMeshZoneType
RobotType
TeleportType
GoalZoneType
AsteroidType