public Deathrattle(Deathrattle deathrattle, BattlegroundBoard board) { this._card = deathrattle._card; this._originalBoard = board; this._isPlayer = deathrattle._isPlayer; this._cardIndex = deathrattle._cardIndex; }
public Deathrattle(DeathrattleBattlegroundCard card, BattlegroundBoard board, bool isPlayer, int cardIndex) { this._card = card; this._originalBoard = board; this._isPlayer = isPlayer; this._cardIndex = cardIndex; }
/** Copy constructor. */ public BattlegroundBoard(BattlegroundBoard board) { playerCards = CloneBattlegroundCards(board.playerCards); opponentCards = CloneBattlegroundCards(board.opponentCards); deadPlayerCards = CloneBattlegroundCards(board.deadPlayerCards); deadOpponentCards = CloneBattlegroundCards(board.deadOpponentCards); playerTurn = board.playerTurn; playerIndex = board.playerIndex; opponentIndex = board.opponentIndex; }
/** * Called the first time using this board. Returns two copies of itself one for player start and one for opponent start. * * Note that if a player has priority (i.e. from more cards on board), then there will be only one board returned. */ public List <BattlegroundBoard> Initialize() { List <BattlegroundBoard> boards = new List <BattlegroundBoard>(); if (playerCards.Count >= opponentCards.Count) { BattlegroundBoard playerStartBoard = new BattlegroundBoard(this); playerStartBoard.playerTurn = true; boards.Add(playerStartBoard); } if (opponentCards.Count >= playerCards.Count) { BattlegroundBoard opponentStartBoard = new BattlegroundBoard(this); opponentStartBoard.playerTurn = false; boards.Add(opponentStartBoard); } return(boards); }
public DeathrattleChain(BattlegroundBoard board) : base(null, board, false, -1) { }
private SimulationStats SimulationHelper(BattlegroundBoard originalBoard) { // Base-case. Draw, win, or loss. if (originalBoard.IsDraw()) { return(new SimulationStats(0, 0, 1)); } if (originalBoard.IsWin()) { return(new SimulationStats(1, 0, 0)); } if (originalBoard.IsLoss()) { return(new SimulationStats(0, 1, 0)); } // Go through every possible iteration. List <BattlegroundCard> opponentCards = originalBoard.playerTurn ? originalBoard.opponentCards : originalBoard.playerCards; int playerIndex = originalBoard.playerTurn ? originalBoard.playerIndex : originalBoard.opponentIndex; SimulationStats simulationStats = new SimulationStats(0, 0, 0); // Look for attackable opponent cards. List <int> opponentCardIndices = new List <int>(); List <int> tauntedIndices = new List <int>(); for (int i = 0; i < opponentCards.Count; i++) { if (opponentCards[i].hasTaunt) { tauntedIndices.Add(i); } opponentCardIndices.Add(i); } if (tauntedIndices.Count > 0) { opponentCardIndices = tauntedIndices; } foreach (int index in opponentCardIndices) { BattlegroundBoard boardClone = new BattlegroundBoard(originalBoard); // Update playerCards and opponentCards with our new cloned board. List <BattlegroundCard> playerCards = boardClone.playerTurn ? boardClone.playerCards : boardClone.opponentCards; opponentCards = boardClone.playerTurn ? boardClone.opponentCards : boardClone.playerCards; BattlegroundCard playerCard = playerCards[playerIndex]; List <int> attackableOpponentIndices = new List <int>(); List <BattlegroundCard> attackableOpponentCards = new List <BattlegroundCard>(); if (playerCard.hasCleave) { if (index > 0) { attackableOpponentIndices.Add(index - 1); attackableOpponentCards.Add(opponentCards[index - 1]); } attackableOpponentIndices.Add(index); attackableOpponentCards.Add(opponentCards[index]); if (index < opponentCardIndices.Count - 1) { attackableOpponentIndices.Add(index + 1); attackableOpponentCards.Add(opponentCards[index + 1]); } } else { attackableOpponentIndices.Add(index); attackableOpponentCards.Add(opponentCards[index]); } List <Deathrattle> deathrattles = new List <Deathrattle>(); if (playerCard.hasDivineShield) { playerCard.hasDivineShield = false; } else { if (opponentCards[index].hasPoison) { playerCard.health = 0; } else { playerCard.health -= opponentCards[index].attack; } if (playerCard.health <= 0 && playerCard is DeathrattleBattlegroundCard) { // Note that the "playerCard" is actually the opponent when isPlayerTurn is false. // TODO: Rename playerCard and opponentCard in this instance. deathrattles.Add(new Deathrattle((DeathrattleBattlegroundCard)playerCard, boardClone, boardClone.playerTurn, playerIndex)); } } foreach (int opponentIndex in attackableOpponentIndices) { BattlegroundCard opponentCard = opponentCards[opponentIndex]; if (opponentCard.hasDivineShield) { opponentCard.hasDivineShield = false; } else { if (playerCard.hasPoison) { opponentCard.health = 0; } else { opponentCard.health -= playerCard.attack; } if (opponentCard.health <= 0 && opponentCard is DeathrattleBattlegroundCard) { deathrattles.Add(new Deathrattle((DeathrattleBattlegroundCard)opponentCard, boardClone, !boardClone.playerTurn, opponentIndex)); } } } if (playerCard.health <= 0) { if (boardClone.playerTurn) { boardClone.RemovePlayerCard(playerCard); } else { boardClone.RemoveOpponentCard(playerCard); } } foreach (BattlegroundCard opponentCard in attackableOpponentCards) { if (opponentCard.health <= 0) { if (boardClone.playerTurn) { boardClone.RemoveOpponentCard(opponentCard); } else { boardClone.RemovePlayerCard(opponentCard); } } } List <BattlegroundBoard> boards = new List <BattlegroundBoard>(); while (deathrattles.Count > 0) { foreach (Deathrattle deathrattle in deathrattles) { List <BattlegroundBoard> deathrattleBoards = deathrattle.ApplyDeathrattle(); if (deathrattleBoards != null) { foreach (BattlegroundBoard deathrattleBoard in deathrattleBoards) { boards.Add(deathrattleBoard); } } } deathrattles.Clear(); // Deathrattles could trigger other deathrattles (e.g. Kaboom Bot killing another card). We must now look for dead cards and reapply deathrattles. // TODO: Modulate this logic with the logic from above. List <BattlegroundBoard> boardsToRemove = new List <BattlegroundBoard>(); foreach (BattlegroundBoard board in boards) { bool triggeredDeathrattles = false; List <BattlegroundCard> playerCardsToRemove = new List <BattlegroundCard>(); List <BattlegroundCard> opponentCardsToRemove = new List <BattlegroundCard>(); DeathrattleChain deathrattleChain = new DeathrattleChain(board); for (int j = 0; j < board.playerCards.Count; j++) { if (board.playerCards[j].health <= 0) { playerCardsToRemove.Add(board.playerCards[j]); if (board.playerCards[j] is DeathrattleBattlegroundCard) { triggeredDeathrattles = true; deathrattleChain.AddDeathrattle(new Deathrattle((DeathrattleBattlegroundCard)board.playerCards[j], board, true, j)); } } } for (int j = 0; j < board.opponentCards.Count; j++) { if (board.opponentCards[j].health <= 0) { opponentCardsToRemove.Add(board.opponentCards[j]); if (board.opponentCards[j] is DeathrattleBattlegroundCard) { triggeredDeathrattles = true; deathrattleChain.AddDeathrattle(new Deathrattle((DeathrattleBattlegroundCard)board.opponentCards[j], board, false, j)); } } } foreach (BattlegroundCard card in playerCardsToRemove) { board.RemovePlayerCard(card); } foreach (BattlegroundCard card in opponentCardsToRemove) { board.RemoveOpponentCard(card); } if (triggeredDeathrattles) { deathrattles.Add(deathrattleChain); boardsToRemove.Add(board); } } // Remove any boards that are going to be handled by the newly triggered deathrattles. foreach (BattlegroundBoard board in boardsToRemove) { boards.Remove(board); } } // Continue on with the deathrattle boards, or the original boardClone if there were no deathrattles. if (boards.Count == 0) { boards.Add(boardClone); } foreach (BattlegroundBoard board in boards) { if (board.playerTurn && playerCard.health > 0) { board.playerIndex = board.playerCards.Count > 0 ? ++board.playerIndex : 0; } if (!board.playerTurn && playerCard.health > 0) { board.opponentIndex = board.opponentCards.Count > 0 ? ++board.opponentIndex : 0; } if (board.playerCards.Count > 0) { board.playerIndex %= board.playerCards.Count; } if (board.opponentCards.Count > 0) { board.opponentIndex %= board.opponentCards.Count; } board.playerTurn = !board.playerTurn; simulationStats.Merge(SimulationHelper(board)); } } return(simulationStats); }
public BattlegroundSimulation(List <Entity> playerBoard, List <Entity> opponentBoard, Dictionary <int, Entity> gameEntities) { _originalBoard = new BattlegroundBoard(CreateCards(playerBoard), CreateCards(opponentBoard)); _gameEntities = gameEntities; simulationStats = RunSimulation(); }
// Testing constructor. public BattlegroundSimulation(BattlegroundBoard board) { _originalBoard = board; simulationStats = RunSimulation(); }
private List <BattlegroundCard> GetOpponentCards(BattlegroundBoard board) { return(_isPlayer ? board.opponentCards : board.playerCards); }
private List <BattlegroundBoard> HandleDeathrattles(List <DeathrattleBattlegroundCard.Deathrattle> deathrattles) { if (deathrattles.Count == 0) { return(new List <BattlegroundBoard>()); } List <BattlegroundBoard> boards = new List <BattlegroundBoard>(); foreach (DeathrattleBattlegroundCard.Deathrattle deathrattle in deathrattles) { BattlegroundBoard board = new BattlegroundBoard(_originalBoard); int index = deathrattle.playerCardIndex; foreach (BattlegroundCard card in deathrattle.playerCards) { MaybeAddCard(GetPlayerCards(board), card, index); index++; } index = deathrattle.opponentCardIndex; foreach (BattlegroundCard card in deathrattle.opponentCards) { MaybeAddCard(GetOpponentCards(board), card, index); index++; } foreach (DeathrattleBattlegroundCard.Buff buff in deathrattle.buffs) { List <BattlegroundCard> playerCards = GetPlayerCards(board); List <BattlegroundCard> opponentCards = GetOpponentCards(board); foreach (int i in buff.playerCardIndices) { playerCards[i].attack += buff.attackToAdd; playerCards[i].health += buff.healthToAdd; playerCards[i].hasDivineShield = playerCards[i].hasDivineShield || buff.divineShield; } foreach (int i in buff.opponentCardIndices) { opponentCards[i].attack += buff.attackToAdd; opponentCards[i].health += buff.healthToAdd; opponentCards[i].hasDivineShield = opponentCards[i].hasDivineShield || buff.divineShield; } } foreach (DeathrattleBattlegroundCard.Debuff debuff in deathrattle.debuffs) { List <BattlegroundCard> playerCards = GetPlayerCards(board); List <BattlegroundCard> opponentCards = GetOpponentCards(board); foreach (int i in debuff.playerCardIndices) { playerCards[i].attack = Math.Max(0, playerCards[i].attack - debuff.attackToRemove); if (debuff.healthToRemove > 0 && playerCards[i].hasDivineShield) { playerCards[i].hasDivineShield = false; } else { playerCards[i].health -= debuff.healthToRemove; } } foreach (int i in debuff.opponentCardIndices) { opponentCards[i].attack = Math.Max(0, opponentCards[i].attack - debuff.attackToRemove); if (debuff.healthToRemove > 0 && opponentCards[i].hasDivineShield) { opponentCards[i].hasDivineShield = false; } else { opponentCards[i].health -= debuff.healthToRemove; } } } boards.Add(board); } return(boards); }