package forge.card.abilityFactory;
import forge.*;
import forge.card.cardFactory.CardFactoryUtil;
import forge.card.spellability.*;
import forge.gui.GuiUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import javax.swing.JOptionPane;
/**
* <p>AbilityFactory_Protection class.</p>
*
* @author dennis.r.friedrichsen (slapshot5 on slightlymagic.net)
* @version $Id: $
*/
public class AbilityFactory_Protection {
/**
* <p>getSpellProtection.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createSpellProtection(final AbilityFactory af) {
SpellAbility spProtect = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 4678736312735724916L;
@Override
public boolean canPlayAI() {
return protectCanPlayAI(af, this);
}
@Override
public String getStackDescription() {
return protectStackDescription(af, this);
}
@Override
public void resolve() {
protectResolve(af, this);
}//resolve
};//SpellAbility
return spProtect;
}
/**
* <p>getAbilityProtection.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createAbilityProtection(final AbilityFactory af) {
final SpellAbility abProtect = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -5295298887428747473L;
@Override
public boolean canPlayAI() {
return protectCanPlayAI(af, this);
}
@Override
public String getStackDescription() {
return protectStackDescription(af, this);
}
@Override
public void resolve() {
protectResolve(af, this);
}//resolve()
@Override
public boolean doTrigger(boolean mandatory) {
return protectTriggerAI(af, this, mandatory);
}
};//SpellAbility
return abProtect;
}
/**
* <p>getDrawbackProtection.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackProtection(final AbilityFactory af) {
SpellAbility dbProtect = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = 8342800124705819366L;
@Override
public boolean canPlayAI() {
return protectCanPlayAI(af, this);
}
@Override
public String getStackDescription() {
return protectStackDescription(af, this);
}
@Override
public void resolve() {
protectResolve(af, this);
}//resolve
@Override
public boolean chkAI_Drawback() {
return protectDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return protectTriggerAI(af, this, mandatory);
}
};//SpellAbility
return dbProtect;
}
private static boolean hasProtectionFrom(Card card, String color) {
ArrayList<String> onlyColors = new ArrayList<String>(Arrays.asList(Constant.Color.onlyColors));
//make sure we have a valid color
if(!onlyColors.contains(color)) return false;
String protection = "Protection from " + color;
if(card.hasKeyword(protection)) return true;
else return false;
}
private static boolean hasProtectionFromAny(Card card, ArrayList<String> colors) {
boolean protect = false;
for(String color : colors) {
protect |= hasProtectionFrom(card, color);
}
return protect;
}
private static boolean hasProtectionFromAll(Card card, ArrayList<String> colors) {
boolean protect = true;
if(colors.size() < 1) return false;
for(String color : colors) {
protect &= hasProtectionFrom(card, color);
}
return protect;
}
/**
* <p>getProtectCreatures.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.CardList} object.
*/
private static CardList getProtectCreatures(AbilityFactory af, SpellAbility sa) {
final Card hostCard = af.getHostCard();
final ArrayList<String> gains = getProtectionList(hostCard, af.getMapParams());
CardList list = AllZoneUtil.getCreaturesInPlay(AllZone.getComputerPlayer());
list = list.filter(new CardListFilter() {
public boolean addCard(Card c) {
if(!CardFactoryUtil.canTarget(hostCard, c))
return false;
//Don't add duplicate protections
if(hasProtectionFromAll(c, gains)) return false;
//will the creature attack (only relevant for sorcery speed)?
if(CardFactoryUtil.AI_doesCreatureAttack(c) && AllZone.getPhase().isBefore(Constant.Phase.Combat_Declare_Attackers)
&& AllZone.getPhase().isPlayerTurn(AllZone.getComputerPlayer()))
return true;
//is the creature blocking and unable to destroy the attacker or would be destroyed itself?
if(c.isBlocking() && (CombatUtil.blockerWouldBeDestroyed(c)
|| CombatUtil.attackerWouldBeDestroyed(AllZone.getCombat().getAttackerBlockedBy(c))))
return true;
//is the creature in blocked and the blocker would survive
if(AllZone.getPhase().isAfter(Constant.Phase.Combat_Declare_Blockers) && AllZone.getCombat().isAttacking(c)
&& AllZone.getCombat().isBlocked(c)
&& CombatUtil.blockerWouldBeDestroyed(AllZone.getCombat().getBlockers(c).get(0)))
return true;
return false;
}
});
return list;
}//getProtectCreatures()
/**
* <p>protectCanPlayAI.</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 protectCanPlayAI(AbilityFactory af, SpellAbility sa) {
HashMap<String,String> params = af.getMapParams();
Card hostCard = af.getHostCard();
// if there is no target and host card isn't in play, don't activate
if(af.getAbTgt() == null && !AllZoneUtil.isCardInPlay(hostCard))
return false;
// temporarily disabled until AI is improved
if(af.getAbCost().getSacCost() && sa.getSourceCard().isCreature()) return false;
if(af.getAbCost().getLifeCost()) {
if(!af.isCurse()) return false; //Use life only to kill creatures
if(AllZone.getComputerPlayer().getLife() - af.getAbCost().getLifeAmount() < 4)
return false;
}
if(af.getAbCost().getSubCounter()) {
// instead of never removing counters, we will have a random possibility of failure.
// all the other tests still need to pass if a counter will be removed
Counters count = af.getAbCost().getCounterType();
double chance = .66;
if(count.equals(Counters.P1P1)) { // 10% chance to remove +1/+1 to protect
chance = .1;
}
else if(count.equals(Counters.CHARGE)) { // 50% chance to remove charge to protect
chance = .5;
}
Random r = MyRandom.random;
if(r.nextFloat() > chance)
return false;
}
if(!ComputerUtil.canPayCost(sa))
return false;
// Phase Restrictions
if(AllZone.getStack().size() == 0 && AllZone.getPhase().isBefore(Constant.Phase.Combat_FirstStrikeDamage)) {
// Instant-speed protections should not be cast outside of combat when the stack is empty
if(!AbilityFactory.isSorcerySpeed(sa))
return false;
}
else if(AllZone.getStack().size() > 0) {
// TODO: protection something only if the top thing on the stack will kill it via damage or destroy
return false;
}
if(af.getAbTgt() == null || !af.getAbTgt().doesTarget()) {
ArrayList<Card> cards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
if(cards.size() == 0)
return false;
/*
// when this happens we need to expand AI to consider if its ok for everything?
for (Card card : cards) {
// TODO: if AI doesn't control Card and Pump is a Curse, than maybe use?
}*/
}
else
return protectTgtAI(af, sa, false);
return false;
}//protectPlayAI()
/**
* <p>protectTgtAI.</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 protectTgtAI(AbilityFactory af, SpellAbility sa, boolean mandatory) {
if (!mandatory && AllZone.getPhase().isAfter(Constant.Phase.Combat_Declare_Blockers_InstantAbility))
return false;
Card source = sa.getSourceCard();
Target tgt = af.getAbTgt();
tgt.resetTargets();
CardList list = getProtectCreatures(af, sa);
list = list.getValidCards(tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard());
/*
* TODO - What this should probably do is if it's time for instants and abilities after Human
* declares attackers, determine desired protection before assigning blockers.
*
* The other time we want protection is if I'm targeted by a damage or destroy spell on the stack
*
* Or, add protection (to make it unblockable) when Compy is attacking.
*/
if(AllZone.getStack().size() == 0) {
// If the cost is tapping, don't activate before declare attack/block
if(sa.getPayCosts() != null && sa.getPayCosts().getTap()) {
if(AllZone.getPhase().isBefore(Constant.Phase.Combat_Declare_Attackers) && AllZone.getPhase().isPlayerTurn(AllZone.getComputerPlayer()))
list.remove(sa.getSourceCard());
if(AllZone.getPhase().isBefore(Constant.Phase.Combat_Declare_Blockers) && AllZone.getPhase().isPlayerTurn(AllZone.getHumanPlayer()))
list.remove(sa.getSourceCard());
}
}
if(list.isEmpty())
return mandatory && protectMandatoryTarget(af, sa, mandatory);
while(tgt.getNumTargeted() < tgt.getMaxTargets(source, sa)) {
Card t = null;
//boolean goodt = false;
if(list.isEmpty()) {
if(tgt.getNumTargeted() < tgt.getMinTargets(source, sa) || tgt.getNumTargeted() == 0) {
if(mandatory)
return protectMandatoryTarget(af, sa, mandatory);
tgt.resetTargets();
return false;
}
else {
// TODO is this good enough? for up to amounts?
break;
}
}
t = CardFactoryUtil.AI_getBestCreature(list);
tgt.addTarget(t);
list.remove(t);
}
return true;
}//protectTgtAI()
/**
* <p>protectMandatoryTarget.</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 protectMandatoryTarget(AbilityFactory af, SpellAbility sa, boolean mandatory) {
final HashMap<String,String> params = af.getMapParams();
final Card host = af.getHostCard();
CardList list = AllZoneUtil.getCardsInPlay();
Target tgt = sa.getTarget();
list = list.getValidCards(tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard());
if(list.size() < tgt.getMinTargets(sa.getSourceCard(), sa)) {
tgt.resetTargets();
return false;
}
// Remove anything that's already been targeted
for(Card c : tgt.getTargetCards())
list.remove(c);
CardList pref = list.getController(AllZone.getComputerPlayer());
pref = pref.filter(new CardListFilter() {
public boolean addCard(Card c) {
return !hasProtectionFromAll(c, getProtectionList(host, params));
}
});
CardList pref2 = list.getController(AllZone.getComputerPlayer());
pref = pref.filter(new CardListFilter() {
public boolean addCard(Card c) {
return !hasProtectionFromAny(c, getProtectionList(host, params));
}
});
CardList forced = list.getController(AllZone.getHumanPlayer());
Card source = sa.getSourceCard();
while(tgt.getNumTargeted() < tgt.getMaxTargets(source, sa)) {
if(pref.isEmpty())
break;
Card c;
if(pref.getNotType("Creature").size() == 0)
c = CardFactoryUtil.AI_getBestCreature(pref);
else
c = CardFactoryUtil.AI_getMostExpensivePermanent(pref, source, true);
pref.remove(c);
tgt.addTarget(c);
}
while(tgt.getNumTargeted() < tgt.getMaxTargets(source, sa)) {
if(pref2.isEmpty())
break;
Card c;
if(pref2.getNotType("Creature").size() == 0)
c = CardFactoryUtil.AI_getBestCreature(pref2);
else
c = CardFactoryUtil.AI_getMostExpensivePermanent(pref2, source, true);
pref2.remove(c);
tgt.addTarget(c);
}
while(tgt.getNumTargeted() < tgt.getMinTargets(source, sa)) {
if(forced.isEmpty())
break;
Card c;
if(forced.getNotType("Creature").size() == 0)
c = CardFactoryUtil.AI_getWorstCreature(forced);
else
c = CardFactoryUtil.AI_getCheapestPermanent(forced, source, true);
forced.remove(c);
tgt.addTarget(c);
}
if(tgt.getNumTargeted() < tgt.getMinTargets(sa.getSourceCard(), sa)) {
tgt.resetTargets();
return false;
}
return true;
}//protectMandatoryTarget()
/**
* <p>protectTriggerAI.</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 protectTriggerAI(AbilityFactory af, SpellAbility sa, boolean mandatory) {
if(!ComputerUtil.canPayCost(sa))
return false;
if(sa.getTarget() == null) {
if(mandatory)
return true;
}
else {
return protectTgtAI(af, sa, mandatory);
}
return true;
}//protectTriggerAI
/**
* <p>protectDrawbackAI.</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 protectDrawbackAI(AbilityFactory af, SpellAbility sa) {
Card host = af.getHostCard();
if(af.getAbTgt() == null || !af.getAbTgt().doesTarget()) {
if(host.isCreature()) {
//TODO
}
}
else
return protectTgtAI(af, sa, false);
return true;
}//protectDrawbackAI()
/**
* <p>protectStackDescription.</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 protectStackDescription(AbilityFactory af, SpellAbility sa) {
HashMap<String,String> params = af.getMapParams();
Card host = af.getHostCard();
final ArrayList<String> gains = getProtectionList(host, params);
boolean choose = (params.containsKey("Choices")) ? true : false;
String joiner = choose ? "or" : "and";
StringBuilder sb = new StringBuilder();
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(" - ");
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(" gain");
if(tgtCards.size() == 1) sb.append("s");
sb.append(" protection from ");
if(choose) sb.append("your choice of ");
for(int i = 0; i < gains.size(); i++) {
if (i != 0)
sb.append(", ");
if (i == gains.size() - 1)
sb.append(joiner).append(" ");
sb.append(gains.get(i));
}
if(!params.containsKey("Permanent"))
sb.append(" until end of turn");
sb.append(".");
}
Ability_Sub abSub = sa.getSubAbility();
if(abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}//protectStackDescription()
/**
* <p>protectResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void protectResolve(AbilityFactory af, SpellAbility sa) {
HashMap<String,String> params = af.getMapParams();
final Card host = af.getHostCard();
boolean isChoice = params.get("Gains").contains("Choice");
ArrayList<String> choices = getProtectionList(host, params);
final ArrayList<String> gains = new ArrayList<String>();
if(isChoice) {
if(sa.getActivatingPlayer().isHuman()) {
Object o = GuiUtils.getChoice("Choose a protection", choices.toArray());
if(null == o) return;
String choice = (String) o;
gains.add(choice);
}
else {
//TODO - needs improvement
String choice = choices.get(0);
gains.add(choice);
JOptionPane.showMessageDialog(null, "Computer chooses "+gains, ""+host, JOptionPane.PLAIN_MESSAGE);
}
}
else
gains.addAll(choices);
ArrayList<Card> tgtCards;
Target tgt = af.getAbTgt();
if(tgt != null) {
tgtCards = tgt.getTargetCards();
}
else {
tgtCards = AbilityFactory.getDefinedCards(host, params.get("Defined"), sa);
}
int size = tgtCards.size();
for(int j = 0; j < size; j++) {
final Card tgtC = tgtCards.get(j);
// only pump things in play
if(!AllZoneUtil.isCardInPlay(tgtC))
continue;
// if this is a target, make sure we can still target now
if(tgt != null && !CardFactoryUtil.canTarget(host, tgtC))
continue;
for(String gain : gains) {
tgtC.addExtrinsicKeyword("Protection from "+gain);
}
if(!params.containsKey("Permanent")) {
// If not Permanent, remove protection at EOT
final Command untilEOT = new Command() {
private static final long serialVersionUID = 7682700789217703789L;
public void execute() {
if(AllZoneUtil.isCardInPlay(tgtC)) {
for (String gain : gains) {
tgtC.removeExtrinsicKeyword("Protection from "+gain);
}
}
}
};
if(params.containsKey("UntilEndOfCombat")) AllZone.getEndOfCombat().addUntil(untilEOT);
else AllZone.getEndOfTurn().addUntil(untilEOT);
}
}
}//protectResolve()
private static ArrayList<String> getProtectionList(Card host, HashMap<String,String> params) {
final ArrayList<String> gains = new ArrayList<String>();
String gainStr = params.get("Gains");
if(gainStr.equals("Choice")) {
String choices = params.get("Choices");
// Replace AnyColor with the 5 colors
if (choices.contains("AnyColor")){
gains.addAll(Arrays.asList(Constant.Color.onlyColors));
choices = choices.replaceAll("AnyColor,?", "");
}
// Add any remaining choices
if (choices.length() > 0)
gains.addAll(Arrays.asList(choices.split(",")));
}
else {
gains.addAll(Arrays.asList(gainStr.split(",")));
}
return gains;
}
// *************************************************************************
// ************************** ProtectionAll ********************************
// *************************************************************************
/**
* <p>getSpellProtectionAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createSpellProtectionAll(final AbilityFactory af) {
SpellAbility spProtectAll = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 7205636088393235571L;
@Override
public boolean canPlayAI() {
return protectAllCanPlayAI(af, this);
}
@Override
public String getStackDescription() {
return protectAllStackDescription(af, this);
}
@Override
public void resolve() {
protectAllResolve(af, this);
}//resolve
};//SpellAbility
return spProtectAll;
}
/**
* <p>getAbilityProtectionAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createAbilityProtectionAll(final AbilityFactory af) {
final SpellAbility abProtectAll = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -8491026929105907288L;
@Override
public boolean canPlayAI() {
return protectAllCanPlayAI(af, this);
}
@Override
public String getStackDescription() {
return protectAllStackDescription(af, this);
}
@Override
public void resolve() {
protectAllResolve(af, this);
}//resolve()
@Override
public boolean doTrigger(boolean mandatory) {
return protectAllTriggerAI(af, this, mandatory);
}
};//SpellAbility
return abProtectAll;
}
/**
* <p>getDrawbackProtectionAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackProtectionAll(final AbilityFactory af) {
SpellAbility dbProtectAll = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = 5096939345199247701L;
@Override
public boolean canPlayAI() {
return protectAllCanPlayAI(af, this);
}
@Override
public String getStackDescription() {
return protectAllStackDescription(af, this);
}
@Override
public void resolve() {
protectAllResolve(af, this);
}//resolve
@Override
public boolean chkAI_Drawback() {
return protectAllDrawbackAI(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return protectAllTriggerAI(af, this, mandatory);
}
};//SpellAbility
return dbProtectAll;
}
/**
* <p>protectAllCanPlayAI.</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 protectAllCanPlayAI(AbilityFactory af, SpellAbility sa) {
Card hostCard = af.getHostCard();
// if there is no target and host card isn't in play, don't activate
if(af.getAbTgt() == null && !AllZoneUtil.isCardInPlay(hostCard))
return false;
// temporarily disabled until AI is improved
if(af.getAbCost().getSacCost()) return false;
if(af.getAbCost().getLifeCost()) {
return false;
}
if(af.getAbCost().getSubCounter()) {
return false;
}
if(!ComputerUtil.canPayCost(sa))
return false;
return false;
}//protectAllCanPlayAI()
/**
* <p>protectAllTriggerAI.</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 protectAllTriggerAI(AbilityFactory af, SpellAbility sa, boolean mandatory) {
if(!ComputerUtil.canPayCost(sa))
return false;
return true;
}//protectAllTriggerAI
/**
* <p>protectAllDrawbackAI.</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 protectAllDrawbackAI(AbilityFactory af, SpellAbility sa) {
return protectAllTriggerAI(af, sa, false);
}//protectAllDrawbackAI()
/**
* <p>protectAllStackDescription.</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 protectAllStackDescription(AbilityFactory af, SpellAbility sa) {
HashMap<String,String> params = af.getMapParams();
Card host = af.getHostCard();
StringBuilder sb = new StringBuilder();
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(" - ");
if (params.containsKey("SpellDescription")) {
sb.append(params.get("SpellDescription"));
} else {
sb.append("Valid card gain protection");
if(!params.containsKey("Permanent"))
sb.append(" until end of turn");
sb.append(".");
}
}
Ability_Sub abSub = sa.getSubAbility();
if(abSub != null) {
sb.append(abSub.getStackDescription());
}
return sb.toString();
}//protectStackDescription()
/**
* <p>protectAllResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void protectAllResolve(AbilityFactory af, SpellAbility sa) {
HashMap<String,String> params = af.getMapParams();
final Card host = af.getHostCard();
boolean isChoice = params.get("Gains").contains("Choice");
ArrayList<String> choices = getProtectionList(host, params);
final ArrayList<String> gains = new ArrayList<String>();
if(isChoice) {
if(sa.getActivatingPlayer().isHuman()) {
Object o = GuiUtils.getChoice("Choose a protection", choices.toArray());
if(null == o) return;
String choice = (String) o;
gains.add(choice);
}
else {
//TODO - needs improvement
String choice = choices.get(0);
gains.add(choice);
JOptionPane.showMessageDialog(null, "Computer chooses "+gains, ""+host, JOptionPane.PLAIN_MESSAGE);
}
}
else
gains.addAll(choices);
String valid = params.get("ValidCards");
CardList list = AllZoneUtil.getCardsInPlay();
list = list.getValidCards(valid, sa.getActivatingPlayer(), host);
for(final Card tgtC : list) {
if(AllZoneUtil.isCardInPlay(tgtC)) {
for(String gain : gains) {
tgtC.addExtrinsicKeyword("Protection from "+gain);
}
if(!params.containsKey("Permanent")) {
// If not Permanent, remove protection at EOT
final Command untilEOT = new Command() {
private static final long serialVersionUID = -6573962672873853565L;
public void execute() {
if(AllZoneUtil.isCardInPlay(tgtC)) {
for (String gain : gains) {
tgtC.removeExtrinsicKeyword("Protection from "+gain);
}
}
}
};
if(params.containsKey("UntilEndOfCombat")) AllZone.getEndOfCombat().addUntil(untilEOT);
else AllZone.getEndOfTurn().addUntil(untilEOT);
}
}
}
}//protectAllResolve()
}//end class AbilityFactory_Protection