예제 #1
0
 def __init__(self, name: str = "Player") -> None:
     """Creates a hand with empty gems collections, empty set of cards, nobles and reserved cards.
     Parameters:
     _ _ _ _ _ _
     name: The name of player who has this hand (optional)."""
     self.name = name
     self.gems_possessed = GemsCollection()
     self.cards_possessed = set()
     self.cards_reserved = set()
     self.nobles_possessed = set()
예제 #2
0
    def to_dict(self):
        gems = GemsCollection()
        gems.gems_dict[GemColor.GOLD] += 1
        if self.return_gem_color is not None:
            gems.gems_dict[self.return_gem_color] -= 1

        return {
            "action_type": self.action_type,
            'gems_flow': gems.to_dict(),
            'card': self.card.to_dict()
        }
예제 #3
0
 def __init__(self,
              card: Card,
              n_gold_gems_to_use: int=0,
              use_gold_as: GemsCollection = GemsCollection()):
     """Parameters:
     _ _ _ _ _ _ _ _
     card: Card to buy.
     gold_gems_to_use: Integer determining how many golden gems will be used to pay for the card.
     use_gold_as: Gems collection that reduces the price (its sum must equal n_gold_gems_to_use)."""
     self.card = card
     assert n_gold_gems_to_use == use_gold_as.sum(), 'n_gold_gems_to_use must be equal the sum of gems in use_gold_as'
     self.n_gold_gems_to_use = n_gold_gems_to_use
     self.use_gold_as = use_gold_as
예제 #4
0
    def evaluate(self, state: State):
        gems = GemsCollection()
        gems.gems_dict[GemColor.GOLD] += 1
        if self.return_gem_color is not None:
            gems.gems_dict[self.return_gem_color] -= 1

        card_properties = self.card.evaluate()

        return {
            "gems_flow": gems.to_dict(),
            "card": [0, None, 0],
            "card_booked": [1, card_properties[0], card_properties[1]],
            "nobles": 0
        }
예제 #5
0
    def __init__(self,
                 list_of_players_hands: List = None,
                 all_cards: Set[Card] = None,
                 all_nobles: Set[Noble] = None,
                 gems_on_board: GemsCollection = None) -> None:

        if all_cards is None:
            all_cards = load_all_cards()
        if all_nobles is None:
            all_nobles = load_all_nobles()
        if gems_on_board is None:
            gems_on_board = GemsCollection(INITIAL_GEMS_ON_BOARD_DICT)
        if list_of_players_hands is None:
            list_of_players_hands = [
                PlayersHand("Player A"),
                PlayersHand("Player B")
            ]

        self.list_of_players_hands = list_of_players_hands
        self.board = Board(all_cards, all_nobles, gems_on_board)

        self.active_player_id = 0  #index

        self.board.lay_cards_on_board()
        self.board.lay_nobles_on_board()
예제 #6
0
        def draw_board(self, board: Board, x_coord: int, y_coord: int,
                       state: State) -> None:
            """Draws the board, that is: cards that lie on the table, nobles that lie on the table and coins.
            Parameters:
            _ _ _ _ _ _
            board: Board to draw.
            x_coord: Horizontal coordinate (from left top corner).
            y_coord: Vertical coordinate (from left top corner).
            active_players_hand: The hand of the player that is currently active. This argument is optional and is used to
            determine which cards should be given buy or reserve buttons. If the value is None no buttons are drawn."""

            self.board_x_ccord = x_coord
            self.board_y_ccord = y_coord

            self.main_canvas.create_text(x_coord + BOARD_TITLE_POSITION_X,
                                         y_coord + BOARD_TITLE_POSITION_Y,
                                         fill=BOARD_NAME_FONT_COLOR,
                                         text=BOARD_TITLE,
                                         font=BOARD_NAME_FONT)

            # dictionary used to keep track of drawn cards
            cards_already_drawn = {row: set() for row in Row}
            for card in board.cards_on_board:
                position_x = HORIZONTAL_CARD_DISTANCE * len(
                    cards_already_drawn[card.row])
                cards_already_drawn[card.row].add(card)
                self.draw_card(
                    card, x_coord + position_x, y_coord +
                    VERTICAL_CARD_DISTANCE * POSITION_Y_DICT[card.row],
                    state.active_players_hand().can_afford_card(card),
                    state.active_players_hand().can_reserve_card(), state)

            for position_index, noble_card in enumerate(board.nobles_on_board):
                position_x = NOBLES_START_X + x_coord + HORIZONTAL_NOBLE_DISTANCE * position_index
                position_y = NOBLES_START_Y + y_coord
                self.draw_noble(noble_card, position_x, position_y)

            self.draw_gems(board.gems_on_board, x_coord + GEMS_BOARD_X,
                           y_coord + GEMS_BOARD_Y)

            if self.interactive:
                for gem_color in GemColor:
                    gem_entry = Entry(self.main_window)
                    gem_entry.place(x=x_coord +
                                    GEM_ENTRY_SHIFT * gem_color.value +
                                    GEMS_ENTRY_INITIAL_X,
                                    y=y_coord + GEMS_ENTRY_INITIAL_Y,
                                    width=GEM_ENTRY_WIDTH)
                    self.entries[gem_color] = gem_entry
                    self.drawn_buttons.add(gem_entry)
                self.set_entries(GemsCollection())
                trade_button = Button(
                    text=TRADE_BUTTON_TITLE,
                    font=TRADE_BUTTON_FONT,
                    command=lambda: self.set_action(
                        ActionTradeGems(self.read_entries())))
                trade_button.place(x=x_coord + TRADE_BUTTON_X,
                                   y=y_coord + TRADE_BUTTON_Y)
                self.drawn_buttons.add(trade_button)
