Esempio n. 1
0
    def __init__(self, game: botbowl.Game):
        self.actions = []
        self.priority_actions = []

        for action_choice in game.get_available_actions():
            if action_choice.action_type not in {
                    ActionType.START_MOVE, ActionType.MOVE,
                    ActionType.END_PLAYER_TURN
            }:
                continue

            if action_choice.action_type == ActionType.MOVE:
                prio_move_square = get_priority_move_square(
                    action_choice, game)

                if prio_move_square is not None:
                    self.priority_actions.append(
                        Action(action_choice.action_type,
                               position=prio_move_square))

            self.actions.extend(convert_to_actions(action_choice))

        if len(self.actions) == 0:
            self.actions.extend(
                collapse(
                    convert_to_actions(action_choice)
                    for action_choice in game.get_available_actions()))

        assert len(self.actions) > 0
        shuffle(self.actions)
Esempio n. 2
0
def scripted_action(game: botbowl.Game) -> Optional[Action]:
    available_action_types = {
        action_choice.action_type
        for action_choice in game.get_available_actions()
    }

    for at in use_directly_action_types:
        if at in available_action_types:
            return Action(at)

    if ActionType.PLACE_BALL in available_action_types:
        x = game.arena.width // 4
        if game.active_team is game.state.away_team:
            x *= 3
        y = game.arena.height // 2
        return Action(ActionType.PLACE_BALL, position=botbowl.Square(x, y))

    proc = game.get_procedure()
    if type(proc) is Setup:
        if game.is_setup_legal(game.active_team):
            return Action(ActionType.END_SETUP)
        for at in available_action_types:
            if at not in {ActionType.END_SETUP, ActionType.PLACE_PLAYER}:
                return Action(at)

    return None
Esempio n. 3
0
def get_filtered_available_actions(game: botbowl.Game):
    allowed_avail_actions = []
    disallowed = {
        ActionType.START_FOUL, ActionType.START_PASS, ActionType.START_HANDOFF
    }

    for action_choice in game.get_available_actions():
        if action_choice.action_type in disallowed:
            continue
        allowed_avail_actions.append(action_choice)
    return allowed_avail_actions
Esempio n. 4
0
    def __call__(
            self, game: botbowl.Game
    ) -> Tuple[float, np.ndarray, List[botbowl.Action]]:
        action = scripted_action(game)
        if action is not None:
            return 0.0, np.array([1.0]), [action]

        actions: MockPolicy.ActionProbList = []

        if self.end_setup:
            self.end_setup = False
            return 0.0, np.array([1.0]), [Action(ActionType.END_SETUP)]

        for action_choice in game.get_available_actions():
            action_type = action_choice.action_type

            if action_type in self.convert_function:
                actions.extend(self.convert_function[action_type](
                    game, action_choice))

            elif action_type in self.positional_types:
                if len(action_choice.positions) > 0:
                    positions = action_choice.positions
                else:
                    positions = [p.position for p in action_choice.players]

                for pos in positions:
                    actions.append((Action(action_type, position=pos), 1))

            elif action_choice.action_type in self.simple_types:
                actions.append((Action(action_type), 1))

            elif type(game.get_procedure()) is Setup and action_type not in {
                    ActionType.END_SETUP, ActionType.PLACE_PLAYER
            }:
                actions.append((Action(action_type), 1))
                self.end_setup = True

        if len(actions) == 0 and ActionType.END_PLAYER_TURN in [
                ac.action_type for ac in game.state.available_actions
        ]:
            actions.append((Action(ActionType.END_PLAYER_TURN), 1))

        action_objects, probabilities = zip(*actions)
        probabilities = np.array(probabilities, dtype=np.float)
        probabilities += 0.0001 * np.random.random(len(probabilities))
        probabilities /= sum(probabilities)

        return 0.0, probabilities, action_objects
