Esempio n. 1
0
    def step(self, state):
        ''' Human agent will display the state and make decisions through interfaces

        Args:
            state (dict): A dictionary that represents the current state

        Returns:
            action (int): The action decided by human
        '''
        if self.is_choosing_action_id:
            raise GinRummyProgramError(
                "self.is_choosing_action_id must be False.")
        if self.state is not None:
            raise GinRummyProgramError("self.state must be None.")
        if self.chosen_action_id is not None:
            raise GinRummyProgramError(
                "self.chosen_action_id={} must be None.".format(
                    self.chosen_action_id))
        self.state = state
        self.is_choosing_action_id = True
        while not self.chosen_action_id:
            time.sleep(0.001)
        if self.chosen_action_id is None:
            raise GinRummyProgramError("self.chosen_action_id cannot be None.")
        chosen_action_event = ActionEvent.decode_action(
            action_id=self.chosen_action_id)
        self.state = None
        self.is_choosing_action_id = False
        self.chosen_action_id = None
        return chosen_action_event
Esempio n. 2
0
def start_new_game(game_canvas: 'GameCanvas'):
    info_messaging.blank_info_message_label(game_canvas=game_canvas)
    if game_canvas.game_canvas_updater.env_thread and game_canvas.game_canvas_updater.env_thread.is_alive(
    ):
        game_canvas.game_canvas_updater.env_thread.stop(
        )  # FIXME: complex stopping of threads; simplify ???
        while game_canvas.game_canvas_updater.env_thread.is_alive(
        ) or not game_canvas.game_canvas_updater.is_stopped:
            game_canvas.update(
            )  # yield time to other threads and to main thread
        if game_canvas.game_canvas_updater.env_thread.is_alive():
            raise GinRummyProgramError("env_thread did not stop.")
    _reset_game_canvas(game_canvas=game_canvas)
    # make new gin_rummy_env
    gin_rummy_env = game_canvas.game_app.make_gin_rummy_env()
    gin_rummy_env.game.settings.going_out_deadwood_count = configurations.GOING_OUT_DEADWOOD_COUNT  # Note this
    gin_rummy_env.game.settings.max_drawn_card_count = configurations.MAX_DRAWN_CARD_COUNT  # Note this
    # start thread
    if utils.is_debug():
        south_agent = gin_rummy_env.agents[1]
        if isinstance(south_agent, HumanAgent):
            if south_agent.state is not None:
                raise GinRummyProgramError("south_agent.state must be None.")
            if south_agent.is_choosing_action_id is True:
                raise GinRummyProgramError(
                    "south_agent.is_choosing_action_id must be False.")
            if south_agent.chosen_action_id is not None:
                raise GinRummyProgramError(
                    "south_agent.chosen_action_id={} must be None.".format(
                        south_agent.chosen_action_id))
    game_canvas.game_canvas_updater.env_thread = EnvThread(
        gin_rummy_env=gin_rummy_env, game_canvas=game_canvas)
    game_canvas.game_canvas_updater.env_thread.start(
    )  # Note this: start env background thread
Esempio n. 3
0
def _handle_can_discard_card(hit_item: CanvasItem,
                             game_canvas: 'GameCanvas'):  # hit_item is target
    # hit_item must be top card of discard_pile or discard_pile_box_item.
    # exactly one held_pile_item must be selected.
    # The selected held_pile_item is discarded.
    # The remaining held_pile_items are fanned.
    top_discard_pile_item_id = game_canvas.getter.get_top_discard_pile_item_id(
    )
    if top_discard_pile_item_id:
        if not hit_item == top_discard_pile_item_id:
            raise GinRummyProgramError(
                "hit_item must be top card of discard_pile.")
    else:
        if not hit_item == game_canvas.discard_pile_box_item:
            raise GinRummyProgramError(
                "hit_item must be discard_pile_box_item.")
    current_player_id = game_canvas.current_player_id
    selected_held_pile_item_ids = game_canvas.getter.get_selected_held_pile_item_ids(
        player_id=current_player_id)
    if len(selected_held_pile_item_ids) == 1:
        if current_player_id == 1:  # remove info_message if south player
            info_messaging.blank_info_message_label(game_canvas=game_canvas)
        selected_held_pile_item_id = selected_held_pile_item_ids[0]
        game_canvas.post_doing_action.post_do_discard_action(
            player_id=current_player_id,
            selected_held_pile_item_id=selected_held_pile_item_id)
    else:
        pass  # FIXME: put warning message ???
