class ValidCardHolder:
    def __init__(self, hands: Hands, trump: int):
        self._hands = hands
        self._trump = trump
        self._rule = RuleSchieber()

    @classmethod
    def from_game_state(cls, game_state: GameState):
        # 4 player, 36 hot encoded cards
        hands = Hands.by_hot_encoded(game_state.hands.copy())
        trump = game_state.trump
        return cls(hands, trump)

    def get_valid_cards(self, jass_carpet: JassCarpet) -> np.array:
        hand = self._hands.get_hand(jass_carpet.current_player)
        current_trick = jass_carpet.last_trick

        if current_trick.is_completed:
            return self._rule.get_valid_cards(hand.asArray(), EMPTY_TRICK, 0,
                                              self._trump)
        else:
            return self._rule.get_valid_cards(
                hand.asArray(), current_trick.asArray(),
                current_trick.index_of_next_missing_card, self._trump)

    def mark_card_as_invalid(self, player: int, card: int) -> None:
        self.get_hand(player).remove_card(card)

    def copy(self) -> ValidCardHolder:
        return ValidCardHolder(self._hands.copy(), self._trump)

    def get_hand(self, player: int) -> Hand:
        return self._hands.get_hand(player)

    def get_hands(self) -> Hands:
        return self._hands

    @classmethod
    def random_from_obs(cls, obs: GameObservation):
        inf_set_obs = InformationSetObservationFactory(obs).create()
        not_allocated_cards_indices = [
            i for i, card in enumerate(inf_set_obs.not_allocated_cards)
            if card == 1
        ]
        sampled_not_allocated_cards = sample(not_allocated_cards_indices,
                                             len(not_allocated_cards_indices))
        random_hands = Hands.empty()
        for player in range(4):
            if player == inf_set_obs.view_player:
                random_hands.add_hand(player, inf_set_obs.view_player_hand)
            else:
                hand = Hand.by_cards(
                    sampled_not_allocated_cards[:inf_set_obs.
                                                nbr_of_cards_in_hands[player]])
                random_hands.add_hand(player, hand)
                sampled_not_allocated_cards = sampled_not_allocated_cards[
                    inf_set_obs.nbr_of_cards_in_hands[player]:]

        trump = obs.trump
        return cls(random_hands, trump)
 def __init__(self):
     # log actions
     self._logger = logging.getLogger(__name__)
     # Use rule object to determine valid actions
     self._rule = RuleSchieber()
     # init random number generator
     self._rng = np.random.default_rng()
class ValidCardHolder:
    def __init__(self, hands: np.array, trump: int):
        self._hands = hands
        self._trump = trump
        self._rule = RuleSchieber()

    @classmethod
    def from_game_state(cls, game_state: GameState):
        # 4 player, 36 hot encoded cards
        hands = game_state.hands.copy()
        trump = game_state.trump
        return cls(hands, trump)

    def get_valid_cards(self, jass_carpet: JassCarpet) -> np.array:
        hand = self._hands[jass_carpet.get_current_player()]
        current_trick = jass_carpet.get_last_trick()

        if current_trick.is_completed():
            return self._rule.get_valid_cards(hand, [-1, -1, -1, -1], 0,
                                              self._trump)
        else:
            return self._rule.get_valid_cards(
                hand, current_trick.asArray(),
                current_trick.get_index_of_next_missing_card(), self._trump)

    def mark_card_as_invalid(self, player: int, card: int) -> None:
        self.get_hand(player)[card] = 0

    def copy(self) -> ValidCardHolder:
        return ValidCardHolder(self._hands.copy(), self._trump)

    def get_hand(self, player: int) -> np.ndarray:
        return self._hands[player]
Beispiel #4
0
 def __init__(self, node_state: ISMCTSNodeState, parent_node: ISMCTSNode = None):
     self._node_state = node_state
     self._parent_node = parent_node
     self._is_explored = False
     self._child_nodes: List[ISMCTSNode] = None
     self._nbr_of_node_was_played = 0
     self._win_los_ration = np.array([0, 0])
     self._nbr_of_node_was_visible = 0
     self._rule = RuleSchieber()
Beispiel #5
0
 def __init__(self,
              played_cards: np.ndarray,
              first_player: int,
              trump: int,
              is_last_round: bool = False) -> None:
     self._played_cards = played_cards
     self._first_player = first_player
     self._trump = trump
     self._is_last_round = is_last_round
     self._rule = RuleSchieber()
class AgentHeuristicSchieber(Agent):
    """
    Heuristic select actions for the match of jass (Schieber)
    """
    def __init__(self):
        # log actions
        self._logger = logging.getLogger(__name__)
        # Use rule object to determine valid actions
        self._rule = RuleSchieber()
        # init random number generator
        self._rng = np.random.default_rng()

    def action_trump(self, obs: GameObservation) -> int:
        trump = 0
        max_number_in_color = 0
        for c in range(4):
            number_in_color = (obs.hand * color_masks[c]).sum()
            if number_in_color > max_number_in_color:
                max_number_in_color = number_in_color
                trump = c
        return trump

    def action_play_card(self, obs: GameObservation) -> int:
        # cards are one hot encoded
        valid_cards = self._rule.get_valid_cards_from_obs(obs)
        # convert to list and draw a value
        card = self._rng.choice(np.flatnonzero(valid_cards))
        self._logger.debug('Played card: {}'.format(card_strings[card]))
        return card
 def __init__(self, max_calculation_time: int = 3):
     # log actions
     self._logger = logging.getLogger(__name__)
     # Use rule object to determine valid actions
     self._rule = RuleSchieber()
     self._max_calculation_time = max_calculation_time
     self._heuristic_trump = HeuristicTrumpBuilder()
