def test_invalid_path(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] position = Square(1, 1) game.put(player, position) target_a = Square(12, 12) path = pf.get_safest_path(game, player, target_a) assert path is None
def test_neighbors(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] position = Square(5, 5) game.put(player, position) for neighbor in game.get_adjacent_squares(position): path = pf.get_safest_path(game, player, neighbor) assert len(path) == 1 and path.steps[0] == neighbor assert path.prob == 1.0
def test_path_to_endzone_away(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.away_team)[0] player.role.ma = 6 position = Square(23, 4) game.put(player, position) path = pf.get_safest_path_to_endzone(game, player) assert path is not None assert len(path) == 3
def test_out_of_bounds(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] position = Square(1, 1) game.put(player, position) for neighbor in game.get_adjacent_squares(position): if game.is_out_of_bounds(neighbor): path = pf.get_safest_path(game, player, neighbor) assert path is None
def test_all_paths(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.away_team)[0] player.role.ma = 6 position = Square(1, 1) game.put(player, position) paths = pf.get_all_paths(game, player) assert paths is not None moves_left = player.num_moves_left(include_gfi=True) assert len(paths) == ((moves_left + 1) * (moves_left + 1)) - 1
def test_all_blitz_paths_one(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.away_team)[0] player.role.ma = 6 game.put(player, Square(1, 1)) opp_player = game.get_reserves(game.state.home_team)[0] game.put(opp_player, Square(3, 3)) paths = pf.get_all_paths(game, player, blitz=True) assert paths is not None blitz_paths = [path for path in paths if path.block_dice is not None] assert len(blitz_paths) == 1
def test_gfi(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] position = Square(5, 5) game.put(player, position) for gfis in [0, 1, 2]: moves = player.get_ma() + gfis target = Square(position.x + moves, position.y) path = pf.get_safest_path(game, player, target) assert len(path.steps) == moves and path.get_last_step() == target assert path.prob == (5 / 6)**gfis
def test_that_unittest_mock_patch_works(): """ This test makes sure that unittest.mock.patch works as expected in other tests. """ with unittest.mock.patch('botbowl.core.procedure.Pathfinder', None): game = get_game_turn() game.config.pathfinding_enabled = True team = game.get_agent_team(game.actor) player = game.get_players_on_pitch(team=team)[0] with pytest.raises(TypeError): game.step(Action(ActionType.START_MOVE, player=player))
def test_straight_paths(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.away_team)[0] game.put(player, Square(7, 7)) paths = pf.get_all_paths(game, player) for path in paths: if path.get_last_step().x == 7: assert all(step.x == 7 for step in path.steps) if path.get_last_step().y == 7: assert all(step.y == 7 for step in path.steps)
def main(): policy = MockPolicy() game = get_game_turn() game.config.pathfinding_enabled = True game.set_available_actions() while not game.state.game_over: _, _, actions = policy(game) action = np.random.choice(actions, 1)[0] game.step(action) print(action)
def test_dodge_needed_path_long(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] position = Square(1, 8) game.put(player, position) opp = game.get_reserves(game.state.away_team)[0] opp_position = Square(3, 8) game.put(opp, opp_position) target_a = Square(9, 8) path = pf.get_safest_path(game, player, position=target_a) assert path is not None assert len(path.steps) == 8 assert path.prob == (4 / 6) * (5 / 6) * (5 / 6)
def test_avoid_path(pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] position = Square(1, 8) game.put(player, position) opp = game.get_reserves(game.state.away_team)[0] opp_position = Square(3, 8) game.put(opp, opp_position) target_a = Square(6, 8) path = pf.get_safest_path(game, player, target_a) assert path is not None assert len(path.steps) == 6 assert path.prob == 1.0
def test_blitz_action_type_is_block(pf): with unittest.mock.patch('botbowl.core.procedure.Pathfinder', pf.Pathfinder): game = get_game_turn() game.config.pathfinding_enabled = True team = game.get_agent_team(game.actor) player = game.get_players_on_pitch(team=team)[0] player.role.ma = 16 game.step(Action(ActionType.START_BLITZ, player=player)) assert np.sum([ len(action.positions) for action in game.get_available_actions() if action.action_type == ActionType.BLOCK ]) == 11
def test_handoff_action_type_is_handoff(pf): with unittest.mock.patch('botbowl.core.procedure.Pathfinder', pf.Pathfinder): game = get_game_turn() game.config.pathfinding_enabled = True team = game.get_agent_team(game.actor) player = game.get_players_on_pitch(team=team)[0] game.move(game.get_ball(), player.position) game.get_ball().is_carried = True player.role.ma = 16 game.step(Action(ActionType.START_HANDOFF, player=player)) assert np.sum([ len(action.positions) for action in game.get_available_actions() if action.action_type == ActionType.HANDOFF ]) == 10
def benchmark_cython_pathfinding(): game = get_game_turn(empty=False) players_on_pitch = game.get_players_on_pitch() def get_paths_of_all_players(pf): for player in players_on_pitch: pf.Pathfinder(game, player, trr=True).get_paths() scope = {'get_paths_of_all_players': get_paths_of_all_players, 'cython_pathfinding': cython_pathfinding, 'python_pathfinding': python_pathfinding} cython_time = timeit("get_paths_of_all_players(cython_pathfinding)",number=2, globals=scope) python_time = timeit("get_paths_of_all_players(python_pathfinding)",number=2, globals=scope) print(f"cython_time = {cython_time}") print(f"python_time = {python_time}") print(f"{python_time/cython_time:.2f} times better")
def test_get_safest_path(skills_and_rerolls, pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] position = Square(1, 1) game.put(player, position) skill, reroll = skills_and_rerolls if skill: player.extra_skills = [Skill.SURE_FEET] for y in range(game.arena.height): for x in range(game.arena.width): square = Square(x, y) if position != square and not game.is_out_of_bounds(square): if position.distance(square) != player.get_ma() + 2: continue # TODO: REMOVE path = pf.get_safest_path(game, player, square, allow_team_reroll=reroll) if position.distance(square) > player.get_ma() + 2: assert path is None else: p = 5 / 6 if position.distance(square) == player.get_ma() + 2: p_clean = p * p p_reroll_one = (p * (1 - p) * p) p_reroll_both = (1 - p) * p * (1 - p) * p if reroll and not skill or not reroll and skill: p = p_clean + p_reroll_one * 2 elif reroll and skill: p = p_clean + p_reroll_one * 2 + p_reroll_both else: p = p_clean assert path is not None assert path.prob == pytest.approx(p, PROP_PRECISION) elif position.distance(square) == player.get_ma() + 1: assert path is not None if reroll or skill: p = p + (1 - p) * p assert path.prob == pytest.approx(p, PROP_PRECISION) else: assert path is not None p = 1.0 assert path.prob == p
def test_compare_cython_python_paths(): """ This test compares paths calculated by cython and python. They should be same. It only compares destination, probability and number of steps, not each individual step. """ assert hasattr(cython_pathfinding, 'Pathfinder'), 'Cython pathfinding was not imported' game = get_game_turn(empty=True) player = game.get_reserves(game.state.away_team)[0] player.extra_skills.append(Skill.DODGE) player.extra_skills.append(Skill.SURE_FEET) player.role.ma = 7 position = Square(7, 7) game.put(player, position) for sq in [Square(8, 8), Square(5, 7), Square(8, 5)]: opp_player = game.get_reserves(game.state.home_team)[0] game.put(opp_player, sq) game.move(game.get_ball(), Square(9, 9)) game.get_ball().is_carried = False cython_paths = cython_pathfinding.Pathfinder(game, player, trr=True).get_paths() python_paths = python_pathfinding.Pathfinder(game, player, directly_to_adjacent=True, trr=True).get_paths() def create_path_str_to_compare(path): return f"({path.get_last_step() .x}, {path.get_last_step() .y}) p={path.prob:.5f} len={len(path.steps)}" def create_path_str_to_debug(path): """ Only used for debugging, see below """ return "->".join([f"({step.x}, {step.y})" for step in path.steps]) + f"rolls={path.rolls}" for python_path, cython_path in zip(python_paths, cython_paths): python_str = create_path_str_to_compare(python_path) cython_str = create_path_str_to_compare(cython_path) assert python_str == cython_str
def test_sure_feet_over_ag4_dodge(sure_feet, pf): game = get_game_turn(empty=True) player = game.get_reserves(game.state.home_team)[0] player.role.ma = 4 player.role.ag = 4 if sure_feet: player.extra_skills = [Skill.SURE_FEET] game.put(player, Square(4, 1)) opp1 = game.get_reserves(game.state.away_team)[0] game.put(opp1, Square(3, 3)) opp2 = game.get_reserves(game.state.away_team)[1] game.put(opp2, Square(5, 3)) target = Square(2, 4) path = pf.get_safest_path(game, player, target) assert path is not None if sure_feet: assert len(path.steps) == 5 p = (5 / 6) assert path.prob == p + (1 - p) * p else: assert len(path.steps) == 4 p = (5 / 6) assert path.prob == p