Difference between revisions of "XanderFramework"

From Robowiki
Jump to navigation Jump to search
m (→‎Radars, Gun, and Drives: minor javadoc fix)
(Stubbed out for version 2.0 of the Xander framework)
Line 1: Line 1:
The Xander framework is an AdvancedRobot framework that makes it easy to build new bots by combining different guns, radars, and drives.  It is based on an abstract class named AbstractXanderBot that extends AdvancedRobot.  All framework classes are in the package xandercat.core.  When looking at any of my xandercat robots, anything outside of the xandercat.core package are components built for the Xander framework, not part of the Xander framework itself.
+
The Xander framework is an AdvancedRobot framework that makes it easy to build new bots by combining different guns, radars, and drives.  It is based on an abstract class named AbstractXanderRobot that extends AdvancedRobot.  All basic framework classes are in the package xander.core.  Some more advanced guess factor and wave surfing classes are in package xander.gfws (I haven't decided whether or not I consider this part of the framework or not).  When looking at any of my xandercat robots, anything outside of the xander.core and xander.gfws packages are components built for the Xander framework, not part of the Xander framework itself.
 +
 
 +
= Xander Framework 2.0 =
 +
The Xander framework is a framework on which Robocode robots can be built.  This section details the core framework.  Recently, the framework has undergone a fairly major update, and is thus now deemed as version 2.0.
 +
 
 +
Major changes from the original framework include:
 +
*  The drive and gun tree concept with compound drives and guns serving as tree nodes has been replaced by a component chain.  The component chain inspired by the ''Chain of Responsibility'' design pattern.  For each tick, the chain is followed until the gun, drive, and radar have all been selected.  One improvement this provides is it cleans up the handling of pair situations where -- for example -- a drive and gun should be used together or not at all.
 +
*  There is no longer a strong distinction between static and non-static components.  All components are now static.  This helps simplify things.
 +
*  Event listeners are now kept through all rounds of a battle.  This is a somewhat fundamental change that means you now add a listener once (usually in a constructor), rather than repeatedly at the beginning of each round.
 +
*  A new '''WaveHistory''' class now takes the responsibility of handling all waves for both self and opponent.  This cleans up wave handling a bit and also provides some new functionality such as calculating ''Bullet Shadows''.
  
= Xander Framework =
 
The Xander framework is a framework on which Robocode robots can be built.  This section details the core framework.
 
 
== Base Robot Class ==  
 
== Base Robot Class ==  
 
Xander robots extend the '''AbstractXanderBot''' class.  The '''AbstractXanderBot''' class contains basic robot setup code and a basic processing loop.   
 
Xander robots extend the '''AbstractXanderBot''' class.  The '''AbstractXanderBot''' class contains basic robot setup code and a basic processing loop.   
  
 
The basic setup code performs as follows:
 
The basic setup code performs as follows:
If it's the first round...
+
TO BE COMPLETED
**  Create new configuration and call the configure(Configuration) method.
 
*  Otherwise...
 
**  Get configuration from the ''static resource mananger''
 
*  call methods setAdjustGunForRobotTurn(true), setAdjustRadarForGunTurn(true), and setAdjustRadarForRobotTurn(true)
 
*  apply robot styling
 
*  initialize ''robot history'' and ''bullet history''
 
*  create or load radar, drive, and gun
 
*  call initalizeForNewRound(AbstractXanderBot) on all static resources
 
*  create ''radar controller'', ''drive controller'', and ''gun controller''
 
*  call drive and gun initialize(...) methods
 
  
 
The basic processing loop performs as follows:
 
The basic processing loop performs as follows:
Line 29: Line 26:
 
** Otherwise...
 
** Otherwise...
 
*** Fire on target with main gun
 
*** Fire on target with main gun
* Notify turn listeners of turn event
 
 
* call execute()
 
* call execute()
  
 
A Xander robot ''must'' implement the following methods:
 
A Xander robot ''must'' implement the following methods:
*  void initialize(Components) - The drive, gun, and radar should be created and stored in the Components object using the appropriate setter methods. (Note: In early versions of the framework, there were separate methods for creating the gun, radar, and drive.  However, this made it more difficult to handle situations where coordination was required between two or more components.  It was for this reason that all three main components are now created within a single method.)
 
  
 
+
TO BE COMPLETED
To aid in testing, it is valid to leave the drive, gun, and/or radar null within the Components object.  A null drive will cause the robot to stay in once place.  A null gun will cause the robot to not fire any bullets.
 
  
 
In addition, a Xander robot may optionally override the following methods:
 
In addition, a Xander robot may optionally override the following methods:
 
*  void configure(Configuration) - allows basic configuration of the robot to be changed
 
*  void configure(Configuration) - allows basic configuration of the robot to be changed
 
*  void style(RobotStyle) - allows setting styling options like robot colors
 
*  void style(RobotStyle) - allows setting styling options like robot colors
*  void doFinishingMoves() - moves to perform after winning a round
 
  
== Static Resources ==
+
== Resources ==
Classes within a Xander robot have easy access to a number of static resources which can be accessed through the ''Static Resource Manager''.  This includes a '''Timer''', '''Robot Proxy''', '''GunStats''', '''DriveStats''', '''Configuration''', and '''RobotStyle'''.
+
Classes within a Xander robot have easy access to a number of resources which can be accessed through the '''Resources''' class. TO BE EXPANDED UPON
  
=== Timer ===
 
The timer simply keeps track of game time.  In addition to round time, it also maintains a cumulative battle time.
 
 
=== RobotProxy ===
 
=== RobotProxy ===
Access to all robot getXxx methods outside of the main robot class itself should be accessed via the RobotProxy object.  As a convenience, it is also passed as an argument to some interface methods.
+
Access to all robot getXxx methods outside of the main robot class itself should be accessed via the RobotProxy object.   
=== GunStats ===
 
Keeps track of hit ratios, virtual hit ratios, and other gun-based statistics.
 
=== DriveStats ===
 
Keeps track of the amount of time each drive has been used, and other drive-based statistics.
 
=== Configuration ===
 
Stores Xander framework configuration parameters.  For the most part, it is the Xander framework itself that needs access to this static resource.
 
=== RobotStyle ===
 
Stores robot vanity information, such as robot colors.
 
=== Guns, Radars, and Drives ===
 
All guns, radars, and drives are treated as static resources.  (Note: In an earlier version of the framework, guns, drives, and radars did not have to be static resources.  However, this was more complicated than necessary, and was therefore changed.  The only downside to this change is that some components not meant to be static may have to clear out their variables between rounds in the initializeForNewRound(...) method.)
 
  
 
== Controllers ==
 
== Controllers ==
 
Radars, guns, and drives control the robot through ''controller'' classes.  The controllers for radar, gun, and drive provide  access to the radar, gun, and drive related setXxx methods of the robot.  This approach helps to prevent components from doing operations that are outside their area of responsibility, and also prevents components from calling the basic '''Robot''' control methods, or any methods that would immediately cause a turn to end.  Controllers may also have other helper methods.  
 
Radars, guns, and drives control the robot through ''controller'' classes.  The controllers for radar, gun, and drive provide  access to the radar, gun, and drive related setXxx methods of the robot.  This approach helps to prevent components from doing operations that are outside their area of responsibility, and also prevents components from calling the basic '''Robot''' control methods, or any methods that would immediately cause a turn to end.  Controllers may also have other helper methods.  
  
== Robot History ==
+
== Snapshot History ==
Robot history is available through the '''RobotHistory''' class, and is accessible via the '''RobotProxy''' class, and is therefore available to all radars, drives, and guns.  Robot history for a particular point in time is stored in a ''robot snapshot'' via the '''RobotSnapshot''' class, an immutable snapshot of a robot at a particular point in time.   
+
Robot history is available through the '''SnapshotHistory'''.  Robot history for a particular point in time is stored in a ''snapshot'' via the '''Snapshot''' class, an immutable snapshot of a robot at a particular point in time.   
  
 
Each turn, a Xander robot takes a new snapshot for itself and stores it in the history.  Each scan, a new snapshot for the scanned robot is generated and stored in the history.  Robot history allows the robot to look back at snapshots of itself and it's opponents back a set number of turns and scans.
 
Each turn, a Xander robot takes a new snapshot for itself and stores it in the history.  Each scan, a new snapshot for the scanned robot is generated and stored in the history.  Robot history allows the robot to look back at snapshots of itself and it's opponents back a set number of turns and scans.
 
== Bullet History ==
 
Bullet history provides information on enemy bullets fired.  Information about a fired bullet is stored as a '''BulletWave'''.  Bullet history is available through the '''BulletHistory''' class, and is accessible via the '''RobotProxy''' class.  The bullet history also keeps track of the opponent's hit ratio.  Any component wishing to be informed of enemy bullet fired events can register itself as a '''BulletWaveListener'''.
 
  
 
== Radar ==
 
== Radar ==
Line 91: Line 69:
 
! Events Issued By (Register With)
 
! Events Issued By (Register With)
 
! Purpose
 
! Purpose
|-
 
| BulletListener
 
| AbstractXanderBot
 
| Repackages Robocode events onBulletHit, onBulletHitBullet, onBulletMissed, and onHitByBullet
 
|-
 
| BulletFiredListener
 
| AbstractXanderBot
 
| Provides basic information on enemy bullet fired at self, including snapshots of enemy, self, and energy of bullet. 
 
|-
 
| BulletWaveHitListener
 
| BulletHistory
 
| Provides details on enemy bullet waves as they are tracked by the bullet history, including when waves are created and destroyed, when they hit, and what wave matches any bullet that hits self.
 
 
|-
 
|-
 
| CollisionListener  
 
| CollisionListener  
| AbstractXanderBot
+
| RobotEvents
 
| Repackages Robocode events onHitRobot and onHitWall
 
| Repackages Robocode events onHitRobot and onHitWall
|-
 
| MyBulletFiredListener
 
| GunController
 
| Provides details on our own bullet waves, including when they are fired, when they are invalidated (by being old or after bullet hit bullet), when they hit the targeted opponent, and what the next wave to hit is.
 
 
|-
 
|-
 
| Painter  
 
| Painter  
| AbstractXanderBot
+
| RobotEvents
 
| Repackages Robocode event onPaint, allowing other components to paint on the battlefield
 
| Repackages Robocode event onPaint, allowing other components to paint on the battlefield
|-
 
| RoundListener
 
| AbstractXanderBot
 
| Repackages Robocode events onWin, onDeath, onBattleEnded, onRobotDeath, and onRoundEnded
 
 
|-
 
|-
 
| ScannedRobotListener  
 
| ScannedRobotListener  
| AbstractXanderBot
+
| RobotEvents
 
| Repackages Robocode event onScannedRobot
 
| Repackages Robocode event onScannedRobot
 
|-
 
|-
 
| TurnListener  
 
| TurnListener  
| AbstractXanderBot
+
| RobotEvents
 
| Event that fires on every iteration of the AbstractXanderBot main processing loop.  This event fires immediately before execute() is called.
 
| Event that fires on every iteration of the AbstractXanderBot main processing loop.  This event fires immediately before execute() is called.
 
|}
 
|}
  
 
= Xander Framework Components =
 
= Xander Framework Components =
Most of these components are not considered part of the Xander framework core; they are more accurately thought of as components built for the Xander framework.  Exceptions to this are '''CompoundDrive''' and '''CompoundGun''', which are part of the basic Xander philosophy of building ''drive trees'' and ''gun trees'', and the '''HeadOnTargeter''', as it is used by a Xander framework core class and must therefore be considered part of the framework.
+
Most of these components are not considered part of the Xander framework core; they are more accurately thought of as components built for the Xander framework.  Exceptions to this are the '''HeadOnTargeter''', as it is used by a Xander framework core class and must therefore be considered part of the framework.
 +
 
 
== Xander Radars ==
 
== Xander Radars ==
 +
 
=== BasicRadar ===
 
=== BasicRadar ===
 
Basic radar scan the field, and locks onto the first target it finds.  Target can switch if another robot happens to be closer and drives through the scan beam.
 
Basic radar scan the field, and locks onto the first target it finds.  Target can switch if another robot happens to be closer and drives through the scan beam.
  
== Xander Guns ==
+
== Xander Guns and Targeters ==
Xander guns must implement the '''Gun''' interface.
 
  
 
=== AntiMirrorGun ===
 
=== AntiMirrorGun ===
Line 149: Line 108:
 
=== LinearTargeter ===
 
=== LinearTargeter ===
 
This gun is for targeting opponents that drive in a straight line.  It fires on the opponent based on the opponents current speed and heading.  It does not attempt to determine whether the target is actually moving in a straight line or not, but does compensate for battlefield bounds (don't shoot off the grid).  The linear intercept calculation is precise (not iterative nor an approximation).
 
This gun is for targeting opponents that drive in a straight line.  It fires on the opponent based on the opponents current speed and heading.  It does not attempt to determine whether the target is actually moving in a straight line or not, but does compensate for battlefield bounds (don't shoot off the grid).  The linear intercept calculation is precise (not iterative nor an approximation).
 
=== StatTargeter ===
 
This gun is a "guess factor" gun that relies on statistics to determine how to aim.  It relies on a Segmenter to determine how to categorize the statistics it collects (Segmenter is a separate interface).  It requires a certain ''load'' before a segment will be used; when under that load, it uses an overall factor array with no segmentation.
 
 
=== AdvancedStatTargeter ===
 
Extends the StatGun, adding the capability of using an '''AdvancedSegmenter''' such that multiple combinations of segmenters can be used on the fly.
 
 
=== CompoundGun ===
 
Combines two or more other guns.  Compound gun delegates gunning to other guns based on a '''GunSelector'''.  By default, a '''CompoundGun''' uses the '''FirstAvailGunSelector'''.
 
 
==== GunSelector ====
 
Compound guns can be set up with different gun selection modules.  Some available gun selection modules include:
 
* '''FirstAvailGunSelector''' - original behavior before gun selectors, this one just hands off to the first gun it finds that claims it can fire at the target.
 
* '''HitRatioGunSelector''' - this gun selector looks at gun hit ratios and bullets fired for each gun to determine which gun to fire with.
 
* '''VirtualHitRatioGunSelector''' - this gun selector looks at ''virtual'' hit ratios for all guns to determine what gun to fire with.
 
  
 
== Xander Drives ==
 
== Xander Drives ==
Xander drives must implement the '''Drive''' interface.
 
  
 
=== AntiMirrorDrive ===
 
=== AntiMirrorDrive ===
Line 174: Line 117:
 
This drive is an adaptation of the Wave Surfing drive used in the BasicGFSurfer robot.
 
This drive is an adaptation of the Wave Surfing drive used in the BasicGFSurfer robot.
  
=== CompoundDrive ===
+
=== IdealPositionDrive ===
A drive that combines multiple other drives.  A CompoundDrive forms a ''branch'' of the ''drive tree'', with individual drives forming the ''leaves''Which drive to use is determined by a '''DriveSelector'''.
+
Attempts to ideally position the robot on the battlefield.  This should only be used when no enemy bullets are in play.
==== DriveSelector ====
 
Interface that provides the means for selecting between drives.
 
 
 
=== OrbitalDrive ===
 
This drive approaches the target using linear targeting and then, when it range, orbits around the target, changing direction periodically.  It originally also used "inverse gravity bullet avoidance", although this is no longer the case; this feature was an early experimental feature of the framework, and has since been removed in favor of tracking bullet "waves" without predicting the firing direction.
 
 
 
=== RamboDrive ===
 
This drive attempts to ram the enemy.  It can be configured so that it does not approach the enemy in a straight line, but the effectiveness may still be limited against the better bots out there.
 
  
 
=== RamEscapeDrive ===
 
=== RamEscapeDrive ===
 
For getting away from needy robots who always want a hug.
 
For getting away from needy robots who always want a hug.
 
=== StatDrive ===
 
This drive is a Wave Surfing drive of my own design.  Similar to the StatGun, it supports using a segmenter, and a compound drive segmenter is available to combine the effects of multiple drive segmenters.
 
 
=== AdvancedStatDrive ===
 
Extends the '''StatDrive''', adding the capability of using an '''AdvancedSegmenter'''.
 
  
 
== Segmentation ==
 
== Segmentation ==
Drives and guns now use a single set of segmenters.  Basic segmenters must implement the '''Segmenter''' interface.  Current available segmenters include:
+
Wave surfing drives and guess factor guns can use segmenters.  Basic segmenters must implement the '''Segmenter''' interface.  Current available segmenters include:
*  '''AdvancedCompoundSegmenter''' - implements the '''AdvancedSegmenter''' interface, which in turn extends the '''Segmenter''' interface.  This is the most advanced form of segmenter that combines multiple other segmenters in a way where different combinations of those segmenters can be used independently.  It is used by the '''AdvancedStatDrive''' and '''AdvancedStatGun'''.
 
*  '''CompoundSegmenter''' - A segmenter that combines multiple other segmenters.  The combined segmenters are always analyzed together in combination.
 
*  '''BulletSpeedSegmenter''' - segments on bullet speed
 
 
*  '''BulletTravelTimeSegmenter''' - segments on bullet travel time
 
*  '''BulletTravelTimeSegmenter''' - segments on bullet travel time
 
*  '''DefenderAccelerationSegmenter''' - segments on defender acceleration
 
*  '''DefenderAccelerationSegmenter''' - segments on defender acceleration
 
*  '''DefenderSpeedSegmenter''' - segments on defender speed
 
*  '''DefenderSpeedSegmenter''' - segments on defender speed
*  '''DistanceSegmenter''' - segments on distance between robots
 
*  '''LateralVelocitySegmenter''' - segments on lateral velocity
 
 
*  '''NullSegmenter''' - provides no segmentation (a segmenter with only a single segment).
 
*  '''NullSegmenter''' - provides no segmentation (a segmenter with only a single segment).
*  '''RelativeDirectionSegmenter''' - segments on whether opponent appears to be orbiting clockwise or counter-clockwise.
 
 
*  '''WallSmoothingSegmenter''' - segments on whether it appears defender will have to wall smooth clockwise, counter-clockwise, both directions (in corner), or not at all.
 
*  '''WallSmoothingSegmenter''' - segments on whether it appears defender will have to wall smooth clockwise, counter-clockwise, both directions (in corner), or not at all.
  
Line 238: Line 161:
 
</pre>
 
</pre>
 
Similar to Log4J, log messages will only be printed if the level of the message is at or above the level set in the Log.  By default, all Logs are at level INFO.  This can be changed globally on startup through the Logger class, or on a Log by Log basis.
 
Similar to Log4J, log messages will only be printed if the level of the message is at or above the level set in the Log.  By default, all Logs are at level INFO.  This can be changed globally on startup through the Logger class, or on a Log by Log basis.
 
The main Xander robot class, AbstractXanderBot, provides a protected method getDefaultLogLevel() for setting the global logging level on startup.  Robots using the Xander framework can override this method to change the default logging level for all Logs.
 
  
 
== Mathematics ==
 
== Mathematics ==
  
=== Circular ===
+
=== RCMath ===
This class contains methods specific to circular targeting.  These methods are available outside the CircularGun because it is possible that other components may have use for calculating circular paths.
 
 
 
=== Linear ===
 
This class contains methods specific to linear targeting.  These methods are available outside the LinearGun because it is possible thar other components may have use for calculating linear paths.  For example, a drive may be interested in approaching an opponent using a linear intercept path.
 
 
 
=== MathUtil ===
 
 
This class provides generic math helper functions.  Most are targeted at solving Robocode problems, but are still usable in a more generic sense.   
 
This class provides generic math helper functions.  Most are targeted at solving Robocode problems, but are still usable in a more generic sense.   
  
=== RoboPhysics ===
+
=== RCPhysics ===
This class provides constants and methods that are only useful within the context of Robocode.  Some of what it provides is obsolete due to various additions to the Robocode API over the last few years -- specifically the Robocode Rules and Utils classes -- but I leave it there for posterity.
+
This class provides constants and methods that are only useful within the context of Robocode physics.  Some of what it provides is obsolete due to various additions to the Robocode API over the last few years -- specifically the Robocode Rules and Utils classes -- but I leave it there for posterity.
  
 
= Xander Code Examples =
 
= Xander Code Examples =
== Radars, Gun, and Drives ==
 
Radars, Guns, and Drives all follow a similar pattern.  Each must implement an interface.  The methods defined in the interfaces provide a ''controller'' as an argument.  Controllers are actually wrappers for the main robot class that limit exposure of main class methods to only those methods they should be allowed to call.  For example, a Gun is allowed to call methods to turn the gun, but is not allowed to call methods that would turn the radar or robot body.
 
 
As an example, below is the Gun interface.  However, note that it will likely change before the Xander framework is considered complete:
 
<pre>
 
/**
 
* Interface to be implemented by Xander gun classes.
 
*
 
* @author Scott Arnold
 
*/
 
public interface Gun extends StaticResource {
 
  
/**
+
TO BE COMPLETED
* Returns the name of this gun.  The name should be unique among guns.
 
*
 
* @return    name of gun
 
*/
 
public String getName();
 
 
/**
 
* If this gun is a wrapper for another gun or guns, this method should
 
* return the name of the gun that is wrapped or would be used for
 
* firing bullets.  Otherwise, this method should just return getName().
 
*
 
* @return
 
*/
 
public String getNestedName();
 
 
/**
 
* Controllers are recreated at the beginning of each round.  This
 
* method can be used to initialize the gun at the beginning of
 
* each round with the new gun controller.
 
*
 
* @param gunController    the gun controller
 
*/
 
public void initializeForNewRound(GunController gunController);
 
 
/**
 
* Returns whether or not this can is currently capable of aiming and
 
* firing on the given robot.  This method should be lightweight (most
 
* guns should just return true).
 
*
 
* @param target          snapshot of robot to fire at
 
* @param gunController    gun controller
 
*
 
* @return                whether or not gun can fire on opponent
 
*/
 
public boolean canFireAt(RobotSnapshot target, GunController gunController);
 
 
/**
 
* Aim and fire upon the given opponent.  Since guns are also required
 
* to have the getAim method, this method can generally call that
 
* method to get the aim.  The only extra work in this method is
 
* actually turning the gun and firing.
 
*
 
* @param target          snapshot of opponent
 
* @param myself          snapshot of self
 
* @param gunController    gun controller
 
*/
 
public void fireAt(RobotSnapshot target, RobotSnapshot myself, GunController gunController);
 
 
 
/**
 
* Returns the aim information for the given opponent. 
 
*
 
* @param target    the opponent to target
 
* @param myself    snapshot of self
 
*
 
* @return          aim information for the given opponent
 
*/
 
public Aim getAim(RobotSnapshot target, RobotSnapshot myself);
 
}
 
</pre>
 
At present, Controllers are recreated at the beginning of each round.  It is primarily for this reason that the initialize(...) method is provided.
 
 
 
== Main Robot Class ==
 
 
 
'''Note:  This section is way outdated and needs to be updated.'''
 
 
 
As an example of how the Xander framework is used, below is the source for the main robot class of XanderCat 2.0.
 
<pre>
 
/**
 
* 1-on-1 robot built on the Xander framework.  Also suitable for melee.
 
*
 
* @author Scott Arnold
 
*/
 
public class XanderCat extends AbstractXanderBot {
 
 
@Override
 
protected Level getLogLevel() {
 
return Log.Level.INFO;
 
}
 
 
 
@Override
 
protected Radar createRadar() {
 
return new BasicRadar(this, 45, 5);
 
}
 
 
 
@Override
 
protected Drive createDrive() {
 
return new OrbitalDrive(this, 200, 40, 0.5f);
 
}
 
 
 
@Override
 
protected Gun createGun() {
 
FiringProfile firingProfile = new FiringProfile(
 
1.0d, 500d, 3.0d, 150d, 0.5d, 450d, 700d);
 
Segmenter segmenter = new CompoundSegmenter(
 
new BulletTravelTimeSegmenter(getName(), 12, getBattlefieldBounds()),
 
new RelativeDirectionSegmenter(10));
 
return new CompoundGun(
 
new StatGun(this, firingProfile, 1000, 10, 30, segmenter, true),
 
new CircularGun(firingProfile),
 
new LinearGun(firingProfile));
 
}
 
 
 
}
 
</pre>
 
  
 
= Handling Static Data =
 
= Handling Static Data =
 
In order to remember information from one battle to the next, it is necessary to save that information in some static variable or object.  However, this would seem to cause problems if you want to pit a robot against itself, or if you want to run two different robots off of the same base framework classes.  This would seem to be a problem because suddenly you have two or more distinct robots sharing certain static resources, when each robot should have it's own unique set.  However, Robocode uses a separate class loader for every robot, putting each robot in it's own isolated sandbox.  This means static variables are not shared among robots.
 
In order to remember information from one battle to the next, it is necessary to save that information in some static variable or object.  However, this would seem to cause problems if you want to pit a robot against itself, or if you want to run two different robots off of the same base framework classes.  This would seem to be a problem because suddenly you have two or more distinct robots sharing certain static resources, when each robot should have it's own unique set.  However, Robocode uses a separate class loader for every robot, putting each robot in it's own isolated sandbox.  This means static variables are not shared among robots.
  
The Xander framework attempts to adhere to good object oriented practices; declaring variables or objects as static to preserve them between rounds is considered contrary to this.  Therefore, the Xander framework provides a ''static resource manager''.  The static resource manager is a singleton that stores objects in a static Map.  Whenever a variable or object needs to be kept or retrieved from round to round, the static resource manager instance is obtained, and then the variable or object is stored or retrieved from it.
+
The Xander framework attempts to adhere to good object oriented practices; declaring variables or objects as static to preserve them between rounds is considered contrary to this.  Therefore, the Xander framework hides this necessity by storing most objects as static, rather than relying on static variables.
 
 
The static resource manager supports storing three different kinds of objects, which are referred to as ''resources'', ''properties'', and ''static objects'':
 

Revision as of 17:08, 6 September 2011

The Xander framework is an AdvancedRobot framework that makes it easy to build new bots by combining different guns, radars, and drives. It is based on an abstract class named AbstractXanderRobot that extends AdvancedRobot. All basic framework classes are in the package xander.core. Some more advanced guess factor and wave surfing classes are in package xander.gfws (I haven't decided whether or not I consider this part of the framework or not). When looking at any of my xandercat robots, anything outside of the xander.core and xander.gfws packages are components built for the Xander framework, not part of the Xander framework itself.

Xander Framework 2.0

The Xander framework is a framework on which Robocode robots can be built. This section details the core framework. Recently, the framework has undergone a fairly major update, and is thus now deemed as version 2.0.

Major changes from the original framework include:

  • The drive and gun tree concept with compound drives and guns serving as tree nodes has been replaced by a component chain. The component chain inspired by the Chain of Responsibility design pattern. For each tick, the chain is followed until the gun, drive, and radar have all been selected. One improvement this provides is it cleans up the handling of pair situations where -- for example -- a drive and gun should be used together or not at all.
  • There is no longer a strong distinction between static and non-static components. All components are now static. This helps simplify things.
  • Event listeners are now kept through all rounds of a battle. This is a somewhat fundamental change that means you now add a listener once (usually in a constructor), rather than repeatedly at the beginning of each round.
  • A new WaveHistory class now takes the responsibility of handling all waves for both self and opponent. This cleans up wave handling a bit and also provides some new functionality such as calculating Bullet Shadows.

Base Robot Class

Xander robots extend the AbstractXanderBot class. The AbstractXanderBot class contains basic robot setup code and a basic processing loop.

The basic setup code performs as follows:

  • TO BE COMPLETED

The basic processing loop performs as follows:

  • Query radar for target
  • If no target is locked...
    • Tell drive to drive without a target
  • Otherwise...
    • Tell drive to drive with given target
    • If target is disabled...
      • Fire on target with Head-On gun
    • Otherwise...
      • Fire on target with main gun
  • call execute()

A Xander robot must implement the following methods:

TO BE COMPLETED

In addition, a Xander robot may optionally override the following methods:

  • void configure(Configuration) - allows basic configuration of the robot to be changed
  • void style(RobotStyle) - allows setting styling options like robot colors

Resources

Classes within a Xander robot have easy access to a number of resources which can be accessed through the Resources class. TO BE EXPANDED UPON

RobotProxy

Access to all robot getXxx methods outside of the main robot class itself should be accessed via the RobotProxy object.

Controllers

Radars, guns, and drives control the robot through controller classes. The controllers for radar, gun, and drive provide access to the radar, gun, and drive related setXxx methods of the robot. This approach helps to prevent components from doing operations that are outside their area of responsibility, and also prevents components from calling the basic Robot control methods, or any methods that would immediately cause a turn to end. Controllers may also have other helper methods.

Snapshot History

Robot history is available through the SnapshotHistory. Robot history for a particular point in time is stored in a snapshot via the Snapshot class, an immutable snapshot of a robot at a particular point in time.

Each turn, a Xander robot takes a new snapshot for itself and stores it in the history. Each scan, a new snapshot for the scanned robot is generated and stored in the history. Robot history allows the robot to look back at snapshots of itself and it's opponents back a set number of turns and scans.

Radar

Radars must implement the Radar interface.

Drive

Drives must implement the Drive interface.

Gun

Guns must implement the Gun interface. However, rather than creating a gun class and directly implementing the gun interface, the recommended approach for a Xander robot is to use the XanderGun class. The XanderGun class relies on two other interfaces: Targeter and PowerSelector. A PowerSelector decides on what fire power to use, while the Targeter determines how to aim the gun based on what the bullet velocity will be. When using a XanderGun, you create classes that implement Targeter and PowerSelector, and the XanderGun takes care of the rest, including:

  • Preparing information for self and target. This takes the latest snapshots and predicts them one turn into the future (necessary for a more accurate aim due to how the Robocode processing loop operates), and passes those to the Targeter for aiming.
  • Calling the setXxx methods to aim the gun and fire bullets.
  • Auto-adjusting the fire power for low energy situations (so long as the PowerSelector allows it). Fire power is modified based on the current state of the target and self. Power selection steps are as follows:
    • Get preferred fire power from the PowerSelector.
    • If power is more than is required to kill the target, reduce firepower to what is needed for a kill.
    • If target is not disabled and firing bullet would disable self, reduce firepower such that it will not disable self.

Events

Robocode issues a number of different events to the robot. A Xander framework robot repackages these events and also provides other custom events, and makes those available to other components. Xander robots can make use of the following events:

Listener Class Events Issued By (Register With) Purpose
CollisionListener RobotEvents Repackages Robocode events onHitRobot and onHitWall
Painter RobotEvents Repackages Robocode event onPaint, allowing other components to paint on the battlefield
ScannedRobotListener RobotEvents Repackages Robocode event onScannedRobot
TurnListener RobotEvents Event that fires on every iteration of the AbstractXanderBot main processing loop. This event fires immediately before execute() is called.

Xander Framework Components

Most of these components are not considered part of the Xander framework core; they are more accurately thought of as components built for the Xander framework. Exceptions to this are the HeadOnTargeter, as it is used by a Xander framework core class and must therefore be considered part of the framework.

Xander Radars

BasicRadar

Basic radar scan the field, and locks onto the first target it finds. Target can switch if another robot happens to be closer and drives through the scan beam.

Xander Guns and Targeters

AntiMirrorGun

Specifically for targeting opponents who use a mirroring drive strategy. Must be used in combination with the AntiMirrorDrive.

BSProtectedGun

A wrapper for other guns that provides support for counteracting bullet shielding.

CircularTargeter

This gun is for targeting opponents that drive in circles. If the opponent does not appear to be going in circles, this gun will not fire on the target. One advantage this gun has over some other circular targeting implementations is that it works for circular paths that are centered anywhere, and is not limited to circular paths centered at the location bullet wave was fired from. This gun pulverizes SpinBot.

HeadOnTargeter

Head-on shots.

LinearTargeter

This gun is for targeting opponents that drive in a straight line. It fires on the opponent based on the opponents current speed and heading. It does not attempt to determine whether the target is actually moving in a straight line or not, but does compensate for battlefield bounds (don't shoot off the grid). The linear intercept calculation is precise (not iterative nor an approximation).

Xander Drives

AntiMirrorDrive

Drive specifically for use with opponents who use a mirroring drive strategy. This drive must be used in combination with the AntiMirrorGun.

BasicSurferDrive

This drive is an adaptation of the Wave Surfing drive used in the BasicGFSurfer robot.

IdealPositionDrive

Attempts to ideally position the robot on the battlefield. This should only be used when no enemy bullets are in play.

RamEscapeDrive

For getting away from needy robots who always want a hug.

Segmentation

Wave surfing drives and guess factor guns can use segmenters. Basic segmenters must implement the Segmenter interface. Current available segmenters include:

  • BulletTravelTimeSegmenter - segments on bullet travel time
  • DefenderAccelerationSegmenter - segments on defender acceleration
  • DefenderSpeedSegmenter - segments on defender speed
  • NullSegmenter - provides no segmentation (a segmenter with only a single segment).
  • WallSmoothingSegmenter - segments on whether it appears defender will have to wall smooth clockwise, counter-clockwise, both directions (in corner), or not at all.

Xander Utilities

Logging

The Xander framework provides basic logging services loosely based on the Log4J logging model. Though not nearly as configurable as Log4J logging, it is much more advanced than just using System.out.print statements.

Xander logs have the following levels, in order of significance:

  • DEBUG - Debugging messages.
  • INFO - Informational messages. This is the default logging level.
  • WARNING - Warning messages.
  • STAT - Statistics messages. These are meant to be messages that are useful during development, but also of interest for a finished robot.
  • ERROR - Error messages.

Log levels are defined by the nested Enum named Level in the Log class (e.g. the level INFO would be accessed via Log.Level.INFO)

Logging consists of two classes: Logger and Log. Each class can have it's own Log. A Log is created by the Logger.

A Log can currently be created in a manner similar to as follows:

public class ExampleClass {

	private static final Log log = Logger.getLog(ExampleClass.class);

}

Once created, it can be used by calling the appropriate methods of the Log class as in the following example:

	log.info("This is an informational message.");

Similar to Log4J, log messages will only be printed if the level of the message is at or above the level set in the Log. By default, all Logs are at level INFO. This can be changed globally on startup through the Logger class, or on a Log by Log basis.

Mathematics

RCMath

This class provides generic math helper functions. Most are targeted at solving Robocode problems, but are still usable in a more generic sense.

RCPhysics

This class provides constants and methods that are only useful within the context of Robocode physics. Some of what it provides is obsolete due to various additions to the Robocode API over the last few years -- specifically the Robocode Rules and Utils classes -- but I leave it there for posterity.

Xander Code Examples

TO BE COMPLETED

Handling Static Data

In order to remember information from one battle to the next, it is necessary to save that information in some static variable or object. However, this would seem to cause problems if you want to pit a robot against itself, or if you want to run two different robots off of the same base framework classes. This would seem to be a problem because suddenly you have two or more distinct robots sharing certain static resources, when each robot should have it's own unique set. However, Robocode uses a separate class loader for every robot, putting each robot in it's own isolated sandbox. This means static variables are not shared among robots.

The Xander framework attempts to adhere to good object oriented practices; declaring variables or objects as static to preserve them between rounds is considered contrary to this. Therefore, the Xander framework hides this necessity by storing most objects as static, rather than relying on static variables.