deck generation moved to core

This commit is contained in:
Maxmtg
2013-11-21 20:59:18 +00:00
parent 2f85d50778
commit 482af12b67
24 changed files with 303 additions and 318 deletions

View File

@@ -1,138 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Nate
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.google.common.base.Function;
/**
* TODO: Write javadoc for this type.
*
*/
public class DeckGroup extends DeckBase {
/**
* Instantiates a new deck group.
*
* @param name0 the name0
*/
public DeckGroup(final String name0) {
super(name0);
}
private static final long serialVersionUID = -1628725522049635829L;
private Deck humanDeck;
private List<Deck> aiDecks = new ArrayList<Deck>();
/**
* Gets the human deck.
*
* @return the human deck
*/
public final Deck getHumanDeck() {
return this.humanDeck;
}
/**
* Gets the ai decks.
*
* @return the ai decks
*/
public final List<Deck> getAiDecks() {
return this.aiDecks;
}
/**
* Sets the human deck.
*
* @param humanDeck the new human deck
*/
public final void setHumanDeck(final Deck humanDeck) {
this.humanDeck = humanDeck;
}
/**
* Evaluate and 'rank' the ai decks.
*
*
*/
public final void rankAiDecks(Comparator<Deck> comparator) {
if (this.aiDecks.size() < 2) {
return;
}
Collections.sort(aiDecks, comparator);
}
@Override
protected void cloneFieldsTo(final DeckBase clone) {
super.cloneFieldsTo(clone);
DeckGroup myClone = (DeckGroup) clone;
myClone.setHumanDeck((Deck) this.getHumanDeck().copyTo(this.getHumanDeck().getName()));
for (int i = 0; i < this.getAiDecks().size(); i++) {
Deck src = this.getAiDecks().get(i);
myClone.addAiDeck((Deck) src.copyTo(src.getName()));
}
}
/**
* Adds the ai deck.
*
* @param aiDeck the ai deck
*/
public final void addAiDeck(final Deck aiDeck) {
if (aiDeck == null) {
return;
}
this.aiDecks.add(aiDeck);
}
/**
* Adds the ai decks.
*
* @param computer the computer
*/
public void addAiDecks(final Deck[] computer) {
for (final Deck element : computer) {
this.aiDecks.add(element);
}
}
/*
* (non-Javadoc)
*
* @see forge.deck.DeckBase#newInstance(java.lang.String)
*/
@Override
protected DeckBase newInstance(final String name0) {
return new DeckGroup(name0);
}
public static final Function<DeckGroup, String> FN_NAME_SELECTOR = new Function<DeckGroup, String>() {
@Override
public String apply(DeckGroup arg1) {
return arg1.getName();
}
};
}

View File

@@ -1,286 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import forge.Singletons;
import forge.card.ICardDatabase;
import forge.item.PaperCard;
/**
* <p>
* DeckRecognizer class.
* </p>
*
* @author Forge
* @version $Id: DeckRecognizer.java 10499 2011-09-17 15:08:47Z Max mtg $
*
*/
public class DeckRecognizer {
/**
* The Enum TokenType.
*/
public enum TokenType {
/** The Known card. */
KnownCard,
/** The Unknown card. */
UnknownCard,
/** The Section name. */
SectionName,
/** The Comment. */
Comment,
/** The Unknown text. */
UnknownText
}
/**
* The Class Token.
*/
public static class Token {
private final TokenType type;
private final PaperCard card;
private final int number;
private final String text;
/**
* Known card.
*
* @param theCard
* the the card
* @param count
* the count
* @return the token
*/
public static Token knownCard(final PaperCard theCard, final int count) {
return new Token(theCard, TokenType.KnownCard, count, null);
}
/**
* Unknown card.
*
* @param cardNme
* the card nme
* @param count
* the count
* @return the token
*/
public static Token unknownCard(final String cardNme, final int count) {
return new Token(null, TokenType.UnknownCard, count, cardNme);
}
private Token(final PaperCard knownCard, final TokenType type1, final int count, final String message) {
this.card = knownCard;
this.number = count;
this.type = type1;
this.text = message;
}
/**
* Instantiates a new token.
*
* @param type1
* the type1
* @param count
* the count
* @param message
* the message
*/
public Token(final TokenType type1, final int count, final String message) {
this(null, type1, count, message);
if ((type1 == TokenType.KnownCard) || (type1 == TokenType.UnknownCard)) {
throw new IllegalArgumentException("Use factory methods for recognized card lines");
}
}
/**
* Gets the text.
*
* @return the text
*/
public final String getText() {
return this.text;
}
/**
* Gets the card.
*
* @return the card
*/
public final PaperCard getCard() {
return this.card;
}
/**
* Gets the type.
*
* @return the type
*/
public final TokenType getType() {
return this.type;
}
/**
* Gets the number.
*
* @return the number
*/
public final int getNumber() {
return this.number;
}
}
// Let's think about it numbers in the back later
// private static final Pattern searchNumbersInBack =
// Pattern.compile("(.*)[^A-Za-wyz]*\\s+([\\d]{1,2})");
private static final Pattern SEARCH_NUMBERS_IN_FRONT = Pattern.compile("([\\d]{1,2})[^A-Za-wyz]*\\s+(.*)");
//private static final Pattern READ_SEPARATED_EDITION = Pattern.compile("[[\\(\\{]([a-zA-Z0-9]){1,3})[]*\\s+(.*)");
private final boolean useLastSet;
private final ICardDatabase db;
private Date recognizeCardsPrintedBefore = null;
public DeckRecognizer(boolean fromLatestSet) {
useLastSet = fromLatestSet;
db = Singletons.getMagicDb().getCommonCards();
}
public Token recognizeLine(final String rawLine) {
if (StringUtils.isBlank(rawLine)) {
return new Token(TokenType.Comment, 0, rawLine);
}
final String line = rawLine.trim();
Token result = null;
final Matcher foundNumbersInFront = DeckRecognizer.SEARCH_NUMBERS_IN_FRONT.matcher(line);
// Matcher foundNumbersInBack = searchNumbersInBack.matcher(line);
if (foundNumbersInFront.matches()) {
final String cardName = foundNumbersInFront.group(2);
final int amount = Integer.parseInt(foundNumbersInFront.group(1));
result = recognizePossibleNameAndNumber(cardName, amount);
} /*
* else if (foundNumbersInBack.matches()) { String cardName =
* foundNumbersInBack.group(1); int amount =
* Integer.parseInt(foundNumbersInBack.group(2)); return new
* Token(cardName, amount); }
*/
else {
PaperCard pc = tryGetCard(line);
if (null != pc) {
return Token.knownCard(pc, 1);
}
result = DeckRecognizer.recognizeNonCard(line, 1);
}
return result != null ? result : new Token(TokenType.UnknownText, 0, line);
}
private PaperCard tryGetCard(String text) {
if(recognizeCardsPrintedBefore != null )
return db.tryGetCardPrintedByDate(text, useLastSet, recognizeCardsPrintedBefore);
return db.tryGetCard(text, useLastSet);
}
private Token recognizePossibleNameAndNumber(final String name, final int n) {
PaperCard pc = tryGetCard(name);
if (null != pc) {
return Token.knownCard(pc, n);
}
// TODO: recognize format: http://topdeck.ru/forum/index.php?showtopic=12711
//final Matcher foundEditionName = READ_SEPARATED_EDITION.matcher(name);
final Token known = DeckRecognizer.recognizeNonCard(name, n);
return null == known ? Token.unknownCard(name, n) : known;
}
private static Token recognizeNonCard(final String text, final int n) {
if (DeckRecognizer.isDecoration(text)) {
return new Token(TokenType.Comment, n, text);
}
if (DeckRecognizer.isSectionName(text)) {
return new Token(TokenType.SectionName, n, text);
}
return null;
}
private static final String[] KNOWN_COMMENTS = new String[] { "land", "lands", "creatures", "creature", "spells",
"enchancements", "other spells", "artifacts" };
private static final String[] KNOWN_COMMENT_PARTS = new String[] { "card" };
private static boolean isDecoration(final String lineAsIs) {
final String line = lineAsIs.toLowerCase();
for (final String s : DeckRecognizer.KNOWN_COMMENT_PARTS) {
if (line.contains(s)) {
return true;
}
}
for (final String s : DeckRecognizer.KNOWN_COMMENTS) {
if (line.equalsIgnoreCase(s)) {
return true;
}
}
return false;
}
private static boolean isSectionName(final String line) {
if (line.toLowerCase().contains("side")) {
return true;
}
if (line.toLowerCase().contains("main")) {
return true;
}
if (line.toLowerCase().contains("commander")) {
return true;
}
if (line.toLowerCase().contains("planes")) {
return true;
}
if (line.toLowerCase().contains("schemes")) {
return true;
}
if (line.toLowerCase().contains("vanguard")) {
return true;
}
return false;
}
/**
* TODO: Write javadoc for this method.
* @param month
* @param year
*/
public void setDateConstraint(int month, Integer year) {
Calendar ca = Calendar.getInstance();
ca.set(year, month, 1);
recognizeCardsPrintedBefore = ca.getTime();
}
}

