def getDiscard(self): minDeadwood = 10000000000000000 candidateCards = [] for card in self.cards: if (card == self.drawnCard and self.drawnCard == self.faceUpCard): continue drawDiscard = [] drawDiscard.append(self.drawnCard) drawDiscard.append(card) if (GinRummyUtil.cardsToBitstring(drawDiscard) in self.drawDiscardBitstrings): continue remainingCards = copy.copy(self.cards) remainingCards.remove(card) bestMeldSets = GinRummyUtil.cardsToBestMeldSets(remainingCards) deadwood = GinRummyUtil.getDeadwoodPoints( None, None, None, remainingCards ) if not bestMeldSets else GinRummyUtil.getDeadwoodPoints( bestMeldSets[0], remainingCards, None, None) if (deadwood <= minDeadwood): if (deadwood < minDeadwood): minDeadwood = deadwood candidateCards.clear() candidateCards.append(card) discard = candidateCards[random.randrange(0, (len(candidateCards)))] drawDiscard = [] drawDiscard.append(self.drawnCard) drawDiscard.append(discard) self.drawDiscardBitstrings.append( GinRummyUtil.cardsToBitstring(drawDiscard)) return discard
def getFinalMelds(self): bestMeldSets = GinRummyUtil.cardsToBestMeldSets(self.cards) if (not self.opponentKnocked and (not bestMeldSets or GinRummyUtil.getDeadwoodPoints( bestMeldSets[0], self.cards, None, None) > GinRummyUtil.MAX_DEADWOOD)): return None return [] if not bestMeldSets else bestMeldSets[random.randrange( 0, len(bestMeldSets))]
def getFinalMelds(self): bestMeldSets = GinRummyUtil.cardsToBestMeldSets(self.cards) #if (!opponentKnocked && (bestMeldSets.isEmpty() || GinRummyUtil.getDeadwoodPoints(bestMeldSets.get(0), cards) > GinRummyUtil.MAX_DEADWOOD)) if (not self.opponentKnocked) and ( (not bestMeldSets) or (GinRummyUtil.getDeadwoodPoints( bestMeldSets[0], self.cards, None, None) > GinRummyUtil.MAX_DEADWOOD)): return None return [] if (not bestMeldSets) else bestMeldSets[random.randrange( 0, len(bestMeldSets))]
def willDrawFaceUpCard(self, card): self.faceUpCard = card newCards = copy.deepcopy(self.cards) newCards.append(card) for meld in GinRummyUtil.cardsToAllMelds(newCards): if (card in meld): return True return False
def getDiscard(self): minDeadwood = sys.maxsize candidateCards = [] for card in self.cards: if (card == self.drawnCard and self.drawnCard == self.faceUpCard): continue drawDiscard = [] drawDiscard.append(self.drawnCard) drawDiscard.append(card) if (GinRummyUtil.cardsToBitstring(drawDiscard) in self.drawDiscardBitstrings): continue remainingCards = copy.deepcopy(self.cards) remainingCards.remove(card) bestMeldSets = GinRummyUtil.cardsToBestMeldSets(remainingCards) deadwood = GinRummyUtil.getDeadwoodPoints(None, None, None, remainingCards) if (not bestMeldSets) \ else GinRummyUtil.getDeadwoodPoints(bestMeldSets[0], remainingCards, None, None) if (deadwood <= minDeadwood): if (deadwood < minDeadwood): minDeadwood = deadwood candidateCards.clear() candidateCards.append(card) if (len(candidateCards) > 1): maxRank = candidateCards[0].rank maxCandidateCards = [] for c in candidateCards: if (c.rank > maxRank): maxCandidateCards.clear() maxRank = c.rank if (c.rank == maxRank): maxCandidateCards.append(c) candidateCards = maxCandidateCards discard = candidateCards[random.randrange(0, len(candidateCards))] drawDiscard = [] drawDiscard.append(self.drawnCard) drawDiscard.append(discard) self.drawDiscardBitstrings.append( GinRummyUtil.cardsToBitstring(drawDiscard)) return discard
def play(startingPlayer): # csvGameRecords = [] csvTurnRecords = [] scores = [0 for i in range(2)] hands = [] hands.append([]) hands.append([]) while scores[0] < GinRummyUtil.GOAL_SCORE and scores[ 1] < GinRummyUtil.GOAL_SCORE: currentPlayer = startingPlayer opponent = 1 if currentPlayer == 0 else 0 prevScores = copy.copy(scores) deck = Card.getShuffle(random.randrange(sys.maxsize)) # deck = Card.getShuffle(1) # print(deck) hands[0].clear() hands[1].clear() # deal cards to players for i in range(2 * HAND_SIZE): hands[i % 2].append(deck.pop()) for i in range(2): handArr = hands[i] players[i].startGame(i, startingPlayer, handArr) if playVerbose: print("Player {} is dealt {}.\n".format(i, hands[i])) if playVerbose: print("Player {} starts.\n".format(startingPlayer)) discards = [] # new Stack<Card>() discards.append(deck.pop()) if playVerbose: print("The initial face up card is {}.\n".format(discards[-1])) firstFaceUpCard = discards[ -1] #https://stackoverflow.com/questions/4085417/how-to-check-the-last-element-of-a-python-list discards.peek() turnsTaken = 0 knockMelds = None revealedCards = [] # ArrayList<Card>() revealedCards.append(firstFaceUpCard) if currentPlayer == 0: currentCards = copy.copy(hands[currentPlayer]) revealedCards.extend(currentCards) # while there still card in the deck of card, play while len(deck) > 2: # print('len deck {}'.format(len(deck))) if toCSV1: turn = [] # new ArrayList<Object>() turn.append(currentPlayer) turn.append(turnsTaken + 1) unmeldedCards = copy.copy(hands[currentPlayer]) turn.append(unmeldedCards) bestMelds = GinRummyUtil.cardsToBestMeldSets(unmeldedCards) if bestMelds: #!bestMelds.isEmpty() melds = bestMelds[0] # turn[3] turn.append(copy.copy(melds)) for meld in melds: for card in meld: unmeldedCards.remove(card) melds.append(unmeldedCards) # turn[4] - deadwoods turn.append(copy.copy(unmeldedCards)) else: turn.append([]) turn.append(copy.copy(unmeldedCards)) drawFaceUp = False faceUpCard = discards[-1] # turn[5] turn.append(faceUpCard) if not (turnsTaken == 3 and faceUpCard == firstFaceUpCard ): # only for the beginning of the hand drawFaceUp = players[currentPlayer].willDrawFaceUpCard( faceUpCard) # print("drawFaceUp {}".format(drawFaceUp)) if not drawFaceUp and faceUpCard == firstFaceUpCard and turnsTaken < 2: if playVerbose: print("Player {} declines {}.\n".format( currentPlayer, firstFaceUpCard)) turn.append(False) turn.append(False) turn.append(None) if (currentPlayer == 0): turn.append(copy.deepcopy(revealedCards)) if not ((not drawFaceUp) and turnsTaken < 2 and faceUpCard == firstFaceUpCard): drawCard = discards.pop() if drawFaceUp else deck.pop() for i in range(2): players[i].reportDraw( currentPlayer, drawCard if i == currentPlayer or drawFaceUp else None) if playVerbose: print("Player {} draws {}.\n".format( currentPlayer, drawCard)) hands[currentPlayer].append(drawCard) if (drawFaceUp): turn.append(True) turn.append(False) else: turn.append(False) turn.append(True) if (currentPlayer == 0): revealedCards.append(drawCard) discardCard = players[currentPlayer].getDiscard() if (not (discardCard in hands[currentPlayer]) ) or discardCard == faceUpCard: if playVerbose: print( "Player {} discards {} illegally and forfeits.\n" .format(currentPlayer, discardCard)) return opponent hands[currentPlayer].remove(discardCard) for i in range(2): players[i].reportDiscard(currentPlayer, discardCard) if playVerbose: print("Player {} discards {}.\n".format( currentPlayer, discardCard)) discards.append(discardCard) # turn[8] turn.append(discardCard) if (currentPlayer == 1): revealedCards.append(discardCard) if (playVerbose): if (not bestMelds): #if bestMelds.isEmpty() print( "Player {} has {} with {} deadwood.\n".format( currentPlayer, unmeldedCards, GinRummyUtil.getDeadwoodPoints( None, None, None, unmeldedCards))) else: melds = bestMelds[0] for meld in melds: for card in meld: unmeldedCards.remove(card) melds.append(unmeldedCards) print( "Player {} has {} with {} deadwood.\n".format( currentPlayer, melds, GinRummyUtil.getDeadwoodPoints( None, None, None, unmeldedCards))) # only player, not opponent receive revealed cards info if (currentPlayer == 0): # turn[9] turn.append(copy.deepcopy(revealedCards)) csvTurnRecords.append(turn) knockMelds = players[currentPlayer].getFinalMelds() # print("knockMelds {}".format(knockMelds)) if (knockMelds != None): break turnsTaken = turnsTaken + 1 currentPlayer = 1 if currentPlayer == 0 else 0 opponent = 1 if currentPlayer == 0 else 0 if (knockMelds != None): handBitstring = GinRummyUtil.cardsToBitstring(hands[currentPlayer]) # print("handBitstring {}".format(handBitstring)) unmelded = handBitstring for meld in knockMelds: # print("meld {}".format(meld)) meldBitstring = GinRummyUtil.cardsToBitstring(meld) # print("meldBitstring {}".format(meldBitstring)) if (not (meldBitstring in GinRummyUtil.getAllMeldBitstrings()) ) or ((meldBitstring & unmelded) != meldBitstring): # TODO if playVerbose: print("Player {} melds {} illegally and forfeits.\n". format(currentPlayer, knockMelds)) print("not here 1") return opponent unmelded = unmelded & ~meldBitstring #print("current hand {}".format(hands[currentPlayer])) knockingDeadwood = GinRummyUtil.getDeadwoodPoints( knockMelds, hands[currentPlayer], None, None) # print("knowckingDeadwood {}".format(knockingDeadwood)) if (knockingDeadwood > GinRummyUtil.MAX_DEADWOOD): if (playVerbose): print( "Player {} melds {} with greater than {} deadwood and forfeits.\n" .format(currentPlayer, knockMelds, knockingDeadwood)) print("not here 2") return opponent meldsCopy = [] for i in range(2): # meldsCopy = < <Card>>() for meld in knockMelds: meldsCopy.append(copy.copy(meld)) meldsCopy.append(GinRummyUtil.bitstringToCards(unmelded)) # print("meldsCopy {}".format(meldsCopy)) players[i].reportFinalMelds(currentPlayer, meldsCopy) if playVerbose: if (knockingDeadwood > 0): print("Player {} melds {} with {} deadwood from {}.\n". format(currentPlayer, knockMelds, knockingDeadwood, GinRummyUtil.bitstringToCards(unmelded))) else: print("Player {} goes gin with melds {}.\n".format( currentPlayer, knockMelds)) opponentMelds = players[opponent].getFinalMelds() # print("opponentMelds {}".format(opponentMelds)) opponentHandBitstring = GinRummyUtil.cardsToBitstring( hands[opponent]) # print("opponentHandBitstring {}".format(opponentHandBitstring)) opponentUnmelded = opponentHandBitstring for meld in opponentMelds: meldBitstring = GinRummyUtil.cardsToBitstring(meld) if not (meldBitstring in GinRummyUtil.getAllMeldBitstrings( )) or ((meldBitstring & opponentUnmelded) != meldBitstring): if (playVerbose): print("Player {} melds {} illegally and forfeits.\n". format(opponent, opponentMelds)) print("not here 3") return currentPlayer opponentUnmelded = opponentUnmelded & ~meldBitstring unmeldedCards = GinRummyUtil.bitstringToCards(opponentUnmelded) # print("unmeldedCards {}".format(unmeldedCards)) if (knockingDeadwood > 0): cardWasLaidOff = True while True: cardWasLaidOff = False layOffCard = None layOffMeld = None for card in unmeldedCards: for meld in knockMelds: newMeld = copy.deepcopy(meld) newMeld.append(card) newMeldBitstring = GinRummyUtil.cardsToBitstring( newMeld) if (newMeldBitstring in GinRummyUtil.getAllMeldBitstrings()): layOffCard = card layOffMeld = meld break if (layOffCard != None): if (playVerbose): print("Player {} lays off {} on {}.\n".format( opponent, layOffCard, layOffMeld)) for player in range(2): players[player].reportLayoff( opponent, layOffCard, layOffMeld) unmeldedCards.remove(layOffCard) layOffMeld.append(layOffCard) cardWasLaidOff = True break if (not cardWasLaidOff): break opponentDeadwood = 0 for card in unmeldedCards: opponentDeadwood += GinRummyUtil.getDeadwoodPoints( None, None, card, None) # print("opponentDeadwood {}".format(opponentDeadwood)) if (playVerbose): print("Player {} has {} deadwood with {}\n".format( opponent, opponentDeadwood, unmeldedCards)) if (playVerbose): print("Player {} melds {}.\n".format(opponent, opponentMelds)) for i in range(2): meldsCopy = [] for meld in opponentMelds: meldsCopy.append(copy.copy(meld)) meldsCopy.append(copy.copy(unmeldedCards)) players[i].reportFinalMelds(opponent, meldsCopy) if (knockingDeadwood == 0): scores[ currentPlayer] += GinRummyUtil.GIN_BONUS + opponentDeadwood if (playVerbose): print( "Player {} scores the gin bonus of {} plus opponent deadwood {} for {} total points.\n" .format(currentPlayer, GinRummyUtil.GIN_BONUS, opponentDeadwood, GinRummyUtil.GIN_BONUS + opponentDeadwood)) elif (knockingDeadwood < opponentDeadwood): scores[currentPlayer] += opponentDeadwood - knockingDeadwood if (playVerbose): print("Player {} scores the deadwood difference of {}.\n". format(currentPlayer, opponentDeadwood - knockingDeadwood)) else: scores[ opponent] += GinRummyUtil.UNDERCUT_BONUS + knockingDeadwood - opponentDeadwood if (playVerbose): print( "Player {} undercuts and scores the undercut bonus of {} plus deadwood difference of {} for {} total points.\n" .format( opponent, GinRummyUtil.UNDERCUT_BONUS, knockingDeadwood - opponentDeadwood, GinRummyUtil.UNDERCUT_BONUS + knockingDeadwood - opponentDeadwood)) startingPlayer = 1 if startingPlayer == 0 else 0 else: # If the round ends due to a two card draw pile with no knocking, the round is cancelled. if (playVerbose): print( "The draw pile was reduced to two cards without knocking, so the hand is cancelled." ) for i in range(2): for j in range(2): players[i].reportFinalHand(j, hands[j]) if (playVerbose): print("Player\tScore\n0\t%d\n1\t%d\n", scores[0], scores[1]) for i in range(2): players[i].reportScores(copy.deepcopy(scores)) if (toCSV1): # fix: for some reason an odd number of turn records produce error. Thus if odd, remove the last turn record if (len(csvTurnRecords) % 2 != 0): # & del csvTurnRecords[len(csvTurnRecords) - 1] i = 0 while i < len(csvTurnRecords) and (i + 1) < len(csvTurnRecords): # Get turn of player and opponent playerTurn = [] oppTurn = [] firstPlayer = (csvTurnRecords[i])[0] if (firstPlayer == 0): playerTurn = csvTurnRecords[i] oppTurn = csvTurnRecords[i + 1] else: playerTurn = csvTurnRecords[i + 1] oppTurn = csvTurnRecords[i] # add opponent draw face up card (oppTurn[5]) to playerTurn if oppTurn[6]: playerTurn.append(oppTurn[5]) else: playerTurn.append(None) # add opponent discard card (oppTurn[8]) to playerTurn playerTurn.append(oppTurn[8]) i = i + 2 # add hand outcome for i in range(len(csvTurnRecords)): turn = csvTurnRecords[i] turnPlayer = turn[0] turnOpponent = 1 - turnPlayer handOutcome = scores[turnPlayer] - prevScores[ turnPlayer] - scores[turnOpponent] + prevScores[ turnOpponent] turn.append(handOutcome) # write to csv file for turn in csvTurnRecords: csv = turn # redundancy just so that don't have to modify code below #matrix = [[0 for c in range(65)] for r in range(4)] #All info of the turn matrix = [[0 for c in range(91)] for r in range(4)] #All info of the turn handOutcome = 0 if (csv[0] == 0): for i in range(len(csv)): if i > 1 and i != 9 and i != 10: # disregard [0] (player), [1] (turn), revealed cards, and opp draw face up if (i == 12): handOutcome = csv[i] #elif (i != 6): # { // if not numeric values: draw card, discard card, revealed cards, opp draw, opp discard else: # { // if not numeric values: draw card, discard card, revealed cards, opp draw, opp discard rankOffset = 0 # // indicate to which set of the 13 rank the info belong #// suit order: club, heart, space, diamond # if (i == 2): # if player's hand if (i == 3): # if melds rankOffset = 0 cards = [] for meld in csv[i]: cards.extend(meld) for c in range(len(cards)): card = cards[c] suit = card.getSuit() rank = card.getRank() matrix[suit][rank + rankOffset] = 1 elif (i == 4): # if deadwoods rankOffset = 1 * 13 cards = [] cards.extend(csv[i]) for c in range(len(cards)): card = cards[c] suit = card.getSuit() rank = card.getRank() matrix[suit][rank + rankOffset] = 1 elif i > 4 and i <= 11: if i == 11: rankOffset = 2 * 13 elif i == 5: # face up card rankOffset = 3 * 13 elif (i == 6): # draw face up? rankOffset = 4 * 13 elif (i == 7): # draw face down? rankOffset = 5 * 13 elif (i == 8): # discard card rankOffset = 6 * 13 if i == 6 or i == 7: if csv[i]: for r in range(4): for c in range( rankOffset, rankOffset + 13): matrix[r][c] = 1 elif (csv[i] != None): card = csv[i] suit = card.getSuit() rank = card.getRank() matrix[suit][rank + rankOffset] = 1 for r in range(len(matrix)): out.writerow(matrix[r]) outY.writerow([handOutcome]) #csvGameRecords.extend(copy.deepcopy(csvTurnRecords)) #DataCollector.csvRecords.extend(csvGameRecords) csvTurnRecords.clear() #if playVerbose: #print("Player {} wins.\n".format(0 if scores[0] > scores[1] else 1)) # winOutcome = [1 if scores[0] > scores[1] else 0, 0 if scores[0] > scores[1] else 1] # for turn in csvGameRecords: # turnPlayer = turn[0] # turn.append(winOutcome[turnPlayer]) # DataCollector.csvRecords.extend(copy.deepcopy(csvGameRecords)) # csvGameRecords.clear() return 0 if scores[0] >= GinRummyUtil.GOAL_SCORE else 1
def play(startingPlayer): # csvGameRecords = [] csvTurnRecords = [] scores = [0 for i in range(2)] hands = [] hands.append([]) hands.append([]) while scores[0] < GinRummyUtil.GOAL_SCORE and scores[ 1] < GinRummyUtil.GOAL_SCORE: turnRecords = [] currentPlayer = startingPlayer opponent = 1 if currentPlayer == 0 else 0 prevScores = copy.copy(scores) deck = Card.getShuffle(random.randrange(sys.maxsize)) # deck = Card.getShuffle(1) # print(deck) hands[0].clear() hands[1].clear() # deal cards to players for i in range(2 * HAND_SIZE): hands[i % 2].append(deck.pop()) for i in range(2): handArr = hands[i] players[i].startGame(i, startingPlayer, handArr) if playVerbose: print("Player {} is dealt {}.".format(i, hands[i])) if playVerbose: print("Player {} starts.".format(startingPlayer)) discards = [] # new Stack<Card>() discards.append(deck.pop()) if playVerbose: print("The initial face up card is {}.".format(discards[-1])) firstFaceUpCard = discards[ -1] #https://stackoverflow.com/questions/4085417/how-to-check-the-last-element-of-a-python-list discards.peek() turnsTaken = 0 knockMelds = None # turn data revealedCards = [] opponentDrawnCards = [] opponentDiscardedCards = [] revealedCards.append(firstFaceUpCard) if currentPlayer == 0: currentCards = copy.copy(hands[currentPlayer]) revealedCards.extend(currentCards) # while there still card in the deck of card while len(deck) > 2: for i in range(2): if playVerbose: print("Player {}'s hand {}.".format(i, hands[i])) turn = [] unmeldedCards = copy.copy(hands[currentPlayer]) turn.append(copy.copy(hands[currentPlayer])) bestMelds = GinRummyUtil.cardsToBestMeldSets(unmeldedCards) playerMelds = [] if bestMelds: #!bestMelds.isEmpty() melds = bestMelds[0] for meld in melds: playerMelds.extend(meld) for card in meld: unmeldedCards.remove(card) melds.append(unmeldedCards) drawFaceUp = False faceUpCard = discards[-1] ######################################################################################################################### # prepare info for player draw decision # include, in order: current hand, opponent drawn cards, player discards, opponent discards if (currentPlayer == 0): decisionData = [ ] # temporary holder before write out to matrix. Will be cleared immediately after written to matrix decisionData.append(hands[currentPlayer]) decisionData.append(opponentDrawnCards) decisionData.append(opponentDiscardedCards) decisionData.append(revealedCards) # decisionData.append(playerMelds) # decisionData.append(unmeldedCards) # decisionData.append(opponentDiscardedCards) # decisionData.append(faceUpCard) ########################################################################################################################## #<#################################################################################################### # TODO implement the decline option for the first 2 turns # Continue with turn if not initial declined option #< #if not ((not drawFaceUp) and turnsTaken < 2 and faceUpCard == firstFaceUpCard): # deciding whether draw face up (discards.pop()) or draw face down (deck.pop()) # draw whichever gives higher predicted hand result # 1 if draw face up # 1.1 append the face up card to the player hand for testing drawFaceUpPoint = 0 drawFaceDownPoint = 0 decisionData[0].append( discards[-1]) # assume that the player draw face up discardIfDrawFaceUp = None maxHandOutcomeIfDrawFaceUp = -1000000 # 1.2 try different possible discards and get the highest expected score cards = copy.copy( decisionData[0] ) # so that can freely remove and append on decisionData[0] for card in cards: decisionData[0].remove(card) hand = arrayToData(decisionData) # if playVerboseNetwork: # print("removed card {}".format(card)) predictedHandOutcome = network.predict(hand)[0][0] # if playVerboseNetwork: # print("estimated handoutcome of draw face up card {} with {} discard: {}".format(discards[-1], card, predictedHandOutcome)) if predictedHandOutcome > maxHandOutcomeIfDrawFaceUp: maxHandOutcomeIfDrawFaceUp = predictedHandOutcome discardIfDrawFaceUp = card decisionData[0].append(card) # print("drawFaceUpPoint {}".format(drawFaceUpPoint)) # if playVerboseNetwork: # print("max draw face up card {}: {} with {} discard".format(discards[-1], maxHandOutcomeIfDrawFaceUp, discardIfDrawFaceUp)) # 1.3 remove the face up card. Don't make decision yet till check draw face down decisionData[0].remove(discards[-1]) # hand should still have just 10 cards if len(decisionData[0]) > 10 or len(hands[currentPlayer]) > 10: print("more cards in hand than allowed") exit(1) # 2: get average point of drawing a face down card drawFaceDownPoint = 0 # 2.1 for each face down card for card in deck: # 2.1.1 get the max score if drawing this card by checking point of each possible discard decisionData[0].append(card) cards = copy.copy(decisionData[0]) maxHandOutcomeThisFaceDown = -100000000 for c in cards: decisionData[0].remove(c) handData = arrayToData(decisionData) predictedHandOutcome = network.predict(handData)[0][0] if maxHandOutcomeThisFaceDown < predictedHandOutcome: maxHandOutcomeThisFaceDown = predictedHandOutcome decisionData[0].append(c) # 2.1.2 add the max score for drawing this card to drawFaceDownPoint drawFaceDownPoint += maxHandOutcomeThisFaceDown # print("pointOfCurrentCard {}".format(pointOfCurrentCard)) # 2.1.3 remove this card out of hand decisionData[0].remove(card) # hand should still have just 10 cards if len(decisionData[0]) > 10 or len(hands[currentPlayer]) > 10: print("more cards in hand than allowed") exit(1) drawFaceDownPoint /= len(deck) # if playVerboseNetwork: # print("predicted outcome draw face down: {}".format(drawFaceDownPoint)) drawCard = None drawFaceUp = False if maxHandOutcomeIfDrawFaceUp >= drawFaceDownPoint: drawCard = discards.pop() drawFaceUp = True else: drawCard = deck.pop() revealedCards.append(drawCard) if playVerbose: print("Player {} draws {}.\n".format( currentPlayer, drawCard)) if playVerboseNetwork: if drawFaceUp: print("Conv net draws face-up {}.\n".format(drawCard)) else: print( "Conv net draws face-down {}.\n".format(drawCard)) for i in range(2): players[i].reportDraw( currentPlayer, drawCard if i == currentPlayer or drawFaceUp else None) hands[currentPlayer].append(drawCard) # deciding which card to discard discardCard = None if drawFaceUp: discardCard = discardIfDrawFaceUp else: bestCardToRemove = None maxPoint = -10000000 for card in hands[currentPlayer]: decisionData[0].remove(card) handIfDiscardThisCard = arrayToData(decisionData) predictedPoint = network.predict(handIfDiscardThisCard) predictedPoint = predictedPoint[0][0] # print("predictedPoint {}".format(predictedPoint)) if predictedPoint > maxPoint: maxPoint = predictedPoint bestCardToRemove = card decisionData[0].append(card) discardCard = bestCardToRemove # if (not (bestCardToRemove in hands[currentPlayer])) or bestCardToRemove == faceUpCard: # if playVerbose: # print("Player {} discards {} illegally and forfeits.\n".format(currentPlayer, discardCard)) # return opponent # if playVerboseNetwork: # print("predicted maxPoint of discard after a draw-face-down: {}".format(maxPoint)) hands[currentPlayer].remove(discardCard) # report the discarded card to both players for i in range(2): players[i].reportDiscard(currentPlayer, discardCard) # add to discard pile of possible drawing discards.append(discardCard) if playVerbose: print("Player {} discards {}.\n".format( currentPlayer, discardCard)) if playVerboseNetwork: print("Conv net discards {}.\n".format(discardCard)) # CHECK FOR KNOCK knockMelds = players[currentPlayer].getFinalMelds() # print("knockMelds {}".format(knockMelds)) if (knockMelds != None): break # player knocked, end of round #> # RECORD TURN DATA turn.append(copy.deepcopy(hands[currentPlayer])) turn.append(copy.deepcopy(opponentDrawnCards)) turn.append(copy.deepcopy(opponentDiscardedCards)) turn.append(copy.deepcopy(revealedCards)) turnRecords.append(copy.deepcopy(turn)) turn.clear() else: # Use old implementation for opponent # ####< Old implementation #### # offer draw face - up iff not 3rd turn with first face up card (decline automatically in that case) if not (turnsTaken == 3 and faceUpCard == firstFaceUpCard): # Moment of decision: draw a face up card? drawFaceUp = players[currentPlayer].willDrawFaceUpCard( faceUpCard) # print("drawFaceUp {}".format(drawFaceUp)) if not drawFaceUp and faceUpCard == firstFaceUpCard and turnsTaken < 2: if playVerbose: print("Player {} declines {}.\n".format( currentPlayer, firstFaceUpCard)) drawCard = discards.pop() if drawFaceUp else deck.pop() for i in range(2): players[i].reportDraw( currentPlayer, drawCard if i == currentPlayer or drawFaceUp else None) if playVerbose: print("Player {} draws {}.\n".format( currentPlayer, drawCard)) hands[currentPlayer].append(drawCard) if drawFaceUp: opponentDrawnCards.append(drawCard) discardCard = players[currentPlayer].getDiscard() if (not (discardCard in hands[currentPlayer]) ) or discardCard == faceUpCard: if playVerbose: print( "Player {} discards {} illegally and forfeits.\n". format(currentPlayer, discardCard)) return opponent hands[currentPlayer].remove(discardCard) opponentDiscardedCards.append(discardCard) revealedCards.append(discardCard) for i in range(2): players[i].reportDiscard(currentPlayer, discardCard) if playVerbose: print("Player {} discards {}.\n".format( currentPlayer, discardCard)) discards.append(discardCard) # if (playVerbose): # if (not bestMelds): #if bestMelds.isEmpty() # print("Player {} has {} with {} deadwood.\n".format(currentPlayer, unmeldedCards, # GinRummyUtil.getDeadwoodPoints(None, None, None, unmeldedCards))) # else: # melds = bestMelds[0] # for meld in melds: # for card in meld: # unmeldedCards.remove(card) # melds.append(unmeldedCards) # print("Player {} has {} with {} deadwood.\n".format(currentPlayer, melds, # GinRummyUtil.getDeadwoodPoints(None, None, None, unmeldedCards))) # only player, not opponent receive revealed cards info # if (currentPlayer == 0): # turn.append(copy.deepcopy(revealedCards)) # csvTurnRecords.append(turn) knockMelds = players[currentPlayer].getFinalMelds() if (knockMelds != None): break #>######################################################################################### turnsTaken = turnsTaken + 1 currentPlayer = 1 if currentPlayer == 0 else 0 opponent = 1 if currentPlayer == 0 else 0 if (knockMelds != None): handBitstring = GinRummyUtil.cardsToBitstring(hands[currentPlayer]) # print("handBitstring {}".format(handBitstring)) unmelded = handBitstring for meld in knockMelds: # print("meld {}".format(meld)) meldBitstring = GinRummyUtil.cardsToBitstring(meld) # print("meldBitstring {}".format(meldBitstring)) if (not (meldBitstring in GinRummyUtil.getAllMeldBitstrings()) ) or ((meldBitstring & unmelded) != meldBitstring): # TODO if playVerbose: print("Player {} melds {} illegally and forfeits.\n". format(currentPlayer, knockMelds)) print("not here 1") return opponent unmelded = unmelded & ~meldBitstring #print("current hand {}".format(hands[currentPlayer])) knockingDeadwood = GinRummyUtil.getDeadwoodPoints( knockMelds, hands[currentPlayer], None, None) # print("knowckingDeadwood {}".format(knockingDeadwood)) if (knockingDeadwood > GinRummyUtil.MAX_DEADWOOD): if (playVerbose): print( "Player {} melds {} with greater than {} deadwood and forfeits.\n" .format(currentPlayer, knockMelds, knockingDeadwood)) print("not here 2") return opponent meldsCopy = [] for i in range(2): # meldsCopy = < <Card>>() for meld in knockMelds: meldsCopy.append(copy.copy(meld)) meldsCopy.append(GinRummyUtil.bitstringToCards(unmelded)) # print("meldsCopy {}".format(meldsCopy)) players[i].reportFinalMelds(currentPlayer, meldsCopy) if playVerbose: if (knockingDeadwood > 0): print("Player {} melds {} with {} deadwood from {}.\n". format(currentPlayer, knockMelds, knockingDeadwood, GinRummyUtil.bitstringToCards(unmelded))) else: print("Player {} goes gin with melds {}.\n".format( currentPlayer, knockMelds)) opponentMelds = players[opponent].getFinalMelds() # print("opponentMelds {}".format(opponentMelds)) opponentHandBitstring = GinRummyUtil.cardsToBitstring( hands[opponent]) # print("opponentHandBitstring {}".format(opponentHandBitstring)) opponentUnmelded = opponentHandBitstring for meld in opponentMelds: meldBitstring = GinRummyUtil.cardsToBitstring(meld) if not (meldBitstring in GinRummyUtil.getAllMeldBitstrings( )) or ((meldBitstring & opponentUnmelded) != meldBitstring): if (playVerbose): print("Player {} melds {} illegally and forfeits.\n". format(opponent, opponentMelds)) print("not here 3") return currentPlayer opponentUnmelded = opponentUnmelded & ~meldBitstring unmeldedCards = GinRummyUtil.bitstringToCards(opponentUnmelded) # print("unmeldedCards {}".format(unmeldedCards)) if (knockingDeadwood > 0): cardWasLaidOff = True while True: cardWasLaidOff = False layOffCard = None layOffMeld = None for card in unmeldedCards: for meld in knockMelds: newMeld = copy.deepcopy(meld) newMeld.append(card) newMeldBitstring = GinRummyUtil.cardsToBitstring( newMeld) if (newMeldBitstring in GinRummyUtil.getAllMeldBitstrings()): layOffCard = card layOffMeld = meld break if (layOffCard != None): if (playVerbose): print("Player {} lays off {} on {}.\n".format( opponent, layOffCard, layOffMeld)) for player in range(2): players[player].reportLayoff( opponent, layOffCard, layOffMeld) unmeldedCards.remove(layOffCard) layOffMeld.append(layOffCard) cardWasLaidOff = True break if (not cardWasLaidOff): break opponentDeadwood = 0 for card in unmeldedCards: opponentDeadwood += GinRummyUtil.getDeadwoodPoints( None, None, card, None) # print("opponentDeadwood {}".format(opponentDeadwood)) if (playVerbose): print("Player {} has {} deadwood with {}\n".format( opponent, opponentDeadwood, unmeldedCards)) if (playVerbose): print("Player {} melds {}.\n".format(opponent, opponentMelds)) for i in range(2): meldsCopy = [] for meld in opponentMelds: meldsCopy.append(copy.copy(meld)) meldsCopy.append(copy.copy(unmeldedCards)) players[i].reportFinalMelds(opponent, meldsCopy) if (knockingDeadwood == 0): scores[ currentPlayer] += GinRummyUtil.GIN_BONUS + opponentDeadwood if (playVerbose): print( "Player {} scores the gin bonus of {} plus opponent deadwood {} for {} total points.\n" .format(currentPlayer, GinRummyUtil.GIN_BONUS, opponentDeadwood, GinRummyUtil.GIN_BONUS + opponentDeadwood)) elif (knockingDeadwood < opponentDeadwood): scores[currentPlayer] += opponentDeadwood - knockingDeadwood if (playVerbose): print("Player {} scores the deadwood difference of {}.\n". format(currentPlayer, opponentDeadwood - knockingDeadwood)) else: scores[ opponent] += GinRummyUtil.UNDERCUT_BONUS + knockingDeadwood - opponentDeadwood if (playVerbose): print( "Player {} undercuts and scores the undercut bonus of {} plus deadwood difference of {} for {} total points.\n" .format( opponent, GinRummyUtil.UNDERCUT_BONUS, knockingDeadwood - opponentDeadwood, GinRummyUtil.UNDERCUT_BONUS + knockingDeadwood - opponentDeadwood)) startingPlayer = 1 if startingPlayer == 0 else 0 else: # If the round ends due to a two card draw pile with no knocking, the round is cancelled. if (playVerbose): print( "The draw pile was reduced to two cards without knocking, so the hand is cancelled." ) # print("scores1 {}, scores2 {}".format(scores[0],scores[1])) # FINAL REPORT for i in range(2): for j in range(2): players[i].reportFinalHand(j, hands[j]) if (playVerbose): print("Player\tScore\n0\t{}\n1\t{}\n".format(scores[0], scores[1])) for i in range(2): players[i].reportScores(copy.deepcopy(scores)) if toCSV: #WRITE TURN DATA TO FILE # write turn data and their according hand outcome to csv file, for training for turn in turnRecords: matrix = arrayToMatrix(turn) for r in range(len(matrix)): out.writerow(matrix[r]) handOutcome = scores[0] - prevScores[0] - scores[ 1] + prevScores[1] outY.writerow([handOutcome]) turnRecords.clear() #if playVerbose: #print("Player {} wins.\n".format(0 if scores[0] > scores[1] else 1)) # winOutcome = [1 if scores[0] > scores[1] else 0, 0 if scores[0] > scores[1] else 1] # for turn in csvGameRecords: # turnPlayer = turn[0] # turn.append(winOutcome[turnPlayer]) # DataCollector.csvRecords.extend(copy.deepcopy(csvGameRecords)) # csvGameRecords.clear() return 0 if scores[0] >= GinRummyUtil.GOAL_SCORE else 1