mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
AI: changed many calls to accept Collection<T> instead of List<T>
GameAction - legend rule and planeswalker rule are updated to match changes introduced with "Magic 2014 Core Set" InputSelectCardsFromList also accepts any Collection<T>, not just List<T> PlayerControllerHuman - chooseSingleCardForEffect tries to use InputSelectCardsFromList when all cards are in Battlefield or own hand
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -14251,6 +14251,7 @@ src/main/java/forge/card/ability/ai/FlipACoinAi.java -text
|
||||
src/main/java/forge/card/ability/ai/FogAi.java -text
|
||||
src/main/java/forge/card/ability/ai/GameLossAi.java -text
|
||||
src/main/java/forge/card/ability/ai/GameWinAi.java -text
|
||||
src/main/java/forge/card/ability/ai/LegendaryRuleAi.java -text
|
||||
src/main/java/forge/card/ability/ai/LifeExchangeAi.java -text
|
||||
src/main/java/forge/card/ability/ai/LifeGainAi.java -text
|
||||
src/main/java/forge/card/ability/ai/LifeLoseAi.java -text
|
||||
|
||||
@@ -58,6 +58,7 @@ import forge.card.ability.ai.FlipACoinAi;
|
||||
import forge.card.ability.ai.FogAi;
|
||||
import forge.card.ability.ai.GameLossAi;
|
||||
import forge.card.ability.ai.GameWinAi;
|
||||
import forge.card.ability.ai.LegendaryRuleAi;
|
||||
import forge.card.ability.ai.LifeExchangeAi;
|
||||
import forge.card.ability.ai.LifeGainAi;
|
||||
import forge.card.ability.ai.LifeLoseAi;
|
||||
@@ -220,8 +221,8 @@ public enum ApiType {
|
||||
WinsGame (GameWinEffect.class, GameWinAi.class),
|
||||
|
||||
|
||||
|
||||
InternalEtbReplacement(ETBReplacementEffect.class, CanPlayAsDrawbackAi.class);
|
||||
InternalEtbReplacement(ETBReplacementEffect.class, CanPlayAsDrawbackAi.class),
|
||||
InternalLegendaryRule(CharmEffect.class, LegendaryRuleAi.class); // Charm has empty resolve blocks, may act as a dummy
|
||||
|
||||
private final Class<? extends SpellAbilityEffect> clsEffect;
|
||||
private final Class<? extends SpellAbilityAi> clsAi;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package forge.card.ability;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
@@ -113,9 +116,9 @@ public abstract class SpellAbilityAi extends SaTargetRountines {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleCard is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||
return options.get(0);
|
||||
return Iterables.getFirst(options, null);
|
||||
}
|
||||
|
||||
public Player chooseSinglePlayer(Player ai, SpellAbility sa, List<Player> options) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -1208,7 +1209,7 @@ public class AttachAi extends SpellAbilityAi {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
return attachToCardAIPreferences(ai, sa, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.ability.SpellAbilityAi;
|
||||
@@ -52,7 +52,7 @@ public final class BondAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@Override
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
return ComputerUtilCard.getBestCreatureAI(options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
@@ -1402,7 +1403,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
|
||||
|
||||
@Override
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
// Called when looking for creature to attach aura or equipment
|
||||
return ComputerUtilCard.getBestAI(options);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
@@ -97,7 +98,7 @@ public class ChooseCardAi extends SpellAbilityAi {
|
||||
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.card.spellability.SpellAbility, java.util.List, boolean)
|
||||
*/
|
||||
@Override
|
||||
public Card chooseSingleCard(final Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(final Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
final Card host = sa.getSourceCard();
|
||||
final String logic = sa.getParam("AILogic");
|
||||
Card choice = null;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
@@ -126,7 +127,7 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.game.player.Player, forge.card.spellability.SpellAbility, java.util.List, boolean)
|
||||
*/
|
||||
@Override
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
// Select a card to attach to
|
||||
return ComputerUtilCard.getBestAI(options);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
@@ -71,7 +72,7 @@ public final class EncodeAi extends SpellAbilityAi {
|
||||
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.game.player.Player, forge.card.spellability.SpellAbility, java.util.List, boolean)
|
||||
*/
|
||||
@Override
|
||||
public Card chooseSingleCard(final Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(final Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
Card choice = null;
|
||||
// final String logic = sa.getParam("AILogic");
|
||||
// if (logic == null) {
|
||||
|
||||
42
src/main/java/forge/card/ability/ai/LegendaryRuleAi.java
Normal file
42
src/main/java/forge/card/ability/ai/LegendaryRuleAi.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.ability.SpellAbilityAi;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.player.Player;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class LegendaryRuleAi extends SpellAbilityAi {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#canPlayAI(forge.game.player.Player, forge.card.spellability.SpellAbility)
|
||||
*/
|
||||
@Override
|
||||
protected boolean canPlayAI(Player aiPlayer, SpellAbility sa) {
|
||||
return false; // should not get here
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Card chooseSingleCard(Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
// Choose a single legendary/planeswalker card to keep
|
||||
Card firstOption = Iterables.getFirst(options, null);
|
||||
boolean choosingFromPlanewalkers = firstOption.isPlaneswalker();
|
||||
|
||||
if ( choosingFromPlanewalkers ) {
|
||||
// AI decision making - should AI compare counters?
|
||||
} else {
|
||||
// AI decision making - should AI compare damage and debuffs?
|
||||
}
|
||||
|
||||
return firstOption;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.card.ability.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -112,7 +113,7 @@ public class PlayAi extends SpellAbilityAi {
|
||||
* @see forge.card.ability.SpellAbilityAi#chooseSingleCard(forge.game.player.Player, forge.card.spellability.SpellAbility, java.util.List, boolean)
|
||||
*/
|
||||
@Override
|
||||
public Card chooseSingleCard(final Player ai, SpellAbility sa, List<Card> options, boolean isOptional) {
|
||||
public Card chooseSingleCard(final Player ai, SpellAbility sa, Collection<Card> options, boolean isOptional) {
|
||||
List<Card> tgtCards = CardLists.filter(options, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
|
||||
@@ -90,7 +90,7 @@ public class InputQueue extends Observable {
|
||||
input.awaitLatchRelease();
|
||||
}
|
||||
|
||||
public void setInput(InputSynchronized input) {
|
||||
void setInput(InputSynchronized input) {
|
||||
this.inputStack.push(input);
|
||||
syncPoint();
|
||||
this.updateObservers();
|
||||
|
||||
@@ -28,9 +28,10 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import forge.Card;
|
||||
import forge.CardCharacteristicName;
|
||||
@@ -46,6 +47,7 @@ import forge.ITargetable;
|
||||
import forge.card.CardType;
|
||||
import forge.card.TriggerReplacementBase;
|
||||
import forge.card.ability.AbilityFactory;
|
||||
import forge.card.ability.ApiType;
|
||||
import forge.card.ability.effects.AttachEffect;
|
||||
import forge.card.cardfactory.CardFactory;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
@@ -54,6 +56,7 @@ import forge.card.mana.ManaCost;
|
||||
import forge.card.replacement.ReplacementResult;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.TargetRestrictions;
|
||||
import forge.card.staticability.StaticAbility;
|
||||
@@ -902,12 +905,14 @@ public class GameAction {
|
||||
game.getStack().chooseOrderOfSimultaneousStackEntryAll();
|
||||
}
|
||||
|
||||
if (this.handleLegendRule()) {
|
||||
checkAgain = true;
|
||||
}
|
||||
|
||||
if (this.handlePlaneswalkerRule()) {
|
||||
checkAgain = true;
|
||||
for(Player p : game.getPlayers() ) {
|
||||
if (this.handleLegendRule(p)) {
|
||||
checkAgain = true;
|
||||
}
|
||||
|
||||
if (this.handlePlaneswalkerRule(p)) {
|
||||
checkAgain = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!checkAgain) {
|
||||
@@ -1139,15 +1144,13 @@ public class GameAction {
|
||||
* destroyPlaneswalkers.
|
||||
* </p>
|
||||
*/
|
||||
private boolean handlePlaneswalkerRule() {
|
||||
private boolean handlePlaneswalkerRule(Player p) {
|
||||
// get all Planeswalkers
|
||||
final List<Card> list = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.PLANEWALKERS);
|
||||
final List<Card> list = CardLists.filter(p.getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.PLANEWALKERS);
|
||||
|
||||
boolean recheck = false;
|
||||
Card c;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
c = list.get(i);
|
||||
|
||||
final Multimap<String, Card> uniqueWalkers = ArrayListMultimap.create();
|
||||
for (Card c : list) {
|
||||
if (c.getCounters(CounterType.LOYALTY) <= 0) {
|
||||
moveToGraveyard(c);
|
||||
// Play the Destroy sound
|
||||
@@ -1155,22 +1158,29 @@ public class GameAction {
|
||||
recheck = true;
|
||||
}
|
||||
|
||||
final ArrayList<String> types = c.getType();
|
||||
for (final String type : types) {
|
||||
if (!CardType.isAPlaneswalkerType(type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final List<Card> cl = CardLists.getType(list, type);
|
||||
|
||||
if (cl.size() > 1) {
|
||||
for (final Card crd : cl) {
|
||||
moveToGraveyard(crd);
|
||||
}
|
||||
recheck = true;
|
||||
for (final String type : c.getType()) {
|
||||
if (CardType.isAPlaneswalkerType(type)) {
|
||||
uniqueWalkers.put(type, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(String key : uniqueWalkers.keySet())
|
||||
{
|
||||
Collection<Card> duplicates = uniqueWalkers.get(key);
|
||||
if ( duplicates.size() < 2)
|
||||
continue;
|
||||
|
||||
recheck = true;
|
||||
|
||||
Card toKeep = p.getController().chooseSingleCardForEffect(duplicates, new AbilitySub(ApiType.InternalLegendaryRule, null, null, null), "You have multiple planeswalkers of type \""+key+"\"in play.\n\nChoose one to stay on battlefield (the rest will be moved to graveyard)");
|
||||
for(Card c: duplicates) {
|
||||
if ( c != toKeep )
|
||||
moveToGraveyard(c);
|
||||
}
|
||||
|
||||
}
|
||||
return recheck;
|
||||
}
|
||||
|
||||
@@ -1179,8 +1189,8 @@ public class GameAction {
|
||||
* destroyLegendaryCreatures.
|
||||
* </p>
|
||||
*/
|
||||
private boolean handleLegendRule() {
|
||||
final List<Card> a = CardLists.getType(game.getCardsIn(ZoneType.Battlefield), "Legendary");
|
||||
private boolean handleLegendRule(Player p) {
|
||||
final List<Card> a = CardLists.getType(p.getCardsIn(ZoneType.Battlefield), "Legendary");
|
||||
if (a.isEmpty() || game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noLegendRule)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1189,24 +1199,26 @@ public class GameAction {
|
||||
if (yamazaki.size() == 2) {
|
||||
a.removeAll(yamazaki);
|
||||
}
|
||||
while (!a.isEmpty()) {
|
||||
List<Card> b = CardLists.filter(game.getCardsIn(ZoneType.Battlefield), CardPredicates.nameEquals(a.get(0).getName()));
|
||||
b = CardLists.getType(b, "Legendary");
|
||||
b = CardLists.filter(b, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return !c.isFaceDown();
|
||||
}
|
||||
});
|
||||
a.remove(0);
|
||||
if (1 < b.size()) {
|
||||
for (int i = 0; i < b.size(); i++) {
|
||||
sacrificeDestroy(b.get(i));
|
||||
}
|
||||
recheck = true;
|
||||
// Play the Destroy sound
|
||||
game.fireEvent(new GameEventCardDestroyed());
|
||||
|
||||
Multimap<String, Card> uniqueLegends = ArrayListMultimap.create();
|
||||
for(Card c : a) {
|
||||
if ( !c.isFaceDown() )
|
||||
uniqueLegends.put(c.getName(), c);
|
||||
}
|
||||
|
||||
for(String name : uniqueLegends.keySet()) {
|
||||
Collection<Card> cc = uniqueLegends.get(name);
|
||||
if ( cc.size() < 2 )
|
||||
continue;
|
||||
|
||||
recheck = true;
|
||||
|
||||
Card toKeep = p.getController().chooseSingleCardForEffect(cc, new AbilitySub(ApiType.InternalLegendaryRule, null, null, null), "You have multiple legendary creatures named \""+name+"\" in play.\n\nChoose the one to stay on battlefield (the rest will be moved to graveyard)");
|
||||
for(Card c: cc) {
|
||||
if ( c != toKeep )
|
||||
sacrificeDestroy(c);
|
||||
}
|
||||
game.fireEvent(new GameEventCardDestroyed());
|
||||
}
|
||||
|
||||
return recheck;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.game.ai;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@@ -124,7 +125,7 @@ public class ComputerUtilCard {
|
||||
* a {@link forge.CardList} object.
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public static Card getBestLandAI(final List<Card> list) {
|
||||
public static Card getBestLandAI(final Collection<Card> list) {
|
||||
final List<Card> land = CardLists.filter(list, CardPredicates.Presets.LANDS);
|
||||
if (land.isEmpty()) {
|
||||
return null;
|
||||
@@ -180,8 +181,7 @@ public class ComputerUtilCard {
|
||||
* a boolean.
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public static Card getCheapestPermanentAI(final List<Card> list, final SpellAbility spell, final boolean targeted) {
|
||||
List<Card> all = list;
|
||||
public static Card getCheapestPermanentAI(Collection<Card> all, final SpellAbility spell, final boolean targeted) {
|
||||
if (targeted) {
|
||||
all = CardLists.filter(all, new Predicate<Card>() {
|
||||
@Override
|
||||
@@ -190,17 +190,16 @@ public class ComputerUtilCard {
|
||||
}
|
||||
});
|
||||
}
|
||||
if (all.size() == 0) {
|
||||
if (all.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// get cheapest card:
|
||||
Card cheapest = null;
|
||||
cheapest = all.get(0);
|
||||
|
||||
for (int i = 0; i < all.size(); i++) {
|
||||
if (cheapest.getManaCost().getCMC() <= cheapest.getManaCost().getCMC()) {
|
||||
cheapest = all.get(i);
|
||||
for (Card c : all) {
|
||||
if (cheapest == null || cheapest.getManaCost().getCMC() <= cheapest.getManaCost().getCMC()) {
|
||||
cheapest = c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +217,7 @@ public class ComputerUtilCard {
|
||||
* a {@link forge.CardList} object.
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public static Card getBestAI(final List<Card> list) {
|
||||
public static Card getBestAI(final Collection<Card> list) {
|
||||
// Get Best will filter by appropriate getBest list if ALL of the list
|
||||
// is of that type
|
||||
if (Iterables.all(list, CardPredicates.Presets.CREATURES))
|
||||
@@ -239,7 +238,7 @@ public class ComputerUtilCard {
|
||||
* the list
|
||||
* @return the card
|
||||
*/
|
||||
public static Card getBestCreatureAI(final List<Card> list) {
|
||||
public static Card getBestCreatureAI(final Collection<Card> list) {
|
||||
return Aggregates.itemWithMax(Iterables.filter(list, CardPredicates.Presets.CREATURES), ComputerUtilCard.fnEvaluateCreature);
|
||||
}
|
||||
|
||||
@@ -292,7 +291,7 @@ public class ComputerUtilCard {
|
||||
* a {@link forge.CardList} object.
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public static Card getWorstAI(final List<Card> list) {
|
||||
public static Card getWorstAI(final Collection<Card> list) {
|
||||
return ComputerUtilCard.getWorstPermanentAI(list, false, false, false, false);
|
||||
}
|
||||
|
||||
@@ -313,7 +312,7 @@ public class ComputerUtilCard {
|
||||
* a boolean.
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public static Card getWorstPermanentAI(final List<Card> list, final boolean biasEnch, final boolean biasLand,
|
||||
public static Card getWorstPermanentAI(final Collection<Card> list, final boolean biasEnch, final boolean biasLand,
|
||||
final boolean biasArt, final boolean biasCreature) {
|
||||
if (list.size() == 0) {
|
||||
return null;
|
||||
@@ -628,7 +627,7 @@ public class ComputerUtilCard {
|
||||
* the all
|
||||
* @return the card
|
||||
*/
|
||||
public static Card getMostExpensivePermanentAI(final List<Card> all) {
|
||||
public static Card getMostExpensivePermanentAI(final Collection<Card> all) {
|
||||
Card biggest = null;
|
||||
|
||||
int bigCMC = -1;
|
||||
|
||||
@@ -112,8 +112,8 @@ public abstract class PlayerController {
|
||||
// Specify a target of a spell (Spellskite)
|
||||
public abstract Pair<SpellAbilityStackInstance, ITargetable> chooseTarget(SpellAbility sa, List<Pair<SpellAbilityStackInstance, ITargetable>> allTargets);
|
||||
|
||||
public Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title) { return chooseSingleCardForEffect(sourceList, sa, title, false); }
|
||||
public abstract Card chooseSingleCardForEffect(List<Card> sourceList, SpellAbility sa, String title, boolean isOptional);
|
||||
public Card chooseSingleCardForEffect(Collection<Card> sourceList, SpellAbility sa, String title) { return chooseSingleCardForEffect(sourceList, sa, title, false); }
|
||||
public abstract Card chooseSingleCardForEffect(Collection<Card> sourceList, SpellAbility sa, String title, boolean isOptional);
|
||||
public abstract Player chooseSinglePlayerForEffect(List<Player> options, SpellAbility sa, String title);
|
||||
public abstract SpellAbility chooseSingleSpellForEffect(List<SpellAbility> spells, SpellAbility sa, String title);
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ public class PlayerControllerAi extends PlayerController {
|
||||
|
||||
|
||||
@Override
|
||||
public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) {
|
||||
public Card chooseSingleCardForEffect(Collection<Card> options, SpellAbility sa, String title, boolean isOptional) {
|
||||
ApiType api = sa.getApi();
|
||||
if ( null == api ) {
|
||||
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
|
||||
|
||||
@@ -37,6 +37,7 @@ import forge.game.Game;
|
||||
import forge.game.GameType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.zone.Zone;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.gui.GuiDialog;
|
||||
@@ -272,17 +273,33 @@ public class PlayerControllerHuman extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) {
|
||||
public Card chooseSingleCardForEffect(Collection<Card> options, SpellAbility sa, String title, boolean isOptional) {
|
||||
// Human is supposed to read the message and understand from it what to choose
|
||||
if (options.isEmpty())
|
||||
return null;
|
||||
if ( !isOptional && options.size() == 1 )
|
||||
return Iterables.getFirst(options, null);
|
||||
|
||||
boolean canUseSelectCardsInput = true;
|
||||
for(Card c : options) {
|
||||
Zone cz = c.getZone();
|
||||
// can point at cards in own hand and anyone's battlefield
|
||||
boolean canUiPointAtCards = cz != null && ( cz.is(ZoneType.Hand) && cz.getPlayer() == player || cz.is(ZoneType.Battlefield));
|
||||
if ( !canUiPointAtCards ) {
|
||||
canUseSelectCardsInput = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isOptional )
|
||||
return GuiChoose.oneOrNone(title, options);
|
||||
else if ( options.size() > 1 )
|
||||
return GuiChoose.one(title, options);
|
||||
else
|
||||
return options.get(0);
|
||||
if ( canUseSelectCardsInput ) {
|
||||
InputSelectCardsFromList input = new InputSelectCardsFromList(isOptional ? 0 : 1, 1, options);
|
||||
input.setCancelAllowed(isOptional);
|
||||
input.setMessage(title);
|
||||
Singletons.getControl().getInputQueue().setInputAndWait(input);
|
||||
return Iterables.getFirst(input.getSelected(), null);
|
||||
}
|
||||
|
||||
return isOptional ? GuiChoose.oneOrNone(title, options) : GuiChoose.one(title, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package forge.gui.input;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import java.util.Collection;
|
||||
import forge.Card;
|
||||
|
||||
public class InputSelectCardsFromList extends InputSelectCards {
|
||||
private static final long serialVersionUID = 6230360322294805986L;
|
||||
|
||||
private final List<Card> validChoices;
|
||||
private final Collection<Card> validChoices;
|
||||
|
||||
public InputSelectCardsFromList(int min, int max, List<Card> validCards) {
|
||||
public InputSelectCardsFromList(int min, int max, Collection<Card> validCards) {
|
||||
super(Math.min(min, validCards.size()), Math.min(max, validCards.size())); // to avoid hangs
|
||||
this.validChoices = validCards;
|
||||
|
||||
|
||||
@@ -369,9 +369,12 @@ public enum CMatchUI {
|
||||
}
|
||||
}
|
||||
|
||||
private final static boolean LOG_UIEVENTS = false;
|
||||
|
||||
// UI-related events should arrive here
|
||||
public void fireEvent(UiEvent uiEvent) {
|
||||
if ( LOG_UIEVENTS )
|
||||
System.out.println("UI: " + uiEvent.toString() + " \t\t " + FThreads.debugGetStackTraceItem(4, true));
|
||||
uiEvents.post(uiEvent);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user