Esempio n. 4
0
 def _perform_score_action_id(self, action_id: int):
     if utils.is_debug():
         if self.busy_body_id == 0:
             if not action_id == configurations.SCORE_PLAYER_0_ACTION_ID:
                 raise GinRummyProgramError(
                     "action_id={} must be SCORE_PLAYER_0_ACTION_ID".format(
                         action_id))
         else:
             if not action_id == configurations.SCORE_PLAYER_1_ACTION_ID:
                 raise GinRummyProgramError(
                     "action_id={} must be SCORE_PLAYER_1_ACTION_ID".format(
                         action_id))
     self.game_canvas.after_idle(self.did_perform_actions, [action_id])
Esempio n. 5
0
def drop_item_ids(item_ids: List[int], on_item_id: int, player_id: int,
                  game_canvas: 'GameCanvas'):
    # on_item_id must be in held_pile_item_ids of player_id
    # item_ids are inserted into held_pile of player_id after on_item_id
    held_pile_item_ids = game_canvas.getter.get_held_pile_item_ids(player_id)
    held_pile_ghost_card_item = game_canvas.held_pile_ghost_card_items[
        player_id]
    if not (on_item_id == held_pile_ghost_card_item
            or on_item_id in held_pile_item_ids):
        raise GinRummyProgramError(
            "on_item_id={} is invalid drop location.".format(on_item_id))
    held_pile_item_ids_count = len(held_pile_item_ids)
    held_pile_tag = game_canvas.held_pile_tags[player_id]
    on_item_index = -1 if on_item_id == held_pile_ghost_card_item else held_pile_item_ids.index(
        on_item_id)
    after_item_ids = []
    for i in range(on_item_index + 1, held_pile_item_ids_count):
        after_item_id = held_pile_item_ids[i]
        if after_item_id not in item_ids:
            after_item_ids.append(after_item_id)
    drop_canvas_items = [
        game_canvas.canvas_item_by_item_id[item_id] for item_id in item_ids
    ]
    drop_card_items = [x for x in drop_canvas_items if isinstance(x, CardItem)]
    sorted_drop_card_items = sorted(
        drop_card_items,
        reverse=True,
        key=lambda card_item: gin_rummy_sort_order_id(card_item.card_id))
    sorted_item_ids = [x.item_id for x in sorted_drop_card_items]
    for item_id in sorted_item_ids:
        item_tags = game_canvas.getter.get_tags(item_id)
        if configurations.SELECTED_TAG in item_tags:
            game_canvas.dtag(item_id, configurations.SELECTED_TAG)
            game_canvas.dtag(item_id, configurations.JOGGED_TAG)
        if configurations.DRAWN_TAG in item_tags:
            game_canvas.dtag(item_id, configurations.DRAWN_TAG)
            if configurations.DISCARD_PILE_TAG in item_tags:
                game_canvas.dtag(item_id, configurations.DISCARD_PILE_TAG)
            elif configurations.STOCK_PILE_TAG in item_tags:
                game_canvas.dtag(item_id, configurations.STOCK_PILE_TAG)
            if held_pile_tag in item_tags:
                raise GinRummyProgramError(
                    "item_tags should not contain held_pile_tag.")
            game_canvas.addtag_withtag(held_pile_tag, item_id)
        game_canvas.tag_raise(item_id)
    for after_item_id in after_item_ids:
        game_canvas.tag_raise(after_item_id)
    fan_held_pile(player_id, game_canvas=game_canvas)
Esempio n. 6
0
 def _advance_mark_for_computer_player(self):
     if not self.mark < len(self.moves):
         raise GinRummyProgramError(
             "mark={} must be less than len(moves)={}.".format(
                 self.mark, len(self.moves)))
     move = self.moves[self.mark]
     if isinstance(move, DealHandMove):
         self._perform_deal_hand_move(move=move)
     elif isinstance(move, DrawCardMove):
         self._perform_draw_card_move(move=move)
     elif isinstance(move, PickupDiscardMove):
         self._perform_pick_up_discard_move(move=move)
     elif isinstance(move, DeclareDeadHandMove):
         self._do_perform_declare_dead_hand_move(move=move)
     elif isinstance(move, DiscardMove):
         self._perform_discard_move(move=move)
     elif isinstance(move, KnockMove):
         self._perform_knock_move(move=move)
     elif isinstance(move, GinMove):
         self._perform_gin_move(move=move)
     elif isinstance(move, ScoreNorthMove) or isinstance(
             move, ScoreSouthMove):
         if utils.is_debug():
             print("{}".format(move))
         self._perform_score_action_id(action_id=move.action.action_id)