예제 #7
0
 def from_dict(self, vector):
     self.name = vector['name']
     gems = vector['gems_possessed']
     self.gems_possessed = self.gems_possessed + GemsCollection(
         {
             GemColor.GOLD: gems[0],
             GemColor.RED: gems[1],
             GemColor.GREEN: gems[2],
             GemColor.BLUE: gems[3],
             GemColor.WHITE: gems[4],
             GemColor.BLACK: gems[5]
         })
예제 #8
0
def tuple_of_gems_to_gems_collection(tuple_of_gems: Tuple[GemColor]) -> GemsCollection:
    """Return a gems collection constructed from the tuple of gems:
    Parameters:
     _ _ _ _ _ _
        tuple_of_gems: Tuple of gems (with possible repetitions).

    Returns: A gems collections. Example:
    (red, red, blue, green) is transformed to GemsCollection({red:2, blue:1, green:1, white:0, black:0, gold:0})."""
    gems_dict = {gem_color: 0 for gem_color in GemColor}
    for element in tuple_of_gems:
        gems_dict[element] += 1
    return GemsCollection(gems_dict)
예제 #9
0
        def draw_gems(self, gems_collection: GemsCollection, x_coord: int,
                      y_coord: int) -> None:

            self.main_canvas.create_text(x_coord + GEMS_SUMMARY_X,
                                         y_coord + GEMS_SUMMARY_Y,
                                         text=GEMS_SUMMARY_TITLE +
                                         str(gems_collection.sum()),
                                         font=GEMS_SUMMARY_FONT)
            for gem_color in GemColor:
                self.main_canvas.create_oval(
                    x_coord + GEMS_BOARD_SHIFT * gem_color.value,
                    y_coord,
                    x_coord + GEMS_BOARD_SHIFT * gem_color.value +
                    GEM_BOARD_OVAL_SIZE,
                    y_coord + GEM_BOARD_OVAL_SIZE,
                    fill=color_dict_tkiter[gem_color])

                self.main_canvas.create_text(
                    x_coord + GEMS_BOARD_SHIFT * gem_color.value +
                    GEMS_BOARD_VALUE_SHIFT,
                    y_coord + GEMS_BOARD_VALUE_VERTICAL_SHIFT,
                    text=str(gems_collection.value(gem_color)),
                    font=GEMS_BOARD_FONT)
예제 #10
0
class PlayersHand:
    """A class that describes possessions of one player."""
    def __init__(self, name: str = "Player") -> None:
        """Creates a hand with empty gems collections, empty set of cards, nobles and reserved cards.
        Parameters:
        _ _ _ _ _ _
        name: The name of player who has this hand (optional)."""
        self.name = name
        self.gems_possessed = GemsCollection()
        self.cards_possessed = set()
        self.cards_reserved = set()
        self.nobles_possessed = set()

    def discount(self):
        """Returns gems collection that contains the sum of profits of card possessed by the players_hand."""
        discount_dict = {gem_color: 0 for gem_color in GemColor}
        for card in self.cards_possessed:
            discount_dict[card.discount_profit] += 1
        return GemsCollection(discount_dict)

    def can_afford_card(self, card: Card) -> bool:
        """Returns true if players_hand can afford card"""
        price_after_discount = card.price % self.discount()
        missing_gems = 0
        for gem_color in GemColor:
            if gem_color != GemColor.GOLD:
                missing_gems += max(
                    price_after_discount.value(gem_color) -
                    self.gems_possessed.value(gem_color), 0)
        return self.gems_possessed.value(GemColor.GOLD) >= missing_gems

    def can_reserve_card(self):
        return len(self.cards_reserved) < MAX_RESERVED_CARDS

    def number_of_my_points(self) -> int:
        return sum([card.victory_points for card in self.cards_possessed]) + \
               sum([noble.victory_points for noble in self.nobles_possessed])
