Esempio n. 1
0
    def __init__(self, stage_data, player_data):
        logger.info("StageController is Created")

        # Stage Data
        self.start_stage_time = datetime.datetime.now()
        self.stage_data = stage_data
        self.player_data = player_data
        self.game_state = GameState(self.player_data)
        self.user_sprite = UserSprite(self.stage_data, self.player_data,
                                      self.game_state.user_state.user_id)
        self.finish_wave = True

        # controllers
        self.sprite_controller = SpriteController(self.stage_data.background,
                                                  self.user_sprite)
        self.player_controller = PlayerController(self.user_sprite,
                                                  self.game_state)
        self.collision_controller = CollisionController(self.sprite_controller)

        # views
        self.user_info_view = UserInfoView(USER_INFO_SIZE, self.player_data)
        self.stage_headline = StageHeadline(self.stage_data.stage_name)

        # events
        dispatcher.connect(self.handle_collision_event,
                           signal=SignalMapper.COLLISION_UPDATE,
                           sender=dispatcher.Any)
        dispatcher.connect(self.handle_combo_event,
                           signal=SignalMapper.COMBO_ATTACK,
                           sender=dispatcher.Any)
Esempio n. 2
0
class Game:
    """
    Interface for game state
    """
    def __init__(self):
        self.currentPlayer = 1
        self.gameState = GameState(empty_board(), 1, (6, 4))
        self.grid_shape = (48, 8)
        self.input_shape = (2, 48, 8)
        self.name = 'paper_soccer'

    def reset(self):
        self.gameState = GameState(empty_board(), 1, (6, 4))
        self.currentPlayer = 1
        return self.gameState

    def get_all_allowed_moves(self, type='deep', params=None):
        if type == 'deep':
            return self.gameState.get_full_moves_deep()
        if type == 'simple':
            return self.gameState.get_full_moves_simple()
        if type == 'random':
            return self.gameState.get_random_move()

    def make_move(self, move):
        return self.gameState.make_move(move)

    def change_player(self):
        self.currentPlayer = -self.currentPlayer
        self.gameState.playerTurn = -self.gameState.playerTurn
        self.gameState.board = turn_board(self.gameState.board)
        self.gameState.current_position = (12 -
                                           self.gameState.current_position[0],
                                           8 -
                                           self.gameState.current_position[1])
 def can_execute_on(self, game_state: GameState) -> bool:
     if game_state.next_player != self.player_id:
         return False
     if self._card not in game_state.cards_in_hand[self.player_id]:
         return False
     if not game_state.is_to_lead(self.player_id):
         if game_state.must_follow_suit():
             if not self._is_following_suit(game_state):
                 return False
     return True
Esempio n. 4
0
    def __init__(self):
        self.__current_state = GameState()
        self.__past_moves = []
        self.__all_possible_moves = {}

        self.__moves_getter = MovesGetter()
        self.__state_verifier = StateVerifier()

        self.__predict_filter = PredictiveFilter()

        self.__current_move_color = PieceColor.WHITE