View File

@@ -1,114 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
import java.util.Arrays;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
/**
* <p>
* Generate2ColorDeck class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class Generate2ColorDeck extends GenerateColoredDeckBase {
@Override protected final float getLandsPercentage() { return 0.39f; }
@Override protected final float getCreatPercentage() { return 0.36f; }
@Override protected final float getSpellPercentage() { return 0.25f; }
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcRelativeWeights = Lists.newArrayList(
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 6),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 4), 4),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(5, 6), 2),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(7, 20), 1)
);
// mana curve of the card pool
// 20x 0 - 2
// 16x 3 - 4
// 12x 5 - 6
// 4x 7 - 20
// = 52x - card pool (before further random filtering)
/**
* <p>
* Constructor for Generate2ColorDeck.
* </p>
*
* @param clr1
* a {@link java.lang.String} object.
* @param clr2
* a {@link java.lang.String} object.
*/
public Generate2ColorDeck(final String clr1, final String clr2) {
int c1 = MagicColor.fromName(clr1);
int c2 = MagicColor.fromName(clr2);
if( c1 == 0 && c2 == 0) {
int color1 = r.nextInt(5);
int color2 = (color1 + 1 + r.nextInt(4)) % 5;
colors = ColorSet.fromMask(MagicColor.WHITE << color1 | MagicColor.WHITE << color2);
} else if ( c1 == 0 || c2 == 0 ) {
byte knownColor = (byte) (c1 | c2);
int color1 = Arrays.binarySearch(MagicColor.WUBRG, knownColor);
int color2 = (color1 + 1 + r.nextInt(4)) % 5;
colors = ColorSet.fromMask(MagicColor.WHITE << color1 | MagicColor.WHITE << color2);
} else {
colors = ColorSet.fromMask(c1 | c2);
}
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcRelativeWeights, forAi);
// Add lands
int numLands = Math.round(size * getLandsPercentage());
adjustDeckSize(size - numLands);
tmpDeck.append(String.format("Adjusted deck size to: %d, should add %d land(s)%n", size - numLands, numLands));
// Add dual lands
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
for (String s : duals) {
this.cardCounts.put(s, 0);
}
int dblsAdded = addSomeStr((numLands / 6), duals);
numLands -= dblsAdded;
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
//System.out.println(tmpDeck.toString());
return tDeck;
}
}

View File