Esempio n. 7
0
 def get_card_id(self, card_item_id: int) -> int:
     game_canvas = self.game_canvas
     if card_item_id in game_canvas.card_item_ids:
         card_id = game_canvas.card_item_ids.index(card_item_id)
     else:
         raise GinRummyProgramError("card_item_id={} not found in card_item_ids.".format(card_item_id))
     return card_id
Esempio n. 8
0
 def get_current_player_id(self) -> int or None:
     result = None  # type: int or None
     game = self.get_game()
     if not game.round:
         return None
     game_canvas = self.game_canvas
     mark = game_canvas.game_canvas_updater.mark
     moves = game.round.move_sheet[:mark]
     if not moves:
         if not mark == 0:
             raise GinRummyProgramError("mark={} must be 0.".format(mark))
         if game.round.move_sheet:
             first_move = game.round.move_sheet[0]
             if isinstance(first_move, DealHandMove):
                 result = first_move.player_dealing.player_id
     else:
         last_move = moves[-1]
         if isinstance(last_move, DealHandMove):
             result = (last_move.player_dealing.player_id + 1) % 2
         elif isinstance(last_move, DrawCardMove):
             result = last_move.player.player_id
         elif isinstance(last_move, PickupDiscardMove):
             result = last_move.player.player_id
         elif isinstance(last_move, DeclareDeadHandMove):
             result = 0
         elif isinstance(last_move, DiscardMove):
             penultimate_move = moves[-2]
             can_keep_turn = configurations.IS_KEEP_TURN_WHEN_DISCARDING_CARD_PICKED_UP
             is_discarding_card_picked_up = False
             if isinstance(penultimate_move, PickupDiscardMove) and last_move.action.card == penultimate_move.card:
                 is_discarding_card_picked_up = True
             if is_discarding_card_picked_up and can_keep_turn:
                 result = last_move.player.player_id  # keep turn when discarding card picked up
             else:
                 result = (last_move.player.player_id + 1) % 2
         elif isinstance(last_move, KnockMove):
             result = 0
         elif isinstance(last_move, GinMove):
             result = 0
         elif isinstance(last_move, ScoreNorthMove):
             result = 1
         elif isinstance(last_move, ScoreSouthMove):
             pass
         else:
             raise GinRummyProgramError('get_current_player_id: unknown last_move={}'.format(last_move))
     return result
Esempio n. 9
0
 def get_held_pile_item_ids(self, player_id: int) -> List[int]:
     if player_id is None:
         raise GinRummyProgramError("player_id must not be None.")
     game_canvas = self.game_canvas
     ghost_card_item = game_canvas.held_pile_ghost_card_items[player_id]
     held_pile_tag = game_canvas.held_pile_tags[player_id]
     held_pile_item_ids = [x for x in game_canvas.find_withtag(held_pile_tag) if x != ghost_card_item]
     return held_pile_item_ids
