class GolfGame: def __init__(self, num_rounds_per_episode=10): self.deck = Deck() self.reset() self.rounds_per_episode = num_rounds_per_episode def reset(self): self.round = -1 self.new_hand() return self._get_state() def new_hand(self): self.deck.shuffle() self.hand = self.deck.draw_n(6) self.top_card = self.deck.draw() self.mask = [0, 0, 0, 0, 0, 0] flip = sample(range(0, 5), 2) self.mask[flip[0]] = 1 self.mask[flip[1]] = 1 self.round += 1 def step(self, action): initial_score = self._get_hand_score() # Make sure we dont run out of cards if len(self.deck.deck) == 0: self.deck.shuffle() if action == 0: # Put card back self.top_card = self.deck.draw() else: # Replace card self.hand[action - 1] = self.top_card self.mask[action - 1] = 1 next_state = self._get_state() reward = initial_score - self._get_hand_score() if all(self.mask): # Every card is flipped over, restart self.new_hand() done = (self.round >= self.rounds_per_episode) return next_state, reward, done def _get_state(self): state = [self.top_card.value[1]] for i, card in enumerate(self.hand): if self.mask[i]: state.append(card.value[1]) else: state.append(-1) return np.array(state) def _get_hand_score(self): hand_score = 0 if not self.hand: return None for column in range(3): card1 = self.hand[column] card2 = self.hand[3 + column] if card1 != card2 and card1 != Card.Joker and card2 != Card.Joker: hand_score += card1.value[0] + card2.value[0] return hand_score
class Game: def __init__(self, players=None, num_rounds=9, verbose=True): if not players: players = [('AI1', PlayerType.Computer), ('AI1', PlayerType.Computer)] self.verbose = verbose self.players = [] for player in players: name, type_ = player self.players.append(Player(name, type_)) self.round = 1 self.num_rounds = num_rounds self.deck = Deck() self.top = None self.first_player = 0 def run(self): while self.round <= self.num_rounds: if self.verbose: print('Round {}\n'.format(self.round)) self._new_round() # Flip over initial cards for player in self.players: player.flip_cards() player.display_hand() # Go around the table until someone flips all of their cards over current_player = self.first_player playing = True while playing: if self.verbose: print('{}\'s Turn'.format( self.players[current_player].name)) self.top = self.players[current_player].move( self.deck, self.top, self.verbose) if self.players[current_player].is_done(): playing = False current_player = (current_player + 1) % len(self.players) # When round is over, add hand score to player scores and increment starting player for player in self.players: player.score += player.get_hand_score() self.first_player = (self.first_player + 1) % len(self.players) self.round += 1 lowest_score = 10000 winner = '' if self.verbose: print('Final Hands: ') for player in self.players: player.mask = [1, 1, 1, 1, 1, 1] if self.verbose: print('Player: {}'.format(player.name)) player.display_hand() if self.verbose: print('Final Scores:') avg_score = 0 for player in self.players: if self.verbose: print('\t {}: {}'.format(player.name, player.score)) avg_score += player.score if player.score < lowest_score: winner = player.name lowest_score = player.score elif player.score == lowest_score: winner += ' and ' + player.name if self.verbose: print('The winner is... {}!'.format(winner)) avg_score /= (len(self.players) * self.num_rounds) return avg_score def _new_round(self): self.deck.shuffle() for player in self.players: player.new_hand(self.deck.draw_n(6)) self.top = self.deck.draw()