* CommonDrawback merged into AbilitySub, as there are no other SubAbilities without api.

* (fixes for 19720 & 19724) CheckAiDrawback was already recursivelly checking every subability, so no special methods were required
* numerous fixes to make ApiType comparisons null-safe
* CommonXXX classes do not take SpellEffect and AILogic as separate parameters. These are obtained from ApiType instead
This commit is contained in:
Maxmtg
2013-02-19 04:22:16 +00:00
parent a405a24b9e
commit ea74bbb492
18 changed files with 190 additions and 247 deletions

3
.gitattributes vendored
View File

@@ -13650,7 +13650,6 @@ src/main/java/forge/card/ability/AbilityFactory.java svneol=native#text/plain
src/main/java/forge/card/ability/AbilityUtils.java -text
src/main/java/forge/card/ability/ApiType.java -text
src/main/java/forge/card/ability/CommonAbility.java -text
src/main/java/forge/card/ability/CommonDrawback.java svneol=native#text/plain
src/main/java/forge/card/ability/CommonSpell.java -text
src/main/java/forge/card/ability/SpellAiLogic.java -text
src/main/java/forge/card/ability/SpellEffect.java -text
@@ -13799,6 +13798,7 @@ src/main/java/forge/card/ability/effects/DigUntilEffect.java -text
src/main/java/forge/card/ability/effects/DiscardEffect.java -text
src/main/java/forge/card/ability/effects/DrainManaEffect.java -text
src/main/java/forge/card/ability/effects/DrawEffect.java -text
src/main/java/forge/card/ability/effects/ETBReplacementEffect.java -text
src/main/java/forge/card/ability/effects/EffectEffect.java -text
src/main/java/forge/card/ability/effects/EncodeEffect.java -text
src/main/java/forge/card/ability/effects/EndTurnEffect.java -text
@@ -14427,6 +14427,7 @@ src/main/java/forge/util/MultiplexOutputStream.java svneol=native#text/plain
src/main/java/forge/util/MyObservable.java svneol=native#text/plain
src/main/java/forge/util/MyRandom.java svneol=native#text/plain
src/main/java/forge/util/PredicateString.java -text
src/main/java/forge/util/ReflectionUtil.java -text
src/main/java/forge/util/TextUtil.java -text
src/main/java/forge/util/ThreadUtil.java svneol=native#text/plain
src/main/java/forge/util/TreeProperties.java svneol=native#text/plain

View File

