Add 2 new random deck types - standard and modern legal random color decks. Also improved dual/tri land selection with oracle parsing. Generated decks now choose basic lands that match a card from the deck.

This commit is contained in:
austinio7116
2017-05-03 10:49:53 +00:00
parent ffe6518f32
commit 7a355a84a1
18 changed files with 366 additions and 76 deletions

View File

@@ -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<PaperCard> filter = Predicates.and(IPaperCard.Predicates.printedInSet(edition),IPaperCard.Predicates.name(name));
Iterable<PaperCard> 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) {

View File

@@ -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<PaperCard> 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);

View File

@@ -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,9 +60,17 @@ public class DeckGenerator3Color extends DeckGeneratorBase {
ImmutablePair.of(new FilterCMC(6, 20), 3)
);
public DeckGenerator3Color(IDeckGenPool pool0, DeckFormat format0, Predicate<PaperCard> 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);
@@ -88,7 +98,7 @@ public class DeckGenerator3Color extends DeckGeneratorBase {
} while ( rc == combo );
combo |= rc;
//$FALL-THROUGH$
//$FALL-THROUGH$
case 2:
do {
rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5);
@@ -119,7 +129,6 @@ public class DeckGenerator3Color extends DeckGeneratorBase {
addBasicLand(numLands);
trace.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -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<PaperCard> 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;
}
}

View File