Esempio n. 5
0
def get_game_state_for_forcing_the_issue_puzzle() -> GameState:
  """
  Generates a game view for the scenario described here:
  http://psellos.com/schnapsen/blog/2012/05/013-forcing.html

  The game state is the following:
    * cards_in_hand: [X♠, Q♥, X♣, A♦, K♦] [X♥, K♥, X♦, Q♦, J♦]
    * trump: ♥
    * trump_card: J♥
    * talon: [A♣], closed
    * next_player: PlayerId.ONE
    * won_tricks: [(K♠, Q♠), (A♥, A♠)], [(J♠, K♣), (J♣, Q♣)]
    * marriage_suits: [], [♣]
    * trick_points: (29, 31)
    * current_trick: (None, J♦)
    * player_that_closed_the_talon: PlayerId.TWO
    * opponent_points_when_talon_was_closed: 29
  """
  cards_in_hand = PlayerPair(
    one=[Card(Suit.SPADES, CardValue.TEN),
         Card(Suit.HEARTS, CardValue.QUEEN),
         Card(Suit.CLUBS, CardValue.TEN),
         Card(Suit.DIAMONDS, CardValue.ACE),
         Card(Suit.DIAMONDS, CardValue.KING)],
    two=[Card(Suit.HEARTS, CardValue.TEN),
         Card(Suit.HEARTS, CardValue.KING),
         Card(Suit.DIAMONDS, CardValue.TEN),
         Card(Suit.DIAMONDS, CardValue.QUEEN),
         Card(Suit.DIAMONDS, CardValue.JACK)])
  trump_card = Card(Suit.HEARTS, CardValue.JACK)
  talon = [Card(Suit.CLUBS, CardValue.ACE)]
  won_tricks = PlayerPair(
    one=[PlayerPair(Card(Suit.SPADES, CardValue.KING),
                    Card(Suit.SPADES, CardValue.QUEEN)),
         PlayerPair(Card(Suit.HEARTS, CardValue.ACE),
                    Card(Suit.SPADES, CardValue.ACE))],
    two=[PlayerPair(Card(Suit.SPADES, CardValue.JACK),
                    Card(Suit.CLUBS, CardValue.KING)),
         PlayerPair(Card(Suit.CLUBS, CardValue.JACK),
                    Card(Suit.CLUBS, CardValue.QUEEN))])
  marriage_suits = PlayerPair(one=[], two=[Suit.CLUBS])
  trick_points = PlayerPair(one=29, two=31)
  game_state = GameState(cards_in_hand=cards_in_hand, trump=trump_card.suit,
                         trump_card=trump_card, talon=talon,
                         won_tricks=won_tricks, trick_points=trick_points,
                         marriage_suits=marriage_suits,
                         next_player=PlayerId.TWO)
  game_state.close_talon()
  game_state.current_trick.two = Card(Suit.DIAMONDS, CardValue.JACK)
  game_state.next_player = PlayerId.ONE
  return game_state
Esempio n. 6
0
def get_game_state_for_know_your_opponent_puzzle() -> GameState:
  """
  Generates a game state for the scenario described here:
  http://psellos.com/schnapsen/blog/2020/09/147-know.html

  The game state is the following:
    * cards_in_hand: [K♠, J♠, K♥, A♣, K♣] [A♠, Q♠, A♥, X♣, Q♣]
    * trump: ♥
    * trump_card: Q♥
    * talon: [J♣], closed
    * next_player: PlayerId.ONE
    * won_tricks: [(X♥, X♦), (J♥, J♦)], [(Q♦, X♠), (K♦, A♦)]
    * marriage_suits: [], []
    * trick_points: (24, 28)
    * current_trick: (None, A♥)
    * player_that_closed_the_talon: PlayerId.TWO
    * opponent_points_when_talon_was_closed: 24
  """
  cards_in_hand = PlayerPair(
    one=[Card(Suit.SPADES, CardValue.KING),
         Card(Suit.SPADES, CardValue.JACK),
         Card(Suit.HEARTS, CardValue.KING),
         Card(Suit.CLUBS, CardValue.ACE),
         Card(Suit.CLUBS, CardValue.KING)],
    two=[Card(Suit.SPADES, CardValue.ACE),
         Card(Suit.SPADES, CardValue.QUEEN),
         Card(Suit.HEARTS, CardValue.ACE),
         Card(Suit.CLUBS, CardValue.TEN),
         Card(Suit.CLUBS, CardValue.QUEEN)])
  trump_card = Card(Suit.HEARTS, CardValue.QUEEN)
  talon = [Card(Suit.CLUBS, CardValue.JACK)]
  won_tricks = PlayerPair(
    one=[PlayerPair(Card(Suit.HEARTS, CardValue.TEN),
                    Card(Suit.DIAMONDS, CardValue.TEN)),
         PlayerPair(Card(Suit.HEARTS, CardValue.JACK),
                    Card(Suit.DIAMONDS, CardValue.JACK))],
    two=[PlayerPair(Card(Suit.DIAMONDS, CardValue.QUEEN),
                    Card(Suit.SPADES, CardValue.TEN)),
         PlayerPair(Card(Suit.DIAMONDS, CardValue.KING),
                    Card(Suit.DIAMONDS, CardValue.ACE))])
  trick_points = PlayerPair(one=24, two=28)
  game_state = GameState(cards_in_hand=cards_in_hand, trump=trump_card.suit,
                         trump_card=trump_card, talon=talon,
                         won_tricks=won_tricks, trick_points=trick_points,
                         next_player=PlayerId.TWO)
  game_state.close_talon()
  game_state.current_trick.two = Card(Suit.HEARTS, CardValue.ACE)
  game_state.next_player = PlayerId.ONE
  return game_state