예제 #11
0
 def __init__(self,
              all_cards: Set[Card],
              all_nobles: Set[Noble],
              gems_on_board: GemsCollection = GemsCollection()) -> None:
     """Creates a board and prepares the game. This method: creates the deck of cards and the deck od nobles. We do
     not shuffle deck and do not put cards and nobles on the board here.
     Parameters:
     _ _ _ _ _ _
     all_cards: A list of cards that will be added to the deck.
     all_nobles: A list of nobles that will be added to the deck.
     gems_on_board: A collection of gems that will be placed on the board at the beginning of the game."""
     self.deck = Deck(all_cards, all_nobles)
     self.gems_on_board = gems_on_board
     self.cards_on_board = set()
     self.nobles_on_board = set()
예제 #12
0
    def prepare_to_reserve(self, card, state: State):

        basic_gems_transfer = GemsCollection()
        if state.active_players_hand().gems_possessed.sum() < MAX_GEMS_ON_HAND and \
                state.board.gems_on_board.gems_dict[GemColor.GOLD] > 0:
            basic_gems_transfer.gems_dict[GemColor.GOLD] = 1
        self.set_entries(basic_gems_transfer)

        confirm_reserve_button = Button(
            text=CONFIRM_RESERVE_TITLE,
            font=CONFIRM_RESERVE_FONT,
            command=lambda: self.do_reserve(card, state))
        confirm_reserve_button.place(x=self.board_x_ccord + CONFIRM_RESERVE_X,
                                     y=self.board_y_ccord + CONFIRM_RESERVE_Y)
        self.drawn_buttons.add(confirm_reserve_button)
예제 #13
0
def generate_all_legal_trades_classic(state: State) -> List[ActionTradeGems]:
    """Returns the list of all possible actions of trade in a given current_state"""
    list_of_actions_trade = []
    n_non_empty_stacks = len(
        state.board.gems_on_board.non_empty_stacks_except_gold())
    n_gems_to_get_netto = min(
        MAX_GEMS_ON_HAND - state.active_players_hand().gems_possessed.sum(),
        MAX_GEMS_IN_ONE_MOVE, n_non_empty_stacks)

    max_gems_to_take = min(MAX_GEMS_IN_ONE_MOVE, n_non_empty_stacks)

    for n_gems_to_get in range(n_gems_to_get_netto, max_gems_to_take + 1):
        n_gems_to_return = n_gems_to_get - n_gems_to_get_netto

        # choose gems to get:
        options_of_taking = list(
            combinations(
                state.board.gems_on_board.non_empty_stacks_except_gold(),
                n_gems_to_get))
        for option_of_taking in options_of_taking:
            # now we have chosen which gems to take, so we need to decide which to return
            gem_colors_not_taken = {
                gem_color
                for gem_color in GemColor if gem_color not in option_of_taking
            }
            # find gems collection to take:
            gems_to_take = tuple_of_gems_to_gems_collection(option_of_taking)
            # find possible options of returning gems:
            options_of_returning = list(
                combinations_with_replacement(gem_colors_not_taken,
                                              n_gems_to_return))
            for option_of_returning in options_of_returning:
                # now we create gem collection describing transfer and check if it satisfies conditions of legal trade
                gems_to_return = tuple_of_gems_to_gems_collection(
                    option_of_returning)

                gems_collection_to_trade = gems_to_take - gems_to_return
                # check if there is enough gems on the board to take:
                condition_1 = state.board.gems_on_board >= gems_collection_to_trade
                # check if the player has enough gems to return:
                condition_2 = state.active_players_hand(
                ).gems_possessed >= -gems_collection_to_trade
                condition3 = gems_collection_to_trade != GemsCollection()
                if condition_1 and condition_2 and condition3:
                    list_of_actions_trade.append(
                        ActionTradeGems(gems_collection_to_trade))

    return list_of_actions_trade
