There are two important parts to retrieving the breach
information (and similar information, such selfDestruct
, etc).
- Breach data is only reported with results of the action phase, which are not stored by default
- Breach data is not parsed by
game_state
, so it will have to be modified to actually retrieve the information.
Retrieving the results of the Action phase
The default AlgoCore does not report action phase data, so you will need to change that. If you look at the block of code from lines 55 to 80 in the algocore.py
file, you can see that this is the section that handles turns. If it is the build / deploy phase, self.on_turn(game_state_string)
, from AlgoStrategy is called, which parses the data. However, if it is the action phase, nothing happens. To change this, I created a function in AlgoStrategy called parse_action_phase
, which takes the game_state_string
as an arguement (similar to on_turn
in this way), and called it in the correct if
block in AlgoCore. I then used that function to parse and store information
Retrieving the information from the game_state_string
Now that data from the action phase has been retrieved, it now has to be parsed so that it is readable for your code. I started by parsing information the same way as in the on_turn
function, by creating a game_state
. To get breach information from the game_state_string
(called serialized_string
or state_line
in game_state.py
), first find the__parse_state
function (technically, you can do this anywhere, but considering that you are parsing a state, this seems to be the correct place to do so). At any point after the line state = json.loads(state_line)
, using state["events"]["breach"]
will give you the information on breaches.
To be honest, I don’t really know what all of the information reported about breach
means. However, these are my best guesses:
- The 1st piece of information, the 2-number array, is the location of the breach
- The 2nd piece of information (counting the array as 1) is the damage dealt by the unit
- The 3rd is the type of information (3 is Ping, 4 is EMP, 5 is Scrambler).
- I don’t really know about the 4th, the string of a number (ex.
"730"
), but it might have to do with the unique identity of a unit?
- The 5th piece of information, the number that, as far as I know, is always either a 1 or 2 (but I am not sure about this), is still a mystery to me. Maybe player identity?
I hope that this was helpful, despite how long and badly phrased it was. If it doesn’t make sense, please ask for clarification.
Edit:
A discussion about what all of the numbers mean has happened in this post:
https://forum.c1games.com/t/parsing-replay-files/276/10
Edit:
One thing that I didn’t mention (because I didn’t know) is that GameUnit
doesn’t like REMOVE
units. If you create a GameState
based on a game_state_string
from the action phase, and a REMOVE
unit is present, your algo will crash. This is because certain qualities (such as speed, damage, range, etc.) are not defined for the REMOVE
unit. If a GameUnit
of a REMOVE
unit is created (GameUnit
s are created when a GameState
is created), you will receive an error. To fix this, you will have to edit unit.py
. In the function __serialize_self
, add 2 lines after the line
from .game_state import FIREWALL_TYPES, UNIT_TYPE_TO_INDEX, ENCRYPTOR, REMOVE
(Or really any time before any undefined qualities are requested). The lines to add are:
if self.unit_type == REMOVE:
<indent>return;
Thanks to the same thread that I referenced earlier (Parsing Replay Files) for mentioning that this was an issue
Edit:
Another issue that I have found is that this sometimes crashes despite this fix. The error is (ignoring the giant line of functions leading up to the error):
File "/tmp/algo16180919916539904124/gamelib/game_state.py", line 136, in __create_parsed_units self.game_map[x,y][0].pending_removal = True
IndexError: list index out of range
To fix it, around the line
if unit_type == REMOVE:
<indent>self.game_map[x,y][0].pending_removal = True
Change it to:
if unit_type == REMOVE:
<indent>try:
<indent><indent>self.game_map[x,y][0].pending_removal = True
<indent>except:
<indent><indent>gamelib.debug_write("Error! Program tried to die while parsing REMOVE unit")
Side note: This is a very hacky fix, so if somebody knows how to fix it properly, feel free to say so. I don’t really know why this is happening.