Esempio n. 10
0
def handle_tap_held_pile(hit_item: CanvasItem, game_canvas: 'GameCanvas'):
    hit_item_tags = hit_item.get_tags()
    if game_canvas.held_pile_tags[0] in hit_item_tags:
        player_id = 0
    elif game_canvas.held_pile_tags[1] in hit_item_tags:
        player_id = 1
    else:
        raise GinRummyProgramError("handle_tap_held_pile: unknown held_pile.")
    player_is_human = game_canvas.player_types[
        player_id] is PlayerType.human_player
    can_draw_from_stock_pile = game_canvas.query.can_draw_from_stock_pile(
        player_id=player_id)
    can_draw_from_discard_pile = game_canvas.query.can_draw_from_discard_pile(
        player_id=player_id)
    is_game_over = game_canvas.query.is_game_over()
    if is_game_over:
        pass
    elif game_canvas.query.can_discard_card(
            player_id=player_id):  # hit_item is source
        if player_is_human:
            utils.toggle_held_pile_item_selected(item=hit_item,
                                                 game_canvas=game_canvas)
    elif can_draw_from_stock_pile or can_draw_from_discard_pile:  # hit_item is target
        drawn_card_item_id = None
        drawn_card_item_tag = None
        if not drawn_card_item_id and can_draw_from_stock_pile:
            top_stock_pile_item_id = game_canvas.getter.get_top_stock_pile_item_id(
            )
            top_stock_pile_item_tags = game_canvas.getter.get_tags(
                top_stock_pile_item_id)
            if configurations.DRAWN_TAG in top_stock_pile_item_tags:
                drawn_card_item_id = top_stock_pile_item_id
                drawn_card_item_tag = configurations.STOCK_PILE_TAG
        if not drawn_card_item_id and can_draw_from_discard_pile:
            top_discard_pile_item_id = game_canvas.getter.get_top_discard_pile_item_id(
            )
            top_discard_pile_item_tags = game_canvas.getter.get_tags(
                top_discard_pile_item_id)
            if configurations.DRAWN_TAG in top_discard_pile_item_tags:
                drawn_card_item_id = top_discard_pile_item_id
                drawn_card_item_tag = configurations.DISCARD_PILE_TAG
        if drawn_card_item_id:
            if player_id == 1:  # remove info_message if south player
                info_messaging.blank_info_message_label(
                    game_canvas=game_canvas)
            game_canvas.post_doing_action.post_do_get_card_action(
                player_id=player_id,
                drawn_card_item_id=drawn_card_item_id,
                hit_item_id=hit_item.item_id,
                drawn_card_item_tag=drawn_card_item_tag)
        else:
            utils.toggle_held_pile_item_selected(item=hit_item,
                                                 game_canvas=game_canvas)
    else:
        if player_is_human:
            utils.toggle_held_pile_item_selected(
                item=hit_item, game_canvas=game_canvas)  # arranging hand
Esempio n. 11
0
def on_tap_to_arrange_held_pile(event):
    widget = event.widget
    if widget.query.is_game_over():
        return
    # game must not be over
    hit_items_ids = widget.find_withtag("current")
    if not hit_items_ids:
        return
    if not len(hit_items_ids) == 1:
        raise GinRummyProgramError("len(hit_items_ids)={} must be 1.".format(
            len(hit_items_ids)))
    hit_item_id = hit_items_ids[0]
    hit_item = None
    for canvas_item in widget.canvas_items:
        if canvas_item.item_id == hit_item_id:
            hit_item = canvas_item
    if hit_item:
        hit_item_tags = hit_item.get_tags()
        hit_held_pile_tag = None
        for held_pile_tag in widget.held_pile_tags:
            if held_pile_tag in hit_item_tags:
                hit_held_pile_tag = held_pile_tag
                break
        if not hit_held_pile_tag:
            return
        # must hit a held_pile
        hitter_id = widget.held_pile_tags.index(hit_held_pile_tag)
        if widget.player_types[hitter_id] is not PlayerType.human_player:
            return
        # held_pile hit must belong to human player
        must_do_on_tap = False
        if hitter_id == widget.current_player_id:
            is_top_discard_pile_item_drawn = widget.query.is_top_discard_pile_item_drawn(
            )
            is_top_stock_pile_item_drawn = widget.query.is_top_stock_pile_item_drawn(
            )
            must_do_on_tap = is_top_discard_pile_item_drawn or is_top_stock_pile_item_drawn
        if must_do_on_tap:
            # Minor kludge to handle the following situation.
            # The current_player should just tap to combine drawn card with the selected cards.
            # However, I suspect the player will get in the habit of treating this situation as an arrangement.
            handling_tap.on_game_canvas_tap(event)  # kludge
        else:
            handle_tap_to_arrange_held_pile(hit_item=hit_item,
                                            game_canvas=widget)
Esempio n. 12
0
def get_best_meld_clusters(hand: List[Card]) -> List[List[List[Card]]]:
    if len(hand) != 10:
        raise GinRummyProgramError(
            "Hand contain {} cards: should be 10 cards.".format(len(hand)))
    result = []  # type: List[List[List[Card]]]
    meld_clusters = get_meld_clusters(
        hand=hand)  # type: List[List[List[Card]]]
    meld_clusters_count = len(meld_clusters)
    if meld_clusters_count > 0:
        deadwood_counts = [
            utils.get_deadwood_count(hand=hand, meld_cluster=meld_cluster)
            for meld_cluster in meld_clusters
        ]
        best_deadwood_count = min(deadwood_counts)
        for i in range(meld_clusters_count):
            if deadwood_counts[i] == best_deadwood_count:
                result.append(meld_clusters[i])
    return result