def mcts_ci_widths_across_multiple_game_states(use_player: bool,
                                               options: MctsPlayerOptions,
                                               num_samples: int,
                                               num_game_states: int):
    data = []
    overlap_count = 0
    for seed in range(num_game_states):
        print(f"Evaluating on GameState.new(random_seed={seed})")
        for _ in range(num_samples):
            if use_player:
                dataframe = run_mcts_player_step_by_step(
                    GameState.new(random_seed=seed).next_player_view(),
                    options, options.max_iterations)
            else:
                dataframe = run_mcts_and_collect_data(
                    GameState.new(random_seed=seed), options,
                    options.max_iterations)
            dataframe[
                "ci_width"] = dataframe["score_upp"] - dataframe["score_low"]
            dataframe = dataframe[dataframe.iteration.eq(
                dataframe.iteration.max())].sort_values("score",
                                                        ascending=False)
            if _is_ci_overlap(dataframe.iloc[0].score_low,
                              dataframe.iloc[0].score_upp,
                              dataframe.iloc[1].score_low,
                              dataframe.iloc[1].score_upp):
                overlap_count += 1
            ci_widths = list(dataframe["ci_width"].values)
            while len(ci_widths) < 7:
                ci_widths.append(np.nan)
            data.append(tuple(ci_widths))
    overlap_pct = np.round(overlap_count / num_samples / num_game_states * 100,
                           2)
    print(f"Overlap in the CIs for the best two actions in {overlap_count} "
          f"cases out of {num_samples * num_game_states} ({overlap_pct}%)")
    dataframe = DataFrame(data,
                          columns=["BestAction"] +
                          [f"Action #{i}" for i in range(2, 8)])
    suffix = "_player" if use_player else ""
    csv_path = f"mcts_ci_widths_across_game_states{suffix}.csv"
    # noinspection PyTypeChecker
    dataframe.to_csv(csv_path, index=False)
    # dataframe = pandas.read_csv(csv_path)
    dataframe.boxplot()
    plt.xticks(rotation=45, ha='right')
    plt.gcf().set_size_inches((5, 5))
    plt.tight_layout()
    plt.savefig(f"mcts_ci_widths_across_game_states{suffix}.png")
Esempio n. 8
0
def debug_game(filename: str, game_index: int, options: MctsPlayerOptions):
  with open(filename, "rb") as binary_file:
    bummerl = pickle.load(binary_file)
  game = bummerl.completed_games[game_index]
  game_points = _get_bummerl_score(bummerl, game_index)
  game_state = GameState.new(dealer=game.dealer, random_seed=game.seed)
  num_actions = len(
    [action for action in game.actions if action.player_id == PlayerId.ONE])
  action_counter = 0
  fig, ax = plt.subplots(nrows=num_actions, ncols=2, squeeze=False)
  for action in game.actions:
    if action.player_id == PlayerId.ONE:
      # cheater = False
      dataframe = run_mcts_player_step_by_step(game_state.next_player_view(),
                                               options,
                                               iterations_step=100,
                                               game_points=game_points)
      _plot_data(dataframe, "score", ax[action_counter, 0], _hlines_for_scores)
      # cheater = True
      dataframe = run_mcts_player_step_by_step(game_state, options,
                                               iterations_step=100,
                                               game_points=game_points)
      _plot_data(dataframe, "score", ax[action_counter, 1], _hlines_for_scores)
      action_counter += 1
    game_state = action.execute(game_state)
  fig.set_size_inches(20, 5 * num_actions)
  fig.suptitle(f"Debug game: dealer={game.dealer}, seed={game.seed}")
  plt.tight_layout()
  plt.savefig("debug_game.png")
