Melee Strategy - Understanding HawkOnFire
By Kawigi - hopefully also looked over/edited by Rozu
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).
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.
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 also overrides the onRobotDeath? method to mark enemies as dead.
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.
Most of these are pretty self-explanitory, 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.
Spins the radar in melee, InfiniteRadarLock?
Not too exciting, the enemy's position is set in onScannedRobot
, 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.
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).
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 antigravity function on lastPosition, Rozu 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 breakthough in and of itself) - simply energy ratio * (1 + perpendicularity) / distanceSq.
- The energy ratio 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.
Great. Haven't read it yet, but I just must comment one of the first statement - "I think it's been on everyone's todo list to take a look at it." Ha! I have never even considered taking a look at it until this page came up. Now though I just might. Just need to fail in a few attempts at melee movements myself first. -- PEZ
I rather read pages like this than to look at the code. When looking at the code, I just see the code. When reading a description like above, I form my own ideas and try to implement them the way I see fit. Ofcourse once in a while I also copy things (like teamcommunication, circular targeting) but I still try to adapt and improve them to my needs. This is yet another excellent page. I wish that I could a) write such clear and informative page and b) write such sophisticated and competetive bot. -- GrubbmGait
Code or prose. Not too much difference for me (as long as the code is somewhat readable). It's just that I don't want to get to "coloured" by other peoples ideas before I try myself. I want to get those "ahhhh!" feels when I later try look at how people have approached the problems I have stumbled across. -- PEZ
I do not know if this has been said yet, but welcome back kawigi. Good to see you around the game still. -- jim
Nice page! I don't think that I have something to edit here. But anyway, I'm open to answer any questions as required. -- rozu