14th
Performance
I copied the referee to simulate the game. In hindsight that may wasn’t the best idea, as my simcount is quite low compared to others (about 3500 single steps in the best cases, also because I used C#).
For speedup I did two things: cache collisions and assign objects to fields on the a grid for faster prechecking.
For caching I just compute all possible collisions at the begin of the turn and later only update the objects involved in one collision.
For the grid collision I split the total board in regions of size 1500x1500 (so I get 8x8 regions on the map, ignoring the edge, where only tankers can be - this makes me blind for collisions in that area, but they aren’t that important). The size is because that fits in a 64 bit integer.
I then create a surrounding rectangle for each object at the beginning of the turn as follows:
// xMin, xMax, yMin, yMax are in range 0..7 for grid coordinates
// don't forget that the objects are moving when computing the limits
ulong xMask = (1UL << (xMax + 1)) - 1;
xMask ^= (1UL << xMin) - 1;
Grid = 0;
for (int y = yMin; y <= yMax; y++)
Grid |= xMask << (8 * y);
Later for ever collision check I can do:
if ((unit1.Grid & unit2.Grid) == 0) continue; // no collision
That checks, if the objects can even be in the same region with a single bitoperator and a comparison. For most cases that is false and I can just skip the more expensive check.
Generating moves
In most cases it makes sense, that the reaper goes to a wreck or the destroyer to a tanker. So I don’t genereate most of my moves in a fully random manner, but select a target depending on the distance and type of the target (the reaper might go to a tanker as well - I can destroy that and make it a wreck before the reaper arrives, but wrecks are more likely to be a good target).
I realized, that the speed is equal to the max speed in many cases, so I choose that more often.
Grenades and tar are placed randomly, as it is hard to see what will happen. But for oil I use a heuristic to selects a good target, as my bot often partially covered a wreck, allowing the opponent reaper to just move a bit to the oncovered part or even split oil accross the map without any opponent or wreck in sight, wasting my rage.
Mutating plans
I did not write a genetic algorithm. Instead I randomly choose one looter, assign some semi-random moves (depth 4) and keep it, if it’s better. In the case, that I wanted to spend more rage on my new plan, than the plans for the other looters allowed, I just set their actions to WAITs.
Enemy prediction
I basicly used the same code to predict the enemy, that I then use for myself, but with some restrictions. The enemy assumes, that I wait myself, doesn’t try to block me and can’t use skills (these predictions were to unreliable). The enemies don’t know about each other’s plans. I use 20% of my time for each enemy and the remaining 60% for myself.
Scoring
The most important factor is water of course. So I massively reward the gain of it.
Then comes the distance of my reaper to wrecks. Here I use the amount of water, squared distance, distance to other wrecks nearby and whether I’m closer to the wreck than the opponent reapers (euclidian distance, the attempt of a more precise estimation including the speed made it worse). The first round is more important than later ones, as the enemy prediction become increasingly unreliable.
I do the same scoring for my opponent too and subtract it with a certain factor. The opponent closer to me in score is more important (so I’ll try to at least save the second place, when one player has much more water than I have, while the other is slightly behind).
I did a little offline training to check, how important different things like closeness to a wreck and having much rage are. I think it gave me 1 or 2 points on the scoreboard, but at some point stopped helping - other arena bots are to different from mine and getting better against myself isn’t the same as getting better against other bots.
About the game
It was a fun game, but sometimes hard to see what’s going on. The complexity didn’t allow heuristics at the top. The referee was very helpful. Much respect for getting such a complex game almost bugfree from the beginning on (only a misplaced exit condition on crashing players).
Thanks for reaching silver in the stream and not struggling to even reach Bronze.
I don’t see a problem with the contest creators participating. They did a great job creating a new contest for us - for free. The least we can do to honor that is letting them participate for fun and not complain about that.