Esempio n. 13
0
def get_action_type(action: int) -> int:
    if action == DRAW_CARD_ACTION_ID:
        result = action
    elif action == PICK_UP_DISCARD_ACTION_ID:
        result = action
    elif action == DECLARE_DEAD_HAND_ACTION_ID:
        result = action
    elif DISCARD_ACTION_ID <= action < DISCARD_ACTION_ID + 52:
        result = DISCARD_ACTION_ID
    elif KNOCK_ACTION_ID <= action < KNOCK_ACTION_ID + 52:
        result = KNOCK_ACTION_ID
    elif action == SCORE_PLAYER_0_ACTION_ID:
        result = action
    elif action == SCORE_PLAYER_1_ACTION_ID:
        result = action
    else:
        raise GinRummyProgramError("No action type for {}.".format(action))
    return result
Esempio n. 14
0
def _reset_game_canvas(game_canvas: 'GameCanvas'):
    game_canvas.dealer_id = 0  # Note: has no effect; will be set later to correct value
    game_canvas.game_canvas_updater.pending_human_action_ids = []
    game_canvas.game_canvas_updater.busy_body_id = None
    game_canvas.game_canvas_updater.is_stopped = False
    for player_id in range(2):
        game_canvas.score_pad_cells[player_id].configure(text="")
    for card_id in range(52):
        card_item_id = game_canvas.card_item_ids[card_id]
        game_canvas.itemconfigure(card_item_id, tags=[])
    game_canvas.update(
    )  # seems to be needed: scores not cleared if 'new game' chosen from menu with no mouse move
    if utils.is_debug():
        for card_id in range(52):
            card_item_id = game_canvas.card_item_ids[card_id]
            tags = game_canvas.gettags(card_item_id)
            if tags:
                raise GinRummyProgramError("tags must be None.")
Esempio n. 15
0
def held_pile_insert(card_item_id: int, above_hit_item_id: int or None,
                     player_id: int, game_canvas: 'GameCanvas'):
    held_pile_item_ids = game_canvas.getter.get_held_pile_item_ids(
        player_id=player_id)
    held_pile_item_ids_count = len(held_pile_item_ids)
    if above_hit_item_id is None or above_hit_item_id == game_canvas.held_pile_ghost_card_items[
            player_id]:
        insertion_index = 0
    else:
        insertion_index = held_pile_item_ids.index(above_hit_item_id) + 1
    held_pile_tab = game_canvas.held_pile_tab
    if not card_item_id == held_pile_item_ids[
            -1]:  # Note: card_item_id is last and already positioned and raised
        raise GinRummyProgramError(
            "card_item_id={} must be last card of hand.".format(card_item_id))
    for i in range(insertion_index, held_pile_item_ids_count - 1):
        held_pile_item_id = held_pile_item_ids[i]
        game_canvas.move(held_pile_item_id, held_pile_tab, 0)
        game_canvas.tag_raise(held_pile_item_id)
Esempio n. 16
0
 def _perform_pick_up_discard_move(self, move: PickupDiscardMove):
     if utils.is_debug():
         print("{}".format(move))
     player = move.player
     player_id = player.player_id
     card = move.card
     source_item_id = self.game_canvas.getter.get_top_discard_pile_item_id()
     source_card_item_id = self.game_canvas.getter.get_card_id(
         card_item_id=source_item_id)
     if not source_card_item_id == gin_rummy_utils.get_card_id(card=card):
         raise GinRummyProgramError(
             "source_card_item_id={} doesn't match with card={}.".format(
                 source_card_item_id, card))
     self.game_canvas.addtag_withtag(configurations.DRAWN_TAG,
                                     source_item_id)
     target_item_id = self.game_canvas.getter.get_held_pile_item_ids(
         player_id=player_id)[-1]
     target_item = self.game_canvas.canvas_item_by_item_id[target_item_id]
     handling_tap_held_pile.handle_tap_held_pile(
         hit_item=target_item, game_canvas=self.game_canvas)
Esempio n. 17
0
def on_game_canvas_tap(event):
    widget = event.widget
    hit_item_ids = widget.find_withtag("current")
    if hit_item_ids:
        if not len(hit_item_ids) == 1:
            raise GinRummyProgramError(
                "len(hit_item_ids)={} must be 1.".format(len(hit_item_ids)))
        hit_item_id = hit_item_ids[0]
        hit_item = None
        for canvas_item in widget.canvas_items:
            if canvas_item.item_id == hit_item_id:
                hit_item = canvas_item
        if hit_item:
            if not widget.query.is_game_over():
                _handle_tap(hit_item=hit_item, event=event, game_canvas=widget)
            else:
                top_discard_pile_item_id = widget.getter.get_top_discard_pile_item_id(
                )
                if hit_item_id == top_discard_pile_item_id:
                    starting_new_game.start_new_game(game_canvas=widget)
