Ended up on the 25th place.
Naive bot
Since I knew I will not have much time for this contest, I decided to kick-start the competition with the Python bot to get early into the league which had the complete rule set.
I implemented following naive heuristic AI:
- if there’s enemy ship within 5 cells from where I am, extrapolate her trajectory and shoot there
- if there’s no enemy around, move to the closest barrel
- else pursue closest enemy ship
I did not even bother working in hex coordinates, used only Cartesian.
Cannon cooldown was resolved by firing only at odd turns.
That was enough to get me to the Bronze League.
Simulator
Then I started writing the game simulator; and having the referee source code was super helpful (but one should have watched for bugfixes there).
Porting the referee from Java to C++ was a bit painful and I second @anon41962965 that the object design could have been better (especially the collision part which is overly complicated).
Scoring function
My scoring function appeared very simple yet super efficient, I came up with it very early and most of the consecutive improvements to it were rather non-improving
So I was maximizing the difference between my and enemy’s score, which was comprised of:
- big bonus for every ship alive
- small bonus for total health across all friendly ships
- a bonus for total speed
- a penalty for bigger distance to the closest barrel
- a penalty for relative angle to the closest barrel
- big penalty for being stuck at the border of the map
Lastly, when all the barrels were collected, like most of the people here I penalized for staying closer to an enemy when I was winning, and vice-versa.
Search
Initially I wrote DFS with the depth of 2 moves (for worst case of 3x3 battle) - that made me competing on par with the middle of the Bronze. Then I started predicting enemy moves applying my naive AI during the simulation and implemented beam search, which propelled me into the top 50 and I never left it since then.
Smart things
…did not work well for me. I tried different advanced tactics, but they at best kept me with the same ranking:
- forcing close combat when ships stuck
- firing at mines that obstruct navigation
- firing at the last barrel when it’s reachable by the enemy
- sacrificing own ship to gain extra health
Probably I did something very wrong.
Performance
Even though I was writing full-fledged OOP with polymorhpic types, dynamic memory and standard library, performance was not an issue. With the use of optimizer #pragmas I’ve been able to simulate about 14k moves per turn which in my opinion was more than enough for such a dynamic game.
Tools
I relied heavily on my unit tests (30 in total, covered mostly the scoring function and the search), which helped a lot to avoid regression.
I used git flow to experiment with improvements on dedicated branches and discard them freely if they did not bring desired result.
CG Spunk was my friend to estimate new bot versus real players before doing timely submission.
Finally I used own-crafted small Python script to compose all the source & header files into single submission unit.