mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Backup Plan with hot swappable Input
This commit is contained in:
@@ -36,6 +36,7 @@ import forge.game.replacement.ReplacementEffect;
|
|||||||
import forge.game.spellability.*;
|
import forge.game.spellability.*;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
|
import forge.game.zone.PlayerZone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
@@ -853,6 +854,22 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
return brains.chooseSaToActivateFromOpeningHand(usableFromOpeningHand);
|
return brains.chooseSaToActivateFromOpeningHand(usableFromOpeningHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlayerZone chooseStartingHand(List<PlayerZone> zones) {
|
||||||
|
// Rate all the hands using the AI's hand evaluation function
|
||||||
|
int bestScore = Integer.MIN_VALUE;
|
||||||
|
PlayerZone bestZone = null;
|
||||||
|
for (PlayerZone zone : zones) {
|
||||||
|
int score = ComputerUtil.scoreHand(zone.getCards(), this.player, 0);
|
||||||
|
if (score > bestScore) {
|
||||||
|
bestScore = score;
|
||||||
|
bestZone = zone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestZone;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int chooseNumber(SpellAbility sa, String title, int min, int max) {
|
public int chooseNumber(SpellAbility sa, String title, int min, int max) {
|
||||||
return brains.chooseNumber(sa, title, min, max);
|
return brains.chooseNumber(sa, title, min, max);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.*;
|
import forge.game.card.*;
|
||||||
import forge.game.event.*;
|
import forge.game.event.*;
|
||||||
|
import forge.game.extrahands.BackupPlanService;
|
||||||
import forge.game.keyword.Keyword;
|
import forge.game.keyword.Keyword;
|
||||||
import forge.game.keyword.KeywordInterface;
|
import forge.game.keyword.KeywordInterface;
|
||||||
import forge.game.mulligan.MulliganService;
|
import forge.game.mulligan.MulliganService;
|
||||||
@@ -2074,7 +2075,10 @@ public class GameAction {
|
|||||||
p1.drawCards(p1.getStartingHandSize());
|
p1.drawCards(p1.getStartingHandSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
// If pl has Backup Plan as a Conspiracy draw that many extra hands
|
BackupPlanService backupPlans = new BackupPlanService(p1);
|
||||||
|
if (backupPlans.initializeExtraHands()) {
|
||||||
|
backupPlans.chooseHand();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Choose starting hand for each player with multiple hands
|
// Choose starting hand for each player with multiple hands
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package forge.game.extrahands;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.PlayerZone;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BackupPlanService {
|
||||||
|
private final Player player;
|
||||||
|
private boolean multipleHands = false;
|
||||||
|
List<PlayerZone> hands = Lists.newArrayList();
|
||||||
|
private PlayerZone hand;
|
||||||
|
|
||||||
|
public BackupPlanService(Player p1) {
|
||||||
|
this.player = p1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean initializeExtraHands() {
|
||||||
|
hand = player.getZone(ZoneType.Hand);
|
||||||
|
hands.add(hand);
|
||||||
|
|
||||||
|
// If pl has Backup Plan as a Conspiracy draw that many extra hands
|
||||||
|
if (player.getExtraZones() == null) {
|
||||||
|
return multipleHands;
|
||||||
|
}
|
||||||
|
for(PlayerZone extraHand : player.getExtraZones()) {
|
||||||
|
if (extraHand.getZoneType() == ZoneType.ExtraHand) {
|
||||||
|
player.drawCards(7, extraHand);
|
||||||
|
multipleHands = true;
|
||||||
|
hands.add(extraHand);
|
||||||
|
// If we figure out how to render the zone in the UI, do it here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.updateZoneForView(hand);
|
||||||
|
return multipleHands;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void chooseHand() {
|
||||||
|
if (!multipleHands) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerZone library = player.getZone(ZoneType.Library);
|
||||||
|
// Choose one of the starting hands and recycle the rest
|
||||||
|
PlayerZone startingHand = player.getController().chooseStartingHand(hands);
|
||||||
|
if (startingHand == hand) {
|
||||||
|
for(PlayerZone extraHand : player.getExtraZones()) {
|
||||||
|
if (extraHand.getZoneType() == ZoneType.ExtraHand) {
|
||||||
|
for (Card c : Lists.newArrayList(extraHand.getCards().iterator())) {
|
||||||
|
player.getGame().getAction().moveTo(library, c, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (Card c : Lists.newArrayList(hand.getCards().iterator())) {
|
||||||
|
player.getGame().getAction().moveTo(library, c, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(PlayerZone extraHand : player.getExtraZones()) {
|
||||||
|
boolean starting = startingHand.equals(extraHand);
|
||||||
|
for (Card c : Lists.newArrayList(extraHand.getCards().iterator())) {
|
||||||
|
if (starting) {
|
||||||
|
player.getGame().getAction().moveTo(hand, c, null);
|
||||||
|
} else {
|
||||||
|
player.getGame().getAction().moveTo(library, c, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
player.resetExtraZones(ZoneType.ExtraHand);
|
||||||
|
player.updateZoneForView(player.getZone(ZoneType.Hand));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -156,6 +156,8 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
private List<Card> completedDungeons = new ArrayList<>();
|
private List<Card> completedDungeons = new ArrayList<>();
|
||||||
|
|
||||||
private final Map<ZoneType, PlayerZone> zones = Maps.newEnumMap(ZoneType.class);
|
private final Map<ZoneType, PlayerZone> zones = Maps.newEnumMap(ZoneType.class);
|
||||||
|
private List<PlayerZone> extraZones = null;
|
||||||
|
|
||||||
private final Map<Long, Integer> adjustLandPlays = Maps.newHashMap();
|
private final Map<Long, Integer> adjustLandPlays = Maps.newHashMap();
|
||||||
private final Set<Long> adjustLandPlaysInfinite = Sets.newHashSet();
|
private final Set<Long> adjustLandPlaysInfinite = Sets.newHashSet();
|
||||||
private Map<Card, Card> maingameCardsMap = Maps.newHashMap();
|
private Map<Card, Card> maingameCardsMap = Maps.newHashMap();
|
||||||
@@ -1198,9 +1200,18 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final CardCollectionView drawCards(final int n) {
|
public final CardCollectionView drawCards(final int n) {
|
||||||
return drawCards(n, null, AbilityKey.newMap());
|
return drawCards(n, null, AbilityKey.newMap(), this.getZone(ZoneType.Hand));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final CardCollectionView drawCards(final int n, PlayerZone zone) {
|
||||||
|
return drawCards(n, null, AbilityKey.newMap(), zone);
|
||||||
|
}
|
||||||
|
|
||||||
public final CardCollectionView drawCards(final int n, SpellAbility cause, Map<AbilityKey, Object> params) {
|
public final CardCollectionView drawCards(final int n, SpellAbility cause, Map<AbilityKey, Object> params) {
|
||||||
|
return drawCards(n, cause, params, this.getZone(ZoneType.Hand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public final CardCollectionView drawCards(final int n, SpellAbility cause, Map<AbilityKey, Object> params, PlayerZone zone) {
|
||||||
final CardCollection drawn = new CardCollection();
|
final CardCollection drawn = new CardCollection();
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
return drawn;
|
return drawn;
|
||||||
@@ -1225,7 +1236,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
if (gameStarted && !canDraw()) {
|
if (gameStarted && !canDraw()) {
|
||||||
return drawn;
|
return drawn;
|
||||||
}
|
}
|
||||||
drawn.addAll(doDraw(toReveal, cause, params));
|
drawn.addAll(doDraw(toReveal, cause, params, zone));
|
||||||
}
|
}
|
||||||
|
|
||||||
// reveal multiple drawn cards when playing with the top of the library revealed
|
// reveal multiple drawn cards when playing with the top of the library revealed
|
||||||
@@ -1240,7 +1251,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
/**
|
/**
|
||||||
* @return a CardCollectionView of cards actually drawn
|
* @return a CardCollectionView of cards actually drawn
|
||||||
*/
|
*/
|
||||||
private CardCollectionView doDraw(Map<Player, CardCollection> revealed, SpellAbility sa, Map<AbilityKey, Object> params) {
|
private CardCollectionView doDraw(Map<Player, CardCollection> revealed, SpellAbility sa, Map<AbilityKey, Object> params, PlayerZone hand) {
|
||||||
final CardCollection drawn = new CardCollection();
|
final CardCollection drawn = new CardCollection();
|
||||||
final PlayerZone library = getZone(ZoneType.Library);
|
final PlayerZone library = getZone(ZoneType.Library);
|
||||||
|
|
||||||
@@ -1275,7 +1286,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c = game.getAction().moveToHand(c, cause, params);
|
c = game.getAction().moveTo(hand, c, cause, params);
|
||||||
drawn.add(c);
|
drawn.add(c);
|
||||||
|
|
||||||
// CR 121.6c additional actions can't be performed when draw gets replaced
|
// CR 121.6c additional actions can't be performed when draw gets replaced
|
||||||
@@ -1341,6 +1352,15 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final List<PlayerZone> getExtraZones() {
|
||||||
|
return extraZones;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetExtraZones(ZoneType type) {
|
||||||
|
extraZones.removeIf(z -> z.getZoneType().equals(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public final CardCollectionView getCardsIn(final ZoneType zoneType) {
|
public final CardCollectionView getCardsIn(final ZoneType zoneType) {
|
||||||
return getCardsIn(zoneType, true);
|
return getCardsIn(zoneType, true);
|
||||||
}
|
}
|
||||||
@@ -2964,6 +2984,15 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Objects.equals(conspire.getName(), "Backup Plan")) {
|
||||||
|
PlayerZone hand = new PlayerZone(ZoneType.ExtraHand, this);
|
||||||
|
if (this.extraZones == null) {
|
||||||
|
this.extraZones = new ArrayList<>();
|
||||||
|
}
|
||||||
|
this.extraZones.add(hand);
|
||||||
|
}
|
||||||
|
|
||||||
com.add(conspire);
|
com.add(conspire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,9 @@
|
|||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import forge.game.*;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
import forge.card.ICardFace;
|
import forge.card.ICardFace;
|
||||||
@@ -22,12 +11,9 @@ import forge.card.mana.ManaCost;
|
|||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
|
import forge.game.*;
|
||||||
import forge.game.GameOutcome.AnteResult;
|
import forge.game.GameOutcome.AnteResult;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardView;
|
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
import forge.game.cost.CostPart;
|
import forge.game.cost.CostPart;
|
||||||
@@ -35,18 +21,23 @@ import forge.game.cost.CostPartMana;
|
|||||||
import forge.game.keyword.KeywordInterface;
|
import forge.game.keyword.KeywordInterface;
|
||||||
import forge.game.mana.Mana;
|
import forge.game.mana.Mana;
|
||||||
import forge.game.mana.ManaConversionMatrix;
|
import forge.game.mana.ManaConversionMatrix;
|
||||||
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.*;
|
||||||
import forge.game.spellability.OptionalCostValue;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
|
||||||
import forge.game.spellability.TargetChoices;
|
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
|
import forge.game.zone.PlayerZone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A prototype for player controller class
|
* A prototype for player controller class
|
||||||
@@ -192,6 +183,7 @@ public abstract class PlayerController {
|
|||||||
public abstract CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave);
|
public abstract CardCollectionView chooseCardsToDelve(int genericAmount, CardCollection grave);
|
||||||
public abstract CardCollectionView chooseCardsToRevealFromHand(int min, int max, CardCollectionView valid);
|
public abstract CardCollectionView chooseCardsToRevealFromHand(int min, int max, CardCollectionView valid);
|
||||||
public abstract List<SpellAbility> chooseSaToActivateFromOpeningHand(List<SpellAbility> usableFromOpeningHand);
|
public abstract List<SpellAbility> chooseSaToActivateFromOpeningHand(List<SpellAbility> usableFromOpeningHand);
|
||||||
|
public abstract PlayerZone chooseStartingHand(List<PlayerZone> zones);
|
||||||
public abstract Mana chooseManaFromPool(List<Mana> manaChoices);
|
public abstract Mana chooseManaFromPool(List<Mana> manaChoices);
|
||||||
|
|
||||||
public abstract String chooseSomeType(String kindOfType, SpellAbility sa, Collection<String> validTypes, List<String> invalidTypes, boolean isOptional);
|
public abstract String chooseSomeType(String kindOfType, SpellAbility sa, Collection<String> validTypes, List<String> invalidTypes, boolean isOptional);
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package forge.game.zone;
|
package forge.game.zone;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import forge.util.Localizer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
|
|
||||||
import forge.util.Localizer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Enum Zone.
|
* The Enum Zone.
|
||||||
*/
|
*/
|
||||||
@@ -26,6 +25,8 @@ public enum ZoneType {
|
|||||||
SchemeDeck(true, "lblSchemeDeckZone"),
|
SchemeDeck(true, "lblSchemeDeckZone"),
|
||||||
PlanarDeck(true, "lblPlanarDeckZone"),
|
PlanarDeck(true, "lblPlanarDeckZone"),
|
||||||
Subgame(true, "lblSubgameZone"),
|
Subgame(true, "lblSubgameZone"),
|
||||||
|
// ExtraHand is used for Backup Plan for temporary extra hands
|
||||||
|
ExtraHand(true, "lblHandZone"),
|
||||||
None(true, "lblNoneZone");
|
None(true, "lblNoneZone");
|
||||||
|
|
||||||
public static final List<ZoneType> STATIC_ABILITIES_SOURCE_ZONES = Arrays.asList(Battlefield, Graveyard, Exile, Command, Stack/*, Hand*/);
|
public static final List<ZoneType> STATIC_ABILITIES_SOURCE_ZONES = Arrays.asList(Battlefield, Graveyard, Exile, Command, Stack/*, Hand*/);
|
||||||
|
|||||||
@@ -205,6 +205,7 @@ public enum CSubmenuDraft implements ICDoc {
|
|||||||
final RegisteredPlayer human = new RegisteredPlayer(humanDeck.getDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
final RegisteredPlayer human = new RegisteredPlayer(humanDeck.getDeck()).setPlayer(GamePlayerUtil.getGuiPlayer());
|
||||||
starter.add(human);
|
starter.add(human);
|
||||||
human.setId(0);
|
human.setId(0);
|
||||||
|
human.assignConspiracies();
|
||||||
for(Map.Entry<Integer, Deck> aiDeck : aiMap.entrySet()) {
|
for(Map.Entry<Integer, Deck> aiDeck : aiMap.entrySet()) {
|
||||||
RegisteredPlayer aiPlayer = new RegisteredPlayer(aiDeck.getValue()).setPlayer(GamePlayerUtil.createAiPlayer());
|
RegisteredPlayer aiPlayer = new RegisteredPlayer(aiDeck.getValue()).setPlayer(GamePlayerUtil.createAiPlayer());
|
||||||
aiPlayer.setId(aiDeck.getKey());
|
aiPlayer.setId(aiDeck.getKey());
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package forge.gamesimulationtests.util;
|
|||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.ai.ComputerUtil;
|
import forge.ai.ComputerUtil;
|
||||||
@@ -37,6 +38,7 @@ import forge.game.replacement.ReplacementEffect;
|
|||||||
import forge.game.spellability.*;
|
import forge.game.spellability.*;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
|
import forge.game.zone.PlayerZone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gamesimulationtests.util.card.CardSpecification;
|
import forge.gamesimulationtests.util.card.CardSpecification;
|
||||||
import forge.gamesimulationtests.util.card.CardSpecificationHandler;
|
import forge.gamesimulationtests.util.card.CardSpecificationHandler;
|
||||||
@@ -51,9 +53,11 @@ import forge.util.MyRandom;
|
|||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default harmless implementation for tests.
|
* Default harmless implementation for tests.
|
||||||
@@ -310,6 +314,11 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
return usableFromOpeningHand;
|
return usableFromOpeningHand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlayerZone chooseStartingHand(List<PlayerZone> zones) {
|
||||||
|
return zones.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mana chooseManaFromPool(List<Mana> manaChoices) {
|
public Mana chooseManaFromPool(List<Mana> manaChoices) {
|
||||||
return chooseItem(manaChoices);
|
return chooseItem(manaChoices);
|
||||||
|
|||||||
4
forge-gui/res/cardsfolder/b/backup_plan.txt
Normal file
4
forge-gui/res/cardsfolder/b/backup_plan.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
Name:Backup Plan
|
||||||
|
Types:Conspiracy
|
||||||
|
Text:Draw an additional hand of seven cards as the game begins. Before taking mulligans, shuffle all but one of your hands into your library.
|
||||||
|
Oracle: (Start the game with this conspiracy face up in the command zone.)\nDraw an additional hand of seven cards as the game begins. Before taking mulligans, shuffle all but one of your hands into your library.
|
||||||
@@ -224,7 +224,7 @@ ScryfallCode=CNS
|
|||||||
1 Advantageous Proclamation|CNS
|
1 Advantageous Proclamation|CNS
|
||||||
1 Aether Searcher|CNS
|
1 Aether Searcher|CNS
|
||||||
1 Agent of Acquisitions|CNS
|
1 Agent of Acquisitions|CNS
|
||||||
#1 Backup Plan|CNS
|
1 Backup Plan|CNS
|
||||||
1 Brago's Favor|CNS
|
1 Brago's Favor|CNS
|
||||||
1 Canal Dredger|CNS
|
1 Canal Dredger|CNS
|
||||||
1 Cogwork Grinder|CNS
|
1 Cogwork Grinder|CNS
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
package forge.gamemodes.match.input;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.PlayerZone;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.player.PlayerControllerHuman;
|
||||||
|
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class InputChooseStartingHand extends InputSyncronizedBase {
|
||||||
|
// An input for choosing multiple different starting hands for Backup Plan
|
||||||
|
// Ideally all would render at once, but for now we're just going to show the primary, and loop through each hand
|
||||||
|
// When you like one, click OK and the rest will be cleared
|
||||||
|
private final Deque<PlayerZone> hands;
|
||||||
|
PlayerZone primaryHand = null;
|
||||||
|
Game game;
|
||||||
|
|
||||||
|
|
||||||
|
public InputChooseStartingHand(final PlayerControllerHuman controller, final Player humanPlayer) {
|
||||||
|
super(controller);
|
||||||
|
|
||||||
|
game = humanPlayer.getGame();
|
||||||
|
primaryHand = humanPlayer.getZone(ZoneType.Hand);
|
||||||
|
hands = Lists.newLinkedList();
|
||||||
|
for(PlayerZone extraHand : humanPlayer.getExtraZones()) {
|
||||||
|
if (extraHand.getZoneType() == ZoneType.ExtraHand) {
|
||||||
|
hands.add(extraHand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerZone getSelectedHand() {
|
||||||
|
// We're going to be manipulating what the primary hand is during this process so always return it
|
||||||
|
return primaryHand;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void showMessage() {
|
||||||
|
if (hands.isEmpty()) {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
getController().getGui().updateButtons(getOwner(), "View Next", "Accept Hand", true, true, true);
|
||||||
|
showMessage("Select the currently viewed hand to start the game with. The other " + hands.size() + " hand(s) will be shuffled into your library.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void onCancel() {
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final void onOk() {
|
||||||
|
// Rotate hands. Take everything in current hand, add it to the next hand
|
||||||
|
// Then take everything in the next hand and add it to the current hand
|
||||||
|
PlayerZone nextExtraHand = hands.poll();
|
||||||
|
assert nextExtraHand != null;
|
||||||
|
List<Card> currentList = Lists.newArrayList(primaryHand.getCards().iterator());
|
||||||
|
List<Card> extraList = Lists.newArrayList(nextExtraHand.getCards().iterator());
|
||||||
|
|
||||||
|
primaryHand.setCards(extraList);
|
||||||
|
nextExtraHand.setCards(currentList);
|
||||||
|
hands.add(nextExtraHand);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getActivateAction(Card card) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,87 +1,24 @@
|
|||||||
package forge.player;
|
package forge.player;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileWriter;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
|
|
||||||
import forge.game.player.actions.SelectCardAction;
|
|
||||||
import forge.game.player.actions.SelectPlayerAction;
|
|
||||||
import forge.game.trigger.TriggerType;
|
|
||||||
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.gamemodes.match.input.*;
|
|
||||||
import forge.trackable.TrackableCollection;
|
|
||||||
import forge.util.ImageUtil;
|
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
|
||||||
import org.apache.commons.lang3.Range;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Collections2;
|
import com.google.common.collect.*;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.ListMultimap;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Multimap;
|
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
import forge.ai.GameState;
|
import forge.ai.GameState;
|
||||||
import forge.ai.PlayerControllerAi;
|
import forge.ai.PlayerControllerAi;
|
||||||
import forge.card.CardDb;
|
import forge.card.*;
|
||||||
import forge.card.CardSplitType;
|
|
||||||
import forge.card.CardStateName;
|
|
||||||
import forge.card.ColorSet;
|
|
||||||
import forge.card.ICardFace;
|
|
||||||
import forge.card.MagicColor;
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.card.mana.ManaCostShard;
|
import forge.card.mana.ManaCostShard;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckRecognizer;
|
import forge.deck.DeckRecognizer;
|
||||||
import forge.deck.DeckSection;
|
import forge.deck.DeckSection;
|
||||||
import forge.game.Game;
|
import forge.game.*;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameEntityView;
|
|
||||||
import forge.game.GameEntityViewMap;
|
|
||||||
import forge.game.GameLogEntryType;
|
|
||||||
import forge.game.GameObject;
|
|
||||||
import forge.game.GameType;
|
|
||||||
import forge.game.PlanarDice;
|
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.ApiType;
|
import forge.game.ability.ApiType;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.*;
|
||||||
import forge.game.card.CardCollection;
|
|
||||||
import forge.game.card.CardCollectionView;
|
|
||||||
import forge.game.card.CardFaceView;
|
|
||||||
import forge.game.card.CardLists;
|
|
||||||
import forge.game.card.CardPlayOption;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.card.CardView;
|
|
||||||
import forge.game.card.CounterEnumType;
|
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.card.token.TokenInfo;
|
import forge.game.card.token.TokenInfo;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
@@ -93,28 +30,23 @@ import forge.game.keyword.Keyword;
|
|||||||
import forge.game.keyword.KeywordInterface;
|
import forge.game.keyword.KeywordInterface;
|
||||||
import forge.game.mana.Mana;
|
import forge.game.mana.Mana;
|
||||||
import forge.game.mana.ManaConversionMatrix;
|
import forge.game.mana.ManaConversionMatrix;
|
||||||
import forge.game.player.DelayedReveal;
|
import forge.game.mana.ManaCostBeingPaid;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.*;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.actions.SelectCardAction;
|
||||||
import forge.game.player.PlayerController;
|
import forge.game.player.actions.SelectPlayerAction;
|
||||||
import forge.game.player.PlayerView;
|
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.replacement.ReplacementLayer;
|
import forge.game.replacement.ReplacementLayer;
|
||||||
import forge.game.spellability.AbilityManaPart;
|
import forge.game.spellability.*;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.OptionalCostValue;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
|
||||||
import forge.game.spellability.SpellAbilityView;
|
|
||||||
import forge.game.spellability.TargetChoices;
|
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
import forge.game.zone.MagicStack;
|
import forge.game.zone.MagicStack;
|
||||||
import forge.game.zone.PlayerZone;
|
import forge.game.zone.PlayerZone;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gamemodes.match.NextGameDecision;
|
import forge.gamemodes.match.NextGameDecision;
|
||||||
|
import forge.gamemodes.match.input.*;
|
||||||
import forge.gui.FThreads;
|
import forge.gui.FThreads;
|
||||||
import forge.gui.GuiBase;
|
import forge.gui.GuiBase;
|
||||||
import forge.gui.control.FControlGamePlayback;
|
import forge.gui.control.FControlGamePlayback;
|
||||||
@@ -130,16 +62,21 @@ import forge.localinstance.achievements.AchievementCollection;
|
|||||||
import forge.localinstance.properties.ForgeConstants;
|
import forge.localinstance.properties.ForgeConstants;
|
||||||
import forge.localinstance.properties.ForgePreferences.FPref;
|
import forge.localinstance.properties.ForgePreferences.FPref;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.util.CardTranslation;
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.util.DeckAIUtils;
|
import forge.util.*;
|
||||||
import forge.util.ITriggerEvent;
|
|
||||||
import forge.util.Lang;
|
|
||||||
import forge.util.Localizer;
|
|
||||||
import forge.util.MessageUtil;
|
|
||||||
import forge.util.TextUtil;
|
|
||||||
import forge.util.collect.FCollection;
|
import forge.util.collect.FCollection;
|
||||||
import forge.util.collect.FCollectionView;
|
import forge.util.collect.FCollectionView;
|
||||||
import io.sentry.Sentry;
|
import io.sentry.Sentry;
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
import org.apache.commons.lang3.Range;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A prototype for player controller class
|
* A prototype for player controller class
|
||||||
@@ -1653,6 +1590,18 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlayerZone chooseStartingHand(List<PlayerZone> zones) {
|
||||||
|
// Create new zone objects in the UI temporarily.
|
||||||
|
// Spawn a new input dialog, it works by selecting a card in the zone you want and clicking OK
|
||||||
|
// The card will then extract the PlayerZone via the card that is chosen and return it to this function
|
||||||
|
// Which will then return the PlayerZone to the caller
|
||||||
|
player.updateZoneForView(player.getZone(ZoneType.Hand));
|
||||||
|
final InputChooseStartingHand inp = new InputChooseStartingHand(this, player);
|
||||||
|
inp.showAndWait();
|
||||||
|
return inp.getSelectedHand();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean chooseBinary(final SpellAbility sa, final String question, final BinaryChoiceType kindOfChoice,
|
public boolean chooseBinary(final SpellAbility sa, final String question, final BinaryChoiceType kindOfChoice,
|
||||||
final Boolean defaultVal) {
|
final Boolean defaultVal) {
|
||||||
|
|||||||
Reference in New Issue
Block a user