mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
refactor AF: ZoneAffecting
some cleanup in BondEffect.java
This commit is contained in:
11
.gitattributes
vendored
11
.gitattributes
vendored
@@ -12490,7 +12490,6 @@ src/main/java/forge/card/abilityfactory/AbilityFactoryReveal.java svneol=native#
|
|||||||
src/main/java/forge/card/abilityfactory/AbilityFactorySacrifice.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactorySacrifice.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactorySetState.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactorySetState.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java -text
|
src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java -text
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryZoneAffecting.java svneol=native#text/plain
|
|
||||||
src/main/java/forge/card/abilityfactory/SpellAiLogic.java -text
|
src/main/java/forge/card/abilityfactory/SpellAiLogic.java -text
|
||||||
src/main/java/forge/card/abilityfactory/SpellEffect.java -text
|
src/main/java/forge/card/abilityfactory/SpellEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/UniversalAbility.java -text
|
src/main/java/forge/card/abilityfactory/UniversalAbility.java -text
|
||||||
@@ -12500,24 +12499,32 @@ src/main/java/forge/card/abilityfactory/ai/AddTurnAi.java svneol=native#text/pla
|
|||||||
src/main/java/forge/card/abilityfactory/ai/AnimateAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/AnimateAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/AnimateAllAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/AnimateAllAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/BondAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/BondAi.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/DiscardAi.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/DrawAi.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/EndTurnAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/ExchangeLifeAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/ExchangeLifeAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/GainLifeAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/GainLifeAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/LoseLifeAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/LoseLifeAi.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/MillAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/PoisonAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/PoisonAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/SetLifeAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/SetLifeAi.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/ShuffleAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/TokenAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/TokenAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/BondEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/BondEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/EndTurnAi.java -text
|
src/main/java/forge/card/abilityfactory/effects/DiscardEffect.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/effects/DrawEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/EndTurnEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/EndTurnEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/ExchangeLifeEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/ExchangeLifeEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/GainLifeEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/GainLifeEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/HelperAnimate.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/effects/HelperAnimate.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/effects/LoseLifeEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/LoseLifeEffect.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/effects/MillEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/PoisonEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/PoisonEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/SetLifeEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/SetLifeEffect.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/effects/ShuffleEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/package-info.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/package-info.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/cardfactory/CardFactory.java svneol=native#text/plain
|
src/main/java/forge/card/cardfactory/CardFactory.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.tools.ant.types.resources.Tokens;
|
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
|
|
||||||
import forge.CardLists;
|
import forge.CardLists;
|
||||||
@@ -215,17 +213,6 @@ public class AbilityFactory {
|
|||||||
return this.abTgt;
|
return this.abTgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Setter for the field <code>abTgt</code>.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param target
|
|
||||||
* a target object.
|
|
||||||
*/
|
|
||||||
public final void setAbTgt(final Target target) {
|
|
||||||
this.abTgt = target;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -707,13 +694,8 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Discard")) {
|
else if (this.api.equals("Discard")) {
|
||||||
if (this.isAb) {
|
ai = new DiscardAi();
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityDiscard(this);
|
se = new DiscardEffect();
|
||||||
} else if (this.isSp) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createSpellDiscard(this);
|
|
||||||
} else if (this.isDb) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackDiscard(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("DrainMana")) {
|
else if (this.api.equals("DrainMana")) {
|
||||||
@@ -727,13 +709,8 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Draw")) {
|
else if (this.api.equals("Draw")) {
|
||||||
if (this.isAb) {
|
ai = new DrawAi();
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityDraw(this);
|
se = new DrawEffect();
|
||||||
} else if (this.isSp) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createSpellDraw(this);
|
|
||||||
} else if (this.isDb) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackDraw(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("EachDamage")) {
|
else if (this.api.equals("EachDamage")) {
|
||||||
@@ -875,13 +852,8 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Mill")) {
|
else if (this.api.equals("Mill")) {
|
||||||
if (this.isAb) {
|
ai = new MillAi();
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityMill(this);
|
se = new MillEffect();
|
||||||
} else if (this.isSp) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createSpellMill(this);
|
|
||||||
} else if (this.isDb) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackMill(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("MoveCounter")) {
|
else if (this.api.equals("MoveCounter")) {
|
||||||
@@ -1189,13 +1161,8 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Shuffle")) {
|
else if (this.api.equals("Shuffle")) {
|
||||||
if (this.isAb) {
|
ai = new ShuffleAi();
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityShuffle(this);
|
se = new ShuffleEffect();
|
||||||
} else if (this.isSp) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createSpellShuffle(this);
|
|
||||||
} else if (this.isDb) {
|
|
||||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackShuffle(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("StoreSVar")) {
|
else if (this.api.equals("StoreSVar")) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -23,5 +23,5 @@ public abstract class SpellAiLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// consider safe
|
// consider safe
|
||||||
public boolean chkAIDrawback(Map<String, String> params, SpellAbility sa) { return true; }
|
public boolean chkAIDrawback(Map<String, String> params, SpellAbility sa, Player aiPlayer) { return true; }
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ class UniversalDrawback extends AbilitySub {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean chkAIDrawback() {
|
public boolean chkAIDrawback() {
|
||||||
boolean chance = ai.chkAIDrawback(params, this);
|
boolean chance = ai.chkAIDrawback(params, this, getActivatingPlayer());
|
||||||
final AbilitySub subAb = getSubAbility();
|
final AbilitySub subAb = getSubAbility();
|
||||||
if (subAb != null) {
|
if (subAb != null) {
|
||||||
chance &= subAb.chkAIDrawback();
|
chance &= subAb.chkAIDrawback();
|
||||||
|
|||||||
@@ -18,25 +18,12 @@
|
|||||||
package forge.card.abilityfactory.ai;
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
import forge.Singletons;
|
|
||||||
import forge.card.spellability.AbilityActivated;
|
|
||||||
import forge.card.spellability.AbilitySub;
|
|
||||||
import forge.card.spellability.Spell;
|
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.spellability.Target;
|
import forge.card.spellability.Target;
|
||||||
import forge.card.abilityfactory.AbilityFactory;
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
import forge.card.abilityfactory.SpellAiLogic;
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
|
||||||
import forge.card.cost.Cost;
|
|
||||||
import forge.game.GameState;
|
|
||||||
import forge.game.phase.ExtraTurn;
|
|
||||||
import forge.game.phase.PhaseType;
|
|
||||||
import forge.game.player.AIPlayer;
|
|
||||||
import forge.game.player.ComputerUtil;
|
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,7 +66,7 @@ public class AddTurnAi extends SpellAiLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa) {
|
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player aiPlayer) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public class AnimateAi extends SpellAiLogic {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean chkAIDrawback(Map<String, String> params, SpellAbility sa) {
|
public boolean chkAIDrawback(Map<String, String> params, SpellAbility sa, Player aiPlayer) {
|
||||||
boolean chance = true;
|
boolean chance = true;
|
||||||
|
|
||||||
if (sa.getTarget() != null) {
|
if (sa.getTarget() != null) {
|
||||||
|
|||||||
204
src/main/java/forge/card/abilityfactory/ai/DiscardAi.java
Normal file
204
src/main/java/forge/card/abilityfactory/ai/DiscardAi.java
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
|
import forge.card.cost.CostUtil;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.ComputerUtil;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
|
public class DiscardAi extends SpellAiLogic {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* discardCanPlayAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI(Player ai, Map<String,String> params, SpellAbility sa) {
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
final Cost abCost = sa.getPayCosts();
|
||||||
|
|
||||||
|
if (abCost != null) {
|
||||||
|
// AI currently disabled for these costs
|
||||||
|
if (!CostUtil.checkSacrificeCost(ai, abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkDiscardCost(ai, abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkRemoveCounterCost(abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean humanHasHand = ai.getOpponent().getCardsIn(ZoneType.Hand).size() > 0;
|
||||||
|
|
||||||
|
if (tgt != null) {
|
||||||
|
if (!discardTargetAI(ai, sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: Add appropriate restrictions
|
||||||
|
final List<Player> players = AbilityFactory.getDefinedPlayers(sa.getSourceCard(),
|
||||||
|
params.get("Defined"), sa);
|
||||||
|
|
||||||
|
if (players.size() == 1) {
|
||||||
|
if (players.get(0).isComputer()) {
|
||||||
|
// the ai should only be using something like this if he has
|
||||||
|
// few cards in hand,
|
||||||
|
// cards like this better have a good drawback to be in the
|
||||||
|
// AIs deck
|
||||||
|
} else {
|
||||||
|
// defined to the human, so that's fine as long the human
|
||||||
|
// has cards
|
||||||
|
if (!humanHasHand) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Both players discard, any restrictions?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!params.get("Mode").equals("Hand") && !params.get("Mode").equals("RevealDiscardAll")) {
|
||||||
|
if (params.get("NumCards").equals("X") && source.getSVar("X").equals("Count$xPaid")) {
|
||||||
|
// Set PayX here to maximum value.
|
||||||
|
final int cardsToDiscard = Math.min(ComputerUtil.determineLeftoverMana(sa, ai), ai.getOpponent()
|
||||||
|
.getCardsIn(ZoneType.Hand).size());
|
||||||
|
source.setSVar("PayX", Integer.toString(cardsToDiscard));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't use draw abilities before main 2 if possible
|
||||||
|
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)
|
||||||
|
&& !params.containsKey("ActivationPhases")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't tap creatures that may be able to block
|
||||||
|
if (ComputerUtil.waitForBlocking(sa) && !params.containsKey("ActivationPhases")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Random r = MyRandom.getRandom();
|
||||||
|
boolean randomReturn = r.nextFloat() <= Math.pow(0.9, sa.getActivationsThisTurn());
|
||||||
|
|
||||||
|
// some other variables here, like handsize vs. maxHandSize
|
||||||
|
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null) {
|
||||||
|
randomReturn &= subAb.chkAIDrawback();
|
||||||
|
}
|
||||||
|
return randomReturn;
|
||||||
|
} // discardCanPlayAI()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* discardTargetAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
private boolean discardTargetAI(final Player ai, final SpellAbility sa) {
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
Player opp = ai.getOpponent();
|
||||||
|
if (opp.getCardsIn(ZoneType.Hand).isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (tgt != null) {
|
||||||
|
if (sa.canTarget(opp)) {
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} // discardTargetAI()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* discardTriggerNoCost.
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doTriggerAINoCost(Player ai, Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
Player opp = ai.getOpponent();
|
||||||
|
if (!discardTargetAI(ai, sa)) {
|
||||||
|
if (mandatory && sa.canTarget(opp)) {
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
} else if (mandatory && sa.canTarget(ai)) {
|
||||||
|
tgt.addTarget(ai);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} // discardTrigger()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* discardCheckDrawbackAI.
|
||||||
|
* </p>
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param subAb
|
||||||
|
* a {@link forge.card.spellability.AbilitySub} object.
|
||||||
|
*
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback(Map<String,String> params, SpellAbility sa, Player ai) {
|
||||||
|
// Drawback AI improvements
|
||||||
|
// if parent draws cards, make sure cards in hand + cards drawn > 0
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
return discardTargetAI(ai, sa);
|
||||||
|
}
|
||||||
|
// TODO: check for some extra things
|
||||||
|
return true;
|
||||||
|
} // discardCheckDrawbackAI()
|
||||||
|
}
|
||||||
311
src/main/java/forge/card/abilityfactory/ai/DrawAi.java
Normal file
311
src/main/java/forge/card/abilityfactory/ai/DrawAi.java
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
* Forge: Play Magic: the Gathering.
|
||||||
|
* Copyright (C) 2011 Forge Team
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
|
import forge.card.cost.CostDiscard;
|
||||||
|
import forge.card.cost.CostPart;
|
||||||
|
import forge.card.cost.CostUtil;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.ComputerUtil;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* drawCanPlayAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
public class DrawAi extends SpellAiLogic {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI(Player ai, Map<String, String> params, SpellAbility sa) {
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
final Cost abCost = sa.getPayCosts();
|
||||||
|
|
||||||
|
if (abCost != null) {
|
||||||
|
// AI currently disabled for these costs
|
||||||
|
if (!CostUtil.checkCreatureSacrificeCost(ai, abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkDiscardCost(ai, abCost, source)) {
|
||||||
|
for (final CostPart part : abCost.getCostParts()) {
|
||||||
|
if (part instanceof CostDiscard) {
|
||||||
|
CostDiscard cd = (CostDiscard) part;
|
||||||
|
cd.decideAIPayment(ai, sa, sa.getSourceCard(), null);
|
||||||
|
List<Card> discards = cd.getList();
|
||||||
|
for (Card discard : discards) {
|
||||||
|
if (!ComputerUtil.isWorseThanDraw(ai, discard)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkRemoveCounterCost(abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean bFlag = targetAI(ai, params, sa, false);
|
||||||
|
|
||||||
|
if (!bFlag) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgt != null) {
|
||||||
|
final ArrayList<Player> players = tgt.getTargetPlayers();
|
||||||
|
if ((players.size() > 0) && players.get(0).isHuman()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't use draw abilities before main 2 if possible
|
||||||
|
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2)
|
||||||
|
&& !params.containsKey("ActivationPhases")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't tap creatures that may be able to block
|
||||||
|
if (ComputerUtil.waitForBlocking(sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double chance = .4; // 40 percent chance of drawing with instant speed
|
||||||
|
// stuff
|
||||||
|
final Random r = MyRandom.getRandom();
|
||||||
|
boolean randomReturn = r.nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
|
||||||
|
if (AbilityFactory.isSorcerySpeed(sa)) {
|
||||||
|
randomReturn = true;
|
||||||
|
}
|
||||||
|
if ((Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.END_OF_TURN)
|
||||||
|
&& Singletons.getModel().getGame().getPhaseHandler().getNextTurn().equals(ai))) {
|
||||||
|
randomReturn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AbilityFactory.playReusable(ai, sa)) {
|
||||||
|
randomReturn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null) {
|
||||||
|
randomReturn &= subAb.chkAIDrawback();
|
||||||
|
}
|
||||||
|
return randomReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* drawTargetAI.
|
||||||
|
* </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 boolean targetAI(final Player ai, final Map<String, String> params, final SpellAbility sa, final boolean mandatory) {
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
|
||||||
|
Player opp = ai.getOpponent();
|
||||||
|
|
||||||
|
int computerHandSize = ai.getCardsIn(ZoneType.Hand).size();
|
||||||
|
final int humanLibrarySize = opp.getCardsIn(ZoneType.Library).size();
|
||||||
|
final int computerLibrarySize = ai.getCardsIn(ZoneType.Library).size();
|
||||||
|
final int computerMaxHandSize = ai.getMaxHandSize();
|
||||||
|
|
||||||
|
//if a spell is used don't count the card
|
||||||
|
if (sa.isSpell() && source.isInZone(ZoneType.Hand)) {
|
||||||
|
computerHandSize -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int numCards = 1;
|
||||||
|
if (params.containsKey("NumCards")) {
|
||||||
|
numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean xPaid = false;
|
||||||
|
final String num = params.get("NumCards");
|
||||||
|
if ((num != null) && num.equals("X") && source.getSVar(num).equals("Count$xPaid")) {
|
||||||
|
// Set PayX here to maximum value.
|
||||||
|
if (sa instanceof AbilitySub) {
|
||||||
|
numCards = Integer.parseInt(source.getSVar("PayX"));
|
||||||
|
} else {
|
||||||
|
numCards = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||||
|
source.setSVar("PayX", Integer.toString(numCards));
|
||||||
|
}
|
||||||
|
xPaid = true;
|
||||||
|
}
|
||||||
|
//if (n)
|
||||||
|
|
||||||
|
// TODO: if xPaid and one of the below reasons would fail, instead of
|
||||||
|
// bailing
|
||||||
|
// reduce toPay amount to acceptable level
|
||||||
|
|
||||||
|
if (tgt != null) {
|
||||||
|
// ability is targeted
|
||||||
|
tgt.resetTargets();
|
||||||
|
|
||||||
|
final boolean canTgtHuman = sa.canTarget(opp);
|
||||||
|
final boolean canTgtComp = sa.canTarget(ai);
|
||||||
|
boolean tgtHuman = false;
|
||||||
|
|
||||||
|
if (!canTgtHuman && !canTgtComp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canTgtHuman && !opp.cantLose() && (numCards >= humanLibrarySize)) {
|
||||||
|
// Deck the Human? DO IT!
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numCards >= computerLibrarySize) {
|
||||||
|
if (xPaid) {
|
||||||
|
numCards = computerLibrarySize - 1;
|
||||||
|
source.setSVar("PayX", Integer.toString(numCards));
|
||||||
|
} else {
|
||||||
|
// Don't deck your self
|
||||||
|
if (!mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tgtHuman = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((computerHandSize + numCards) > computerMaxHandSize)
|
||||||
|
&& Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().isComputer()) {
|
||||||
|
if (xPaid) {
|
||||||
|
numCards = computerMaxHandSize - computerHandSize;
|
||||||
|
source.setSVar("PayX", Integer.toString(numCards));
|
||||||
|
} else {
|
||||||
|
// Don't draw too many cards and then risk discarding cards
|
||||||
|
// at EOT
|
||||||
|
if (!(params.containsKey("NextUpkeep") || (sa instanceof AbilitySub)) && !mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numCards == 0 && !mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!tgtHuman || !canTgtHuman) && canTgtComp) {
|
||||||
|
tgt.addTarget(ai);
|
||||||
|
} else if (mandatory && canTgtHuman) {
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: consider if human is the defined player
|
||||||
|
|
||||||
|
// ability is not targeted
|
||||||
|
if (numCards >= computerLibrarySize) {
|
||||||
|
// Don't deck yourself
|
||||||
|
if (!mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numCards == 0 && !mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((computerHandSize + numCards) > computerMaxHandSize)
|
||||||
|
&& Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn().isComputer()
|
||||||
|
&& !sa.isTrigger()) {
|
||||||
|
// Don't draw too many cards and then risk discarding cards at
|
||||||
|
// EOT
|
||||||
|
if (!(params.containsKey("NextUpkeep") || (sa instanceof AbilitySub)) && !mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} // drawTargetAI()
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* drawTriggerNoCost.
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doTriggerAINoCost(Player ai, java.util.Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||||
|
if (!targetAI(ai, params, sa, mandatory)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check SubAbilities DoTrigger?
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
return abSub.doTrigger(mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package forge.card.abilityfactory.effects;
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ public class EndTurnAi extends SpellAiLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa) { return false; }
|
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player aiPlayer) { return false; }
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
203
src/main/java/forge/card/abilityfactory/ai/MillAi.java
Normal file
203
src/main/java/forge/card/abilityfactory/ai/MillAi.java
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
|
import forge.card.cost.CostUtil;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.ComputerUtil;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
|
public class MillAi extends SpellAiLogic {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* millCanPlayAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI(Player ai, java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
final Cost abCost = sa.getPayCosts();
|
||||||
|
|
||||||
|
if (abCost != null) {
|
||||||
|
// AI currently disabled for these costs
|
||||||
|
if (!CostUtil.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkDiscardCost(ai, abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkSacrificeCost(ai, abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkRemoveCounterCost(abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!targetAI(ai, params, sa, false)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Random r = MyRandom.getRandom();
|
||||||
|
|
||||||
|
// Don't use draw abilities before main 2 if possible
|
||||||
|
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2) && !params.containsKey("ActivationPhases")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't tap creatures that may be able to block
|
||||||
|
if (ComputerUtil.waitForBlocking(sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double chance = .4; // 40 percent chance of milling with instant speed
|
||||||
|
// stuff
|
||||||
|
if (AbilityFactory.isSorcerySpeed(sa)) {
|
||||||
|
chance = .667; // 66.7% chance for sorcery speed
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.END_OF_TURN)
|
||||||
|
&& Singletons.getModel().getGame().getPhaseHandler().getNextTurn().equals(ai))) {
|
||||||
|
chance = .9; // 90% for end of opponents turn
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean randomReturn = r.nextFloat() <= Math.pow(chance, sa.getActivationsThisTurn() + 1);
|
||||||
|
|
||||||
|
if (params.get("NumCards").equals("X") && source.getSVar("X").startsWith("Count$xPaid")) {
|
||||||
|
// Set PayX here to maximum value.
|
||||||
|
final int cardsToDiscard =
|
||||||
|
Math.min(ComputerUtil.determineLeftoverMana(sa, ai), ai.getOpponent().getCardsIn(ZoneType.Library).size());
|
||||||
|
source.setSVar("PayX", Integer.toString(cardsToDiscard));
|
||||||
|
if (cardsToDiscard <= 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AbilityFactory.playReusable(ai, sa)) {
|
||||||
|
randomReturn = true;
|
||||||
|
// some other variables here, like deck size, and phase and other fun stuff
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* millTargetAI.
|
||||||
|
* </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 boolean targetAI(final Player ai, final Map<String, String> params, final SpellAbility sa, final boolean mandatory) {
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
Player opp = ai.getOpponent();
|
||||||
|
|
||||||
|
if (tgt != null) {
|
||||||
|
tgt.resetTargets();
|
||||||
|
if (!sa.canTarget(opp)) {
|
||||||
|
if (mandatory && sa.canTarget(ai)) {
|
||||||
|
tgt.addTarget(ai);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
|
||||||
|
final List<Card> pLibrary = opp.getCardsIn(ZoneType.Library);
|
||||||
|
|
||||||
|
if (pLibrary.size() == 0) { // deck already empty, no need to mill
|
||||||
|
if (!mandatory) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numCards >= pLibrary.size()) {
|
||||||
|
// Can Mill out Human's deck? Do it!
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Obscure case when you know what your top card is so you might?
|
||||||
|
// want to mill yourself here
|
||||||
|
// if (AI wants to mill self)
|
||||||
|
// tgt.addTarget(AllZone.getComputerPlayer());
|
||||||
|
// else
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* millDrawback.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback(Map<String,String> params, SpellAbility sa, Player aiPlayer) {
|
||||||
|
return targetAI(aiPlayer, params, sa, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doTriggerAINoCost(Player aiPlayer, Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||||
|
if (!targetAI(aiPlayer, params, sa, mandatory)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
if (params.get("NumCards").equals("X") && source.getSVar("X").equals("Count$xPaid")) {
|
||||||
|
// Set PayX here to maximum value.
|
||||||
|
final int cardsToDiscard = Math.min(ComputerUtil.determineLeftoverMana(sa, aiPlayer), aiPlayer.getOpponent()
|
||||||
|
.getCardsIn(ZoneType.Library).size());
|
||||||
|
source.setSVar("PayX", Integer.toString(cardsToDiscard));
|
||||||
|
}
|
||||||
|
|
||||||
|
// check SubAbilities DoTrigger?
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
return abSub.doTrigger(mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
98
src/main/java/forge/card/abilityfactory/ai/ShuffleAi.java
Normal file
98
src/main/java/forge/card/abilityfactory/ai/ShuffleAi.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
|
||||||
|
public class ShuffleAi extends SpellAiLogic {
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* shuffleCanPlayAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI(Player aiPlayer, java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
// not really sure when the compy would use this; maybe only after a
|
||||||
|
// human
|
||||||
|
// deliberately put a card on top of their library
|
||||||
|
return false;
|
||||||
|
/*
|
||||||
|
* if (!ComputerUtil.canPayCost(sa)) return false;
|
||||||
|
*
|
||||||
|
* Card source = sa.getSourceCard();
|
||||||
|
*
|
||||||
|
* Random r = MyRandom.random; boolean randomReturn = r.nextFloat() <=
|
||||||
|
* Math.pow(.667, sa.getActivationsThisTurn()+1);
|
||||||
|
*
|
||||||
|
* if (AbilityFactory.playReusable(sa)) randomReturn = true;
|
||||||
|
*
|
||||||
|
* Ability_Sub subAb = sa.getSubAbility(); if (subAb != null)
|
||||||
|
* randomReturn &= subAb.chkAI_Drawback(); return randomReturn;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* shuffleTargetAI.
|
||||||
|
* </p>
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param primarySA
|
||||||
|
* a boolean.
|
||||||
|
* @param mandatory
|
||||||
|
* a boolean.
|
||||||
|
*
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player aiPlayer) {
|
||||||
|
return shuffleTargetAI(sa, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private boolean shuffleTargetAI(final SpellAbility sa, final boolean primarySA, final boolean mandatory) {
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // shuffleTargetAI()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* shuffleTrigger.
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doTriggerAINoCost(Player aiPlayer, java.util.Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||||
|
if (!shuffleTargetAI(sa, false, mandatory)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check SubAbilities DoTrigger?
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
return abSub.doTrigger(mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,10 +26,6 @@ public class BondEffect extends SpellEffect {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
// final Card source = sa.getSourceCard();
|
|
||||||
// final Card host = af.getHostCard();
|
|
||||||
// final Map<String, String> svars = host.getSVars();
|
|
||||||
|
|
||||||
// find card that triggered pairing first
|
// find card that triggered pairing first
|
||||||
ArrayList<Card> trigCards;
|
ArrayList<Card> trigCards;
|
||||||
trigCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
|
trigCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
@@ -48,13 +44,13 @@ public class BondEffect extends SpellEffect {
|
|||||||
|
|
||||||
Card partner = cards.get(0);
|
Card partner = cards.get(0);
|
||||||
// skip choice if only one card on list
|
// skip choice if only one card on list
|
||||||
if (cards.size() > 1 && sa.getActivatingPlayer().isHuman()) {
|
if (cards.size() > 1)
|
||||||
Object o = GuiChoose.one("Select a card to pair with", cards);
|
if ( sa.getActivatingPlayer().isHuman() ) {
|
||||||
|
Card o = GuiChoose.one("Select a card to pair with", cards);
|
||||||
if (o != null) {
|
if (o != null) {
|
||||||
partner = (Card) o;
|
partner = o;
|
||||||
}
|
}
|
||||||
} else if (cards.size() > 1) {
|
} else {
|
||||||
// TODO - Pick best creature instead of just the first on the list
|
// TODO - Pick best creature instead of just the first on the list
|
||||||
partner = CardFactoryUtil.getBestCreatureAI(cards);
|
partner = CardFactoryUtil.getBestCreatureAI(cards);
|
||||||
}
|
}
|
||||||
@@ -62,87 +58,8 @@ public class BondEffect extends SpellEffect {
|
|||||||
// pair choices together
|
// pair choices together
|
||||||
trigCards.get(0).setPairedWith(partner);
|
trigCards.get(0).setPairedWith(partner);
|
||||||
partner.setPairedWith(trigCards.get(0));
|
partner.setPairedWith(trigCards.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
} // bondResolve
|
|
||||||
|
|
||||||
// /**
|
|
||||||
// * <p>
|
|
||||||
// * createSpellBond.
|
|
||||||
// * </p>
|
|
||||||
// *
|
|
||||||
// * @param af
|
|
||||||
// * a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
// * @return a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
// */
|
|
||||||
// public static SpellAbility createSpellBond(final AbilityFactory af) {
|
|
||||||
// final SpellAbility spBond = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
|
|
||||||
// private static final long serialVersionUID = -4047747186919390147L;
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public boolean canPlayAI() {
|
|
||||||
// return AbilityFactoryBond.bondCanPlayAI(af, this);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void resolve() {
|
|
||||||
// AbilityFactoryBond.bondResolve(af, this);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public String getStackDescription() {
|
|
||||||
// return AbilityFactoryBond.bondStackDescription(af, this);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// return spBond;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /**
|
|
||||||
// * <p>
|
|
||||||
// * createDrawbackBond.
|
|
||||||
// * </p>
|
|
||||||
// *
|
|
||||||
// * @param af
|
|
||||||
// * a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
// * @return a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
// */
|
|
||||||
// public static SpellAbility createDrawbackBond(final AbilityFactory af) {
|
|
||||||
// final SpellAbility dbBond = new AbilitySub(af.getHostCard(), af.getAbTgt()) {
|
|
||||||
// private static final long serialVersionUID = -8659938411460952874L;
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void resolve() {
|
|
||||||
// AbilityFactoryBond.bondResolve(af, this);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public boolean chkAIDrawback() {
|
|
||||||
// return AbilityFactoryBond.bondPlayDrawbackAI(af, this);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public String getStackDescription() {
|
|
||||||
// return AbilityFactoryBond.bondStackDescription(af, this);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public boolean doTrigger(final boolean mandatory) {
|
|
||||||
// return AbilityFactoryBond.bondTriggerAI(af, this, mandatory);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// return dbBond;
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* bondStackDescription.
|
|
||||||
* </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.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
public String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
ArrayList<Card> tgts;
|
ArrayList<Card> tgts;
|
||||||
@@ -163,4 +80,4 @@ public class BondEffect extends SpellEffect {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
} // end bondStackDescription()
|
} // end bondStackDescription()
|
||||||
|
|
||||||
} // end class AbilityFactoryBond
|
}
|
||||||
@@ -0,0 +1,355 @@
|
|||||||
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.CardLists;
|
||||||
|
import forge.CardUtil;
|
||||||
|
import forge.GameActionUtil;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.AbilityFactoryReveal;
|
||||||
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.player.ComputerUtil;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.gui.GuiChoose;
|
||||||
|
|
||||||
|
public class DiscardEffect extends SpellEffect {
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* discardStackDescription.
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final String mode = params.get("Mode");
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(sa instanceof AbilitySub)) {
|
||||||
|
sb.append(sa.getSourceCard().getName()).append(" - ");
|
||||||
|
} else {
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String conditionDesc = params.get("ConditionDescription");
|
||||||
|
if (conditionDesc != null) {
|
||||||
|
sb.append(conditionDesc).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgtPlayers.size() > 0) {
|
||||||
|
|
||||||
|
for (final Player p : tgtPlayers) {
|
||||||
|
sb.append(p.toString()).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("RevealYouChoose")) {
|
||||||
|
sb.append("reveals his or her hand.").append(" You choose (");
|
||||||
|
} else if (mode.equals("RevealDiscardAll")) {
|
||||||
|
sb.append("reveals his or her hand. Discard (");
|
||||||
|
} else {
|
||||||
|
sb.append("discards (");
|
||||||
|
}
|
||||||
|
|
||||||
|
int numCards = 1;
|
||||||
|
if (params.containsKey("NumCards")) {
|
||||||
|
numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("Hand")) {
|
||||||
|
sb.append("his or her hand");
|
||||||
|
} else if (mode.equals("RevealDiscardAll")) {
|
||||||
|
sb.append("All");
|
||||||
|
} else {
|
||||||
|
sb.append(numCards);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(")");
|
||||||
|
|
||||||
|
if (mode.equals("RevealYouChoose")) {
|
||||||
|
sb.append(" to discard");
|
||||||
|
} else if (mode.equals("RevealDiscardAll")) {
|
||||||
|
String valid = params.get("DiscardValid");
|
||||||
|
if (valid == null) {
|
||||||
|
valid = "Card";
|
||||||
|
}
|
||||||
|
sb.append(" of type: ").append(valid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("Defined")) {
|
||||||
|
sb.append(" defined cards");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("Random")) {
|
||||||
|
sb.append(" at random.");
|
||||||
|
} else {
|
||||||
|
sb.append(".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
sb.append(abSub.getStackDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
} // discardStackDescription()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* discardResolve.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
final String mode = params.get("Mode");
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Card> discarded = new ArrayList<Card>();
|
||||||
|
|
||||||
|
for (final Player p : tgtPlayers) {
|
||||||
|
if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
||||||
|
if (mode.equals("Defined")) {
|
||||||
|
final ArrayList<Card> toDiscard = AbilityFactory.getDefinedCards(source, params.get("DefinedCards"),
|
||||||
|
sa);
|
||||||
|
for (final Card c : toDiscard) {
|
||||||
|
discarded.addAll(p.discard(c, sa));
|
||||||
|
}
|
||||||
|
if (params.containsKey("RememberDiscarded")) {
|
||||||
|
for (final Card c : discarded) {
|
||||||
|
source.addRemembered(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("Hand")) {
|
||||||
|
final List<Card> list = p.discardHand(sa);
|
||||||
|
if (params.containsKey("RememberDiscarded")) {
|
||||||
|
for (final Card c : list) {
|
||||||
|
source.addRemembered(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("NotRemembered")) {
|
||||||
|
final List<Card> dPHand =
|
||||||
|
CardLists.getValidCards(p.getCardsIn(ZoneType.Hand), "Card.IsNotRemembered", source.getController(), source);
|
||||||
|
for (final Card c : dPHand) {
|
||||||
|
p.discard(c, sa);
|
||||||
|
discarded.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int numCards = 1;
|
||||||
|
if (params.containsKey("NumCards")) {
|
||||||
|
numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
if (p.getCardsIn(ZoneType.Hand).size() > 0
|
||||||
|
&& p.getCardsIn(ZoneType.Hand).size() < numCards) {
|
||||||
|
// System.out.println("Scale down discard from " + numCards + " to " + p.getCardsIn(ZoneType.Hand).size());
|
||||||
|
numCards = p.getCardsIn(ZoneType.Hand).size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode.equals("Random")) {
|
||||||
|
boolean runDiscard = true;
|
||||||
|
if (params.containsKey("Optional")) {
|
||||||
|
if (p.isHuman()) {
|
||||||
|
// TODO Ask if Human would like to discard a card at Random
|
||||||
|
StringBuilder sb = new StringBuilder("Would you like to discard ");
|
||||||
|
sb.append(numCards).append(" random card(s)?");
|
||||||
|
runDiscard = GameActionUtil.showYesNoDialog(source, sb.toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO For now AI will always discard Random used currently with:
|
||||||
|
// Balduvian Horde and similar cards
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runDiscard) {
|
||||||
|
final String valid = params.containsKey("DiscardValid") ? params.get("DiscardValid") : "Card";
|
||||||
|
discarded.addAll(p.discardRandom(numCards, sa, valid));
|
||||||
|
}
|
||||||
|
} else if (mode.equals("TgtChoose") && params.containsKey("UnlessType")) {
|
||||||
|
p.discardUnless(numCards, params.get("UnlessType"), sa);
|
||||||
|
} else if (mode.equals("RevealDiscardAll")) {
|
||||||
|
// Reveal
|
||||||
|
final List<Card> dPHand = p.getCardsIn(ZoneType.Hand);
|
||||||
|
|
||||||
|
if (p.isHuman()) {
|
||||||
|
// "reveal to computer" for information gathering
|
||||||
|
} else {
|
||||||
|
GuiChoose.oneOrNone("Revealed computer hand", dPHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
String valid = params.get("DiscardValid");
|
||||||
|
if (valid == null) {
|
||||||
|
valid = "Card";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valid.contains("X")) {
|
||||||
|
valid = valid.replace("X", Integer.toString(AbilityFactory.calculateAmount(source, "X", sa)));
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Card> dPChHand = CardLists.getValidCards(dPHand, valid.split(","), source.getController(), source);
|
||||||
|
// Reveal cards that will be discarded?
|
||||||
|
for (final Card c : dPChHand) {
|
||||||
|
p.discard(c, sa);
|
||||||
|
discarded.add(c);
|
||||||
|
}
|
||||||
|
} else if (mode.equals("RevealYouChoose") || mode.equals("RevealOppChoose") || mode.equals("TgtChoose")) {
|
||||||
|
// Is Reveal you choose right? I think the wrong player is
|
||||||
|
// being used?
|
||||||
|
List<Card> dPHand = new ArrayList<Card>(p.getCardsIn(ZoneType.Hand));
|
||||||
|
if (dPHand.size() != 0) {
|
||||||
|
if (params.containsKey("RevealNumber")) {
|
||||||
|
String amountString = params.get("RevealNumber");
|
||||||
|
int amount = amountString.matches("[0-9][0-9]?") ? Integer.parseInt(amountString)
|
||||||
|
: CardFactoryUtil.xCount(source, source.getSVar(amountString));
|
||||||
|
dPHand = AbilityFactoryReveal.getRevealedList(p, dPHand, amount, false);
|
||||||
|
}
|
||||||
|
List<Card> dPChHand = new ArrayList<Card>(dPHand);
|
||||||
|
String[] dValid = null;
|
||||||
|
if (params.containsKey("DiscardValid")) { // Restrict card choices
|
||||||
|
dValid = params.get("DiscardValid").split(",");
|
||||||
|
dPChHand = CardLists.getValidCards(dPHand, dValid, source.getController(), source);
|
||||||
|
}
|
||||||
|
Player chooser = p;
|
||||||
|
if (mode.equals("RevealYouChoose")) {
|
||||||
|
chooser = source.getController();
|
||||||
|
} else if (mode.equals("RevealOppChoose")) {
|
||||||
|
chooser = source.getController().getOpponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chooser.isComputer()) {
|
||||||
|
// AI
|
||||||
|
if (p.isComputer()) { // discard AI cards
|
||||||
|
int max = chooser.getCardsIn(ZoneType.Hand).size();
|
||||||
|
max = Math.min(max, numCards);
|
||||||
|
List<Card> list = ComputerUtil.discardNumTypeAI(p, max, dValid, sa);
|
||||||
|
if (mode.startsWith("Reveal")) {
|
||||||
|
GuiChoose.oneOrNone("Computer has chosen", list);
|
||||||
|
}
|
||||||
|
discarded.addAll(list);
|
||||||
|
for (Card card : list) {
|
||||||
|
p.discard(card, sa);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// discard human cards
|
||||||
|
for (int i = 0; i < numCards; i++) {
|
||||||
|
if (dPChHand.size() > 0) {
|
||||||
|
List<Card> goodChoices = CardLists.filter(dPChHand, new Predicate<Card>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(final Card c) {
|
||||||
|
if (c.hasKeyword("If a spell or ability an opponent controls causes you to discard CARDNAME," +
|
||||||
|
" put it onto the battlefield instead of putting it into your graveyard.")
|
||||||
|
|| !c.getSVar("DiscardMe").equals("")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (goodChoices.isEmpty()) {
|
||||||
|
goodChoices = dPChHand;
|
||||||
|
}
|
||||||
|
final List<Card> dChoices = new ArrayList<Card>();
|
||||||
|
if (params.containsKey("DiscardValid")) {
|
||||||
|
final String validString = params.get("DiscardValid");
|
||||||
|
if (validString.contains("Creature") && !validString.contains("nonCreature")) {
|
||||||
|
final Card c = CardFactoryUtil.getBestCreatureAI(goodChoices);
|
||||||
|
if (c != null) {
|
||||||
|
dChoices.add(CardFactoryUtil.getBestCreatureAI(goodChoices));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(goodChoices, CardLists.TextLenReverseComparator);
|
||||||
|
|
||||||
|
CardLists.sortCMC(goodChoices);
|
||||||
|
dChoices.add(goodChoices.get(0));
|
||||||
|
|
||||||
|
final Card dC = goodChoices.get(CardUtil.getRandomIndex(goodChoices));
|
||||||
|
dPChHand.remove(dC);
|
||||||
|
|
||||||
|
if (mode.startsWith("Reveal")) {
|
||||||
|
final List<Card> dCs = new ArrayList<Card>();
|
||||||
|
dCs.add(dC);
|
||||||
|
GuiChoose.oneOrNone("Computer has chosen", dCs);
|
||||||
|
}
|
||||||
|
discarded.add(dC);
|
||||||
|
p.discard(dC, sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// human
|
||||||
|
if (mode.startsWith("Reveal")) {
|
||||||
|
GuiChoose.oneOrNone("Revealed " + p + " hand", dPHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < numCards; i++) {
|
||||||
|
if (dPChHand.size() > 0) {
|
||||||
|
Card dC = null;
|
||||||
|
if (params.containsKey("Optional")) {
|
||||||
|
dC = GuiChoose.oneOrNone("Choose a card to be discarded", dPChHand);
|
||||||
|
} else {
|
||||||
|
dC = GuiChoose.one("Choose a card to be discarded", dPChHand);
|
||||||
|
} if (dC != null) {
|
||||||
|
dPChHand.remove(dC);
|
||||||
|
discarded.add(dC);
|
||||||
|
p.discard(dC, sa);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("RememberDiscarded")) {
|
||||||
|
for (final Card c : discarded) {
|
||||||
|
source.addRemembered(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // discardResolve()
|
||||||
|
|
||||||
|
}
|
||||||
169
src/main/java/forge/card/abilityfactory/effects/DrawEffect.java
Normal file
169
src/main/java/forge/card/abilityfactory/effects/DrawEffect.java
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.GameActionUtil;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.gui.GuiChoose;
|
||||||
|
|
||||||
|
public class DrawEffect extends SpellEffect {
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* drawStackDescription.
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (!(sa instanceof AbilitySub)) {
|
||||||
|
sb.append(sa.getSourceCard().getName()).append(" - ");
|
||||||
|
} else {
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String conditionDesc = params.get("ConditionDescription");
|
||||||
|
if (conditionDesc != null) {
|
||||||
|
sb.append(conditionDesc).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (!params.containsKey("Defined") && tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgtPlayers.size() > 0) {
|
||||||
|
final Iterator<Player> it = tgtPlayers.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
sb.append(it.next().toString());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
sb.append(" and ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int numCards = 1;
|
||||||
|
if (params.containsKey("NumCards")) {
|
||||||
|
numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgtPlayers.size() > 1) {
|
||||||
|
sb.append(" each");
|
||||||
|
}
|
||||||
|
sb.append(" draw");
|
||||||
|
if (tgtPlayers.size() == 1) {
|
||||||
|
sb.append("s");
|
||||||
|
}
|
||||||
|
sb.append(" (").append(numCards).append(")");
|
||||||
|
|
||||||
|
if (params.containsKey("NextUpkeep")) {
|
||||||
|
sb.append(" at the beginning of the next upkeep");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
sb.append(abSub.getStackDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* drawResolve.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
int numCards = 1;
|
||||||
|
if (params.containsKey("NumCards")) {
|
||||||
|
numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (!params.containsKey("Defined") && tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(source, params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean optional = params.containsKey("OptionalDecider");
|
||||||
|
final boolean slowDraw = params.containsKey("NextUpkeep");
|
||||||
|
|
||||||
|
for (final Player p : tgtPlayers) {
|
||||||
|
if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
||||||
|
if (optional) {
|
||||||
|
if (p.isComputer()) {
|
||||||
|
if (numCards >= p.getCardsIn(ZoneType.Library).size()) {
|
||||||
|
// AI shouldn't itself
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Do you want to draw ").append(numCards).append(" cards(s)");
|
||||||
|
|
||||||
|
if (slowDraw) {
|
||||||
|
sb.append(" next upkeep");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append("?");
|
||||||
|
|
||||||
|
if (!GameActionUtil.showYesNoDialog(sa.getSourceCard(), sb.toString())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slowDraw) {
|
||||||
|
for (int i = 0; i < numCards; i++) {
|
||||||
|
p.addSlowtripList(source);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
final List<Card> drawn = p.drawCards(numCards);
|
||||||
|
if (params.containsKey("Reveal")) {
|
||||||
|
GuiChoose.one("Revealing drawn cards", drawn);
|
||||||
|
}
|
||||||
|
if (params.containsKey("RememberDrawn")) {
|
||||||
|
for (final Card c : drawn) {
|
||||||
|
source.addRemembered(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // drawResolve()
|
||||||
|
}
|
||||||
|
// **********************************************************************
|
||||||
|
// ******************************* MILL *********************************
|
||||||
|
// **********************************************************************
|
||||||
140
src/main/java/forge/card/abilityfactory/effects/MillEffect.java
Normal file
140
src/main/java/forge/card/abilityfactory/effects/MillEffect.java
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
public class MillEffect extends SpellEffect {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* millResolve.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
final int numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
final boolean bottom = params.containsKey("FromBottom");
|
||||||
|
|
||||||
|
if (params.containsKey("ForgetOtherRemembered")) {
|
||||||
|
source.clearRemembered();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZoneType destination = ZoneType.smartValueOf(params.get("Destination"));
|
||||||
|
if (destination == null) {
|
||||||
|
destination = ZoneType.Graveyard;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Player p : tgtPlayers) {
|
||||||
|
if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
||||||
|
final List<Card> milled = p.mill(numCards, destination, bottom);
|
||||||
|
if (params.containsKey("RememberMilled")) {
|
||||||
|
for (final Card c : milled) {
|
||||||
|
source.addRemembered(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (params.containsKey("Imprint")) {
|
||||||
|
for (final Card c : milled) {
|
||||||
|
source.addImprinted(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* millStackDescription.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @return a {@link java.lang.String} object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String getStackDescription(Map<String,String> params, SpellAbility sa) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
final int numCards = AbilityFactory.calculateAmount(sa.getSourceCard(), params.get("NumCards"), sa);
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(sa instanceof AbilitySub)) {
|
||||||
|
sb.append(sa.getSourceCard().getName()).append(" - ");
|
||||||
|
} else {
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String conditionDesc = params.get("ConditionDescription");
|
||||||
|
if (conditionDesc != null) {
|
||||||
|
sb.append(conditionDesc).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("StackDescription")) {
|
||||||
|
if (params.get("StackDescription").equals("None")) {
|
||||||
|
sb.append("");
|
||||||
|
} else {
|
||||||
|
sb.append(params.get("StackDescription"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (final Player p : tgtPlayers) {
|
||||||
|
sb.append(p.toString()).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
final ZoneType dest = ZoneType.smartValueOf(params.get("Destination"));
|
||||||
|
if ((dest == null) || dest.equals(ZoneType.Graveyard)) {
|
||||||
|
sb.append("mills ");
|
||||||
|
} else if (dest.equals(ZoneType.Exile)) {
|
||||||
|
sb.append("exiles ");
|
||||||
|
} else if (dest.equals(ZoneType.Ante)) {
|
||||||
|
sb.append("antes ");
|
||||||
|
}
|
||||||
|
sb.append(numCards);
|
||||||
|
sb.append(" card");
|
||||||
|
if (numCards != 1) {
|
||||||
|
sb.append("s");
|
||||||
|
}
|
||||||
|
final String millPosition = params.containsKey("FromBottom") ? "bottom" : "top";
|
||||||
|
sb.append(" from the " + millPosition + " of his or her library.");
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
sb.append(abSub.getStackDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.GameActionUtil;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* shuffleResolve.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class ShuffleEffect extends SpellEffect {
|
||||||
|
@Override
|
||||||
|
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final Card host = sa.getSourceCard();
|
||||||
|
final boolean optional = params.containsKey("Optional");
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Player p : tgtPlayers) {
|
||||||
|
if ((tgt == null) || p.canBeTargetedBy(sa)) {
|
||||||
|
if (optional && sa.getActivatingPlayer().isHuman()
|
||||||
|
&& !GameActionUtil.showYesNoDialog(host, "Have " + p + " shuffle?")) {
|
||||||
|
} else {
|
||||||
|
p.shuffle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (!(sa instanceof AbilitySub)) {
|
||||||
|
sb.append(sa.getSourceCard().getName()).append(" - ");
|
||||||
|
} else {
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
final String conditionDesc = params.get("ConditionDescription");
|
||||||
|
if (conditionDesc != null) {
|
||||||
|
sb.append(conditionDesc).append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tgtPlayers.size() > 0) {
|
||||||
|
final Iterator<Player> it = tgtPlayers.iterator();
|
||||||
|
while (it.hasNext()) {
|
||||||
|
sb.append(it.next().getName());
|
||||||
|
if (it.hasNext()) {
|
||||||
|
sb.append(" and ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append("Error - no target players for Shuffle. ");
|
||||||
|
}
|
||||||
|
sb.append(" shuffle");
|
||||||
|
if (tgtPlayers.size() > 1) {
|
||||||
|
sb.append(" their libraries");
|
||||||
|
} else {
|
||||||
|
sb.append("s his or her library");
|
||||||
|
}
|
||||||
|
sb.append(".");
|
||||||
|
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
sb.append(abSub.getStackDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end class AbilityFactory_ZoneAffecting
|
||||||
@@ -18,7 +18,6 @@
|
|||||||
package forge.card.abilityfactory.effects;
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -28,9 +27,7 @@ import forge.Singletons;
|
|||||||
import forge.card.abilityfactory.AbilityFactory;
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
import forge.card.abilityfactory.SpellEffect;
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
import forge.card.spellability.AbilityActivated;
|
|
||||||
import forge.card.spellability.AbilitySub;
|
import forge.card.spellability.AbilitySub;
|
||||||
import forge.card.spellability.Spell;
|
|
||||||
import forge.card.spellability.SpellAbility;
|
import forge.card.spellability.SpellAbility;
|
||||||
import forge.card.trigger.Trigger;
|
import forge.card.trigger.Trigger;
|
||||||
import forge.card.trigger.TriggerHandler;
|
import forge.card.trigger.TriggerHandler;
|
||||||
|
|||||||
Reference in New Issue
Block a user