@@ -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;
/**
* <p>
@@ -51,19 +55,31 @@ public abstract class DeckGeneratorBase {
protected final Map<String, Integer> cardCounts = new HashMap<String, Integer>();
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<PaperCard> 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<PaperCard> cards = selectCardsOfMatchingColorForPlayer(forAi);
// build subsets based on type
final Iterable<PaperCard> 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<PaperCard> 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<PaperCard> 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<CardRules> canPlay = forAi ? AI_CAN_PLAY : HUMAN_CAN_PLAY;
Predicate<CardRules> 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<String, Integer> countLands(ItemPool<PaperCard> outList) {
@@ -351,24 +387,22 @@ public abstract class DeckGeneratorBase {
private static Map<Integer, String[]> dualLands = new HashMap<Integer, String[]>();
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<String> getDualLandList() {
@@ -383,22 +417,70 @@ public abstract class DeckGeneratorBase {
addCardNameToList("Evolving Wilds", dLands);
addCardNameToList("Terramorphic Expanse", dLands);
}
for (Entry<Integer, String[]> 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<PaperCard> dualLandFilter = Predicates.compose(CardRulesPredicates.coreType(true, CardType.CoreType.Land), PaperCard.FN_GET_RULES);
Predicate<PaperCard> exceptBasicLand = Predicates.not(Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES));
Iterable<PaperCard> landCards = pool.getAllCards(Predicates.and(dualLandFilter,exceptBasicLand));
Iterable<String> 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<String> regexLandSearch(String pattern, Iterable<PaperCard> landCards){
final List<String> dLands = new ArrayList<String>();
Pattern p = Pattern.compile(pattern);
for (PaperCard card:landCards){
Matcher matcher = p.matcher(card.getRules().getOracleText());
while (matcher.find()) {
List<String> 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<String> regexFetchLandSearch(Iterable<PaperCard> landCards){
final String fetchPattern="Search your library for a ([^\\s]*) or ([^\\s]*) card";
final List<String> dLands = new ArrayList<String>();
Map<String,String> 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<String> 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<String> getInverseDualLandList() {

View File

@@ -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<PaperCard> 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;
}
}

View File

@@ -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<PaperCard> 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();

View File

@@ -70,6 +70,8 @@ public enum CSubmenuGauntletQuick implements ICDoc {
// Find appropriate filename for new save, create and set new save file.
final List<DeckType> allowedDeckTypes = new ArrayList<DeckType>();
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); }

View File

@@ -51,6 +51,8 @@ public enum VSubmenuGauntletQuick implements IVSubmenu<CSubmenuGauntletQuick> {
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<CSubmenuGauntletQuick> {
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<CSubmenuGauntletQuick> {
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<CSubmenuGauntletQuick> {
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;

View File

@@ -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<String> cardNames= Arrays.asList("tundra.txt", "hallowed_fountain.txt", "flooded_strand.txt", "prairie_stream.txt", "sunken_hollow.txt", "smoldering_marsh.txt");
List<PaperCard> 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<String> dLands = new ArrayList<String>();
Map<String,String> 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<String> 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.
*

View File

@@ -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<DeckType> chooser = new ListChooser<DeckType>(
"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<List<DeckType>>() {
@Override

View File

@@ -82,11 +82,13 @@ public class NewGauntletScreen extends LaunchScreen {
if (numOpponents == null) { return; }
ListChooser<DeckType> chooser = new ListChooser<DeckType>(
"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<List<DeckType>>() {
@Override

View File

@@ -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<ColorDeckGenerator> {
public static List<DeckProxy> getColorDecks(final IItemManager<DeckProxy> lstDecks0, final boolean isAi0) {
public static List<DeckProxy> getColorDecks(final IItemManager<DeckProxy> lstDecks0, final Predicate<PaperCard> formatFilter0, final boolean isAi0) {
final String[] colors = new String[] { "Random 1", "Random 2", "Random 3",
"White", "Blue", "Black", "Red", "Green" };
final List<DeckProxy> decks = new ArrayList<DeckProxy>();
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<ColorDec
private final int index;
private final IItemManager<DeckProxy> lstDecks;
private final boolean isAi;
private final Predicate<PaperCard> formatFilter;
private ColorDeckGenerator(final String name0, final int index0, final IItemManager<DeckProxy> lstDecks0, final boolean isAi0) {
private ColorDeckGenerator(final String name0, final int index0, final IItemManager<DeckProxy> lstDecks0,final Predicate<PaperCard> 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<ColorDec
selection.add(deck.getName());
}
if (DeckgenUtil.colorCheck(selection)) {
return DeckgenUtil.buildColorDeck(selection, isAi);
return DeckgenUtil.buildColorDeck(selection, formatFilter, isAi);
}
return null;
}

View File

@@ -12,6 +12,8 @@ public enum DeckType {
PRECONSTRUCTED_DECK("Preconstructed Decks"),
QUEST_OPPONENT_DECK ("Quest Opponent Decks"),
COLOR_DECK ("Random Color Decks"),
STANDARD_COLOR_DECK ("Random Standard Color Decks"),
MODERN_COLOR_DECK ("Random Modern Color Decks"),
THEME_DECK ("Random Theme Decks"),
RANDOM_DECK ("Random Decks"),
NET_DECK ("Net Decks"),
@@ -22,6 +24,8 @@ public enum DeckType {
DeckType.PRECONSTRUCTED_DECK,
DeckType.QUEST_OPPONENT_DECK,
DeckType.COLOR_DECK,
DeckType.STANDARD_COLOR_DECK,
DeckType.MODERN_COLOR_DECK,
DeckType.THEME_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_DECK

View File

@@ -13,6 +13,7 @@ import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.deck.generation.*;
import forge.game.GameType;
import forge.item.IPaperCard;
import forge.item.PaperCard;
import forge.itemmanager.IItemManager;
import forge.model.FModel;
@@ -44,25 +45,39 @@ public class DeckgenUtil {
* @param selection {@link java.lang.String} array
* @return {@link forge.deck.Deck}
*/
public static Deck buildColorDeck(List<String> selection, boolean forAi) {
public static Deck buildColorDeck(List<String> selection, Predicate<PaperCard> 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));
@@ -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<PaperCard> formatFilter, boolean forAi) {
final int[] colorCount = new int[] {1, 2, 3};
final int count = colorCount[MyRandom.getRandom().nextInt(colorCount.length)];
final List<String> selection = new ArrayList<String>();
// 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} */

View File

@@ -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<RandomD
case QUEST_OPPONENT_DECK:
return Aggregates.random(DeckProxy.getAllQuestEventAndChallenges()).getDeck();
case COLOR_DECK:
final List<String> colors = new ArrayList<String>();
final int count = Aggregates.randomInt(1, 3);
List<String> colors = new ArrayList<String>();
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<String>();
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<String>();
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:

View File

@@ -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());

View File

@@ -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());