I’m noticing that damage is calculated on the first action phase, and I think this is either a bug/undesirable behavior. When either parsing replay files or using on_first_frame(), the game state being passed in is really the “second” frame of the turn.
Here’s a (highly theoretical) example. If player 1 placed 10 EMPs up close, and player 2 likewise an encryptor up close, neither player would be able to see that encryptor when analyzing action phases, as it doesn’t exist in “p2Units” (because it was destroyed in the “first” action frame). Note that it is visible in that frame in the “spawn” section, but the starter kit’s game_state parsing does not account for this and goes purely off the “p1Units” and “p2Units” part of the serialized string (this is done when game states are initialized out of the game state string passed to on_first_frame()). Here’s the replay of me doing this (by skipping the first 60 some turns in the game) game_engine_bug.replay (91.3 KB) It can be seen that the encryptor placed is entirely missing out of the “p2Units” section.
A more realistic (and very common) example is when information units are in range to attack anything on that first frame. The unit information passed in to algos/parsed from replays will see the game map after the damage has been accounted for that frame, giving inaccurate information regarding how that turn started. The particular worst-case of this is when information units attack each other and die that frame, making crucial information about enemy placements unavailable. Another bad case that can confuse algos is the destruction of a firewall unit on the “first” frame, which is fairly common when playing against a maze algo that will chip away at a corner placement.
Here are a couple fixes:
- Have an actual “first turn” of the action phase, where no damage is dealt/no units are moved. The downside is, of course, that the .replay format has changed and the game engine has changed, which could seriously mess up some players.
- Read in the game map from before either player has placed that turn, then add in the new units from the “spawn” event section to update the map.
– For algos, this would need to be done by the starter kit by storing a copy of the original on_turn() game state, and having a special game_state constructor for the specific case of the on_first_frame() function, as well as calling on_turn() within on_first_frame() to not miss information from the “first” frame that was passed in. Not ideal, and causes an extra call to on_turn() when no information units were spawned that turn, so a special case needs to be tied in for when there are no information placements.
– On the replay parsing side of things, this would work fairly well, since on_first_frame() and on_turn() consequences aren’t relevant.