def get_available_actions(game_state: GameState) -> List[PlayerAction]:
    """
  Returns a list of all the valid actions that can be performed in a given game
  state.
  """
    actions: List[PlayerAction] = []
    player_id = game_state.next_player
    is_to_lead = game_state.is_to_lead(player_id)
    for card in game_state.cards_in_hand[player_id]:
        # TODO(options): Allow Queen/King to be played without announcing marriage?
        if card.card_value in [CardValue.QUEEN, CardValue.KING] and is_to_lead:
            marriage = AnnounceMarriageAction(player_id, card)
            if marriage.can_execute_on(game_state):
                actions.append(marriage)
                continue
        play_card = PlayCardAction(player_id, card)
        if play_card.can_execute_on(game_state):
            actions.append(play_card)
    if is_to_lead:
        exchange_trump = ExchangeTrumpCardAction(player_id)
        if exchange_trump.can_execute_on(game_state):
            actions.append(exchange_trump)
        close_talon = CloseTheTalonAction(player_id)
        if close_talon.can_execute_on(game_state):
            actions.append(close_talon)
    return actions
Esempio n. 10
0
    def _on_lead_action(self, game_view: GameState) -> PlayerAction:
        # Store the available actions.
        available_actions = get_available_actions(game_view)
        self._actions = {}
        for action in available_actions:
            # Always exchange the trump card if possible.
            if isinstance(action, ExchangeTrumpCardAction):
                return action
            if isinstance(action, (AnnounceMarriageAction, PlayCardAction)):
                self._actions[action.card] = action
        assert len(self._actions) == len(self._my_cards)

        # Check if we have a preferred marriage in hand, but don't play it yet
        # because we might have higher cards that cannot be beaten by the opponent
        # (e.g., Trump Ace) and can secure the necessary points such that showing
        # the marriage will end the game.
        self._marriage_suit = None
        marriage_action = get_best_marriage(available_actions, game_view.trump)
        if marriage_action is not None:
            logging.debug("HeuristicPlayer: Storing marriage suit: %s",
                          marriage_action.card.suit)
            self._marriage_suit = marriage_action.card.suit

        # Maybe close the talon.
        close_talon_action = self._should_close_talon(game_view)
        if close_talon_action is not None:
            return close_talon_action

        # Get the preferred action to be played depending on the game state.
        if game_view.must_follow_suit():
            return self._on_lead_follow_suit(game_view)
        return self._on_lead_do_not_follow_suit(game_view)
 def new_init(self):
     self.game_finished_timestamp = None
     game_state = GameState.get_default_with_field(3, 3)
     self.game = TicTacToeGame(game_state,
                               TicTacToeDefaultWinnerCheckStrategy(),
                               self.game_changed_callback)
     self.user_cursor_controller.cursor_position = Coordinate(1, 1)
Esempio n. 12
0
    def test_max_iterations(self):
        class TestMcts(Mcts):
            def __init__(self, *args, **kwargs):
                super().__init__(*args, **kwargs)
                self.counter = 0

            def run_one_iteration(self,
                                  root_node: Node,
                                  select_best_child: bool = False) -> bool:
                self.counter += 1
                return False

        game_state = GameState.new(random_seed=0)

        # Run ten iterations.
        mcts = TestMcts(game_state.next_player)
        self.assertEqual(0, mcts.counter)
        mcts.build_tree(game_state, 10)
        self.assertEqual(10, mcts.counter)

        # Run one hundred iterations.
        mcts = TestMcts(game_state.next_player)
        self.assertEqual(0, mcts.counter)
        mcts.build_tree(game_state, 100)
        self.assertEqual(100, mcts.counter)

        # Negative or zero max_iterations are not allowed.
        with self.assertRaisesRegex(AssertionError,
                                    "max_iterations must be positive"):
            mcts.build_tree(game_state, 0)
        with self.assertRaisesRegex(AssertionError,
                                    "max_iterations must be positive"):
            mcts.build_tree(game_state, -1)
