The topic where you can tell how you liked the challenge, & how you solved it.
Thanks again to the creators csj and Matteh and to the testers eulerscheZahl, Illedan, Nanosplitter and SeebOmega
The topic where you can tell how you liked the challenge, & how you solved it.
Thanks again to the creators csj and Matteh and to the testers eulerscheZahl, Illedan, Nanosplitter and SeebOmega
Nice contest overall.
Few if statements to make it to Bronze, few more to climb to Legend.
What I would like:
Lovely contest, and one of the best for me in terms of rank/code ratio - 45th legend before rerun, finalized at 64th.
I have promised a full article to Thibaud, but here’s a quick boildown of my usual lazy approach, which did wonders this time.
I have a very straightforward core algorithm, selecting one order and working at it until it’s complete:
Movement is very simple: with the single exception of the oven, for which I’m keeping the location, I consider everything as a resource and locate it dynamically from the map, from appliances to semi-completed dishes and raw products. A simple function scans the entire map and picks the closest location to the target I’m asking and goes to it with
Elements pickup at step 4 is also rather simple: I go to the closest location that will provide the largest number of missing items.
… and, well, that’s most of it, really. No tricks, no cunning computations, no pathfinding, no accounting for the other player’s actions… More to come in the full PM
BlitzProg - 306th (PHP)
This contest was harder than it looks, and even if you did things right, ranking through the leagues could very well not go as expected. Still, very interesting concept, the other players being partners rather than opponents is something I’d like to see more in the future, perhaps with more defined roles at the beginning (so we actually have to co-operate rather than it being optional). Fairly happy with my rank for the time invested, even if not so good - my only goal was to get into the gold league so I stopped making progress when I finally got in.
Here are the strategies i used:
My AI consisted in preparing in advance most of the 3 required orders displayed, an internal value would be updated during the game, representing the current “job” of my bot. For example if there was no croissant anywhere and it was required by some customers (and the other player isn’t already doing that), then it will start making croissants until there is enough to satisfy all orders.
The same logic applies to strawberries and pies. It will only double on what the other player is doing if that’s the only thing required before making dishes. A job only starts or ends when my player’s hands are empty. When there is no job, it start filling dishes.
Dish logic is fairly simple too, every turn it looks at what it has on the dish, select the appropriate order with the most points, then find the closest ingredient needed to add to it.
I did not work on any form of path optimisation, The “MOVE” command was only ever used for getting rid of items if every table around me was already full - and i relied on the built-in path finding to reach the points of interest.
My AI doesn’t deal with existing dishes nor look at what the other player is doing, maybe dealing with that could have improved it. If the dish is no longer usable, It’ll just deposit it and forget about it.
This logic is what got me from silver to gold tho, this is an upgrade from locking itself to the index of the order (which could change and let it prepare an incorrect dish) and filling the dish in the exact order given, potentially losing time with terrible pathing and realizing at the end it can’t meet the requirement anymore.
Glad I made it into Gold! So far I’ve finished every contest in that league See you next time!
The most interesting contest since the beginning of Codingame.
I wrote a dirty code without reading the rules, in order to reach Bronze on the first Saturday. Then I realize that it was a coop game and it wasn’t necessary to steal croissants and tarts in order to be the first to deliver to customer…
Reaching top 30 of the gold league was very easy, but the gold boss was pretty hard to pass.
In the legend league, I totally loose control. I tried many strategies but ranking was totally random.
Finished 93th with a pretty simple code :
I find the ladder a bit too random. I was changing strategies each league to promote. Got legend but with 135 players in legend i don’t really care.
Also the randomness pretty much ruins testing. On top of that submits were extra slow this contest, takes far longer to test.
My last submit isn’t my best bot, it’s the one that randomly gets highest rank. Went for the dice roll with highest win chances and left it as it is, because in the previous contests i always screwed myself up on last minute submits.
Now about the game. I really liked the cooperative aspect of it. However a 2v2 would have been more fun.
Hope you allow communication at least in the multi to make it more interesting.
Issues about the contest and game:
All in all i like the uniqueness and hope there will be more coop games in the future. Maybe different scoring system.
As for my bot, what i wanted the most is to simply improve my c++ knowledge and i think i spent most of the time fixing bugs.
I finished somewhere around 10th (rerun pending) in legend. At the start of the week I wasn’t really a fan of the coop aspect so didn’t intend to spend a lot of time on it and started with a basic rule based bot, deciding what to do and then using the ‘USE X Y’ to move to that point.
I had 3 priorities: Complete Order, Manage Oven, Create Finished. My final bot still has these as 3 different things, but implemented with 3 searches instead of rules.
Complete Order does a breadth first search only allowing picking up items that could go into a finished order (with the exception of allowing the first item to be unchopped strawberries and the second action to be chopping). Nothing was allowed to be put down (originally I allowed dropping the item I was carrying at the start of the turn, but this didn’t work as well). Visited states were kept unique based on [location, inventory]. If I had a full order and was next to the customer window, I’d keep the move that lead to the highest hand in score. If my partner had a dish with an item on it, the highest scoring order that could be filled with that dish was ignored.
If no orders could be completed from my current state then Manage Oven was called. If there was an item in the oven and my partner wasn’t next to the oven in a state to pick it up I’d try to find a route that went to the oven. This was done with a breadth first search again, but this time I had to get to the oven before it burnt and was allowed to pickup a single item from the edge of the arena and drop it on tables towards the center (dough / strawberries could be chopped on the way and blueberries could be added to chopped dough) before heading to the oven. This was kept unique based on [location, inventory, dropscore] (dropscore was 1 for normal ingredients, 5 for chopped dough / strawberries and 10 for rawtart if the item had been dropped onto a middle table). Once I’d dropped an item the search wasn’t allowed to pickup anything else, it just had to get to the oven. The idea was that items in the center were more easily accessible, but the priority was to not burn anything.
If neither of the above states were valid (no orders could be completed / oven was empty) my final search would try to find the best way to get a raw tart or dough next to the oven or chop strawberries and put them on a middle table. This was again done with a third breadth first search, only allowing picking up unchopped strawberries, dough, chopped dough and blueberries. The unique state for this search was [location, inventory, blueberry location]. If I was carrying anything other than blueberries at the start of the turn it was allowed to be put down on a middle table, but not included as part of the search. The blueberry location was set when I dropped blueberries (to allow moving them closer for preparing tarts). This search would terminate when it had found a route to do all 3 actions. I’d then choose which of the 3 dishes to create based on number of turns, number of each item available and number of each item required for the current set of recipes. Cooking time wasn’t included in the time, and croissants had a penalty of 5 turns so I’d prefer to prepare tarts as they were worth more. If the oven was empty and my partner didn’t appear to be trying to use it (carrying dough / chopped dough / rawtart) strawberries had a penalty of 5 turns added to prefer to get something in the oven.
For my partner I assumed they would stay still and do nothing at all times. If they were by the oven and could pickup the item in it then I would count the oven as empty. If they were in a corner and blocking an item I’d move them one square away from me to allow the search to always find an item. If they had a dish with an item on it I would ignore the order with the highest score that they could complete.
I didn’t have any logic for allowing dishwashing (I tracked how many dishes were out and didn’t allow using it for a blank dish if 3 were out, but couldn’t clean a dish with items on it).
This was enough to be top of legend on Saturday, but other people improved a lot on Sunday. I think I end up struggling due to how I’d separated tasks as I let things burn if an order could be completed and some maps I would do very inefficient routes as I wouldn’t start preparing a dish until all the components were available. Partners who didn’t stand next to the oven while cooking also caused me problems as I’d try to save items that didn’t need saving, which I think was happening more and more towards the end of the contest.
What is your bot doing if the partner waits in the corner, next to the oven and blocks another item?
Fun ! I really liked this contest, sadly life got in the way after wednesday, so my final code is my wednesday code. Still I manage to reach legend with that code (it’s still stabilizing, but I would probably end up around 100-110).
I’m starting to become a csj fanboy, I really liked Code Royal and really liked this one. Simple for heuristic and the co-op was a good idea (and funny since I was playing Overcooked these days with my gf hehe).
I’d say most of my progress is du to a good organization of my data.
All the ingredients has some static data where I classed them like:
Then based on whats in my hands and the customers I would just sort missing customer ingredients by how long it takes to make them (tart, croissant, chopped strawberry, then the rest)
So let’s say I need a tart, I had a recursive function who would check:
Once I had that it was pretty easy to separate the decision making from the “doing it”.
The 2 other “good thing” my bot was positioning for next task and dropping stuff.
I made a small sim to predict depth 1, well not exacly depth 1, but where I would be once I reached the end of my current task (If I’m trying to chop strawberry, that would be next to the choppingboard). Then I would simply rerun my AI on that new data, depending on the “futur action” I would stand closer to this location since by default the “USE” command will stop at the closest location when going further could be better since you can move by 4.
The other thing was dropping, I would try to drop things either next to where im going (if im chopping stuff, I’ll leave that useless icecream close to the chopping board) so I can potencially pick it back up once I’m done. But later I added a check to drop stuff on a counter where someone standing next to the transformation station could reach it, so someone looking for strawberries to chop or dough to cook are more likely to have one standing right next to the station and combined with my better position because of my sim, it often meant going next to the oven pick that dough and put it in in 3 turns.
In the end I started to make enemy prediction, so I could stop going all the way around, it was working but didnt do anything with that info, if I’m motivated for multiplayer, I would probably improve on that.
This was my first contest, did not know what to expect, but it was really fun. I guess my competitiveness took hold of me and I did not get enough sleep for a few nights.
Anyway, finished 70 Legend. As others, no problem until gold, then got stuck with the boss. What finally got me to legend was calculating distance to every needed ingredient and picking the closest.
My strategy was a simple one (if you can call 80 ifs simple):
If I needed to be there I’d just keep trying to walk into them. I never saw this happen more than once, but it was something I was concerned about and just didn’t have time to come up with a better solution (originally I moved them one square closer to me, but that performed worse). I think as it limited their options to only moving in the other direction most people would move away quickly.
Looks like it’s going to be 116 for me, legend. But only because someone broke the gold boss last night and I passed.
It was certainly interesting to play coop, and like most people I didn’t realize right away. There was this one guy that kept throwing away my croissant to prevent me from fulfilling a recipe. Such fun!
It didn’t come naturally to me, so had to work hard to pass each league. In fact, I’ve never put so much effort into a contest or multi so far and lucky me I didn’t have much work at work
The core of my retarded bot was counting all the necessary items needed for the current orders and subtracting the relevant items that are ready laying around. Based on the count and the score of the order that an item is used in, I went for making the “most valuable” one. This worked far better for me than anything else, and, believe you me, I tried some stuff. I think this worked particularly well because this way more orders are “covered” at the same time (e.g. 3 orders have a tart in them - go for tart). So the different sorting among other players problem was little bit eliminated.
Things that didn’t work for me (like in every contest/multi) was the predictions. For instance, I tried accounting the other chef’s items and subtract from the total count and so on. Result - abysmal. It was horrible. I think I passed bronze or silver (forgot) by just assuming the other cook is going to burn whatever it’s in the oven, so for a long time I glued myself to it, whenever there is something in it.
Some small things did help though: using BFS to measure distance instead of some approximation, leaving items on the S-ish shaped table in the center and ignoring the outer ring did open up a lot of options, leaving complete orders on said table for the other chef to deliver, and of course a little bit better oven handling with proper priority.
I’m kind of surprised to reach legend, a bit of luck for me for a change
Finished pretty much at the bottom of Legend.
In all honesty, I wasn’t very inspired by this contest, probably due to a mix between the very slow pushes at times, the randomness of the ladder and the complexity of the engine if I was gonna write it combined to a bout of laziness.
In the end I think I must only have spent something like 12ish hours on this during the first half of the contest and left it at that.
If there’s one thing to be proud of tho, it’s that my bot still made it to legend, with only some 260 lines of code, no simulation, and a minimal number of if statements.
I simply wrote the code for what happens when you “USE” any kitchen implement or item/dish sitting on a table according to whatever it is I’m carrying.
So on any given turn, I’ll simply try “USEing” every possible thing on the map (regardless of distance) and score whatever I’m gonna be carrying as a result, compare it to my current score and then pick the best.
The eval is as follows:
If no “USE” action actually increases the score, drop whatever I’m currently holding on the nearest empty table (because that means it’s useless).
And finally, if currently holding a dish that exactly matches an active order, go to the bell to deliver it.
And that’s pretty much it. It actually performed admirably all things considered.
I’m 6th Legend with deep search algorithm.
It was a funny and great contest, i loved it!
Here is the pseudo algorithm of my solution.
(Please forgive my poor english grammar, i know my weakness :/).
Each Turn :
1- I remove the customer order more near from the other bot’s dish (if have one with at least one item).
1b- If an order is removed, i add the next customer order from the full order list to the current list.
2- From the current order list, take the one (or more if they’ve equals esimtations) wich have the next task more near to me (the most profitable).
(Next task can is : make an item, assemble the dish or deliver it).
Set the root node to the current kitchen state.
While have time (50ms) :
Build all actions from the current node state. Actions are, all moves 1-4 tiles from my position, all uses just next to me (3x3 tiles), one drop (the table beetween me and other bot), and wait.
There is 10-15 moves average in a game for a kitchen state.
For all actions :
If i’ve evaluate all actions of the current depth, go to the next depth.
The next depth is a new action for me, not the other bot action. It’s like i consider the other bot play only WAIT.
At the end of time, play the best move in depth 1.
My code be able to see depth 3-4, it depends on situations. So, my bot can takes shortcut for build the dish for exemple.
At the end of contest, i had a better oven management, plates counter, littles rectifications, etc …
Concerning code’s architecture, i have an asbract Action with two mains methods [play(Chief, Kitchen) and inverse(Chief, Kithen)] for browse the game tree, and multiples extended actions likes MoveAction, OvenAction, DishWasherAction, DropAction, etc …
Thanks to csj and Matteh for they job !
I coded only the first Friday to try the game and reach bronze, so my feedback is very limited, I just want to say that the “cooperative but competitive” genre of the game was fresh and cleverly implemented with the 2-player rotations !
That was a great game, I wished I had the time to really participate (my code is only a bunch of IFs conflicting with each other).
To the creators of the game: that would be awesome to have a SOLO version and an OPTIMIZATION version.
Here are some ideas:
SOLO: only one player, limited time to finish one or several orders (to be decided). 1 or more chefs (to be decided). Different maps or not. There could be several versions depending on the difficulty of the puzzle.
OPTIMIZATION: same as solo but you need to do the best score. Maybe only 1 test case ?
13th Legend. I went out of my way to do something complicated and sub-optimal this time, so the result is a nice surprise!
Regarding the contest, it’s really cool that it allows heuristics to be competitive, so kudos for that. On the other hand, scoring was ridiculously random, my bot could end anywhere between 10th and 40th… I wonder if there might be ways to improve this aspect.
For my solution:
In retrospect I would probably have been better off taking the time to write a score function and limit the search to a few turns, but using more action possibilities, and simulating the other chef as well. But god do I hate to write score functions.
I have 179 ifs in my code. Could have been worse I guess.
Thanks again to csj and Matteh!
Great contest. Thanks a lot to the creators. I ended 8th and put my post mortem here:
Many thanks to csj and Matteh for an excellent competition!
I ended up coming second. Many congratulations to morozec, a clear winner in a messy contest.
In summary: a nest of ifs. Perhaps the core choice that I made is not to head for particular dishes. Instead, I make ingredients that are needed, and then assemble items that have all ingredients ready as they come up.
I have two main phases: target selection, which assumes my partner will stay still, and route planning, which thinks about partner movement.
This returns our next usable destination and our probable destination after that, and is the meat of the algorithm.
We start by prioritising croissants, tarts and strawberries. We only care about items needed in the current three recipes that we don’t already have enough of. Within those, we prioritise those that don’t exist, and that our partner isn’t making. After that, we prioritise those we need the most of.
We then go down the following list, taking the first action that applies:
This takes a destination and a next destination from the target selection
Other bits and bobs
Unimplemented ideas (mostly half-baked)
What I prioritised was definitely guided as much by what fitted into my (messy) code as what was important or right.
Thoughts on the game and my approach to it
Thanks again to the creators for a fun contest!