Esempio n. 5
0
def expand_moving(game: botbowl.Game, parent: Node) -> Node:
    # noinspection PyTypeChecker
    active_proc: Union[procedures.GFI, procedures.Dodge] = game.get_procedure()
    assert type(active_proc) is procedures.Dodge or type(
        active_proc) is procedures.GFI

    move_action_proc: procedures.MoveAction = first(
        proc for proc in reversed(game.state.stack.items)
        if isinstance(proc, procedures.MoveAction))

    is_blitz = type(move_action_proc) is procedures.BlitzAction
    is_handoff = type(move_action_proc) is procedures.HandoffAction

    player = move_action_proc.player

    if move_action_proc.steps is not None:
        final_step = move_action_proc.steps[-1]
    else:
        if is_blitz:
            block_proc: procedures.Block = first(
                filter(lambda proc: type(proc) is procedures.Block,
                       game.state.stack.items))
            final_step = block_proc.defender.position
        elif is_handoff:
            raise ValueError()
        else:
            final_step = active_proc.position

    is_pickup = game.get_ball(
    ).position == final_step and not game.get_ball().is_carried
    path = move_action_proc.paths[final_step]
    """
    This block of code sets two important variables: 
        probability_success - probability of the remaining path  
        rolls - list[int] - the remaining rolls of the path 
    Normal case we just fetch this from the path object. If we're in a rerolled proc, it's nasty... 
    """
    if active_proc.roll is None:
        probability_success = path.prob
        rolls = list(collapse(path.rolls))
        if is_pickup:
            # remove the pickup roll and probability
            rolls.pop()
            probability_success /= game.get_pickup_prob(
                active_proc.player, final_step)

    else:
        with only_fixed_rolls(game):
            game.step()

        new_proc = game.get_procedure()
        if type(new_proc) not in {procedures.GFI, procedures.Dodge}:
            assert not active_proc.reroll.use_reroll
            return expand_none_action(game, parent)

        # if we get here, it means that a reroll was used.
        assert new_proc is active_proc
        assert active_proc.roll is None
        assert active_proc.reroll is None

        current_step = active_proc.position
        try:
            assert player.position.distance(
                current_step) == 1 or is_pickup or is_blitz
        except AssertionError as e:
            raise e

        i = 0
        while path.steps[i] != current_step:
            i += 1
        remaining_current_step_rolls = path.rolls[i][:]

        if is_pickup and current_step == final_step:
            remaining_current_step_rolls.pop()

        num_current_step_remaining_rolls = len(
            list(
                filter(lambda x: type(x) in {procedures.GFI, procedures.Dodge},
                       game.state.stack.items)))
        assert num_current_step_remaining_rolls in [1, 2]
        remaining_current_step_rolls = remaining_current_step_rolls[
            -num_current_step_remaining_rolls:]

        probability_success = reduce(
            operator.mul,
            map(lambda d: (7 - d) / 6, remaining_current_step_rolls), 1.0)
        rolls = list(collapse(remaining_current_step_rolls))

        if current_step != final_step:
            step_count = game.get_step()
            if player.position != current_step:
                try:
                    game.move(player, current_step)
                except AssertionError as e:
                    raise e
            new_path = pf.get_safest_path(game,
                                          player,
                                          final_step,
                                          blitz=is_blitz)
            game.revert(step_count)

            #try:
            #    # assert new_path.steps == path.steps[-len(new_path):]  this assert can't be made because of small randomness in pathfinder
            #    assert list(collapse(new_path.rolls)) == list(collapse(path.rolls[-len(new_path):])), f"{new_path.rolls} != {path.rolls[-len(new_path):]}"
            #except AssertionError as e:
            #    raise e
            try:
                rolls.extend(collapse(new_path.rolls))
            except AttributeError as e:
                raise e
            probability_success *= new_path.prob

            if is_pickup:
                # remove the pickup roll and probability
                rolls.pop()
                probability_success /= game.get_pickup_prob(
                    active_proc.player, final_step)

    try:
        p = np.array(rolls) / sum(rolls)
        index_of_failure = np.random.choice(range(len(rolls)), 1, p=p)[0]
    except ValueError as e:
        raise e

    # STEP UNTIL FAILURE (possibly no steps at all)
    with only_fixed_rolls(game, d6=[6] * index_of_failure):
        while len(botbowl.D6.FixedRolls) > 0:
            if len(game.get_available_actions()) > 0:
                raise AttributeError("wrong")
            game.step()

    new_parent = ChanceNode(game, parent)
    debug_step_count = game.get_step()

    # SUCCESS SCENARIO
    with only_fixed_rolls(game, d6=[6] * (len(rolls) - index_of_failure)):
        while len(botbowl.D6.FixedRolls) > 0:
            if type(game.get_procedure()) not in {
                    procedures.GFI, procedures.Block, procedures.Dodge,
                    procedures.Move, procedures.MoveAction,
                    procedures.BlitzAction
            }:
                raise AttributeError("wrong")
            if len(game.get_available_actions()) > 0:
                raise AttributeError("wrong")
            if type(game.get_procedure()
                    ) is procedures.Block and not game.get_procedure().gfi:
                raise AttributeError("wrong")
            game.step()
    success_node = expand_none_action(game, new_parent, moving_handled=True)
    new_parent.connect_child(success_node, probability_success)

    assert debug_step_count == game.get_step()

    # FAILURE SCENARIO
    with only_fixed_rolls(game, d6=[1]):
        while len(botbowl.D6.FixedRolls) > 0:
            if len(game.get_available_actions()) > 0:
                raise AttributeError("wrong")
            game.step()
    fail_node = expand_none_action(game, new_parent, moving_handled=True)
    new_parent.connect_child(fail_node, 1 - probability_success)

    assert debug_step_count == game.get_step()

    return new_parent