Difference between revisions of "HawkOnFire/Understanding HawkOnFire"

From Robowiki
Jump to navigation Jump to search
m (change YouTube link text)
m (Small fixups)
 
(3 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 
{{Youtube|7e9qyOmo6nc|HawkOnFire}}
 
{{Youtube|7e9qyOmo6nc|HawkOnFire}}
[[Rozu]] released the source to his breakthrough melee bot, [[HawkOnFire]], when he saw that people were genuinely interested in it some time ago, but hasn't packaged it with the bot. Since then, I think it's been on everyone's todo list to take a look at it. You can go see by going to http://www.robocoderepository.com/BotDetail.jsp?id=1575 and clicking on "Download Source".  If I refer to the source, I'll be referring to that source.  It appears that [[Rozu]] took some time to edit and fix up the code before uploading it here, and for the benefit of clarity, it compiles to be a bit larger than the barely-micro size that HawkOnFire normally is.  That having been said, with some analysis and tweaking, I got HawkOnFireOS under 700 bytes with no loss of functionality or performance that I can tell (so if you have something to use 50 bytes for, [[Rozu]], let me know).
+
[[Rozu]] released the source to his breakthrough melee bot, [[HawkOnFire]], when he saw that people were genuinely interested in it some time ago. Since then, I think it's been on everyone's todo list to take a look at it. You can view it [[HawkOnFire/Code|here]].
  
=== Classes ===
+
It seems that [[Rozu]] took some time to edit and fix up the code before uploading it here, and for the benefit of clarity, it compiles to be a bit larger than the barely-micro size HawkOnFire normally is. That having been said, with some analysis and tweaking, I got HawkOnFireOS under 700 bytes with no loss of functionality or performance that I can see.
[[HawkOnFire]] is made up of 2 classes:
 
* The main robot class
 
* the microEnemy class, which contains the location, energy, and whether or not the enemy is alive.  These are stored in a Hashtable in the robot class.
 
  
=== Functions ===
+
== Classes ==
There are a few typical utility functions, calcPoint (which projects a point some distance away from a base location at some angle) and calcAngle (which finds the absolute bearing from one point to another).
+
HawkOnFire is made up of 2 classes:
 +
* The main robot class.
 +
* the <tt>microEnemy</tt> class, which contains the location, energy, and whether or not the enemy is alive. These are stored in a <tt>Hashtable</tt> in the robot class.
  
[[HawkOnFire]] also overrides the onRobotDeath method to mark enemies as dead.
+
== Functions ==
 +
The primary magic in HawkOnFire lives in the <tt>evaluate()</tt> and <tt>doMovementAndGun()</tt> methods. <tt>run()</tt> doesn't do much besides set up and call these methods, and <tt>onScannedRobot()</tt> just updates the enemies and handles target selection.
  
The primary magic in [[HawkOnFire]] lives in the <tt>evaluate</tt> and <tt>doMovementAndGun</tt> methods. <tt>run</tt> doesn't do much besides set up and call these methods, and <tt>onScannedRobot</tt> just updates the enemies and handles target selection.
+
There are a few typical utility functions:
 +
* <tt>calcPoint()</tt>, which projects a point some distance away from a base location at some angle.
 +
* <tt>calcAngle()</tt>, which finds the absolute bearing from one point to another.
  
=== Globals ===
+
HawkOnFire also overrides the <tt>onRobotDeath()</tt> method to mark enemies as dead.
Most of these are pretty self-explanitory, but the Points declared should be explained:
 
* <tt>nextDestination</tt> is the point that [[HawkOnFire]] is trying to get to.
 
* <tt>lastPosition</tt> is the point that [[HawkOnFire]] is coming from last.
 
* <tt>myPos</tt> is where [[HawkOnFire]] is now.
 
  
=== Radar ===
+
== Globals ==
Spins the radar in melee, InfiniteRadarLock in 1-on-1.
+
Most of these are pretty self-explanatory, but the <tt>Point</tt>s declared should be explained:
 +
* <tt>nextDestination</tt> is the point that HawkOnFire is trying to get to.
 +
* <tt>lastPosition</tt> is the point that HawkOnFire is coming from last.
 +
* <tt>myPos</tt> is where HawkOnFire is now.
  
=== Gun ===
+
== Radar ==
Not too exciting, the enemy's position is set in <tt>onScannedRobot</tt>, lines 54-57 turn the gun and fire.  Contrary to rumors, [[HawkOnFire]] does not always fire power-3 bullets - it's a little more aggressive than alot of small melee bots as far as firepower is concerned, but not as aggressive as bots with a dependable gun.  One feature that's worth pointing out is that target.energy/3 is in there, which is more than enough to kill the target at that point.  [[HawkOnFire]] doesn't want a low-energy target to get lucky after being hit :-)  Also, [[HawkOnFire]] always tries to target the closest living enemy, and likes to have its gun turned, and never fires when its energy is under 1.
+
Spins the radar in melee, [[One on One Radar#The Infinity Lock|Infinity Lock]] in 1-on-1.
  
=== Movement ===
+
== Gun ==
[[HawkOnFire]] is a textbook example of [[MinimumRiskMovement]]. The point-generating function generates 200 points at random between 100 and 300 pixels away but no more than 80% of the distance to its current target (to avoid hitting other robots as much).
+
Not too exciting. The enemy's position is set in <tt>onScannedRobot()</tt>, and lines 54-57 turn the gun and fire.
  
==== Risk Function ====
+
Contrary to rumors, HawkOnFire does not always fire power-3 bullets ‒ it's a little more aggressive than a lot of small melee bots as far as firepower is concerned, but not as aggressive as bots with a dependable gun. One feature that's worth pointing out is that <code>target.energy / 3</code> is in there, which is more than enough to kill the target at that point. HawkOnFire doesn't want a low-energy target to get lucky after being hit. Also, HawkOnFire always tries to target the closest living enemy, and likes to have its gun turned, and never fires when its energy is under 1.
The <tt>evaluate</tt> method is [[HawkOnFire]]'s risk function, except for one part - the <tt>addLast</tt> variable that is passed in as a parameter is precomputed for consistency so that the same value is used when comparing for every point. <tt>addLast</tt> is set to <tt>1 - Math.rint(Math.pow(Math.random(), getOthers()))</tt>, which makes it 1 most of the time with more bots on the field and 0 about half of the time in 1-on-1.  This variable determines whether <tt>lastPosition</tt> is used in the risk calculation.
 
  
Which leads us into <tt>evaluate</tt> itself.  Basically, after starting out the risk as addLast times an antigravity function on <tt>lastPosition</tt>, [[Rozu]] iterates through the enemies, and for each live one, adds the proposed risk to the total risk (called <tt>eval</tt>). The formula is very simple and elegant (and I don't think I'm exaggerating to say that it's a breakthough in and of itself) - simply <tt>energy ratio * (1 + perpendicularity) / distanceSq</tt>.
+
== Movement ==
* The energy ratio is the enemy's energy / [[HawkOnFire]]'s energy (but no more than 2) - this makes enemies with higher energy more "dangerous"
+
HawkOnFire is a textbook example of [[Minimum Risk Movement]]. The point-generating function generates 200 points at random between 100 and 300 pixels away but no more than 80% of the distance to its current target (to avoid hitting other robots as much).
* perpendicularity is the absolute value of the cosine of the difference between the angle from the point to [[HawkOnFire]]'s current location and the angle from the point to the enemy.  This is 0 when the point is at a right angle and 1 if the point is directly toward or away from the enemy.
 
* distanceSq is the distance from the point to the enemy.
 
  
Once you understand this formula, you pretty much understand [[HawkOnFire]].
+
=== Risk Function ===
 +
The <tt>evaluate()</tt> method is HawkOnFire's risk function, except for one part ‒ the <tt>addLast</tt> variable that is passed in as a parameter is precomputed for consistency so that the same value is used when comparing for every point. <tt>addLast</tt> is set to <code>1 - Math.rint(Math.pow(Math.random(), getOthers()))</code>, which makes it 1 most of the time with more bots on the field and 0 about half of the time in 1-on-1. This variable determines whether <tt>lastPosition</tt> is used in the risk calculation.
 +
 
 +
Which leads us into <tt>evaluate()</tt> itself. Basically, after starting out the risk as addLast times an [[Anti-Gravity Movement|anti-gravity]] function on <tt>lastPosition</tt>, HawkOnFire iterates through the enemies, and for each live one, adds the proposed risk to the total risk (called <tt>eval</tt>). The formula is very simple and elegant (and I don't think I'm exaggerating to say that it's a breakthrough in and of itself) ‒ simply <code>energyRatio * (1 + perpendicularity) / distanceSq</code>.
 +
* <tt>energyRatio</tt> is the enemy's energy / HawkOnFire's energy (but no more than 2) ‒ this makes enemies with higher energy more "dangerous".
 +
* <tt>perpendicularity</tt> is the absolute value of the cosine of the difference between the angle from the point to HawkOnFire's current location and the angle from the point to the enemy. This is 0 when the point is at a right angle and 1 if the point is directly toward or away from the enemy.
 +
* <tt>distanceSq</tt> is the distance from the point to the enemy.
 +
 
 +
Once you understand this formula, you pretty much understand HawkOnFire.
 +
 
 +
[[Category:Tutorials]]

Latest revision as of 22:29, 24 October 2017

Youtube
Youtube has a video of HawkOnFire in action: click here to watch

Rozu released the source to his breakthrough melee bot, HawkOnFire, when he saw that people were genuinely interested in it some time ago. Since then, I think it's been on everyone's todo list to take a look at it. You can view it here.

It seems that Rozu took some time to edit and fix up the code before uploading it here, and for the benefit of clarity, it compiles to be a bit larger than the barely-micro size HawkOnFire normally is. That having been said, with some analysis and tweaking, I got HawkOnFireOS under 700 bytes with no loss of functionality or performance that I can see.

Classes

HawkOnFire is made up of 2 classes:

  • The main robot class.
  • the microEnemy class, which contains the location, energy, and whether or not the enemy is alive. These are stored in a Hashtable in the robot class.

Functions

The primary magic in HawkOnFire lives in the evaluate() and doMovementAndGun() methods. run() doesn't do much besides set up and call these methods, and onScannedRobot() just updates the enemies and handles target selection.

There are a few typical utility functions:

  • calcPoint(), which projects a point some distance away from a base location at some angle.
  • calcAngle(), which finds the absolute bearing from one point to another.

HawkOnFire also overrides the onRobotDeath() method to mark enemies as dead.

Globals

Most of these are pretty self-explanatory, but the Points declared should be explained:

  • nextDestination is the point that HawkOnFire is trying to get to.
  • lastPosition is the point that HawkOnFire is coming from last.
  • myPos is where HawkOnFire is now.

Radar

Spins the radar in melee, Infinity Lock in 1-on-1.

Gun

Not too exciting. The enemy's position is set in onScannedRobot(), and lines 54-57 turn the gun and fire.

Contrary to rumors, HawkOnFire does not always fire power-3 bullets ‒ it's a little more aggressive than a lot of small melee bots as far as firepower is concerned, but not as aggressive as bots with a dependable gun. One feature that's worth pointing out is that target.energy / 3 is in there, which is more than enough to kill the target at that point. HawkOnFire doesn't want a low-energy target to get lucky after being hit. Also, HawkOnFire always tries to target the closest living enemy, and likes to have its gun turned, and never fires when its energy is under 1.

Movement

HawkOnFire is a textbook example of Minimum Risk Movement. The point-generating function generates 200 points at random between 100 and 300 pixels away but no more than 80% of the distance to its current target (to avoid hitting other robots as much).

Risk Function

The evaluate() method is HawkOnFire's risk function, except for one part ‒ the addLast variable that is passed in as a parameter is precomputed for consistency so that the same value is used when comparing for every point. addLast is set to 1 - Math.rint(Math.pow(Math.random(), getOthers())), which makes it 1 most of the time with more bots on the field and 0 about half of the time in 1-on-1. This variable determines whether lastPosition is used in the risk calculation.

Which leads us into evaluate() itself. Basically, after starting out the risk as addLast times an anti-gravity function on lastPosition, HawkOnFire iterates through the enemies, and for each live one, adds the proposed risk to the total risk (called eval). The formula is very simple and elegant (and I don't think I'm exaggerating to say that it's a breakthrough in and of itself) ‒ simply energyRatio * (1 + perpendicularity) / distanceSq.

  • energyRatio is the enemy's energy / HawkOnFire's energy (but no more than 2) ‒ this makes enemies with higher energy more "dangerous".
  • perpendicularity is the absolute value of the cosine of the difference between the angle from the point to HawkOnFire's current location and the angle from the point to the enemy. This is 0 when the point is at a right angle and 1 if the point is directly toward or away from the enemy.
  • distanceSq is the distance from the point to the enemy.

Once you understand this formula, you pretty much understand HawkOnFire.