Lots of code cleanup, including removing some useless null checks,

preventing some NPE's before they ever occur, and clean up some
of the inheritance hierarchy.
This commit is contained in:
elcnesh
2015-04-13 14:29:01 +00:00
parent 19ccab3d00
commit 6dacb83c37
19 changed files with 322 additions and 262 deletions

2
.gitattributes vendored
View File

@@ -319,7 +319,7 @@ forge-game/src/main/java/forge/game/ability/AbilityApiBased.java -text
forge-game/src/main/java/forge/game/ability/AbilityFactory.java svneol=native#text/plain forge-game/src/main/java/forge/game/ability/AbilityFactory.java svneol=native#text/plain
forge-game/src/main/java/forge/game/ability/AbilityUtils.java -text forge-game/src/main/java/forge/game/ability/AbilityUtils.java -text
forge-game/src/main/java/forge/game/ability/ApiType.java -text forge-game/src/main/java/forge/game/ability/ApiType.java -text
forge-game/src/main/java/forge/game/ability/SaTargetRoutines.java -text forge-game/src/main/java/forge/game/ability/IllegalAbilityException.java -text
forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java -text forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java -text
forge-game/src/main/java/forge/game/ability/SpellApiBased.java -text forge-game/src/main/java/forge/game/ability/SpellApiBased.java -text
forge-game/src/main/java/forge/game/ability/StaticAbilityApiBased.java -text forge-game/src/main/java/forge/game/ability/StaticAbilityApiBased.java -text

View File

