From 9f5178268ea5bb094d40a963d9a0a378c4bb9aef Mon Sep 17 00:00:00 2001 From: En Yi Date: Fri, 14 Jun 2019 18:48:50 +0100 Subject: [PATCH] Finish up Vbot play --- ai_comp/ai.py | 55 +++++++++++++++++++++++++++++++++++--- main.py | 3 +++ seeds/Vbot_good_hand.rng | Bin 0 -> 3784 bytes seeds/Vbot_good_hand2.rng | Bin 0 -> 3758 bytes table.py | 20 +++++++++----- 5 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 seeds/Vbot_good_hand.rng create mode 100644 seeds/Vbot_good_hand2.rng diff --git a/ai_comp/ai.py b/ai_comp/ai.py index 56359c1..14a9e16 100644 --- a/ai_comp/ai.py +++ b/ai_comp/ai.py @@ -175,7 +175,7 @@ class VivianAI(RandomAI): suit_values.append(sum([num for suit, num in zip(card_suits, card_nums) if suit == i+1])) min_val = min(suit_values) - weakest_suit = [i + 1 for i, val in enumerate(suit_values) if suit_values == min_val] + weakest_suit = [i + 1 for i, val in enumerate(suit_values) if val == min_val] if len(weakest_suit) > 1: weakest_suit = random.choice(weakest_suit) else: @@ -184,9 +184,9 @@ class VivianAI(RandomAI): all_nums = [i+2 for i in range(13)] weak_nums = [num for suit, num in zip(card_suits, card_nums) if suit == weakest_suit] [all_nums.remove(num) for num in weak_nums] - return weakest_suit*100 + max(weak_nums) + return weakest_suit*100 + max(all_nums) - def make_an_play(self, sub_state): + def make_a_play(self, sub_state): """ :param sub_state: @@ -200,7 +200,54 @@ class VivianAI(RandomAI): else: valid_plays = self.get_valid_plays(False) - card_viability = [0] * len(valid_plays) + n_cards = len(valid_plays) + card_viability = [1] * n_cards + card_nums = [cards.get_card_number(play) for play in valid_plays] + card_suits = [cards.get_card_suit(play) for play in valid_plays] + high_cards = [max(card_set) if card_set else 0 for card_set in self.unplayed_cards] + + suit_counts = [0] * 4 + for i in range(4): + suit_counts[i] = card_suits.count(i+1) + + non_empty_suits = [i+1 for i, count in enumerate(suit_counts) if count] + suit_counts = [count for count in suit_counts if count] + + min_suit_count = min(suit_counts) + low_suits = [suit for suit, counts in zip(non_empty_suits, suit_counts) if counts == min_suit_count] + + for i in range(n_cards): + card_viability[i] += any([card_suits[i] == s for s in low_suits]) / min_suit_count + + # Leading-specific viability + if sub_state == 0: + for i in range(n_cards): + card_viability[i] += any([valid_plays[i] == card for card in high_cards]) * 1.2 + else: + played_cards = [card.value if card else None for card in self.table_status["played cards"]] + played_nums = [cards.get_card_number(card) if card else 0 for card in played_cards] + played_suits = [cards.get_card_suit(card) if card else 0 for card in played_cards] + + trumped = any([suit == self.table_status['trump suit'] for suit in played_suits]) + max_played_num = max(played_nums) + max_trump_played = [num for suit, num in zip(played_suits, played_nums) + if suit == self.table_status['trump suit']] + if max_trump_played: + max_trump_played = max(max_trump_played) + else: + max_trump_played = 1 + + for i in range(n_cards): + if trumped and card_suits[i] != self.table_status['trump suit']: + card_viability[i] *= card_nums[i]/7 + card_viability[i] += (card_nums[i] < max_played_num) / card_nums[i] + if card_suits[i] == self.table_status['trump suit'] and\ + card_nums[i]>max_trump_played : + card_viability[i] *= 2 / card_nums[i] + + best_viability = max(card_viability) + best_cards = [play for viability, play in zip(card_viability, valid_plays) if viability == best_viability] + return random.choice(best_cards) def update_memory(self): played_cards = [card.value for card in self.table_status["played cards"]] diff --git a/main.py b/main.py index b018873..ca883dd 100644 --- a/main.py +++ b/main.py @@ -101,6 +101,9 @@ if __name__ == '__main__': with open('last_game_rng.rng', 'wb') as f: pickle.dump(rng_state, f) + #with open('seeds/Vbot_good_hand2.rng', 'rb') as f: + # rng_state = pickle.load(f) + #random.setstate(rng_state) main_view = GameScreen(900, 600, clear_colour=(255, 0, 0), autoplay=True, view_all_cards=VIEW_ALL_CARDS) diff --git a/seeds/Vbot_good_hand.rng b/seeds/Vbot_good_hand.rng new file mode 100644 index 0000000000000000000000000000000000000000..ad47a7e7abdf3d0151b42b350f72cc4a805828fc GIT binary patch literal 3784 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 E4|oRmCIA2c literal 0 HcmV?d00001 diff --git a/seeds/Vbot_good_hand2.rng b/seeds/Vbot_good_hand2.rng new file mode 100644 index 0000000000000000000000000000000000000000..c1c5fef52472ddb4f11ff0c78da6a43b5c65295a GIT binary patch literal 3758 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 literal 0 HcmV?d00001 diff --git a/table.py b/table.py index 1c88b01..c88ec6c 100644 --- a/table.py +++ b/table.py @@ -599,16 +599,16 @@ class Table: card_nums = [card.number() for card in self.table_status["played cards"]] follow_suits = [suit == leading_card.suit() for suit in card_suits] trumps = [suit == self.table_status['trump suit'] for suit in card_suits] - trump_played = any(trumps) + #trump_played = any(trumps) # Break trump if the trump suit is played - if not self.table_status['trump broken']: - if trump_played: - self.table_status['trump broken'] = True - self.write_message("Trump Broken!", delay_time=1) + #if not self.table_status['trump broken']: + # if trump_played: + # self.table_status['trump broken'] = True + # self.write_message("Trump Broken!", delay_time=1) # Determine which players to check for winner, and determine winner - valid_nums = [card_nums[i] * ((follow_suits[i] and not trump_played) or trumps[i]) + valid_nums = [card_nums[i] * ((follow_suits[i] and not self.table_status['trump broken']) or trumps[i]) for i in range(NUM_OF_PLAYERS)] winning_player = valid_nums.index(max(valid_nums)) self.write_message("Player {0:d} wins!\n".format(winning_player), delay_time=1) @@ -636,6 +636,14 @@ class Table: self.update_table.emit() return + # Break trump if the trump suit is played + if not self.table_status['trump broken']: + trump_played = card.suit() == self.table_status['trump suit'] + if trump_played: + self.table_status['trump broken'] = True + self.write_message("Trump Broken!", delay_time=1.5) + + if not self.table_status['partner reveal']: if card.value == self.table_status['partner']: self.table_status['partner reveal'] = True