예제 #14
0
def load_all_nobles(file: str = NOBLES_DATABASE_FILE) -> Set[Noble]:
    """Loads information about nobles from file and returns a set of cards."""
    set_of_nobles = set()
    nobles_database_file = open(file)
    reader = csv.reader(nobles_database_file)
    _ = next(reader, None)
    noble_id = 100
    for row in reader:
        price = GemsCollection({GemColor.BLACK: int(row[1]), GemColor.WHITE: int(row[2]), GemColor.RED: int(row[3]),
                                GemColor.BLUE: int(row[4]), GemColor.GREEN: int(row[5]), GemColor.GOLD: 0})
        new_noble = Noble(row[0], noble_id, price, int(row[6]))
        set_of_nobles.add(new_noble)
        id_to_noble_dict[noble_id] = new_noble
        name_to_noble_dict[new_noble.name] = new_noble
        noble_id += 1
    return set_of_nobles
예제 #15
0
def load_all_cards(file: str = CARDS_DATABASE_FILE) -> Set[Card]:
    """Loads information about cards from file and returns a set of cards."""
    set_of_cards = set()
    cards_database_file = open(file)
    reader = csv.reader(cards_database_file)
    _ = next(reader, None)
    card_id = 0
    for row in reader:
        price = GemsCollection({GemColor.BLACK: int(row[2]), GemColor.WHITE: int(row[3]), GemColor.RED: int(row[4]),
                                GemColor.BLUE: int(row[5]), GemColor.GREEN: int(row[6]), GemColor.GOLD: 0})
        card = Card(row[0], card_id, str_to_row[row[1]], price, str_to_color[row[7]], int(row[8]))
        set_of_cards.add(card)
        id_to_card_dict[card_id] = card
        name_to_card_dict[card.name] = card
        card_id += 1
    return set_of_cards
예제 #16
0
    def from_dict(self, vector):
        """Take player's gems from the board. """

        gems = vector['board']['gems_on_board']
        self.gems_on_board = GemsCollection({
            GemColor.GOLD: gems[0],
            GemColor.RED: gems[1],
            GemColor.GREEN: gems[2],
            GemColor.BLUE: gems[3],
            GemColor.WHITE: gems[4],
            GemColor.BLACK: gems[5]
        })
        """Puts cards on the board according to previous current_state. """
        cards = vector['board']['cards_on_board']
        drawn_cards = map(lambda x: self.deck.pop_cards_from_id_list(cards, x),
                          self.deck.decks_dict.keys())
        self.cards_on_board = set(reduce(lambda x, y: x + y, drawn_cards))
예제 #17
0
    def prepare_to_buy(self, card: Card, state: State):

        price_after_discount = card.price % state.active_players_hand(
        ).discount()
        min_gold = (price_after_discount %
                    state.active_players_hand().gems_possessed).sum()
        min_gold_price = GemsCollection({
            gem_color:
            min(price_after_discount.value(gem_color),
                state.active_players_hand().gems_possessed.value(gem_color))
            for gem_color in GemColor
        })
        min_gold_price.gems_dict[GemColor.GOLD] = min_gold
        self.set_entries(min_gold_price)

        confirm_buy_button = Button(text=CONFIRM_BUY_TITLE,
                                    font=CONFIRM_BUY_FONT,
                                    command=lambda: self.do_buy(card, state))
        confirm_buy_button.place(x=self.board_x_ccord + CONFIRM_BUY_X,
                                 y=self.board_y_ccord + CONFIRM_BUY_Y)
        self.drawn_buttons.add(confirm_buy_button)
        neptune.stop()
        if output_weights_file_name is not None:
            self.network.save_weights(output_weights_file_name)
        return fit_history

    def load_weights(self, weights_file):
        assert self.network is not None, 'You must create network before loading weights.'
        self.set_corrent_session()
        self.network.load_weights(weights_file)

    def save_weights(self, output_weights_file_name):
        self.set_corrent_session()
        self.network.save_weights(output_weights_file_name)

    def get_value(self, state_as_dict: StateAsDict) -> float:
        assert self.network is not None, 'You must create network first.'
        self.set_corrent_session()
        vector_of_state = self.vectorize_state(state_as_dict)
        input_vec = np.array(vector_of_state)
        return self.network.predict(x=input_vec.reshape(1, 498))[0][0]

    def get_value_of_vector(self, vector_of_state)->float:
        assert self.network is not None, 'You must create network first.'
        self.set_corrent_session()
        return self.network.predict(x=vector_of_state.reshape(1, 498))[0][0]