@@ -1,120 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
import forge.util.MyRandom;
/**
* <p>
* Generate3ColorDeck class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class Generate3ColorDeck extends GenerateColoredDeckBase {
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 12),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 5), 9),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(6, 20), 3)
);
/**
* <p>
* Constructor for Generate3ColorDeck.
* </p>
*
* @param clr1
* a {@link java.lang.String} object.
* @param clr2
* a {@link java.lang.String} object.
* @param clr3
* a {@link java.lang.String} object.
*/
public Generate3ColorDeck(final String clr1, final String clr2, final String clr3) {
int c1 = MagicColor.fromName(clr1);
int c2 = MagicColor.fromName(clr2);
int c3 = MagicColor.fromName(clr3);
int rc = 0;
int combo = c1 | c2 | c3;
ColorSet param = ColorSet.fromMask(combo);
switch(param.countColors()) {
case 3:
colors = param;
return;
case 0:
int color1 = r.nextInt(5);
int color2 = (color1 + 1 + r.nextInt(4)) % 5;
colors = ColorSet.fromMask(MagicColor.WHITE << color1 | MagicColor.WHITE << color2).inverse();
return;
case 1:
do {
rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5);
} while ( rc == combo );
combo |= rc;
// fall-through
case 2:
do {
rc = MagicColor.WHITE << MyRandom.getRandom().nextInt(5);
} while ( (rc & combo) != 0 );
combo |= rc;
break;
}
colors = ColorSet.fromMask(combo);
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcLevels, forAi);
// Add lands
int numLands = Math.round(size * getLandsPercentage());
adjustDeckSize(size - numLands);
tmpDeck.append("numLands:").append(numLands).append("\n");
// Add dual lands
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
for (String s : duals) {
this.cardCounts.put(s, 0);
}
int dblsAdded = addSomeStr((numLands / 4), duals);
numLands -= dblsAdded;
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -1,83 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
/**
* <p>
* Generate5ColorDeck class.
* </p>
*
* @author Forge
* @version $Id$
*/
public class Generate5ColorDeck extends GenerateColoredDeckBase {
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 3),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 5), 2),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(6, 20), 1)
);
// resulting mana curve of the card pool
// 30x 0 - 2
// 20x 3 - 5
// 10x 6 - 20
// =60x - card pool
/**
* Instantiates a new generate5 color deck.
*/
public Generate5ColorDeck() {
colors = ColorSet.fromMask(0).inverse();
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcLevels, forAi);
// Add lands
int numLands = Math.round(size * getLandsPercentage());
adjustDeckSize(size - numLands);
tmpDeck.append("numLands:").append(numLands).append("\n");
// Add dual lands
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
for (String s : duals) {
this.cardCounts.put(s, 0);
}
int dblsAdded = addSomeStr((numLands / 4), duals);
numLands -= dblsAdded;
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -1,275 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.TreeMap;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Singletons;
import forge.card.CardRules;
import forge.card.CardRulesPredicates;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
import forge.item.PaperCard;
import forge.properties.ForgePreferences.FPref;
import forge.util.Aggregates;
import forge.util.ItemPool;
import forge.util.ItemPoolView;
import forge.util.MyRandom;
/**
* <p>
* Generate2ColorDeck class.
* </p>
*
* @author Forge
* @version $Id: Generate2ColorDeck.java 14959 2012-03-28 14:03:43Z Chris H. $
*/
public abstract class GenerateColoredDeckBase {
protected final Random r = MyRandom.getRandom();
protected final Map<String, Integer> cardCounts = new HashMap<String, Integer>();
protected int maxDuplicates;
protected ColorSet colors;
protected final ItemPool<PaperCard> tDeck;
// 2-colored deck generator has its own constants. The rest works fine with these ones
protected float getLandsPercentage() { return 0.44f; }
protected float getCreatPercentage() { return 0.34f; }
protected float getSpellPercentage() { return 0.22f; }
StringBuilder tmpDeck = new StringBuilder();
public GenerateColoredDeckBase() {
this.maxDuplicates = Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS) ? 1 : 4;
tDeck = new ItemPool<PaperCard>(PaperCard.class);
}
protected void addCreaturesAndSpells(int size, List<ImmutablePair<FilterCMC, Integer>> cmcLevels, boolean forAi) {
tmpDeck.append("Building deck of ").append(size).append("cards\n");
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(getCreatPercentage() * size);
tmpDeck.append("Creatures to add:").append(creatCnt).append("\n");
addCmcAdjusted(creatures, creatCnt, cmcLevels);
Predicate<PaperCard> preSpells = Predicates.compose(CardRulesPredicates.Presets.IS_NONCREATURE_SPELL_FOR_GENERATOR, PaperCard.FN_GET_RULES);
final Iterable<PaperCard> spells = Iterables.filter(cards, preSpells);
final int spellCnt = (int) Math.ceil(getSpellPercentage() * size);
tmpDeck.append("Spells to add:").append(spellCnt).append("\n");
addCmcAdjusted(spells, spellCnt, cmcLevels);
tmpDeck.append(String.format("Current deck size: %d... should be %f%n", tDeck.countAll(), size * (getCreatPercentage() + getSpellPercentage())));
}
public ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
return null; // all but theme deck do override this method
}
protected void addSome(int cnt, List<PaperCard> source) {
for (int i = 0; i < cnt; i++) {
PaperCard cp;
int lc = 0;
int srcLen = source.size();
do {
cp = source.get(this.r.nextInt(srcLen));
lc++;
} while (this.cardCounts.get(cp.getName()) > this.maxDuplicates - 1 && lc <= 100);
if (lc > 100) {
throw new RuntimeException("Generate2ColorDeck : get2ColorDeck -- looped too much -- Cr12");
}
tDeck.add(cp);
final int n = this.cardCounts.get(cp.getName());
this.cardCounts.put(cp.getName(), n + 1);
if( n + 1 == this.maxDuplicates )
source.remove(cp);
tmpDeck.append(String.format("(%d) %s [%s]%n", cp.getRules().getManaCost().getCMC(), cp.getName(), cp.getRules().getManaCost()));
}
}
protected int addSomeStr(int cnt, List<String> source) {
int res = 0;
for (int i = 0; i < cnt; i++) {
String s;
int lc = 0;
do {
s = source.get(this.r.nextInt(source.size()));
lc++;
} while ((this.cardCounts.get(s) > 3) && (lc <= 20));
// not an error if looped too much - could play singleton mode, with 6 slots for 3 non-basic lands.
PaperCard cp = Singletons.getMagicDb().getCommonCards().getCard(s);
tDeck.add(Singletons.getMagicDb().getCommonCards().getCard(cp.getName(), false));
final int n = this.cardCounts.get(s);
this.cardCounts.put(s, n + 1);
tmpDeck.append(s + "\n");
res++;
}
return res;
}
protected void addBasicLand(int cnt) {
tmpDeck.append(cnt).append(" basic lands remain").append("\n");
// attempt to optimize basic land counts according to colors of picked cards
final Map<String, Integer> clrCnts = countLands(tDeck);
// total of all ClrCnts
float totalColor = 0;
for (Entry<String, Integer> c : clrCnts.entrySet()) {
totalColor += c.getValue();
tmpDeck.append(c.getKey()).append(":").append(c.getValue()).append("\n");
}
tmpDeck.append("totalColor:").append(totalColor).append("\n");
int landsLeft = cnt;
for (Entry<String, Integer> c : clrCnts.entrySet()) {
String color = c.getKey();
// calculate number of lands for each color
final int nLand = Math.min(landsLeft, Math.round(cnt * c.getValue() / totalColor));
tmpDeck.append("nLand-").append(color).append(":").append(nLand).append("\n");
// just to prevent a null exception by the deck size fixing code
this.cardCounts.put(color, nLand);
PaperCard cp = Singletons.getMagicDb().getCommonCards().getCard(color);
String basicLandSet = cp.getEdition();
tDeck.add(Singletons.getMagicDb().getCommonCards().getCard(cp.getName(), basicLandSet), nLand);
landsLeft -= nLand;
}
}
protected void adjustDeckSize(int targetSize) {
// fix under-sized or over-sized decks, due to integer arithmetic
int actualSize = tDeck.countAll();
if (actualSize < targetSize) {
final int diff = targetSize - actualSize;
addSome(diff, tDeck.toFlatList());
} else if (actualSize > targetSize) {
Predicate<PaperCard> exceptBasicLand = Predicates.not(Predicates.compose(CardRulesPredicates.Presets.IS_BASIC_LAND, PaperCard.FN_GET_RULES));
for (int i = 0; i < 3 && actualSize > targetSize; i++) {
Iterable<PaperCard> matchingCards = Iterables.filter(tDeck.toFlatList(), exceptBasicLand);
List<PaperCard> toRemove = Aggregates.random(matchingCards, actualSize - targetSize);
tDeck.removeAllFlat(toRemove);
for (PaperCard c : toRemove) {
tmpDeck.append("Removed:").append(c.getName()).append("\n");
}
actualSize = tDeck.countAll();
}
}
}
protected void addCmcAdjusted(Iterable<PaperCard> source, int cnt, List<ImmutablePair<FilterCMC, Integer>> cmcLevels) {
int totalWeight = 0;
for (ImmutablePair<FilterCMC, Integer> pair : cmcLevels) {
totalWeight += pair.getRight();
}
float variability = 0.6f; // if set to 1, you'll get minimum cards to choose from
float desiredWeight = (float)cnt / ( maxDuplicates * variability );
float desiredOverTotal = desiredWeight / totalWeight;
float requestedOverTotal = (float)cnt / totalWeight;
for (ImmutablePair<FilterCMC, Integer> pair : cmcLevels) {
Iterable<PaperCard> matchingCards = Iterables.filter(source, Predicates.compose(pair.getLeft(), PaperCard.FN_GET_RULES));
int cmcCountForPool = (int) Math.ceil(pair.getRight().intValue() * desiredOverTotal);
int addOfThisCmc = Math.round(pair.getRight().intValue() * requestedOverTotal);
tmpDeck.append(String.format("Adding %d cards for cmc range from a pool with %d cards:%n", addOfThisCmc, cmcCountForPool));
final List<PaperCard> curved = Aggregates.random(matchingCards, cmcCountForPool);
final List<PaperCard> curvedRandomized = Lists.newArrayList();
for (PaperCard c : curved) {
this.cardCounts.put(c.getName(), 0);
curvedRandomized.add(Singletons.getMagicDb().getCommonCards().getCard(c.getName(), false));
}
addSome(addOfThisCmc, curvedRandomized);
}
}
protected Iterable<PaperCard> selectCardsOfMatchingColorForPlayer(boolean forAi) {
// start with all cards
// remove cards that generated decks don't like
Predicate<CardRules> canPlay = forAi ? GenerateDeckUtil.AI_CAN_PLAY : GenerateDeckUtil.HUMAN_CAN_PLAY;
Predicate<CardRules> hasColor = new GenerateDeckUtil.MatchColorIdentity(colors);
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)) {
hasColor = Predicates.or(hasColor, GenerateDeckUtil.COLORLESS_CARDS);
}
return Iterables.filter(Singletons.getMagicDb().getCommonCards().getAllCards(), Predicates.compose(Predicates.and(canPlay, hasColor), PaperCard.FN_GET_RULES));
}
protected static Map<String, Integer> countLands(ItemPool<PaperCard> outList) {
// attempt to optimize basic land counts according
// to color representation
Map<String, Integer> res = new TreeMap<String, Integer>();
// count each card color using mana costs
// TODO: count hybrid mana differently?
for (Entry<PaperCard, Integer> cpe : outList) {
int profile = cpe.getKey().getRules().getManaCost().getColorProfile();
if ((profile & MagicColor.WHITE) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(0), cpe.getValue());
} else if ((profile & MagicColor.BLUE) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(1), cpe.getValue());
} else if ((profile & MagicColor.BLACK) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(2), cpe.getValue());
} else if ((profile & MagicColor.RED) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(3), cpe.getValue());
} else if ((profile & MagicColor.GREEN) != 0) {
increment(res, MagicColor.Constant.BASIC_LANDS.get(4), cpe.getValue());
}
}
return res;
}
protected static void increment(Map<String, Integer> map, String key, int delta)
{
final Integer boxed = map.get(key);
map.put(key, boxed == null ? delta : boxed.intValue() + delta);
}
}

