package net.demilich.metastone.game.spells;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.demilich.metastone.game.Attribute;
import net.demilich.metastone.game.GameContext;
import net.demilich.metastone.game.Player;
import net.demilich.metastone.game.actions.BattlecryAction;
import net.demilich.metastone.game.actions.GameAction;
import net.demilich.metastone.game.cards.Card;
import net.demilich.metastone.game.cards.CardCatalogue;
import net.demilich.metastone.game.cards.CardCollection;
import net.demilich.metastone.game.cards.CardType;
import net.demilich.metastone.game.cards.ChooseOneCard;
import net.demilich.metastone.game.cards.SpellCard;
import net.demilich.metastone.game.entities.Entity;
import net.demilich.metastone.game.events.CardRevealedEvent;
import net.demilich.metastone.game.events.OverloadEvent;
import net.demilich.metastone.game.spells.desc.SpellArg;
import net.demilich.metastone.game.spells.desc.SpellDesc;
import net.demilich.metastone.game.spells.desc.filter.CardFilter;
import net.demilich.metastone.game.spells.desc.source.CardSource;
import net.demilich.metastone.game.targeting.TargetSelection;
public class CastRandomSpellSpell extends Spell {
Logger logger = LoggerFactory.getLogger(CastRandomSpellSpell.class);
public static SpellDesc create(int value) {
Map<SpellArg, Object> arguments = SpellDesc.build(CastRandomSpellSpell.class);
arguments.put(SpellArg.VALUE, value);
return new SpellDesc(arguments);
}
@Override
protected void onCast(GameContext context, Player player, SpellDesc desc, Entity source, Entity target) {
// This spell is crazy.
CardFilter filter = (CardFilter) desc.get(SpellArg.CARD_FILTER);
CardCollection spells = CardCatalogue.query(context.getDeckFormat(), CardType.SPELL);
CardSource cardSource = (CardSource) desc.get(SpellArg.CARD_SOURCE);
if (cardSource != null) {
spells = cardSource.getCards(context, player);
}
CardCollection filteredSpells = new CardCollection();
for (Card spell : spells) {
if (filter == null || filter.matches(context, player, spell)) {
filteredSpells.add(spell);
}
}
// Straight up insane.
// Set behavior to random. Because we're already insane.
// This allows Discover effects and targeting to actually be random.
Player originalPlayer = player;
Player opponent = context.getOpponent(player);
opponent.setAttribute(Attribute.ALL_RANDOM_YOGG_ONLY_FINAL_DESTINATION, true);
player.setAttribute(Attribute.ALL_RANDOM_YOGG_ONLY_FINAL_DESTINATION, true);
// HAHAHAHAHAHAHAHAHAHA!
int numberOfSpellsToCast = desc.getValue(SpellArg.VALUE, context, player, target, source, 1);
for (int i = 0; i < numberOfSpellsToCast; i++) {
// In case Yogg changes sides, this should case who the spells are being cast for.
player = context.getPlayer(source.getOwner());
// If Yogg is removed from the board, stop casting spells.
if (!player.getSummons().contains(source)) {
break;
}
Card randomCard = filteredSpells.getRandom();
logger.debug("Yogg-Saron chooses to play " + randomCard.getName());
CardRevealedEvent revealEvent = new CardRevealedEvent(context, player.getId(), randomCard, 1.2 * (i + 1));
context.fireGameEvent(revealEvent);
if (randomCard instanceof ChooseOneCard && !context.getLogic().hasAttribute(player, Attribute.BOTH_CHOOSE_ONE_OPTIONS)) {
// While it might seem odd to do this, Choose One spells are still chosen
// randomly, even if the choice isn't available.
ChooseOneCard chooseOneCard = (ChooseOneCard) randomCard;
Card[] cards = chooseOneCard.getChoiceCards();
randomCard = cards[context.getLogic().random(cards.length)];
} else if (randomCard instanceof ChooseOneCard && context.getLogic().hasAttribute(player, Attribute.BOTH_CHOOSE_ONE_OPTIONS)) {
ChooseOneCard chooseOneCard = (ChooseOneCard) randomCard;
randomCard = chooseOneCard.getBothChoicesCard();
}
SpellCard spellCard = (SpellCard) randomCard;
if (spellCard.canBeCast(context, player)) {
SpellCard copyCard = spellCard.clone();
context.getLogic().drawSetAsideCard(player.getId(), copyCard);
BattlecryAction battlecry = BattlecryAction.createBattlecry(copyCard.getSpell(), copyCard.getTargetRequirement());
GameAction battlecryAction = null;
battlecry.setSource(copyCard.getReference());
if (battlecry.getTargetRequirement() != TargetSelection.NONE) {
List<Entity> validTargets = context.getLogic().getValidTargets(player.getId(), battlecry);
if (validTargets.isEmpty()) {
continue;
}
List<GameAction> battlecryActions = new ArrayList<>();
for (Entity validTarget : validTargets) {
GameAction targetedBattlecry = battlecry.clone();
targetedBattlecry.setTarget(validTarget);
battlecryActions.add(targetedBattlecry);
}
battlecryAction = battlecryActions.get(context.getLogic().random(battlecryActions.size()));
} else {
battlecryAction = battlecry;
}
context.getLogic().performGameAction(player.getId(), battlecryAction);
// If the card has Overload, then start overloading...
if (spellCard.hasAttribute(Attribute.OVERLOAD)) {
player.modifyAttribute(Attribute.OVERLOAD, spellCard.getAttributeValue(Attribute.OVERLOAD));
context.fireGameEvent(new OverloadEvent(context, player.getId(), spellCard));
}
}
// Technically, this is only half correct. Yogg-Saron should not stop if
// your opponent has died, but should if you do. But, it works for now.
context.getLogic().checkForDeadEntities();
}
opponent.removeAttribute(Attribute.ALL_RANDOM_YOGG_ONLY_FINAL_DESTINATION);
originalPlayer.removeAttribute(Attribute.ALL_RANDOM_YOGG_ONLY_FINAL_DESTINATION);
// *ahem* Back to normal.
}
}