x = EmbeddingAveragePool_v0()
ddd = {GemColor.RED: 0, GemColor.GREEN : 1, GemColor.BLUE:2, GemColor.WHITE:3, GemColor.BLACK:7, GemColor.GOLD:0}
f = Card('R19', 10, Row.CHEAP, GemsCollection(gems_values_dict=ddd), discount_profit=GemColor.GREEN, victory_points=2)
b = x.card_to_vector(f)
print(len(b))
예제 #19
0
 def vectorize(self):
     gems = GemsCollection()
     gems.gems_dict[GemColor.GOLD] += 1
     gems[self.return_gem_color] -= 1
     return gems.vectorize(), self.card.vectorize()
예제 #20
0
 def set_entries(self, gems_collection: GemsCollection) -> None:
     for gem_color in GemColor:
         self.entries[gem_color].delete(0, END)
         self.entries[gem_color].insert(
             0, gems_collection.value(gem_color))
예제 #21
0
 def read_entries(self) -> GemsCollection:
     return GemsCollection({
         gem_color: int(self.entries[gem_color].get())
         for gem_color in GemColor
     })
예제 #22
0
 def discount(self):
     """Returns gems collection that contains the sum of profits of card possessed by the players_hand."""
     discount_dict = {gem_color: 0 for gem_color in GemColor}
     for card in self.cards_possessed:
         discount_dict[card.discount_profit] += 1
     return GemsCollection(discount_dict)
예제 #23
0
class PlayersHand:
    """A class that describes possessions of one player."""
    def __init__(self, name: str = "Player") -> None:
        """Creates a hand with empty gems collections, empty set of cards, nobles and reserved cards.
        Parameters:
        _ _ _ _ _ _
        name: The name of player who has this hand (optional)."""
        self.name = name
        self.gems_possessed = GemsCollection()
        self.cards_possessed = set()
        self.cards_reserved = set()
        self.nobles_possessed = set()

    def discount(self):
        """Returns gems collection that contains the sum of profits of card possessed by the players_hand."""
        discount_dict = {gem_color: 0 for gem_color in GemColor}
        for card in self.cards_possessed:
            discount_dict[card.discount_profit] += 1
        return GemsCollection(discount_dict)

    def can_afford_card(self,
                        card: Card,
                        discount: GemsCollection = None) -> bool:
        """Returns true if players_hand can afford card"""
        if discount is None:
            discount = self.discount()
        price_after_discount = card.price % discount
        trade = [
            a - b for a, b in zip(price_after_discount.to_dict(),
                                  self.gems_possessed.to_dict())
        ]
        return sum([max(a, 0) for a in trade[1:6]]) <= -trade[0]

    def min_gold_needed_to_buy_card(self, card: Card) -> int:
        price_after_discount = card.price % self.discount()
        missing_gems = 0
        for gem_color in GemColor:
            if gem_color != GemColor.GOLD:
                missing_gems += max(
                    price_after_discount.value(gem_color) -
                    self.gems_possessed.value(gem_color), 0)
        return missing_gems

    def can_reserve_card(self):
        return len(self.cards_reserved) < MAX_RESERVED_CARDS

    def number_of_my_points(self) -> int:
        return sum([
            card.victory_points for card in self.cards_possessed
        ]) + sum([noble.victory_points for noble in self.nobles_possessed])

    def to_dict(self):
        return {
            'noble_possessed_ids':
            {x.to_dict()
             for x in self.nobles_possessed},
            'cards_possessed_ids': {x.to_dict()
                                    for x in self.cards_possessed},
            'cards_reserved_ids': {x.to_dict()
                                   for x in self.cards_reserved},
            'gems_possessed': self.gems_possessed.to_dict(),
            'name': self.name
        }

    def from_dict(self, vector):
        self.name = vector['name']
        gems = vector['gems_possessed']
        self.gems_possessed = self.gems_possessed + GemsCollection(
            {
                GemColor.GOLD: gems[0],
                GemColor.RED: gems[1],
                GemColor.GREEN: gems[2],
                GemColor.BLUE: gems[3],
                GemColor.WHITE: gems[4],
                GemColor.BLACK: gems[5]
            })