View File

@@ -1,173 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.google.common.base.Predicate;
import forge.card.CardRules;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.card.mana.ManaCost;
/**
* <p>
* GenerateDeckUtil class.
* </p>
*
* @author Forge
* @version $Id: GenerateDeckUtil.java 10011 2011-08-28 12:20:52Z Sloth $
*/
public class GenerateDeckUtil {
public static final Predicate<CardRules> AI_CAN_PLAY = new Predicate<CardRules>() {
@Override
public boolean apply(CardRules c) {
return !c.getAiHints().getRemAIDecks() && !c.getAiHints().getRemRandomDecks();
}
};
public static final Predicate<CardRules> HUMAN_CAN_PLAY = new Predicate<CardRules>() {
@Override
public boolean apply(CardRules c) {
return !c.getAiHints().getRemRandomDecks();
}
};
public static final Predicate<CardRules> COLORLESS_CARDS = new Predicate<CardRules>() {
@Override
public boolean apply(CardRules c) {
ManaCost mc = c.getManaCost();
return c.getColorIdentity().isColorless() && !mc.isNoCost();
}
};
public static class MatchColorIdentity implements Predicate<CardRules> {
private final ColorSet allowedColor;
public MatchColorIdentity(ColorSet color) {
allowedColor = color;
}
@Override
public boolean apply(CardRules subject) {
ManaCost mc = subject.getManaCost();
return !mc.isPureGeneric() && allowedColor.containsAllColorsFrom(subject.getColorIdentity().getColor());
//return mc.canBePaidWithAvaliable(allowedColor);
// return allowedColor.containsAllColorsFrom(mc.getColorProfile());
}
}
public static class FilterCMC implements Predicate<CardRules> {
private final int min;
private final int max;
public FilterCMC(int from, int to) {
min = from;
max = to;
}
@Override
public boolean apply(CardRules c) {
ManaCost mc = c.getManaCost();
int cmc = mc.getCMC();
return cmc >= min && cmc <= max && !mc.isNoCost();
}
}
private static Map<Integer, String[]> dualLands = new HashMap<Integer, String[]>();
static {
dualLands.put(MagicColor.WHITE | MagicColor.BLUE, new String[] { "Tundra", "Hallowed Fountain", "Flooded Strand",
"Azorius Guildgate" });
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",
"Rakdos Guildgate" });
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",
"Selesnya Guildgate" });
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",
"Izzet Guildgate" });
dualLands.put(MagicColor.BLACK | MagicColor.GREEN, new String[] { "Bayou", "Overgrown Tomb", "Verdant Catacombs",
"Golgari Guildgate" });
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" });
}
/**
* Get list of dual lands for this color combo.
*
* @param color
* the color
* @return dual land names
*/
public static List<String> getDualLandList(final ColorSet color) {
final List<String> dLands = new ArrayList<String>();
if (color.countColors() > 3) {
dLands.add("Rupture Spire");
dLands.add("Undiscovered Paradise");
}
if (color.countColors() > 2) {
dLands.add("Evolving Wilds");
dLands.add("Terramorphic Expanse");
}
for (Entry<Integer, String[]> dual : dualLands.entrySet()) {
if (color.hasAllColors(dual.getKey())) {
for (String s : dual.getValue()) {
dLands.add(s);
}
}
}
return dLands;
}
/**
* Get all dual lands that do not match this color combo.
*
* @param color
* the color
* @return dual land names
*/
public static List<String> getInverseDualLandList(final ColorSet color) {
final List<String> dLands = new ArrayList<String>();
for (Entry<Integer, String[]> dual : dualLands.entrySet()) {
if (!color.hasAllColors(dual.getKey())) {
for (String s : dual.getValue()) {
dLands.add(s);
}
}
}
return dLands;
}
}