def mcts_variance_across_multiple_game_states(cheater: bool,
                                              options: MctsPlayerOptions,
                                              num_samples: int,
                                              num_game_states: int):
    data = []
    for seed in range(num_game_states):
        print(f"Evaluating on GameState.new(random_seed={seed})")
        dataframe = _get_dataframe(GameState.new(random_seed=seed), cheater,
                                   options, num_samples)
        details = dataframe.describe().T.sort_values(by="mean",
                                                     ascending=False)
        std_dev = list(details["std"].values)
        while len(std_dev) < 7:
            std_dev.append(np.nan)
        data.append(tuple(std_dev))
    dataframe = DataFrame(data,
                          columns=["BestAction"] +
                          [f"Action #{i}" for i in range(2, 8)])
    csv_path = "mcts_variance_across_game_states.csv"
    # noinspection PyTypeChecker
    dataframe.to_csv(csv_path, index=False)
    # dataframe = pandas.read_csv(csv_path)
    dataframe.boxplot()
    plt.xticks(rotation=45, ha='right')
    plt.gcf().set_size_inches((5, 5))
    plt.tight_layout()
    plt.savefig("mcts_variance_across_game_states.png")
Esempio n. 14
0
 def _not_on_lead_action(self, game_view: GameState) -> PlayerAction:
     if game_view.must_follow_suit():
         card = self._not_on_lead_follow_suit(game_view)
     else:
         card = self._not_on_lead_do_not_follow_suit(game_view)
     logging.debug("HeuristicPlayer: Playing %s", card)
     return PlayCardAction(self.id, card)
Esempio n. 15
0
def evaluate_game(game, players, bummerl_score, bummerl_id, game_id):
    eval_results = []
    game_state = GameState.new(game.dealer, game.seed)
    for evaluated_action in game.actions:
        player = players[game_state.next_player]
        mcts_actions_and_scores = player.get_actions_and_scores(
            game_state.next_player_view(), bummerl_score)
        if len(mcts_actions_and_scores) == 1:
            # The player didn't have to make a decision. There is only one valid
            # action at this point.
            eval_results.append(
                (bummerl_id, str(game_id), evaluated_action, None, []))
        else:
            evaluated_action_score = None
            max_score = max(score for action, score in mcts_actions_and_scores)
            max_actions = [
                action for action, score in mcts_actions_and_scores
                if score == max_score
            ]
            if isinstance(max_score, tuple):
                max_score = max_score[0]
            for action, score in mcts_actions_and_scores:
                if action == evaluated_action:
                    evaluated_action_score = score
                    if isinstance(evaluated_action_score, tuple):
                        evaluated_action_score = evaluated_action_score[0]
                    break
            eval_results.append(
                (bummerl_id, str(game_id), evaluated_action,
                 3 * (evaluated_action_score - max_score), max_actions))
        game_state = evaluated_action.execute(game_state)
    return eval_results
Esempio n. 16
0
def profile(max_permutations: int, max_iterations: int = 1000):
    profiler = cProfile.Profile()

    for seed in range(NUM_SEEDS):
        game_state = GameState.new(random_seed=seed)
        if max_permutations == 1:
            closure_to_profile, cleanup = _get_algorithm_closure(
                game_state, max_iterations)
        else:
            closure_to_profile, cleanup = _get_player_closure(
                game_state, max_iterations, max_permutations)
        profiler.enable()
        closure_to_profile()
        profiler.disable()
        cleanup()

    # Save and print the profile info.
    folder = os.path.join(os.path.dirname(__file__), "data")
    suffix = _get_file_suffix(max_permutations)
    profiler_path = os.path.join(folder,
                                 f"iterations_and_time{suffix}.profile")
    profiler.dump_stats(profiler_path)
    with open(profiler_path + ".txt", "w") as output_file:
        stats = pstats.Stats(profiler,
                             stream=output_file).strip_dirs().sort_stats(
                                 SortKey.CUMULATIVE)
        stats.print_stats()
