Sopra Steria Coding Challenge

thanks for reporting it, we’ll look at it right away

EDIT: should be back really soon

There is an error in the statement and in the example program:
C’est votre premier buster […]”
This is the third buster and not the first buster.

Moreover I don’t see colored border for each buster.

For the busters, you can either:

  • use the debug mod (available in the settings),
  • add a letter (H for hunter, C for chaser, S for support) at the end of each command.
1 Like

This is not a post-mortem as my ranking does not justify it, just my two cents on the contest.

First, the subject itself. Even though it is closely related to CodeBusters, the differences (specialized busters, ghost behaviour) called for a completely different bot and I think I have only started to scratch the surface. Even though it may happen again as a semi-private contest, it will be still worth playing it.

On the event. This is exactly the kind of community event I wish CodinGame organize on an extended weekend: select a multi (people keep on delivering new ones) and gather a bunch of people around it. It does not matter if there is nothing to win and if it is slightly unfair because some people have already played it. This would be a great opportunity to learn, improve, brag and have fun with people sharing the same interests


Hello everyone,

Ranked 2nd.

It was more interesting then I though after seeing that it was similar to Code Busters event. I didn’t really participated in this previous event, so I was not able to take a previous code.

I have to admit that winning the PS5 was interesting me. That’s why I spent a lot of time on this contest.

Like nearly everybody else, my code was a huge bunch of if/else.

My first rush between the beginning of the contest and Saturday night, not bad because I reached 2nd place.
I think I won’t be able to remember everything that I code. Here are some few:

  • If possible, bring back ghost with 40 stamina before BUST
  • STUN only when useful (catcher having or going to take a ghost, hunter if stamina>10 and no ghost with low stamina near the opponent catcher)
  • Better management of bringing back a ghost (if an opponent is near, be as close as possible)

Then break until Tuesday night due to an important personal thing to prepare (not compatible with sleeping few hours due to the contest). Even with this break, I was still in the top10.

On Thursday night, I was able to reach top 1 \o/ and keep it nearly until Saturday night (pb4 posted nearly equals to me on Saturday, then became clearly stronger during the night). During these few days, it was just a frustration. I was still having many ideas, but none of them were helping me ><’. It was similar or even worse according to tests performed with CGBenchmark.

  • Seeing if I can steal an opponent ghost. SAME RESULT
  • Being better placed when waiting for a ghost to be at stamina 0. SAME RESULT
  • Reach my hunter when the stamina remaining and my distance to the ghost match. SAME RESULT
  • If waiting with hunter, stay enough far to not allow my opponent to see the busted ghost. SAME RESULT

I still don’t understand why all of this was leading to an IA with similar results as the one posted :frowning:

I finally decided to stop doing my ‘TODO list’, watch more replay and try to see something improvable.

I performed a small modification: when a ghost was going outside my view, I admitted he was just nearby at a calculated spot. But when my opponent was STUNing my catcher, and making the ghost going more far, I wasn’t able to find him. For me, if the ghost was not in the ‘supposed’ place, he was in its initial position, which was not true too… He was just a little more far! And that’s how I was giving ghost with 0 stamina to my opponent…

So I coded something to try to go further once “just in case” if not seen in the calculated spot. It was between 3 a.m and 5 a.m in the Saturday night… (that late in the night is already Sunday ^^)

I wasn’t home during Sunday, but I launched CGBench to test it. When coming back home. I saw that it significantly improved score :slight_smile: . It is my last and posted version around 20p.m.

I was having many ideas on being super aggressive and try to fight a lot with opponent on ghost. But there was some behavior/bug that stopped me.

  • The barycenter when several busters were at the same ghost position was truncated. Which means that the red player was having a huuuuuge advantage (I let you do the math, but truncate would always lead to something good for red when busters are fighting for it at a distance of 1).
  • The hunter would still be able to stun the ghost even with stamina 0. This would avoid the ghost to move. Hard to see and could be dangerous
  • Bug: I have been able to see two busters on the same spot. Let’s take (400, 400) as example; and ghost on (401, 400). Expecting it to be on (801, 400) on the next turn. But it ended on (1, 400). So going on the opposite way XD. I still haven’t been able to understand why.

Thanks to pb4, it is the first time that I use CGBenchmark, and I have to admit that it is so useful!

  • Debug à In this contest with deterministic IA, you could create a new functionality with an assert in it. You launch CGB, at the first crash of your bot, you have found a game where you can try and debug this functionality. Moreover, you can let CGB turn to saw how frequently it will be call by counting the number of game leading to a crash.
  • Knowing what seens to be better (coeff, functionality actived…). I have a family, and it is hard to code before 22p.m. So, when you can’t code, you launch it on different versions and it will provide you useful data =).

The last 5 hours of the contest were incredible. So much pressure seeing so much top10 submitting code. Still, I was at a comfortable 2nd position 30min before the end.

And then… Daporan makes its entrance. The first submit was scaring. I was using CGB against him and was having around 35% of win… pb4 told me it was around 40% for him. We thought we were doomed. BUT, he was not that good against the other player in the top10. He finished 3rd after its 1st commit.

Few minutes before the end, he submitted again expecting to be more lucky. And he was… He was still having around 65% against me (so not lucky, not unlucky according to CGB). But against pb4 he was super lucky. Something around 75% of win. That’s what leads us to him first, and pb4 going below me. Unexpected and lucky O_O.

To be honest, even if allowed to hide your bot during the entire contest, for me it is not fairplay.

Not having a rerun at the end was really bad. Few matches with a close top players could leads to lucky ending like it happened. For me pb4 should be first. Daporan and me really close for the 2nd place.