View File

@@ -1,97 +0,0 @@
/*
* Forge: Play Magic: the Gathering.
* Copyright (C) 2011 Forge Team
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
import java.util.List;
import org.apache.commons.lang3.tuple.ImmutablePair;
import com.google.common.collect.Lists;
import forge.card.ColorSet;
import forge.card.MagicColor;
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
/**
* <p>
* Generate2ColorDeck class.
* </p>
*
* @author Forge
* @version $Id: Generate2ColorDeck.java 19765 2013-02-20 03:01:37Z myk $
*/
public class GenerateMonoColorDeck extends GenerateColoredDeckBase {
@Override protected final float getLandsPercentage() { return 0.39f; }
@Override protected final float getCreatPercentage() { return 0.36f; }
@Override protected final float getSpellPercentage() { return 0.25f; }
@SuppressWarnings("unchecked")
final List<ImmutablePair<FilterCMC, Integer>> cmcLevels = Lists.newArrayList(
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(0, 2), 10),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(3, 4), 8),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(5, 6), 5),
ImmutablePair.of(new GenerateDeckUtil.FilterCMC(7, 20), 3)
);
// mana curve of the card pool
// 20x 0 - 2
// 16x 3 - 4
// 12x 5 - 6
// 4x 7 - 20
// = 52x - card pool (before further random filtering)
/**
* <p>
* Constructor for Generate2ColorDeck.
* </p>
*
* @param clr1
* a {@link java.lang.String} object.
* @param clr2
* a {@link java.lang.String} object.
*/
public GenerateMonoColorDeck(final String clr1) {
if (MagicColor.fromName(clr1) == 0) {
int color1 = r.nextInt(5);
colors = ColorSet.fromMask(MagicColor.WHITE << color1);
} else {
colors = ColorSet.fromNames(clr1);
}
}
@Override
public final ItemPoolView<PaperCard> getDeck(final int size, final boolean forAi) {
addCreaturesAndSpells(size, cmcLevels, forAi);
// Add lands
int numLands = (int) (getLandsPercentage() * size);
tmpDeck.append("numLands:").append(numLands).append("\n");
addBasicLand(numLands);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
adjustDeckSize(size);
tmpDeck.append("DeckSize:").append(tDeck.countAll()).append("\n");
return tDeck;
}
}

View File

@@ -1,3 +0,0 @@
/** Forge Card Game. */
package forge.deck.generate;

View File