@@ -1209,7 +1209,7 @@ public class ComputerUtilMana {
* @return map between creatures and shards to convoke * @return map between creatures and shards to convoke
*/ */
public static Map<Card, ManaCostShard> getConvokeFromList(final ManaCost cost, List<Card> list) { public static Map<Card, ManaCostShard> getConvokeFromList(final ManaCost cost, List<Card> list) {
HashMap<Card, ManaCostShard> convoke = new HashMap<Card, ManaCostShard>(); final Map<Card, ManaCostShard> convoke = new HashMap<Card, ManaCostShard>();
Card convoked = null; Card convoked = null;
for (ManaCostShard toPay : cost) { for (ManaCostShard toPay : cost) {
for (Card c : list) { for (Card c : list) {
@@ -1219,9 +1219,6 @@ public class ComputerUtilMana {
convoke.put(c, toPay); convoke.put(c, toPay);
break; break;
} }
if (convoked != null){
break;
}
} }
if (convoked != null) { if (convoked != null) {
list.remove(convoked); list.remove(convoked);

View File

@@ -1,10 +1,11 @@
package forge.ai; package forge.ai;
import java.util.Collection;
import java.util.List;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import forge.game.GameEntity; import forge.game.GameEntity;
import forge.game.ability.SaTargetRoutines;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -14,10 +15,7 @@ import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions; import forge.game.spellability.TargetRestrictions;
import java.util.Collection; public abstract class SpellAbilityAi {
import java.util.List;
public abstract class SpellAbilityAi extends SaTargetRoutines {
public final boolean canPlayAIWithSubs(final Player aiPlayer, final SpellAbility sa) { public final boolean canPlayAIWithSubs(final Player aiPlayer, final SpellAbility sa) {
if (!canPlayAI(aiPlayer, sa)) { if (!canPlayAI(aiPlayer, sa)) {

View File

@@ -1,6 +1,10 @@
package forge.ai; package forge.ai;
import java.util.EnumMap; import java.util.EnumMap;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import forge.ai.ability.*; import forge.ai.ability.*;
import forge.game.ability.ApiType; import forge.game.ability.ApiType;
@@ -9,144 +13,143 @@ import forge.util.ReflectionUtil;
public enum SpellApiToAi { public enum SpellApiToAi {
Converter; Converter;
private final static EnumMap<ApiType, Class<? extends SpellAbilityAi>> apiToClass = new EnumMap<>(ApiType.class); private final Map<ApiType, SpellAbilityAi> apiToInstance = new EnumMap<>(ApiType.class);
private final EnumMap<ApiType, SpellAbilityAi> apiToInstance = new EnumMap<>(ApiType.class);
static { // Do the extra copy to make an actual EnumMap (faster)
apiToClass.put(ApiType.Abandon, AlwaysPlayAi.class); private final Map<ApiType, Class<? extends SpellAbilityAi>> apiToClass = Maps.newEnumMap(ImmutableMap
apiToClass.put(ApiType.ActivateAbility, ActivateAbilityAi.class); .<ApiType, Class<? extends SpellAbilityAi>>builder()
apiToClass.put(ApiType.AddOrRemoveCounter, CountersPutOrRemoveAi.class); .put(ApiType.Abandon, AlwaysPlayAi.class)
apiToClass.put(ApiType.AddPhase, AddPhaseAi.class); .put(ApiType.ActivateAbility, ActivateAbilityAi.class)
apiToClass.put(ApiType.AddTurn, AddTurnAi.class); .put(ApiType.AddOrRemoveCounter, CountersPutOrRemoveAi.class)
apiToClass.put(ApiType.Animate, AnimateAi.class); .put(ApiType.AddPhase, AddPhaseAi.class)
apiToClass.put(ApiType.AnimateAll, AnimateAllAi.class); .put(ApiType.AddTurn, AddTurnAi.class)
apiToClass.put(ApiType.Attach, AttachAi.class); .put(ApiType.Animate, AnimateAi.class)
apiToClass.put(ApiType.Balance, BalanceAi.class); .put(ApiType.AnimateAll, AnimateAllAi.class)
apiToClass.put(ApiType.BecomesBlocked, BecomesBlockedAi.class); .put(ApiType.Attach, AttachAi.class)
apiToClass.put(ApiType.BidLife, BidLifeAi.class); .put(ApiType.Balance, BalanceAi.class)
apiToClass.put(ApiType.Bond, BondAi.class); .put(ApiType.BecomesBlocked, BecomesBlockedAi.class)
apiToClass.put(ApiType.ChangeTargets, ChangeTargetsAi.class); .put(ApiType.BidLife, BidLifeAi.class)
apiToClass.put(ApiType.ChangeZone, ChangeZoneAi.class); .put(ApiType.Bond, BondAi.class)
apiToClass.put(ApiType.ChangeZoneAll, ChangeZoneAllAi.class); .put(ApiType.ChangeTargets, ChangeTargetsAi.class)
.put(ApiType.ChangeZone, ChangeZoneAi.class)
.put(ApiType.ChangeZoneAll, ChangeZoneAllAi.class)
.put(ApiType.Charm, CharmAi.class)
.put(ApiType.ChooseCard, ChooseCardAi.class)
.put(ApiType.ChooseColor, ChooseColorAi.class)
.put(ApiType.ChooseDirection, ChooseDirectionAi.class)
.put(ApiType.ChooseNumber, ChooseNumberAi.class)
.put(ApiType.ChoosePlayer, ChoosePlayerAi.class)
.put(ApiType.ChooseSource, ChooseSourceAi.class)
.put(ApiType.ChooseType, ChooseTypeAi.class)
.put(ApiType.Clash, ClashAi.class)
.put(ApiType.Cleanup, AlwaysPlayAi.class)
.put(ApiType.Clone, CloneAi.class)
.put(ApiType.CopyPermanent, CopyPermanentAi.class)
.put(ApiType.CopySpellAbility, CanPlayAsDrawbackAi.class)
.put(ApiType.ControlPlayer, CannotPlayAi.class)
.put(ApiType.ControlSpell, CannotPlayAi.class)
.put(ApiType.Counter, CounterAi.class)
.put(ApiType.DamageAll, DamageAllAi.class)
.put(ApiType.DealDamage, DamageDealAi.class)
.put(ApiType.Debuff, DebuffAi.class)
.put(ApiType.DeclareCombatants, CannotPlayAi.class)
.put(ApiType.DelayedTrigger, DelayedTriggerAi.class)
.put(ApiType.Destroy, DestroyAi.class)
.put(ApiType.DestroyAll, DestroyAllAi.class)
.put(ApiType.Dig, DigAi.class)
.put(ApiType.DigUntil, DigUntilAi.class)
.put(ApiType.Discard, DiscardAi.class)
.put(ApiType.DrainMana, DrainManaAi.class)
.put(ApiType.Draw, DrawAi.class)
.put(ApiType.EachDamage, DamageEachAi.class)
.put(ApiType.Effect, EffectAi.class)
.put(ApiType.Encode, EncodeAi.class)
.put(ApiType.EndTurn, EndTurnAi.class)
.put(ApiType.ExchangeLife, LifeExchangeAi.class)
.put(ApiType.ExchangeControl, ControlExchangeAi.class)
.put(ApiType.ExchangeControlVariant, CannotPlayAi.class)
.put(ApiType.ExchangePower, PowerExchangeAi.class)
.put(ApiType.ExchangeZone, ZoneExchangeAi.class)
.put(ApiType.Fight, FightAi.class)
.put(ApiType.FlipACoin, FlipACoinAi.class)
.put(ApiType.Fog, FogAi.class)
.put(ApiType.GainControl, ControlGainAi.class)
.put(ApiType.GainLife, LifeGainAi.class)
.put(ApiType.GainOwnership, CannotPlayAi.class)
.put(ApiType.GenericChoice, ChooseGenericEffectAi.class)
.put(ApiType.LoseLife, LifeLoseAi.class)
.put(ApiType.LosesGame, GameLossAi.class)
.put(ApiType.Mana, ManaEffectAi.class)
.put(ApiType.ManaReflected, CannotPlayAi.class)
.put(ApiType.Manifest, ManifestAi.class)
.put(ApiType.Mill, MillAi.class)
.put(ApiType.MoveCounter, CountersMoveAi.class)
.put(ApiType.MultiplePiles, CannotPlayAi.class)
.put(ApiType.MustAttack, MustAttackAi.class)
.put(ApiType.MustBlock, MustBlockAi.class)
.put(ApiType.NameCard, ChooseCardNameAi.class)
.put(ApiType.PeekAndReveal, PeekAndRevealAi.class)
.put(ApiType.PermanentCreature, PermanentCreatureAi.class)
.put(ApiType.PermanentNoncreature, PermanentNoncreatureAi.class)
.put(ApiType.Phases, PhasesAi.class)
.put(ApiType.Planeswalk, AlwaysPlayAi.class)
.put(ApiType.Play, PlayAi.class)
.put(ApiType.PlayLandVariant, CannotPlayAi.class)
.put(ApiType.Poison, PoisonAi.class)
.put(ApiType.PreventDamage, DamagePreventAi.class)
.put(ApiType.PreventDamageAll, DamagePreventAllAi.class)
.put(ApiType.Proliferate, CountersProliferateAi.class)
.put(ApiType.Protection, ProtectAi.class)
.put(ApiType.ProtectionAll, ProtectAllAi.class)
.put(ApiType.Pump, PumpAi.class)
.put(ApiType.PumpAll, PumpAllAi.class)
.put(ApiType.PutCounter, CountersPutAi.class)
.put(ApiType.PutCounterAll, CountersPutAllAi.class)
.put(ApiType.RearrangeTopOfLibrary, RearrangeTopOfLibraryAi.class)
.put(ApiType.Regenerate, RegenerateAi.class)
.put(ApiType.RegenerateAll, RegenerateAllAi.class)
.put(ApiType.RemoveCounter, CountersRemoveAi.class)
.put(ApiType.RemoveCounterAll, CannotPlayAi.class)
.put(ApiType.RemoveFromCombat, RemoveFromCombatAi.class)
.put(ApiType.ReorderZone, AlwaysPlayAi.class)
.put(ApiType.Repeat, RepeatAi.class)
.put(ApiType.RepeatEach, RepeatEachAi.class)
.put(ApiType.RestartGame, RestartGameAi.class)
.put(ApiType.Reveal, RevealAi.class)
.put(ApiType.RevealHand, RevealHandAi.class)
.put(ApiType.ReverseTurnOrder, AlwaysPlayAi.class)
.put(ApiType.RollPlanarDice, RollPlanarDiceAi.class)
.put(ApiType.RunSVarAbility, AlwaysPlayAi.class)
.put(ApiType.Sacrifice, SacrificeAi.class)
.put(ApiType.SacrificeAll, SacrificeAllAi.class)
.put(ApiType.Scry, ScryAi.class)
.put(ApiType.SetInMotion, AlwaysPlayAi.class)
.put(ApiType.SetLife, LifeSetAi.class)
.put(ApiType.SetState, SetStateAi.class)
.put(ApiType.Shuffle, ShuffleAi.class)
.put(ApiType.SkipTurn, SkipTurnAi.class)
.put(ApiType.StoreMap, StoreMapAi.class)
.put(ApiType.StoreSVar, StoreSVarAi.class)
.put(ApiType.Tap, TapAi.class)
.put(ApiType.TapAll, TapAllAi.class)
.put(ApiType.TapOrUntap, TapOrUntapAi.class)
.put(ApiType.TapOrUntapAll, TapOrUntapAllAi.class)
.put(ApiType.Token, TokenAi.class)
.put(ApiType.TwoPiles, TwoPilesAi.class)
.put(ApiType.Unattach, CannotPlayAi.class)
.put(ApiType.UnattachAll, UnattachAllAi.class)
.put(ApiType.Untap, UntapAi.class)
.put(ApiType.UntapAll, UntapAllAi.class)
.put(ApiType.Vote, VoteAi.class)
.put(ApiType.WinsGame, GameWinAi.class)
apiToClass.put(ApiType.Charm, CharmAi.class); .put(ApiType.InternalEtbReplacement, CanPlayAsDrawbackAi.class)
apiToClass.put(ApiType.ChooseCard, ChooseCardAi.class); .put(ApiType.InternalLegendaryRule, LegendaryRuleAi.class)
apiToClass.put(ApiType.ChooseColor, ChooseColorAi.class); .put(ApiType.InternalHaunt, HauntAi.class)
apiToClass.put(ApiType.ChooseDirection, ChooseDirectionAi.class); .put(ApiType.InternalIgnoreEffect, CannotPlayAi.class)
apiToClass.put(ApiType.ChooseNumber, ChooseNumberAi.class); .build());
apiToClass.put(ApiType.ChoosePlayer, ChoosePlayerAi.class);
apiToClass.put(ApiType.ChooseSource, ChooseSourceAi.class);
apiToClass.put(ApiType.ChooseType, ChooseTypeAi.class);
apiToClass.put(ApiType.Clash, ClashAi.class);
apiToClass.put(ApiType.Cleanup, AlwaysPlayAi.class);
apiToClass.put(ApiType.Clone, CloneAi.class);
apiToClass.put(ApiType.CopyPermanent, CopyPermanentAi.class);
apiToClass.put(ApiType.CopySpellAbility, CanPlayAsDrawbackAi.class);
apiToClass.put(ApiType.ControlPlayer, CannotPlayAi.class);
apiToClass.put(ApiType.ControlSpell, CannotPlayAi.class);
apiToClass.put(ApiType.Counter, CounterAi.class);
apiToClass.put(ApiType.DamageAll, DamageAllAi.class);
apiToClass.put(ApiType.DealDamage, DamageDealAi.class); public SpellAbilityAi get(final ApiType api) {
apiToClass.put(ApiType.Debuff, DebuffAi.class);
apiToClass.put(ApiType.DeclareCombatants, CannotPlayAi.class);
apiToClass.put(ApiType.DelayedTrigger, DelayedTriggerAi.class);
apiToClass.put(ApiType.Destroy, DestroyAi.class);
apiToClass.put(ApiType.DestroyAll, DestroyAllAi.class);
apiToClass.put(ApiType.Dig, DigAi.class);
apiToClass.put(ApiType.DigUntil, DigUntilAi.class);
apiToClass.put(ApiType.Discard, DiscardAi.class);
apiToClass.put(ApiType.DrainMana, DrainManaAi.class);
apiToClass.put(ApiType.Draw, DrawAi.class);
apiToClass.put(ApiType.EachDamage, DamageEachAi.class);
apiToClass.put(ApiType.Effect, EffectAi.class);
apiToClass.put(ApiType.Encode, EncodeAi.class);
apiToClass.put(ApiType.EndTurn, EndTurnAi.class);
apiToClass.put(ApiType.ExchangeLife, LifeExchangeAi.class);
apiToClass.put(ApiType.ExchangeControl, ControlExchangeAi.class);
apiToClass.put(ApiType.ExchangeControlVariant, CannotPlayAi.class);
apiToClass.put(ApiType.ExchangePower, PowerExchangeAi.class);
apiToClass.put(ApiType.ExchangeZone, ZoneExchangeAi.class);
apiToClass.put(ApiType.Fight, FightAi.class);
apiToClass.put(ApiType.FlipACoin, FlipACoinAi.class);
apiToClass.put(ApiType.Fog, FogAi.class);
apiToClass.put(ApiType.GainControl, ControlGainAi.class);
apiToClass.put(ApiType.GainLife, LifeGainAi.class);
apiToClass.put(ApiType.GainOwnership, CannotPlayAi.class);
apiToClass.put(ApiType.GenericChoice, ChooseGenericEffectAi.class);
apiToClass.put(ApiType.LoseLife, LifeLoseAi.class);
apiToClass.put(ApiType.LosesGame, GameLossAi.class);
apiToClass.put(ApiType.Mana, ManaEffectAi.class);
apiToClass.put(ApiType.ManaReflected, CannotPlayAi.class);
apiToClass.put(ApiType.Manifest, ManifestAi.class);
apiToClass.put(ApiType.Mill, MillAi.class);
apiToClass.put(ApiType.MoveCounter, CountersMoveAi.class);
apiToClass.put(ApiType.MultiplePiles, CannotPlayAi.class);
apiToClass.put(ApiType.MustAttack, MustAttackAi.class);
apiToClass.put(ApiType.MustBlock, MustBlockAi.class);
apiToClass.put(ApiType.NameCard, ChooseCardNameAi.class);
apiToClass.put(ApiType.PeekAndReveal, PeekAndRevealAi.class);
apiToClass.put(ApiType.PermanentCreature, PermanentCreatureAi.class);
apiToClass.put(ApiType.PermanentNoncreature, PermanentNoncreatureAi.class);
apiToClass.put(ApiType.Phases, PhasesAi.class);
apiToClass.put(ApiType.Planeswalk, AlwaysPlayAi.class);
apiToClass.put(ApiType.Play, PlayAi.class);
apiToClass.put(ApiType.PlayLandVariant, CannotPlayAi.class);
apiToClass.put(ApiType.Poison, PoisonAi.class);
apiToClass.put(ApiType.PreventDamage, DamagePreventAi.class);
apiToClass.put(ApiType.PreventDamageAll, DamagePreventAllAi.class);
apiToClass.put(ApiType.Proliferate, CountersProliferateAi.class);
apiToClass.put(ApiType.Protection, ProtectAi.class);
apiToClass.put(ApiType.ProtectionAll, ProtectAllAi.class);
apiToClass.put(ApiType.Pump, PumpAi.class);
apiToClass.put(ApiType.PumpAll, PumpAllAi.class);
apiToClass.put(ApiType.PutCounter, CountersPutAi.class);
apiToClass.put(ApiType.PutCounterAll, CountersPutAllAi.class);
apiToClass.put(ApiType.RearrangeTopOfLibrary, RearrangeTopOfLibraryAi.class);
apiToClass.put(ApiType.Regenerate, RegenerateAi.class);
apiToClass.put(ApiType.RegenerateAll, RegenerateAllAi.class);
apiToClass.put(ApiType.RemoveCounter, CountersRemoveAi.class);
apiToClass.put(ApiType.RemoveCounterAll, CannotPlayAi.class);
apiToClass.put(ApiType.RemoveFromCombat, RemoveFromCombatAi.class);
apiToClass.put(ApiType.ReorderZone, AlwaysPlayAi.class);
apiToClass.put(ApiType.Repeat, RepeatAi.class);
apiToClass.put(ApiType.RepeatEach, RepeatEachAi.class);
apiToClass.put(ApiType.RestartGame, RestartGameAi.class);
apiToClass.put(ApiType.Reveal, RevealAi.class);
apiToClass.put(ApiType.RevealHand, RevealHandAi.class);
apiToClass.put(ApiType.ReverseTurnOrder, AlwaysPlayAi.class);
apiToClass.put(ApiType.RollPlanarDice, RollPlanarDiceAi.class);
apiToClass.put(ApiType.RunSVarAbility, AlwaysPlayAi.class);
apiToClass.put(ApiType.Sacrifice, SacrificeAi.class);
apiToClass.put(ApiType.SacrificeAll, SacrificeAllAi.class);
apiToClass.put(ApiType.Scry, ScryAi.class);
apiToClass.put(ApiType.SetInMotion, AlwaysPlayAi.class);
apiToClass.put(ApiType.SetLife, LifeSetAi.class);
apiToClass.put(ApiType.SetState, SetStateAi.class);
apiToClass.put(ApiType.Shuffle, ShuffleAi.class);
apiToClass.put(ApiType.SkipTurn, SkipTurnAi.class);
apiToClass.put(ApiType.StoreMap, StoreMapAi.class);
apiToClass.put(ApiType.StoreSVar, StoreSVarAi.class);
apiToClass.put(ApiType.Tap, TapAi.class);
apiToClass.put(ApiType.TapAll, TapAllAi.class);
apiToClass.put(ApiType.TapOrUntap, TapOrUntapAi.class);
apiToClass.put(ApiType.TapOrUntapAll, TapOrUntapAllAi.class);
apiToClass.put(ApiType.Token, TokenAi.class);
apiToClass.put(ApiType.TwoPiles, TwoPilesAi.class);
apiToClass.put(ApiType.Unattach, CannotPlayAi.class);
apiToClass.put(ApiType.UnattachAll, UnattachAllAi.class);
apiToClass.put(ApiType.Untap, UntapAi.class);
apiToClass.put(ApiType.UntapAll, UntapAllAi.class);
apiToClass.put(ApiType.Vote, VoteAi.class);
apiToClass.put(ApiType.WinsGame, GameWinAi.class);
apiToClass.put(ApiType.InternalEtbReplacement, CanPlayAsDrawbackAi.class);
apiToClass.put(ApiType.InternalLegendaryRule, LegendaryRuleAi.class);
apiToClass.put(ApiType.InternalHaunt, HauntAi.class);
apiToClass.put(ApiType.InternalIgnoreEffect, CannotPlayAi.class);
}
public SpellAbilityAi get(ApiType api) {
SpellAbilityAi result = apiToInstance.get(api); SpellAbilityAi result = apiToInstance.get(api);
if (null == result) { if (null == result) {
Class<? extends SpellAbilityAi> clz = apiToClass.get(api); Class<? extends SpellAbilityAi> clz = apiToClass.get(api);

View File

@@ -738,9 +738,9 @@ public class ChangeZoneAi extends SpellAbilityAi {
if (source.isInZone(ZoneType.Hand)) { if (source.isInZone(ZoneType.Hand)) {
list = CardLists.filter(list, Predicates.not(CardPredicates.nameEquals(source.getName()))); // Don't get the same card back. list = CardLists.filter(list, Predicates.not(CardPredicates.nameEquals(source.getName()))); // Don't get the same card back.
} }
System.out.println("isPreferredTarget " + list); //System.out.println("isPreferredTarget " + list);
if (sa.hasParam("AttachedTo")) { if (sa.hasParam("AttachedTo")) {
System.out.println("isPreferredTarget att " + list); //System.out.println("isPreferredTarget att " + list);
list = CardLists.filter(list, new Predicate<Card>() { list = CardLists.filter(list, new Predicate<Card>() {
@Override @Override
public boolean apply(final Card c) { public boolean apply(final Card c) {
@@ -752,7 +752,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
return false; return false;
} }
}); });
System.out.println("isPreferredTarget ok " + list); //System.out.println("isPreferredTarget ok " + list);
} }
if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) { if (list.size() < tgt.getMinTargets(sa.getHostCard(), sa)) {

View File

@@ -1,6 +1,9 @@
package forge.ai.ability; package forge.ai.ability;
import java.util.List;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCard;
import forge.ai.ComputerUtilCombat; import forge.ai.ComputerUtilCombat;
@@ -22,8 +25,6 @@ import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.spellability.TargetRestrictions; import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import java.util.List;
public class ChooseSourceAi extends SpellAbilityAi { public class ChooseSourceAi extends SpellAbilityAi {
/* (non-Javadoc) /* (non-Javadoc)
@@ -184,4 +185,10 @@ public class ChooseSourceAi extends SpellAbilityAi {
} }
return null; return null;
} }
private static List<GameObject> getTargets(final SpellAbility sa) {
return sa.usesTargeting() && (!sa.hasParam("Defined"))
? Lists.newArrayList(sa.getTargets().getTargets())
: AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam("Defined"), sa);
}
} }

View File

@@ -146,7 +146,7 @@ public class DamagePreventAi extends SpellAbilityAi {
} }
} }
} }
if (sa.hasParam("DividedAsYouChoose") && sa.getTargets() != null && !sa.getTargets().getTargets().isEmpty()) { if (tgt != null && sa.hasParam("DividedAsYouChoose") && sa.getTargets() != null && !sa.getTargets().getTargets().isEmpty()) {
tgt.addDividedAllocation(sa.getTargets().getTargets().get(0), AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa)); tgt.addDividedAllocation(sa.getTargets().getTargets().get(0), AbilityUtils.calculateAmount(sa.getHostCard(), sa.getParam("Amount"), sa));
} }

View File

@@ -11,6 +11,7 @@ import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions; import forge.game.spellability.TargetRestrictions;
import forge.util.FCollection;
import java.util.List; import java.util.List;
@@ -19,7 +20,9 @@ public class LifeLoseAi extends SpellAbilityAi {
@Override @Override
public boolean chkAIDrawback(SpellAbility sa, Player ai) { public boolean chkAIDrawback(SpellAbility sa, Player ai) {
List<Player> tgtPlayers = getTargetPlayers(sa); final List<Player> tgtPlayers = sa.usesTargeting() && !sa.hasParam("Defined")
? new FCollection<Player>(sa.getTargets().getTargetPlayers())
: AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa);
final Card source = sa.getHostCard(); final Card source = sa.getHostCard();
final String amountStr = sa.getParam("LifeAmount"); final String amountStr = sa.getParam("LifeAmount");
@@ -158,7 +161,9 @@ public class LifeLoseAi extends SpellAbilityAi {
amount = AbilityUtils.calculateAmount(source, amountStr, sa); amount = AbilityUtils.calculateAmount(source, amountStr, sa);
} }
List<Player> tgtPlayers = getTargetPlayers(sa); final List<Player> tgtPlayers = sa.usesTargeting() && !sa.hasParam("Defined")
? new FCollection<Player>(sa.getTargets().getTargetPlayers())
: AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa);
if (!mandatory && tgtPlayers.contains(ai) && amount > 0 && amount + 3 > ai.getLife()) { if (!mandatory && tgtPlayers.contains(ai) && amount > 0 && amount + 3 > ai.getLife()) {
// For cards like Foul Imp, ETB you lose life // For cards like Foul Imp, ETB you lose life

View File

@@ -1,5 +1,7 @@
package forge.ai.ability; package forge.ai.ability;
import java.util.List;
import forge.ai.SpellAbilityAi; import forge.ai.SpellAbilityAi;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.Card; import forge.game.card.Card;
@@ -9,8 +11,7 @@ import forge.game.player.Player;
import forge.game.spellability.SpellAbility; import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions; import forge.game.spellability.TargetRestrictions;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.FCollection;
import java.util.List;
public class TwoPilesAi extends SpellAbilityAi { public class TwoPilesAi extends SpellAbilityAi {
@Override @Override
@@ -37,7 +38,9 @@ public class TwoPilesAi extends SpellAbilityAi {
} }
} }
List<Player> tgtPlayers = getTargetPlayers(sa); final List<Player> tgtPlayers = sa.usesTargeting() && !sa.hasParam("Defined")
? new FCollection<Player>(sa.getTargets().getTargetPlayers())
: AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Defined"), sa);
final Player p = tgtPlayers.get(0); final Player p = tgtPlayers.get(0);
CardCollectionView pool; CardCollectionView pool;

View File

@@ -1,40 +1,61 @@
package forge.util; package forge.util;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/** /**
* TODO: Write javadoc for this type. * Static utilities related to reflection.
* *
* @see java.lang.Class
*/ */
public class ReflectionUtil { public final class ReflectionUtil {
public static <T> T makeDefaultInstanceOf(Class<? extends T> cls) { /**
if ( null == cls ) * Private constructor to prevent instantiation.
*/
private ReflectionUtil() {
}
/**
* Generates a default instance of the supplied class, using that class'
* default constructor.
*
* @param cls
* a {@link Class}.
* @return an instance of the supplied class.
* @throws RuntimeException
* if the supplied class has no visible default constructor, or
* if an exception is thrown by the constructor.
* @see Class#newInstance()
*/
public static <T> T makeDefaultInstanceOf(final Class<? extends T> cls) {
if (null == cls) {
throw new IllegalArgumentException("Class<? extends T> cls must not be null"); 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 { try {
T res = c.newInstance(); final Constructor<? extends T> c = cls.getConstructor();
return res; return c.newInstance();
} catch (Exception e) { } catch (final NoSuchMethodException e) {
e.printStackTrace(); throw new RuntimeException(String.format("No default constructor found in class %s", cls.getName()));
} catch (final SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(String.format("Can't instantiate class %s using default constructor", cls.getName()));
} }
} }
}
throw new RuntimeException("No default constructor found in class " + cls.getName());
}
/** /**
* Cast object to a given type if possible, returning null if not possible * Cast object to a given type if possible, returning null if not possible
*
* @param obj * @param obj
* an object.
* @param type * @param type
* the {@link Class} to which to cast the object.
* @return a reference to the object if it's an instance of the given class,
* or {@code null} if it isn't.
* @see Class#isInstance(Object)
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T safeCast(Object obj, Class<T> type) { public static <T> T safeCast(final Object obj, final Class<T> type) {
if (type.isInstance(obj)) { if (type.isInstance(obj)) {
return (T) obj; return (T) obj;
} }

View File

@@ -0,0 +1,20 @@
package forge.game.ability;
import forge.game.spellability.SpellAbility;
public class IllegalAbilityException extends RuntimeException {
private static final long serialVersionUID = -8638474348184716635L;
public IllegalAbilityException(final SpellAbility sa) {
this(sa.toString());
}
public IllegalAbilityException(final SpellAbility sa, final SpellAbilityEffect effect) {
this(String.format("%s (effect %s)", sa, effect.getClass().getName()));
}
private IllegalAbilityException(final String message) {
super(message);
}
}

View File

@@ -1,62 +0,0 @@
package forge.game.ability;
import com.google.common.collect.Lists;
import forge.game.GameObject;
import forge.game.card.CardCollection;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.FCollection;
import java.util.List;
// Class contains all that methods that are used by both effects and AI to fetch their targets.
// {SA}Effect and {SA}Ai now inherit from this class to use these routines, though they should not.
public class SaTargetRoutines {
// Cards
protected CardCollection getTargetCards(SpellAbility sa) { return getCards(false, "Defined", sa); }
protected CardCollection getTargetCards(SpellAbility sa, String definedParam) { return getCards(false, definedParam, sa); }
protected CardCollection getDefinedCardsOrTargeted(SpellAbility sa) { return getCards(true, "Defined", sa); }
protected CardCollection getDefinedCardsOrTargeted(SpellAbility sa, String definedParam) { return getCards(true, definedParam, sa); }
private static CardCollection getCards(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam))
&& sa.getTargets() != null && (sa.getTargets().isTargetingAnyCard() || sa.getTargets().getTargets().isEmpty());
return useTargets ? new CardCollection(sa.getTargets().getTargetCards())
: AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Players
protected FCollection<Player> getTargetPlayers(SpellAbility sa) { return getPlayers(false, "Defined", sa); }
protected FCollection<Player> getTargetPlayers(SpellAbility sa, String definedParam) { return getPlayers(false, definedParam, sa); }
protected FCollection<Player> getDefinedPlayersOrTargeted(SpellAbility sa ) { return getPlayers(true, "Defined", sa); }
protected FCollection<Player> getDefinedPlayersOrTargeted(SpellAbility sa, String definedParam) { return getPlayers(true, definedParam, sa); }
private static FCollection<Player> getPlayers(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? new FCollection<Player>(sa.getTargets().getTargetPlayers())
: AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Spells
protected List<SpellAbility> getTargetSpells(SpellAbility sa) { return getSpells(false, "Defined", sa); }
protected List<SpellAbility> getTargetSpells(SpellAbility sa, String definedParam) { return getSpells(false, definedParam, sa); }
protected List<SpellAbility> getDefinedSpellsOrTargeted(SpellAbility sa, String definedParam) { return getSpells(true, definedParam, sa); }
private static List<SpellAbility> getSpells(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargetSpells())
: AbilityUtils.getDefinedSpellAbilities(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Targets of unspecified type
protected List<GameObject> getTargets(SpellAbility sa) { return getTargetables(false, "Defined", sa); }
protected List<GameObject> getTargets(SpellAbility sa, String definedParam) { return getTargetables(false, definedParam, sa); }
protected List<GameObject> getDefinedOrTargeted(SpellAbility sa, String definedParam) { return getTargetables(true, definedParam, sa); }
private static List<GameObject> getTargetables(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargets())
: AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam(definedParam), sa);
}
}

View File

@@ -1,16 +1,22 @@
package forge.game.ability; package forge.game.ability;
import forge.game.GameObject;
import forge.game.card.CardFactoryUtil;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import org.apache.commons.lang3.StringUtils;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
import forge.game.GameObject;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardFactoryUtil;
import forge.game.player.Player;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.util.FCollection;
/** /**
* <p> * <p>
* AbilityFactory_AlterLife class. * AbilityFactory_AlterLife class.
@@ -20,7 +26,7 @@ import java.util.StringTokenizer;
* @version $Id: AbilityFactoryAlterLife.java 17656 2012-10-22 19:32:56Z Max mtg $ * @version $Id: AbilityFactoryAlterLife.java 17656 2012-10-22 19:32:56Z Max mtg $
*/ */
public abstract class SpellAbilityEffect extends SaTargetRoutines { public abstract class SpellAbilityEffect {
public abstract void resolve(SpellAbility sa); public abstract void resolve(SpellAbility sa);
@@ -129,4 +135,52 @@ public abstract class SpellAbilityEffect extends SaTargetRoutines {
} }
} }
} }
// Target/defined methods
// Cards
protected final static CardCollection getTargetCards(final SpellAbility sa) { return getCards(false, "Defined", sa); }
protected final static CardCollection getTargetCards(final SpellAbility sa, final String definedParam) { return getCards(false, definedParam, sa); }
protected final static CardCollection getDefinedCardsOrTargeted(final SpellAbility sa) { return getCards(true, "Defined", sa); }
protected final static CardCollection getDefinedCardsOrTargeted(final SpellAbility sa, final String definedParam) { return getCards(true, definedParam, sa); }
private static CardCollection getCards(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam))
&& sa.getTargets() != null && (sa.getTargets().isTargetingAnyCard() || sa.getTargets().getTargets().isEmpty());
return useTargets ? new CardCollection(sa.getTargets().getTargetCards())
: AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Players
protected final static FCollection<Player> getTargetPlayers(final SpellAbility sa) { return getPlayers(false, "Defined", sa); }
protected final static FCollection<Player> getTargetPlayers(final SpellAbility sa, final String definedParam) { return getPlayers(false, definedParam, sa); }
protected final static FCollection<Player> getDefinedPlayersOrTargeted(final SpellAbility sa ) { return getPlayers(true, "Defined", sa); }
protected final static FCollection<Player> getDefinedPlayersOrTargeted(final SpellAbility sa, final String definedParam) { return getPlayers(true, definedParam, sa); }
private static FCollection<Player> getPlayers(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? new FCollection<Player>(sa.getTargets().getTargetPlayers())
: AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Spells
protected final static List<SpellAbility> getTargetSpells(final SpellAbility sa) { return getSpells(false, "Defined", sa); }
protected final static List<SpellAbility> getTargetSpells(final SpellAbility sa, final String definedParam) { return getSpells(false, definedParam, sa); }
protected final static List<SpellAbility> getDefinedSpellsOrTargeted(final SpellAbility sa, final String definedParam) { return getSpells(true, definedParam, sa); }
private static List<SpellAbility> getSpells(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargetSpells())
: AbilityUtils.getDefinedSpellAbilities(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Targets of unspecified type
protected final static List<GameObject> getTargets(final SpellAbility sa) { return getTargetables(false, "Defined", sa); }
protected final static List<GameObject> getTargets(final SpellAbility sa, final String definedParam) { return getTargetables(false, definedParam, sa); }
protected final static List<GameObject> getDefinedOrTargeted(SpellAbility sa, final String definedParam) { return getTargetables(true, definedParam, sa); }
private static List<GameObject> getTargetables(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargets())
: AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam(definedParam), sa);
}
} }

View File

@@ -1,10 +1,19 @@
package forge.game.ability.effects; package forge.game.ability.effects;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.game.Game; import forge.game.Game;
import forge.game.ability.AbilityFactory; import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.IllegalAbilityException;
import forge.game.ability.SpellAbilityEffect; import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card; import forge.game.card.Card;
import forge.game.card.CardCollection; import forge.game.card.CardCollection;
@@ -17,8 +26,6 @@ import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.FCollection; import forge.util.FCollection;
import java.util.*;
import java.util.Map.Entry;
public class RepeatEachEffect extends SpellAbilityEffect { public class RepeatEachEffect extends SpellAbilityEffect {
@@ -63,6 +70,9 @@ public class RepeatEachEffect extends SpellAbilityEffect {
loopOverCards = true; loopOverCards = true;
} }
} }
else {
throw new IllegalAbilityException(sa, this);
}
if (sa.hasParam("ClearRemembered")) { if (sa.hasParam("ClearRemembered")) {
source.clearRemembered(); source.clearRemembered();

View File

@@ -8,6 +8,7 @@ import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Objects;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
@@ -23,6 +24,7 @@ import forge.game.zone.ZoneType;
import forge.trackable.TrackableCollection; import forge.trackable.TrackableCollection;
import forge.trackable.TrackableProperty; import forge.trackable.TrackableProperty;
import forge.trackable.Tracker; import forge.trackable.Tracker;
import forge.util.FCollection;
import forge.util.FCollectionView; import forge.util.FCollectionView;
import forge.util.Lang; import forge.util.Lang;
@@ -82,7 +84,7 @@ public class PlayerView extends GameEntityView {
} }
public FCollectionView<PlayerView> getOpponents() { public FCollectionView<PlayerView> getOpponents() {
return get(TrackableProperty.Opponents); return Objects.firstNonNull(this.<FCollectionView<PlayerView>>get(TrackableProperty.Opponents), new FCollection<PlayerView>());
} }
void updateOpponents(Player p) { void updateOpponents(Player p) {
set(TrackableProperty.Opponents, PlayerView.getCollection(p.getOpponents())); set(TrackableProperty.Opponents, PlayerView.getCollection(p.getOpponents()));
@@ -123,7 +125,7 @@ public class PlayerView extends GameEntityView {
final FCollectionView<PlayerView> opponents = getOpponents(); final FCollectionView<PlayerView> opponents = getOpponents();
final List<String> info = Lists.newArrayListWithExpectedSize(opponents.size()); final List<String> info = Lists.newArrayListWithExpectedSize(opponents.size());
info.add(String.format("Commander: %s", commander)); info.add(String.format("Commander: %s", commander));
for (final PlayerView p : Iterables.concat(Collections.singleton(this), opponents == null ? Collections.<PlayerView>emptySet() : opponents)) { for (final PlayerView p : Iterables.concat(Collections.singleton(this), opponents)) {
final int damage = this.getCommanderDamage(p.getCommander()); final int damage = this.getCommanderDamage(p.getCommander());
if (damage > 0) { if (damage > 0) {
final String text; final String text;

View File

@@ -103,7 +103,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
private int totalManaSpent = 0; private int totalManaSpent = 0;
/** The pay costs. */ /** The pay costs. */
private Cost payCosts = null; private Cost payCosts;
private SpellAbilityRestriction restrictions = new SpellAbilityRestriction(); private SpellAbilityRestriction restrictions = new SpellAbilityRestriction();
private SpellAbilityCondition conditions = new SpellAbilityCondition(); private SpellAbilityCondition conditions = new SpellAbilityCondition();
private AbilitySub subAbility = null; private AbilitySub subAbility = null;

View File

@@ -66,7 +66,7 @@ public class DeckgenUtil {
} }
gen.setSingleton(FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS)); gen.setSingleton(FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS));
gen.setUseArtifacts(!FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)); gen.setUseArtifacts(!FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
CardPool cards = gen == null ? null : gen.getDeck(60, forAi); final CardPool cards = gen.getDeck(60, forAi);
if (null == deckName) { if (null == deckName) {
deckName = Lang.joinHomogenous(Arrays.asList(selection)); deckName = Lang.joinHomogenous(Arrays.asList(selection));
@@ -312,7 +312,7 @@ public class DeckgenUtil {
gen = new DeckGenerator2Color(cardDb, format, comColors.get(0), comColors.get(1)); gen = new DeckGenerator2Color(cardDb, format, comColors.get(0), comColors.get(1));
gen.setSingleton(true); gen.setSingleton(true);
gen.setUseArtifacts(!FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)); gen.setUseArtifacts(!FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
CardPool cards = gen == null ? null : gen.getDeck(gameType.getDeckFormat().getMainRange().getMaximum(), forAi); CardPool cards = gen.getDeck(gameType.getDeckFormat().getMainRange().getMaximum(), forAi);
// After generating card lists, build deck. // After generating card lists, build deck.
deck = new Deck("Generated " + gameType.toString() + " deck (" + commander.getName() + ")"); deck = new Deck("Generated " + gameType.toString() + " deck (" + commander.getName() + ")");

View File

@@ -385,13 +385,14 @@ public abstract class GameLobby {
deck = autoGenerateVariant.autoGenerateDeck(rp); deck = autoGenerateVariant.autoGenerateDeck(rp);
} }
// Initialise variables for other variants
deck = deck == null ? rp.getDeck() : deck;
final CardPool avatarPool = deck.get(DeckSection.Avatar); final CardPool avatarPool = deck.get(DeckSection.Avatar);
if (avatarPool != null) { if (avatarPool != null) {
vanguardAvatar = avatarPool.get(0); vanguardAvatar = avatarPool.get(0);
} }
// Initialise variables for other variants
deck = deck == null ? rp.getDeck() : deck;
Iterable<PaperCard> schemes = null; Iterable<PaperCard> schemes = null;
Iterable<PaperCard> planes = null; Iterable<PaperCard> planes = null;

View File

@@ -155,18 +155,19 @@ public class FGameClient implements IToServer {
replies.complete(event.getIndex(), event.getReply()); replies.complete(event.getIndex(), event.getReply());
} else if (msg instanceof GuiGameEvent) { } else if (msg instanceof GuiGameEvent) {
final GuiGameEvent event = (GuiGameEvent) msg; final GuiGameEvent event = (GuiGameEvent) msg;
final String method = event.getMethod();
final Object[] args = event.getObjects(); final Object[] args = event.getObjects();
Serializable reply = null; Serializable reply = null;
boolean doReply = false; boolean doReply = false;
final IButton btn; final IButton btn;
if (args.length >= 2 && args[0] instanceof PlayerView && args[1] instanceof MatchButtonType) { if (method.startsWith("btn_") && args.length >= 2 && args[0] instanceof PlayerView && args[1] instanceof MatchButtonType) {
btn = args[1] == MatchButtonType.OK ? clientGui.getBtnOK((PlayerView) args[0]) : clientGui.getBtnCancel((PlayerView) args[0]); btn = args[1] == MatchButtonType.OK ? clientGui.getBtnOK((PlayerView) args[0]) : clientGui.getBtnCancel((PlayerView) args[0]);
} else { } else {
btn = null; btn = null;
} }
switch (event.getMethod()) { switch (method) {
case "setGameView": case "setGameView":
clientGui.setGameView((GameView) args[0]); clientGui.setGameView((GameView) args[0]);
break; break;