package forge.card.abilityFactory;
import forge.*;
import forge.card.cardFactory.CardFactoryUtil;
import forge.card.spellability.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
/**
* <p>AbilityFactory_Regenerate class.</p>
*
* @author Forge
* @version $Id: $
*/
public class AbilityFactory_Regenerate {
// Ex: A:SP$Regenerate | Cost$W | Tgt$TgtC | SpellDescription$Regenerate target creature.
// http://www.slightlymagic.net/wiki/Forge_AbilityFactory#Regenerate
//**************************************************************
// ********************* Regenerate ****************************
//**************************************************************
/**
* <p>getAbilityRegenerate.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility getAbilityRegenerate(final AbilityFactory af) {
final SpellAbility abRegenerate = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -6386981911243700037L;
@Override
public boolean canPlayAI() {
return regenerateCanPlayAI(af, this);
}
@Override
public void resolve() {
regenerateResolve(af, this);
af.getHostCard().setAbilityUsed(af.getHostCard().getAbilityUsed() + 1);
}
@Override
public String getStackDescription() {
return regenerateStackDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return doTriggerAI(af, this, mandatory);
}
};//Ability_Activated
return abRegenerate;
}
/**
* <p>getSpellRegenerate.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility getSpellRegenerate(final AbilityFactory af) {
final SpellAbility spRegenerate = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -3899905398102316582L;
@Override
public boolean canPlayAI() {
return regenerateCanPlayAI(af, this);
}
@Override
public void resolve() {
regenerateResolve(af, this);
}
@Override
public String getStackDescription() {
return regenerateStackDescription(af, this);
}
}; // Spell
return spRegenerate;
}
/**
* <p>createDrawbackRegenerate.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackRegenerate(final AbilityFactory af) {
final SpellAbility dbRegen = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = -2295483806708528744L;
@Override
public String getStackDescription() {
return regenerateStackDescription(af, this);
}
@Override
public void resolve() {
regenerateResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
return doTriggerAI(af, this, mandatory);
}
};
return dbRegen;
}
/**
* <p>regenerateStackDescription.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a {@link java.lang.String} object.
*/
private static String regenerateStackDescription(AbilityFactory af, SpellAbility sa) {
final HashMap<String, String> params = af.getMapParams();
StringBuilder sb = new StringBuilder();
Card host = af.getHostCard();
ArrayList<Card> tgtCards;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtCards = tgt.getTargetCards();
else
tgtCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
if (tgtCards.size() > 0) {
if (sa instanceof Ability_Sub)
sb.append(" ");
else
sb.append(host).append(" - ");
sb.append("Regenerate ");
Iterator<Card> it = tgtCards.iterator();
while (it.hasNext()) {
Card tgtC = it.next();
if (tgtC.isFaceDown()) sb.append("Morph");
else sb.append(tgtC);
if (it.hasNext()) sb.append(", ");
}
}
sb.append(".");
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}
/**
* <p>regenerateCanPlayAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
private static boolean regenerateCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
final HashMap<String, String> params = af.getMapParams();
final Card hostCard = af.getHostCard();
boolean chance = false;
Cost abCost = af.getAbCost();
if (abCost != null) {
// AI currently disabled for these costs
if (abCost.getSacCost() && !abCost.getSacThis()) {
//only sacrifice something that's supposed to be sacrificed
String type = abCost.getSacType();
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
typeList = typeList.getValidCards(type.split(","), hostCard.getController(), hostCard);
if (ComputerUtil.getCardPreference(hostCard, "SacCost", typeList) == null)
return false;
}
if (abCost.getLifeCost()) {
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
return false;
}
}
if (!ComputerUtil.canPayCost(sa))
return false;
Target tgt = sa.getTarget();
if (tgt == null) {
// As far as I can tell these Defined Cards will only have one of them
ArrayList<Card> list = AbilityFactory.getDefinedCards(hostCard, params.get("Defined"), sa);
if (AllZone.getStack().size() > 0) {
ArrayList<Object> objects = AbilityFactory.predictThreatenedObjects();
for (Card c : list) {
if (objects.contains(c) && c.getShield() == 0)
chance = true;
}
} else {
if (AllZone.getPhase().is(Constant.Phase.Combat_Declare_Blockers_InstantAbility)) {
boolean flag = false;
for (Card c : list) {
if (c.getShield() == 0)
flag |= CombatUtil.combatantWouldBeDestroyed(c);
}
chance = flag;
} else { // if nothing on the stack, and it's not declare blockers. no need to regen
return false;
}
}
} else {
tgt.resetTargets();
// filter AIs battlefield by what I can target
CardList targetables = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
targetables = targetables.getValidCards(tgt.getValidTgts(), AllZone.getComputerPlayer(), hostCard);
if (targetables.size() == 0)
return false;
if (AllZone.getStack().size() > 0) {
// check stack for something on the stack will kill anything i control
ArrayList<Object> objects = AbilityFactory.predictThreatenedObjects();
CardList threatenedTargets = new CardList();
for (Card c : targetables) {
if (!objects.contains(c) && c.getShield() == 0)
threatenedTargets.add(c);
}
// Choose "best" of the remaining to regenerate
tgt.addTarget(CardFactoryUtil.AI_getBestCreature(threatenedTargets));
} else {
if (AllZone.getPhase().is(Constant.Phase.Combat_Declare_Blockers_InstantAbility)) {
CardList combatants = targetables.getType("Creature");
CardListUtil.sortByEvaluateCreature(combatants);
for (Card c : combatants) {
if (c.getShield() == 0 && CombatUtil.combatantWouldBeDestroyed(c)) {
tgt.addTarget(c);
chance = true;
break;
}
}
}
}
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return chance;
}//regenerateCanPlayAI
/**
* <p>doTriggerAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param mandatory a boolean.
* @return a boolean.
*/
private static boolean doTriggerAI(final AbilityFactory af, final SpellAbility sa, boolean mandatory) {
boolean chance = false;
if (!ComputerUtil.canPayCost(sa))
return false;
Target tgt = sa.getTarget();
if (tgt == null) {
// If there's no target on the trigger, just say yes.
chance = true;
} else {
chance = regenMandatoryTarget(af, sa, mandatory);
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.doTrigger(mandatory);
return chance;
}
/**
* <p>regenMandatoryTarget.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param mandatory a boolean.
* @return a boolean.
*/
private static boolean regenMandatoryTarget(AbilityFactory af, SpellAbility sa, boolean mandatory) {
final Card hostCard = af.getHostCard();
Target tgt = sa.getTarget();
tgt.resetTargets();
// filter AIs battlefield by what I can target
CardList targetables = AllZoneUtil.getCardsInPlay();
targetables = targetables.getValidCards(tgt.getValidTgts(), AllZone.getComputerPlayer(), hostCard);
CardList compTargetables = targetables.getController(AllZone.getComputerPlayer());
if (targetables.size() == 0)
return false;
if (!mandatory && compTargetables.size() == 0)
return false;
if (compTargetables.size() > 0) {
CardList combatants = compTargetables.getType("Creature");
CardListUtil.sortByEvaluateCreature(combatants);
if (AllZone.getPhase().is(Constant.Phase.Combat_Declare_Blockers_InstantAbility)) {
for (Card c : combatants) {
if (c.getShield() == 0 && CombatUtil.combatantWouldBeDestroyed(c)) {
tgt.addTarget(c);
return true;
}
}
}
// TODO see if something on the stack is about to kill something i can target
// choose my best X without regen
if (compTargetables.getNotType("Creature").size() == 0) {
for (Card c : combatants) {
if (c.getShield() == 0) {
tgt.addTarget(c);
return true;
}
}
tgt.addTarget(combatants.get(0));
return true;
} else {
CardListUtil.sortByMostExpensive(compTargetables);
for (Card c : compTargetables) {
if (c.getShield() == 0) {
tgt.addTarget(c);
return true;
}
}
tgt.addTarget(compTargetables.get(0));
return true;
}
}
tgt.addTarget(CardFactoryUtil.AI_getCheapestPermanent(targetables, hostCard, true));
return true;
}
/**
* <p>regenerateResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void regenerateResolve(final AbilityFactory af, final SpellAbility sa) {
Card hostCard = af.getHostCard();
final HashMap<String, String> params = af.getMapParams();
ArrayList<Card> tgtCards;
Target tgt = af.getAbTgt();
if (tgt != null)
tgtCards = tgt.getTargetCards();
else
tgtCards = AbilityFactory.getDefinedCards(hostCard, params.get("Defined"), sa);
for (final Card tgtC : tgtCards) {
final Command untilEOT = new Command() {
private static final long serialVersionUID = 1922050611313909200L;
public void execute() {
tgtC.resetShield();
}
};
if (AllZoneUtil.isCardInPlay(tgtC) && (tgt == null || CardFactoryUtil.canTarget(hostCard, tgtC))) {
tgtC.addShield();
AllZone.getEndOfTurn().addUntil(untilEOT);
}
}
}//regenerateResolve
//**************************************************************
// ********************* RegenerateAll *************************
//**************************************************************
/**
* <p>getAbilityRegenerateAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility getAbilityRegenerateAll(final AbilityFactory af) {
final SpellAbility abRegenerateAll = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -3001272997209059394L;
@Override
public boolean canPlayAI() {
return regenerateAllCanPlayAI(af, this);
}
@Override
public void resolve() {
regenerateAllResolve(af, this);
af.getHostCard().setAbilityUsed(af.getHostCard().getAbilityUsed() + 1);
}
@Override
public String getStackDescription() {
return regenerateAllStackDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return regenerateAllDoTriggerAI(af, this, mandatory);
}
};//Ability_Activated
return abRegenerateAll;
}
/**
* <p>getSpellRegenerateAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility getSpellRegenerateAll(final AbilityFactory af) {
final SpellAbility spRegenerateAll = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -4185454527676705881L;
@Override
public boolean canPlayAI() {
return regenerateAllCanPlayAI(af, this);
}
@Override
public void resolve() {
regenerateAllResolve(af, this);
}
@Override
public String getStackDescription() {
return regenerateAllStackDescription(af, this);
}
}; // Spell
return spRegenerateAll;
}
/**
* <p>createDrawbackRegenerateAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackRegenerateAll(final AbilityFactory af) {
final SpellAbility dbRegenAll = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = 4777861790603705572L;
@Override
public String getStackDescription() {
return regenerateAllStackDescription(af, this);
}
@Override
public void resolve() {
regenerateAllResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return true;
}
@Override
public boolean doTrigger(boolean mandatory) {
return regenerateAllDoTriggerAI(af, this, mandatory);
}
};
return dbRegenAll;
}
/**
* <p>regenerateAllStackDescription.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a {@link java.lang.String} object.
*/
private static String regenerateAllStackDescription(AbilityFactory af, SpellAbility sa) {
final HashMap<String, String> params = af.getMapParams();
StringBuilder sb = new StringBuilder();
Card host = af.getHostCard();
if (sa instanceof Ability_Sub)
sb.append(" ");
else
sb.append(host).append(" - ");
String desc = "";
if (params.containsKey("SpellDescription")) {
desc = params.get("SpellDescription");
} else {
desc = "Regenerate all valid cards.";
}
sb.append(desc);
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}
/**
* <p>regenerateAllCanPlayAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @return a boolean.
*/
private static boolean regenerateAllCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
final HashMap<String, String> params = af.getMapParams();
final Card hostCard = af.getHostCard();
boolean chance = false;
Cost abCost = af.getAbCost();
if (abCost != null) {
// AI currently disabled for these costs
if (abCost.getSacCost() && !abCost.getSacThis()) {
//only sacrifice something that's supposed to be sacrificed
String type = abCost.getSacType();
CardList typeList = AllZoneUtil.getPlayerCardsInPlay(AllZone.getComputerPlayer());
typeList = typeList.getValidCards(type.split(","), hostCard.getController(), hostCard);
if (ComputerUtil.getCardPreference(hostCard, "SacCost", typeList) == null)
return false;
}
if (abCost.getLifeCost()) {
if (AllZone.getComputerPlayer().getLife() - abCost.getLifeAmount() < 4)
return false;
}
}
if (!ComputerUtil.canPayCost(sa))
return false;
// filter AIs battlefield by what I can target
String valid = "";
if (params.containsKey("ValidCards"))
valid = params.get("ValidCards");
CardList list = AllZoneUtil.getCardsInPlay();
list = list.getValidCards(valid.split(","), hostCard.getController(), hostCard);
if (list.size() == 0)
return false;
int numSaved = 0;
if (AllZone.getStack().size() > 0) {
//TODO - check stack for something on the stack will kill anything i control
} else {
if (AllZone.getPhase().is(Constant.Phase.Combat_Declare_Blockers_InstantAbility)) {
CardList combatants = list.getType("Creature");
for (Card c : combatants) {
if (c.getShield() == 0 && CombatUtil.combatantWouldBeDestroyed(c)) {
numSaved++;
}
}
}
}
if (numSaved > 1) {
chance = true;
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return chance;
}
/**
* <p>regenerateAllDoTriggerAI.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
* @param mandatory a boolean.
* @return a boolean.
*/
private static boolean regenerateAllDoTriggerAI(final AbilityFactory af, final SpellAbility sa, boolean mandatory) {
boolean chance = true;
if (!ComputerUtil.canPayCost(sa))
return false;
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.doTrigger(mandatory);
return chance;
}
/**
* <p>regenerateAllResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void regenerateAllResolve(final AbilityFactory af, final SpellAbility sa) {
Card hostCard = af.getHostCard();
final HashMap<String, String> params = af.getMapParams();
String valid = "";
if (params.containsKey("ValidCards"))
valid = params.get("ValidCards");
CardList list = AllZoneUtil.getCardsInPlay();
list = list.getValidCards(valid.split(","), hostCard.getController(), hostCard);
for (final Card c : list) {
final Command untilEOT = new Command() {
private static final long serialVersionUID = 259368227093961103L;
public void execute() {
c.resetShield();
}
};
if (AllZoneUtil.isCardInPlay(c)) {
c.addShield();
AllZone.getEndOfTurn().addUntil(untilEOT);
}
}
}//regenerateAllResolve
}//end class AbilityFactory_Regenerate