package com.hearthsim.util.factory;
import com.hearthsim.card.Card;
import com.hearthsim.card.CharacterIndex;
import com.hearthsim.card.Deck;
import com.hearthsim.card.minion.Hero;
import com.hearthsim.card.minion.Minion;
import com.hearthsim.exception.HSException;
import com.hearthsim.model.PlayerModel;
import com.hearthsim.model.PlayerSide;
import com.hearthsim.util.HearthAction;
import com.hearthsim.util.HearthAction.Verb;
import com.hearthsim.util.tree.HearthTreeNode;
import java.util.ArrayList;
public class ChildNodeCreatorBase implements ChildNodeCreator {
/**
* Constructor
* maxThinkTime defaults to 10000 milliseconds (10 seconds)
*/
public ChildNodeCreatorBase(Deck deckPlayer0, Deck deckPlayer1) {
}
@Override
public ArrayList<HearthTreeNode> createAttackChildren(HearthTreeNode boardStateNode) throws HSException {
ArrayList<HearthTreeNode> nodes = new ArrayList<>();
ArrayList<Integer> attackable = boardStateNode.data_.getAttackableMinions();
PlayerModel currentPlayer = boardStateNode.data_.modelForSide(PlayerSide.CURRENT_PLAYER);
HearthTreeNode newState;
Minion tempMinion;
// attack with characters
for (int attackerIndex = 0; attackerIndex < currentPlayer
.getNumCharacters(); ++attackerIndex) {
if (!currentPlayer.getCharacter(CharacterIndex.fromInteger(attackerIndex)).canAttack(boardStateNode.data_, PlayerSide.CURRENT_PLAYER)) {
continue;
}
for (final Integer integer : attackable) {
CharacterIndex targetIndex = CharacterIndex.fromInteger(integer);
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
tempMinion = newState.data_.getCurrentPlayer().getCharacter(CharacterIndex.fromInteger(attackerIndex));
newState = tempMinion.attack(PlayerSide.WAITING_PLAYER, targetIndex, newState);
if (newState != null) {
nodes.add(newState);
}
}
}
// If no nodes were created then nothing could attack. If something could attack, we want to explicitly do nothing in its own node.
if (!nodes.isEmpty()) {
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
newState.setAction(new HearthAction(Verb.DO_NOT_ATTACK));
for (Minion minion : newState.data_.modelForSide(PlayerSide.CURRENT_PLAYER).getMinions()) {
minion.hasAttacked(true);
}
newState.data_.getCurrentPlayer().getHero().hasAttacked(true);
nodes.add(newState);
}
return nodes;
}
@Override
public ArrayList<HearthTreeNode> createPlayCardChildren(HearthTreeNode boardStateNode) throws HSException {
ArrayList<HearthTreeNode> nodes = new ArrayList<>();
Minion targetMinion;
Card card;
Card copiedCard;
HearthTreeNode newState;
PlayerModel currentPlayer = boardStateNode.data_.modelForSide(PlayerSide.CURRENT_PLAYER);
PlayerModel waitingPlayer = boardStateNode.data_.modelForSide(PlayerSide.WAITING_PLAYER);
int mana = boardStateNode.data_.getCurrentPlayer().getMana();
for (int cardIndex = 0; cardIndex < boardStateNode.data_.getCurrentPlayer().getHand().size(); ++cardIndex) {
card = boardStateNode.data_.getCurrentPlayer().getHand().get(cardIndex);
if (card.getManaCost(PlayerSide.CURRENT_PLAYER, boardStateNode.data_) <= mana && !card.hasBeenUsed()) {
// we can use this card! Let's try using it on everything
for (int tIndex = 0; tIndex <= currentPlayer.getNumMinions(); ++tIndex) {
CharacterIndex targetIndex = CharacterIndex.fromInteger(tIndex);
targetMinion = boardStateNode.data_.getCurrentPlayer().getCharacter(targetIndex);
if (card.canBeUsedOn(PlayerSide.CURRENT_PLAYER, targetMinion, boardStateNode.data_)) {
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
copiedCard = newState.data_.getCurrentPlayer().getHand().get(cardIndex);
newState = copiedCard.useOn(PlayerSide.CURRENT_PLAYER, targetIndex, newState);
if (newState != null) {
nodes.add(newState);
}
}
}
for (int tIndex = 0; tIndex <= waitingPlayer.getNumMinions(); ++tIndex) {
CharacterIndex targetIndex = CharacterIndex.fromInteger(tIndex);
targetMinion = boardStateNode.data_.getWaitingPlayer().getCharacter(targetIndex);
if (card.canBeUsedOn(PlayerSide.WAITING_PLAYER, targetMinion, boardStateNode.data_)) {
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
copiedCard = newState.data_.getCurrentPlayer().getHand().get(cardIndex);
newState = copiedCard.useOn(PlayerSide.WAITING_PLAYER, targetIndex, newState);
if (newState != null) {
nodes.add(newState);
}
}
}
}
}
// If no nodes were created then nothing could be played. If something could be played, we want to explicitly do nothing in its own node.
if (!nodes.isEmpty()) {
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
newState.setAction(new HearthAction(Verb.DO_NOT_USE_CARD));
for (Card c : newState.data_.getCurrentPlayer().getHand()) {
c.hasBeenUsed(true);
}
nodes.add(newState);
}
return nodes;
}
@Override
public ArrayList<HearthTreeNode> createHeroAbilityChildren(HearthTreeNode boardStateNode) throws HSException {
ArrayList<HearthTreeNode> nodes = new ArrayList<>();
Hero player = boardStateNode.data_.getCurrentPlayer().getHero();
if (player.hasBeenUsed()) {
return nodes;
}
PlayerModel currentPlayer = boardStateNode.data_.modelForSide(PlayerSide.CURRENT_PLAYER);
PlayerModel waitingPlayer = boardStateNode.data_.modelForSide(PlayerSide.WAITING_PLAYER);
HearthTreeNode newState;
// Case0: Decided to use the hero ability -- Use it on everything!
for (int i = 0; i <= currentPlayer.getNumMinions(); ++i) {
CharacterIndex targetIndex = CharacterIndex.fromInteger(i);
if (player.canBeUsedOn(PlayerSide.CURRENT_PLAYER, targetIndex, boardStateNode.data_)) {
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
newState = newState.data_.getCurrentPlayer().getHero().useHeroAbility(PlayerSide.CURRENT_PLAYER, targetIndex, newState);
if (newState != null) {
nodes.add(newState);
}
}
}
for (int i = 0; i <= waitingPlayer.getNumMinions(); ++i) {
CharacterIndex targetIndex = CharacterIndex.fromInteger(i);
if (player.canBeUsedOn(PlayerSide.WAITING_PLAYER, targetIndex, boardStateNode.data_)) {
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
newState = newState.data_.getCurrentPlayer().getHero().useHeroAbility(PlayerSide.WAITING_PLAYER, targetIndex, newState);
if (newState != null) {
nodes.add(newState);
}
}
}
// Don't need to check hasBeenUsed here because we checked it above
if (!nodes.isEmpty()) {
// Case1: Decided not to use the hero ability
newState = new HearthTreeNode(boardStateNode.data_.deepCopy());
newState.setAction(new HearthAction(Verb.DO_NOT_USE_HEROPOWER));
newState.data_.getCurrentPlayer().getHero().hasBeenUsed(true);
nodes.add(newState);
}
return nodes;
}
}