def _generate_data(cheater: bool, options: MctsPlayerOptions,
                   constant_budget: bool):
    dataframes = []
    fully_simulated_game_states = {
        "You first. No, you first":
        get_game_state_for_you_first_no_you_first_puzzle(),
        "Elimination play":
        get_game_state_for_elimination_play_puzzle(),
        "Playing to win the last trick":
        get_game_state_for_playing_to_win_the_last_trick_puzzle(),
        "Tempo":
        get_game_state_for_tempo_puzzle(),
        "Who laughs last":
        get_game_state_for_who_laughs_last_puzzle(),
        "Forcing the issue":
        get_game_state_for_forcing_the_issue_puzzle(),
        "Game state for tests":
        get_game_state_for_tests(),
    }
    dataframes.extend(
        _run_simulations(fully_simulated_game_states, cheater, options,
                         constant_budget))
    partially_simulated_game_states = {}
    for seed in [0, 20, 40, 60, 100]:
        partially_simulated_game_states[f"Random GameState (seed={seed})"] = \
          GameState.new(dealer=PlayerId.ONE, random_seed=seed)
    dataframes.extend(
        _run_simulations(partially_simulated_game_states, cheater, options,
                         constant_budget))
    dataframes.extend(
        _run_simulations(same_game_state_after_each_trick_scenarios(20),
                         cheater, options, constant_budget))
    dataframe = pandas.concat(dataframes, ignore_index=True)
    # noinspection PyTypeChecker
    dataframe.to_csv(_get_csv_path(cheater), index=False)
 def test_max_iterations_less_than_available_actions():
     # Here not all of the root node's children will be expanded.
     options = MctsPlayerOptions(max_iterations=1,
                                 max_permutations=10,
                                 num_processes=1)
     game_state = GameState.new(random_seed=0)
     mcts_player = CythonMctsPlayer(game_state.next_player, False, options)
     mcts_player.request_next_action(game_state.next_player_view())
 def can_execute_on(self, game_state: GameState) -> bool:
     if not game_state.is_to_lead(self.player_id):
         return False
     if game_state.is_talon_closed:
         return False
     if len(game_state.talon) == 0:
         return False
     return True
Esempio n. 20
0
def same_game_state_after_each_trick_scenarios(seed):
  game_state = GameState.new(dealer=PlayerId.ONE, random_seed=seed)
  same_game_state_after_each_trick = {}
  for i in range(5):
    game_state = _play_one_trick(game_state)
    same_game_state_after_each_trick[
      f"GameState (seed={seed}), after {i + 1} trick(s) played"] = game_state
  return same_game_state_after_each_trick
    def _run_test(self, player_class):
        options = MctsPlayerOptions(num_processes=1,
                                    max_permutations=10,
                                    max_iterations=10,
                                    merge_scoring_info_func=functools.partial(
                                        self._assert_num_iterations, 10 * 10),
                                    reallocate_computational_budget=False)
        game_view = GameState.new(random_seed=0).next_player_view()
        player = player_class(game_view.next_player, False, options)
        player.get_actions_and_scores(game_view)

        # There is one card left in the talon, the opponent played already a card
        # from their hand, so there are only 4 unknown cards in the opponent's hand.
        # This means there are only 4 permutations possible.
        game_view = get_game_view_for_duck_puzzle()

        # Without reallocating the computational budget, the player runs 4
        # permutations of 100 iterations each.
        options = MctsPlayerOptions(num_processes=1,
                                    max_permutations=100,
                                    max_iterations=100,
                                    merge_scoring_info_func=functools.partial(
                                        self._assert_num_iterations, 4 * 100),
                                    reallocate_computational_budget=False)
        player = player_class(game_view.next_player, False, options)
        player.get_actions_and_scores(game_view)

        # When reallocating the computational budget, the player runs 4
        # permutations of 2500 iterations each, but 5784 are enough to simulate the
        # entire game tree.
        options = MctsPlayerOptions(num_processes=1,
                                    max_permutations=100,
                                    max_iterations=100,
                                    merge_scoring_info_func=functools.partial(
                                        self._assert_num_iterations, 5784),
                                    reallocate_computational_budget=True)
        player = player_class(game_view.next_player, False, options)
        player.get_actions_and_scores(game_view)

        # If max_iterations is None, the computational budget is unlimited, so
        # reallocate_computational_budget has no effect.
        options = MctsPlayerOptions(num_processes=1,
                                    max_permutations=100,
                                    max_iterations=None,
                                    merge_scoring_info_func=functools.partial(
                                        self._assert_num_iterations, 5784),
                                    reallocate_computational_budget=False)
        player = player_class(game_view.next_player, False, options)
        player.get_actions_and_scores(game_view)
        options = MctsPlayerOptions(num_processes=1,
                                    max_permutations=100,
                                    max_iterations=None,
                                    merge_scoring_info_func=functools.partial(
                                        self._assert_num_iterations, 5784),
                                    reallocate_computational_budget=True)
        player = player_class(game_view.next_player, False, options)
        player.get_actions_and_scores(game_view)