@@ -17,7 +17,7 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.Singletons;
import forge.Constant.Preferences;
import forge.card.CardAiHints;
import forge.card.CardEdition;
import forge.card.CardEditionPredicates;
@@ -31,20 +31,21 @@ import forge.card.mana.ManaCostShard;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.deck.generate.GenerateDeckUtil;
import forge.deck.generation.DeckGeneratorBase;
import forge.item.PaperCard;
import forge.item.IPaperCard;
import forge.util.ItemPoolView;
import forge.util.MyRandom;
/**
* Limited format deck.
*
*/
public class LimitedDeckBuilder {
public class LimitedDeckBuilder extends DeckGeneratorBase{
private int numSpellsNeeded = 22;
private int landsNeeded = 18;
private ColorSet colors;
private final DeckColors deckColors;
private Predicate<CardRules> hasColor;
private final List<PaperCard> availableList;
@@ -59,6 +60,8 @@ public class LimitedDeckBuilder {
private static ReadDraftRankings draftRankings = new ReadDraftRankings();
private static final boolean logToConsole = false;
/**
*
* Constructor.
@@ -69,6 +72,7 @@ public class LimitedDeckBuilder {
* Chosen colors.
*/
public LimitedDeckBuilder(List<PaperCard> dList, DeckColors pClrs) {
super(Singletons.getMagicDb().getCommonCards());
this.availableList = dList;
this.deckColors = pClrs;
this.colors = pClrs.getChosenColors();
@@ -93,6 +97,11 @@ public class LimitedDeckBuilder {
this(list, new DeckColors());
}
@Override
public ItemPoolView<PaperCard> getDeck(int size, boolean forAi) {
return buildDeck().getMain();
}
/**
* <p>
* buildDeck.
@@ -102,7 +111,7 @@ public class LimitedDeckBuilder {
*/
public Deck buildDeck() {
// 1. Prepare
hasColor = Predicates.or(new GenerateDeckUtil.MatchColorIdentity(colors), GenerateDeckUtil.COLORLESS_CARDS);
hasColor = Predicates.or(new MatchColorIdentity(colors), COLORLESS_CARDS);
colorList = Iterables.filter(aiPlayables, Predicates.compose(hasColor, PaperCard.FN_GET_RULES));
onColorCreatures = Iterables.filter(colorList,
Predicates.compose(CardRulesPredicates.Presets.IS_CREATURE, PaperCard.FN_GET_RULES));
@@ -144,7 +153,7 @@ public class LimitedDeckBuilder {
deckList.add(c);
getAiPlayables().remove(c);
landsNeeded--;
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Low CMC: " + c.getName());
}
}
@@ -178,7 +187,7 @@ public class LimitedDeckBuilder {
CardPool cp = result.getOrCreate(DeckSection.Sideboard);
cp.add(aiPlayables);
cp.add(availableList);
if (Preferences.DEV_MODE) {
if (logToConsole) {
debugFinalDeck();
}
return result;
@@ -301,7 +310,7 @@ public class LimitedDeckBuilder {
// calculate number of lands for each color
final float p = (float) clrCnts[i] / (float) totalColor;
final int nLand = Math.round(landsNeeded * p); // desired truncation to int
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.printf("Basics[%s]: %d/%d = %f%% = %d cards%n", MagicColor.Constant.BASIC_LANDS.get(i), clrCnts[i], totalColor, 100*p, nLand);
}
@@ -359,7 +368,7 @@ public class LimitedDeckBuilder {
* Add non-basic lands to the deck.
*/
private void addNonBasicLands() {
List<String> inverseDuals = GenerateDeckUtil.getInverseDualLandList(colors);
List<String> inverseDuals = getInverseDualLandList();
Iterable<PaperCard> lands = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NONBASIC_LAND, PaperCard.FN_GET_RULES));
List<Pair<Double, PaperCard>> ranked = rankCards(lands);
@@ -374,7 +383,7 @@ public class LimitedDeckBuilder {
deckList.add(bean.getValue());
aiPlayables.remove(bean.getValue());
landsNeeded--;
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("NonBasicLand[" + landsNeeded + "]:" + bean.getValue().getName());
}
}
@@ -401,8 +410,8 @@ public class LimitedDeckBuilder {
}
}
hasColor = Predicates.or(new GenerateDeckUtil.MatchColorIdentity(colors),
GenerateDeckUtil.COLORLESS_CARDS);
hasColor = Predicates.or(new DeckGeneratorBase.MatchColorIdentity(colors),
DeckGeneratorBase.COLORLESS_CARDS);
Iterable<PaperCard> threeColorList = Iterables.filter(aiPlayables,
Predicates.compose(hasColor, PaperCard.FN_GET_RULES));
ranked = rankCards(threeColorList);
@@ -411,7 +420,7 @@ public class LimitedDeckBuilder {
deckList.add(bean.getValue());
aiPlayables.remove(bean.getValue());
nCards--;
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Third Color[" + nCards + "]:" + bean.getValue().getName() + "("
+ bean.getValue().getRules().getManaCost() + ")");
}
@@ -436,7 +445,7 @@ public class LimitedDeckBuilder {
deckList.add(bean.getValue());
aiPlayables.remove(bean.getValue());
nCards--;
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Random[" + nCards + "]:" + bean.getValue().getName() + "("
+ bean.getValue().getRules().getManaCost() + ")");
}
@@ -460,7 +469,7 @@ public class LimitedDeckBuilder {
deckList.add(cardToAdd);
num--;
getAiPlayables().remove(cardToAdd);
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Others[" + num + "]:" + cardToAdd.getName() + " ("
+ cardToAdd.getRules().getManaCost() + ")");
}
@@ -486,7 +495,7 @@ public class LimitedDeckBuilder {
if (hints != null && hints.getType() != DeckHints.Type.NONE) {
Iterable<PaperCard> onColor = Iterables.filter(aiPlayables, Predicates.compose(hasColor, PaperCard.FN_GET_RULES));
List<PaperCard> comboCards = hints.filter(onColor);
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Found " + comboCards.size() + " cards for " + cardToAdd.getName());
}
for (Pair<Double, PaperCard> comboBean : rankCards(comboCards)) {
@@ -535,7 +544,7 @@ public class LimitedDeckBuilder {
comboCards.addAll(hints.filter(deckList));
}
if (comboCards.isEmpty()) {
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("No combo cards found for " + card.getName() + ", removing it.");
}
it.remove();
@@ -546,7 +555,7 @@ public class LimitedDeckBuilder {
numOthers++;
}
} else {
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Found " + comboCards.size() + " cards for " + card.getName());
}
}
@@ -580,7 +589,7 @@ public class LimitedDeckBuilder {
deckList.add(c);
num--;
getAiPlayables().remove(c);
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Creature[" + num + "]:" + c.getName() + " (" + c.getRules().getManaCost() + ")");
}
num = addDeckHintsCards(c, num);
@@ -645,12 +654,12 @@ public class LimitedDeckBuilder {
num--;
getAiPlayables().remove(c);
creatureCosts.put(cmc, creatureCosts.get(cmc) + 1);
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println("Creature[" + num + "]:" + c.getName() + " (" + c.getRules().getManaCost() + ")");
}
num = addDeckHintsCards(c, num);
} else {
if (Preferences.DEV_MODE) {
if (logToConsole) {
System.out.println(c.getName() + " not added because CMC " + c.getRules().getManaCost().getCMC()
+ " has " + currentAtCmc + " already.");
}

View File

@@ -1,4 +1,4 @@
package forge.deck;
package forge.gui.deckchooser;
import java.awt.Toolkit;
import java.awt.datatransfer.StringSelection;
@@ -15,14 +15,17 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.Singletons;
import forge.deck.generate.Generate2ColorDeck;
import forge.deck.generate.Generate3ColorDeck;
import forge.deck.generate.Generate5ColorDeck;
import forge.deck.generate.GenerateColoredDeckBase;
import forge.deck.generate.GenerateMonoColorDeck;
import forge.deck.generate.GenerateThemeDeck;
import forge.card.CardDb;
import forge.deck.CardPool;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.deck.generation.DeckGenerator2Color;
import forge.deck.generation.DeckGenerator3Color;
import forge.deck.generation.DeckGenerator5Color;
import forge.deck.generation.DeckGeneratorBase;
import forge.deck.generation.DeckGeneratorMonoColor;
import forge.item.PaperCard;
import forge.item.PreconDeck;
import forge.properties.ForgePreferences.FPref;
import forge.quest.QuestController;
import forge.quest.QuestEvent;
import forge.quest.QuestEventChallenge;
@@ -60,19 +63,20 @@ public class DeckgenUtil {
final Deck deck;
String deckName = null;
GenerateColoredDeckBase gen = null;
DeckGeneratorBase gen = null;
CardDb cardDb = Singletons.getMagicDb().getCommonCards();
if (selection.size() == 1) {
gen = new GenerateMonoColorDeck(selection.get(0));
gen = new DeckGeneratorMonoColor(cardDb, selection.get(0));
} else if (selection.size() == 2) {
gen = new Generate2ColorDeck(selection.get(0), selection.get(1));
gen = new DeckGenerator2Color(cardDb, selection.get(0), selection.get(1));
} else if (selection.size() == 3) {
gen = new Generate3ColorDeck(selection.get(0), selection.get(1), selection.get(2));
gen = new DeckGenerator3Color(cardDb, selection.get(0), selection.get(1), selection.get(2));
} else {
gen = new Generate5ColorDeck();
gen = new DeckGenerator5Color(cardDb);
deckName = "5 colors";
}
gen.setSingleton(Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS));
gen.setUseArtifacts(Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
ItemPoolView<PaperCard> cards = gen == null ? null : gen.getDeck(60, forAi);
if(null == deckName)
@@ -92,6 +96,8 @@ public class DeckgenUtil {
public static Deck buildThemeDeck(final String selection) {
final GenerateThemeDeck gen = new GenerateThemeDeck();
final Deck deck = new Deck();
gen.setSingleton(Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS));
gen.setUseArtifacts(Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
deck.getMain().addAll(gen.getThemeDeck(selection, 60));
return deck;
@@ -162,13 +168,6 @@ public class DeckgenUtil {
final String name = allDecks.getItemNames().toArray(new String[0])[rand];
return allDecks.get(name);
}
public static Deck getRandomPreconDeck() {
final IStorage<PreconDeck> allDecks = QuestController.getPrecons();
final int rand = (int) (Math.floor(Math.random() * allDecks.size()));
final String name = allDecks.getItemNames().toArray(new String[0])[rand];
return allDecks.get(name).getDeck();
}
/** @return {@link forge.deck.Deck} */
public static Deck getRandomQuestDeck() {

View File

@@ -22,8 +22,6 @@ import org.apache.commons.lang3.ArrayUtils;
import forge.Command;
import forge.Singletons;
import forge.deck.Deck;
import forge.deck.DeckgenUtil;
import forge.deck.generate.GenerateThemeDeck;
import forge.game.RegisteredPlayer;
import forge.gui.MouseUtil;
import forge.gui.MouseUtil.MouseCursor;

View File

@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package forge.deck.generate;
package forge.gui.deckchooser;
import java.io.File;
import java.util.ArrayList;
@@ -23,6 +23,7 @@ import java.util.List;
import java.util.Random;
import forge.Singletons;
import forge.deck.generation.DeckGeneratorBase;
import forge.error.BugReporter;
import forge.item.PaperCard;
import forge.util.FileUtil;
@@ -37,7 +38,7 @@ import forge.util.MyRandom;
* @author Forge
* @version $Id$
*/
public class GenerateThemeDeck extends GenerateColoredDeckBase {
public class GenerateThemeDeck extends DeckGeneratorBase {
private int basicLandPercentage = 0;
private boolean testing = false;
@@ -47,6 +48,7 @@ public class GenerateThemeDeck extends GenerateColoredDeckBase {
* </p>
*/
public GenerateThemeDeck() {
super(Singletons.getMagicDb().getCommonCards());
this.maxDuplicates = 4;
}

View File

@@ -38,6 +38,7 @@ import javax.swing.text.ElementIterator;
import org.apache.commons.lang3.StringUtils;
import net.miginfocom.swing.MigLayout;
import forge.Singletons;
import forge.deck.Deck;
import forge.deck.DeckBase;
import forge.deck.DeckRecognizer;
@@ -221,7 +222,7 @@ public class DeckImport<TItem extends InventoryItem, TModel extends DeckBase> ex
final ElementIterator it = new ElementIterator(this.txtInput.getDocument().getDefaultRootElement());
Element e;
DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected());
DeckRecognizer recognizer = new DeckRecognizer(newEditionCheck.isSelected(), Singletons.getMagicDb().getCommonCards());
if(dateTimeCheck.isSelected())
recognizer.setDateConstraint(monthDropdown.getSelectedIndex(), yearDropdown.getSelectedItem());

View File

@@ -6,13 +6,16 @@ import com.google.common.collect.Iterables;
import forge.Command;
import forge.Singletons;
import forge.card.CardDb;
import forge.card.CardRulesPredicates;
import forge.card.MagicColor;
import forge.deck.Deck;
import forge.deck.DeckBase;
import forge.deck.generate.Generate2ColorDeck;
import forge.deck.generate.Generate3ColorDeck;
import forge.deck.generate.Generate5ColorDeck;
import forge.deck.generation.DeckGenerator2Color;
import forge.deck.generation.DeckGenerator3Color;
import forge.deck.generation.DeckGenerator5Color;
import forge.deck.generation.DeckGeneratorBase;
import forge.deck.generation.DeckGeneratorMonoColor;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.SEditorIO;
import forge.gui.deckeditor.views.VDeckgen;
@@ -20,6 +23,7 @@ import forge.gui.framework.ICDoc;
import forge.gui.toolbox.FLabel;
import forge.item.PaperCard;
import forge.item.InventoryItem;
import forge.properties.ForgePreferences.FPref;
import forge.util.Aggregates;
@@ -100,22 +104,22 @@ public enum CDeckgen implements ICDoc {
if (!SEditorIO.confirmSaveChanges(Singletons.getControl().getCurrentScreen())) { return; }
final Deck genConstructed = new Deck();
CardDb cardDb = Singletons.getMagicDb().getCommonCards();
DeckGeneratorBase gen = null;
switch (colorCount0) {
case 2:
genConstructed.getMain().addAll((new Generate2ColorDeck(null, null)).getDeck(60, false));
break;
case 3:
genConstructed.getMain().addAll((new Generate3ColorDeck(null, null, null)).getDeck(60, false));
break;
case 5:
genConstructed.getMain().addAll((new Generate5ColorDeck()).getDeck(60, false));
break;
default:
case 1: gen = new DeckGeneratorMonoColor(cardDb, null); break;
case 2: gen = new DeckGenerator2Color(cardDb, null, null); break;
case 3: gen = new DeckGenerator3Color(cardDb, null, null, null); break;
case 5: gen = new DeckGenerator5Color(cardDb); break;
}
if( null != gen ) {
gen.setSingleton(Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS));
gen.setUseArtifacts(Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
genConstructed.getMain().addAll(gen.getDeck(60, false));
}
final ACEditorBase<TItem, TModel> ed = (ACEditorBase<TItem, TModel>)
CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController();
final ACEditorBase<TItem, TModel> ed = (ACEditorBase<TItem, TModel>) CDeckEditorUI.SINGLETON_INSTANCE.getCurrentEditorController();
ed.getDeckController().setModel((TModel) genConstructed);
}

View File

@@ -15,13 +15,13 @@ import forge.Command;
import forge.FThreads;
import forge.Singletons;
import forge.deck.Deck;
import forge.deck.DeckgenUtil;
import forge.game.GameType;
import forge.game.Match;
import forge.game.RegisteredPlayer;
import forge.gauntlet.GauntletData;
import forge.gauntlet.GauntletIO;
import forge.gui.SOverlayUtils;
import forge.gui.deckchooser.DeckgenUtil;
import forge.gui.framework.ICDoc;
import forge.net.FServer;
import forge.net.Lobby;

View File

@@ -14,14 +14,14 @@ import forge.Command;
import forge.FThreads;
import forge.Singletons;
import forge.deck.Deck;
import forge.deck.DeckgenUtil;
import forge.deck.DeckgenUtil.DeckTypes;
import forge.game.GameType;
import forge.game.Match;
import forge.game.RegisteredPlayer;
import forge.gauntlet.GauntletData;
import forge.gauntlet.GauntletIO;
import forge.gui.SOverlayUtils;
import forge.gui.deckchooser.DeckgenUtil;
import forge.gui.deckchooser.DeckgenUtil.DeckTypes;
import forge.gui.framework.ICDoc;
import forge.net.FServer;
import forge.net.Lobby;

View File

@@ -15,12 +15,12 @@ import forge.FThreads;
import forge.Singletons;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.deck.DeckgenUtil;
import forge.game.GameType;
import forge.game.Match;
import forge.game.RegisteredPlayer;
import forge.gui.GuiDialog;
import forge.gui.SOverlayUtils;
import forge.gui.deckchooser.DeckgenUtil;
import forge.gui.deckchooser.FDeckChooser;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.controllers.CEditorVariant;

View File

@@ -15,13 +15,13 @@ import forge.FThreads;
import forge.Singletons;
import forge.deck.Deck;
import forge.deck.DeckSection;
import forge.deck.DeckgenUtil;
import forge.game.GameType;
import forge.game.Match;
import forge.game.RegisteredPlayer;
import forge.game.player.LobbyPlayer;
import forge.gui.GuiDialog;
import forge.gui.SOverlayUtils;
import forge.gui.deckchooser.DeckgenUtil;
import forge.gui.deckchooser.FDeckChooser;
import forge.gui.deckeditor.CDeckEditorUI;
import forge.gui.deckeditor.controllers.CEditorVariant;

View File

@@ -3,6 +3,9 @@ package forge.deck.generate;
import org.testng.Assert;
import org.testng.annotations.Test;
import forge.Singletons;
import forge.card.CardDb;
import forge.deck.generation.DeckGenerator2Color;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
@@ -17,7 +20,8 @@ public class Generate2ColorDeckTest {
*/
@Test(enabled = false)
public void generate2ColorDeckTest1() {
final Generate2ColorDeck gen = new Generate2ColorDeck("white", "blue");
CardDb cardDb = Singletons.getMagicDb().getCommonCards();
final DeckGenerator2Color gen = new DeckGenerator2Color(cardDb, "white", "blue");
final ItemPoolView<PaperCard> cardList = gen.getDeck(60, false);
Assert.assertNotNull(cardList);
}

View File

@@ -3,6 +3,9 @@ package forge.deck.generate;
import org.testng.Assert;
import org.testng.annotations.Test;
import forge.Singletons;
import forge.card.CardDb;
import forge.deck.generation.DeckGenerator3Color;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
@@ -17,7 +20,8 @@ public class Generate3ColorDeckTest {
*/
@Test(timeOut = 1000, enabled = false)
public void generate3ColorDeckTest1() {
final Generate3ColorDeck gen = new Generate3ColorDeck("white", "blue", "black");
CardDb cardDb = Singletons.getMagicDb().getCommonCards();
final DeckGenerator3Color gen = new DeckGenerator3Color(cardDb, "white", "blue", "black");
final ItemPoolView<PaperCard> cardList = gen.getDeck(60, false);
Assert.assertNotNull(cardList);
}

View File

@@ -3,6 +3,9 @@ package forge.deck.generate;
import org.testng.Assert;
import org.testng.annotations.Test;
import forge.Singletons;
import forge.card.CardDb;
import forge.deck.generation.DeckGenerator5Color;
import forge.item.PaperCard;
import forge.util.ItemPoolView;
@@ -17,7 +20,8 @@ public class Generate5ColorDeckTest {
*/
@Test(timeOut = 1000, enabled = false)
public void generate5ColorDeckTest1() {
final Generate5ColorDeck gen = new Generate5ColorDeck();
CardDb cardDb = Singletons.getMagicDb().getCommonCards();
final DeckGenerator5Color gen = new DeckGenerator5Color(cardDb);
final ItemPoolView<PaperCard> cardList = gen.getDeck(60, false);
Assert.assertNotNull(cardList);
}