Individual ranking: #67
School ranking: #1 University of Wrocław
Language: C#
Thanks.
First is first - I need to thank quite a lot of people, for the contest itself, for valuable advice, and just a friendly talk and support. I am starting with huge thanks for the CG stuff for organizing the contest (@TwoSteps ). I would also like to thank the members of our Polish CG Community (including but not limited to @Zylo , @Nerchio , and @TheSkolar ) - if anyone wants to join, just let Zylo or me know.
Last but definitely not least, I would like to thank our students who participated in this contest. I hope it was fun for you (even if it was a mandatory AI4Games exercise list…). In particular, huge congratulations to the awesome coding team forming our university’s representation: @DomiKo, @MichalOp, @maras, @Manwi23, and my colleague @MSz . In my wildest dreams, I didn’t imagine having six people in legend. But I love you even when you don’t get such high scores, don’t worry.
My code.
I did (surprise) beamsearch. I started the contest with, of course, some fast-bronze short python code, then switch to C# and ‘wasted’ >two days encoding everything on bits. Inventory / each spell / tome /potion to fit in simple ints. With a little bit of overthinking, too early, and with multiple inefficiencies on the way, but I was really curious can I do this. I could, I did, and with small extensions I stuck with this representation till the end (with only minor copy-paste inconveniences along the way).
Simultaneously with representation, I was working on some basic BFS, gradually rewriting the engine and adding crucial parts. After finally encoding spells, I tried searching towards the endgame score, i.e., rupees + tier>0 resources. At that time, timeout issues kicked in, and I had to deal with the garbage collector and reusing memory (thanks to @Illedan for helping me). Then comes beamsearch, and some more or less viable approaches to make evaluation function dependent on the inventory related to potions. I had some days of no coding or just small bugfixing, and the gold league came out. I discover a stupid serious bug and, after a day or so, get gold finally. Ah, and of course, I always learn free spells for some constant number of first turns.
In gold, I finally implemented counting how many potions each player brew, and tried some pvp strategies. I got the following: when I discover the opponent has one potion to win, I make for him a BFS depth 5 ending with the first potion. This gives me a threshold, and I perform BFS for myself up to this depth, trying to maximize my score. I slightly extended this with search when the opponent has 2 potions to win and can make a potion in the current turn. I did the things ‘weird way’ because of my limited computational resources. That’s for the defense. For the offense, when my beamsearch discovered terminal state in the previous turn on depth <= 6, I performed BFS optimizing endgame score ending on the first score better than what the opponent can make in the current turn (1 depth search with pots/spells). At this point, I had about eight situation-tuned BFS variants copypasted in my code and reached the character limit, so I had to cut out the unused and commented ones :-).
Then comes a long, last day of using CGBenchmark and optimizing parameters. (And constantly being in nearly-top gold.) Finally, the function turned out to be pretty simple:
PotionValue * 10 * 0.97^depth + Tier0 * 4 + Tier1 * 7 + Tier2 * 8 + Tier3 * 15
I also added some small fix to check my one-turn win, and increase initial learning turns to 10. I tried using hashtables, but they didn’t improve.
I don’t know when (I was finally sleeping, @Manwi23 kept watch) the code was promoted to legend. In legend, I just discovered that as I aready removed one of my expensive heuristics out of evaluation, I can increase search depth limit. Now (using beam size 1000) I usually reach depths 9-11 with ~80-100k nodes per turn.
The game.
I didn’t like it. At all. It was a really awful game showing out what is worst at CodinGame.
The game required really fast performance, cutting out most of the slower languages users except some expert wizards. It had again (remember the post mortems from the Spring!) very low interaction between the players. Not fun. I still feel somehow bad that I made it an exercise list on my AI course. If not for the contest, and knowing it in advance, I wouldn’t use it in my classes.
And the visualization, although graphically nice, was terrible to analyze. It really should have some debug mode with even plain circles and arrows. Pausing each frame to understand which jumping potion comes from which cauldron to which order was a pain. Really.
On top of that comes server issues, extremely lengthy submissions, dead chat problems, etc.
Summary.
The contest was really awesome, and I will always remember it, but sadly not because of the quality of the game - the reason will be people and interactions, making it a great community/social experience. This cat thanks you all.