Esempio n. 22
0
def iterations_and_time(max_permutations: int):
    # pylint: disable=too-many-locals
    data = []
    for seed in range(NUM_SEEDS):
        game_state = GameState.new(random_seed=seed)
        iterations = 10
        duration_sec = 0
        while duration_sec < 10:
            if max_permutations == 1:
                closure_to_profile, cleanup = _get_algorithm_closure(
                    game_state, iterations)
            else:
                closure_to_profile, cleanup = _get_player_closure(
                    game_state, iterations, max_permutations)
            timer = timeit.Timer(closure_to_profile)
            number, time_taken = timer.autorange()
            duration_sec = time_taken / number
            logging.info("Run %s iterations in %.5f seconds (seed=%s)",
                         iterations, duration_sec, seed)
            data.append((seed, iterations, duration_sec))
            cleanup()
            iterations *= 2

    suffix = _get_file_suffix(max_permutations)

    # Save the dataframe with the timing info.
    dataframe = DataFrame(data, columns=["seed", "iterations", "duration_sec"])
    folder = os.path.join(os.path.dirname(__file__), "data")
    csv_path = os.path.join(folder, f"iterations_and_time{suffix}.csv")
    # noinspection PyTypeChecker
    dataframe.to_csv(csv_path, index=False)

    # Plot the timing data obtained.
    for seed in sorted(dataframe.seed.drop_duplicates()):
        filtered_dataframe = dataframe[dataframe["seed"].eq(seed)]
        plt.plot(filtered_dataframe.iterations,
                 filtered_dataframe.duration_sec,
                 label=f"seed={seed}",
                 alpha=0.5)
        plt.scatter(filtered_dataframe.iterations,
                    filtered_dataframe.duration_sec,
                    s=10)
    mean = dataframe.groupby("iterations").mean().sort_index()
    plt.plot(mean.index,
             mean.duration_sec,
             label="Average",
             color="r",
             linewidth=3)
    plt.grid(which="both", linestyle="--")
    plt.legend(loc=0)
    plt.xlabel("Iterations")
    plt.ylabel("Duration (seconds)")
    plt.xscale("log")
    plt.yscale("log")
    plt.title(cpuinfo.get_cpu_info()["brand_raw"])
    plt.savefig(os.path.join(folder, f"iterations_and_time{suffix}.png"))
Esempio n. 23
0
    def test_stop_is_called_with_pending_callback(self):
        self.render(None)

        game_widget = Mock()
        players = PlayerPair(Mock(), Mock())
        players.one.is_cheater.return_value = False
        players.two.is_cheater.return_value = False
        score_view = Mock()
        # noinspection PyTypeChecker
        game_controller = GameController(game_widget, players, score_view)

        bummerl = Bummerl(next_dealer=PlayerId.ONE)
        bummerl.start_game(seed=2)
        actions = get_actions_for_one_complete_game(PlayerId.TWO)

        expected_game_state = GameState.new(dealer=PlayerId.ONE, random_seed=2)

        game_controller.start(bummerl)

        # Initializes the game widget.
        game_widget.reset.assert_called_once()
        game_widget.init_from_game_state.assert_called_once()
        actual_game_state, done_callback, game_points = \
          game_widget.init_from_game_state.call_args.args
        self.assertEqual(expected_game_state, actual_game_state)
        self.assertEqual(PlayerPair(0, 0), game_points)
        game_widget.reset_mock()
        done_callback()

        # Player action is requested.
        action = actions[0]
        players[action.player_id].request_next_action.assert_called_once()
        actual_game_state, action_callback, actual_game_points = \
          players[action.player_id].request_next_action.call_args.args

        self.assertEqual(bummerl.game_points, actual_game_points)
        expected_game_state = action.execute(expected_game_state)
        players[action.player_id].reset_mock()

        # GameController.stop() is called before the GameWidget calls
        # action_callback().
        game_controller.stop()

        # Player responds with an action.
        action_callback(action)

        # GameWidget.on_action() is called to update the UI.
        game_widget.on_action.assert_called_once()
        actual_action, done_callback = game_widget.on_action.call_args.args
        self.assertEqual(action, actual_action)
        game_widget.reset_mock()
        done_callback()

        # The GameController requests no action from the next player.
        next_player = expected_game_state.next_player
        players[next_player].request_next_action.assert_not_called()