Beispiel #8
0
 def __init__(self, jass_carpet: JassCarpet, valid_card_holder: ValidCardHolder):
     self._rule = RuleSchieber()
     self._jass_carpet = jass_carpet
     self._valid_card_holder = valid_card_holder
     self._child_nodes = None
     self._heuristic_value = None
     # log actions
     self._logger = logging.getLogger(__name__)
Beispiel #9
0
class Trick:
    def __init__(self,
                 played_cards: np.ndarray,
                 first_player: int,
                 trump: int,
                 is_last_round: bool = False) -> None:
        self._played_cards = played_cards
        self._first_player = first_player
        self._trump = trump
        self._is_last_round = is_last_round
        self._rule = RuleSchieber()

    @classmethod
    def with_played_cards(cls,
                          played_cards: np.ndarray,
                          first_player: int,
                          trump: int,
                          is_last_round: bool = False) -> Trick:
        return Trick(played_cards, first_player, trump, is_last_round)

    @classmethod
    def without_played_cards(cls,
                             first_player: int,
                             trump: int,
                             is_last_round: bool = False) -> Trick:
        played_cards = np.full(NBR_OF_CARDS_IN_ONE_TRICK,
                               MISSING_CARD_IN_TRICK)
        return Trick(played_cards, first_player, trump, is_last_round)

    @property
    def winner(self) -> int:
        return self._rule.calc_winner(self._played_cards, self._first_player,
                                      self._trump)

    def add_card(self, card: int):
        self._played_cards[self.index_of_next_missing_card] = card

    @property
    def index_of_next_missing_card(self):
        if not self.is_completed:
            return np.argwhere(self._played_cards == MISSING_CARD_IN_TRICK)[0]
        else:
            return -1

    @property
    def is_completed(self) -> bool:
        return MISSING_CARD_IN_TRICK not in self._played_cards

    @property
    def is_in_process(self) -> bool:
        return self.index_of_next_missing_card > 0

    def asArray(self) -> np.ndarray:
        return self._played_cards

    def copy(self) -> Trick:
        return Trick(self._played_cards.copy(), self._first_player,
                     self._trump, self._is_last_round)
 def __init__(self, info_set: InformationSet, jass_carpet: JassCarpet):
     self._info_set = info_set
     self._jass_carpet = jass_carpet
     self._rule = RuleSchieber()
Beispiel #11
0
 def __init__(self, game_state: GameState):
     # log actions
     self._logger = logging.getLogger(__name__)
     # Use rule object to determine valid actions
     self._rule = RuleSchieber()
     self._game_state = game_state
Beispiel #12
0
class Trick:
    def __init__(self,
                 played_cards: np.ndarray,
                 first_player: int,
                 trump: int,
                 is_last_round: bool = False) -> None:
        self._rule = RuleSchieber()
        self._played_cards = played_cards
        self._first_player = first_player
        self._trump = trump
        self._is_last_round = is_last_round

    @classmethod
    def with_played_cards(cls,
                          played_cards: np.ndarray,
                          first_player: int,
                          trump: int,
                          is_last_round: bool = False) -> Trick:
        return Trick(played_cards, first_player, trump, is_last_round)

    @classmethod
    def without_played_cards(cls,
                             first_player: int,
                             trump: int,
                             is_last_round: bool = False) -> Trick:
        played_cards = np.full(NBR_OF_CARDS_IN_ONE_TRICK, MISSING_CARD)
        return Trick(played_cards, first_player, trump, is_last_round)

    def get_winner(self) -> int:
        return self._rule.calc_winner(self._played_cards, self._first_player,
                                      self._trump)

    def get_points(self) -> int:
        return self._rule.calc_points(self._played_cards, self._is_last_round)

    def add_card(self, card: int):
        self._played_cards[self.get_index_of_next_missing_card()] = card

    def get_index_of_next_missing_card(self):
        for index in range(len(self._played_cards)):
            if self._played_cards[index] == MISSING_CARD:
                return index
        return -1

    def is_completed(self) -> bool:
        return MISSING_CARD not in self._played_cards

    def is_in_process(self) -> bool:
        return self.get_index_of_next_missing_card() > 0

    def get_last_played_card(self) -> int:
        if self.is_completed():
            return self._played_cards[NBR_OF_CARDS_IN_ONE_TRICK - 1]
        elif self.is_in_process():
            return self._played_cards[self.get_index_of_next_missing_card() -
                                      1]
        return -1

    def asArray(self) -> np.ndarray:
        return self._played_cards

    def copy(self) -> Trick:
        return Trick(self._played_cards.copy(), self._first_player,
                     self._trump, self._is_last_round)

    def __str__(self) -> str:
        return str(self._played_cards)
