Get_path_to_edge but ignore the starting location

so the function get_path_to_edge returns None if the location was blocked, How could I say to ignore that one location? such that even if only that location was blocked, it would still output a path (even if that location was blocked)

I use find_path_to_edge. That will return the path it will take to edge or to the point where it will explode. I think this was documented somewhere, but I just looked into the game_state.py file to find it.

Oh right, it was called find_path_to_edge but this does not solve the problem, I still want to know how to ignore the starting location

O you ment blocking the spawn location… just program an algo to find a new starting location that isn’t blocked? e.g. look a coordinate one up or one inward? Or make a copy of the game_state and forcefully remove the firewall with a function available in the game_map class and then run find_path_to_edge on the copied game_state. I haven’t encountered this specific problem so I have no code lying around to share. There should be some options though…

No, I am trying to find the path that a hypothetical unit would take, at a blocked location, but assume that spawn location is not blocked.

I understand what you ment. So you can either predict yourself what the next coordinate might be (one up or one inward) and use that as the starting point in the function call, or create a copy of the game_state and modify it so the spawn is no longer blocked by forcefully removing the firewall in the copy.

I do not want to use a different location, so I supposed I will have to copy the game_state, remove the blocked location, and find that path, then use that location. Is it as easy as it sounds?
copy = game_state
copy.remove_location(blocked_location)
path = find_path_to_edge(blocked_location, TOP_RIGHT)
the_location_I_want = path[-1]

I think something like that should work but I haven’t tried and I can’t right now. Though I am pretty sure remove location is from game_map, so that would be

copy.game_map.remove_location(blocked_location)

If you find the time to test it out, let me know if it works :slight_smile:

I’m not good at python but
copy = game_state
should be a reference to game_state instead of a copy.
You need to instantiate a new GameState object the same way you created the game_state in the first place.
copy = GameState(config)
or something like that (I don’t have the code on my screen right now)
And if you want to modify it to a hypothetical state you could (like @kkroep said) use remove_unit in the game_map inside the copy because the remove function in game_state will create a “remove” unit instead of
removing the unit right away.

No I think that would not work for the reason issued by @thephoenix107, you should use a deep copy (or another way of copying the game_state and the content of the game_map inside it)
copy = copy.deepcopy(game_state)

Though, you should also be able to do the same without a copy if you

  1. Remove the unit(s) with game_map.remove_unit
  2. Then do the pathfinding
  3. Replace the unit(s) with game_map.add_unit

This way you only need to copy the list of units in that one spot rather than the whole map

2 Likes

Would that really work? Why does that work?

Admittedly I haven’t tried it, but the game_map is just a store of data describing a game board, and game_state.find_path_to_edge operates on this board. So any changes you make to the board will alter the path that navigation algorithm outputs.

Also, you can directly access all of the units in a tile with game_map[x,y], which would be less hassle when replacing all the units afterwards.

I just tested this:

        if game_state.contains_stationary_unit(state[0]) == False:
                path = (game_state.find_path_to_edge(state[0], game_state.game_map.BOTTOM_LEFT))
            else:
                unit = game_state.contains_stationary_unit(state[0])
                game_state.game_map.remove_unit(state[0])
                path = (game_state.find_path_to_edge(state[0], game_state.game_map.BOTTOM_LEFT))
                game_state.game_map.add_unit(unit, state[0], 1)
            state = path[-1]

This does not seem to work, Am I doing something wrong? There error is:

  File "/tmp/algo742875861392608389/gamelib/game_map.py", line 172, in add_unit
    new_unit = GameUnit(unit_type, self.config, player_index, None, location[0], location[1])
  File "/tmp/algo742875861392608389/gamelib/unit.py", line 34, in __init__
    self.__serialize_type()
  File "/tmp/algo742875861392608389/gamelib/unit.py", line 40, in __serialize_type
    type_config = self.config["unitInformation"][UNIT_TYPE_TO_INDEX[self.unit_type]]
KeyError: Enemy DF, stability: 75.0 location: [27, 14]

game_state.contains_stationary_unit(location) returns either False or a GameUnit.
So your “unit” is of type “GameUnit”
def add_unit(self, unit_type, location, player_index=0) needs the unit type but you are giving it the whole GameUnit object instead.
Try game_state.game_map.add_unit(unit.unit_type, state[0], 1)

1 Like

Something that I used, rather than find_path_to_edge (I don’t really know why), was something like:

end_point = gamelib.navigation.ShortestPathFinder()
path = end_point.navigate_multiple_endpoints(start_loc, game_state.game_map.get_edge_locations(game_state.game_map.TOP_LEFT) + game_state.game_map.get_edge_locations(game_state.game_map.TOP_RIGHT), game_state)

I don’t really know why this works for me if you had issues with yours, because this worked well for me, even in situations where the path to the edge was blocked (which I saw a lot with my particular algo). find_path_to_edge, looking at the code, seems to do exactly the same thing considering that it uses the function that I used directly. It might have something to do with how I had it check for both edges rather than just one