Esempio n. 24
0
 def request_next_action(
         self,
         game_view: GameState,
         game_points: Optional[PlayerPair[int]] = None) -> PlayerAction:
     """Returns the action that this player chose to play next."""
     assert game_view.next_player == self.id, "Not my turn"
     self._cache_game_state(game_view)
     if game_view.is_to_lead(self.id):
         return self._on_lead_action(game_view)
     return self._not_on_lead_action(game_view)
 def can_execute_on(self, game_state: GameState) -> bool:
     if not game_state.is_to_lead(self.player_id):
         return False
     queen = Card(self._card.suit, CardValue.QUEEN)
     king = Card(self._card.suit, CardValue.KING)
     if queen not in game_state.cards_in_hand[self.player_id]:
         return False
     if king not in game_state.cards_in_hand[self.player_id]:
         return False
     return True
    def test_function_with_invalid_changes(self):
        @validate_game_states
        def func(game_state: GameState) -> int:
            game_state.trick_points = PlayerPair(0, 0)
            return 42

        self.assertEqual(42, func(GameState.new(PlayerId.ONE)))
        with self.assertRaisesRegex(InvalidGameStateError,
                                    "Invalid trick points"):
            func(get_game_state_for_tests())
Esempio n. 27
0
 def __setstate__(self, state):
     """
 Restore the instance variable and recreate the game state by executing all
 the player actions.
 """
     self.__dict__.update(state)
     self._game_state: GameState = GameState.new(dealer=self._dealer,
                                                 random_seed=self._seed)
     for action in self._actions:
         self._game_state = action.execute(self._game_state)
    def test_the_player_to_lead_must_have_won_a_trick(self):
        for trick in self.game_state.won_tricks.two:
            self.game_state.talon.extend([trick.one, trick.two])
            self.game_state.trick_points.two -= trick.one.card_value
            self.game_state.trick_points.two -= trick.two.card_value
        self.game_state.won_tricks.two = []
        self.game_state.trick_points.two = 0
        validate(self.game_state)
        self.game_state.next_player = PlayerId.TWO
        with self.assertRaisesRegex(
                InvalidGameStateError,
                "player that is to lead did not win any trick"):
            validate(self.game_state)

        # At the beginning of a game, any player can lead without winning any trick.
        self.game_state = GameState.new(PlayerId.ONE)
        validate(self.game_state)
        self.game_state = GameState.new(PlayerId.TWO)
        validate(self.game_state)
 def can_execute_on(self, game_state: GameState) -> bool:
     if not game_state.is_to_lead(self.player_id):
         return False
     if game_state.is_talon_closed:
         return False
     if game_state.trump_card is None:
         return False
     trump_jack = Card(suit=game_state.trump, card_value=CardValue.JACK)
     if trump_jack not in game_state.cards_in_hand[self.player_id]:
         return False
     return True
 def __init__(self, game_changed_callback, exit_usecase, ui_show_strategy):
     game_state = GameState.get_default_with_field(3, 3)
     self.scene_changed_callback = game_changed_callback
     self.ui_show_strategy = ui_show_strategy
     self.game = TicTacToeGame(game_state,
                               TicTacToeDefaultWinnerCheckStrategy(),
                               self.game_changed_callback)
     self.user_cursor_controller = UserCursorController(game_state)
     self.exit_usecase = exit_usecase
     self.game_begin_timestamp = time.time()
     self.game_finished_timestamp = None