40R15T3, Eldidou, FredericBautista, Magus, Neumann, PB4608, Yqnn… do the names ring any bell? These CodinGamers have all performed very well in at least one of the past three multiplayer contests: Back to the Code, Coders Strike Back and Smash the Code. With Codebusters coming in less than 3 weeks, we’ve asked them if they could share some tips and strategies.
While some of the tips below are only intended for people who want to reach Legend league, a lot of them are very useful for any player wanting to progress.
The Calm Before the Storm
As a multiplayer contest lasts for 8 days, it can be overwhelming. What’s the best way to prepare for it?
“To prepare for a multiplayer contest, the best I found was to… do multiplayer contests.”
“I try to free some time. Obviously, you cannot do much without time. I also try to find information about the contest.”
“Usually I don’t prepare much. I try to keep abreast of any information which might be given on the chat or elsewhere.”
“I check that I have everything ready to code (IDE and local environment). Then I do something else than coding, since I’ll code a lot for 8 days.”
“I don’t prepare at all.”
Fast and Furious?
Once the contest starts, everyone eagerly discovers the game and first ideas come to minds. How should the problem be approached?
“At the beginning, I try to understand fully the subject and I do some research on the linked problems. I model the game engine to be able to simulate some turns of the game. Then I check that my model is close enough to the game engine by comparing my simulation to the input of the next turn.”
“The first thing I do at the beginning of the contest is setting-up local tests. This often means re-implementing the server-side code (most of the time a good solution will also include this code so it’s not a waste of time).
And after that, every time I make a change in my solution I check if it indeed improves the score by running a lot (hundreds) of tests of this solution versus the previous best one.
Some pieces of advice for this:
- use multi-thread/process, hundreds of tests can take a lot of time
- make your solution deterministic (at least locally) as well as the test case generation, it’s great for debugging
- use an appropriate amount of tests. I often start with 100, and increase it during the contest, since at the end of a contest the improvement I found are often very small and therefore require more test to be measured accurately”
“I spend the beginning of the contest searching for information on Internet while creating a “framework” to simulate the game. I don’t really bother about the ranking yet, I just focus on the efficiency of my simulation.”
“First thing I do is to code the game engine in my local generic arena to be able to test massively as testing in CodinGame IDE is slower. Then I test a lot of ideas: check what works, or what doesn’t. And I also note what could deserve more advanced investigation.”
“The beauty of most multiplayer contests proposed by CodinGame lies in their relative simplicity. It is generally easy to code a simple solution: just aim at the next checkpoint for CodersStrikeBack, make predefined rectangles for BackToTheCode or simply avoid walls in TheGreatEscape.
This simplicity opens the possibility for players to write a simple AI and upgrade it incrementally: this is what we see during the first three days of each contest.
While I understand most people go for the incremental approach, this is not how I prepare for multiplayer contests. I try to stay away from the keyboard for the first few days of the contest. This time is spent on getting a deep understanding of the rules, and designing the full algorithm used to approach the contest. It is also helpful to take the time and observe what basic strategies are used by the first successful AIs. Those are certainly the ones that I will need to counter.”
“I consider the contest like a game, so I don’t have a specific approach. I do it incrementally: I write a bit of code, test it, try to understand why the AI does not play well and then work on improving it.”
Aiming For The Sky
After a few days, we can see the process of slow but sure improvement of the AIs. How does it happen?
“I check after every major change that I have indeed improved when submitting my code: either I get a better rank or I beat more often another player.
I also check for eventual regressions by looking at my first defeats.
I watch a lot of matches to try to understand other player strategies. It can give useful ideas.”
“I often start with a simple non-trivial solution, analyze how it behaves, re-implement a more complex solution, analyze it, and so on.
The time is limited so it should be used wisely:
- Sometimes I fix a bug in my code but it decreases my score. Then I decide to keep the bug which becomes a feature :), and spend some time analyzing why the bug increases the score.
- I look at the code running on the server to find test cases where my solution works unexpectedly well or bad, and I try to analyse it.
- If I don’t know yet what will be my final approach then I don’t spend time on optimization (sorry D. Knuth), as some algorithms start to shine with a fast enough code. On the other hand if I think I’ve got a good approach, I run the current solution with twice more the allocated time versus itself to see if it’s worthwhile to optimize the code.”
“At the middle of the contest, I start again from scratch trying to keep in mind all possible leads.”
“The main trap is to try to do something too difficult, and modify the code with small patches to fix weaknesses of the bot in specific cases. Who never modify his/her code until one match is won only to discover that his/her final ranking is lower after submitting the code?
In this case, it’s important to take a break to come back later with a fresh mind, even if it means re-writing all or part of the code. Starting again from scratch at the middle of the contest might look like a loss of time, but it is usually really efficient.
The only way to know if a modification of my AI is good, is to submit my code. Indeed my AI will fight a lot of opponents with different strategies, so the result will be way more representative than playing against one in the IDE.”
“After the first days of the contest, I write the main algorithm. This generally takes me a few days as I am a slow programmer. I can now speed the process up a little bit by re-using code snippets from previous contests, but I am still nowhere near as fast as regular programmers.”
One Language to Rule Them All
While we have seen many languages reach the top 10 of a contest, C++ seems to be preferred. What’s your favorite?
“I use Dart because:
- I have practiced it enough to feel comfortable with
- Basic libraries offer what is needed for contests
- It enables both types of coding: ugly (not typed, global variable/function…) and proper (typed, inheritance…); so that I can make a ugly try and make it proper once I’ve verified it was worth it
- The competition to earn a CodinGame T-Shirt is easier since only a few are using this language”
“I mainly work with C++ and lately C#, that’s why I chose C# for my first contest CodersStrikeBack (I discovered CodinGame one week before). For the next one, I chose C++ for performance reasons as I was interested to try meta heuristics thanks to the excellent blog post by Jeff06.
C++ is a language with a long history and a large number of users which makes it easy to find examples on Internet. I often use intrinsics specific to GCC and I make the most of attributes and pragmas such as always_inline and optimize.
On the other hand, C# has the advantage of reducing development time by limiting stupid bugs (and not always easy to fix), like for example non initialized variables or segmentation faults.”
“I always code in C++ because good performances are mandatory.”
“I code in C++, for no good reason. I had no real coding experience before joining Codingame, and had to choose a language to learn. I only picked C++ to follow the example of a friend who joined Codingame at the same time.
Don’t use the STL though. Code like a beginner who doesn’t even know that the STL exists. Not using the STL makes C++ much faster on Codingame, which probably helped me a lot during TheGreatEscape. True story :)”
“I use C++ if performances are important, else Python.”
To Infinity and Beyond
Managing to get in the top 10 of a multiplayer contest is a great achievement. Any additional tip?
“There are a few algorithms that are good to know since they often outperform other ones on some classes of problems. For a multi-player contest, I advise to look at minimax, alpha-beta, MCTS. You should know how to implement them, but more importantly when to use them.
Bad practices are actually good in a contest. You will be the only one working on this code and only for few days, so don’t waste your time trying to make beautiful designs, reusable code, or even implementing things like accessors.
No only it will save you a lot a time, but will also often increase the code performance (especially for C++, since the optimization flags are not yet used). So here are few examples of things that you should not be afraid to use :
- global variables
- plain arrays (for C++, avoid as much as possible the STL)
- list of arrays instead of arrays of struct
- and make everything public because you can 🙂
The last advice is to never consider that your code is good enough, you can always do better. Several times, I found myself stuck for a few days and then found a small, but game-changing idea.”
“Never hesitate to question your whole AI.
Always stay on the chat, this is where you’ll find the most information and tricks.”
“You have to play with the different versions of your code and always keep track of your modifications to be able to add or remove features depending on the results. Using a version control system like Git or SVN helps.”
Once you’ve written a “big algorithm” (genetic algorithm, minimax, …), it becomes easy to use it again. It is a brick in your portfolio. Having participated in 4 contests, I am now comfortable with a lot of building material to design complex algorithms with.”
To all of you 40R15T3, Eldidou, FredericBautista, Magus, Neumann, PB4608, and Yqnn, thanks a lot for taking the time to share your tips with everyone!