Esempio n. 18
0
 def _perform_discard_move(self, move: DiscardMove):
     if utils.is_debug():
         print("{}".format(move))
     action_id = move.action.action_id
     if self.busy_body_id is None:
         raise GinRummyProgramError("busy_body_id cannot be None.")
     card_id = utils.get_action_card_id(action_id)
     source_item_id = self.game_canvas.card_item_ids[card_id]
     self.game_canvas.addtag_withtag(configurations.SELECTED_TAG,
                                     source_item_id)
     target_item_id = self.game_canvas.getter.get_top_discard_pile_item_id()
     if target_item_id is None:
         target_item_id = self.game_canvas.discard_pile_box_item
     if not self.game_canvas.is_treating_as_human(
             player_id=self.busy_body_id):
         # move source_item_id to end of held_pile invisibly
         self.game_canvas.tag_raise(source_item_id)
         utils.fan_held_pile(player_id=self.busy_body_id,
                             game_canvas=self.game_canvas)
     handling_tap_discard_pile.handle_tap_discard_pile(
         hit_item=target_item_id, game_canvas=self.game_canvas)
Esempio n. 19
0
 def on_going_out(self):
     if self.query.is_game_over():
         raise GinRummyProgramError("Cannot go out if game is over.")
     current_player_id = self.current_player_id
     selected_held_pile_item_ids = self.getter.get_selected_held_pile_item_ids(
         player_id=current_player_id)
     legal_actions = self.getter.get_legal_actions(
         player_id=current_player_id)
     gin_action = GinAction()
     if gin_action in legal_actions:
         self.post_doing_action.post_do_gin_action()
     elif len(selected_held_pile_item_ids) == 1:
         selected_held_pile_item_id = selected_held_pile_item_ids[0]
         card_id = self.card_item_ids.index(selected_held_pile_item_id)
         card = gin_rummy_utils.get_card(card_id=card_id)
         knock_action = KnockAction(card=card)
         if knock_action in legal_actions:
             self.post_doing_action.post_do_knock_action(
                 selected_held_pile_item_id)
         else:
             pass  # FIXME: need message
     else:
         pass  # FIXME: need message
Esempio n. 20
0
def show_new_game(game_canvas: 'GameCanvas'):
    game = game_canvas.game_canvas_updater.env_thread.gin_rummy_env.game
    game_canvas.dealer_id = game.round.dealer_id
    dealer = game.round.dealer
    shuffled_deck = dealer.shuffled_deck
    # Deal cards to players
    if utils.is_debug():
        for card_id in range(52):
            card_item_id = game_canvas.card_item_ids[card_id]
            tags = game_canvas.gettags(card_item_id)
            if tags:
                raise GinRummyProgramError("tags must be None.")
    for i in range(2):
        player_id = (game_canvas.dealer_id + 1 + i) % 2
        anchor_x, anchor_y = game_canvas.player_held_pile_anchors[player_id]
        face_up = True
        # Note: cannot use card_ids = [gin_rummy_utils.get_card_id(card) for card in game.round.players[player_id].hand]
        if not game_canvas.is_treating_as_human(player_id=player_id):
            face_up = False
        if i == 0:
            dealt_cards = list(shuffled_deck[-11:])
        else:
            dealt_cards = list(shuffled_deck[-21:-11])
        card_ids = [
            gin_rummy_utils.get_card_id(card=card) for card in dealt_cards
        ]
        card_ids = sorted(card_ids,
                          reverse=True,
                          key=utils.gin_rummy_sort_order_id)
        for card_id in card_ids:
            card_item_id = game_canvas.card_item_ids[card_id]
            if utils.is_debug() or True:
                tags = game_canvas.gettags(card_item_id)
                if tags:
                    raise GinRummyProgramError("tags must be None.")
            game_canvas.tag_raise(card_item_id)  # note this
            game_canvas.itemconfig(card_item_id,
                                   tag=game_canvas.held_pile_tags[player_id])
            utils.set_card_id_face_up(card_id=card_id,
                                      face_up=face_up,
                                      game_canvas=game_canvas)
            utils.move_to(card_item_id, anchor_x, anchor_y, parent=game_canvas)
            game_canvas.itemconfigure(card_item_id, state=tk.NORMAL)
            anchor_x += game_canvas.held_pile_tab
    # Deal stockpile cards
    stock_pile_x, stock_pile_y = game_canvas.stock_pile_anchor
    # Note: cannot use stock_pile = [gin_rummy_utils.get_card_id(card) for card in game.round.dealer.stock_pile]
    stock_pile = list(shuffled_deck[:31])
    stock_pile_card_ids = [
        gin_rummy_utils.get_card_id(card) for card in stock_pile
    ]
    for card_id in stock_pile_card_ids:
        card_item_id = game_canvas.card_item_ids[card_id]
        if utils.is_debug():
            tags = game_canvas.gettags(card_item_id)
            if tags:
                raise GinRummyProgramError("tags must be None.")
        game_canvas.tag_raise(card_item_id)  # note this
        game_canvas.itemconfig(card_item_id, tag=configurations.STOCK_PILE_TAG)
        utils.set_card_id_face_up(card_id=card_id,
                                  face_up=False,
                                  game_canvas=game_canvas)
        utils.move_to(card_item_id,
                      stock_pile_x,
                      stock_pile_y,
                      parent=game_canvas)
        game_canvas.itemconfigure(card_item_id, state=tk.NORMAL)
        stock_pile_x += game_canvas.stock_pile_tab
    # update canvas
    game_canvas.update(
    )  # seems to be needed: scores not cleared if 'new game' chosen from menu with no mouse move
    if utils.is_debug():
        settings = game.settings
        settings.print_settings()