What will I win? Daporan is Belgian. I don’t know if he is living in France or not… If not, I hope he will not fake it.

Thanks a lot Codingame and Sopra for the contest. I enjoyed it (even if my sleep account was terrible thanks to it XD). I haven’t been able to see many streams, but thanks also to Neumann and jfaixo, it was nice from you to do it :).
See you in the next contest!


There is only thing I am proud of in my code. So I am going to share it.

It is my function getNearestGhost where I take a list of Filter defined as enum.
Thanks to this, it is nearly the only “for” loop on ghosts in my entire code :slight_smile: .

As discussed in CGChat, some persons used a lot of “for” loop. If this can help them in the future, it will be a pleasure.

Also, if you think it could be performed better, feel free to comment it. I would love to have feedbacks.

Nah, his AI was better. His code clearly deserves the 1st place.
But I would have loved the late push to be unsuccessful, like his very first push :innocent:


k4ng0u - 6th (C++)

It’s been a while since I used so much heuristic in a contest (probably since Code A la mode). My final code contains 207 "if"s and 69 "for"s :sweat_smile:

About the contest

At first, I thought people that participated to CodeBusters would be at an advantage but in the end, I think the buster roles and the fact that ghosts return to their initial position made it that most of their code wouldn’t be reusable or at least invaded by a fast growing new forest of ifs. So the contest was actually quite refreshing and fair for everyone.

On the negative side, the statement and inputs were awful to understand, notably the ghosts movement and the value/state from the input depending on the entity type/role. If another contest is hosted on a variant of CB, please at least state the “nearest ghosts” instead of “near ghosts”.

My strategy

Full exploration to know the ghosts initial position

My first thought was that, thanks to the symetry of the map and the fact that ghosts return to their initial position, it’s possible to have a very good estimate on where all ghosts should be after a few turns of exploration. And this would also prevent my busters to wander aimlessly during the rest of the game.

So at the start of the game I would be in exploration mode on my half of the map until I know where all the ghosts (other than the one in the middle) are. Each time a ghost is found, I would keep its initial position and apply it to his symetric. This would mostly be accurate since the ghosts closest to your base are unlikely to have been moved by the opponent.

For the exploration I used a beam search with 12 angles per buster and a beam width of 15. With that I could only reach depth 2. It was quite ridiculous and retrospectively I should have just hard coded some positions, but well it was more or less doing the job.

Understanding ghost moves

The other important point was to have an accurate ghost simulation to know their next positions: where the ghost is pushed and how it will try to go back to his initial position. Here is how we could translate the statement (or at least what seemed to work for me):

  • “If a buster is closer than 2200 from a ghost, and this ghost is not being busted, the ghost will move away from the mean position of the near busters”: ghosts move away from the closest buster in their vision range. If multiple busters are the closest, it moves away from their mean position.

  • “If they aren’t at their starting position, the ghosts will try to return directly to it. If this makes the ghost go closer than 2200 units to a buster, it will begin to flee again”: If this makes the ghost go closer than 2200 units, the ghost won’t move.

  • Ghosts don’t move when the point they want to flee is on top of them

  • Ghosts don’t move when they lost at least 1 life point during the previous turn (but they do when they are busted and their life was already 0)

Various micro strategies

My macro strategy was bad overall but I had a few micro optimization that would compensate for it:

  • When busters go for a ghost, they should target their next position and not the current one

  • Catcher should always try to position itself so that it can catch the ghost but at the same time be as close as possible to its base

  • When releasing the ghost try to be at exactly 1600 from the base to be faster to get to the next ghost

  • When too close to opponent catcher or too far from my base, the hunter should push the ghost toward my base

  • When pushing a ghost, place yourself at 1 unit from his next position (this got me to the top on the 1st Sunday)

  • when the opponent catcher is stunned with a ghost, if you can’t take the ghost and get 5 moves away from it before the opponent support can stun you, just give up on that ghost as you will lose the trade

  • If both catchers try to catch the same ghost, position your support so that the ghost will move out of the opponent catcher range => this way you are the first to catch it forcing the opponent to stun first and you will likely win the trade (this put me back on #1 on Wednesday)

Laet Additions on Sunday evening

On Sunday most top players were doing everything I did a bit better and I was barely hanging in the top 10. So I added a few last minutes updates:

  • When pushing without opponents around, do it with a distance 50 so that the ghost take a better angle towards the base (with distance one, it was either 0, 45 or 90 degrees)

  • When pushing with opponents around, do it at a distance of exactly 1 pixel. With this the ghost can only be pushed horizontally or vertically but at least you prevent the opponent to be the only closest buster and totally drive the ghost move. E.g. ghost is at 400,400 you want to push it towards 0,0 and places yourself at 401,401 and the opponent positions itself at 399,400 the ghost will go 800,400

  • If the opponent catcher is carrying a ghost and I can win the trade according to stun coolddowns, chase his catcher instead of trying to get other ghosts

  • With more and more pixel perfect plays, it often happened that the game will be stalled, ending in a draw. In this case, I would stun the opponent catcher at turn 249 so that in case the opponent doesn’t do the same, I could catch the ghost on the last turn and came out the winner (I stole this from a replay with egaetan but I think a lot of top players were using it as well)

My goal was initially to beat Saelyos’ bot which was submitted 18 minutes after the contest started. So mission (barely) accomplished! (thanks bowwowforeach)

Thanks Codingame and Sopra Steria, as darkhorse mentioned it was quite fun to have many people gathered together around the same game for a week! Maybe it could be nice from time to time to have a multiplayer of the week/month with bonus xp/cp for people who passed leagues/improved their ranking?


Dapo won? :slight_smile: