Before I begin, I’d like to highlight that the creation of the Mean Max contest was very rewarding. Building a game for AIs is an exercise I’m not used to and which demands specific thinking. You’ll see that the journey has sometimes been chaotic, but the fruit of our efforts is particularly satisfying. The contest counts around 2500 players, and the feedback seems to indicate that the players liked the game, despite its complexity.
In the Beginning, There Was Only Chaos
Thibaud, community manager at CodinGame, contacted the four of us (Agade, pb4, reCurse and me) on the 31st of May. At that time, even CodinGame wasn’t sure where this whole project was going. They were thinking about how they could open their tools and didn’t know if we would be interested in such a project.
We had a lot of questions:
- Who will do what?
- Who will participate in the design of the game?
- Will we have to code the referee program?
- Will we have to code the view?
- How will we handle disagreements within the team?
- What type of game will it be? (multiplayer, solo, optimization…)
But the most important question was the following: how much time will it take? We had no idea. We all have a job. Some of us were busier than others (Agade was completing his thesis, for example). We couldn’t put ourselves into a project which would require 8 hours of work per day.
Thibaud gave us some answers, but he also admitted that as the creators of the first community contest, we would encounter issues that no one had yet thought of.
However, the best of the best would not stop at the first boulder on the road, would they? (Yes, I like to congratulate myself!)
We all agreed to go for a multiplayer bot programming 10-day contest, but we could have chosen any type of game. Then, Thibaud created the Slack. At first, CodinGame wanted us to come into their office for a day, but this wasn’t possible for us.
Discovering the Tools
During the first two months, we had 2 objectives: begin to think about the design of the game, and understand how to use the tools. About these tools — you have to know that CodinGame wants to simplify them a lot. So, don’t worry, nobody else will have to suffer as much as we did…
At the beginning, I did a super simple prototype of a multiplayer game without view: guess a secret number between 0 and 100. That’s all. Both AIs had to output 1 integer until one of them found the right one! Hey, I had to start somewhere. Next, I coded a more advanced prototype: some kind of “Mini Mean Max” with just one vehicle per player: the vehicle had to be the first to reach a secret checkpoint on the map. No collisions — still very simple.
Brainstorming on the Design
In parallel, we started thinking about the design. We didn’t really know where to go; we actually disagreed on a lot of things. For example, Agade was interested in a “fog of war” mechanic (like in Codebusters), but pb4 was against it. So we finally decided to explore all ideas. Everyone could propose an idea for a game by explaining the outlines and how it would be played.
In total, 14 ideas for games were proposed and discussed. One idea even came from a CodinGame employee (SaiksyApo). I prefer not to reveal the 14 ideas, because they might eventually transform into a real contest. One day, maybe.
Mean Max First Steps
One of the 14 ideas was more interesting to me than the others. At this time, I didn’t know which idea would finally be kept, since we had not started to choose. So I created a prototype for this idea — Asteroids — which turned out to be the first version of Mean Max. One player would control 3 ships on a map. The principle was quite the same: one “Destroyer” to wreck asteroids, one “Reaper” to collect ore and one “Bard” to … do things. What the future Doof could do was still vague.
As an exclusive, here is a screenshot of the first version of Mean Max:
Please take a moment to admire my graphic designer skills.
Then pb4 modified this prototype of Asteroids and had ore ejected from asteroids when the destroyer collided with them.
The Quiet Moment
The first difficulty when you work remotely: people never work at the same time. This slowed down the creation of the contest a lot. You can ask a question and not get an answer until 1 or 2 days later. This is quite frustrating when you decide to get involved. It was worse during the summer when we all had holidays.
At the beginning of the project, Thibaud had given us a rough roadmap with a possible release in November — he had some clairvoyance! Despite this quiet moment, we were still on time.
The First Vote — and Difficulties
We couldn’t work on 14 ideas. We had to focus our efforts. So we decided to vote to keep only 4 ideas. Our plan was to create a prototype for each of these 4 ideas. I was afraid this wouldn’t work, and sure enough, it didn’t — for several reasons.
First, even if CodinGame’s SDK was working, some people on the team had difficulties making it work. The main issue, though, is that we had to make our AIs work on our own machines. I coded them in NodeJS, pb4 in C++, reCurse in C#. Because of this, we needed to install the different compilers and environments so that it would work on everyone’s machines.. Not to mention the different OS we were using…
At this point, I realized something. I had some time available for the project, but not all the people were in the same position. If we were all to vote for an idea that nobody could code, there wouldn’t be a contest at all. Ideas are fine, but at the end of the day, someone needs to code.
We ended up with 2 prototypes: the Asteroids one and one created by reCurse in C# for another idea. So some ideas had been proposed by people who hadn’t had time to prototype them. Eventually, we voted for an idea — SaiksyApo’s idea — that I was eager to develop. I had coded the referee, and I was working on the view. That’s when we started to doubt the global design and fear for the balance of the game. I can’t get into the details, but we couldn’t think of how to solve the design issue.
CodinGame had to make a decision (it was mid-September), so Thibaud told us to go back to the Asteroids game.
There Is No Decision Without a Decision-Maker
The slowness of the project until then was due to one thing: we were all equals. To make a decision, we needed everyone’s approval. It was a huge waste of time. So we all agreed that I should take the role of lead developer from this point on, and be the sole decision-maker. Obviously everyone could share their point of view, but if we had to cut a discussion short, I would make the decision.
Thanks to this new arrangement, the project progressed very quickly. We had a basic understanding of the game, and I could work on the referee and the view. But, we still had to improve the design a lot to have an interesting game.
The Choice of the Theme
Asteroids was a generic name I initially gave to my idea. We wanted to remain consistent with the CodinGame themes, so we took inspiration from the cinema, the literature and the geek culture. As you can guess, we had quite a lot of choices.
We were looking for a theme that could support the idea of vehicles collecting something. I wanted a theme from the Baywatch movie — with a cover showing “The Rock” on a jetski with girls and… But the others refused, surprisingly.
We finally chose Mad Max as the theme because we were very fond of the pun, “Mean Max,” that Agade had come up with.
To be consistent with the theme, we named the vehicles accordingly: “Looter”, “Doof”… We also went for collecting water instead of gas, as it appeared to us as a precious resource worth fighting for in a desert.
The Design Evolution
At the beginning, Mean Max was a bit different. Tankers disappeared once they reached the center of the map. When a destroyer ruined a tanker, the tanker released a barrel of water (instead of turning into a wreck containing water). This barrel was a unit with which other units (except the Reaper) could collide. The quantity of water that a tanker carried was proportional to its size. The Doof didn’t generate rage, but had an aura that would repel any other unit around it. There was no rage at all; skills just had a cooldown.
But even with all these changes, the outline of the game stayed: a 1v1v1 game mode on a circular map with symmetry (for better ranking) and 3 units per player. Nobody but me supported the 1v1v1 mode, and pb4 expressed some concerns regarding the 3 different units (he preferred the 3 units to have the same skills). But I’m a bit stubborn, so I went forward with my ideas.
The following are some ideas that we tried before reaching the state of the game that you know:
- Looters had 2 modes. The skill they could use was only to change the mode with a 5- second cooldown. For example, the Destroyer would have a normal mode and a “berserk” mode where it would see its mass greatly increased, which would allow it to ruin tankers.
- We tried to use the Destroyer’s grenade to destroy the tankers.
- We also tested “inverting” the tankers. They would spawn at the center of the map and attempt to reach the outer order of WaterTown. But it was very complex to handle. We had to prevent the looters from entering the inner part of WaterTown. This would have been a nightmare for heuristic solutions.
Designing such a game is complex because you need to manage some problems:
- Beginners should enjoy the game.
- Advanced players should have something to code after 10 days of contest
- Is there a simple strategy that allows you to get great results too easily?
- Is the game interesting enough for everyone? Do heuristic solutions have a chance to compete?
- Can we guess in advance the type of AI that will win the contest? If yes, are these
algorithms used too often on CodinGame?
These questions motivated our design choices. Here is some additional information about these different choices:
- The 1v1v1 mode: I personally like it a lot, and that’s why I added it to the game. To me, it adds very interesting aspects to the game. Unfortunately, on CodinGame this mode 1v1v1 is not handled correctly. You have to play additional matches to ensure a fair ranking because the maps are not symmetric, and some starting conditions give an advantage to some players.
- The circular map: This is the only way I thought of to have a balanced map with 3 players. I thought about a map with no limits (like on Coders Strike Back [CSB]), but players would have been able to disturb the spawn of tankers.
- The 3 different looters: Even if some were against it, this was an idea I wanted to have because it has never been used before on CodinGame.
- The skills: The skills have been designed to help heuristic solutions. In a game involving physics, search algorithms have an edge. We needed something to balance it.
- The movements: At first, we took the constants of CSB for the friction. But handling movements with simple codes was a bit hard. So we increased the friction so the looters were easier to maneuver.
Was the design successful? I believe it was. If you look at the post-mortems of players in the forum, you can see that the best players have used a search algorithm with heuristics to manage skills. That’s exactly what we tried to achieve.
The Development of the Game
This chapter will be very technical, and might not be interesting to everyone. Just remember that CodinGame is currently improving their tools to create a contest. The next creators will likely not encounter the following issues.
The main parts to code in a contest are the referee program and the view.
The referee is a more or less classic Java program. You can find the complete code on GitHub. Coding it isn’t that complex if you’re used to coding in Java. Here are the main parts:
- Initializing a game.
- Configuring of a game: These are the settings you can find in the “Options” in the IDE.
- Managing the inputs of all players.
- Managing the outputs of all players.
- Handling a turn.
If you implement these parts, you’ll have a working referee, but no view.
To code the engine, I used my own C++ codes from CSB and Fantastic Bits, and also the referee from CSB. CodinGame gave us a lot of game referees; that helped us a lot.
After reaching a state of mental health close to complete madness, and thanks to the precious help from Julien, I managed to understand how all of it worked. To me, the biggest issue lies within the communication between the referee program and the view.
For the viewer to show something, it obviously needs to know the data to display. There is a function in the referee that generates this data. I quickly noticed that CodinGame has a habit of basing the communication between the referee and the view on strings.
At the beginning, I wondered why they weren’t using a JSON format, but I understood why quickly. The CodinGame architecture forces the amount of data transiting between the referee and the view to be the smallest possible. If there is too much data, not only do you impact the bandwidth of CodinGame, but the games load up very slowly. Not to mention the space used on their servers.
In the first Mean Max versions I coded, I was sending too much data. Games were extremely slow to play, and I was trespassing the limit of data set in their tools. I thus worked a long time on optimizing the flow of data. To better understand this issue, you can have a look at how the referee generates the “frames” of the view.
In the view, you have to spend a certain amount of time rebuilding the flow of data. And then, you need to create the different elements on the map. After spending some time understanding how PixiJS works, I managed to draw circles. Fortunately, this was more or less everything that I needed. The animation isn’t automatic; you have to code it, too. If you don’t, there is no transition between two turns. Coding this without bugs requires some time.
Then comes the part where you need to integrate the graphical assets to the view. Julien took care of it. The assets have been produced by a freelancer paid by CodinGame. I’m a bit sad because I asked for flames for the Doof, but the viewer would have been unreasonably packed with details.
The Final Stretch
Several weeks before the contest, we still had to take care of important tasks:
- Write the statement in both languages
- Create the welcome pop-up that appears when you reach a new league
- Create the Wood leagues and their bosses
- Test the game as much as possible to find bugs and possible balance issues
Agade took care of the English statement, and pb4 translated it into French. We have had several issues. There were many updates, and sometimes they didn’t get translated into both French and English. It is written as an HTML file with some conditional comments to handle different leagues. It’s not overly complex, but a mistake happens quickly. 30 minutes before the beginning of the contest, on Friday afternoon, we were still updating it…
But the biggest issue to me is that we had been working on this project for months, so we forgot basic things because they were so obvious to us. What is a looter? Do we always control 3 looters? In this aspect, we didn’t hesitate to update the statement during the contest. I believe we did well. We have even been helped by the community; Orabig created the recap chart you probably saw in the statement.
On this note, I want to confirm that it’s utopian to expect the statement to contain all the rules. It would just become a huge scary block of text that would make a lot of players run. Regular players can refer to the referee if they want details.
I’ve often cursed CodinGame for the quality of their statements. I invite you to come over to the dark side — like me — and see for yourself how easy it is.
The welcome pop-ups are simple pop-ups that summarize the new rules. They are html files that contain screen captures and a bit of text. I took care of it for both languages. I copied the ones from Wondev Woman to begin with.
Fun anecdote: I took screen captures with my mouse visible. A classic! Agade fixed it.
In the code, Wood leagues are represented by a static variable “GAME_VERSION” in the referee program. The bosses are AIs coded in the language of your choice (as long as it’s supported by CodinGame). Respecting CodinGame’s policy regarding these leagues wasn’t so easy:
- The first boss should be beaten with just a few lines of code.
- Each new league should bring in a new rule.
- An AI should not be able to beat a boss without implementing the rule from the new league.
With these rules in mind, we implemented the Wood bosses like this:
- The Wood 3 boss could be beaten by going to any wreck with an acceleration of 250.
- To beat the Wood 2 boss, you could order your Destroyer to ruin the closest tanker to your Reaper.
- The Wood 1 boss uses a simple formula for the Doof: ‘ print(doof.x + doof.vx, doof.y + doof.vy, 300)’. You can beat it using the same formula. With the rage generated, you can throw grenades on your own Reaper to defend it.
An impressive number of players finished in the Wood 1 league. Maybe the boss was too strong. Or the rules added in Wood 1 were too complicated. Maybe a bit of both.
Whatever, I was surprised by how simple it was to get out of Wood. Ordering your Reaper to go to the closest wreck would put you close to Wood 1. Offsetting the speed of your Reaper (`print(wreck.x – 1.5*reaper.vx, wreck.y – 1.5*reaper.vy, 300)`) would rank you in Bronze.
Testing, Testing, Testing
Despite the tests and several bugs corrections, the game still contained a bug in the end condition when we released it. We corrected it during the contest.
Creating Mean Max has been very rewarding. I’ve discovered some problematics that CodinGame usually faces, but which were completely unknown to me. Nonetheless, I’m very proud of the final result. If you’re interested in creating one of the next Community Contests, you should know a bit more what to expect. I’ll likely try the experience again, but not too soon. I will be there to play the next contest, though!