Esempio n. 21
0
 def _advance_mark(self):
     if self.env.game.round is None:
         return
     if self.game_canvas.query.is_game_over() and self.mark >= len(
             self.moves):
         return
     if self.busy_body_id is not None:
         return
     if self.human_agent and not self.human_agent.is_choosing_action_id:
         return
     if self.human_agent and self.human_agent.chosen_action_id is not None:
         return
     if self.env_thread.is_action_id_available():
         move = self.moves[self.mark]
         thinking_time_in_ms = 0  # type: int
         if isinstance(move, DealHandMove):
             if not self.mark == 0:
                 raise GinRummyProgramError("mark={} must be 0.".format(
                     self.mark))
             self.busy_body_id = move.player_dealing.player_id
         elif isinstance(move, ScoreNorthMove) or isinstance(
                 move, ScoreSouthMove):
             self.busy_body_id = move.player.player_id
         elif isinstance(move, PlayerMove):
             self.busy_body_id = move.player.player_id
             thinking_time_in_ms = 1000  # type: int  # simulate the computer thinking
         else:
             raise GinRummyProgramError(
                 "GameCanvasUpdater advance_mark: unknown move={move}")
         if self.mark > 0:
             if self.game_canvas.player_types[
                     self.busy_body_id] == PlayerType.human_player:
                 raise GinRummyProgramError(
                     "busy_body_id={} must not be human player.".format(
                         self.busy_body_id))
         if not self.busy_body_id == self.game_canvas.getter.get_current_player_id(
         ):
             raise GinRummyProgramError(
                 "busy_body_id={} must equal current_player_id={}".format(
                     self.busy_body_id,
                     self.game_canvas.getter.get_current_player_id()))
         self._show_prolog_messages_on_computer_turn()
         self.game_canvas.after(thinking_time_in_ms,
                                self._advance_mark_for_computer_player)
         return
     if self.pending_human_action_ids:
         action_id = self.pending_human_action_ids.pop(
             0)  # pending_human_action_ids is queue
         if utils.is_debug():
             action_event = ActionEvent.decode_action(action_id=action_id)
             print("S {}".format(
                 action_event))  # FIXME: South may not always be actor
         self.human_agent.chosen_action_id = action_id
         return
     if not self.mark >= len(
             self.moves):  # FIXME: should be no pending computer moves
         raise GinRummyProgramError("Should be no pending computer moves.")
     waiting_player_id = self.env_thread.get_waiting_player_id()
     if waiting_player_id is None:
         return
     # FIXME: should be no pending computer moves
     if self.human_agent.chosen_action_id is not None:
         raise GinRummyProgramError(
             "self.human_agent.chosen_action_id must not be None.")
     if self.busy_body_id is not None:
         raise GinRummyProgramError("busy_body_id={} must be None.".format(
             self.busy_body_id))
     if not waiting_player_id == self.game_canvas.getter.get_current_player_id(
     ):
         raise GinRummyProgramError(
             "waiting_player_id={} must be current_player_id.".format(
                 waiting_player_id))
     self.busy_body_id = waiting_player_id
     if not self.game_canvas.player_types[
             self.busy_body_id] == PlayerType.human_player:
         raise GinRummyProgramError(
             "busy_body_id={} must be human player.".format(
                 self.busy_body_id))
     raw_legal_actions = self.human_agent.state['raw_legal_actions']
     if self.game_canvas.query.is_scoring(legal_actions=raw_legal_actions):
         # 'boss' performs this, not human
         if not len(raw_legal_actions) == 1:
             raise GinRummyProgramError(
                 "len(legal_actions)={} must be 1.".format(
                     len(raw_legal_actions)))
         action_id = raw_legal_actions[0]
         self._perform_score_action_id(action_id=action_id)
         return
     self._show_prolog_messages_on_human_turn()
