package com.hearthsim.util.tree;
import com.hearthsim.card.Deck;
import com.hearthsim.model.PlayerSide;
import com.hearthsim.player.playercontroller.BoardScorer;
import com.hearthsim.util.HearthAction;
/**
* A card draw triggers a stop
*
* Note: a card draw triggers a stop only when it is a card that you draw on your turn.
* Any effects that draws a card for the opponent should just draw the card right away.
*
*/
public class CardDrawNode extends StopNode {
private int numCardsToDraw_;
public CardDrawNode(HearthTreeNode origNode, int numCardsToDraw) {
super(origNode);
numCardsToDraw_ = numCardsToDraw;
}
/**
* Add a number of cards to the draw queue
*
* @param valueToAdd
*/
public void addNumCardsToDraw(int valueToAdd) {
numCardsToDraw_ += valueToAdd;
}
public int getNumCardsToDraw() {
return numCardsToDraw_;
}
/**
* Draw the cards that are queued
* <p>
* This function actually draws the cards that are queued up by the various card draw mechanics.
* This function shouldn't be called by anyone except BoardStateFactory.
*/
private void drawQueuedCard() {
for (int indx = 0; indx < numCardsToDraw_; ++indx) {
data_.getCurrentPlayer().drawNextCardFromDeck();
}
}
public double cardDrawScore(Deck deck, BoardScorer ai) {
int numCardsInDeck = deck.getNumCards();
int numCardsRemaining = numCardsInDeck - data_.getCurrentPlayer().getDeckPos();
int numCardsToActuallyDraw = numCardsToDraw_;
int totalFatigueDamage = 0;
if (numCardsRemaining < numCardsToDraw_) {
//expected fatigue damage
int fatigueDamage = data_.getCurrentPlayer().getFatigueDamage();
for (int i = 0; i < numCardsToDraw_ - numCardsRemaining; ++i) {
totalFatigueDamage += fatigueDamage;
fatigueDamage += 1;
}
numCardsToActuallyDraw = numCardsRemaining;
}
//find the average card score of the remaining cards
double averageCardScore = 0.0;
if (numCardsRemaining > 0) {
for (int indx = data_.getCurrentPlayer().getDeckPos(); indx < numCardsInDeck; ++indx) {
averageCardScore += ai.cardInHandScore(deck.drawCard(indx), this.data_);
}
averageCardScore = averageCardScore / numCardsRemaining;
}
double toRet = averageCardScore * numCardsToActuallyDraw;
int heroHealth = data_.getCurrentPlayer().getHero().getHealth();
int heroArmor = data_.getCurrentPlayer().getHero().getArmor();
int armorLeft = heroArmor > totalFatigueDamage ? heroArmor - totalFatigueDamage : 0;
int healthLeft = armorLeft > 0 ? heroHealth : heroHealth - (totalFatigueDamage - heroArmor);
toRet += ai.heroHealthScore_p0(healthLeft, armorLeft) - ai.heroHealthScore_p0(heroHealth, heroArmor);
//If you are going to draw a card 2 different ways, it is usually better to draw the cards when you have more mana
double manaBenefit = 1.e-2 * data_.getCurrentPlayer().getMana();
toRet += manaBenefit;
return toRet;
}
@Override
public HearthTreeNode finishAllEffects() {
this.drawQueuedCard();
HearthAction drawAction = new HearthAction(HearthAction.Verb.DRAW_CARDS, PlayerSide.CURRENT_PLAYER, this.numCardsToDraw_);
return new HearthTreeNode(this.data_, drawAction, this.score_, this.depth_, this.children_);
}
}