@Override public int hashCode() { int hs = p0_hand_.size(); if (hs < 0) hs = 0; int res = hs + p0_minions_.size() * 10 + p1_minions_.size() * 100; res += (p0_mana_ <= 0 ? 0 : (p0_mana_ - 1) * 1000); res += ((p0_hero_.getHealth() + p1_hero_.getHealth()) % 100) * 10000; int th = 0; if (hs > 0) { Card cc = p0_hand_.get(0); try { Minion mm = (Minion) cc; th += (cc.hasBeenUsed() ? 1 : 0) + mm.getAttack() + mm.getHealth() + cc.getMana(); } catch (ClassCastException e) { th += (cc.hasBeenUsed() ? 1 : 0) + cc.getMana(); } } if (hs > 1) { Card cc = p0_hand_.get(1); try { Minion mm = (Minion) cc; th += (cc.hasBeenUsed() ? 1 : 0) + mm.getAttack() + mm.getHealth() + cc.getMana(); } catch (ClassCastException e) { th += (cc.hasBeenUsed() ? 1 : 0) + cc.getMana(); } } res += (th % 10) * 1000000; int mh0 = 0; if (p0_minions_.size() > 0) { mh0 += p0_minions_.get(0).getHealth(); } if (p0_minions_.size() > 1) { mh0 += p0_minions_.get(1).getHealth(); } res += (mh0 % 100) * 10000000; int mh1 = 0; if (p1_minions_.size() > 0) { mh1 += p1_minions_.get(0).getHealth(); } if (p1_minions_.size() > 1) { mh1 += p1_minions_.get(1).getHealth(); } res += (mh1 % 20) * 100000000; return res; }
/** Reset the has_been_used state of the cards in hand */ public void resetHand() { for (Card card : p0_hand_) { card.hasBeenUsed(false); } }
// TODO Unused? public HearthTreeNode perform(HearthTreeNode boardState) throws HSException { HearthTreeNode toRet = boardState; PlayerModel actingPlayer = actionPerformerPlayerSide != null ? boardState.data_.modelForSide(actionPerformerPlayerSide) : null; PlayerModel targetPlayer = targetPlayerSide != null ? boardState.data_.modelForSide(targetPlayerSide) : null; switch (verb_) { case USE_CARD: { Card card = actingPlayer.getHand().get(cardOrCharacterIndex_); toRet = card.useOn(targetPlayerSide, targetCharacterIndex, toRet); } break; case HERO_ABILITY: { Hero hero = actingPlayer.getHero(); Minion target = targetPlayer.getCharacter(targetCharacterIndex); toRet = hero.useHeroAbility(targetPlayerSide, target, toRet); } break; case ATTACK: { Minion attacker = actingPlayer.getCharacter(CharacterIndex.fromInteger(cardOrCharacterIndex_)); toRet = attacker.attack(targetPlayerSide, targetCharacterIndex, toRet); } break; case UNTARGETABLE_BATTLECRY: { Minion minion = actingPlayer.getCharacter(CharacterIndex.fromInteger(cardOrCharacterIndex_)); toRet = minion.useUntargetableBattlecry(targetCharacterIndex, toRet); break; } case TARGETABLE_BATTLECRY: { Minion minion = actingPlayer.getCharacter(CharacterIndex.fromInteger(cardOrCharacterIndex_)); toRet = minion.useTargetableBattlecry(targetPlayerSide, targetCharacterIndex, toRet); break; } case START_TURN: { toRet = new HearthTreeNode(Game.beginTurn(boardState.data_.deepCopy())); break; } case END_TURN: { toRet = new HearthTreeNode(Game.endTurn(boardState.data_.deepCopy()).flipPlayers()); break; } case DO_NOT_USE_CARD: { for (Card c : actingPlayer.getHand()) { c.hasBeenUsed(true); } break; } case DO_NOT_ATTACK: { for (Minion minion : actingPlayer.getMinions()) { minion.hasAttacked(true); } actingPlayer.getHero().hasAttacked(true); break; } case DO_NOT_USE_HEROPOWER: { actingPlayer.getHero().hasBeenUsed(true); break; } case RNG: { // We need to perform the current state again if the children don't exist yet. This can // happen in certain replay scenarios. // Do not do this if the previous action was *also* RNG or we will end up in an infinite // loop. if (toRet.isLeaf() && boardState.getAction().verb_ != Verb.RNG) { boardState.data_.getCurrentPlayer().addNumCardsUsed((byte) -1); // do not double count toRet = boardState.getAction().perform(boardState); } // RNG has declared this child happened toRet = toRet.getChildren().get(cardOrCharacterIndex_); break; } case DRAW_CARDS: { // Note, this action only supports drawing cards from the deck. Cards like Ysera or // Webspinner need to be implemented using RNG children. for (int indx = 0; indx < cardOrCharacterIndex_; ++indx) { actingPlayer.drawNextCardFromDeck(); } break; } } return toRet; }