Esempio n. 22
0
def translated_by(dx: float, dy: float, location):
    if not len(location) == 2:
        raise GinRummyProgramError(
            "location={} must have length of 2.".format(location))
    return [location[0] + dx, location[1] + dy]
Esempio n. 23
0
 def get_legal_actions(self, player_id: int) -> List[ActionEvent]:
     if player_id != self.get_current_player_id():
         return []
     legal_actions = []  # type: List[ActionEvent]
     game = self.get_game()
     game_canvas = self.game_canvas
     moves = game.round.move_sheet[:game_canvas.game_canvas_updater.mark]
     last_move = None if not moves else moves[-1]
     if not last_move:
         return []
     settings = self.get_settings()
     if isinstance(last_move, DealHandMove) or \
             isinstance(last_move, DrawCardMove) or \
             isinstance(last_move, PickupDiscardMove):
         going_out_deadwood_count = settings.going_out_deadwood_count
         hand = self.get_held_pile_cards(player_id=player_id)
         knock_cards, gin_cards = judge.get_going_out_cards(hand=hand, going_out_deadwood_count=going_out_deadwood_count)
         if settings.is_allowed_gin and gin_cards:
             legal_actions = [GinAction()]
         else:
             cards_to_discard = [card for card in hand]
             if isinstance(last_move, PickupDiscardMove):
                 if not settings.is_allowed_to_discard_picked_up_card:
                     picked_up_card = last_move.card
                     cards_to_discard.remove(picked_up_card)
             discard_actions = [DiscardAction(card=card) for card in cards_to_discard]
             legal_actions = discard_actions
             if settings.is_allowed_knock:
                 if player_id == 0 or not settings.is_south_never_knocks:
                     if knock_cards:
                         knock_actions = [KnockAction(card=card) for card in knock_cards]
                         if not settings.is_always_knock:
                             legal_actions.extend(knock_actions)
                         else:
                             legal_actions = knock_actions
     elif isinstance(last_move, DeclareDeadHandMove):
         legal_actions = [ScoreNorthPlayerAction()]
     elif isinstance(last_move, GinMove):
         legal_actions = [ScoreNorthPlayerAction()]
     elif isinstance(last_move, DiscardMove):
         stock_pile_item_ids = self.get_stock_pile_item_ids()
         can_draw_card = len(stock_pile_item_ids) > settings.stockpile_dead_card_count
         if settings.max_drawn_card_count < 52:  # NOTE: this
             draw_card_moves = [x for x in moves if isinstance(x, DrawCardMove)]
             if len(draw_card_moves) >= settings.max_drawn_card_count:
                 can_draw_card = False
         if can_draw_card:
             legal_actions = [DrawCardAction()]
             if settings.is_allowed_pick_up_discard:
                 legal_actions.append(PickUpDiscardAction())
         else:
             legal_actions = [DeclareDeadHandAction()]
             if settings.is_allowed_pick_up_discard:
                 legal_actions.append(PickUpDiscardAction())
     elif isinstance(last_move, KnockMove):
         legal_actions = [ScoreNorthPlayerAction()]
     elif isinstance(last_move, ScoreNorthMove):
         legal_actions = [ScoreSouthPlayerAction()]
     elif isinstance(last_move, ScoreSouthMove):
         pass
     else:
         raise GinRummyProgramError('get_legal_actions: unknown last_move={}'.format(last_move))
     return legal_actions