def test_foul(pf): game, (player, opp_player_1, opp_player_2) = get_custom_game_turn(player_positions=[(1, 1)], opp_player_positions=[(1, 2), (1, 3)]) player.role.ma = 1 opp_player_1.state.up = False opp_player_2.state.up = False pathfinder = pf.Pathfinder(game, player, directly_to_adjacent=True, can_foul=True, trr=False) paths = pathfinder.get_paths() total_fouls = 0 for path in paths: fouls = 0 for step in path.steps: if step in [opp_player_1.position, opp_player_2.position]: fouls += 1 assert step == path.get_last_step() assert fouls <= 1 total_fouls += fouls assert total_fouls == 2
def test_scoring_paths(pf, as_home): home_positions = [(2, 1), (2, 2), (3, 1), (3, 2)] away_positions = [(25, 1), (25, 2), (24, 1), (24, 2)] ball_pos = home_positions[0] if as_home else away_positions[0] end_zone_x = 1 if as_home else 26 game, _ = get_custom_game_turn(player_positions=home_positions, opp_player_positions=away_positions, ball_position=ball_pos) ball_carrier = game.get_ball_carrier() paths = pf.get_all_paths(game, ball_carrier) assert len(paths) == 2 for path in paths: # we make sure that there are no steps after passing home_td zone found_td = False for step in path.steps: assert not found_td if step.x == end_zone_x: found_td = True
def test_mcts(): game, _ = get_custom_game_turn(player_positions=[(6, 6), (7, 7)], opp_player_positions=[(5, 6)], ball_position=(6, 6), pathfinding_enabled=True) weights = HeuristicVector(score=1, ball_marked=0.1, ball_carried=0.2, ball_position=0.01, tv_on_pitch=1) tree = SearchTree(game) policy = MockPolicy() for i in range(20): do_mcts_branch(tree, policy, weights, exploration_coeff=5) print("") mcts_info = tree.root_node.info for action, visits, action_val in zip(mcts_info.actions, mcts_info.visits, mcts_info.action_values): action.player = None action_value = np.dot(action_val, weights) print(f"{action}, {visits=}, {action_value=:.2f}") print("") print(f"{len(tree.all_action_nodes)=}")
def test_dodge_pickup_score(): game, players = get_custom_game_turn(player_positions=[(5, 5), (6, 6)], opp_player_positions=[(4, 4), (4, 2)], ball_position=(3, 3), forward_model_enabled=True, pathfinding_enabled=True) weights = HeuristicVector(score=1, ball_marked=0, ball_carried=0, ball_position=0.001, tv_on_pitch=0) tree = SearchTree(game) policy = MockPolicy() def search_select_step(): for i in range(100): do_mcts_branch(tree, policy, weights, exploration_coeff=0.5) info: MCTS_Info = tree.root_node.info print(" ") print_node(tree.root_node, weights) return info.actions[np.argmax(info.visits)] a = search_select_step() game.step(a) tree.set_new_root(game) a = search_select_step() game.step(a) tree.set_new_root(game) a = search_select_step() game.step(a)
def test_expand_move(data): move_target, outcome_probs = data assert sum(outcome_probs) == 1.0 game, (player, _, _) = get_custom_game_turn(player_positions=[(1, 1)], opp_player_positions=[(1, 3), (3, 1)], forward_model_enabled=True, pathfinding_enabled=True) game.step(Action(ActionType.START_MOVE, position=player.position)) action = Action(ActionType.MOVE, position=move_target) parent_action_node: ActionNode = ActionNode(game, parent=None) next_node: Node = expand_action(game, action, parent_action_node) assert next_node.parent is parent_action_node if len(outcome_probs) == 1: assert type(next_node) is ActionNode else: next_node: ChanceNode assert type(next_node) is ChanceNode assert sum(next_node.child_probability) == 1.0 assert all(y == approx(x, abs=1e-12) for x, y in zip( sorted(next_node.child_probability), sorted(outcome_probs)))
def test_expand_block(): game, (attacker, _, defender) = get_custom_game_turn(player_positions=[(5, 5), (7, 7)], opp_player_positions=[(6, 6)], forward_model_enabled=True) defender.extra_skills.append(Skill.DODGE) tree = SearchTree(game) next_node, = tree.expand_action_node( tree.root_node, Action(ActionType.START_BLOCK, player=attacker)) assert len(tree.all_action_nodes) == 2 next_node, *_ = tree.expand_action_node( next_node, Action(ActionType.BLOCK, position=defender.position)) assert len(tree.all_action_nodes) == 6 next_node, = tree.expand_action_node( next_node, Action(ActionType.SELECT_DEFENDER_DOWN)) assert len(tree.all_action_nodes) == 7 next_node, = tree.expand_action_node( next_node, Action(ActionType.PUSH, position=Square(7, 6))) assert len(tree.all_action_nodes) == 8 next_node, *_ = tree.expand_action_node( next_node, Action(ActionType.FOLLOW_UP, position=Square(6, 6))) assert len(tree.all_action_nodes) == 11
def test_forced_pickup_path(pf): game, (player1, player2, player3) = get_custom_game_turn(player_positions=[(1, 1), (1, 2), (2, 2)], ball_position=(2, 1), pathfinding_enabled=True) paths = pf.get_all_paths(game, player1) assert len(paths) == 1 assert paths[0].get_last_step() == game.get_ball_position()
def test_set_new_root(): game, (player1, player2, opp_player) = get_custom_game_turn(player_positions=[(5, 5), (6, 6)], opp_player_positions=[(4, 4)], ball_position=(5, 5), pathfinding_enabled=True, forward_model_enabled=True) action_p2_1 = Action(ActionType.START_BLITZ, position=player2.position) action_p2_2 = Action(ActionType.BLOCK, position=Square(4, 4)) action_p1_1 = Action(ActionType.START_MOVE, position=player1.position) action_p1_2 = Action(ActionType.MOVE, position=Square(1, 5)) tree = SearchTree(deepcopy(game)) assert tree.root_node.depth == 0 # Move player 2 new_node, = tree.expand_action_node(tree.root_node, action_p2_1) new_nodes = tree.expand_action_node(new_node, action_p2_2) assert new_node.depth == 1 assert new_nodes[0].depth == 2 assert len(tree.all_action_nodes) == 2 + 4 # Move player 1 new_node, = tree.expand_action_node(tree.root_node, action_p1_1) assert len(tree.all_action_nodes) == 2 + 4 + 1 new_nodes = tree.expand_action_node(new_node, action_p1_2) assert new_node.depth == 1 assert new_nodes[0].depth == 2 assert len(tree.all_action_nodes) == 2 + 4 + 1 + 7 game.step(action_p1_1) tree.set_new_root(game) assert len(tree.all_action_nodes) == 8 assert new_node is tree.root_node assert new_node.depth == 0 assert new_nodes[0].depth == 1 with only_fixed_rolls(game, d6=[6]): game.step(action_p1_2) tree.set_new_root(game) tree.expand_action_node(tree.root_node, Action(ActionType.SETUP_FORMATION_SPREAD)) assert new_nodes[0] is tree.root_node assert len(tree.all_action_nodes) == 2 game.step(Action(ActionType.SETUP_FORMATION_SPREAD)) game.step(Action(ActionType.END_SETUP)) tree.set_new_root(game) assert len(tree.all_action_nodes) == 1 assert len(tree.root_node.children) == 0
def test_forced_pickup_path(pf): game, (player, ) = get_custom_game_turn(player_positions=[(1, 1)], ball_position=(3, 3), pathfinding_enabled=True) ball = game.get_ball() ball.on_ground = False paths = pf.get_all_paths(game, player) path: python_pathfinding.Path = first( filter(lambda p: p.get_last_step() == ball.position, paths)) assert path.prob == 1
def test_foul_after_gfi(pf): game, (player, opp_player) = get_custom_game_turn(player_positions=[(1, 1)], opp_player_positions=[(2, 2)]) player.role.ma = 6 player.state.moves = 8 opp_player.state.up = False pathfinder = pf.Pathfinder(game, player, can_foul=True) paths = pathfinder.get_paths() assert len(paths) == 1 assert len(paths[0].steps) == 1 assert paths[0].steps[0] == opp_player.position
def test_handoff_after_gfi(pf): game, (player, other_player) = get_custom_game_turn(player_positions=[ (2, 2), (3, 3) ], ball_position=(2, 2)) player.role.ma = 6 player.state.moves = 8 pathfinder = pf.Pathfinder(game, player, can_handoff=True) paths = pathfinder.get_paths() assert len(paths) == 1 assert len(paths[0].steps) == 1 assert paths[0].steps[0] == other_player.position
def test_pickup_score(): game, (player, ) = get_custom_game_turn(player_positions=[(5, 5)], ball_position=(3, 3), forward_model_enabled=True, pathfinding_enabled=True) player.role.ma = 4 game.set_available_actions() weights = HeuristicVector(score=1, ball_marked=0, ball_carried=0, ball_position=0, tv_on_pitch=0) tree = SearchTree(game) policy = MockPolicy() def search_select_step(): for i in range(40): do_mcts_branch(tree, policy, weights, exploration_coeff=0.5) info: MCTS_Info = tree.root_node.info print(" ") print_node(tree.root_node, weights) return info.actions[np.argmax(info.visits)] a = search_select_step() assert a.action_type == ActionType.START_MOVE and a.position == player.position with only_fixed_rolls(game): game.step(a) tree.set_new_root(game) setup_node: ActionNode = first( filter(lambda n: n.simple_hash.find('Setup') > 0, tree.all_action_nodes)) assert setup_node.get_accum_prob() == approx(2 / 3) a = search_select_step() assert a.action_type == ActionType.MOVE and a.position == Square(3, 3) with only_fixed_rolls(game, d6=[3]): game.step(a) tree.set_new_root(game) a = search_select_step() assert a.action_type == ActionType.MOVE and a.position.x == 1 with only_fixed_rolls(game): game.step(a) tree.set_new_root(game)
def test_blitz_one_move_left(pf_enabled): game, (player, opp_player) = get_custom_game_turn(player_positions=[(5, 5)], opp_player_positions=[(6, 6)], pathfinding_enabled=pf_enabled) player.role.ma = 1 game.step(Action(ActionType.START_BLITZ, player=player)) assert player.num_moves_left() == 1 game.step(Action(ActionType.BLOCK, position=opp_player.position)) assert not game.has_report_of_type(botbowl.OutcomeType.FAILED_GFI) assert not game.has_report_of_type(botbowl.OutcomeType.SUCCESSFUL_GFI)
def test_expand_throw_in(): game, (attacker, defender) = get_custom_game_turn(player_positions=[(5, 2)], opp_player_positions=[(5, 1)], ball_position=(5, 1), forward_model_enabled=True, pathfinding_enabled=True) with only_fixed_rolls(game, block_dice=[BBDieResult.DEFENDER_DOWN]): game.step(Action(ActionType.START_BLOCK, position=attacker.position)) game.step(Action(ActionType.BLOCK, position=defender.position)) game.step(Action(ActionType.SELECT_DEFENDER_DOWN)) action = Action(ActionType.PUSH, position=Square(5, 0)) tree = SearchTree(game) tree.expand_action_node(tree.root_node, action) assert len(tree.all_action_nodes) == 2
def test_handoff(pf): game, (player, teammate_1, teammate_2) = get_custom_game_turn(player_positions=[(2, 2), (2, 3), (2, 4)], ball_position=(2, 2)) player.role.ma = 1 pathfinder = pf.Pathfinder(game, player, directly_to_adjacent=True, can_handoff=True, trr=False) paths = pathfinder.get_paths() total_handoffs = 0 for path in paths: handoffs = 0 for step in path.steps: if step in [teammate_1.position, teammate_2.position]: handoffs += 1 assert step == path.get_last_step() assert handoffs <= 1 total_handoffs += handoffs assert total_handoffs == 2
def main(): game = get_custom_game_turn(player_positions=[(6, 6), (7, 7)], opp_player_positions=[(5, 6)], ball_position=(6, 6), pathfinding_enabled=True)