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/AbilityFactorySetState.java svneol=native#text/plain
|
||||
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/SpellEffect.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/AnimateAllAi.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/GainLifeAi.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/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/effects/AddTurnEffect.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/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/ExchangeLifeEffect.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/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/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/package-info.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.List;
|
||||
|
||||
import org.apache.tools.ant.types.resources.Tokens;
|
||||
|
||||
import forge.Card;
|
||||
|
||||
import forge.CardLists;
|
||||
@@ -215,17 +213,6 @@ public class AbilityFactory {
|
||||
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>
|
||||
@@ -707,13 +694,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("Discard")) {
|
||||
if (this.isAb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityDiscard(this);
|
||||
} else if (this.isSp) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createSpellDiscard(this);
|
||||
} else if (this.isDb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackDiscard(this);
|
||||
}
|
||||
ai = new DiscardAi();
|
||||
se = new DiscardEffect();
|
||||
}
|
||||
|
||||
else if (this.api.equals("DrainMana")) {
|
||||
@@ -727,13 +709,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("Draw")) {
|
||||
if (this.isAb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityDraw(this);
|
||||
} else if (this.isSp) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createSpellDraw(this);
|
||||
} else if (this.isDb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackDraw(this);
|
||||
}
|
||||
ai = new DrawAi();
|
||||
se = new DrawEffect();
|
||||
}
|
||||
|
||||
else if (this.api.equals("EachDamage")) {
|
||||
@@ -875,13 +852,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("Mill")) {
|
||||
if (this.isAb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityMill(this);
|
||||
} else if (this.isSp) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createSpellMill(this);
|
||||
} else if (this.isDb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackMill(this);
|
||||
}
|
||||
ai = new MillAi();
|
||||
se = new MillEffect();
|
||||
}
|
||||
|
||||
else if (this.api.equals("MoveCounter")) {
|
||||
@@ -1189,13 +1161,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("Shuffle")) {
|
||||
if (this.isAb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createAbilityShuffle(this);
|
||||
} else if (this.isSp) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createSpellShuffle(this);
|
||||
} else if (this.isDb) {
|
||||
spellAbility = AbilityFactoryZoneAffecting.createDrawbackShuffle(this);
|
||||
}
|
||||
ai = new ShuffleAi();
|
||||
se = new ShuffleEffect();
|
||||
}
|
||||
|
||||
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
|
||||
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
|
||||
public boolean chkAIDrawback() {
|
||||
boolean chance = ai.chkAIDrawback(params, this);
|
||||
boolean chance = ai.chkAIDrawback(params, this, getActivatingPlayer());
|
||||
final AbilitySub subAb = getSubAbility();
|
||||
if (subAb != null) {
|
||||
chance &= subAb.chkAIDrawback();
|
||||
|
||||
@@ -18,25 +18,12 @@
|
||||
package forge.card.abilityfactory.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
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.Target;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -79,7 +66,7 @@ public class AddTurnAi extends SpellAiLogic {
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ public class AnimateAi extends SpellAiLogic {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback(Map<String, String> params, SpellAbility sa) {
|
||||
public boolean chkAIDrawback(Map<String, String> params, SpellAbility sa, Player aiPlayer) {
|
||||
boolean chance = true;
|
||||
|
||||
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;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class EndTurnAi extends SpellAiLogic {
|
||||
}
|
||||
|
||||
@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)
|
||||
* @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
|
||||
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
|
||||
ArrayList<Card> trigCards;
|
||||
trigCards = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
|
||||
@@ -48,119 +44,40 @@ public class BondEffect extends SpellEffect {
|
||||
|
||||
Card partner = cards.get(0);
|
||||
// skip choice if only one card on list
|
||||
if (cards.size() > 1 && sa.getActivatingPlayer().isHuman()) {
|
||||
Object o = GuiChoose.one("Select a card to pair with", cards);
|
||||
|
||||
if (o != null) {
|
||||
partner = (Card) o;
|
||||
if (cards.size() > 1)
|
||||
if ( sa.getActivatingPlayer().isHuman() ) {
|
||||
Card o = GuiChoose.one("Select a card to pair with", cards);
|
||||
if (o != null) {
|
||||
partner = o;
|
||||
}
|
||||
} else {
|
||||
// TODO - Pick best creature instead of just the first on the list
|
||||
partner = CardFactoryUtil.getBestCreatureAI(cards);
|
||||
}
|
||||
} else if (cards.size() > 1) {
|
||||
// TODO - Pick best creature instead of just the first on the list
|
||||
partner = CardFactoryUtil.getBestCreatureAI(cards);
|
||||
}
|
||||
|
||||
// pair choices together
|
||||
trigCards.get(0).setPairedWith(partner);
|
||||
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
|
||||
public String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||
ArrayList<Card> tgts;
|
||||
tgts = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
|
||||
ArrayList<Card> tgts;
|
||||
tgts = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
|
||||
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
for (final Card c : tgts) {
|
||||
sb.append(c).append(" ");
|
||||
}
|
||||
sb.append("pairs with another unpaired creature you control.");
|
||||
for (final Card c : tgts) {
|
||||
sb.append(c).append(" ");
|
||||
}
|
||||
sb.append("pairs with another unpaired creature you control.");
|
||||
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
sb.append(abSub.getStackDescription());
|
||||
}
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
if (abSub != null) {
|
||||
sb.append(abSub.getStackDescription());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
} // end bondStackDescription()
|
||||
return sb.toString();
|
||||
} // 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;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -28,9 +27,7 @@ import forge.Singletons;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.SpellEffect;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
|
||||
Reference in New Issue
Block a user