def __init__(self): oneMonte_threeNaive_anon = [ Player("AI 1 ", PlayerTypes.NaiveMinAI, self), Player("AI 2 ", PlayerTypes.MonteCarloAI, self), Player("AI 3 ", PlayerTypes.NaiveMinAI, self), Player("AI 4 ", PlayerTypes.NaiveMaxAI, self) ] thePlayers = oneMonte_threeNaive_anon #Shake up the order random.shuffle(thePlayers) self.players = thePlayers self.allTricks = [] self.currentTrick = Trick() self.trickWinner = -1 self.cardsPlayed = () #keep track of state in a tuple temp = dict.fromkeys(thePlayers) for key in temp: temp[key] = [] self.cardsPlayedbyPlayer = temp self.shift = 0 self.winningPlayer = None self.winningPlayers = None self.humanExists = False self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 #self.passes = [1, -1, 2, 0] # left, right, across, no pass self.heartsBroken = False self.losingPlayer = None
def __init__(self): self.round_num = 0 self.trick_num = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick(self.trick_num) self.trickWinner = -1 self.hearts_broken = False self.losingPlayer = None self.passingCards = [[], [], [], []] self.scoreboard = [0, 0, 0, 0] self.verbose = False ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' self.players = [ PolicyNN("Jason"), SimpleAI("Jack"), SimpleAI("Sam"), SimpleAI("JB") ] self.newRound()
def __init__(self, players): self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick() self.trickWinner = -1 self.heartsBroken = False self.losingPlayer = None self.passingCards = [[], [], [], []] # Make four players self.players = players #self.players = [QLearningBoi("Dani"), AutoPlayer("Desmond"), AutoPlayer("Ben"), AutoPlayer("Tyler")] ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' # Generate a full deck of cards and shuffle it self.newRound()
def evaluateTrick(self): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) self.printCurrentTrick() print p.name + " won the trick." # print 'Making new trick' self.currentTrick = Trick() print self.currentTrick.suit
def evaluateTrick(self, printOut=True): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) self.printCurrentTrick() if printOut: print(f"{p.name} won the trick.") # print 'Making new trick' self.currentTrick = Trick() if printOut: print(self.currentTrick.suit)
def evaluateTrick(self): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) for p in self.players: if p.name == "Maddox": p.eval(self) self.printCurrentTrick() # print p.name + " won the trick." # print 'Making new trick' self.currentTrick = Trick()
def newRound(self): self.deck = Deck() self.deck.shuffle() self.roundNum += 1 self.trickNum = 0 self.trickWinner = -1 self.heartsBroken = False self.dealer = (self.dealer + 1) % len(self.players) self.dealCards() self.currentTrick = Trick() self.passingCards = [[], [], [], []] for p in self.players: p.discardTricks()
def play_game_trick(game_state) -> Gamestate: trick = Trick() # Whose turn it is can start the trick for _ in game_state.players: card = game_state.players[game_state.current_turn].spielt_Karte(trick) # When called ace is played, everyone knows the teams if card.farbe == game_state.called_ace and card.schlag == "Ass": game_state.teams['ist_spieler'].append(game_state.current_turn) for player in game_state.players.values(): if player.number not in game_state.teams['ist_spieler']: game_state.teams['nicht_spieler'].append(player.number) trick.Karte_reinlegen(card, game_state.players[game_state.current_turn]) game_state.current_trick = trick next_turn(game_state=game_state) # Update process_data game_state.played_tricks[len(game_state.played_tricks)] = trick if trick.winner() in game_state.teams['ist_spieler']: game_state.points['ist_spieler'] += trick.get_punkte() else: game_state.points['nicht_spieler'] += trick.get_punkte() print(trick) # Points for the winner trick.winner().stiche.append(trick) return game_state
def main(): hearts = Hearts() hearts.verbose = True # play until someone loses while hearts.losingPlayer is None or hearts.losingPlayer.score < maxScore: print("====================Round " + str(hearts.round_num) + "====================") while hearts.trick_num < totalTricks: if hearts.trick_num == 0: hearts.playersPassCards() hearts.getFirstTrickStarter() hearts.playTrick(hearts.trickWinner) hearts.currentTrick = Trick(hearts.trick_num) # tally scores hearts.handleScoring() print() # new round if no one has lost if (hearts.losingPlayer.score < maxScore): hearts.newRound() print() # spacing winners = hearts.getWinner() winnerString = "" for w in winners: winnerString += w.name + " " print(winnerString + "wins!")
def reset(self): self.round_num = 0 self.trick_num = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick(self.trick_num) self.trickWinner = -1 self.hearts_broken = False self.losingPlayer = None self.passingCards = [[], [], [], []] self.scoreboard = [0, 0, 0, 0] for a_player in self.players: a_player.reset() self.newRound()
def start(self): """ Start and run the game """ self.determine_dealer() self.deal() self.show_flip() #while self.score[0] < 10 and self.score[1] < 10: Trick(self.flip, self.dealer, self.players, self.position).start()
def __init__(self): self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick() self.trickWinner = -1 self.heartsBroken = False self.losingPlayer = None self.passingCards = [[], [], [], []] # Make four players self.players = [Player("Danny"), Player("Desmond"), Player("Ben"), Player("Tyler")] ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' # Generate a full deck of cards and shuffle it self.newRound()
def newSimRound(self, rollout): rollout.deck = Deck() rollout.deck.shuffle() rollout.roundNum += 1 rollout.trickNum = 0 rollout.trickWinner = -1 rollout.heartsBroken = False rollout.dealer = (self.dealer + 1) % len(self.players) rollout.dealCards(rollout) rollout.currentTrick = Trick() for p in rollout.players: p.discardTricks()
def __init__(self, felicity, maddox): self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick() self.trickWinner = -1 self.heartsBroken = False self.losingPlayer = None self.passingCards = [[], [], [], []] # Make four players self.players = [felicity, maddox, Dumb("Dumb"), Dumb("Dumber")] #initialize Felicity self.players[0].hand = Hand() self.players[0].score = 0 self.players[0].roundScore = 0 self.players[0].tricksWon = [] #initialize Maddox self.players[1].hand = Hand() self.players[1].score = 0 self.players[1].roundScore = 0 self.players[1].tricksWon = [] ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' # Generate a full deck of cards and shuffle it self.newRound()
def nextTrick(self): currentTrick = Trick() if Card.trumpSuit == 4: print("=== NEW TRICK (!" + Card.VALUES[Player.players[self.boss].level] + ")===") else: print("=== NEW TRICK (" + Card.SUITS[Card.trumpSuit] + Card.VALUES[Player.players[self.boss].level] + ")===") for i in Player.players: print("Player " + str(i.id) + ": " + str(self.playerPoints[i.id]) + " points") for i in range(Round.NUM_PLAYERS): if len(self.tricks) == 0: playerID = (i + self.boss) % Round.NUM_PLAYERS else: playerID = (i + self.tricks[len(self.tricks) - 1].getWinner()) % Round.NUM_PLAYERS self.updateDisplay(Player.players[playerID]) self.playCards(Player.players[playerID], currentTrick) self.updatePoints(currentTrick.getWinner(), currentTrick.getPoints()) print("Player " + str(currentTrick.getWinner()) + " wins trick and earns " + str(currentTrick.getPoints()) + " points!") return currentTrick
class Hearts: def __init__(self, felicity, maddox): self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick() self.trickWinner = -1 self.heartsBroken = False self.losingPlayer = None self.passingCards = [[], [], [], []] # Make four players self.players = [felicity, maddox, Dumb("Dumb"), Dumb("Dumber")] #initialize Felicity self.players[0].hand = Hand() self.players[0].score = 0 self.players[0].roundScore = 0 self.players[0].tricksWon = [] #initialize Maddox self.players[1].hand = Hand() self.players[1].score = 0 self.players[1].roundScore = 0 self.players[1].tricksWon = [] ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' # Generate a full deck of cards and shuffle it self.newRound() def handleScoring(self): p, highestScore = None, 0 # print "\nScores:\n" for player in self.players: # print(player.name + ": " + str(player.score)) if player.score > highestScore: p = player highestScore = player.score self.losingPlayer = p def newRound(self): self.deck = Deck() self.deck.shuffle() self.roundNum += 1 self.trickNum = 0 self.trickWinner = -1 self.heartsBroken = False self.dealer = (self.dealer + 1) % len(self.players) self.dealCards() self.currentTrick = Trick() self.passingCards = [[], [], [], []] for p in self.players: p.discardTricks() print(p.roundScore) def getFirstTrickStarter(self): for i,p in enumerate(self.players): if p.hand.contains2ofclubs: self.trickWinner = i def dealCards(self): i = 0 while(self.deck.size() > 0): self.players[i % len(self.players)].addCard(self.deck.deal()) i += 1 def evaluateTrick(self): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) for p in self.players: if p.name == "Maddox": p.eval(self) self.printCurrentTrick() # print p.name + " won the trick." # print 'Making new trick' self.currentTrick = Trick() # print self.currentTrick.suit def roundScore(self): for p in self.players: if (p.roundScore == 26): self.shootTheMoon(p) else: p.score += p.roundScore # if p.name == "Maddox": # p.eval(self) def shootTheMoon(self, player): if (auto): r = randint(0,1) if r: for p in self.players: if (p != player): p.add26() else: player.subtract26() else: inp = raw_input(self.name + ", do you want to add or subtract") if (inp == "add"): for p in self.players: if (p != player): p.add26() else: player.subtract26() def passCards(self, index): # print self.printPassingCards() passTo = self.passes[self.trickNum] # how far to pass cards passTo = (index + passTo) % len(self.players) # the index to which cards are passed while len(self.passingCards[passTo]) < cardsToPass: # pass three cards passCard = None while passCard is None: # make sure string passed is valid passCard = self.players[index].play(option='pass', auto=auto, state=self) if passCard is not None: # remove card from player hand and add to passed cards self.passingCards[passTo].append(passCard) self.players[index].removeCard(passCard) def distributePassedCards(self): for i,passed in enumerate(self.passingCards): for card in passed: self.players[i].addCard(card) self.passingCards = [[], [], [], []] def printPassingCards(self): out = "[ " for passed in self.passingCards: out += "[" for card in passed: out += card.__str__() + " " out += "] " out += " ]" return out def playersPassCards(self): self.printPlayers() if not self.trickNum % 4 == 3: # don't pass every fourth hand for i in range(0, len(self.players)): # print # spacing self.printPlayer(i) self.passCards(i % len(self.players)) self.distributePassedCards() self.printPlayers() def playTrick(self, start): shift = 0 if self.trickNum == 0: startPlayer = self.players[start] addCard = startPlayer.play(option="play", c='2c', state=self) startPlayer.removeCard(addCard) self.currentTrick.addCard(addCard, start) shift = 1 # alert game that first player has already played # have each player take their turn for i in range(start + shift, start + len(self.players)): self.printCurrentTrick() curPlayerIndex = i % len(self.players) self.printPlayer(curPlayerIndex) curPlayer = self.players[curPlayerIndex] addCard = None while addCard is None: # wait until a valid card is passed addCard = curPlayer.play(auto=auto, state=self) # change auto to False to play manually # the rules for what cards can be played # card set to None if it is found to be invalid if addCard is not None: # if it is not the first trick and no cards have been played, # set the first card played as the trick suit if it is not a heart # or if hearts have been broken if self.trickNum != 0 and self.currentTrick.cardsInTrick == 0: if addCard.suit == Suit(hearts) and not self.heartsBroken: # if player only has hearts but hearts have not been broken, # player can play hearts if not curPlayer.hasOnlyHearts(): # print curPlayer.hasOnlyHearts() # print curPlayer.hand.__str__() # print "Hearts have not been broken." addCard = None else: self.currentTrick.setTrickSuit(addCard) else: self.currentTrick.setTrickSuit(addCard) # player tries to play off suit but has trick suit if addCard is not None and addCard.suit != self.currentTrick.suit: if curPlayer.hasSuit(self.currentTrick.suit): #print "Must play the suit of the current trick." addCard = None elif addCard.suit == Suit(hearts): self.heartsBroken = True if self.trickNum == 0: if addCard is not None: if addCard.suit == Suit(hearts): #print "Hearts cannot be broken on the first hand." self.heartsBroken = False addCard = None elif addCard.suit == Suit(spades) and addCard.rank == Rank(queen): # print "The queen of spades cannot be played on the first hand." addCard = None if addCard is not None and self.currentTrick.suit == Suit(noSuit): if addCard.suit == Suit(hearts) and not self.heartsBroken: # print "Hearts not yet broken." addCard = None if addCard is not None: if addCard == Card(queen, spades): self.heartsBroken = True curPlayer.removeCard(addCard) self.currentTrick.addCard(addCard, curPlayerIndex) self.evaluateTrick() self.trickNum += 1 # print player's hand def printPlayer(self, i): p = self.players[i] # print p.name + "'s hand: " + str(p.hand) # print all players' hands def printPlayers(self): pass # for p in self.players: # # print p.name + ": " + str(p.hand) # show cards played in current trick def printCurrentTrick(self): trickStr = '\nCurrent table:\n' trickStr += "Trick suit: " + self.currentTrick.suit.__str__() + "\n" for i, card in enumerate(self.currentTrick.trick): if self.currentTrick.trick[i] is not 0: trickStr += self.players[i].name + ": " + str(card) + "\n" else: trickStr += self.players[i].name + ": None\n" # print trickStr def getWinner(self): minScore = 200 # impossibly high winner = None for p in self.players: if p.score < minScore: winner = p minScore = p.score return winner
def main(): trainer = Hearts_env_policy() tot_wins = 0 tot_loss = 0 last200Wins = [] last200Loss = [] jason_wins = 0 sam_wins = 0 jb_wins = 0 jason_loss = 0 sam_loss = 0 jb_loss = 0 current_odds = .5 trainer.hearts_game = Hearts() record_final_score = [] for i in range(epochs): # play until someone loses while trainer.hearts_game.losingPlayer is None or trainer.hearts_game.losingPlayer.score < max_score: while trainer.hearts_game.trick_num < total_tricks: # print("Round: ", trainer.hearts_game.trick_num) if trainer.hearts_game.trick_num == 0: trainer.hearts_game.playersPassCards() trainer.hearts_game.getFirstTrickStarter() # print(trainer.hearts_game.players[1].hand) previous_scores = [ pl.currentScore for pl in trainer.hearts_game.players ] trainer.hearts_game.playTrick(trainer.hearts_game.trickWinner) # add reward to the model for this timestep for j, a_palyer in enumerate(trainer.hearts_game.players): q_reward = trainer.get_reward(j, previous_scores) a_palyer.store_reward(q_reward) trainer.hearts_game.currentTrick = Trick( trainer.hearts_game.trick_num) # tally scores trainer.hearts_game.handleScoring() #Learn based off the past round trainer.hearts_game.players[1].play_policy.learn() # new round if no one has lost if trainer.hearts_game.losingPlayer.score < max_score: trainer.hearts_game.newRound() # Record Jack's final score record_final_score.append(trainer.hearts_game.players[1].score) winners = trainer.hearts_game.getWinner() winnerString = "" for w in winners: winnerString += w.name + " " if len(last200Wins) == 200: last200Wins.pop(0) if w.name == "Jack": tot_wins += 1 last200Wins.append(1) else: last200Wins.append(0) if w.name == "Jason": jason_wins += 1 if w.name == "Sam": sam_wins += 1 if w.name == "JB": jb_wins += 1 if i % 25 == 0: print() for a, player in enumerate(trainer.hearts_game.players): print(player.name + ": " + str(player.score)) print(winnerString + "wins!") print("--------------------------------------") print("Jack last 200 games wins: ", np.sum(last200Wins)) print("Jack wins: ", tot_wins) print("Jason wins: ", jason_wins) print("Sam wins: ", sam_wins) print("JB wins: ", jb_wins) print("num games: ", i) losers = trainer.hearts_game.getLosers() losersString = "" if len(last200Loss) == 200: last200Loss.pop(0) if 'Jack' in [l.name for l in losers]: last200Loss.append(1) else: last200Loss.append(0) for w in losers: losersString += w.name + " " if w.name == "Jack": tot_loss += 1 if w.name == "Jason": jason_loss += 1 if w.name == "Sam": sam_loss += 1 if w.name == "JB": jb_loss += 1 if i % 25 == 0: print("\n") for a, player in enumerate(trainer.hearts_game.players): print(player.name + ": " + str(player.score)) print(losersString + "lose.") print("--------------------------------------") print("Jack last 200 games losses: %d (%.2f%%)" % (np.sum(last200Loss), 100 * np.sum(last200Loss) / len(last200Loss))) print(" Average final score: %.2f" % (np.sum(record_final_score[-200:]) / len(record_final_score[-200:]))) print("Jack losses: ", tot_loss) print("Jason losses: ", jason_loss) print("Sam losses: ", sam_loss) print("JB losses: ", jb_loss) print("num games: ", i) if i % 50 == 0: for player in trainer.hearts_game.players: try: player.play_policy.save_model() except Exception as E: pass trainer.hearts_game.reset() plot_records(record_final_score, "Final score") jack = [pl for pl in trainer.hearts_game.players if pl.name == "Jack"][0] plot_records(jack.play_policy.loss_actor, "Loss Actor") plot_records(np.log(jack.play_policy.loss_critic), "Log-loss Critic")
def main(): trainer = Hearts_env_policy() player0_win = np.array([]) player1_win = np.array([]) player2_win = np.array([]) player3_win = np.array([]) player0_scores = np.array([]) player1_scores = np.array([]) player2_scores = np.array([]) player3_scores = np.array([]) num_hands = 0 if play_self: policy1 = PolicyNN("Sam") models = policy1.play_policy.policy, policy1.play_policy.predict policy2 = PolicyNN("Jack", models=models) policy3 = PolicyNN("Jason", models=models) policy4 = PolicyNN("JB", models=models) trainer.hearts_game.players = [policy1, policy2, policy3, policy4] trainer.hearts_game.reset() for i in range(epochs): # play until someone loses while trainer.hearts_game.losingPlayer is None or trainer.hearts_game.losingPlayer.score < max_score: while trainer.hearts_game.trick_num < total_tricks: if trainer.hearts_game.trick_num == 0: trainer.hearts_game.playersPassCards() trainer.hearts_game.getFirstTrickStarter() trainer.hearts_game.playTrick(trainer.hearts_game.trickWinner) # add reward to the model for this timestep for j, a_player in enumerate(trainer.hearts_game.players): # reward = trainer.get_reward(j) # reward = trainer.get_reward_simple(j) reward = trainer.get_reward_simple_v2(j) a_player.store_reward(reward) trainer.hearts_game.currentTrick = Trick(trainer.hearts_game.trick_num) # tally scores trainer.hearts_game.handleScoring() # Learn based off the past round if train: num_hands += 1 if num_hands == batch_size: for j, player in enumerate(trainer.hearts_game.players): if type(player) is PolicyNN: player.play_policy.learn(batch_size) num_hands = 0 # new round if no one has lost if trainer.hearts_game.losingPlayer.score < max_score: trainer.hearts_game.newRound() if track[0]: player0_scores = np.append(player0_scores, trainer.hearts_game.players[0].score) if track[1]: player1_scores = np.append(player1_scores, trainer.hearts_game.players[1].score) if track[2]: player2_scores = np.append(player2_scores, trainer.hearts_game.players[2].score) if track[3]: player3_scores = np.append(player3_scores, trainer.hearts_game.players[3].score) winners = trainer.hearts_game.getWinner() winnerString = "" won = [False, False, False, False] for w in winners: winnerString += w.name + " " if w.name == trainer.hearts_game.players[0].name: won[0] = True elif w.name == trainer.hearts_game.players[1].name: won[1] = True elif w.name == trainer.hearts_game.players[2].name: won[2] = True elif w.name == trainer.hearts_game.players[3].name: won[3] = True if track[0]: if won[0]: player0_win = np.append(player0_win, 1) else: player0_win = np.append(player0_win, 0) if track[1]: if won[1]: player1_win = np.append(player1_win, 1) else: player1_win = np.append(player1_win, 0) if track[2]: if won[2]: player2_win = np.append(player2_win, 1) else: player2_win = np.append(player2_win, 0) if track[3]: if won[3]: player3_win = np.append(player3_win, 1) else: player3_win = np.append(player3_win, 0) if i % display_stats_epochs == (display_stats_epochs - 1): # Console output print() for a, player in enumerate(trainer.hearts_game.players): print(player.name + ": " + str(player.score)) print(winnerString + "wins!") print("--------------------------------------") if track[0]: print("Player 0 wins:", np.sum(player0_win)) print("Player 0 avg. score:", np.mean(player0_scores)) if track[1]: print("Player 1 wins:", np.sum(player1_win)) print("Player 1 avg. score:", np.mean(player1_scores)) if track[2]: print("Player 2 wins:", np.sum(player2_win)) print("Player 2 avg. score:", np.mean(player2_scores)) if track[3]: print("Player 3 wins:", np.sum(player3_win)) print("Player 3 avg. score:", np.mean(player3_scores)) print("num games: ", i + 1) if train and i % physical_save_epochs == (physical_save_epochs - 1): # Physical save print("Saving model") for player in trainer.hearts_game.players: plot_records(player0_scores, "Final score", "models/policy/Scores.png") if type(player) is PolicyNN: plot_records(player.play_policy.loss_policy, "Loss Actor", "models/policy/loss_" + player.name + ".png") try: player.play_policy.save_model() except: pass # Change players and reset if i % 10 == 9: for j in randomize_players: rand = np.random.randint(10) if rand == 9: trainer.hearts_game.players[j] = RandomAI("rand" + str(j)) else: trainer.hearts_game.players[j] = SimpleAI("simple" + str(j)) trainer.hearts_game.reset() if train: for i, player in enumerate(trainer.hearts_game.players): plot_records(player0_scores, "Final score", "models/policy/Scores.png") if type(player) is PolicyNN: plot_records(player.play_policy.loss_policy, "Loss Actor", "models/policy/loss_" + player.name + ".png")
def evaluateTrick(self): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) self.allTricks.append(self.currentTrick.trick) self.currentTrick = Trick()
def evaluateTrick(self, rollout): rollout.trickWinner = rollout.currentTrick.winner p = rollout.players[rollout.trickWinner] p.trickWon(rollout.currentTrick) rollout.currentTrick = Trick()
class Hearts: def __init__(self): oneMonte_threeNaive_anon = [ Player("AI 1 ", PlayerTypes.NaiveMinAI, self), Player("AI 2 ", PlayerTypes.MonteCarloAI, self), Player("AI 3 ", PlayerTypes.NaiveMinAI, self), Player("AI 4 ", PlayerTypes.NaiveMaxAI, self) ] thePlayers = oneMonte_threeNaive_anon #Shake up the order random.shuffle(thePlayers) self.players = thePlayers self.allTricks = [] self.currentTrick = Trick() self.trickWinner = -1 self.cardsPlayed = () #keep track of state in a tuple temp = dict.fromkeys(thePlayers) for key in temp: temp[key] = [] self.cardsPlayedbyPlayer = temp self.shift = 0 self.winningPlayer = None self.winningPlayers = None self.humanExists = False self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 #self.passes = [1, -1, 2, 0] # left, right, across, no pass self.heartsBroken = False self.losingPlayer = None # Generate a full deck of cards and shuffle it # # else: # self = copy.deepcopy(orig) #return flat array of cards def getLegalPlays(self, player): if player.type == PlayerTypes.MonteCarloAI: validHand = [] for suit in range(0, 4): handSuit = player.hand.hand[suit] for card in handSuit: if self.isValidCard(card, player): validHand.append(card) else: monterCards = sum(self.players[0].hand.hand, []) playedCards = self.cardsPlayed d = Deck() validHand = [ i for i in d.deck if i not in monterCards + list(playedCards) ] #print('player:',player.name,'vali:',validHand) return validHand def getCurrentPlayer(self): return self.players[self.currentTrick.getCurrentPlayer( self.trickWinner)] def step(self, card, player, monteCarlo=False): #add card to state self.cardsPlayed = self.cardsPlayed + (card, ) self.cardsPlayedbyPlayer[player].append(card) player.removeCard(card) start = (self.trickWinner + self.shift) % len(self.players) self.currentTrick.addCard(card, start) self.shift += 1 if self.shift == 4: self.evaluateTrick() self.trickNum += 1 self.shift = 0 #end game and evaluate winner if round is over if monteCarlo: if (self.trickNum >= totalTricks): self.winningPlayers = self.roundWinners() self.handleScoring() self.winningPlayer = self.getWinner() def isValidCard(self, card, player): if card is None: return False # if it is not the first trick and no cards have been played: if self.trickNum != 0 and self.currentTrick.cardsInTrick == 0: if card.suit == Suit(hearts) and not self.heartsBroken: if not player.hasOnlyHearts(): return False #Can't play hearts or queen of spades on first hand if self.trickNum == 0: if card.suit == Suit(hearts): return False elif card.suit == Suit(spades) and card.rank == Rank(queen): return False return True def evaluateTrick(self): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) self.allTricks.append(self.currentTrick.trick) self.currentTrick = Trick() def roundWinners(self): winners = [] for player in self.players: if player.roundscore == 26: #shotMoon = True winners.append(player) return winners minScore = 200 # impossibly high winner = None for p in self.players: if p.roundscore < minScore: winner = p minScore = p.roundscore winners.append(winner) #check for a draw for p in self.players: if p != winner and p.roundscore == minScore: winners.append(p) return winners def handleScoring(self): p, highestScore = None, 0 shotMoon = False for player in self.players: if player.roundscore == 26: shotMoon = True for player in self.players: if shotMoon and player.roundscore != 26: player.score += 26 elif not shotMoon: player.score += player.roundscore player.roundscore = 0 if player.score > highestScore: p = player highestScore = player.score self.losingPlayer = p def getWinner(self): minScore = 200 # impossibly high winner = None for p in self.players: if p.score < minScore: winner = p minScore = p.score return winner def getFirstTrickStarter(self): for i, p in enumerate(self.players): if p.hand.contains2ofclubs: self.trickWinner = i
class Hearts: def __init__(self, players): self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick() self.trickWinner = -1 self.heartsBroken = False self.losingPlayer = None self.passingCards = [[], [], [], []] # Make four players self.players = players #self.players = [QLearningBoi("Dani"), AutoPlayer("Desmond"), AutoPlayer("Ben"), AutoPlayer("Tyler")] ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' # Generate a full deck of cards and shuffle it self.newRound() def handleScoring(self): p, highestScore = None, 0 print("\nScores:\n") for player in self.players: print(player.name + ": " + str(player.score)) if player.score > highestScore: p = player highestScore = player.score self.losingPlayer = p def newRound(self): self.deck = Deck() self.deck.shuffle() self.roundNum += 1 self.trickNum = 0 self.trickWinner = -1 self.heartsBroken = False self.dealer = (self.dealer + 1) % len(self.players) self.dealCards() self.currentTrick = Trick() self.passingCards = [[], [], [], []] for p in self.players: p.discardTricks() def getFirstTrickStarter(self): for i, p in enumerate(self.players): if p.hand.contains2ofclubs: self.trickWinner = i def dealCards(self): i = 0 while (self.deck.size() > 0): self.players[i % len(self.players)].addCard(self.deck.deal()) i += 1 def evaluateTrick(self, printOut=True): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) self.printCurrentTrick() if printOut: print(f"{p.name} won the trick.") # print 'Making new trick' self.currentTrick = Trick() if printOut: print(self.currentTrick.suit) def passCards(self, index): print(self.printPassingCards()) passTo = self.passes[self.trickNum] # how far to pass cards passTo = (index + passTo) % len( self.players) # the index to which cards are passed while len(self.passingCards[passTo]) < cardsToPass: # pass three cards passCard = None while passCard is None: # make sure string passed is valid passCard = self.players[index].play(self, option='pass') if passCard is not None: # remove card from player hand and add to passed cards self.passingCards[passTo].append(passCard) self.players[index].removeCard(passCard) def distributePassedCards(self): for i, passed in enumerate(self.passingCards): for card in passed: self.players[i].addCard(card) self.passingCards = [[], [], [], []] def printPassingCards(self): out = "[ " for passed in self.passingCards: out += "[" for card in passed: out += card.__str__() + " " out += "] " out += " ]" return out def playersPassCards(self): self.printPlayers() if not self.trickNum % 4 == 3: # don't pass every fourth hand for i in range(0, len(self.players)): print('\n') self.printPlayer(i) self.passCards(i % len(self.players)) self.distributePassedCards() self.printPlayers() def finishTrick(self, start, action): print("finishTrick start") if self.trickNum >= totalTricks: print('end game') return playersLeft = len(self.players) - self.currentTrick.cardsInTrick # have each player take their turn for i in range(start, start + playersLeft): # print("playerNum: ", i) # self.printCurrentTrick() curPlayerIndex = i % len(self.players) # self.printPlayer(curPlayerIndex) curPlayer = self.players[curPlayerIndex] addCard = None while addCard is None: # wait until a valid card is passed if i == 0: addCard = action else: addCard = curPlayer.play( self) # change auto to False to play manually # the rules for what cards can be played # card set to None if it is found to be invalid if addCard is not None: # if it is not the first trick and no cards have been played, # set the first card played as the trick suit if it is not a heart # or if hearts have been broken if self.trickNum != 0 and self.currentTrick.cardsInTrick == 0: if addCard.suit == Suit( hearts) and not self.heartsBroken: # if player only has hearts but hearts have not been broken, # player can play hearts if not curPlayer.hasOnlyHearts(): # print(curPlayer.hasOnlyHearts()) # print(curPlayer.hand.__str__()) print("Hearts have not been broken.") addCard = None else: self.currentTrick.setTrickSuit(addCard) else: self.currentTrick.setTrickSuit(addCard) # player tries to play off suit but has trick suit if addCard is not None and addCard.suit != self.currentTrick.suit: if curPlayer.hasSuit(self.currentTrick.suit): print("Must play the suit of the current trick.") addCard = None elif addCard.suit == Suit(hearts): self.heartsBroken = True if self.trickNum == 0: if addCard is not None: if addCard.suit == Suit(hearts): print( "Hearts cannot be broken on the first hand." ) self.heartsBroken = False addCard = None elif addCard.suit == Suit( spades) and addCard.rank == Rank(queen): print( "The queen of spades cannot be played on the first hand." ) addCard = None if addCard is not None and self.currentTrick.suit == Suit( noSuit): if addCard.suit == Suit( hearts) and not self.heartsBroken: print("Hearts not yet broken.") addCard = None if addCard is not None: if addCard == Card(queen, spades): self.heartsBroken = True curPlayer.removeCard(addCard) self.currentTrick.addCard(addCard, curPlayerIndex) print('all players played') self.evaluateTrick(printOut=False) self.trickNum += 1 def playTrick(self, start): shift = 0 if self.trickNum == 0: startPlayer = self.players[start] addCard = startPlayer.play(self, option="play", c='2c') startPlayer.removeCard(addCard) self.currentTrick.addCard(addCard, start) shift = 1 # alert game that first player has already played # have each player take their turn for i in range(start + shift, start + len(self.players)): self.printCurrentTrick() curPlayerIndex = i % len(self.players) self.printPlayer(curPlayerIndex) curPlayer = self.players[curPlayerIndex] addCard = None while addCard is None: # wait until a valid card is passed addCard = curPlayer.play( self) # change auto to False to play manually # print('addCard', addCard) # the rules for what cards can be played # card set to None if it is found to be invalid if addCard is not None: # if it is not the first trick and no cards have been played, # set the first card played as the trick suit if it is not a heart # or if hearts have been broken if self.trickNum != 0 and self.currentTrick.cardsInTrick == 0: if addCard.suit == Suit( hearts) and not self.heartsBroken: # if player only has hearts but hearts have not been broken, # player can play hearts if not curPlayer.hasOnlyHearts(): print(curPlayer.hasOnlyHearts()) print(curPlayer.hand.__str__()) print("Hearts have not been broken.") addCard = None else: self.currentTrick.setTrickSuit(addCard) else: self.currentTrick.setTrickSuit(addCard) # player tries to play off suit but has trick suit if addCard is not None and addCard.suit != self.currentTrick.suit: if curPlayer.hasSuit(self.currentTrick.suit): print("Must play the suit of the current trick.") addCard = None elif addCard.suit == Suit(hearts): self.heartsBroken = True if self.trickNum == 0: if addCard is not None: if addCard.suit == Suit(hearts): print( "Hearts cannot be broken on the first hand." ) self.heartsBroken = False addCard = None elif addCard.suit == Suit( spades) and addCard.rank == Rank(queen): print( "The queen of spades cannot be played on the first hand." ) addCard = None if addCard is not None and self.currentTrick.suit == Suit( noSuit): if addCard.suit == Suit( hearts) and not self.heartsBroken: print("Hearts not yet broken.") addCard = None if addCard is not None: if addCard == Card(queen, spades): self.heartsBroken = True curPlayer.removeCard(addCard) self.currentTrick.addCard(addCard, curPlayerIndex) self.evaluateTrick() self.trickNum += 1 # print player's hand def printPlayer(self, i): p = self.players[i] print(p.name + "'s hand: " + str(p.hand)) # print all players' hands def printPlayers(self): for p in self.players: print(p.name + ": " + str(p.hand)) # show cards played in current trick def printCurrentTrick(self): trickStr = '\nCurrent table:\n' trickStr += "Trick suit: " + self.currentTrick.suit.__str__() + "\n" for i, card in enumerate(self.currentTrick.trick): if self.currentTrick.trick[i] is not 0: trickStr += self.players[i].name + ": " + str(card) + "\n" else: trickStr += self.players[i].name + ": None\n" print(trickStr) def getWinner(self): minScore = 200 # impossibly high winner = None for p in self.players: if p.score < minScore: winner = p minScore = p.score return winner
def main(): trainer = Hearts_env() tot_wins = 0 sam_wins = 0 current_odds = .5 trainer.hearts_game = Hearts() for i in range(epochs): current_odds *= trainer.hearts_game.players[1].play_policy.decay_factor trainer.hearts_game.players[1].play_policy.odds_explore = current_odds # play until someone loses while trainer.hearts_game.losingPlayer is None or trainer.hearts_game.losingPlayer.score < max_score: while trainer.hearts_game.trick_num < total_tricks: if trainer.hearts_game.trick_num == 0: trainer.hearts_game.playersPassCards() trainer.hearts_game.getFirstTrickStarter() trainer.hearts_game.playTrick(trainer.hearts_game.trickWinner) # train anybody that needs to be trained for j, a_palyer in enumerate(trainer.hearts_game.players): q_reward = trainer.get_reward(j) a_palyer.store_reward(q_reward) trainer.hearts_game.currentTrick = Trick(trainer.hearts_game.trick_num) # tally scores trainer.hearts_game.handleScoring() # new round if no one has lost if trainer.hearts_game.losingPlayer.score < max_score: trainer.hearts_game.newRound() for j, a_palyer in enumerate(trainer.hearts_game.players): a_palyer.learn() winners = trainer.hearts_game.getWinner() winnerString = "" for w in winners: winnerString += w.name + " " if w.name == "Jack": tot_wins += 1 if w.name == "Sam": sam_wins += 1 if i % 25 == 0: print() for a, player in enumerate(trainer.hearts_game.players): print(player.name + ": " + str(player.score)) print("Jack wins: ", tot_wins) print("Sam wins: ", sam_wins) print("num games: ", i) print(winnerString + "wins!") if i % 50 == 0: for player in trainer.hearts_game.players: try: player.play_policy.save_model() except: pass trainer.hearts_game.reset()
def MonteCarloPlay(deck, history_self, history_A, history_B, history_C, history_P0, REPLAY=False): ''' 输入一摞牌,选出最应该出的牌 规则打牌的判断机制,对于自己第几个出,自己出牌前已经打出的牌,红桃牌,黑桃Q的打出情况, 以及应该打出大小点等各类情况都进行判断,从而选出应当打出的最适合的牌。 input: deck: 列表,当前玩家手中的牌,如: deck = [Card_C(point=7, suit=0),Card_C(point=10, suit=3),Card_C(point=11, suit=3)] history_self: 同deck列表,当前玩家已出的牌 history_A: 同deck列表,玩家A已出的牌 history_B: 同deck列表,玩家B已出的牌 history_C: 同deck列表,玩家C已出的牌 history_P0: 列表,每个回合第一个发牌的人的index。当前玩家:0, A:1, B:2, C:3 如:history_P0 = [0,1,1]表示第一回合是当前玩家先出的牌,第二回合玩家1先出的牌,第三回合还是玩家1先出的牌 output: pos: Card_C类型,选出的最优的牌 ''' # -------------------------初始化MentorCarol类---------------------------------- # 计算历史牌 deck = sorted(deck, key=lambda x: x.suit * 10 + x.point) history = [history_self, history_A, history_B, history_C] #从输入参数中计算每轮出的牌 allTurnsCard = [] # 每个回合的出牌情况,总共三层,第一层为玩家i,出牌c,第二层为4个玩家,第三层为出了几个回合[[[1,Card(2,3)],[2,Card(3,3)],[],[]]] for i, j in enumerate(history_P0): tmp = [] for k in range(4): now = history[(j + k) % 4] if len(now) > i: tmp.append([(j + k) % 4, now[i]]) allTurnsCard.append(tmp) score_dict = getScoreFromAllcards(allTurnsCard) # 每个玩家的得分dict thisTurnOutCard = allTurnsCard[-1] if allTurnsCard and len( allTurnsCard[-1]) != 4 else [] # 当前回合玩家出牌情况,按照出牌顺序排列 #outQueen = True if [outCard for turn in allTurnsCard for outCard in turn if outCard[1] == Card_C(12,2)] else False outHeart = True if [j for i in allTurnsCard for j in i if j[1].suit == 3] else False # 红桃是否已出 h = Hearts() # h是MonteCarlo使用的游戏类,在该类中,四个玩家轮流出牌并计算得分,计出MonteCarlo玩家出什么牌时得到最优的概率并选择出该牌 oneMonte_threeNaive_anon = [ Player("AI 1 ", PlayerTypes.MonteCarloAI, h), Player("AI 2 ", PlayerTypes.NaiveMinAI, h), Player("AI 3 ", PlayerTypes.NaiveMinAI, h), Player("AI 4 ", PlayerTypes.NaiveMaxAI, h) ] # 在模拟策略中使用一个MonteCarlo方法,其余三个使用Naive方法,此处可以设计不同的玩家规则来提高MonteCarlo模拟的表现 h.players = oneMonte_threeNaive_anon h.heartsBroken = outHeart h.losingPlayer = None h.allTricks = [] h.currentTrick = Trick() for j, i in enumerate(h.players): # 更新四个玩家的得分 i.score = score_dict[j] for i in thisTurnOutCard: # 更新当前回合出的牌 h.currentTrick.addCard(Card_C2Card(i[1]), i[0]) h.trickWinner = thisTurnOutCard[0][0] if thisTurnOutCard else 0 h.cardsPlayed = tuple(Card_C2Card( i[1]) for i in sum(allTurnsCard, [])) # keep track of state in a tuple h.cardsPlayedbyPlayer = { h.players[j]: [Card_C2Card(k) for k in i] for j, i in enumerate(history) } # 每个玩家已出牌字典 h.shift = len(thisTurnOutCard) # 出牌次序 h.winningPlayer = None h.winningPlayers = None # list h.trickNum = len(history_P0) - 1 # 当前是第一轮出牌 #h.dealer = 0 # so that first dealer is 0 #更新模拟的Monto玩家的牌 MontoPlayer = h.players[0] for j in deck: MontoPlayer.hand.addCard(Card(j.point, j.suit)) MontoPlayer.hand.updateHand() # 更新状态信息 #--------------------------------------开始玩游戏---------------------------------------- if MontoPlayer.hand.contains2ofclubs: # 如果有梅花2,则调用play函数直接出2c addCard = MontoPlayer.play(option="play", c='2c') else: addCard = None while addCard is None: # wait until a valid card is passed addCard = MontoPlayer.play(auto=True) if addCard is not None: if h.isValidCard(addCard, MontoPlayer) == False: addCard = None out_card = Card_C(point=addCard.rank.rank, suit=addCard.suit.iden) # 输出牌转换为接口的nametuple类型 return out_card
class Hearts: def __init__(self): self.round_num = 0 self.trick_num = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick(self.trick_num) self.trickWinner = -1 self.hearts_broken = False self.losingPlayer = None self.passingCards = [[], [], [], []] self.scoreboard = [0, 0, 0, 0] self.verbose = False ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' self.players = [ PolicyNN("Jason"), SimpleAI("Jack"), SimpleAI("Sam"), SimpleAI("JB") ] self.newRound() def reset(self): self.round_num = 0 self.trick_num = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick(self.trick_num) self.trickWinner = -1 self.hearts_broken = False self.losingPlayer = None self.passingCards = [[], [], [], []] self.scoreboard = [0, 0, 0, 0] for a_player in self.players: a_player.reset() self.newRound() def handleScoring(self): p, highestScore = None, 0 if self.verbose: print("\n=====Scores=====") tempScores = [] for aPlayer in self.players: tempScores.append(aPlayer.currentScore) if 26 in tempScores: player_shoot = tempScores.index(26) for i, player in enumerate(self.players): if i != player_shoot: player.score += 26 else: for a_player in self.players: a_player.score += a_player.currentScore for i, player in enumerate(self.players): if self.verbose: print(player.name + ": " + str(player.score)) self.scoreboard[i] = player.score if player.score > highestScore: p = player highestScore = player.score self.losingPlayer = p def newRound(self): self.deck = Deck() self.deck.shuffle() self.dealCards() self.round_num += 1 self.trick_num = 0 self.trickWinner = -1 self.hearts_broken = False self.dealer = (self.dealer + 1) % len(self.players) self.currentTrick = Trick(self.trick_num) self.passingCards = [[], [], [], []] for p in self.players: p.discardTricks() p.clearCurrentScore() def dealCards(self): i = 0 while self.deck.size() > 0: self.players[i % len(self.players)].add_card(self.deck.deal()) i += 1 def passCards(self, index): passTo = self.passes[(self.round_num - 1) % 4] # how far to pass cards passTo = (index + passTo) % len( self.players) # the index to which cards are passed for i in range(cardsToPass): passCard = None while passCard is None: # make sure string passed is valid passCard = self.players[index].pass_cards(passTo, i) if passCard is not None: # remove card from player hand and add to passed cards self.passingCards[passTo].append(passCard) self.players[index].removeCard(passCard) if self.verbose: print(self.players[index].name + " is passing " + self.printPassingCards(passTo) + " to " + self.players[passTo].name) def distributePassedCards(self): for i, passed in enumerate(self.passingCards): for card in passed: self.players[i].add_card(card) def printPassingCards(self, playerIndex): out = "[ " for card in self.passingCards[playerIndex]: out += card.__str__() + " " out += "]" return out def playersPassCards(self): if self.round_num % 4 != 0: # Don't pass on round 4 if self.verbose: print("All player's hands before passing") self.printPlayers() for i in range(0, len(self.players)): if self.verbose: print() # spacing curPlayer = self.players[i] print(curPlayer.name + "'s hand: " + str(curPlayer.hand)) self.passCards(i) self.distributePassedCards() if self.verbose: print() print("All player's hands after passing") self.printPlayers() def getFirstTrickStarter(self): for i, p in enumerate(self.players): if p.hand.hasCard('2c'): self.trickWinner = i def evaluateTrick(self): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) if self.verbose: self.printCurrentTrick() print(p.name + " won the trick.") print() def getWinner(self): minScore = 200 # impossibly high winner = [] for p in self.players: if p.score < minScore: winner = [] winner.append(p) minScore = p.score elif p.score == minScore: winner.append(p) return winner def getLosers(self): return [pl for pl in self.players if pl.score >= 100] def playTrick(self, start): if self.verbose: print('\n==========Trick number ' + str(self.trick_num + 1) + '==========') # have each player take their turn for i in range(start, start + len(self.players)): curPlayerIndex = i % len(self.players) curPlayer = self.players[curPlayerIndex] played_card = None if self.verbose: self.printCurrentTrick() print(curPlayer.name + "'s hand: " + str(curPlayer.hand)) game_state = GameState(curPlayerIndex, self.currentTrick, self.hearts_broken, self.players) while played_card is None: # wait until a valid card is passed played_card = curPlayer.play(game_state) suit = played_card[-1:] rank = played_card[:-1] # the rules for what cards can be played # card set to None if it is found to be invalid if played_card is not None: # if it is not the first trick and no cards have been played, # set the first card played as the trick suit if it is not a heart # or if hearts have been broken if self.trick_num != 0 and self.currentTrick.cardsInTrick == 0: if suit == 'h' and not self.hearts_broken: # if player only has hearts but hearts have not been broken, # player can play hearts if not curPlayer.hasOnlyHearts(): # print("Hearts have not been broken.") played_card = None else: self.currentTrick.set_trick_suit(played_card) else: self.currentTrick.set_trick_suit(played_card) # check if card played in first trick is not a heart or qs if self.trick_num == 0: if played_card is not None: if self.currentTrick.suit == 'x' and played_card != '2c': print( "First card of the round must be the 2 of clubs" ) played_card = None if suit == 'h' or (suit == 's' and rank == 'Q'): if curPlayer.hand.has_only_points(): print( "Points cannot be played on the first hand when possible." ) played_card = None # player tries to play off suit but has trick suit if played_card is not None and suit != self.currentTrick.suit: if curPlayer.has_suit(self.currentTrick.suit): print("Must play the suit of the current trick.") played_card = None elif suit == 'h': self.hearts_broken = True if played_card is not None: if rank == 'Q' and suit == 's': self.hearts_broken = True curPlayer.removeCard(played_card) self.currentTrick.add_card(played_card, curPlayerIndex) self.evaluateTrick() self.trick_num += 1 def printPlayers(self): for p in self.players: print(p.name + ": " + str(p.hand)) # show cards played in current trick def printCurrentTrick(self): if self.currentTrick.cardsInTrick == 4: trickStr = '\n=====Final Trick=====\n' else: trickStr = '\n=====Current Trick=====\n' trickStr += "Trick suit: " + self.currentTrick.suit.__str__() + "\n" for i, card in enumerate(self.currentTrick.trick): if self.currentTrick.trick[i] is not 0: trickStr += self.players[i].name + ": " + str(card) + "\n" else: trickStr += self.players[i].name + ": None\n" print(trickStr)
class Hearts: def __init__(self): self.roundNum = 0 self.trickNum = 0 # initialization value such that first round is round 0 self.dealer = -1 # so that first dealer is 0 self.passes = [1, -1, 2, 0] # left, right, across, no pass self.currentTrick = Trick() self.trickWinner = -1 self.heartsBroken = False self.losingPlayer = None self.passingCards = [[], [], [], []] # Make four players self.players = [Player("Danny"), Player("Desmond"), Player("Ben"), Player("Tyler")] ''' Player physical locations: Game runs clockwise p3 p2 p4 p1 ''' # Generate a full deck of cards and shuffle it self.newRound() def handleScoring(self): p, highestScore = None, 0 print "\nScores:\n" for player in self.players: print player.name + ": " + str(player.score) if player.score > highestScore: p = player highestScore = player.score self.losingPlayer = p def newRound(self): self.deck = Deck() self.deck.shuffle() self.roundNum += 1 self.trickNum = 0 self.trickWinner = -1 self.heartsBroken = False self.dealer = (self.dealer + 1) % len(self.players) self.dealCards() self.currentTrick = Trick() self.passingCards = [[], [], [], []] for p in self.players: p.discardTricks() def getFirstTrickStarter(self): for i,p in enumerate(self.players): if p.hand.contains2ofclubs: self.trickWinner = i def dealCards(self): i = 0 while(self.deck.size() > 0): self.players[i % len(self.players)].addCard(self.deck.deal()) i += 1 def evaluateTrick(self): self.trickWinner = self.currentTrick.winner p = self.players[self.trickWinner] p.trickWon(self.currentTrick) self.printCurrentTrick() print p.name + " won the trick." # print 'Making new trick' self.currentTrick = Trick() print self.currentTrick.suit def passCards(self, index): print self.printPassingCards() passTo = self.passes[self.trickNum] # how far to pass cards passTo = (index + passTo) % len(self.players) # the index to which cards are passed while len(self.passingCards[passTo]) < cardsToPass: # pass three cards passCard = None while passCard is None: # make sure string passed is valid passCard = self.players[index].play(option='pass') if passCard is not None: # remove card from player hand and add to passed cards self.passingCards[passTo].append(passCard) self.players[index].removeCard(passCard) def distributePassedCards(self): for i,passed in enumerate(self.passingCards): for card in passed: self.players[i].addCard(card) self.passingCards = [[], [], [], []] def printPassingCards(self): out = "[ " for passed in self.passingCards: out += "[" for card in passed: out += card.__str__() + " " out += "] " out += " ]" return out def playersPassCards(self): self.printPlayers() if not self.trickNum % 4 == 3: # don't pass every fourth hand for i in range(0, len(self.players)): print # spacing self.printPlayer(i) self.passCards(i % len(self.players)) self.distributePassedCards() self.printPlayers() def playTrick(self, start): shift = 0 if self.trickNum == 0: startPlayer = self.players[start] addCard = startPlayer.play(option="play", c='2c') startPlayer.removeCard(addCard) self.currentTrick.addCard(addCard, start) shift = 1 # alert game that first player has already played # have each player take their turn for i in range(start + shift, start + len(self.players)): self.printCurrentTrick() curPlayerIndex = i % len(self.players) self.printPlayer(curPlayerIndex) curPlayer = self.players[curPlayerIndex] addCard = None while addCard is None: # wait until a valid card is passed addCard = curPlayer.play(auto=auto) # change auto to False to play manually # the rules for what cards can be played # card set to None if it is found to be invalid if addCard is not None: # if it is not the first trick and no cards have been played, # set the first card played as the trick suit if it is not a heart # or if hearts have been broken if self.trickNum != 0 and self.currentTrick.cardsInTrick == 0: if addCard.suit == Suit(hearts) and not self.heartsBroken: # if player only has hearts but hearts have not been broken, # player can play hearts if not curPlayer.hasOnlyHearts(): print curPlayer.hasOnlyHearts() print curPlayer.hand.__str__() print "Hearts have not been broken." addCard = None else: self.currentTrick.setTrickSuit(addCard) else: self.currentTrick.setTrickSuit(addCard) # player tries to play off suit but has trick suit if addCard is not None and addCard.suit != self.currentTrick.suit: if curPlayer.hasSuit(self.currentTrick.suit): print "Must play the suit of the current trick." addCard = None elif addCard.suit == Suit(hearts): self.heartsBroken = True if self.trickNum == 0: if addCard is not None: if addCard.suit == Suit(hearts): print "Hearts cannot be broken on the first hand." self.heartsBroken = False addCard = None elif addCard.suit == Suit(spades) and addCard.rank == Rank(queen): print "The queen of spades cannot be played on the first hand." addCard = None if addCard is not None and self.currentTrick.suit == Suit(noSuit): if addCard.suit == Suit(hearts) and not self.heartsBroken: print "Hearts not yet broken." addCard = None if addCard is not None: if addCard == Card(queen, spades): self.heartsBroken = True curPlayer.removeCard(addCard) self.currentTrick.addCard(addCard, curPlayerIndex) self.evaluateTrick() self.trickNum += 1 # print player's hand def printPlayer(self, i): p = self.players[i] print p.name + "'s hand: " + str(p.hand) # print all players' hands def printPlayers(self): for p in self.players: print p.name + ": " + str(p.hand) # show cards played in current trick def printCurrentTrick(self): trickStr = '\nCurrent table:\n' trickStr += "Trick suit: " + self.currentTrick.suit.__str__() + "\n" for i, card in enumerate(self.currentTrick.trick): if self.currentTrick.trick[i] is not 0: trickStr += self.players[i].name + ": " + str(card) + "\n" else: trickStr += self.players[i].name + ": None\n" print trickStr def getWinner(self): minScore = 200 # impossibly high winner = None for p in self.players: if p.score < minScore: winner = p minScore = p.score return winner