Beispiel #13
0
class ISMCTSNode:

    def __init__(self, node_state: ISMCTSNodeState, parent_node: ISMCTSNode = None):
        self._node_state = node_state
        self._parent_node = parent_node
        self._is_explored = False
        self._child_nodes: List[ISMCTSNode] = None
        self._nbr_of_node_was_played = 0
        self._win_los_ration = np.array([0, 0])
        self._nbr_of_node_was_visible = 0
        self._rule = RuleSchieber()

    def update(self, payoff: np.ndarray) -> None:
        self._nbr_of_node_was_played += 1
        self._win_los_ration += payoff
        if self._parent_node is not None:
            self._parent_node.update(payoff)

    def has_child_nodes(self) -> bool:
        return len(self.get_child_nodes()) != 0

    def get_child_nodes(self) -> List[ISMCTSNode]:
        if self._child_nodes is None:
            self._child_nodes = self._determine_child_nodes()
        return self._child_nodes

    def _determine_child_nodes(self) -> List[ISMCTSNode]:
        cards = [i for i, card in enumerate(self._node_state.get_cards_of_current_player())
                 if card == 1]
        child_nodes = []
        for card in cards:
            copy_node_state = self._node_state.copy()
            copy_node_state.remove_card(card)
            child_nodes.append(ISMCTSNode(copy_node_state, self))
        return child_nodes

    def has_visible_child_nodes(self, valid_card_holder: ValidCardHolder) -> bool:
        return len(self.get_visible_child_nodes(valid_card_holder)) != 0

    def get_visible_child_nodes(self, valid_card_holder: ValidCardHolder) -> List[ISMCTSNode]:
        return list(filter(lambda child: child.is_visible(valid_card_holder), self.get_child_nodes()))

    def has_visible_explored_child_nodes(self, valid_card_holder: ValidCardHolder) -> bool:
        return len(self.get_visible_explored_child_nodes(valid_card_holder)) != 0

    def get_visible_explored_child_nodes(self, valid_card_holder: ValidCardHolder) -> List[ISMCTSNode]:
        return list(filter(lambda child: child.is_visible(valid_card_holder) and child.is_explored,
                           self.get_child_nodes()))

    def has_visible_unexplored_child_nodes(self, valid_card_holder: ValidCardHolder) -> bool:
        return len(self.get_visible_unexplored_child_nodes(valid_card_holder)) != 0

    def get_visible_unexplored_child_nodes(self, valid_card_holder: ValidCardHolder) -> List[ISMCTSNode]:
        return list(filter(lambda child: child.is_visible(valid_card_holder) and not child.is_explored,
                           self.get_child_nodes()))

    def is_visible(self, valid_card_holder: ValidCardHolder) -> bool:
        return self._node_state.information_set.covered_by(valid_card_holder.get_hands()) and \
               self._does_node_represent_valid_card(valid_card_holder)

    def _does_node_represent_valid_card(self, valid_card_holder: ValidCardHolder) -> bool:
        parent_jass_carpet = self._parent_node._node_state.jass_carpet
        sampled_hand = valid_card_holder.get_hand(parent_jass_carpet.current_player).copy()
        parent_jass_carpet.remove_already_played_card_from(sampled_hand)
        current_trick = parent_jass_carpet.last_trick
        if current_trick.is_completed:
            return self._rule.get_valid_cards(sampled_hand.asArray(), EMPTY_TRICK, 0,
                                              parent_jass_carpet.trump)[self.last_played_card] == EXISTING_CARD

        else:
            return self._rule.get_valid_cards(sampled_hand.asArray(), current_trick.asArray(),
                                              current_trick.index_of_next_missing_card,
                                              parent_jass_carpet.trump)[self.last_played_card] == EXISTING_CARD

    def mark_as_explored(self):
        self._is_explored = True

    @property
    def parent_node(self):
        return self._parent_node

    @property
    def is_explored(self):
        return self._is_explored

    @property
    def nbr_of_node_was_played(self):
        return self._nbr_of_node_was_played

    @property
    def nbr_of_node_had_won(self):
        return self.win_los_ration[0]

    @property
    def nbr_of_node_was_visible(self):
        return self._nbr_of_node_was_visible

    @nbr_of_node_was_visible.setter
    def nbr_of_node_was_visible(self, value):
        self._nbr_of_node_was_visible = value

    @property
    def win_los_ration(self) -> np.ndarray:
        return self._win_los_ration

    @property
    def payoff(self) -> np.ndarray:
        return self._node_state.payoff

    @property
    def last_played_card(self) -> int:
        return self._node_state.last_played_card

    def copy(self) -> ISMCTSNode:
        return ISMCTSNode(self._node_state.copy(), self._parent_node)
 def __init__(self, hands: Hands, trump: int):
     self._hands = hands
     self._trump = trump
     self._rule = RuleSchieber()