diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGenPool.java b/forge-core/src/main/java/forge/deck/generation/DeckGenPool.java index 5de342fb626..b64062f0345 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGenPool.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGenPool.java @@ -4,8 +4,10 @@ import java.util.HashMap; import java.util.Map; import com.google.common.base.Predicate; +import com.google.common.base.Predicates; import com.google.common.collect.Iterables; +import forge.item.IPaperCard; import forge.item.PaperCard; public class DeckGenPool implements IDeckGenPool { @@ -37,12 +39,18 @@ public class DeckGenPool implements IDeckGenPool { @Override public PaperCard getCard(String name, String edition) { - return cards.get(name); + Predicate filter = Predicates.and(IPaperCard.Predicates.printedInSet(edition),IPaperCard.Predicates.name(name)); + Iterable editionCards=Iterables.filter(cards.values(), filter); + if (editionCards.iterator().hasNext()){ + return editionCards.iterator().next(); + }else { + return getCard(name); + } } @Override public PaperCard getCard(String name, String edition, int artIndex) { - return cards.get(name); + return getCard(name, edition); } public boolean contains(PaperCard card) { diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGenerator2Color.java b/forge-core/src/main/java/forge/deck/generation/DeckGenerator2Color.java index c26d6e3399d..903fa7bfc53 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGenerator2Color.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGenerator2Color.java @@ -17,6 +17,7 @@ */ package forge.deck.generation; +import com.google.common.base.Predicate; import com.google.common.collect.Lists; import forge.card.ColorSet; @@ -24,6 +25,7 @@ import forge.card.MagicColor; import forge.deck.CardPool; import forge.deck.DeckFormat; +import forge.item.PaperCard; import org.apache.commons.lang3.tuple.ImmutablePair; import java.util.Arrays; @@ -66,8 +68,17 @@ public class DeckGenerator2Color extends DeckGeneratorBase { // 4x 7 - 20 // = 52x - card pool (before further random filtering) + public DeckGenerator2Color(IDeckGenPool pool0, DeckFormat format0, Predicate formatFilter0, final String clr1, final String clr2) { + super(pool0, format0,formatFilter0); + initialize(format0,clr1,clr2); + } + public DeckGenerator2Color(IDeckGenPool pool0, DeckFormat format0, final String clr1, final String clr2) { super(pool0, format0); + initialize(format0,clr1,clr2); + } + + private void initialize(DeckFormat format0, final String clr1, final String clr2){ int c1 = MagicColor.fromName(clr1); int c2 = MagicColor.fromName(clr2); diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGenerator3Color.java b/forge-core/src/main/java/forge/deck/generation/DeckGenerator3Color.java index 41bad03bf43..f3d6185cc01 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGenerator3Color.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGenerator3Color.java @@ -17,12 +17,14 @@ */ package forge.deck.generation; +import com.google.common.base.Predicate; import com.google.common.collect.Lists; import forge.card.ColorSet; import forge.card.MagicColor; import forge.deck.CardPool; import forge.deck.DeckFormat; +import forge.item.PaperCard; import forge.util.MyRandom; import org.apache.commons.lang3.tuple.ImmutablePair; @@ -58,15 +60,23 @@ public class DeckGenerator3Color extends DeckGeneratorBase { ImmutablePair.of(new FilterCMC(6, 20), 3) ); + public DeckGenerator3Color(IDeckGenPool pool0, DeckFormat format0, Predicate formatFilter0, final String clr1, final String clr2, final String clr3) { + super(pool0, format0, formatFilter0); + initialize(format0,clr1,clr2,clr3); + } + public DeckGenerator3Color(IDeckGenPool pool0, DeckFormat format0, final String clr1, final String clr2, final String clr3) { super(pool0, format0); + initialize(format0,clr1,clr2,clr3); + } + private void initialize(DeckFormat format0, final String clr1, final String clr2, final String clr3){ format0.adjustCMCLevels(cmcLevels); int c1 = MagicColor.fromName(clr1); int c2 = MagicColor.fromName(clr2); int c3 = MagicColor.fromName(clr3); - + int rc = 0; int combo = c1 | c2 | c3; @@ -84,14 +94,14 @@ public class DeckGenerator3Color extends DeckGeneratorBase { case 1: do { - rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5); + rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5); } while ( rc == combo ); combo |= rc; - //$FALL-THROUGH$ + //$FALL-THROUGH$ case 2: do { - rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5); + rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5); } while ( (rc & combo) != 0 ); combo |= rc; break; @@ -119,7 +129,6 @@ public class DeckGenerator3Color extends DeckGeneratorBase { addBasicLand(numLands); trace.append("DeckSize:").append(tDeck.countAll()).append("\n"); - return tDeck; } } diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGenerator5Color.java b/forge-core/src/main/java/forge/deck/generation/DeckGenerator5Color.java index f4ac719ff59..8f713cf6274 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGenerator5Color.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGenerator5Color.java @@ -17,12 +17,14 @@ */ package forge.deck.generation; +import com.google.common.base.Predicate; import com.google.common.collect.Lists; import forge.card.ColorSet; import forge.deck.CardPool; import forge.deck.DeckFormat; +import forge.item.PaperCard; import org.apache.commons.lang3.tuple.ImmutablePair; import java.util.List; @@ -65,12 +67,21 @@ public class DeckGenerator5Color extends DeckGeneratorBase { /** * Instantiates a new generate5 color deck. */ + public DeckGenerator5Color(IDeckGenPool pool0, DeckFormat format0, Predicate formatFilter0) { + super(pool0, format0, formatFilter0); + + } + public DeckGenerator5Color(IDeckGenPool pool0, DeckFormat format0) { super(pool0, format0); format0.adjustCMCLevels(cmcLevels); colors = ColorSet.fromMask(0).inverse(); } + private void initialize(DeckFormat format0) { + format0.adjustCMCLevels(cmcLevels); + colors = ColorSet.fromMask(0).inverse(); + } @Override public final CardPool getDeck(final int size, final boolean forAi) { @@ -91,7 +102,6 @@ public class DeckGenerator5Color extends DeckGeneratorBase { numLands -= dblsAdded; addBasicLand(numLands); - trace.append("DeckSize:").append(tDeck.countAll()).append("\n"); return tDeck; } } diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java index 0c78e2462b3..94f962cc498 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorBase.java @@ -26,6 +26,7 @@ import forge.card.*; import forge.card.mana.ManaCost; import forge.deck.CardPool; import forge.deck.DeckFormat; +import forge.item.IPaperCard; import forge.item.PaperCard; import forge.util.Aggregates; import forge.util.DebugTrace; @@ -34,8 +35,11 @@ import forge.util.MyRandom; import org.apache.commons.lang3.tuple.ImmutablePair; +import java.awt.print.Paper; import java.util.*; import java.util.Map.Entry; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** *

@@ -51,19 +55,31 @@ public abstract class DeckGeneratorBase { protected final Map cardCounts = new HashMap(); protected int maxDuplicates = 4; protected boolean useArtifacts = true; + protected String basicLandEdition = null; protected ColorSet colors; protected final CardPool tDeck = new CardPool(); protected final IDeckGenPool pool; + protected IDeckGenPool landPool; protected final DeckFormat format; + protected final IDeckGenPool fullCardDB; protected abstract float getLandPercentage(); protected abstract float getCreaturePercentage(); protected abstract float getSpellPercentage(); - public DeckGeneratorBase(IDeckGenPool pool0, DeckFormat format0) { - pool = format0.getCardPool(pool0); + public DeckGeneratorBase(IDeckGenPool pool0, DeckFormat format0, Predicate formatFilter0) { + pool = new DeckGenPool(format0.getCardPool(pool0).getAllCards(formatFilter0)); format = format0; + fullCardDB = pool0; + //setBasicLandPool(null); + } + + public DeckGeneratorBase(IDeckGenPool pool0, DeckFormat format0) { + pool = new DeckGenPool(format0.getCardPool(pool0).getAllCards()); + format = format0; + fullCardDB = pool0; + //setBasicLandPool(null); } public void setSingleton(boolean singleton){ @@ -79,6 +95,7 @@ public abstract class DeckGeneratorBase { final Iterable cards = selectCardsOfMatchingColorForPlayer(forAi); // build subsets based on type + final Iterable creatures = Iterables.filter(cards, Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES)); final int creatCnt = (int) Math.ceil(getCreaturePercentage() * size); trace.append("Creatures to add:").append(creatCnt).append("\n"); @@ -97,6 +114,19 @@ public abstract class DeckGeneratorBase { return null; // all but theme deck do override this method } + protected boolean setBasicLandPool(String edition){ + Predicate isSetBasicLand; + if (edition !=null){ + isSetBasicLand = Predicates.and(IPaperCard.Predicates.printedInSet(edition), + Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES)); + }else{ + isSetBasicLand = Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES); + } + + landPool = new DeckGenPool(format.getCardPool(fullCardDB).getAllCards(isSetBasicLand)); + return landPool.contains("Plains"); + } + protected int addSome(int cnt, List source) { int srcLen = source.size(); if (srcLen == 0) { return 0; } @@ -109,6 +139,11 @@ public abstract class DeckGeneratorBase { //add card to deck if not already maxed out on card if (newCount <= maxDuplicates) { tDeck.add(pool.getCard(cp.getName(), cp.getEdition())); + if(basicLandEdition == null){ + if(setBasicLandPool(cp.getEdition())){ + basicLandEdition = cp.getEdition(); + }; + } cardCounts.put(cp.getName(), newCount); trace.append(String.format("(%d) %s [%s]%n", cp.getRules().getManaCost().getCMC(), cp.getName(), cp.getRules().getManaCost())); res++; @@ -181,17 +216,19 @@ public abstract class DeckGeneratorBase { cardCounts.put(basicLandName, nLand); PaperCard cp; + if (!landPool.contains("Plains")) {//in case none of the cards came from a set with all basic lands + setBasicLandPool("BFZ"); + basicLandEdition="BFZ"; + } if (edition != null) { - cp = pool.getCard(basicLandName, edition); + cp = landPool.getCard(basicLandName, edition); } else { - cp = pool.getCard(basicLandName); + cp = landPool.getCard(basicLandName, basicLandEdition); } - String basicLandSet = cp.getEdition(); - for (int i = 0; i < nLand; i++) { - tDeck.add(pool.getCard(cp.getName(), basicLandSet, -1), 1); + tDeck.add(landPool.getCard(cp.getName(), basicLandEdition, -1), 1); } landsLeft -= nLand; @@ -254,11 +291,10 @@ public abstract class DeckGeneratorBase { // remove cards that generated decks don't like Predicate canPlay = forAi ? AI_CAN_PLAY : HUMAN_CAN_PLAY; Predicate hasColor = new MatchColorIdentity(colors); - if (useArtifacts) { hasColor = Predicates.or(hasColor, COLORLESS_CARDS); } - return Iterables.filter(pool.getAllCards(), Predicates.compose(Predicates.and(canPlay, hasColor), PaperCard.FN_GET_RULES)); + return Iterables.filter(pool.getAllCards(),Predicates.compose(Predicates.and(canPlay, hasColor), PaperCard.FN_GET_RULES)); } protected static Map countLands(ItemPool outList) { @@ -351,24 +387,22 @@ public abstract class DeckGeneratorBase { private static Map dualLands = new HashMap(); static { - dualLands.put(MagicColor.WHITE | MagicColor.BLUE, new String[] { "Tundra", "Hallowed Fountain", "Flooded Strand" }); - dualLands.put(MagicColor.BLACK | MagicColor.BLUE, new String[] { "Underground Sea", "Watery Grave", "Polluted Delta" }); - dualLands.put(MagicColor.BLACK | MagicColor.RED, new String[] { "Badlands", "Blood Crypt", "Bloodstained Mire" }); - dualLands.put(MagicColor.GREEN | MagicColor.RED, new String[] { "Taiga", "Stomping Ground", "Wooded Foothills" }); - dualLands.put(MagicColor.GREEN | MagicColor.WHITE, new String[] { "Savannah", "Temple Garden", "Windswept Heath" }); + dualLands.put(MagicColor.WHITE | MagicColor.BLUE, new String[] { "Tundra", "Hallowed Fountain", "Flooded Strand", "Prairie Stream" }); + dualLands.put(MagicColor.BLACK | MagicColor.BLUE, new String[] { "Underground Sea", "Watery Grave", "Polluted Delta", "Sunken Hollow" }); + dualLands.put(MagicColor.BLACK | MagicColor.RED, new String[] { "Badlands", "Blood Crypt", "Bloodstained Mire", "Smoldering Marsh" }); + dualLands.put(MagicColor.GREEN | MagicColor.RED, new String[] { "Taiga", "Stomping Ground", "Wooded Foothills", "Cinder Glade" }); + dualLands.put(MagicColor.GREEN | MagicColor.WHITE, new String[] { "Savannah", "Temple Garden", "Windswept Heath", "Canopy Vista" }); - dualLands.put(MagicColor.WHITE | MagicColor.BLACK, new String[] { "Scrubland", "Godless Shrine", "Marsh Flats" }); - dualLands.put(MagicColor.BLUE | MagicColor.RED, new String[] { "Volcanic Island", "Steam Vents", "Scalding Tarn" }); - dualLands.put(MagicColor.BLACK | MagicColor.GREEN, new String[] { "Bayou", "Overgrown Tomb", "Verdant Catacombs" }); - dualLands.put(MagicColor.WHITE | MagicColor.RED, new String[] { "Plateau", "Sacred Foundry", "Arid Mesa" }); - dualLands.put(MagicColor.GREEN | MagicColor.BLUE, new String[] { "Tropical Island", "Breeding Pool", "Misty Rainforest" }); + dualLands.put(MagicColor.WHITE | MagicColor.BLACK, new String[] { "Scrubland", "Godless Shrine", "Marsh Flats", "Concealed Courtyard" }); + dualLands.put(MagicColor.BLUE | MagicColor.RED, new String[] { "Volcanic Island", "Steam Vents", "Scalding Tarn", "Spirebluff Canal" }); + dualLands.put(MagicColor.BLACK | MagicColor.GREEN, new String[] { "Bayou", "Overgrown Tomb", "Verdant Catacombs", "Blooming Marsh" }); + dualLands.put(MagicColor.WHITE | MagicColor.RED, new String[] { "Plateau", "Sacred Foundry", "Arid Mesa", "Inspiring Vantage" }); + dualLands.put(MagicColor.GREEN | MagicColor.BLUE, new String[] { "Tropical Island", "Breeding Pool", "Misty Rainforest", "Botanical Sanctum" }); } /** * Get list of dual lands for this color combo. - * - * @param color - * the color + * * @return dual land names */ protected List getDualLandList() { @@ -383,22 +417,70 @@ public abstract class DeckGeneratorBase { addCardNameToList("Evolving Wilds", dLands); addCardNameToList("Terramorphic Expanse", dLands); } - for (Entry dual : dualLands.entrySet()) { - if (colors.hasAllColors(dual.getKey())) { - for (String s : dual.getValue()) { - addCardNameToList(s, dLands); + + //filter to provide all dual lands from pool matching 2 or 3 colors from current deck + Predicate dualLandFilter = Predicates.compose(CardRulesPredicates.coreType(true, CardType.CoreType.Land), PaperCard.FN_GET_RULES); + Predicate exceptBasicLand = Predicates.not(Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES)); + Iterable landCards = pool.getAllCards(Predicates.and(dualLandFilter,exceptBasicLand)); + Iterable dualLandPatterns = Arrays.asList("Add \\{([WUBRG])\\} or \\{([WUBRG])\\} to your mana pool", + "Add \\{([WUBRG])\\}, \\{([WUBRG])\\}, or \\{([WUBRG])\\} to your mana pool", + "Add \\{([WUBRG])\\}\\{([WUBRG])\\} to your mana pool", + "Add \\{[WUBRG]\\}\\{[WUBRG]\\}, \\{([WUBRG])\\}\\{([WUBRG])\\}, or \\{[WUBRG]\\}\\{[WUBRG]\\} to your mana pool"); + for (String pattern:dualLandPatterns){ + dLands.addAll(regexLandSearch(pattern, landCards)); + } + dLands.addAll(regexFetchLandSearch(landCards)); + return dLands; + } + + public List regexLandSearch(String pattern, Iterable landCards){ + final List dLands = new ArrayList(); + Pattern p = Pattern.compile(pattern); + for (PaperCard card:landCards){ + Matcher matcher = p.matcher(card.getRules().getOracleText()); + while (matcher.find()) { + List manaColorNames = new ArrayList<>(); + for (int i = 1; i <= matcher.groupCount(); i++) { + manaColorNames.add(matcher.group(i)); + } + ColorSet manaColorSet = ColorSet.fromNames(manaColorNames); + if (colors.hasAllColors(manaColorSet.getColor())){ + addCardNameToList(card.getName(),dLands); } } } + return dLands; + } + public List regexFetchLandSearch(Iterable landCards){ + final String fetchPattern="Search your library for a ([^\\s]*) or ([^\\s]*) card"; + final List dLands = new ArrayList(); + Map colorLookup= new HashMap<>(); + colorLookup.put("Plains","W"); + colorLookup.put("Forest","G"); + colorLookup.put("Mountain","R"); + colorLookup.put("Island","U"); + colorLookup.put("Swamp","B"); + Pattern p = Pattern.compile(fetchPattern); + for (PaperCard card:landCards){ + Matcher matcher = p.matcher(card.getRules().getOracleText()); + while (matcher.find()) { + List manaColorNames = new ArrayList<>(); + for (int i = 1; i <= matcher.groupCount(); i++) { + manaColorNames.add(colorLookup.get(matcher.group(i))); + } + ColorSet manaColorSet = ColorSet.fromNames(manaColorNames); + if (colors.hasAllColors(manaColorSet.getColor())){ + addCardNameToList(card.getName(),dLands); + } + } + } return dLands; } /** * Get all dual lands that do not match this color combo. - * - * @param color - * the color + * * @return dual land names */ protected List getInverseDualLandList() { diff --git a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorMonoColor.java b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorMonoColor.java index ae4becfba97..5a5549d2fe1 100644 --- a/forge-core/src/main/java/forge/deck/generation/DeckGeneratorMonoColor.java +++ b/forge-core/src/main/java/forge/deck/generation/DeckGeneratorMonoColor.java @@ -17,6 +17,7 @@ */ package forge.deck.generation; +import com.google.common.base.Predicate; import com.google.common.collect.Lists; import forge.card.ColorSet; @@ -24,6 +25,7 @@ import forge.card.MagicColor; import forge.deck.CardPool; import forge.deck.DeckFormat; +import forge.item.PaperCard; import org.apache.commons.lang3.tuple.ImmutablePair; import java.util.List; @@ -65,8 +67,17 @@ public class DeckGeneratorMonoColor extends DeckGeneratorBase { // 4x 7 - 20 // = 52x - card pool (before further random filtering) + public DeckGeneratorMonoColor(IDeckGenPool pool0, DeckFormat format0, Predicate formatFilter0, final String clr1) { + super(pool0, format0, formatFilter0); + initialize(clr1); + } + public DeckGeneratorMonoColor(IDeckGenPool pool0, DeckFormat format0, final String clr1) { super(pool0, format0); + initialize(clr1); + } + + public void initialize(final String clr1){ if (MagicColor.fromName(clr1) == 0) { int color1 = r.nextInt(5); colors = ColorSet.fromMask(MagicColor.WHITE << color1); @@ -90,7 +101,6 @@ public class DeckGeneratorMonoColor extends DeckGeneratorBase { adjustDeckSize(size); trace.append("DeckSize:").append(tDeck.countAll()).append("\n"); - return tDeck; } } diff --git a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java index 4632151cd10..7aabf9f17c1 100644 --- a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java +++ b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java @@ -8,6 +8,8 @@ import java.util.List; import javax.swing.JOptionPane; import javax.swing.JPanel; +import com.google.common.base.Predicate; +import forge.item.PaperCard; import net.miginfocom.swing.MigLayout; import org.apache.commons.lang3.StringUtils; @@ -135,10 +137,10 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener { updateDecks(DeckProxy.getAllConstructedDecks(), ItemManagerConfig.CONSTRUCTED_DECKS); } - private void updateColors() { + private void updateColors(Predicate formatFilter) { lstDecks.setAllowMultipleSelections(true); - lstDecks.setPool(ColorDeckGenerator.getColorDecks(lstDecks, isAi)); + lstDecks.setPool(ColorDeckGenerator.getColorDecks(lstDecks, formatFilter, isAi)); lstDecks.setup(ItemManagerConfig.STRING_ONLY); btnRandom.setText("Random Colors"); @@ -277,7 +279,13 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener { updateCustom(); break; case COLOR_DECK: - updateColors(); + updateColors(null); + break; + case STANDARD_COLOR_DECK: + updateColors(FModel.getFormats().getStandard().getFilterPrinted()); + break; + case MODERN_COLOR_DECK: + updateColors(FModel.getFormats().getModern().getFilterPrinted()); break; case THEME_DECK: updateThemes(); diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletQuick.java b/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletQuick.java index 657e7c55bf9..e2693ce6fd0 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletQuick.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletQuick.java @@ -70,6 +70,8 @@ public enum CSubmenuGauntletQuick implements ICDoc { // Find appropriate filename for new save, create and set new save file. final List allowedDeckTypes = new ArrayList(); if (view.getBoxColorDecks().isSelected()) { allowedDeckTypes.add(DeckType.COLOR_DECK); } + if (view.getBoxStandardColorDecks().isSelected()) { allowedDeckTypes.add(DeckType.STANDARD_COLOR_DECK); } + if (view.getBoxModernColorDecks().isSelected()) { allowedDeckTypes.add(DeckType.MODERN_COLOR_DECK); } if (view.getBoxThemeDecks().isSelected()) { allowedDeckTypes.add(DeckType.THEME_DECK); } if (view.getBoxUserDecks().isSelected()) { allowedDeckTypes.add(DeckType.CUSTOM_DECK); } if (view.getBoxQuestDecks().isSelected()) { allowedDeckTypes.add(DeckType.QUEST_OPPONENT_DECK); } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java b/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java index 2b08d2cac93..f12e223845a 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java @@ -51,6 +51,8 @@ public enum VSubmenuGauntletQuick implements IVSubmenu { private final JCheckBox boxPreconDecks = new FCheckBox(DeckType.PRECONSTRUCTED_DECK.toString()); private final JCheckBox boxQuestDecks = new FCheckBox(DeckType.QUEST_OPPONENT_DECK.toString()); private final JCheckBox boxColorDecks = new FCheckBox(DeckType.COLOR_DECK.toString()); + private final JCheckBox boxStandardColorDecks = new FCheckBox(DeckType.STANDARD_COLOR_DECK.toString()); + private final JCheckBox boxModernColorDecks = new FCheckBox(DeckType.MODERN_COLOR_DECK.toString()); private final JCheckBox boxThemeDecks = new FCheckBox(DeckType.THEME_DECK.toString()); private final FDeckChooser lstDecks = new FDeckChooser(null, false); @@ -78,6 +80,8 @@ public enum VSubmenuGauntletQuick implements IVSubmenu { boxQuestDecks.setSelected(true); boxThemeDecks.setSelected(true); boxColorDecks.setSelected(true); + boxStandardColorDecks.setSelected(true); + boxModernColorDecks.setSelected(true); sliOpponents.setMajorTickSpacing(5); sliOpponents.setMinorTickSpacing(0); @@ -98,7 +102,9 @@ public enum VSubmenuGauntletQuick implements IVSubmenu { pnlOptions.add(boxPreconDecks, "w 96%!, h 30px!, gap 2% 0 0 5px"); pnlOptions.add(boxQuestDecks, "w 96%!, h 30px!, gap 2% 0 0 5px"); pnlOptions.add(boxThemeDecks, "w 96%!, h 30px!, gap 2% 0 0 5px"); - pnlOptions.add(boxColorDecks, "w 96%!, h 30px!, gap 2% 0 0 0"); + pnlOptions.add(boxColorDecks, "w 96%!, h 30px!, gap 2% 0 0 5px"); + pnlOptions.add(boxStandardColorDecks, "w 96%!, h 30px!, gap 2% 0 0 5px"); + pnlOptions.add(boxModernColorDecks, "w 96%!, h 30px!, gap 2% 0 0 0"); } /* (non-Javadoc) @@ -171,6 +177,16 @@ public enum VSubmenuGauntletQuick implements IVSubmenu { return boxColorDecks; } + /** @return {@link javax.swing.JCheckBox} */ + public JCheckBox getBoxStandardColorDecks() { + return boxStandardColorDecks; + } + + /** @return {@link javax.swing.JCheckBox} */ + public JCheckBox getBoxModernColorDecks() { + return boxModernColorDecks; + } + /** @return {@link javax.swing.JCheckBox} */ public JCheckBox getBoxThemeDecks() { return boxThemeDecks; diff --git a/forge-gui-desktop/src/test/java/forge/item/DeckHintsTest.java b/forge-gui-desktop/src/test/java/forge/item/DeckHintsTest.java index 1797939170b..1bc1fd27731 100644 --- a/forge-gui-desktop/src/test/java/forge/item/DeckHintsTest.java +++ b/forge-gui-desktop/src/test/java/forge/item/DeckHintsTest.java @@ -1,11 +1,12 @@ package forge.item; import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import com.google.common.collect.Iterables; +import forge.card.ColorSet; import junit.framework.Assert; import org.testng.annotations.BeforeTest; @@ -155,6 +156,57 @@ public class DeckHintsTest { Assert.assertEquals(1, hints.filter(list).size()); } + /** + * Test for finding dual lands for deck generation. + */ + @Test(timeOut = 1000, enabled = true) + void testFindDualLands() { + List cardNames= Arrays.asList("tundra.txt", "hallowed_fountain.txt", "flooded_strand.txt", "prairie_stream.txt", "sunken_hollow.txt", "smoldering_marsh.txt"); + List cards = new ArrayList<>(); + for (String name:cardNames){ + cards.add(readCard(name)); + } + final String pattern="Add \\{([WUBRG])\\} or \\{([WUBRG])\\} to your mana pool"; + Pattern p = Pattern.compile(pattern); + for (PaperCard card:cards){ + System.out.println(card.getRules().getOracleText()); + Matcher matcher = p.matcher(card.getRules().getOracleText()); + while (matcher.find()) { + System.out.println("Full match: " + matcher.group(0)); + for (int i = 1; i <= matcher.groupCount(); i++) { + System.out.println("Group " + i + ": " + matcher.group(i)); + } + } + } + + final String fetchPattern="Search your library for a ([^\\s]*) or ([^\\s]*) card"; + final List dLands = new ArrayList(); + Map colorLookup= new HashMap<>(); + colorLookup.put("Plains","W"); + colorLookup.put("Forest","G"); + colorLookup.put("Mountain","R"); + colorLookup.put("Island","U"); + colorLookup.put("Swamp","B"); + Pattern p2 = Pattern.compile(fetchPattern); + for (PaperCard card:cards){ + System.out.println(card.getName()); + Matcher matcher = p2.matcher(card.getRules().getOracleText()); + while (matcher.find()) { + List manaColorNames = new ArrayList<>(); + System.out.println(card.getName()); + for (int i = 1; i <= matcher.groupCount(); i++) { + manaColorNames.add(colorLookup.get(matcher.group(i))); + } + System.out.println(manaColorNames.toString()); + ColorSet manaColorSet = ColorSet.fromNames(manaColorNames); + } + } + System.out.println(dLands.toString()); + return; + + //Assert.assertNotNull(has); + } + /** * Create a CardPrinted from the given filename. * diff --git a/forge-gui-mobile/src/forge/deck/FDeckChooser.java b/forge-gui-mobile/src/forge/deck/FDeckChooser.java index 6c6a2ebd037..395ce56abd7 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckChooser.java +++ b/forge-gui-mobile/src/forge/deck/FDeckChooser.java @@ -147,7 +147,8 @@ public class FDeckChooser extends FScreen { btnViewDeck.setCommand(new FEventHandler() { @Override public void handleEvent(FEvent e) { - if (selectedDeckType != DeckType.COLOR_DECK && selectedDeckType != DeckType.THEME_DECK) { + if (selectedDeckType != DeckType.STANDARD_COLOR_DECK && selectedDeckType != DeckType.MODERN_COLOR_DECK && + selectedDeckType != DeckType.COLOR_DECK && selectedDeckType != DeckType.THEME_DECK) { FDeckViewer.show(getDeck()); } } @@ -160,7 +161,8 @@ public class FDeckChooser extends FScreen { testSelectedDeck(); return; } - if (selectedDeckType == DeckType.COLOR_DECK) { + if (selectedDeckType == DeckType.COLOR_DECK || selectedDeckType == DeckType.STANDARD_COLOR_DECK + || selectedDeckType == DeckType.MODERN_COLOR_DECK) { DeckgenUtil.randomSelectColors(lstDecks); } else { @@ -259,6 +261,8 @@ public class FDeckChooser extends FScreen { NewGameScreen.SealedDeck.open(); return; case COLOR_DECK: + case STANDARD_COLOR_DECK: + case MODERN_COLOR_DECK: case THEME_DECK: case RANDOM_DECK: final DeckProxy deck = lstDecks.getSelectedItem(); @@ -427,6 +431,8 @@ public class FDeckChooser extends FScreen { cmbDeckTypes.addItem(DeckType.PRECONSTRUCTED_DECK); cmbDeckTypes.addItem(DeckType.QUEST_OPPONENT_DECK); cmbDeckTypes.addItem(DeckType.COLOR_DECK); + cmbDeckTypes.addItem(DeckType.STANDARD_COLOR_DECK); + cmbDeckTypes.addItem(DeckType.MODERN_COLOR_DECK); cmbDeckTypes.addItem(DeckType.THEME_DECK); cmbDeckTypes.addItem(DeckType.RANDOM_DECK); cmbDeckTypes.addItem(DeckType.NET_DECK); @@ -575,7 +581,17 @@ public class FDeckChooser extends FScreen { break; case COLOR_DECK: maxSelections = 3; - pool = ColorDeckGenerator.getColorDecks(lstDecks, isAi); + pool = ColorDeckGenerator.getColorDecks(lstDecks, null, isAi); + config = ItemManagerConfig.STRING_ONLY; + break; + case STANDARD_COLOR_DECK: + maxSelections = 3; + pool = ColorDeckGenerator.getColorDecks(lstDecks, FModel.getFormats().getStandard().getFilterPrinted(), isAi); + config = ItemManagerConfig.STRING_ONLY; + break; + case MODERN_COLOR_DECK: + maxSelections = 3; + pool = ColorDeckGenerator.getColorDecks(lstDecks, FModel.getFormats().getModern().getFilterPrinted(), isAi); config = ItemManagerConfig.STRING_ONLY; break; case THEME_DECK: @@ -900,11 +916,13 @@ public class FDeckChooser extends FScreen { if (numOpponents == null) { return; } ListChooser chooser = new ListChooser( - "Choose allowed deck types for opponents", 0, 5, Arrays.asList(new DeckType[] { + "Choose allowed deck types for opponents", 0, 7, Arrays.asList(new DeckType[] { DeckType.CUSTOM_DECK, DeckType.PRECONSTRUCTED_DECK, DeckType.QUEST_OPPONENT_DECK, DeckType.COLOR_DECK, + DeckType.STANDARD_COLOR_DECK, + DeckType.MODERN_COLOR_DECK, DeckType.THEME_DECK }), null, new Callback>() { @Override diff --git a/forge-gui-mobile/src/forge/screens/gauntlet/NewGauntletScreen.java b/forge-gui-mobile/src/forge/screens/gauntlet/NewGauntletScreen.java index c39accf80f0..b4c74a6eafd 100644 --- a/forge-gui-mobile/src/forge/screens/gauntlet/NewGauntletScreen.java +++ b/forge-gui-mobile/src/forge/screens/gauntlet/NewGauntletScreen.java @@ -82,11 +82,13 @@ public class NewGauntletScreen extends LaunchScreen { if (numOpponents == null) { return; } ListChooser chooser = new ListChooser( - "Choose allowed deck types for opponents", 0, 5, Arrays.asList(new DeckType[] { + "Choose allowed deck types for opponents", 0, 7, Arrays.asList(new DeckType[] { DeckType.CUSTOM_DECK, DeckType.PRECONSTRUCTED_DECK, DeckType.QUEST_OPPONENT_DECK, DeckType.COLOR_DECK, + DeckType.STANDARD_COLOR_DECK, + DeckType.MODERN_COLOR_DECK, DeckType.THEME_DECK }), null, new Callback>() { @Override diff --git a/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java b/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java index 61c694083a6..13b0250130b 100644 --- a/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java +++ b/forge-gui/src/main/java/forge/deck/ColorDeckGenerator.java @@ -3,15 +3,19 @@ package forge.deck; import java.util.ArrayList; import java.util.List; +import com.google.common.base.Predicate; +import forge.item.IPaperCard; +import forge.item.PaperCard; import forge.itemmanager.IItemManager; +import forge.model.FModel; public class ColorDeckGenerator extends DeckProxy implements Comparable { - public static List getColorDecks(final IItemManager lstDecks0, final boolean isAi0) { + public static List getColorDecks(final IItemManager lstDecks0, final Predicate formatFilter0, final boolean isAi0) { final String[] colors = new String[] { "Random 1", "Random 2", "Random 3", "White", "Blue", "Black", "Red", "Green" }; final List decks = new ArrayList(); for (int i = 0; i < colors.length; i++) { - decks.add(new ColorDeckGenerator(colors[i], i, lstDecks0, isAi0)); + decks.add(new ColorDeckGenerator(colors[i], i, lstDecks0, formatFilter0, isAi0)); } return decks; } @@ -20,13 +24,15 @@ public class ColorDeckGenerator extends DeckProxy implements Comparable lstDecks; private final boolean isAi; + private final Predicate formatFilter; - private ColorDeckGenerator(final String name0, final int index0, final IItemManager lstDecks0, final boolean isAi0) { + private ColorDeckGenerator(final String name0, final int index0, final IItemManager lstDecks0,final Predicate formatFilter0, final boolean isAi0) { super(); name = name0; index = index0; lstDecks = lstDecks0; isAi = isAi0; + formatFilter = formatFilter0; } @Override @@ -51,7 +57,7 @@ public class ColorDeckGenerator extends DeckProxy implements Comparable selection, boolean forAi) { + + public static Deck buildColorDeck(List selection, Predicate formatFilter, boolean forAi) { try { final Deck deck; String deckName = null; - + DeckGeneratorBase gen = null; CardDb cardDb = FModel.getMagicDb().getCommonCards(); - if (selection.size() == 1) { - gen = new DeckGeneratorMonoColor(cardDb, DeckFormat.Constructed, selection.get(0)); - } - else if (selection.size() == 2) { - gen = new DeckGenerator2Color(cardDb, DeckFormat.Constructed, selection.get(0), selection.get(1)); - } - else if (selection.size() == 3) { - gen = new DeckGenerator3Color(cardDb, DeckFormat.Constructed, selection.get(0), selection.get(1), selection.get(2)); - } - else { - gen = new DeckGenerator5Color(cardDb, DeckFormat.Constructed); - deckName = "5 colors"; + if (formatFilter == null){ + if (selection.size() == 1) { + gen = new DeckGeneratorMonoColor(cardDb, DeckFormat.Constructed,selection.get(0)); + } + else if (selection.size() == 2) { + gen = new DeckGenerator2Color(cardDb, DeckFormat.Constructed,selection.get(0), selection.get(1)); + } + else if (selection.size() == 3) { + gen = new DeckGenerator3Color(cardDb, DeckFormat.Constructed,selection.get(0), selection.get(1), selection.get(2)); + } + else { + gen = new DeckGenerator5Color(cardDb, DeckFormat.Constructed); + deckName = "5 colors"; + } + }else { + if (selection.size() == 1) { + gen = new DeckGeneratorMonoColor(cardDb, DeckFormat.Constructed, formatFilter, selection.get(0)); + } else if (selection.size() == 2) { + gen = new DeckGenerator2Color(cardDb, DeckFormat.Constructed, formatFilter, selection.get(0), selection.get(1)); + } else if (selection.size() == 3) { + gen = new DeckGenerator3Color(cardDb, DeckFormat.Constructed, formatFilter, selection.get(0), selection.get(1), selection.get(2)); + } else { + gen = new DeckGenerator5Color(cardDb, DeckFormat.Constructed, formatFilter); + deckName = "5 colors"; + } } gen.setSingleton(FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS)); gen.setUseArtifacts(!FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)); final CardPool cards = gen.getDeck(60, forAi); - + if (null == deckName) { deckName = Lang.joinHomogenous(Arrays.asList(selection)); } - + // After generating card lists, build deck. deck = new Deck("Random deck : " + deckName); deck.setDirectory("generated/color"); @@ -81,7 +96,7 @@ public class DeckgenUtil { catch (Exception e) { e.printStackTrace(); } - return buildColorDeck(selection, forAi); //try again if previous color deck couldn't be generated + return buildColorDeck(selection, formatFilter, forAi); //try again if previous color deck couldn't be generated } public static QuestEvent getQuestEvent(final String name) { @@ -98,6 +113,17 @@ public class DeckgenUtil { return duel; } + /** @return {@link forge.deck.Deck} */ + public static Deck getRandomColorDeck(Predicate formatFilter, boolean forAi) { + final int[] colorCount = new int[] {1, 2, 3}; + final int count = colorCount[MyRandom.getRandom().nextInt(colorCount.length)]; + final List selection = new ArrayList(); + + // A simulated selection of "random 1" will trigger the AI selection process. + for (int i = 0; i < count; i++) { selection.add("Random"); } + return DeckgenUtil.buildColorDeck(selection, formatFilter, forAi); + } + /** @return {@link forge.deck.Deck} */ public static Deck getRandomColorDeck(boolean forAi) { final int[] colorCount = new int[] {1, 2, 3, 5}; @@ -106,8 +132,7 @@ public class DeckgenUtil { // A simulated selection of "random 1" will trigger the AI selection process. for (int i = 0; i < count; i++) { selection.add("Random"); } - - return DeckgenUtil.buildColorDeck(selection, forAi); + return DeckgenUtil.buildColorDeck(selection, null, forAi); } /** @return {@link forge.deck.Deck} */ diff --git a/forge-gui/src/main/java/forge/deck/RandomDeckGenerator.java b/forge-gui/src/main/java/forge/deck/RandomDeckGenerator.java index 8217f971362..6e84ea5d7fa 100644 --- a/forge-gui/src/main/java/forge/deck/RandomDeckGenerator.java +++ b/forge-gui/src/main/java/forge/deck/RandomDeckGenerator.java @@ -8,6 +8,7 @@ import com.google.common.collect.Iterables; import forge.game.GameType; import forge.game.IHasGameType; +import forge.model.FModel; import forge.quest.QuestController; import forge.util.Aggregates; @@ -91,12 +92,26 @@ public class RandomDeckGenerator extends DeckProxy implements Comparable colors = new ArrayList(); - final int count = Aggregates.randomInt(1, 3); + List colors = new ArrayList(); + int count = Aggregates.randomInt(1, 3); for (int i = 1; i <= count; i++) { colors.add("Random " + i); } - return DeckgenUtil.buildColorDeck(colors, isAi); + return DeckgenUtil.buildColorDeck(colors, null, isAi); + case STANDARD_COLOR_DECK: + colors = new ArrayList(); + count = Aggregates.randomInt(1, 3); + for (int i = 1; i <= count; i++) { + colors.add("Random " + i); + } + return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getStandard().getFilterPrinted(), isAi); + case MODERN_COLOR_DECK: + colors = new ArrayList(); + count = Aggregates.randomInt(1, 3); + for (int i = 1; i <= count; i++) { + colors.add("Random " + i); + } + return DeckgenUtil.buildColorDeck(colors, FModel.getFormats().getModern().getFilterPrinted(), isAi); case THEME_DECK: return Aggregates.random(DeckProxy.getAllThemeDecks()).getDeck(); default: diff --git a/forge-gui/src/main/java/forge/gauntlet/GauntletUtil.java b/forge-gui/src/main/java/forge/gauntlet/GauntletUtil.java index 69a1c4de224..387a327b486 100644 --- a/forge-gui/src/main/java/forge/gauntlet/GauntletUtil.java +++ b/forge-gui/src/main/java/forge/gauntlet/GauntletUtil.java @@ -29,6 +29,12 @@ public class GauntletUtil { deck = DeckgenUtil.getRandomColorDeck(true); eventNames.add("Random colors deck"); break; + case STANDARD_COLOR_DECK: + deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getStandard().getFilterPrinted(),true); + break; + case MODERN_COLOR_DECK: + deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getModern().getFilterPrinted(),true); + break; case CUSTOM_DECK: deck = DeckgenUtil.getRandomCustomDeck(); eventNames.add(deck.getName()); diff --git a/forge-gui/src/main/java/forge/tournament/TournamentUtil.java b/forge-gui/src/main/java/forge/tournament/TournamentUtil.java index a3eaa4be2d5..754368afdc9 100644 --- a/forge-gui/src/main/java/forge/tournament/TournamentUtil.java +++ b/forge-gui/src/main/java/forge/tournament/TournamentUtil.java @@ -29,6 +29,12 @@ public class TournamentUtil { deck = DeckgenUtil.getRandomColorDeck(true); eventNames.add("Random colors deck"); break; + case STANDARD_COLOR_DECK: + deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getStandard().getFilterPrinted(),true); + break; + case MODERN_COLOR_DECK: + deck = DeckgenUtil.getRandomColorDeck(FModel.getFormats().getModern().getFilterPrinted(),true); + break; case CUSTOM_DECK: deck = DeckgenUtil.getRandomCustomDeck(); eventNames.add(deck.getName());