Let me start with saying that this was the most complex multi-player game ever attempted in CG. I'm sure that team CG was very happy to see how you pushed the new platform to its limits and from that experience it can only get better over time. Unfortunately, at the same time it was the least polished contest of them all. Partly perhaps because of the complexity of the task, but partly due to the design choices made.
I thought it will be useful to dissect these choices, and talk in detail about what and how to improve, as this might help not only you adjusting the game for multi, but hopefully would be a good lesson for future contests makers too. So this is my attempt at constructive criticism, where I'll try not only to complain (as many people before me did :P) but also to discuss the possible solutions.
My Python code was 300 lines. 100 was parsing the input. And I had to do it for the very first bot in Wood 3 already, even if I couldn't yet buy any item or cast spells and I really didn't need to know about creeps and the jungle bushes yet. All I needed at this point was: (x, y, hp) for every minion and hero and maybe the tower health.
More details on input, entities and attributes
Yes, tower should not be a unit and have "stun", "shield" or "gold". Also, static attributes that do not change throughout the game, like tower "range" shouldn't be a part of input (same for bush "radius" or creep "mana regeneration"). I was also really surprised that all the units (yes, including towers) had given the hero attributes, just set to zeros and "-". Why? It doesn't simplify anything. I have a type, I can tell which entity object to create. All I need to do is:
unit_type, owner, *params = input().split()
hero = Hero(params, *map(int, params[1:]))
tower = Tower(*map(int, params))
towers[owner] = tower
minions = Minion(*map(int, params))
Also, it would be great if string attributes are at the beginning (or at the end) of the attribute list, so I can easily convert the rest to numbers (see the Hero constructor in the example above).
And I don't understand why we needed to have "roundType" when all you have to do is:
turn = 0
team, zones, items = init()
me, enemy, creeps = read_state(team)
turn += 1
if turn == 1:
if turn == 2:
Furthermore, I think the choice of a hero in the early leagues should be fixed. Use just one, same as boss is using. Then also fix the second hero, and only introduce all 5 in bronze (or later...). That would make the introduction into the contest much gentler.
I know there were several people asking for all input from the start in the past contests. But this is a bad idea. If you haven't seen it so far, I hope you learned your lesson now. It's much easier to start small and handle more input later when needed (and useful...).
Last thing, the score (here: last hits / denies / hero kills). Already mentioned by several people. The engine should track the score and provide it as input, letting the players focus on playing the game.
Description was overwhelming. But if you take away bushes, neutral units, skills, items and limit the actions to "MOVE" and "ATTACK NEAREST", and the input to heroes and minions "x, y, HP" and towers "HP", it starts to look easy... Also the initial winning condition could be simply "kill all heroes or have more gold" and you can introduce the last hits and denies only when items become available. Really, nothing is more rewarding than being able to start simple and discover more depth as you go (which links to the leagues design, more on that later).
The biggest problem though, was the description formatting. You underused lists (itemisation) except in description of the skills (where you used them), which was begging to be a table. For my own sanity I actually made one, as I got tired of not being able to compare things quickly:
It should probably be combined with the tables given in the github readme. And I don't really mind whether it is a part of the description or external resource with "detailed details", as long as it's all in one place, and easy to compare.
The other issue was the very description of the spells. It's confusing and inaccurate. It took me long time before I understood why my opponents are able to escape the "instantly casted" WIRE. Surprise, surprise, it has a fly time of 0.3 and if enemy moves out of range, no hit. So it's not really instant (like Hulk's EXPLOSIVE SHIELD for example). I only found this out by reading the source code...
The biggest surprise though, was that I can't "MOVE ATTACK" a predicted position of a charging hero while retreating. Simply, if I finish the move faster, I will fire out of range, while the other hero will still be "getting there". The only way to attack in this turn was to move forward with "ATTACK" (bad idea when your goal is to retreat). That was really non-obvious, and it put an end to my 2 * melee sneaky strategy that (I thought) was my ticket to legend... So yeah, such side effects of the complex rules should either be explained, or rather avoided if possible (see more on that below).
I really liked the game concept. Co-op play with multiple objectives, hidden information and opponent moves prediction. All the best things my favourite contest -- CodeBusters -- had (I still remember the brilliance of Recar's ghost hurding tactic :)).
On top of that, you added a time mechanic where actions take fractions of a turn time. It's great idea but it should be implemented differently. Instead of fixed actions with specific
"time properties", players should have the full control over time (in higher leagues). That is, be able to specify a list of actions to execute at each turn. Exactly like humans playing MOBA can do.
Why? Because "ATTACK" or "ATTACK NEAREST" are not that useful. I find myself doing "MOVE, ATTACK" a lot and really wishing for "ATTACK, MOVE" or "MOVE, SPELL, MOVE". Because if you think about it, there is no reason why the number of actions per turn should be limited, when you have time. Time becomes the limit, and as long as you have it, you should be able to chain actions in any order you find useful.
First rule of visualisation is "more is less". I understand that plain geometric objects (like in reCurse's battle station) are not very exciting, but this is why we have the debug mode option. You should use it to show unit IDs, movement and attack vectors, spells and damage / health, all at ones, without a need for mouse hovering for tooltips. Everyone would love you for it
Another thing is stepping turns vs. continuous play. I understand that due to the time mechanics some events happen in the middle of a turn and looking only at the end point (which happens while you're stepping through) doesn't give a full picture. But I would argue that it should, to make the game analysis easier. That is, for every action regardless of the exact time, there should be a visible indicator that it has taken place this turn, at the final animation frame. So that, when I step through a game, I can still tell what happened. Evaporating damage numbers are a good anti-example here.
Also, attack and move speed are not the key stats. HP and mana should take their place rather than being written with white font over a bright bar... (at least use a black font). And it would be great to have a small text notifying of the effect of spells (e.g. "hit by WIRE", "shield activated" or "pulled to (x, y)"). It would help tracking the action and especially, identifying cases when a spell failed.
Leagues and Bosses
The key to success here, is to gradually uncover the complexity. Introduce new rules, actions and input as people advance through the leagues and write bosses that use the new things and are difficult to beat without some improvements. I remember that Wood 1 boss was extremely weak. I've just added a 2nd hero doing exactly the same thing as the first one and rolled over it (I wondered if 2-hero Wood 2 boss wouldn't be stronger). It should at least challenge me to buy items or maybe even trigger root aggro so I have to stop ignoring the creeps.
Anyway, if I was designing the leagues I would do something like this:
| ACTIONS | HEROES | WIN CONDITIONS
WOOD 3 | attack nearest, move | 1, no spells | kill heroes/tower or more gold
WOOD 2 | attack, move attack | 1, 1 spell | kill heroes/tower or more gold
WOOD 1 | buy, sell | 2, 1 spell | more kills (instead of more gold)
BRONZE | action chains | 2, 3 spells | last hits (instead of more kills)
SILVER | | 5, 3 spells | denies
I'm quite convinced that it would help if in lower leagues taking down the tower was easier than later (was it like that already?). And probably in general the towers should be weaker, so that they have to be defended more carefully. I would also make the creeps weaker to incentivise the jungle play and make more strategic shopping possible.
I don't share the sentiment expressed by Magus, Agade and Neumann, that optimising a clear objective is more fun than constantly tracking the META and countering opponents strategies. I enjoy the battle of the wits a lot, even if I'm not particularly great at it
I also don't see anything wrong with "hard coding" a behaviour to counter specific strategies. This is a multi-player game, not an optimisation puzzle, so you need to adapt to the opponents play. And the rock-paper-scissors effect in the ranking, is an evidence that it was hard to win with a single strategy. You need to do variety of things to be hard to counter, and also, constantly improve your bot, when other people challenge you. I see why reCurse didn't like it, but when you are not in the top 10 for the entire 10 days, you see this as a chance!
I also don't agree with Unihedron that the contest should be about programming. It's not that we implement to specification and go home (would that be fun?). We play a game! And part of playing it, is to figure out what is going on, develop a strategy, outsmart the opponents. However, I agree that the learning curve could be more kind, but that can be solved with a better leagues design.
I started this contest feeling I will hate it. I don't play MOBA and I had no strategic intuition of what should my hero do. My very simple approach just blasted me to bronze and I didn't have time to feel the game and understand the mechanics. So I watched how other bots play, and started trying out all sort of sneaky tactics, understanding the mechanics by trial and error (and some reading of the engine code). My efforts where not extremely successful, my initial range bot was still ranked higher than all the sneakiness, but I enjoyed the process a lot!
So thank you @AntiSquid, @Illedan, @Wildum for all your efforts, staying on chat patiently answering questions, fixing bugs, trying to make everyone happy. I think you did great job and a few of the shortcomings listed above, should not overshadow that.
Note to the CG Team
Please make the engine usable in an "old referee" mode, that is to run local games from command line. It's a win/win situation if we can test locally, as we don't abuse CG servers with multiple submits through greasemonkey scripts...