def actions(self, state): results = [] kingdom, deck, hand, drawPile, discardPile, phase, turn, buys, actions, money, cardsPlayed = state if self.endOfGame(state): #Note: Most simulations should never get here. #Returns an "idle" move if the game is over, so that getQ for qLearning doesn't break. return ["idle"] if phase == "buy": results.append(("buy", -1)) handValue = cardUtils.computeHandValue(hand) for cardID in kingdom: if kingdom[cardID] > 0: buyCard = cardUtils.getCardFromID(cardID) if buyCard.cardCost <= money: results.append(("buy", buyCard.cardID)) if phase == "action": results.append(("play", -1)) for cardID in set(hand): card = cardUtils.getCardFromID(cardID) if "action" in card.cardType: results.append(("play", card.cardID)) return results
def __init__(self, mdp, usingCachedWeights=False, cachingWeights=False, cacheStringKey=""): self.handSize = mdp.handSize self.maxTurns = mdp.maxTurns self.bigVPCard = max((cardUtils.getCardFromID(cardID).victoryPoints, cardUtils.getCardFromID(cardID)) for cardID in mdp.startKingdom)[1] self.usingCachedWeights = usingCachedWeights self.cachingWeights = cachingWeights self.cacheStringKey = cacheStringKey return
def printGameHistory(gameHistory, mdp, allPlayerStates=[], playerID=None): #TODO: readability: /3 , * 3 ??? print "player states: ", allPlayerStates for i in range(len(gameHistory) / 3): state = gameHistory[i * 3 + 2] kingdom, deck, hand, drawPile, discardPile, phase, turn, buys, actions, money, cardsPlayed = state print "Turn:", turn, if phase == "buy": print "Money:", money, action = gameHistory[i * 3] if action[0] == 'buy': buy, buyCardID = action if buyCardID == -1: cardName = "None" else: cardName = cardUtils.getCardFromID(buyCardID).cardName print "Action:", buy, cardName else: print action print "Deck after:", cardUtils.printDeck(deck) print "Drew hand: ", hand print "###############################################" if mdp.endOfGame(state): print "end of game" for ID in range(len(allPlayerStates)): kingdom1, deck1, hand1, drawPile1, discardPile1, phase1, turn1, buys1, actions1, money1, cardsPlayed1 = allPlayerStates[ID] otherPlayerStates = list(allPlayerStates) otherPlayerStates.remove(allPlayerStates[ID]) print "Player ", str(ID), "Game Reward: ", str(mdp.computeReward(allPlayerStates[ID], otherPlayerStates)) print "Number of Victory Points:", str(cardUtils.computeVictoryPoints(deck1)) print "Number of Turns:", turn
def computeHandValue(hand): handValue = 0 for cardID in hand: card = cardUtils.getCardFromID(cardID) if card.cardType == "treasure": handValue += card.treasureValue return handValue
def getAction(self, state, actions, otherPlayerStates = []): kingdom, deck, hand, drawPile, discardPile, phase, turn, buys, actions, money, cardsPlayed = state if phase == "buy": handValue = cardUtils.computeHandValue(hand) if handValue > self.bigVPCard.cardCost: return ("buy", self.bigVPCard.cardID) bestTreasureCard = None bestTreasureValue = float('-inf') for cardID in kingdom: card = cardUtils.getCardFromID(cardID) if "treasure" in card.cardType: if card.cardCost <= handValue and card.treasureValue > bestTreasureValue: bestTreasureCard = card bestTreasureValue = card.treasureValue return ("buy", bestTreasureCard.cardID) if phase == "action": return ("play", -1)
def getAction(self, state, actions, otherPlayerStates=[]): kingdom, deck, hand, drawPile, discardPile, phase, turn, buys, actions, money, cardsPlayed = state if phase == "buy": handValue = cardUtils.computeHandValue(hand) if handValue > self.bigVPCard.cardCost: return ("buy", self.bigVPCard.cardID) bestTreasureCard = None bestTreasureValue = float('-inf') for cardID in kingdom: card = cardUtils.getCardFromID(cardID) if "treasure" in card.cardType: if card.cardCost <= handValue and card.treasureValue > bestTreasureValue: bestTreasureCard = card bestTreasureValue = card.treasureValue return ("buy", bestTreasureCard.cardID) if phase == "action": return ("play", -1)
def getBestCardToBuy(self, money, kingdom): #Deal with buying VP cards if money >= 8: return 5 #CardID of province if kingdom[5] <= self.vpParemeters[0]: if money >= 5: return 4 if kingdom[5] <= self.vpParemeters[1]: if money >= 2: return 3 for i in range(len(self.buyList)): cardID, numberToBuy = self.buyList[i] if numberToBuy > 0 and kingdom[cardID] > 0: cardCost = cardUtils.getCardFromID(cardID).cardCost if cardCost <= money: self.buyList[i] = (cardID, numberToBuy - 1) return cardID return -1
def actions(self, state): def computeHandValue(hand): handValue = 0 for cardID in hand: card = cardUtils.getCardFromID(cardID) if card.cardType == "treasure": handValue += card.treasureValue return handValue # BEGIN_YOUR_CODE (around 5 lines of code expected) results = [] results.append(("buy", -1)) deck, hand, drawPile, discardPile, phase, turn = state if turn == self.maxTurns: return [] if phase == "buy": handValue = computeHandValue(hand) for cardID in self.kingdom: buyCard = cardUtils.getCardFromID(cardID) if buyCard.cardCost <= handValue: results.append(("buy", buyCard.cardID)) #print handValue return results
def gameStageFeatureExtractor(state, otherPlayerStates=[]) : kingdom, deck, hand, drawPile, discardPile, phase, turn, buys, actions, money, cardsPlayed = state features = [] #Compute "Stage" of game opponentState = otherPlayerStates[0] oppkingdom, oppdeck, opphand, oppdrawPile, oppdiscardPile, oppphase, oppturn, oppbuys, oppactions, oppmoney, oppcardsPlayed = opponentState gameStage = "Start" if deck[5] > 0 or oppdeck[5] > 0: gameStage = "Middle" if deck[5] + oppdeck[5] > 6: gameStage = "End" deckValue = cardUtils.computeDeckValue(deck) treasureCount = 0 for cardID in deck: if "treasure" in cardUtils.getCardFromID(cardID).cardType: treasureCount += deck[cardID] averageMoneyValue = (deckValue + 0.0) / treasureCount roundedMoneyValue = round(averageMoneyValue, 1) features.append(("AverageMoneyValue:" + str(roundedMoneyValue) + "Stage" + gameStage, 1)) numProvinces = cardUtils.getNumProvinceCards(deck) features.append(("provincesInDeck:" + str(numProvinces) + "Stage:" + gameStage, 1)) for cardID in deck: features.append(("numOfCardsInDeckOfType" + str(cardID) + "=" + str(deck[cardID]) + "Stage:" + gameStage, 1)) vPoints = cardUtils.computeVictoryPoints(deck) maxOtherPlayerVPoints = 0 for state in otherPlayerStates: playerVPoints = cardUtils.computeVPointsFromState(state) if playerVPoints > maxOtherPlayerVPoints: maxOtherPlayerVPoints = playerVPoints vPointsDif = vPoints - maxOtherPlayerVPoints features.append(("vPointsDif" + str(vPointsDif) + "Stage" + gameStage, 1)) return features
def printActions(actions): for action in actions: actionType, cardID = action print actionType, cardUtils.getCardFromID(cardID).cardName, ",", print
def succAndProbs(self, state, action, otherPlayerStates=[]): kingdom, deck, hand, drawPile, discardPile, phase, turn, buys, actions, money, cardsPlayed = state nextDeck = Counter(deck) nextDiscardPile = Counter(discardPile) nextKingdom = Counter(kingdom) nextPhase = phase nextBuys = buys nextActions = actions nextMoney = money actionType, cardID = action results = [] newDrawPile = Counter(drawPile) nextCardsPlayed = Counter(cardsPlayed) if actionType == "play": #Not playing a card (i.e. Playing "None") if cardID == -1: nextMoney += cardUtils.computeHandValue(hand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(hand), util.HashableDict(newDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) else: nextHand = list(hand) #Remove card from hand nextHand.remove(cardID) #Discard the card nextCardsPlayed[cardID] += 1 #Play the card (Deal with the effects) nextActions -= 1 cardEffects = cardUtils.getCardFromID(cardID).effects nextBuys += cardEffects["buys"] nextActions += cardEffects["actions"] nextMoney += cardEffects["money"] #Draw cards numCardsToDraw = cardEffects["cards"] if numCardsToDraw == 0: if nextActions == 0: nextMoney += cardUtils.computeHandValue(nextHand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(newDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) else: newHand = list(nextHand) if sum(newDrawPile.values()) + sum(nextDiscardPile.values()) < numCardsToDraw: #Draw the rest of the deck for cardID in newDrawPile.keys(): for i in range(newDrawPile[cardID]): newHand.append(cardID) newDrawPile[cardID] -= 1 numCardsToDraw -= 1 #Draw the rest of the discard pile for cardID in nextDiscardPile.keys(): for i in range(nextDiscardPile[cardID]): newHand.append(cardID) nextDiscardPile[cardID] -= 1 numCardsToDraw -= 1 nextHand = newHand nextHand.sort() nextDrawPile = Counter(newDrawPile) if nextActions == 0: nextMoney += cardUtils.computeHandValue(nextHand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(nextDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) else: if sum(newDrawPile.values()) < numCardsToDraw: #Draw the rest of the deck for cardID in newDrawPile.keys(): for i in range(newDrawPile[cardID]): newHand.append(cardID) newDrawPile[cardID] -= 1 numCardsToDraw -= 1 #Reshuffle newDrawPile = nextDiscardPile nextDiscardPile = Counter() numHands = util.nchoosek(sum(newDrawPile.values()), numCardsToDraw) handsAndProbs = [] computeHandsAndProbs(kingdom, [], numHands, handsAndProbs, Counter(newDrawPile), 0, numCardsToDraw) results = [] tempMoney = nextMoney for handAddition, prob in handsAndProbs: nextMoney = tempMoney nextHand = newHand + handAddition nextHand.sort() nextDrawPile = Counter(newDrawPile) for cardID in handAddition: nextDrawPile[cardID] -= 1 if nextActions == 0: nextMoney += cardUtils.computeHandValue(nextHand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(nextDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) results.append((newState, prob)) # if actionType == "buy": if cardID != -1: #Buy the card nextDeck[cardID] += 1 nextDiscardPile[cardID] += 1 nextKingdom[cardID] -= 1 nextBuys -= 1 nextMoney -= cardUtils.getCardFromID(cardID).cardCost #Start a new turn if we choose to buy nothing or only have one card to buy if buys == 1 or cardID == -1: #Discard the action cards we played nextDiscardPile += nextCardsPlayed nextCardsPlayed = Counter() turn += 1 nextBuys = 1 nextMoney = 0 nextActions = 1 nextPhase = "action" #Discard your hand for cardID in hand: nextDiscardPile[cardID] += 1 #Compute new hands and probabilities newHand = [] handSize = self.handSize newDrawPile = Counter(drawPile) if sum(newDrawPile.values()) < self.handSize: #Reshuffle. for cardID in newDrawPile.keys(): for i in range(newDrawPile[cardID]): newHand.append(cardID) newDrawPile[cardID] -= 1 handSize -= 1 newDrawPile = nextDiscardPile nextDiscardPile = Counter() numHands = util.nchoosek(sum(newDrawPile.values()), handSize) handsAndProbs = [] computeHandsAndProbs(kingdom, [], numHands, handsAndProbs, Counter(newDrawPile), 0, handSize) results = [] for handAddition, prob in handsAndProbs: nextHand = newHand + handAddition nextHand.sort() nextDrawPile = Counter(newDrawPile) for cardID in handAddition: nextDrawPile[cardID] -= 1 newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(nextDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) results.append((newState, prob)) else: newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(hand), util.HashableDict(newDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) return results
def succAndProbs(self, state, action, otherPlayerStates=[]): kingdom, deck, hand, drawPile, discardPile, phase, turn, buys, actions, money, cardsPlayed = state nextDeck = Counter(deck) nextDiscardPile = Counter(discardPile) nextKingdom = Counter(kingdom) nextPhase = phase nextBuys = buys nextActions = actions nextMoney = money actionType, cardID = action results = [] newDrawPile = Counter(drawPile) nextCardsPlayed = Counter(cardsPlayed) if actionType == "play": #Not playing a card (i.e. Playing "None") if cardID == -1: nextMoney += cardUtils.computeHandValue(hand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(hand), util.HashableDict(newDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) else: nextHand = list(hand) #Remove card from hand nextHand.remove(cardID) #Discard the card nextCardsPlayed[cardID] += 1 #Play the card (Deal with the effects) nextActions -= 1 cardEffects = cardUtils.getCardFromID(cardID).effects nextBuys += cardEffects["buys"] nextActions += cardEffects["actions"] nextMoney += cardEffects["money"] #Draw cards numCardsToDraw = cardEffects["cards"] if numCardsToDraw == 0: if nextActions == 0: nextMoney += cardUtils.computeHandValue(nextHand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(newDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) else: newHand = list(nextHand) if sum(newDrawPile.values()) + sum( nextDiscardPile.values()) < numCardsToDraw: #Draw the rest of the deck for cardID in newDrawPile.keys(): for i in range(newDrawPile[cardID]): newHand.append(cardID) newDrawPile[cardID] -= 1 numCardsToDraw -= 1 #Draw the rest of the discard pile for cardID in nextDiscardPile.keys(): for i in range(nextDiscardPile[cardID]): newHand.append(cardID) nextDiscardPile[cardID] -= 1 numCardsToDraw -= 1 nextHand = newHand nextHand.sort() nextDrawPile = Counter(newDrawPile) if nextActions == 0: nextMoney += cardUtils.computeHandValue(nextHand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(nextDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) else: if sum(newDrawPile.values()) < numCardsToDraw: #Draw the rest of the deck for cardID in newDrawPile.keys(): for i in range(newDrawPile[cardID]): newHand.append(cardID) newDrawPile[cardID] -= 1 numCardsToDraw -= 1 #Reshuffle newDrawPile = nextDiscardPile nextDiscardPile = Counter() numHands = util.nchoosek(sum(newDrawPile.values()), numCardsToDraw) handsAndProbs = [] computeHandsAndProbs(kingdom, [], numHands, handsAndProbs, Counter(newDrawPile), 0, numCardsToDraw) results = [] tempMoney = nextMoney for handAddition, prob in handsAndProbs: nextMoney = tempMoney nextHand = newHand + handAddition nextHand.sort() nextDrawPile = Counter(newDrawPile) for cardID in handAddition: nextDrawPile[cardID] -= 1 if nextActions == 0: nextMoney += cardUtils.computeHandValue( nextHand) nextPhase = "buy" newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(nextDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) results.append((newState, prob)) # if actionType == "buy": if cardID != -1: #Buy the card nextDeck[cardID] += 1 nextDiscardPile[cardID] += 1 nextKingdom[cardID] -= 1 nextBuys -= 1 nextMoney -= cardUtils.getCardFromID(cardID).cardCost #Start a new turn if we choose to buy nothing or only have one card to buy if buys == 1 or cardID == -1: #Discard the action cards we played nextDiscardPile += nextCardsPlayed nextCardsPlayed = Counter() turn += 1 nextBuys = 1 nextMoney = 0 nextActions = 1 nextPhase = "action" #Discard your hand for cardID in hand: nextDiscardPile[cardID] += 1 #Compute new hands and probabilities newHand = [] handSize = self.handSize newDrawPile = Counter(drawPile) if sum(newDrawPile.values()) < self.handSize: #Reshuffle. for cardID in newDrawPile.keys(): for i in range(newDrawPile[cardID]): newHand.append(cardID) newDrawPile[cardID] -= 1 handSize -= 1 newDrawPile = nextDiscardPile nextDiscardPile = Counter() numHands = util.nchoosek(sum(newDrawPile.values()), handSize) handsAndProbs = [] computeHandsAndProbs(kingdom, [], numHands, handsAndProbs, Counter(newDrawPile), 0, handSize) results = [] for handAddition, prob in handsAndProbs: nextHand = newHand + handAddition nextHand.sort() nextDrawPile = Counter(newDrawPile) for cardID in handAddition: nextDrawPile[cardID] -= 1 newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(nextHand), util.HashableDict(nextDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) results.append((newState, prob)) else: newState = (util.HashableDict(nextKingdom), util.HashableDict(nextDeck), tuple(hand), util.HashableDict(newDrawPile), util.HashableDict(nextDiscardPile), nextPhase, turn, nextBuys, nextActions, nextMoney, util.HashableDict(nextCardsPlayed)) prob = 1 results.append((newState, prob)) return results