@@ -2652,7 +2652,7 @@ public class Card extends GameEntity implements Comparable<Card> {
// if there is a parent ability the AI can't use it
final Cost cost = a.getPayCosts();
if (!cost.hasNoManaCost()
|| (!a.getApi().equals(ApiType.Mana) && !a.getApi().equals(ApiType.ManaReflected))) {
|| (a.getApi() != ApiType.Mana && a.getApi() != ApiType.ManaReflected)) {
continue;
}
@@ -5973,7 +5973,7 @@ public class Card extends GameEntity implements Comparable<Card> {
*/
public final boolean isReflectedLand() {
for (final SpellAbility a : this.getCharacteristics().getManaAbility()) {
if (a.getApi().equals(ApiType.ManaReflected)) {
if (a.getApi() == ApiType.ManaReflected) {
return true;
}
}

View File

@@ -503,7 +503,7 @@ public final class CardUtil {
// so we don't infinite recurse.
final Card card = abMana.getSourceCard();
if (!abMana.getApi().equals(ApiType.ManaReflected)) {
if (abMana.getApi() != ApiType.ManaReflected) {
return colors;
}

View File

@@ -126,15 +126,13 @@ public final class AbilityFactory {
}
}
SpellAiLogic ai = api.getAi();
SpellEffect se = api.getSpellEffect();
if (isAb) {
spellAbility = new CommonAbility(api, hostCard, abCost, abTgt, mapParams, se, ai);
spellAbility = new CommonAbility(api, hostCard, abCost, abTgt, mapParams);
} else if (isSp) {
spellAbility = new CommonSpell(api, hostCard, abCost, abTgt, mapParams, se, ai);
spellAbility = new CommonSpell(api, hostCard, abCost, abTgt, mapParams);
} else if (isDb) {
spellAbility = new CommonDrawback(api, hostCard, abTgt, mapParams, se, ai);
spellAbility = new AbilitySub(api, hostCard, abTgt, mapParams);
}

View File

@@ -1,9 +1,12 @@
package forge.card.ability;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.TreeMap;
import forge.card.ability.ai.*;
import forge.card.ability.effects.*;
import forge.util.ReflectionUtil;
/**
* TODO: Write javadoc for this type.
@@ -113,69 +116,41 @@ public enum ApiType {
UnattachAll (UnattachAllEffect.class, UnattachAllAi.class),
Untap (UntapEffect.class, UntapAi.class),
UntapAll (UntapAllEffect.class, UntapAllAi.class),
WinsGame (GameWinEffect.class, GameWinAi.class);
WinsGame (GameWinEffect.class, GameWinAi.class),
InternalEtbReplacement(ETBReplacementEffect.class, CanPlayAsDrawbackAi.class);
private final Class<? extends SpellEffect> clsEffect;
private final Class<? extends SpellAiLogic> clsAi;
private static final Map<String, ApiType> allValues = new TreeMap<String, ApiType>(String.CASE_INSENSITIVE_ORDER);
ApiType(Class<? extends SpellEffect> clsEf, Class<? extends SpellAiLogic> clsAI) {
clsEffect = clsEf;
clsAi = clsAI;
}
private final Class<? extends SpellEffect> clsEffect;
private final Class<? extends SpellAiLogic> clsAi;
public static ApiType smartValueOf(String value) {
final String valToCompate = value.trim();
for (final ApiType v : ApiType.values()) {
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
return v;
}
}
throw new RuntimeException("Element " + value + " not found in ApiType enum");
if (allValues.isEmpty())
for(ApiType c : ApiType.values())
allValues.put(c.toString(), c);
ApiType v = allValues.get(value);
if ( v == null )
throw new RuntimeException("Element " + value + " not found in ApiType enum");
return v;
}
public SpellEffect getSpellEffect() {
if (null == clsEffect) {
return null;
}
@SuppressWarnings("unchecked")
Constructor<? extends SpellEffect>[] cc = (Constructor<? extends SpellEffect>[]) clsEffect.getConstructors();
for (Constructor<? extends SpellEffect> c : cc) {
Class<?>[] pp = c.getParameterTypes();
if (pp.length == 0) {
try {
SpellEffect res = c.newInstance();
return res;
} catch (Exception e) {
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
}
}
}
throw new RuntimeException("No default constructor found in class " + clsEffect.getName());
return clsEffect == null ? null : ReflectionUtil.makeDefaultInstanceOf(clsEffect);
}
public SpellAiLogic getAi() {
if (null == clsAi) {
return null;
}
@SuppressWarnings("unchecked")
Constructor<? extends SpellAiLogic>[] cc = (Constructor<? extends SpellAiLogic>[]) clsAi.getConstructors();
for (Constructor<? extends SpellAiLogic> c : cc) {
Class<?>[] pp = c.getParameterTypes();
if (pp.length == 0) {
try {
SpellAiLogic res = c.newInstance();
return res;
} catch (Exception e) {
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
e.printStackTrace();
}
}
}
throw new RuntimeException("No default constructor found in class " + clsEffect.getName());
return clsAi == null ? null : ReflectionUtil.makeDefaultInstanceOf(clsAi);
}
}

View File

@@ -20,20 +20,20 @@ public class CommonAbility extends AbilityActivated {
private static final long serialVersionUID = -4183793555528531978L;
public CommonAbility(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0, SpellEffect effect0, SpellAiLogic ai0) {
public CommonAbility(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0) {
super(sourceCard, abCost, tgt);
params = params0;
api = api0;
effect = effect0;
ai = ai0;
effect = api.getSpellEffect();
ai = api.getAi();
if (effect0 instanceof ManaEffect || effect0 instanceof ManaReflectedEffect) {
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
this.setManaPart(new AbilityManaPart(sourceCard, params));
this.setUndoable(true); // will try at least
}
if (effect0 instanceof ChangeZoneEffect || effect0 instanceof ChangeZoneAllEffect) {
if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) {
AbilityFactory.adjustChangeZoneTarget(params, this);
}
}
@@ -49,7 +49,7 @@ public class CommonAbility extends AbilityActivated {
@Override
public AbilityActivated getCopy() {
Target tgt = getTarget() == null ? null : new Target(getTarget());
AbilityActivated res = new CommonAbility(api, getSourceCard(), getPayCosts(), tgt, params, effect, ai);
AbilityActivated res = new CommonAbility(api, getSourceCard(), getPayCosts(), tgt, params);
CardFactoryUtil.copySpellAbility(this, res);
return res;
}

View File

@@ -1,88 +0,0 @@
/*
* 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.ability;
import java.util.Map;
import forge.Card;
import forge.card.ability.effects.ChangeZoneAllEffect;
import forge.card.ability.effects.ChangeZoneEffect;
import forge.card.ability.effects.ManaEffect;
import forge.card.ability.effects.ManaReflectedEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.Target;
import forge.game.player.AIPlayer;
public class CommonDrawback extends AbilitySub {
private final SpellEffect effect;
private final SpellAiLogic ai;
private static final long serialVersionUID = 6631124959690157874L;
public CommonDrawback(ApiType api0, final Card ca, final Target t, Map<String, String> params0, SpellEffect effect0, SpellAiLogic ai0) {
super(ca, t);
api = api0;
params = params0;
ai = ai0;
effect = effect0;
if (effect0 instanceof ManaEffect || effect0 instanceof ManaReflectedEffect) {
this.setManaPart(new AbilityManaPart(ca, params));
}
if (effect0 instanceof ChangeZoneEffect || effect0 instanceof ChangeZoneAllEffect) {
AbilityFactory.adjustChangeZoneTarget(params, this);
}
}
@Override
public AbilitySub getCopy() {
Target t = getTarget() == null ? null : new Target(getTarget());
AbilitySub res = new CommonDrawback(api, getSourceCard(), t, params, effect, ai);
CardFactoryUtil.copySpellAbility(this, res);
return res;
}
@Override
public String getStackDescription() {
return effect.getStackDescriptionWithSubs(params, this);
}
@Override
public boolean canPlayAI() {
return ai.canPlayAIWithSubs((AIPlayer)getActivatingPlayer(), this);
}
@Override
public void resolve() {
effect.resolve(this);
}
@Override
public boolean chkAIDrawback(AIPlayer aiPlayer) {
final AbilitySub subAb = getSubAbility();
return ai.chkAIDrawback(this, aiPlayer) && (subAb == null || subAb.chkAIDrawback(aiPlayer));
}
@Override
public boolean doTrigger(final boolean mandatory, AIPlayer aiPlayer) {
return ai.doTriggerAI(aiPlayer, this, mandatory);
}
}
// end class AbilityFactory_AlterLife

View File

@@ -18,18 +18,18 @@ public class CommonSpell extends Spell {
private final SpellEffect effect;
private final SpellAiLogic ai;
public CommonSpell(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0, SpellEffect effect0, SpellAiLogic ai0) {
public CommonSpell(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0) {
super(sourceCard, abCost, tgt);
params = params0;
api = api0;
effect = effect0;
ai = ai0;
effect = api.getSpellEffect();
ai = api.getAi();
if (effect0 instanceof ManaEffect || effect0 instanceof ManaReflectedEffect) {
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
this.setManaPart(new AbilityManaPart(sourceCard, params));
}
if (effect0 instanceof ChangeZoneEffect || effect0 instanceof ChangeZoneAllEffect) {
if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) {
AbilityFactory.adjustChangeZoneTarget(params, this);
}
}

View File

@@ -16,10 +16,7 @@ public abstract class SpellAiLogic {
return false;
}
final AbilitySub subAb = sa.getSubAbility();
if (subAb != null && !subAb.chkAIDrawbackWithSubs(aiPlayer)) {
return false;
}
return true;
return subAb == null || subAb.chkAIDrawback(aiPlayer);
}
protected abstract boolean canPlayAI(final AIPlayer aiPlayer, final SpellAbility sa);

View File

@@ -295,9 +295,7 @@ public class ChangeZoneAi extends SpellAiLogic {
chance &= (r.nextFloat() < .8);
final AbilitySub subAb = sa.getSubAbility();
if (subAb != null) {
chance &= subAb.chkAIDrawback(ai);
}
chance &= subAb == null || subAb.chkAIDrawback(ai);
return chance;
}
@@ -589,13 +587,13 @@ public class ChangeZoneAi extends SpellAiLogic {
}
final AbilitySub abSub = sa.getSubAbility();
ApiType subAPI = null;
ApiType subApi = null;
if (abSub != null) {
subAPI = abSub.getApi();
subApi = abSub.getApi();
}
// only use blink or bounce effects
if (!(destination.equals(ZoneType.Exile) && (subAPI == ApiType.DelayedTrigger || subAPI == ApiType.ChangeZone))
if (!(destination.equals(ZoneType.Exile) && (subApi == ApiType.DelayedTrigger || subApi == ApiType.ChangeZone))
&& !destination.equals(ZoneType.Hand)) {
return false;
}
@@ -629,11 +627,9 @@ public class ChangeZoneAi extends SpellAiLogic {
}
final AbilitySub subAb = sa.getSubAbility();
if (subAb != null) {
chance &= subAb.chkAIDrawback(ai);
}
chance &= subAb == null || subAb.chkAIDrawback(ai);
return (chance);
return chance;
}
/**
@@ -676,10 +672,10 @@ public class ChangeZoneAi extends SpellAiLogic {
final Target tgt = sa.getTarget();
final AbilitySub abSub = sa.getSubAbility();
ApiType subAPI = null;
ApiType subApi = null;
String subAffected = "";
if (abSub != null) {
subAPI = abSub.getApi();
subApi = abSub.getApi();
if (abSub.hasParam("Defined")) {
subAffected = abSub.getParam("Defined");
}
@@ -714,7 +710,7 @@ public class ChangeZoneAi extends SpellAiLogic {
// if it's blink or bounce, try to save my about to die stuff
if ((destination.equals(ZoneType.Hand) || (destination.equals(ZoneType.Exile)
&& (subAPI == ApiType.DelayedTrigger || (subAPI == ApiType.ChangeZone && subAffected.equals("Remembered")))))
&& (subApi == ApiType.DelayedTrigger || (subApi == ApiType.ChangeZone && subAffected.equals("Remembered")))))
&& (tgt.getMinTargets(sa.getSourceCard(), sa) <= 1)) {
// check stack for something on the stack that will kill
@@ -792,7 +788,7 @@ public class ChangeZoneAi extends SpellAiLogic {
// blink human targets only during combat
if (origin.equals(ZoneType.Battlefield)
&& destination.equals(ZoneType.Exile)
&& (subAPI == ApiType.DelayedTrigger || (subAPI == ApiType.ChangeZone && subAffected.equals("Remembered")))
&& (subApi == ApiType.DelayedTrigger || (subApi == ApiType.ChangeZone && subAffected.equals("Remembered")))
&& !(Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) || sa
.isAbility())) {
return false;

View File

@@ -0,0 +1,16 @@
package forge.card.ability.effects;
import forge.Card;
import forge.card.ability.SpellEffect;
import forge.card.spellability.SpellAbility;
/**
* TODO: Write javadoc for this type.
*
*/
public class ETBReplacementEffect extends SpellEffect {
@Override
public void resolve(SpellAbility sa) {
forge.Singletons.getModel().getGame().getAction().moveToPlay(((Card) sa.getReplacingObject("Card")));
}
}

View File

@@ -50,9 +50,7 @@ import forge.card.MagicColor;
import forge.card.SpellManaCost;
import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils;
import forge.card.ability.CommonDrawback;
import forge.card.ability.SpellEffect;
import forge.card.ability.ai.CanPlayAsDrawbackAi;
import forge.card.ability.ApiType;
import forge.card.cost.Cost;
import forge.card.mana.ManaCostParser;
import forge.card.mana.ManaCostShard;
@@ -62,6 +60,7 @@ import forge.card.replacement.ReplacementLayer;
import forge.card.spellability.Ability;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityStatic;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.Spell;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRestriction;
@@ -4469,14 +4468,7 @@ public class CardFactoryUtil {
tailend = tailend.getSubAbility();
}
class ETBReplacementEffect extends SpellEffect {
@Override
public void resolve(SpellAbility sa) {
forge.Singletons.getModel().getGame().getAction().moveToPlay(((Card) sa.getReplacingObject("Card")));
}
}
tailend.setSubAbility(new CommonDrawback(null, sa.getSourceCard(), null, null, new ETBReplacementEffect(), new CanPlayAsDrawbackAi()));
tailend.setSubAbility(new AbilitySub(ApiType.InternalEtbReplacement, sa.getSourceCard(), null, null));
// ETBReplacementMove(sa.getSourceCard(), null));
}

View File

@@ -17,7 +17,18 @@
*/
package forge.card.spellability;
import java.util.Map;
import forge.Card;
import forge.card.ability.AbilityFactory;
import forge.card.ability.ApiType;
import forge.card.ability.SpellAiLogic;
import forge.card.ability.SpellEffect;
import forge.card.ability.effects.ChangeZoneAllEffect;
import forge.card.ability.effects.ChangeZoneEffect;
import forge.card.ability.effects.ManaEffect;
import forge.card.ability.effects.ManaReflectedEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.game.player.AIPlayer;
/**
@@ -28,61 +39,12 @@ import forge.game.player.AIPlayer;
* @author Forge
* @version $Id$
*/
public abstract class AbilitySub extends SpellAbility implements java.io.Serializable {
public final class AbilitySub extends SpellAbility implements java.io.Serializable {
/** Constant <code>serialVersionUID=4650634415821733134L</code>. */
private static final long serialVersionUID = 4650634415821733134L;
private SpellAbility parent = null;
/**
* <p>
* Constructor for Ability_Sub.
* </p>
*
* @param sourceCard
* a {@link forge.Card} object.
* @param tgt
* a {@link forge.card.spellability.Target} object.
*/
public AbilitySub(final Card sourceCard, final Target tgt) {
super(sourceCard);
this.setTarget(tgt);
}
/** {@inheritDoc} */
@Override
public boolean canPlay() {
// this should never be on the Stack by itself
return false;
}
/**
* <p>
* chkAI_Drawback.
* </p>
* @param ai TODO
*
* @return a boolean.
*/
public abstract boolean chkAIDrawback(AIPlayer ai);
public final boolean chkAIDrawbackWithSubs(final AIPlayer aiPlayer) {
if (!chkAIDrawback(aiPlayer)) {
return false;
}
final AbilitySub subAb = this.getSubAbility();
if (subAb != null && !subAb.chkAIDrawbackWithSubs(aiPlayer)) {
return false;
}
return true;
}
public abstract AbilitySub getCopy();
/** {@inheritDoc} */
@Override
public abstract boolean doTrigger(boolean mandatory, AIPlayer ai);
/**
* <p>
* Setter for the field <code>parent</code>.
@@ -106,4 +68,66 @@ public abstract class AbilitySub extends SpellAbility implements java.io.Seriali
public final SpellAbility getParent() {
return this.parent;
}
/** {@inheritDoc} */
@Override
public boolean canPlay() {
// this should never be on the Stack by itself
return false;
}
private final SpellEffect effect;
private final SpellAiLogic ai;
public AbilitySub(ApiType api0, final Card ca, final Target tgt, Map<String, String> params0) {
super(ca);
this.setTarget(tgt);
api = api0;
params = params0;
ai = api.getAi();
effect = api.getSpellEffect();
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
this.setManaPart(new AbilityManaPart(ca, params));
}
if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) {
AbilityFactory.adjustChangeZoneTarget(params, this);
}
}
public AbilitySub getCopy() {
Target t = getTarget() == null ? null : new Target(getTarget());
AbilitySub res = new AbilitySub(api, getSourceCard(), t, params);
CardFactoryUtil.copySpellAbility(this, res);
return res;
}
@Override
public String getStackDescription() {
return effect.getStackDescriptionWithSubs(params, this);
}
@Override
public boolean canPlayAI() {
return ai.canPlayAIWithSubs((AIPlayer)getActivatingPlayer(), this);
}
@Override
public void resolve() {
effect.resolve(this);
}
public boolean chkAIDrawback(AIPlayer aiPlayer) {
final AbilitySub subAb = getSubAbility();
return ai.chkAIDrawback(this, aiPlayer) && (subAb == null || subAb.chkAIDrawback(aiPlayer));
}
@Override
public boolean doTrigger(final boolean mandatory, AIPlayer aiPlayer) {
return ai.doTriggerAI(aiPlayer, this, mandatory);
}
}

View File

@@ -28,6 +28,7 @@ import forge.Singletons;
import forge.CardLists;
import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType;
import forge.control.input.Input;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -442,11 +443,11 @@ public class TargetSelection {
choices[i - 1] = i;
}
String apiBasedMessage = "Distribute how much to ";
if (sa.getApi().toString().equals("DealDamage")) {
if (sa.getApi() == ApiType.DealDamage) {
apiBasedMessage = "Select how much damage to deal to ";
} else if (sa.getApi().toString().equals("PreventDamage")) {
} else if (sa.getApi() == ApiType.PreventDamage) {
apiBasedMessage = "Select how much damage to prevent to ";
} else if (sa.getApi().toString().equals("PutCounter")) {
} else if (sa.getApi() == ApiType.PutCounter) {
apiBasedMessage = "Select how many counters to distribute to ";
}
final StringBuilder sb = new StringBuilder();
@@ -486,9 +487,9 @@ public class TargetSelection {
choices[i - 1] = i;
}
String apiBasedMessage = "Distribute how much to ";
if (sa.getApi().toString().equals("DealDamage")) {
if (sa.getApi() == ApiType.DealDamage) {
apiBasedMessage = "Select how much damage to deal to ";
} else if (sa.getApi().toString().equals("PreventDamage")) {
} else if (sa.getApi() == ApiType.PreventDamage) {
apiBasedMessage = "Select how much damage to prevent to ";
}
final StringBuilder sb = new StringBuilder();

View File

@@ -69,7 +69,7 @@ public abstract class InputPayManaBase extends Input {
if (m.isAnyMana()) {
return true;
}
if (am.getApi().equals(ApiType.ManaReflected)) {
if (am.getApi() == ApiType.ManaReflected) {
final Iterable<String> reflectableColors = CardUtil.getReflectableManaColors(am, am, new HashSet<String>(), new ArrayList<Card>());
for (final String color : reflectableColors) {
if (mana.contains(MagicColor.toShortString(color))) {
@@ -228,7 +228,7 @@ public abstract class InputPayManaBase extends Input {
for (final SpellAbility am : abilities) {
AbilityManaPart m = am.getManaPart();
if (am.getApi().equals(ApiType.ManaReflected)) {
if (am.getApi() == ApiType.ManaReflected) {
final Iterable<String> reflectableColors = CardUtil.getReflectableManaColors(am, am, new HashSet<String>(), new ArrayList<Card>());
for (final String color : reflectableColors) {
if (manaCost.isColor(color)) {

View File

@@ -1533,7 +1533,7 @@ public final class GameActionUtil {
baseMana = "Any";
}
}
else if (sa.getApi().equals(ApiType.ManaReflected)) {
else if (sa.getApi() == ApiType.ManaReflected) {
baseMana = abMana.getExpressChoice();
}
else {

View File

@@ -132,7 +132,7 @@ public class ComputerUtilMana {
m.setExpressChoice(colorChoice);
colorChoice = ComputerUtilMana.getComboManaChoice(ai, ma, sa, cost);
m.setExpressChoice(colorChoice);
} else if (ma.getApi().equals(ApiType.ManaReflected)) {
} else if (ma.getApi() == ApiType.ManaReflected) {
if (CardUtil.getReflectableManaColors(ma, ma, new HashSet<String>(), new ArrayList<Card>()).contains(MagicColor.toLongString(costParts[nPart]))) {
m.setExpressChoice(costParts[nPart]);
} else {

View File

@@ -0,0 +1,31 @@
package forge.util;
import java.lang.reflect.Constructor;
/**
* TODO: Write javadoc for this type.
*
*/
public class ReflectionUtil {
public static <T> T makeDefaultInstanceOf(Class<? extends T> cls) {
if ( null == cls )
throw new IllegalArgumentException("Class<? extends T> cls must not be null");
@SuppressWarnings("unchecked")
Constructor<? extends T>[] cc = (Constructor<? extends T>[]) cls.getConstructors();
for (Constructor<? extends T> c : cc) {
Class<?>[] pp = c.getParameterTypes();
if (pp.length == 0) {
try {
T res = c.newInstance();
return res;
} catch (Exception e) {
e.printStackTrace();
}
}
}
throw new RuntimeException("No default constructor found in class " + cls.getName());
}
}