mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +00:00
Deck generation uses CardPrinted
This commit is contained in:
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -11623,9 +11623,11 @@ src/main/java/forge/deck/DeckBase.java -text
|
|||||||
src/main/java/forge/deck/DeckGroup.java -text
|
src/main/java/forge/deck/DeckGroup.java -text
|
||||||
src/main/java/forge/deck/DeckRecognizer.java -text
|
src/main/java/forge/deck/DeckRecognizer.java -text
|
||||||
src/main/java/forge/deck/DeckSection.java -text
|
src/main/java/forge/deck/DeckSection.java -text
|
||||||
|
src/main/java/forge/deck/generate/CCnt.java -text
|
||||||
src/main/java/forge/deck/generate/Generate2ColorDeck.java svneol=native#text/plain
|
src/main/java/forge/deck/generate/Generate2ColorDeck.java svneol=native#text/plain
|
||||||
src/main/java/forge/deck/generate/Generate3ColorDeck.java svneol=native#text/plain
|
src/main/java/forge/deck/generate/Generate3ColorDeck.java svneol=native#text/plain
|
||||||
src/main/java/forge/deck/generate/Generate5ColorDeck.java svneol=native#text/plain
|
src/main/java/forge/deck/generate/Generate5ColorDeck.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/deck/generate/GenerateColoredDeckBase.java -text
|
||||||
src/main/java/forge/deck/generate/GenerateDeckUtil.java -text
|
src/main/java/forge/deck/generate/GenerateDeckUtil.java -text
|
||||||
src/main/java/forge/deck/generate/GenerateThemeDeck.java svneol=native#text/plain
|
src/main/java/forge/deck/generate/GenerateThemeDeck.java svneol=native#text/plain
|
||||||
src/main/java/forge/deck/generate/package-info.java svneol=native#text/plain
|
src/main/java/forge/deck/generate/package-info.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -29,19 +29,10 @@ import forge.Constant;
|
|||||||
*/
|
*/
|
||||||
public final class CardColor implements Comparable<CardColor> {
|
public final class CardColor implements Comparable<CardColor> {
|
||||||
|
|
||||||
/** The Constant WHITE. */
|
|
||||||
public static final byte WHITE = 1 << 1;
|
public static final byte WHITE = 1 << 1;
|
||||||
|
|
||||||
/** The Constant BLUE. */
|
|
||||||
public static final byte BLUE = 1 << 2;
|
public static final byte BLUE = 1 << 2;
|
||||||
|
|
||||||
/** The Constant BLACK. */
|
|
||||||
public static final byte BLACK = 1 << 3;
|
public static final byte BLACK = 1 << 3;
|
||||||
|
|
||||||
/** The Constant RED. */
|
|
||||||
public static final byte RED = 1 << 4;
|
public static final byte RED = 1 << 4;
|
||||||
|
|
||||||
/** The Constant GREEN. */
|
|
||||||
public static final byte GREEN = 1 << 5;
|
public static final byte GREEN = 1 << 5;
|
||||||
|
|
||||||
private final byte myColor;
|
private final byte myColor;
|
||||||
@@ -56,8 +47,34 @@ public final class CardColor implements Comparable<CardColor> {
|
|||||||
* the mana
|
* the mana
|
||||||
*/
|
*/
|
||||||
public CardColor(final CardManaCost mana) {
|
public CardColor(final CardManaCost mana) {
|
||||||
this.myColor = mana.getColorProfile();
|
this(mana.getColorProfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
private CardColor(final byte mask) {
|
||||||
|
this.myColor = mask;
|
||||||
this.orderWeight = this.getOrderWeight();
|
this.orderWeight = this.getOrderWeight();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CardColor fromMask(int mask) {
|
||||||
|
return new CardColor((byte)mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CardColor fromNames(String... colors) {
|
||||||
|
byte mask = 0;
|
||||||
|
for(String s : colors) {
|
||||||
|
if ( s.equalsIgnoreCase(Constant.Color.WHITE) || s.equalsIgnoreCase("w"))
|
||||||
|
mask |= WHITE;
|
||||||
|
if ( s.equalsIgnoreCase(Constant.Color.BLUE) || s.equalsIgnoreCase("u"))
|
||||||
|
mask |= BLUE;
|
||||||
|
if ( s.equalsIgnoreCase(Constant.Color.BLACK) || s.equalsIgnoreCase("b"))
|
||||||
|
mask |= BLACK;
|
||||||
|
if ( s.equalsIgnoreCase(Constant.Color.RED) || s.equalsIgnoreCase("r"))
|
||||||
|
mask |= RED;
|
||||||
|
if ( s.equalsIgnoreCase(Constant.Color.GREEN) || s.equalsIgnoreCase("g"))
|
||||||
|
mask |= GREEN;
|
||||||
|
}
|
||||||
|
return fromMask(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
private CardColor() {
|
private CardColor() {
|
||||||
@@ -66,7 +83,7 @@ public final class CardColor implements Comparable<CardColor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The null color. */
|
/** The null color. */
|
||||||
private static CardColor nullColor = new CardColor();
|
private static final CardColor nullColor = new CardColor();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks for any color.
|
* Checks for any color.
|
||||||
@@ -75,7 +92,7 @@ public final class CardColor implements Comparable<CardColor> {
|
|||||||
* the colormask
|
* the colormask
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
public boolean hasAnyColor(final byte colormask) {
|
public boolean hasAnyColor(final int colormask) {
|
||||||
return (this.myColor & colormask) != 0;
|
return (this.myColor & colormask) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,10 +103,21 @@ public final class CardColor implements Comparable<CardColor> {
|
|||||||
* the colormask
|
* the colormask
|
||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
public boolean hasAllColors(final byte colormask) {
|
public boolean hasAllColors(final int colormask) {
|
||||||
return (this.myColor & colormask) == colormask;
|
return (this.myColor & colormask) == colormask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** this has no other colors except defined by operand */
|
||||||
|
public boolean hasNoColorsExcept(final int colormask) {
|
||||||
|
return (this.myColor & ~colormask) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Operand has no other colors except defined by this */
|
||||||
|
public boolean containsAllColorsFrom(int colorProfile) {
|
||||||
|
return (~this.myColor & colorProfile) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Count colors.
|
* Count colors.
|
||||||
*
|
*
|
||||||
@@ -254,6 +282,12 @@ public final class CardColor implements Comparable<CardColor> {
|
|||||||
return this.isEqual(CardColor.GREEN);
|
return this.isEqual(CardColor.GREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CardColor inverse() {
|
||||||
|
byte mask = this.myColor;
|
||||||
|
mask ^= ( WHITE | BLUE | BLACK | GREEN | RED );
|
||||||
|
return fromMask(mask);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* (non-Javadoc)
|
* (non-Javadoc)
|
||||||
*
|
*
|
||||||
@@ -291,16 +325,6 @@ public final class CardColor implements Comparable<CardColor> {
|
|||||||
return CardColor.nullColor;
|
return CardColor.nullColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the null color.
|
|
||||||
*
|
|
||||||
* @param nullColor0
|
|
||||||
* the nullColor to set
|
|
||||||
*/
|
|
||||||
public static void setNullColor(final CardColor nullColor0) {
|
|
||||||
CardColor.nullColor = nullColor0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shares color with.
|
* Shares color with.
|
||||||
*
|
*
|
||||||
@@ -308,27 +332,6 @@ public final class CardColor implements Comparable<CardColor> {
|
|||||||
* @return true, if successful
|
* @return true, if successful
|
||||||
*/
|
*/
|
||||||
public boolean sharesColorWith(CardColor ccOther) {
|
public boolean sharesColorWith(CardColor ccOther) {
|
||||||
|
return ( this.myColor & ccOther.myColor ) != 0;
|
||||||
if (this.isWhite() && ccOther.isWhite()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isBlue() && ccOther.isBlue()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isBlack() && ccOther.isBlack()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isRed() && ccOther.isRed()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isGreen() && ccOther.isGreen()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import java.util.Collections;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import forge.card.cost.CostMana;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* CardManaCost class.
|
* CardManaCost class.
|
||||||
@@ -40,14 +42,16 @@ public final class CardManaCost implements Comparable<CardManaCost> {
|
|||||||
private Float compareWeight = null;
|
private Float compareWeight = null;
|
||||||
|
|
||||||
/** The Constant empty. */
|
/** The Constant empty. */
|
||||||
public static final CardManaCost EMPTY = new CardManaCost();
|
public static final CardManaCost EMPTY = new CardManaCost(-1);
|
||||||
|
public static final CardManaCost ZERO = new CardManaCost(0);
|
||||||
|
public static final CardManaCost ONE = new CardManaCost(1);
|
||||||
|
|
||||||
// pass mana cost parser here
|
// pass mana cost parser here
|
||||||
private CardManaCost() {
|
private CardManaCost(int cmc) {
|
||||||
this.hasNoCost = true;
|
this.hasNoCost = cmc < 0;
|
||||||
this.genericCost = 0;
|
this.genericCost = cmc < 0 ? 0 : cmc;
|
||||||
this.stringValue = "";
|
|
||||||
this.shards = Collections.unmodifiableList(new ArrayList<CardManaCostShard>());
|
this.shards = Collections.unmodifiableList(new ArrayList<CardManaCostShard>());
|
||||||
|
this.stringValue = this.getSimpleString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// public ctor, should give it a mana parser
|
// public ctor, should give it a mana parser
|
||||||
@@ -208,4 +212,29 @@ public final class CardManaCost implements Comparable<CardManaCost> {
|
|||||||
int getTotalColorlessCost();
|
int getTotalColorlessCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write javadoc for this method.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean hasPhyrexian() {
|
||||||
|
for(CardManaCostShard shard : shards) {
|
||||||
|
if ( shard.isPhyrexian() )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write javadoc for this method.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int countX() {
|
||||||
|
int iX = 0;
|
||||||
|
for(CardManaCostShard shard : shards) {
|
||||||
|
if ( shard == CardManaCostShard.X )
|
||||||
|
iX++;
|
||||||
|
}
|
||||||
|
return iX;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -317,4 +317,12 @@ public class CardManaCostShard {
|
|||||||
public String getImageKey() {
|
public String getImageKey() {
|
||||||
return this.imageKey;
|
return this.imageKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Write javadoc for this method.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isPhyrexian() {
|
||||||
|
return (this.shard & Atom.OR_2_LIFE) != 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,13 +18,12 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import forge.util.Predicate;
|
import forge.util.Predicate;
|
||||||
@@ -809,6 +808,12 @@ public final class CardRules {
|
|||||||
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL = Predicate.compose(Presets.IS_CREATURE,
|
public static final Predicate<CardRules> IS_NON_CREATURE_SPELL = Predicate.compose(Presets.IS_CREATURE,
|
||||||
PredicatesOp.NOR, Presets.IS_LAND);
|
PredicatesOp.NOR, Presets.IS_LAND);
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static final Predicate<CardRules> isNonCreatureSpellForGenerator = Predicate.or( Arrays.asList(
|
||||||
|
Presets.IS_SORCERY, Presets.IS_INSTANT, Presets.IS_PLANESWALKER, Presets.IS_ENCHANTMENT,
|
||||||
|
Predicate.compose(Presets.IS_ARTIFACT, PredicatesOp.GT, Presets.IS_CREATURE ))
|
||||||
|
);
|
||||||
|
|
||||||
/** The Constant isWhite. */
|
/** The Constant isWhite. */
|
||||||
public static final Predicate<CardRules> IS_WHITE = Predicates.isColor(CardColor.WHITE);
|
public static final Predicate<CardRules> IS_WHITE = Predicates.isColor(CardColor.WHITE);
|
||||||
|
|
||||||
|
|||||||
83
src/main/java/forge/deck/generate/CCnt.java
Normal file
83
src/main/java/forge/deck/generate/CCnt.java
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
package forge.deck.generate;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* CCnt class.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Forge
|
||||||
|
* @version $Id: CCnt.java 12850 2011-12-26 14:55:09Z slapshot5 $
|
||||||
|
*/
|
||||||
|
public class CCnt {
|
||||||
|
|
||||||
|
/** The Color. */
|
||||||
|
public final String Color;
|
||||||
|
|
||||||
|
/** The Count. */
|
||||||
|
private int count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Constructor for CCnt.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clr
|
||||||
|
* a {@link java.lang.String} object.
|
||||||
|
* @param cnt
|
||||||
|
* a int.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* deckColors class.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clr
|
||||||
|
* a {@link java.lang.String} object.
|
||||||
|
* @param cnt
|
||||||
|
* a int.
|
||||||
|
*/
|
||||||
|
public CCnt(final String clr, final int cnt) {
|
||||||
|
Color = clr;
|
||||||
|
this.setCount(cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the count.
|
||||||
|
*
|
||||||
|
* @return the count
|
||||||
|
*/
|
||||||
|
public int getCount() {
|
||||||
|
return this.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the count.
|
||||||
|
*
|
||||||
|
* @param count0
|
||||||
|
* the count to set
|
||||||
|
*/
|
||||||
|
public void setCount(final int count0) {
|
||||||
|
this.count = count0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increment() { this.count++; }
|
||||||
|
public void increment(int amount) { this.count += amount; }
|
||||||
|
}
|
||||||
@@ -17,23 +17,17 @@
|
|||||||
*/
|
*/
|
||||||
package forge.deck.generate;
|
package forge.deck.generate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import forge.AllZone;
|
|
||||||
import forge.Card;
|
|
||||||
import forge.CardList;
|
|
||||||
import forge.CardListFilter;
|
|
||||||
import forge.Constant;
|
|
||||||
import forge.PlayerType;
|
import forge.PlayerType;
|
||||||
import forge.Singletons;
|
import forge.card.CardColor;
|
||||||
|
import forge.card.CardRules;
|
||||||
|
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||||
import forge.error.ErrorViewer;
|
import forge.error.ErrorViewer;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPool;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
import forge.properties.ForgeProps;
|
import forge.properties.ForgeProps;
|
||||||
import forge.util.MyRandom;
|
|
||||||
import forge.util.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -43,15 +37,24 @@ import forge.util.Predicate;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class Generate2ColorDeck {
|
public class Generate2ColorDeck extends GenerateColoredDeckBase {
|
||||||
private String color1 = "";
|
final float landsPercentage = 0.42f;
|
||||||
private String color2 = "";
|
final float creatPercentage = 0.34f;
|
||||||
private Random r = null;
|
final float spellPercentage = 0.24f;
|
||||||
private Map<String, String> clrMap = null;
|
|
||||||
private ArrayList<String> notColors = null;
|
final List<FilterCMC> cmcLevels = Arrays.asList(
|
||||||
private ArrayList<String> dL = null;
|
new GenerateDeckUtil.FilterCMC(0, 2),
|
||||||
private Map<String, Integer> cardCounts = null;
|
new GenerateDeckUtil.FilterCMC(3, 4),
|
||||||
private int maxDuplicates = 4;
|
new GenerateDeckUtil.FilterCMC(5, 6),
|
||||||
|
new GenerateDeckUtil.FilterCMC(7, 20));
|
||||||
|
final int[] cmcAmounts = {10, 8, 6, 2};
|
||||||
|
|
||||||
|
// 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>
|
* <p>
|
||||||
@@ -64,361 +67,58 @@ public class Generate2ColorDeck {
|
|||||||
* a {@link java.lang.String} object.
|
* a {@link java.lang.String} object.
|
||||||
*/
|
*/
|
||||||
public Generate2ColorDeck(final String clr1, final String clr2) {
|
public Generate2ColorDeck(final String clr1, final String clr2) {
|
||||||
this.r = MyRandom.getRandom();
|
|
||||||
|
|
||||||
this.cardCounts = new HashMap<String, Integer>();
|
|
||||||
|
|
||||||
this.clrMap = new HashMap<String, String>();
|
|
||||||
this.clrMap.put("white", "W");
|
|
||||||
this.clrMap.put("blue", "U");
|
|
||||||
this.clrMap.put("black", "B");
|
|
||||||
this.clrMap.put("red", "R");
|
|
||||||
this.clrMap.put("green", "G");
|
|
||||||
|
|
||||||
this.notColors = new ArrayList<String>();
|
|
||||||
this.notColors.add("white");
|
|
||||||
this.notColors.add("blue");
|
|
||||||
this.notColors.add("black");
|
|
||||||
this.notColors.add("red");
|
|
||||||
this.notColors.add("green");
|
|
||||||
|
|
||||||
if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS)) {
|
|
||||||
this.maxDuplicates = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clr1.equals("AI")) {
|
if (clr1.equals("AI")) {
|
||||||
// choose first color
|
int color1 = r.nextInt(5);
|
||||||
this.color1 = this.notColors.get(this.r.nextInt(5));
|
int color2 = ( color1 + 1 + r.nextInt(4) ) % 5 ;
|
||||||
|
colors = CardColor.fromMask(CardColor.WHITE << color1 | CardColor.WHITE << color2);
|
||||||
// choose second color
|
|
||||||
String c2 = this.notColors.get(this.r.nextInt(5));
|
|
||||||
while (c2.equals(this.color1)) {
|
|
||||||
c2 = this.notColors.get(this.r.nextInt(5));
|
|
||||||
}
|
|
||||||
this.color2 = c2;
|
|
||||||
} else {
|
} else {
|
||||||
this.color1 = clr1;
|
colors = CardColor.fromNames(clr1, clr2);
|
||||||
this.color2 = clr2;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.notColors.remove(this.color1);
|
|
||||||
this.notColors.remove(this.color2);
|
|
||||||
|
|
||||||
this.dL = GenerateDeckUtil.getDualLandList(this.clrMap.get(this.color1) + this.clrMap.get(this.color2));
|
|
||||||
|
|
||||||
for (int i = 0; i < this.dL.size(); i++) {
|
|
||||||
this.cardCounts.put(this.dL.get(i), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* get2ColorDeck.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param size
|
|
||||||
* a int.
|
|
||||||
* @param pt
|
|
||||||
* the pt
|
|
||||||
* @return a {@link forge.CardList} object.
|
|
||||||
*/
|
|
||||||
public final CardList get2ColorDeck(final int size, final PlayerType pt) {
|
|
||||||
int lc = 0; // loop counter to prevent infinite card selection loops
|
|
||||||
String tmpDeck = "";
|
|
||||||
final CardList tDeck = new CardList();
|
|
||||||
|
|
||||||
final int landsPercentage = 42;
|
|
||||||
final int creatPercentage = 34;
|
|
||||||
final int spellPercentage = 24;
|
|
||||||
|
|
||||||
// start with all cards
|
|
||||||
// remove cards that generated decks don't like
|
|
||||||
|
|
||||||
Predicate<Card> toUse = pt == PlayerType.HUMAN ? GenerateDeckUtil.humanCanPlay : GenerateDeckUtil.aiCanPlay;
|
|
||||||
CardList allCards = new CardList(toUse.select(AllZone.getCardFactory()));
|
|
||||||
|
|
||||||
// reduce to cards that match the colors
|
|
||||||
CardList cl1 = allCards.getColor(this.color1);
|
|
||||||
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)) {
|
|
||||||
cl1.addAll(allCards.getColor(Constant.Color.COLORLESS));
|
|
||||||
}
|
|
||||||
CardList cl2 = allCards.getColor(this.color2);
|
|
||||||
|
|
||||||
// remove multicolor cards that don't match the colors
|
|
||||||
final CardListFilter clrF = new CardListFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean addCard(final Card c) {
|
|
||||||
for (int i = 0; i < Generate2ColorDeck.this.notColors.size(); i++) {
|
|
||||||
if (c.getManaCost().contains(
|
|
||||||
Generate2ColorDeck.this.clrMap.get(Generate2ColorDeck.this.notColors.get(i)))) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cl1 = cl1.filter(clrF);
|
|
||||||
cl2 = cl2.filter(clrF);
|
|
||||||
|
|
||||||
|
|
||||||
|
public final ItemPoolView<CardPrinted> get2ColorDeck(final int size, final PlayerType pt) {
|
||||||
|
List<CardPrinted> cards = selectCardsOfMatchingColorForPlayer(pt);
|
||||||
// build subsets based on type
|
// build subsets based on type
|
||||||
final CardList cr1 = cl1.getType("Creature");
|
final List<CardPrinted> creatures = CardRules.Predicates.Presets.IS_CREATURE.select(cards, CardPrinted.FN_GET_RULES);
|
||||||
final CardList cr2 = cl2.getType("Creature");
|
final List<CardPrinted> spells = CardRules.Predicates.Presets.isNonCreatureSpellForGenerator.select(cards, CardPrinted.FN_GET_RULES);
|
||||||
|
|
||||||
final String[] ise = { "Instant", "Sorcery", "Enchantment", "Planeswalker", "Artifact.nonCreature" };
|
|
||||||
final CardList sp1 = cl1.getValidCards(ise, null, null);
|
|
||||||
final CardList sp2 = cl2.getValidCards(ise, null, null);
|
|
||||||
|
|
||||||
// final card pools
|
final ItemPool<CardPrinted> tDeck = new ItemPool<CardPrinted>(CardPrinted.class);
|
||||||
final CardList cr12 = new CardList();
|
|
||||||
final CardList sp12 = new CardList();
|
|
||||||
|
|
||||||
// used for mana curve in the card pool
|
final int creatCnt = (int) (creatPercentage * size);
|
||||||
final int[] minCMC = { 0 };
|
tmpDeck.append( "Creature Count:" + creatCnt + "\n" );
|
||||||
final int[] maxCMC = { 2 };
|
addCmcAdjusted(tDeck, creatures, creatCnt, cmcLevels, cmcAmounts);
|
||||||
final CardListFilter cmcF = new CardListFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean addCard(final Card c) {
|
|
||||||
final int cCMC = c.getCMC();
|
|
||||||
return (cCMC >= minCMC[0]) && (cCMC <= maxCMC[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// select cards to build card pools using a mana curve
|
final int spellCnt = (int) (spellPercentage * size);
|
||||||
for (int i = 4; i > 0; i--) {
|
tmpDeck.append( "Spell Count:" + spellCnt + "\n" );
|
||||||
|
addCmcAdjusted(tDeck, spells, spellCnt, cmcLevels, cmcAmounts);
|
||||||
if (i == 1) {
|
|
||||||
maxCMC[0] = 20; //the last category is open ended
|
|
||||||
i = 0; // this reduces the number of cards in the last category to 4
|
|
||||||
}
|
|
||||||
final CardList cr1CMC = cr1.filter(cmcF);
|
|
||||||
final CardList cr2CMC = cr2.filter(cmcF);
|
|
||||||
final CardList sp1CMC = sp1.filter(cmcF);
|
|
||||||
final CardList sp2CMC = sp2.filter(cmcF);
|
|
||||||
|
|
||||||
for (int j = 0; j < i + 1; j++) {
|
|
||||||
Card c = cr1CMC.get(this.r.nextInt(cr1CMC.size()));
|
|
||||||
cr12.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = cr2CMC.get(this.r.nextInt(cr2CMC.size()));
|
|
||||||
cr12.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = sp1CMC.get(this.r.nextInt(sp1CMC.size()));
|
|
||||||
sp12.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = sp2CMC.get(this.r.nextInt(sp2CMC.size()));
|
|
||||||
sp12.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
minCMC[0] += 2;
|
|
||||||
if (i == 4) {
|
|
||||||
minCMC[0] = 3;
|
|
||||||
}
|
|
||||||
maxCMC[0] += 2;
|
|
||||||
// resulting mana curve of the card pool
|
|
||||||
// 20x 0 - 2
|
|
||||||
// 16x 3 - 4
|
|
||||||
// 12x 5 - 6
|
|
||||||
// 4x 7 - 20
|
|
||||||
// =52x - card pool
|
|
||||||
}
|
|
||||||
|
|
||||||
// shuffle card pools
|
|
||||||
cr12.shuffle();
|
|
||||||
sp12.shuffle();
|
|
||||||
|
|
||||||
// calculate card counts
|
|
||||||
float p = (float) (creatPercentage * .01);
|
|
||||||
final int creatCnt = (int) (p * size);
|
|
||||||
tmpDeck += "Creature Count:" + creatCnt + "\n";
|
|
||||||
|
|
||||||
p = (float) (spellPercentage * .01);
|
|
||||||
final int spellCnt = (int) (p * size);
|
|
||||||
tmpDeck += "Spell Count:" + spellCnt + "\n";
|
|
||||||
|
|
||||||
// build deck from the card pools
|
|
||||||
for (int i = 0; i < creatCnt; i++) {
|
|
||||||
Card c = cr12.get(this.r.nextInt(cr12.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > (this.maxDuplicates - 1)) || (lc > 100)) {
|
|
||||||
c = cr12.get(this.r.nextInt(cr12.size()));
|
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > 100) {
|
|
||||||
throw new RuntimeException("Generate2ColorDeck : get2ColorDeck -- looped too much -- Cr12");
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeck += c.getName() + " " + c.getManaCost() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < spellCnt; i++) {
|
|
||||||
Card c = sp12.get(this.r.nextInt(sp12.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > (this.maxDuplicates - 1)) || (lc > 100)) {
|
|
||||||
c = sp12.get(this.r.nextInt(sp12.size()));
|
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > 100) {
|
|
||||||
throw new RuntimeException("Generate2ColorDeck : get2ColorDeck -- looped too much -- Sp12");
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeck += c.getName() + " " + c.getManaCost() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add lands
|
// Add lands
|
||||||
int numLands = 0;
|
int numLands = landsPercentage > 0 ? (int) (landsPercentage * size) : size - tDeck.countAll();
|
||||||
if (landsPercentage > 0) {
|
|
||||||
p = (float) (landsPercentage * .01);
|
|
||||||
numLands = (int) (p * size);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* else { // otherwise, just fill in the rest of the deck with basic //
|
|
||||||
* lands numLands = size - tDeck.size(); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
tmpDeck += "numLands:" + numLands + "\n";
|
tmpDeck.append( "numLands:" + numLands + "\n");
|
||||||
|
|
||||||
final int nDLands = (numLands / 6);
|
// Add dual lands
|
||||||
for (int i = 0; i < nDLands; i++) {
|
|
||||||
String s = this.dL.get(this.r.nextInt(this.dL.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
||||||
while ((this.cardCounts.get(s) > 3) || (lc > 20)) {
|
for(String s : duals) {
|
||||||
s = this.dL.get(this.r.nextInt(this.dL.size()));
|
this.cardCounts.put(s, 0);
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > 20) {
|
|
||||||
throw new RuntimeException("Generate2ColorDeck : get2ColorDeck -- looped too much -- DL");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(s, AllZone.getHumanPlayer()));
|
int dblsAdded = addSomeStr(tDeck, (numLands / 6), duals);
|
||||||
final int n = this.cardCounts.get(s);
|
numLands -= dblsAdded;
|
||||||
this.cardCounts.put(s, n + 1);
|
|
||||||
tmpDeck += s + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
numLands -= nDLands;
|
addBasicLand(tDeck, numLands);
|
||||||
|
tmpDeck.append( "DeckSize:" + tDeck.countAll() + "\n" );
|
||||||
|
|
||||||
if (numLands > 0) {
|
adjustDeckSize(tDeck, size);
|
||||||
// attempt to optimize basic land counts according to
|
tmpDeck.append( "DeckSize:" + tDeck.countAll() + "\n" );
|
||||||
// color representation
|
|
||||||
final CCnt[] clrCnts = { new CCnt("Plains", 0), new CCnt("Island", 0), new CCnt("Swamp", 0),
|
|
||||||
new CCnt("Mountain", 0), new CCnt("Forest", 0) };
|
|
||||||
|
|
||||||
// count each card color using mana costs
|
|
||||||
// TODO count hybrid mana differently?
|
|
||||||
for (int i = 0; i < tDeck.size(); i++) {
|
|
||||||
final String mc = tDeck.get(i).getManaCost();
|
|
||||||
|
|
||||||
// count each mana symbol in the mana cost
|
|
||||||
for (int j = 0; j < mc.length(); j++) {
|
|
||||||
final char c = mc.charAt(j);
|
|
||||||
|
|
||||||
if (c == 'W') {
|
|
||||||
clrCnts[0].count++;
|
|
||||||
} else if (c == 'U') {
|
|
||||||
clrCnts[1].count++;
|
|
||||||
} else if (c == 'B') {
|
|
||||||
clrCnts[2].count++;
|
|
||||||
} else if (c == 'R') {
|
|
||||||
clrCnts[3].count++;
|
|
||||||
} else if (c == 'G') {
|
|
||||||
clrCnts[4].count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// total of all ClrCnts
|
|
||||||
int totalColor = 0;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
totalColor += clrCnts[i].count;
|
|
||||||
tmpDeck += clrCnts[i].color + ":" + clrCnts[i].count + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeck += "totalColor:" + totalColor + "\n";
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
if (clrCnts[i].count > 0) { // calculate number of lands for
|
|
||||||
// each color
|
|
||||||
p = (float) clrCnts[i].count / (float) totalColor;
|
|
||||||
final int nLand = (int) (numLands * p);
|
|
||||||
tmpDeck += "nLand-" + clrCnts[i].color + ":" + nLand + "\n";
|
|
||||||
|
|
||||||
// just to prevent a null exception by the deck size fixing
|
|
||||||
// code
|
|
||||||
this.cardCounts.put(clrCnts[i].color, nLand);
|
|
||||||
|
|
||||||
for (int j = 0; j <= nLand; j++) {
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(clrCnts[i].color, AllZone.getComputerPlayer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
|
|
||||||
|
|
||||||
// fix under-sized or over-sized decks, due to integer arithmetic
|
|
||||||
if (tDeck.size() < size) {
|
|
||||||
final int diff = size - tDeck.size();
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
Card c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > 3) || (lc > size)) {
|
|
||||||
c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > size) {
|
|
||||||
throw new RuntimeException("Generate2ColorDeck : get2ColorDeck -- looped too much -- undersize");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeck += "Added:" + c.getName() + "\n";
|
|
||||||
}
|
|
||||||
} else if (tDeck.size() > size) {
|
|
||||||
final int diff = tDeck.size() - size;
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
Card c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
|
|
||||||
while (c.isBasicLand()) { // don't remove basic lands
|
|
||||||
c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.remove(c);
|
|
||||||
tmpDeck += "Removed:" + c.getName() + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
|
|
||||||
if (ForgeProps.getProperty("showdeck/2color", "false").equals("true")) {
|
if (ForgeProps.getProperty("showdeck/2color", "false").equals("true")) {
|
||||||
ErrorViewer.showError(tmpDeck);
|
ErrorViewer.showError(tmpDeck.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return tDeck;
|
return tDeck;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CCnt {
|
|
||||||
private final String color;
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
public CCnt(final String clr, final int cnt) {
|
|
||||||
this.color = clr;
|
|
||||||
this.count = cnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,17 @@
|
|||||||
*/
|
*/
|
||||||
package forge.deck.generate;
|
package forge.deck.generate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import forge.AllZone;
|
|
||||||
import forge.Card;
|
|
||||||
import forge.CardList;
|
|
||||||
import forge.CardListFilter;
|
|
||||||
import forge.Constant;
|
|
||||||
import forge.PlayerType;
|
import forge.PlayerType;
|
||||||
import forge.Singletons;
|
import forge.card.CardColor;
|
||||||
|
import forge.card.CardRules;
|
||||||
|
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||||
import forge.error.ErrorViewer;
|
import forge.error.ErrorViewer;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPool;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
import forge.properties.ForgeProps;
|
import forge.properties.ForgeProps;
|
||||||
import forge.util.MyRandom;
|
|
||||||
import forge.util.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -43,16 +37,16 @@ import forge.util.Predicate;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class Generate3ColorDeck {
|
public class Generate3ColorDeck extends GenerateColoredDeckBase {
|
||||||
private String color1 = "";
|
private final float landsPercentage = .44f;
|
||||||
private String color2 = "";
|
private final float creatPercentage = .34f;
|
||||||
private String color3 = "";
|
private final float spellPercentage = .22f;
|
||||||
private Random r = null;
|
|
||||||
private Map<String, String> crMap = null;
|
final List<FilterCMC> cmcLevels = Arrays.asList(
|
||||||
private ArrayList<String> notColors = null;
|
new GenerateDeckUtil.FilterCMC(0, 2),
|
||||||
private ArrayList<String> dL = null;
|
new GenerateDeckUtil.FilterCMC(3, 5),
|
||||||
private Map<String, Integer> cardCounts = null;
|
new GenerateDeckUtil.FilterCMC(6, 20) );
|
||||||
private int maxDuplicates = 4;
|
final int[] cmcAmounts = {12, 9, 3};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -67,61 +61,13 @@ public class Generate3ColorDeck {
|
|||||||
* a {@link java.lang.String} object.
|
* a {@link java.lang.String} object.
|
||||||
*/
|
*/
|
||||||
public Generate3ColorDeck(final String clr1, final String clr2, final String clr3) {
|
public Generate3ColorDeck(final String clr1, final String clr2, final String clr3) {
|
||||||
this.r = MyRandom.getRandom();
|
|
||||||
|
|
||||||
this.cardCounts = new HashMap<String, Integer>();
|
|
||||||
|
|
||||||
this.crMap = new HashMap<String, String>();
|
|
||||||
this.crMap.put("white", "W");
|
|
||||||
this.crMap.put("blue", "U");
|
|
||||||
this.crMap.put("black", "B");
|
|
||||||
this.crMap.put("red", "R");
|
|
||||||
this.crMap.put("green", "G");
|
|
||||||
|
|
||||||
this.notColors = new ArrayList<String>();
|
|
||||||
this.notColors.add("white");
|
|
||||||
this.notColors.add("blue");
|
|
||||||
this.notColors.add("black");
|
|
||||||
this.notColors.add("red");
|
|
||||||
this.notColors.add("green");
|
|
||||||
|
|
||||||
if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS)) {
|
|
||||||
this.maxDuplicates = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clr1.equals("AI")) {
|
if (clr1.equals("AI")) {
|
||||||
// choose first color
|
int color1 = r.nextInt(5);
|
||||||
this.color1 = this.notColors.get(this.r.nextInt(5));
|
int color2 = ( color1 + 1 + r.nextInt(4) ) % 5 ;
|
||||||
|
colors = CardColor.fromMask(CardColor.WHITE << color1 | CardColor.WHITE << color2).inverse();
|
||||||
// choose second color
|
|
||||||
String c2 = this.notColors.get(this.r.nextInt(5));
|
|
||||||
while (c2.equals(this.color1)) {
|
|
||||||
c2 = this.notColors.get(this.r.nextInt(5));
|
|
||||||
}
|
|
||||||
this.color2 = c2;
|
|
||||||
|
|
||||||
String c3 = this.notColors.get(this.r.nextInt(5));
|
|
||||||
while (c3.equals(this.color1) || c3.equals(this.color2)) {
|
|
||||||
c3 = this.notColors.get(this.r.nextInt(5));
|
|
||||||
}
|
|
||||||
this.color3 = c3;
|
|
||||||
} else {
|
} else {
|
||||||
this.color1 = clr1;
|
colors = CardColor.fromNames(clr1, clr2, clr3);
|
||||||
this.color2 = clr2;
|
|
||||||
this.color3 = clr3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.notColors.remove(this.color1);
|
|
||||||
this.notColors.remove(this.color2);
|
|
||||||
this.notColors.remove(this.color3);
|
|
||||||
|
|
||||||
this.dL = GenerateDeckUtil.getDualLandList(this.crMap.get(this.color1) + this.crMap.get(this.color2)
|
|
||||||
+ this.crMap.get(this.color3));
|
|
||||||
|
|
||||||
for (int i = 0; i < this.dL.size(); i++) {
|
|
||||||
this.cardCounts.put(this.dL.get(i), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -135,312 +81,46 @@ public class Generate3ColorDeck {
|
|||||||
* the pt
|
* the pt
|
||||||
* @return a {@link forge.CardList} object.
|
* @return a {@link forge.CardList} object.
|
||||||
*/
|
*/
|
||||||
public final CardList get3ColorDeck(final int size, final PlayerType pt) {
|
public final ItemPoolView<CardPrinted> get3ColorDeck(final int size, final PlayerType pt) {
|
||||||
int lc = 0; // loop counter to prevent infinite card selection loops
|
List<CardPrinted> cards = selectCardsOfMatchingColorForPlayer(pt);
|
||||||
String tmpDeck = "";
|
|
||||||
final CardList tDeck = new CardList();
|
|
||||||
|
|
||||||
final int landsPercentage = 44;
|
|
||||||
final int creatPercentage = 34;
|
|
||||||
final int spellPercentage = 22;
|
|
||||||
|
|
||||||
// start with all cards
|
|
||||||
// remove cards that generated decks don't like
|
|
||||||
Predicate<Card> toUse = pt == PlayerType.HUMAN ? GenerateDeckUtil.humanCanPlay : GenerateDeckUtil.aiCanPlay;
|
|
||||||
CardList allCards = new CardList(toUse.select(AllZone.getCardFactory()));
|
|
||||||
|
|
||||||
// reduce to cards that match the colors
|
|
||||||
CardList cl1 = allCards.getColor(this.color1);
|
|
||||||
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)) {
|
|
||||||
cl1.addAll(allCards.getColor(Constant.Color.COLORLESS));
|
|
||||||
}
|
|
||||||
CardList cl2 = allCards.getColor(this.color2);
|
|
||||||
CardList cl3 = allCards.getColor(this.color3);
|
|
||||||
|
|
||||||
// remove multicolor cards that don't match the colors
|
|
||||||
final CardListFilter clrF = new CardListFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean addCard(final Card c) {
|
|
||||||
for (int i = 0; i < Generate3ColorDeck.this.notColors.size(); i++) {
|
|
||||||
if (c.getManaCost().contains(
|
|
||||||
Generate3ColorDeck.this.crMap.get(Generate3ColorDeck.this.notColors.get(i)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cl1 = cl1.filter(clrF);
|
|
||||||
cl2 = cl2.filter(clrF);
|
|
||||||
cl3 = cl3.filter(clrF);
|
|
||||||
|
|
||||||
// build subsets based on type
|
// build subsets based on type
|
||||||
final CardList cr1 = cl1.getType("Creature");
|
final List<CardPrinted> creatures = CardRules.Predicates.Presets.IS_CREATURE.select(cards, CardPrinted.FN_GET_RULES);
|
||||||
final CardList cr2 = cl2.getType("Creature");
|
final List<CardPrinted> spells = CardRules.Predicates.Presets.isNonCreatureSpellForGenerator.select(cards, CardPrinted.FN_GET_RULES);
|
||||||
final CardList cr3 = cl3.getType("Creature");
|
|
||||||
|
|
||||||
final String[] ise = { "Instant", "Sorcery", "Enchantment", "Planeswalker", "Artifact.nonCreature" };
|
|
||||||
final CardList sp1 = cl1.getValidCards(ise, null, null);
|
|
||||||
final CardList sp2 = cl2.getValidCards(ise, null, null);
|
|
||||||
final CardList sp3 = cl3.getValidCards(ise, null, null);
|
|
||||||
|
|
||||||
// final card pools
|
final ItemPool<CardPrinted> tDeck = new ItemPool<CardPrinted>(CardPrinted.class);
|
||||||
final CardList cr123 = new CardList();
|
|
||||||
final CardList sp123 = new CardList();
|
|
||||||
|
|
||||||
// used for mana curve in the card pool
|
final int creatCnt = (int) (creatPercentage * size);
|
||||||
final int[] minCMC = { 0 };
|
tmpDeck.append( "Creature Count:" + creatCnt + "\n" );
|
||||||
final int[] maxCMC = { 2 };
|
addCmcAdjusted(tDeck, creatures, creatCnt, cmcLevels, cmcAmounts);
|
||||||
final CardListFilter cmcF = new CardListFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean addCard(final Card c) {
|
|
||||||
final int cCMC = c.getCMC();
|
|
||||||
return (cCMC >= minCMC[0]) && (cCMC <= maxCMC[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// select cards to build card pools using a mana curve
|
final int spellCnt = (int) (spellPercentage * size);
|
||||||
for (int i = 3; i > 0; i--) {
|
tmpDeck.append( "Spell Count:" + spellCnt + "\n" );
|
||||||
if (i == 1) {
|
addCmcAdjusted(tDeck, spells, spellCnt, cmcLevels, cmcAmounts);
|
||||||
maxCMC[0] = 20; //the last category is open ended
|
|
||||||
i = 0; // this reduces the number of cards in the last category to 6
|
|
||||||
}
|
|
||||||
final CardList cr1CMC = cr1.filter(cmcF);
|
|
||||||
final CardList cr2CMC = cr2.filter(cmcF);
|
|
||||||
final CardList cr3CMC = cr3.filter(cmcF);
|
|
||||||
|
|
||||||
final CardList sp1CMC = sp1.filter(cmcF);
|
|
||||||
final CardList sp2CMC = sp2.filter(cmcF);
|
|
||||||
final CardList sp3CMC = sp3.filter(cmcF);
|
|
||||||
|
|
||||||
for (int j = 0; j < i + 1; j++) {
|
|
||||||
Card c = cr1CMC.get(this.r.nextInt(cr1CMC.size()));
|
|
||||||
cr123.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = cr2CMC.get(this.r.nextInt(cr2CMC.size()));
|
|
||||||
cr123.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = cr3CMC.get(this.r.nextInt(cr3CMC.size()));
|
|
||||||
cr123.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = sp1CMC.get(this.r.nextInt(sp1CMC.size()));
|
|
||||||
sp123.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = sp2CMC.get(this.r.nextInt(sp2CMC.size()));
|
|
||||||
sp123.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = sp3CMC.get(this.r.nextInt(sp3CMC.size()));
|
|
||||||
sp123.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
minCMC[0] += 3;
|
|
||||||
maxCMC[0] += 3;
|
|
||||||
// resulting mana curve of the card pool
|
|
||||||
// 24x 0 - 2
|
|
||||||
// 18x 3 - 5
|
|
||||||
// 6x 6 - 20
|
|
||||||
// =58x - card pool
|
|
||||||
}
|
|
||||||
|
|
||||||
// shuffle card pools
|
|
||||||
cr123.shuffle();
|
|
||||||
sp123.shuffle();
|
|
||||||
|
|
||||||
// calculate card counts
|
|
||||||
float p = (float) (creatPercentage * .01);
|
|
||||||
final int creatCnt = (int) (p * size);
|
|
||||||
tmpDeck += "Creature Count:" + creatCnt + "\n";
|
|
||||||
|
|
||||||
p = (float) (spellPercentage * .01);
|
|
||||||
final int spellCnt = (int) (p * size);
|
|
||||||
tmpDeck += "Spell Count:" + spellCnt + "\n";
|
|
||||||
|
|
||||||
// build deck from the card pools
|
|
||||||
for (int i = 0; i < creatCnt; i++) {
|
|
||||||
Card c = cr123.get(this.r.nextInt(cr123.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > (this.maxDuplicates - 1)) || (lc > 100)) {
|
|
||||||
c = cr123.get(this.r.nextInt(cr123.size()));
|
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > 100) {
|
|
||||||
throw new RuntimeException("Generate3ColorDeck : get3ColorDeck -- looped too much -- Cr123");
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeck += c.getName() + " " + c.getManaCost() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < spellCnt; i++) {
|
|
||||||
Card c = sp123.get(this.r.nextInt(sp123.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > (this.maxDuplicates - 1)) || (lc > 100)) {
|
|
||||||
c = sp123.get(this.r.nextInt(sp123.size()));
|
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > 100) {
|
|
||||||
throw new RuntimeException("Generate3ColorDeck : get3ColorDeck -- looped too much -- Sp123");
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeck += c.getName() + " " + c.getManaCost() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add lands
|
// Add lands
|
||||||
int numLands = 0;
|
int numLands = landsPercentage > 0 ? (int) (landsPercentage * size) : size - tDeck.countAll();
|
||||||
if (landsPercentage > 0) {
|
|
||||||
p = (float) (landsPercentage * .01);
|
tmpDeck.append( "numLands:" + numLands + "\n");
|
||||||
numLands = (int) (p * size);
|
|
||||||
|
// Add dual lands
|
||||||
|
|
||||||
|
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
||||||
|
for(String s : duals) {
|
||||||
|
this.cardCounts.put(s, 0);
|
||||||
}
|
}
|
||||||
/*
|
int dblsAdded = addSomeStr(tDeck, (numLands / 4), duals);
|
||||||
* else { // otherwise, just fill in the rest of the deck with basic
|
numLands -= dblsAdded;
|
||||||
* lands numLands = size - tDeck.size(); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
tmpDeck += "numLands:" + numLands + "\n";
|
addBasicLand(tDeck, numLands);
|
||||||
|
tmpDeck.append( "DeckSize:" + tDeck.countAll() + "\n" );
|
||||||
|
|
||||||
final int ndLands = (numLands / 4);
|
adjustDeckSize(tDeck, size);
|
||||||
for (int i = 0; i < ndLands; i++) {
|
tmpDeck.append( "DeckSize:" + tDeck.countAll() + "\n" );
|
||||||
String s = this.dL.get(this.r.nextInt(this.dL.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
|
||||||
while ((this.cardCounts.get(s) > 3) || (lc > 20)) {
|
|
||||||
s = this.dL.get(this.r.nextInt(this.dL.size()));
|
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > 20) {
|
|
||||||
throw new RuntimeException("Generate3ColorDeck : get3ColorDeck -- looped too much -- dL");
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(s, AllZone.getHumanPlayer()));
|
|
||||||
final int n = this.cardCounts.get(s);
|
|
||||||
this.cardCounts.put(s, n + 1);
|
|
||||||
tmpDeck += s + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
numLands -= ndLands;
|
|
||||||
|
|
||||||
if (numLands > 0) {
|
|
||||||
// attempt to optimize basic land counts according to
|
|
||||||
// color representation
|
|
||||||
final CCnt[] clrCnts = { new CCnt("Plains", 0), new CCnt("Island", 0), new CCnt("Swamp", 0),
|
|
||||||
new CCnt("Mountain", 0), new CCnt("Forest", 0) };
|
|
||||||
|
|
||||||
// count each card color using mana costs
|
|
||||||
// TODO count hybrid mana differently?
|
|
||||||
for (int i = 0; i < tDeck.size(); i++) {
|
|
||||||
final String mc = tDeck.get(i).getManaCost();
|
|
||||||
|
|
||||||
// count each mana symbol in the mana cost
|
|
||||||
for (int j = 0; j < mc.length(); j++) {
|
|
||||||
final char c = mc.charAt(j);
|
|
||||||
|
|
||||||
if (c == 'W') {
|
|
||||||
clrCnts[0].count++;
|
|
||||||
} else if (c == 'U') {
|
|
||||||
clrCnts[1].count++;
|
|
||||||
} else if (c == 'B') {
|
|
||||||
clrCnts[2].count++;
|
|
||||||
} else if (c == 'R') {
|
|
||||||
clrCnts[3].count++;
|
|
||||||
} else if (c == 'G') {
|
|
||||||
clrCnts[4].count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// total of all ClrCnts
|
|
||||||
int totalColor = 0;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
totalColor += clrCnts[i].count;
|
|
||||||
tmpDeck += clrCnts[i].color + ":" + clrCnts[i].count + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeck += "totalColor:" + totalColor + "\n";
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
if (clrCnts[i].count > 0) { // calculate number of lands for
|
|
||||||
// each color
|
|
||||||
p = (float) clrCnts[i].count / (float) totalColor;
|
|
||||||
final int nLand = (int) (numLands * p);
|
|
||||||
tmpDeck += "nLand-" + clrCnts[i].color + ":" + nLand + "\n";
|
|
||||||
|
|
||||||
// just to prevent a null exception by the deck size fixing
|
|
||||||
// code
|
|
||||||
this.cardCounts.put(clrCnts[i].color, nLand);
|
|
||||||
|
|
||||||
for (int j = 0; j <= nLand; j++) {
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(clrCnts[i].color, AllZone.getComputerPlayer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
|
|
||||||
|
|
||||||
// fix under-sized or over-sized decks, due to integer arithmetic
|
|
||||||
if (tDeck.size() < size) {
|
|
||||||
final int diff = size - tDeck.size();
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
Card c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
|
|
||||||
lc = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > 3) || (lc > size)) {
|
|
||||||
c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
lc++;
|
|
||||||
}
|
|
||||||
if (lc > size) {
|
|
||||||
throw new RuntimeException("Generate3ColorDeck : get3ColorDeck -- looped too much -- undersize");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeck += "Added:" + c.getName() + "\n";
|
|
||||||
}
|
|
||||||
} else if (tDeck.size() > size) {
|
|
||||||
final int diff = tDeck.size() - size;
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
Card c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
|
|
||||||
while (c.isBasicLand()) {
|
|
||||||
// don't remove basic lands
|
|
||||||
c = tDeck.get(this.r.nextInt(tDeck.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.remove(c);
|
|
||||||
tmpDeck += "Removed:" + c.getName() + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
|
|
||||||
if (ForgeProps.getProperty("showdeck/3color", "false").equals("true")) {
|
if (ForgeProps.getProperty("showdeck/3color", "false").equals("true")) {
|
||||||
ErrorViewer.showError(tmpDeck);
|
ErrorViewer.showError(tmpDeck.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return tDeck;
|
return tDeck;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class CCnt {
|
|
||||||
private final String color;
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
public CCnt(final String clr, final int cnt) {
|
|
||||||
this.color = clr;
|
|
||||||
this.count = cnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,23 +17,17 @@
|
|||||||
*/
|
*/
|
||||||
package forge.deck.generate;
|
package forge.deck.generate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import forge.AllZone;
|
|
||||||
import forge.Card;
|
|
||||||
import forge.CardList;
|
|
||||||
import forge.CardListFilter;
|
|
||||||
import forge.Constant;
|
|
||||||
import forge.PlayerType;
|
import forge.PlayerType;
|
||||||
import forge.Singletons;
|
import forge.card.CardColor;
|
||||||
|
import forge.card.CardRules;
|
||||||
|
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||||
import forge.error.ErrorViewer;
|
import forge.error.ErrorViewer;
|
||||||
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPool;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
import forge.properties.ForgeProps;
|
import forge.properties.ForgeProps;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
|
||||||
import forge.util.MyRandom;
|
|
||||||
import forge.util.Predicate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -43,83 +37,28 @@ import forge.util.Predicate;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class Generate5ColorDeck {
|
public class Generate5ColorDeck extends GenerateColoredDeckBase {
|
||||||
private String color1 = "white";
|
private final float landsPercentage = .44f;
|
||||||
private String color2 = "blue";
|
private final float creatPercentage = .34f;
|
||||||
private String color3 = "black";
|
private final float spellPercentage = .22f;
|
||||||
private String color4 = "red";
|
|
||||||
private String color5 = "green";
|
final List<FilterCMC> cmcLevels = Arrays.asList(
|
||||||
private Random r = null;
|
new GenerateDeckUtil.FilterCMC(0, 2),
|
||||||
private Map<String, String> colorMap = null;
|
new GenerateDeckUtil.FilterCMC(3, 5),
|
||||||
private ArrayList<String> notColors = null;
|
new GenerateDeckUtil.FilterCMC(6, 20) );
|
||||||
private ArrayList<String> dualLands = null;
|
final int[] cmcAmounts = {15, 10, 5};
|
||||||
private Map<String, Integer> cardCounts = null;
|
|
||||||
private int maxDuplicates = 4;
|
// 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.
|
* Instantiates a new generate5 color deck.
|
||||||
*/
|
*/
|
||||||
public Generate5ColorDeck() {
|
public Generate5ColorDeck() {
|
||||||
this("white", "blue", "black", "red", "green");
|
colors = CardColor.fromMask(0).inverse();
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Constructor for Generate5ColorDeck.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param color1
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
* @param color2
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
* @param color3
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
* @param color4
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
* @param color5
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
*/
|
|
||||||
public Generate5ColorDeck(final String color1, final String color2, final String color3, final String color4,
|
|
||||||
final String color5) {
|
|
||||||
this.r = MyRandom.getRandom();
|
|
||||||
|
|
||||||
this.cardCounts = new HashMap<String, Integer>();
|
|
||||||
|
|
||||||
this.colorMap = new HashMap<String, String>();
|
|
||||||
this.colorMap.put("white", "W");
|
|
||||||
this.colorMap.put("blue", "U");
|
|
||||||
this.colorMap.put("black", "B");
|
|
||||||
this.colorMap.put("red", "R");
|
|
||||||
this.colorMap.put("green", "G");
|
|
||||||
|
|
||||||
this.notColors = new ArrayList<String>();
|
|
||||||
this.notColors.add("white");
|
|
||||||
this.notColors.add("blue");
|
|
||||||
this.notColors.add("black");
|
|
||||||
this.notColors.add("red");
|
|
||||||
this.notColors.add("green");
|
|
||||||
|
|
||||||
this.color1 = color1;
|
|
||||||
this.color2 = color2;
|
|
||||||
this.color3 = color3;
|
|
||||||
this.color4 = color4;
|
|
||||||
this.color5 = color5;
|
|
||||||
|
|
||||||
this.notColors.remove(this.color1);
|
|
||||||
this.notColors.remove(this.color2);
|
|
||||||
this.notColors.remove(this.color3);
|
|
||||||
this.notColors.remove(this.color4);
|
|
||||||
this.notColors.remove(this.color5);
|
|
||||||
|
|
||||||
if (Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS)) {
|
|
||||||
this.maxDuplicates = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.dualLands = GenerateDeckUtil.getDualLandList("WUBRG");
|
|
||||||
|
|
||||||
for (int i = 0; i < this.dualLands.size(); i++) {
|
|
||||||
this.cardCounts.put(this.dualLands.get(i), 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -133,362 +72,46 @@ public class Generate5ColorDeck {
|
|||||||
* a PlayerType
|
* a PlayerType
|
||||||
* @return a {@link forge.CardList} object.
|
* @return a {@link forge.CardList} object.
|
||||||
*/
|
*/
|
||||||
public final CardList get5ColorDeck(final int deckSize, final PlayerType playerType) {
|
public final ItemPoolView<CardPrinted> get5ColorDeck(final int size, final PlayerType pt) {
|
||||||
int loopCounter = 0; // loop counter to prevent infinite card selection loops
|
List<CardPrinted> cards = selectCardsOfMatchingColorForPlayer(pt);
|
||||||
String tmpDeckErrorMessage = "";
|
|
||||||
final CardList tempDeck = new CardList();
|
|
||||||
|
|
||||||
final int landsPercentage = 44;
|
|
||||||
final int creaturePercentage = 34;
|
|
||||||
final int spellPercentage = 22;
|
|
||||||
|
|
||||||
// start with all cards
|
|
||||||
// remove cards that generated decks don't like
|
|
||||||
Predicate<Card> toUse = playerType == PlayerType.HUMAN ? GenerateDeckUtil.humanCanPlay : GenerateDeckUtil.aiCanPlay;
|
|
||||||
CardList allCards = new CardList(toUse.select(AllZone.getCardFactory()));
|
|
||||||
|
|
||||||
// reduce to cards that match the colors
|
|
||||||
CardList cardList1 = allCards.getColor(this.color1);
|
|
||||||
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)) {
|
|
||||||
cardList1.addAll(allCards.getColor(Constant.Color.COLORLESS));
|
|
||||||
}
|
|
||||||
CardList cardList2 = allCards.getColor(this.color2);
|
|
||||||
CardList cardList3 = allCards.getColor(this.color3);
|
|
||||||
CardList cardList4 = allCards.getColor(this.color4);
|
|
||||||
CardList cardList5 = allCards.getColor(this.color5);
|
|
||||||
|
|
||||||
// remove multicolor cards that don't match the colors
|
|
||||||
final CardListFilter cardListFilter = new CardListFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean addCard(final Card c) {
|
|
||||||
for (int i = 0; i < Generate5ColorDeck.this.notColors.size(); i++) {
|
|
||||||
if (c.getManaCost().contains(
|
|
||||||
Generate5ColorDeck.this.colorMap.get(Generate5ColorDeck.this.notColors.get(i)))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cardList1 = cardList1.filter(cardListFilter);
|
|
||||||
cardList2 = cardList2.filter(cardListFilter);
|
|
||||||
cardList3 = cardList3.filter(cardListFilter);
|
|
||||||
cardList4 = cardList4.filter(cardListFilter);
|
|
||||||
cardList5 = cardList5.filter(cardListFilter);
|
|
||||||
|
|
||||||
// build subsets based on type
|
// build subsets based on type
|
||||||
final CardList creatureCardList1 = cardList1.getType("Creature");
|
final List<CardPrinted> creatures = CardRules.Predicates.Presets.IS_CREATURE.select(cards, CardPrinted.FN_GET_RULES);
|
||||||
final CardList creatureCardList2 = cardList2.getType("Creature");
|
final List<CardPrinted> spells = CardRules.Predicates.Presets.isNonCreatureSpellForGenerator.select(cards, CardPrinted.FN_GET_RULES);
|
||||||
final CardList creatureCardList3 = cardList3.getType("Creature");
|
|
||||||
final CardList creatureCardList4 = cardList4.getType("Creature");
|
|
||||||
final CardList creatureCardList5 = cardList5.getType("Creature");
|
|
||||||
|
|
||||||
final String[] nonCreatureSpells = { "Instant", "Sorcery", "Enchantment", "Planeswalker", "Artifact.nonCreature" };
|
|
||||||
final CardList spellCardList1 = cardList1.getValidCards(nonCreatureSpells, null, null);
|
|
||||||
final CardList spellCardList2 = cardList2.getValidCards(nonCreatureSpells, null, null);
|
|
||||||
final CardList spellCardList3 = cardList3.getValidCards(nonCreatureSpells, null, null);
|
|
||||||
final CardList spellCardList4 = cardList4.getValidCards(nonCreatureSpells, null, null);
|
|
||||||
final CardList spellCardList5 = cardList5.getValidCards(nonCreatureSpells, null, null);
|
|
||||||
|
|
||||||
// final card pools
|
final ItemPool<CardPrinted> tDeck = new ItemPool<CardPrinted>(CardPrinted.class);
|
||||||
final CardList creatures12345 = new CardList();
|
|
||||||
final CardList spells12345 = new CardList();
|
|
||||||
|
|
||||||
// used for mana curve in the card pool
|
final int creatCnt = (int) (creatPercentage * size);
|
||||||
final int[] minConvertedManaCost = { 0 };
|
tmpDeck.append( "Creature Count:" + creatCnt + "\n" );
|
||||||
final int[] maxConvertedManaCost = { 2 };
|
addCmcAdjusted(tDeck, creatures, creatCnt, cmcLevels, cmcAmounts);
|
||||||
final CardListFilter convertedManaCostFilter = new CardListFilter() {
|
|
||||||
@Override
|
|
||||||
public boolean addCard(final Card c) {
|
|
||||||
final int cardConvertedManaCost = c.getCMC();
|
|
||||||
return (cardConvertedManaCost >= minConvertedManaCost[0]) && (cardConvertedManaCost <= maxConvertedManaCost[0]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// select cards to build card pools using a mana curve
|
final int spellCnt = (int) (spellPercentage * size);
|
||||||
for (int i = 3; i > 0; i--) {
|
tmpDeck.append( "Spell Count:" + spellCnt + "\n" );
|
||||||
if (i == 1) {
|
addCmcAdjusted(tDeck, spells, spellCnt, cmcLevels, cmcAmounts);
|
||||||
maxConvertedManaCost[0] = 20; //the last category is open ended
|
|
||||||
}
|
|
||||||
final CardList creature1ConvertedManaCost = creatureCardList1.filter(convertedManaCostFilter);
|
|
||||||
final CardList creature2ConvertedManaCost = creatureCardList2.filter(convertedManaCostFilter);
|
|
||||||
final CardList creature3ConvertedManaCost = creatureCardList3.filter(convertedManaCostFilter);
|
|
||||||
final CardList creature4ConvertedManaCost = creatureCardList4.filter(convertedManaCostFilter);
|
|
||||||
final CardList creature5ConvertedManaCost = creatureCardList5.filter(convertedManaCostFilter);
|
|
||||||
|
|
||||||
final CardList spell1ConvertedManaCost = spellCardList1.filter(convertedManaCostFilter);
|
|
||||||
final CardList spell2ConvertedManaCost = spellCardList2.filter(convertedManaCostFilter);
|
|
||||||
final CardList spell3ConvertedManaCost = spellCardList3.filter(convertedManaCostFilter);
|
|
||||||
final CardList spell4ConvertedManaCost = spellCardList4.filter(convertedManaCostFilter);
|
|
||||||
final CardList spell5ConvertedManaCost = spellCardList5.filter(convertedManaCostFilter);
|
|
||||||
|
|
||||||
for (int j = 0; j < i; j++) {
|
|
||||||
Card c = creature1ConvertedManaCost.get(this.r.nextInt(creature1ConvertedManaCost.size()));
|
|
||||||
creatures12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = creature2ConvertedManaCost.get(this.r.nextInt(creature2ConvertedManaCost.size()));
|
|
||||||
creatures12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = creature3ConvertedManaCost.get(this.r.nextInt(creature3ConvertedManaCost.size()));
|
|
||||||
creatures12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = creature4ConvertedManaCost.get(this.r.nextInt(creature4ConvertedManaCost.size()));
|
|
||||||
creatures12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = creature5ConvertedManaCost.get(this.r.nextInt(creature5ConvertedManaCost.size()));
|
|
||||||
creatures12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = spell1ConvertedManaCost.get(this.r.nextInt(spell1ConvertedManaCost.size()));
|
|
||||||
spells12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = spell2ConvertedManaCost.get(this.r.nextInt(spell2ConvertedManaCost.size()));
|
|
||||||
spells12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = spell3ConvertedManaCost.get(this.r.nextInt(spell3ConvertedManaCost.size()));
|
|
||||||
spells12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = spell4ConvertedManaCost.get(this.r.nextInt(spell4ConvertedManaCost.size()));
|
|
||||||
spells12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
|
|
||||||
c = spell5ConvertedManaCost.get(this.r.nextInt(spell5ConvertedManaCost.size()));
|
|
||||||
spells12345.add(c);
|
|
||||||
this.cardCounts.put(c.getName(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
minConvertedManaCost[0] += 2;
|
|
||||||
maxConvertedManaCost[0] += 2;
|
|
||||||
// resulting mana curve of the card pool
|
|
||||||
// 30x 0 - 2
|
|
||||||
// 20x 3 - 5
|
|
||||||
// 10x 6 - 20
|
|
||||||
// =60x - card pool
|
|
||||||
}
|
|
||||||
|
|
||||||
// shuffle card pools
|
|
||||||
creatures12345.shuffle();
|
|
||||||
spells12345.shuffle();
|
|
||||||
|
|
||||||
// calculate card counts
|
|
||||||
float p = (float) (creaturePercentage * .01);
|
|
||||||
final int creatureCount = (int) (p * deckSize);
|
|
||||||
tmpDeckErrorMessage += "Creature Count:" + creatureCount + "\n";
|
|
||||||
|
|
||||||
p = (float) (spellPercentage * .01);
|
|
||||||
final int spellCount = (int) (p * deckSize);
|
|
||||||
tmpDeckErrorMessage += "Spell Count:" + spellCount + "\n";
|
|
||||||
|
|
||||||
// build deck from the card pools
|
|
||||||
for (int i = 0; i < creatureCount; i++) {
|
|
||||||
Card c = creatures12345.get(this.r.nextInt(creatures12345.size()));
|
|
||||||
|
|
||||||
loopCounter = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > (this.maxDuplicates - 1)) || (loopCounter > 100)) {
|
|
||||||
c = creatures12345.get(this.r.nextInt(creatures12345.size()));
|
|
||||||
loopCounter++;
|
|
||||||
}
|
|
||||||
if (loopCounter > 100) {
|
|
||||||
throw new RuntimeException("Generate5ColorDeck : get5ColorDeck -- looped too much -- Cr123");
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeckErrorMessage += c.getName() + " " + c.getManaCost() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < spellCount; i++) {
|
|
||||||
Card c = spells12345.get(this.r.nextInt(spells12345.size()));
|
|
||||||
|
|
||||||
loopCounter = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > (this.maxDuplicates - 1)) || (loopCounter > 100)) {
|
|
||||||
c = spells12345.get(this.r.nextInt(spells12345.size()));
|
|
||||||
loopCounter++;
|
|
||||||
}
|
|
||||||
if (loopCounter > 100) {
|
|
||||||
throw new RuntimeException("Generate5ColorDeck : get5ColorDeck -- looped too much -- Sp123");
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeckErrorMessage += c.getName() + " " + c.getManaCost() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add lands
|
// Add lands
|
||||||
int numberOfLands = 0;
|
int numLands = landsPercentage > 0 ? (int) (landsPercentage * size) : size - tDeck.countAll();
|
||||||
if (landsPercentage > 0) {
|
|
||||||
p = (float) (landsPercentage * .01);
|
tmpDeck.append( "numLands:" + numLands + "\n");
|
||||||
numberOfLands = (int) (p * deckSize);
|
|
||||||
|
// Add dual lands
|
||||||
|
|
||||||
|
List<String> duals = GenerateDeckUtil.getDualLandList(colors);
|
||||||
|
for(String s : duals) {
|
||||||
|
this.cardCounts.put(s, 0);
|
||||||
}
|
}
|
||||||
/*
|
int dblsAdded = addSomeStr(tDeck, (numLands / 4), duals);
|
||||||
* else { // otherwise, just fill in the rest of the deck with basic //
|
numLands -= dblsAdded;
|
||||||
* lands numLands = size - tDeck.size(); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
tmpDeckErrorMessage += "numLands:" + numberOfLands + "\n";
|
addBasicLand(tDeck, numLands);
|
||||||
|
tmpDeck.append( "DeckSize:" + tDeck.countAll() + "\n" );
|
||||||
|
|
||||||
final int numberOfDualLands = (numberOfLands / 4);
|
adjustDeckSize(tDeck, size);
|
||||||
for (int i = 0; i < numberOfDualLands; i++) {
|
tmpDeck.append( "DeckSize:" + tDeck.countAll() + "\n" );
|
||||||
String s = this.dualLands.get(this.r.nextInt(this.dualLands.size()));
|
|
||||||
|
|
||||||
loopCounter = 0;
|
|
||||||
while ((this.cardCounts.get(s) > 3) || (loopCounter > 20)) {
|
|
||||||
s = this.dualLands.get(this.r.nextInt(this.dualLands.size()));
|
|
||||||
loopCounter++;
|
|
||||||
}
|
|
||||||
if (loopCounter > 20) {
|
|
||||||
throw new RuntimeException("Generate5ColorDeck : get5ColorDeck -- looped too much -- DL");
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDeck.add(AllZone.getCardFactory().getCard(s, AllZone.getHumanPlayer()));
|
|
||||||
final int n = this.cardCounts.get(s);
|
|
||||||
this.cardCounts.put(s, n + 1);
|
|
||||||
tmpDeckErrorMessage += s + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
numberOfLands -= numberOfDualLands;
|
|
||||||
|
|
||||||
if (numberOfLands > 0) {
|
|
||||||
// attempt to optimize basic land counts according to
|
|
||||||
// color representation
|
|
||||||
final ColorCount[] colorCounts = { new ColorCount("Plains", 0), new ColorCount("Island", 0), new ColorCount("Swamp", 0),
|
|
||||||
new ColorCount("Mountain", 0), new ColorCount("Forest", 0) };
|
|
||||||
|
|
||||||
// count each card color using mana costs
|
|
||||||
// TODO: count hybrid mana differently?
|
|
||||||
for (int i = 0; i < tempDeck.size(); i++) {
|
|
||||||
final String mc = tempDeck.get(i).getManaCost();
|
|
||||||
|
|
||||||
// count each mana symbol in the mana cost
|
|
||||||
for (int j = 0; j < mc.length(); j++) {
|
|
||||||
final char c = mc.charAt(j);
|
|
||||||
|
|
||||||
if (c == 'W') {
|
|
||||||
colorCounts[0].setCount(colorCounts[0].getCount() + 1);
|
|
||||||
} else if (c == 'U') {
|
|
||||||
colorCounts[1].setCount(colorCounts[1].getCount() + 1);
|
|
||||||
} else if (c == 'B') {
|
|
||||||
colorCounts[2].setCount(colorCounts[2].getCount() + 1);
|
|
||||||
} else if (c == 'R') {
|
|
||||||
colorCounts[3].setCount(colorCounts[3].getCount() + 1);
|
|
||||||
} else if (c == 'G') {
|
|
||||||
colorCounts[4].setCount(colorCounts[4].getCount() + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// total of all ColorCounts
|
|
||||||
int totalColor = 0;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
totalColor += colorCounts[i].getCount();
|
|
||||||
tmpDeckErrorMessage += colorCounts[i].getColor() + ":" + colorCounts[i].getCount() + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeckErrorMessage += "totalColor:" + totalColor + "\n";
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
if (colorCounts[i].getCount() > 0) { // calculate number of lands
|
|
||||||
// for each color
|
|
||||||
p = (float) colorCounts[i].getCount() / (float) totalColor;
|
|
||||||
final int nLand = (int) (numberOfLands * p);
|
|
||||||
tmpDeckErrorMessage += "nLand-" + colorCounts[i].getColor() + ":" + nLand + "\n";
|
|
||||||
|
|
||||||
// just to prevent a null exception by the deck size fixing
|
|
||||||
// code
|
|
||||||
this.cardCounts.put(colorCounts[i].getColor(), nLand);
|
|
||||||
|
|
||||||
for (int j = 0; j <= nLand; j++) {
|
|
||||||
tempDeck.add(AllZone.getCardFactory().getCard(colorCounts[i].getColor(), AllZone.getComputerPlayer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmpDeckErrorMessage += "DeckSize:" + tempDeck.size() + "\n";
|
|
||||||
|
|
||||||
// fix under-sized or over-sized decks, due to integer arithmetic
|
|
||||||
if (tempDeck.size() < deckSize) {
|
|
||||||
final int diff = deckSize - tempDeck.size();
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
Card c = tempDeck.get(this.r.nextInt(tempDeck.size()));
|
|
||||||
|
|
||||||
loopCounter = 0;
|
|
||||||
while ((this.cardCounts.get(c.getName()) > 3) || (loopCounter > deckSize)) {
|
|
||||||
c = tempDeck.get(this.r.nextInt(tempDeck.size()));
|
|
||||||
loopCounter++;
|
|
||||||
}
|
|
||||||
if (loopCounter > deckSize) {
|
|
||||||
throw new RuntimeException("Generate5ColorDeck : get5ColorDeck -- looped too much -- undersize");
|
|
||||||
}
|
|
||||||
|
|
||||||
final int n = this.cardCounts.get(c.getName());
|
|
||||||
tempDeck.add(AllZone.getCardFactory().getCard(c.getName(), AllZone.getComputerPlayer()));
|
|
||||||
this.cardCounts.put(c.getName(), n + 1);
|
|
||||||
tmpDeckErrorMessage += "Added:" + c.getName() + "\n";
|
|
||||||
}
|
|
||||||
} else if (tempDeck.size() > deckSize) {
|
|
||||||
final int diff = tempDeck.size() - deckSize;
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
Card c = tempDeck.get(this.r.nextInt(tempDeck.size()));
|
|
||||||
|
|
||||||
while (c.isBasicLand()) { // don't remove basic lands
|
|
||||||
c = tempDeck.get(this.r.nextInt(tempDeck.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
tempDeck.remove(c);
|
|
||||||
tmpDeckErrorMessage += "Removed:" + c.getName() + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeckErrorMessage += "DeckSize:" + tempDeck.size() + "\n";
|
|
||||||
if (ForgeProps.getProperty("showdeck/5color", "false").equals("true")) {
|
if (ForgeProps.getProperty("showdeck/5color", "false").equals("true")) {
|
||||||
ErrorViewer.showError(tmpDeckErrorMessage);
|
ErrorViewer.showError(tmpDeck.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return tempDeck;
|
return tDeck;
|
||||||
}
|
|
||||||
|
|
||||||
private class ColorCount {
|
|
||||||
private final String color;
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
public ColorCount(final String color, final int count) {
|
|
||||||
this.color = color;
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getColor() {
|
|
||||||
return this.color;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int getCount() {
|
|
||||||
return this.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param color
|
|
||||||
*/
|
|
||||||
public void setCount(final int count) {
|
|
||||||
this.count = count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
225
src/main/java/forge/deck/generate/GenerateColoredDeckBase.java
Normal file
225
src/main/java/forge/deck/generate/GenerateColoredDeckBase.java
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* 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 java.util.Random;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
|
||||||
|
import forge.PlayerType;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.CardColor;
|
||||||
|
import forge.card.CardRules;
|
||||||
|
import forge.deck.generate.GenerateDeckUtil.FilterCMC;
|
||||||
|
import forge.item.CardDb;
|
||||||
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPool;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
import forge.util.Predicate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <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 final int maxDuplicates;
|
||||||
|
|
||||||
|
protected CardColor colors;
|
||||||
|
|
||||||
|
StringBuilder tmpDeck = new StringBuilder();
|
||||||
|
|
||||||
|
// protected final float landsPercentage = 0.42f;
|
||||||
|
// protected float creatPercentage = 0.34f;
|
||||||
|
// protected float spellPercentage = 0.24f;
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Constructor for Generate2ColorDeck.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param clr1
|
||||||
|
* a {@link java.lang.String} object.
|
||||||
|
* @param clr2
|
||||||
|
* a {@link java.lang.String} object.
|
||||||
|
*/
|
||||||
|
public GenerateColoredDeckBase() {
|
||||||
|
this.maxDuplicates = Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_SINGLETONS) ? 1 : 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected void addSome(ItemPool<CardPrinted> tDeck, int cnt, List<CardPrinted> source) {
|
||||||
|
for (int i = 0; i < cnt; i++) {
|
||||||
|
CardPrinted c;
|
||||||
|
int lc = 0;
|
||||||
|
do {
|
||||||
|
c = source.get(this.r.nextInt(source.size()));
|
||||||
|
lc++;
|
||||||
|
} while ((this.cardCounts.get(c.getName()) > (this.maxDuplicates - 1)) || (lc > 100));
|
||||||
|
|
||||||
|
if (lc > 100) {
|
||||||
|
throw new RuntimeException("Generate2ColorDeck : get2ColorDeck -- looped too much -- Cr12");
|
||||||
|
}
|
||||||
|
|
||||||
|
tDeck.add(c);
|
||||||
|
final int n = this.cardCounts.get(c.getName());
|
||||||
|
this.cardCounts.put(c.getName(), n + 1);
|
||||||
|
tmpDeck.append(c.getName() + " " + c.getCard().getManaCost() + "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int addSomeStr(ItemPool<CardPrinted> tDeck, 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) > (this.maxDuplicates - 1)) || (lc > 20));
|
||||||
|
// not an error if looped too much - could play singleton mode, with 6 slots for 3 non-basic lands.
|
||||||
|
|
||||||
|
tDeck.add(CardDb.instance().getCard(s));
|
||||||
|
final int n = this.cardCounts.get(s);
|
||||||
|
this.cardCounts.put(s, n + 1);
|
||||||
|
tmpDeck.append(s + "\n");
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addBasicLand(ItemPool<CardPrinted> tDeck, int cnt) {
|
||||||
|
// attempt to optimize basic land counts according to colors of picked cards
|
||||||
|
final CCnt[] clrCnts = countLands(tDeck);
|
||||||
|
// total of all ClrCnts
|
||||||
|
int totalColor = 0;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
totalColor += clrCnts[i].getCount();
|
||||||
|
tmpDeck.append( clrCnts[i].Color + ":" + clrCnts[i].getCount() + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpDeck.append( "totalColor:" + totalColor + "\n");
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
if (clrCnts[i].getCount() <= 0) continue;
|
||||||
|
|
||||||
|
// calculate number of lands for each color
|
||||||
|
float p = (float) clrCnts[i].getCount() / (float) totalColor;
|
||||||
|
final int nLand = (int) (cnt * p);
|
||||||
|
tmpDeck.append( "nLand-" + clrCnts[i].Color + ":" + nLand + "\n");
|
||||||
|
|
||||||
|
// just to prevent a null exception by the deck size fixing
|
||||||
|
// code
|
||||||
|
this.cardCounts.put(clrCnts[i].Color, nLand);
|
||||||
|
|
||||||
|
for (int j = 0; j <= nLand; j++) {
|
||||||
|
tDeck.add(CardDb.instance().getCard(clrCnts[i].Color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void adjustDeckSize(ItemPool<CardPrinted> tDeck, 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(tDeck, diff, tDeck.toFlatList());
|
||||||
|
} else if (actualSize > targetSize) {
|
||||||
|
|
||||||
|
Predicate<CardRules> exceptBasicLand = Predicate.not(CardRules.Predicates.Presets.IS_BASIC_LAND);
|
||||||
|
|
||||||
|
for( int i = 0; i < 3 && actualSize > targetSize; i++ ) {
|
||||||
|
List<CardPrinted> toRemove = exceptBasicLand.random(tDeck.toFlatList(), CardPrinted.FN_GET_RULES, actualSize - targetSize);
|
||||||
|
tDeck.removeAllFlat(toRemove);
|
||||||
|
|
||||||
|
for(CardPrinted c: toRemove)
|
||||||
|
tmpDeck.append( "Removed:" + c.getName() + "\n" );
|
||||||
|
|
||||||
|
actualSize = tDeck.countAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void addCmcAdjusted(ItemPool<CardPrinted> tDeck, List<CardPrinted> source, int cnt, List<FilterCMC> cmcLevels, int[] cmcAmounts) {
|
||||||
|
final List<CardPrinted> curved = new ArrayList<CardPrinted>();
|
||||||
|
|
||||||
|
|
||||||
|
for(int i = 0; i < cmcAmounts.length; i++){
|
||||||
|
curved.addAll(cmcLevels.get(i).random(source, CardPrinted.FN_GET_RULES, cmcAmounts[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(CardPrinted c: curved)
|
||||||
|
this.cardCounts.put(c.getName(), 0);
|
||||||
|
|
||||||
|
addSome(tDeck, cnt, curved);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<CardPrinted> selectCardsOfMatchingColorForPlayer(PlayerType pt)
|
||||||
|
{
|
||||||
|
// start with all cards
|
||||||
|
// remove cards that generated decks don't like
|
||||||
|
Predicate<CardRules> canPlay = pt == PlayerType.HUMAN ? GenerateDeckUtil.humanCanPlay : GenerateDeckUtil.aiCanPlay;
|
||||||
|
Predicate<CardRules> hasColor = new GenerateDeckUtil.ContainsAllColorsFrom(colors);
|
||||||
|
|
||||||
|
if (!Singletons.getModel().getPreferences().getPrefBoolean(FPref.DECKGEN_ARTIFACTS)) {
|
||||||
|
hasColor = Predicate.or( hasColor, GenerateDeckUtil.colorlessCards );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Predicate.and(canPlay, hasColor).select(CardDb.instance().getAllCards(), CardPrinted.FN_GET_RULES);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static CCnt[] countLands(ItemPool<CardPrinted> outList) {
|
||||||
|
// attempt to optimize basic land counts according
|
||||||
|
// to color representation
|
||||||
|
final CCnt[] clrCnts = { new CCnt("Plains", 0), new CCnt("Island", 0), new CCnt("Swamp", 0),
|
||||||
|
new CCnt("Mountain", 0), new CCnt("Forest", 0) };
|
||||||
|
|
||||||
|
// count each card color using mana costs
|
||||||
|
// TODO: count hybrid mana differently?
|
||||||
|
for( Entry<CardPrinted, Integer> cpe : outList)
|
||||||
|
{
|
||||||
|
int profile = cpe.getKey().getCard().getManaCost().getColorProfile();
|
||||||
|
|
||||||
|
if ((profile & CardColor.WHITE) != 0 ) {
|
||||||
|
clrCnts[0].increment(cpe.getValue());
|
||||||
|
} else if ((profile & CardColor.BLUE) != 0 ) {
|
||||||
|
clrCnts[1].increment(cpe.getValue());
|
||||||
|
} else if ((profile & CardColor.BLACK) != 0 ) {
|
||||||
|
clrCnts[2].increment(cpe.getValue());
|
||||||
|
} else if ((profile & CardColor.RED) != 0 ) {
|
||||||
|
clrCnts[3].increment(cpe.getValue());
|
||||||
|
} else if ((profile & CardColor.GREEN) != 0 ) {
|
||||||
|
clrCnts[4].increment(cpe.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return clrCnts;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,8 +18,16 @@
|
|||||||
package forge.deck.generate;
|
package forge.deck.generate;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import forge.Card;
|
import forge.Card;
|
||||||
|
import forge.card.CardColor;
|
||||||
|
import forge.card.CardManaCost;
|
||||||
|
import forge.card.CardRules;
|
||||||
|
import forge.item.CardPrinted;
|
||||||
import forge.util.Predicate;
|
import forge.util.Predicate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,99 +40,91 @@ import forge.util.Predicate;
|
|||||||
*/
|
*/
|
||||||
public class GenerateDeckUtil {
|
public class GenerateDeckUtil {
|
||||||
|
|
||||||
public static final Predicate<Card> aiCanPlay = new Predicate<Card>() {
|
public static final Predicate<CardRules> aiCanPlay = new Predicate<CardRules>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrue(Card c) {
|
public boolean isTrue(CardRules c) {
|
||||||
return !c.getSVar("RemRandomDeck").equals("True") && !c.getSVar("RemAIDeck").equals("True");
|
return !c.getRemAIDecks() && c.getRemRandomDecks();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final Predicate<Card> humanCanPlay = new Predicate<Card>() {
|
public static final Predicate<CardRules> humanCanPlay = new Predicate<CardRules>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean isTrue(Card c) {
|
public boolean isTrue(CardRules c) {
|
||||||
return !c.getSVar("RemRandomDeck").equals("True");
|
return !c.getRemRandomDecks();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/**
|
|
||||||
*
|
|
||||||
* Arrays of dual and tri-land cards.
|
|
||||||
*
|
|
||||||
* @param colors
|
|
||||||
* a String
|
|
||||||
* @return ArrayList<String>
|
|
||||||
*/
|
|
||||||
public static ArrayList<String> getDualLandList(final String colors) {
|
|
||||||
|
|
||||||
final ArrayList<String> dLands = new ArrayList<String>();
|
public static final Predicate<CardRules> colorlessCards = new Predicate<CardRules>() {
|
||||||
|
@Override
|
||||||
|
public boolean isTrue(CardRules c) {
|
||||||
|
CardManaCost mc = c.getManaCost();
|
||||||
|
return mc.getColorProfile() == 0 && !mc.isEmpty();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (colors.length() > 3) {
|
public static class ContainsAllColorsFrom extends Predicate<CardRules> {
|
||||||
|
private final CardColor allowedColor;
|
||||||
|
public ContainsAllColorsFrom(CardColor color) {
|
||||||
|
allowedColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTrue(CardRules subject) {
|
||||||
|
return allowedColor.containsAllColorsFrom(subject.getManaCost().getColorProfile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class FilterCMC extends Predicate<CardRules> {
|
||||||
|
private final int min;
|
||||||
|
private final int max;
|
||||||
|
|
||||||
|
public FilterCMC(int from, int to) {
|
||||||
|
min = from; max = to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTrue(CardRules c) {
|
||||||
|
CardManaCost mc = c.getManaCost();
|
||||||
|
int cmc = mc.getCMC();
|
||||||
|
return cmc >= min && cmc <= max && !mc.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<Integer, String[]> dualLands = new HashMap<Integer, String[]>();
|
||||||
|
static {
|
||||||
|
dualLands.put(CardColor.WHITE | CardColor.BLUE, new String[]{"Tundra", "Hallowed Fountain", "Flooded Strand"});
|
||||||
|
dualLands.put(CardColor.BLACK | CardColor.BLUE, new String[]{"Underground Sea", "Watery Grave", "Polluted Delta"});
|
||||||
|
dualLands.put(CardColor.BLACK | CardColor.RED, new String[]{"Badlands", "Blood Crypt", "Bloodstained Mire"});
|
||||||
|
dualLands.put(CardColor.GREEN | CardColor.RED, new String[]{"Taiga", "Stomping Ground", "Wooded Foothills"});
|
||||||
|
dualLands.put(CardColor.GREEN | CardColor.WHITE, new String[]{"Savannah", "Temple Garden", "Windswept Heath"});
|
||||||
|
|
||||||
|
dualLands.put(CardColor.WHITE | CardColor.BLACK, new String[]{"Scrubland", "Godless Shrine", "Marsh Flats"});
|
||||||
|
dualLands.put(CardColor.BLUE | CardColor.RED, new String[]{"Volcanic Island", "Steam Vents", "Scalding Tarn"});
|
||||||
|
dualLands.put(CardColor.BLACK | CardColor.GREEN, new String[]{"Bayou", "Overgrown Tomb", "Verdant Catacombs"});
|
||||||
|
dualLands.put(CardColor.WHITE | CardColor.RED, new String[]{"Plateau","Sacred Foundry","Arid Mesa"});
|
||||||
|
dualLands.put(CardColor.GREEN | CardColor.BLUE, new String[]{"Tropical Island", "Breeding Pool", "Misty Rainforest"});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<String> getDualLandList(final CardColor color) {
|
||||||
|
|
||||||
|
final List<String> dLands = new ArrayList<String>();
|
||||||
|
|
||||||
|
if (color.countColors() > 3) {
|
||||||
dLands.add("Rupture Spire");
|
dLands.add("Rupture Spire");
|
||||||
dLands.add("Undiscovered Paradise");
|
dLands.add("Undiscovered Paradise");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colors.length() > 2) {
|
if (color.countColors() > 2) {
|
||||||
dLands.add("Evolving Wilds");
|
dLands.add("Evolving Wilds");
|
||||||
dLands.add("Terramorphic Expanse");
|
dLands.add("Terramorphic Expanse");
|
||||||
}
|
}
|
||||||
|
for(Entry<Integer, String[]> dual : dualLands.entrySet()) {
|
||||||
if (colors.contains("W") && colors.contains("U")) {
|
if( color.hasAllColors(dual.getKey()) ) {
|
||||||
dLands.add("Tundra");
|
for(String s : dual.getValue())
|
||||||
dLands.add("Hallowed Fountain");
|
dLands.add(s);
|
||||||
dLands.add("Flooded Strand");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colors.contains("U") && colors.contains("B")) {
|
|
||||||
dLands.add("Underground Sea");
|
|
||||||
dLands.add("Watery Grave");
|
|
||||||
dLands.add("Polluted Delta");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("B") && colors.contains("R")) {
|
|
||||||
dLands.add("Badlands");
|
|
||||||
dLands.add("Blood Crypt");
|
|
||||||
dLands.add("Bloodstained Mire");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("R") && colors.contains("G")) {
|
|
||||||
dLands.add("Taiga");
|
|
||||||
dLands.add("Stomping Ground");
|
|
||||||
dLands.add("Wooded Foothills");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("G") && colors.contains("W")) {
|
|
||||||
dLands.add("Savannah");
|
|
||||||
dLands.add("Temple Garden");
|
|
||||||
dLands.add("Windswept Heath");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("W") && colors.contains("B")) {
|
|
||||||
dLands.add("Scrubland");
|
|
||||||
dLands.add("Godless Shrine");
|
|
||||||
dLands.add("Marsh Flats");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("U") && colors.contains("R")) {
|
|
||||||
dLands.add("Volcanic Island");
|
|
||||||
dLands.add("Steam Vents");
|
|
||||||
dLands.add("Scalding Tarn");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("B") && colors.contains("G")) {
|
|
||||||
dLands.add("Bayou");
|
|
||||||
dLands.add("Overgrown Tomb");
|
|
||||||
dLands.add("Verdant Catacombs");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("R") && colors.contains("W")) {
|
|
||||||
dLands.add("Plateau");
|
|
||||||
dLands.add("Sacred Foundry");
|
|
||||||
dLands.add("Arid Mesa");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (colors.contains("G") && colors.contains("U")) {
|
|
||||||
dLands.add("Tropical Island");
|
|
||||||
dLands.add("Breeding Pool");
|
|
||||||
dLands.add("Misty Rainforest");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dLands;
|
return dLands;
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import forge.AllZone;
|
|
||||||
import forge.Card;
|
|
||||||
import forge.CardList;
|
|
||||||
import forge.error.ErrorViewer;
|
import forge.error.ErrorViewer;
|
||||||
|
import forge.item.CardDb;
|
||||||
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPool;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,7 +41,7 @@ import forge.util.MyRandom;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
public class GenerateThemeDeck {
|
public class GenerateThemeDeck extends GenerateColoredDeckBase{
|
||||||
private BufferedReader in = null;
|
private BufferedReader in = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,8 +96,8 @@ public class GenerateThemeDeck {
|
|||||||
* a int.
|
* a int.
|
||||||
* @return a {@link forge.CardList} object.
|
* @return a {@link forge.CardList} object.
|
||||||
*/
|
*/
|
||||||
public final CardList getThemeDeck(final String themeName, final int size) {
|
public final ItemPoolView<CardPrinted> getThemeDeck(final String themeName, final int size) {
|
||||||
final CardList tDeck = new CardList();
|
final ItemPool<CardPrinted> tDeck = new ItemPool<CardPrinted>(CardPrinted.class);
|
||||||
|
|
||||||
final ArrayList<Grp> groups = new ArrayList<Grp>();
|
final ArrayList<Grp> groups = new ArrayList<Grp>();
|
||||||
|
|
||||||
@@ -197,7 +198,7 @@ public class GenerateThemeDeck {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final int n = cardCounts.get(s);
|
final int n = cardCounts.get(s);
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(s, AllZone.getComputerPlayer()));
|
tDeck.add(CardDb.instance().getCard(s));
|
||||||
cardCounts.put(s, n + 1);
|
cardCounts.put(s, n + 1);
|
||||||
tmpDeck += s + "\n";
|
tmpDeck += s + "\n";
|
||||||
|
|
||||||
@@ -210,94 +211,18 @@ public class GenerateThemeDeck {
|
|||||||
numBLands = (int) (p * size);
|
numBLands = (int) (p * size);
|
||||||
} else { // otherwise, just fill in the rest of the deck with basic
|
} else { // otherwise, just fill in the rest of the deck with basic
|
||||||
// lands
|
// lands
|
||||||
numBLands = size - tDeck.size();
|
numBLands = size - tDeck.countAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpDeck += "numBLands:" + numBLands + "\n";
|
tmpDeck += "numBLands:" + numBLands + "\n";
|
||||||
|
|
||||||
if (numBLands > 0) {
|
addBasicLand(tDeck, numBLands);
|
||||||
// attempt to optimize basic land counts according to
|
|
||||||
// color representation
|
|
||||||
final CCnt[] clrCnts = { new CCnt("Plains", 0), new CCnt("Island", 0), new CCnt("Swamp", 0),
|
|
||||||
new CCnt("Mountain", 0), new CCnt("Forest", 0) };
|
|
||||||
|
|
||||||
// count each instance of a color in mana costs
|
tmpDeck += "DeckSize:" + tDeck.countAll() + "\n";
|
||||||
// TODO count hybrid mana differently?
|
|
||||||
for (int i = 0; i < tDeck.size(); i++) {
|
|
||||||
final String mc = tDeck.get(i).getManaCost();
|
|
||||||
|
|
||||||
for (int j = 0; j < mc.length(); j++) {
|
adjustDeckSize(tDeck, size);
|
||||||
final char c = mc.charAt(j);
|
|
||||||
|
|
||||||
if (c == 'W') {
|
tmpDeck += "DeckSize:" + tDeck.countAll() + "\n";
|
||||||
clrCnts[0].count++;
|
|
||||||
} else if (c == 'U') {
|
|
||||||
clrCnts[1].count++;
|
|
||||||
} else if (c == 'B') {
|
|
||||||
clrCnts[2].count++;
|
|
||||||
} else if (c == 'R') {
|
|
||||||
clrCnts[3].count++;
|
|
||||||
} else if (c == 'G') {
|
|
||||||
clrCnts[4].count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int totalColor = 0;
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
totalColor += clrCnts[i].count;
|
|
||||||
tmpDeck += clrCnts[i].color + ":" + clrCnts[i].count + "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeck += "totalColor:" + totalColor + "\n";
|
|
||||||
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
if (clrCnts[i].count > 0) { // calculate number of lands for
|
|
||||||
// each color
|
|
||||||
final float p = (float) clrCnts[i].count / (float) totalColor;
|
|
||||||
final int nLand = (int) (numBLands * p);
|
|
||||||
tmpDeck += "numLand-" + clrCnts[i].color + ":" + nLand + "\n";
|
|
||||||
|
|
||||||
cardCounts.put(clrCnts[i].color, 2);
|
|
||||||
for (int j = 0; j < nLand; j++) {
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(clrCnts[i].color, AllZone.getComputerPlayer()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
|
|
||||||
|
|
||||||
if (tDeck.size() < size) {
|
|
||||||
final int diff = size - tDeck.size();
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
s = tDeck.get(r.nextInt(tDeck.size())).getName();
|
|
||||||
|
|
||||||
while (cardCounts.get(s) >= 4) {
|
|
||||||
s = tDeck.get(r.nextInt(tDeck.size())).getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
final int n = cardCounts.get(s);
|
|
||||||
tDeck.add(AllZone.getCardFactory().getCard(s, AllZone.getComputerPlayer()));
|
|
||||||
cardCounts.put(s, n + 1);
|
|
||||||
tmpDeck += "Added:" + s + "\n";
|
|
||||||
}
|
|
||||||
} else if (tDeck.size() > size) {
|
|
||||||
final int diff = tDeck.size() - size;
|
|
||||||
|
|
||||||
for (int i = 0; i < diff; i++) {
|
|
||||||
Card c = tDeck.get(r.nextInt(tDeck.size()));
|
|
||||||
|
|
||||||
while (c.isBasicLand()) {
|
|
||||||
c = tDeck.get(r.nextInt(tDeck.size()));
|
|
||||||
}
|
|
||||||
|
|
||||||
tDeck.remove(c);
|
|
||||||
tmpDeck += "Removed:" + s + "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDeck += "DeckSize:" + tDeck.size() + "\n";
|
|
||||||
if (testing) {
|
if (testing) {
|
||||||
ErrorViewer.showError(tmpDeck);
|
ErrorViewer.showError(tmpDeck);
|
||||||
}
|
}
|
||||||
@@ -326,28 +251,6 @@ public class GenerateThemeDeck {
|
|||||||
}
|
}
|
||||||
} // readLine(Card)
|
} // readLine(Card)
|
||||||
|
|
||||||
private class CCnt {
|
|
||||||
|
|
||||||
/** The Color. */
|
|
||||||
private final String color;
|
|
||||||
|
|
||||||
/** The Count. */
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiates a new c cnt.
|
|
||||||
*
|
|
||||||
* @param clr
|
|
||||||
* the clr
|
|
||||||
* @param cnt
|
|
||||||
* the cnt
|
|
||||||
*/
|
|
||||||
public CCnt(final String clr, final int cnt) {
|
|
||||||
this.color = clr;
|
|
||||||
this.count = cnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Grp {
|
private class Grp {
|
||||||
|
|
||||||
/** The Cardnames. */
|
/** The Cardnames. */
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ public final class MenuCommon extends MenuBase<Deck> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final Deck genConstructed = new Deck();
|
final Deck genConstructed = new Deck();
|
||||||
genConstructed.getMain().add((new Generate2ColorDeck("AI", "AI")).get2ColorDeck(60, PlayerType.HUMAN));
|
genConstructed.getMain().addAll((new Generate2ColorDeck("AI", "AI")).get2ColorDeck(60, PlayerType.HUMAN));
|
||||||
this.getController().setModel(genConstructed);
|
this.getController().setModel(genConstructed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import forge.gui.OverlayUtils;
|
|||||||
import forge.gui.home.ICSubmenu;
|
import forge.gui.home.ICSubmenu;
|
||||||
import forge.gui.toolbox.FLabel;
|
import forge.gui.toolbox.FLabel;
|
||||||
import forge.item.CardPrinted;
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.quest.QuestController;
|
import forge.quest.QuestController;
|
||||||
@@ -372,7 +373,7 @@ public enum CSubmenuConstructed implements ICSubmenu {
|
|||||||
|
|
||||||
/** Generates deck from current list selection(s). */
|
/** Generates deck from current list selection(s). */
|
||||||
private Deck generateDeck(final JList lst0, final PlayerType player0) {
|
private Deck generateDeck(final JList lst0, final PlayerType player0) {
|
||||||
CardList cards = null;
|
ItemPoolView<CardPrinted> cards = null;
|
||||||
final String[] selection = Arrays.copyOf(lst0.getSelectedValues(),
|
final String[] selection = Arrays.copyOf(lst0.getSelectedValues(),
|
||||||
lst0.getSelectedValues().length, String[].class);
|
lst0.getSelectedValues().length, String[].class);
|
||||||
|
|
||||||
@@ -406,7 +407,7 @@ public enum CSubmenuConstructed implements ICSubmenu {
|
|||||||
|
|
||||||
// After generating card lists, build deck.
|
// After generating card lists, build deck.
|
||||||
deck = new Deck();
|
deck = new Deck();
|
||||||
deck.getMain().add(cards);
|
deck.getMain().addAll(cards);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Theme deck
|
// Theme deck
|
||||||
@@ -416,7 +417,7 @@ public enum CSubmenuConstructed implements ICSubmenu {
|
|||||||
|
|
||||||
// After generating card lists, build deck.
|
// After generating card lists, build deck.
|
||||||
deck = new Deck();
|
deck = new Deck();
|
||||||
deck.getMain().add(cards);
|
deck.getMain().addAll(cards);
|
||||||
}
|
}
|
||||||
else if (lst0.getName().equals(ESubmenuConstructedTypes.QUESTEVENTS.toString())) {
|
else if (lst0.getName().equals(ESubmenuConstructedTypes.QUESTEVENTS.toString())) {
|
||||||
deck = quest.getDuelsManager().getEvent(selection[0]).getEventDeck();
|
deck = quest.getDuelsManager().getEvent(selection[0]).getEventDeck();
|
||||||
|
|||||||
@@ -224,7 +224,14 @@ public class ItemPool<T extends InventoryItem> extends ItemPoolView<T> {
|
|||||||
for (final Entry<T, Integer> e : map) {
|
for (final Entry<T, Integer> e : map) {
|
||||||
this.remove(e.getKey(), e.getValue());
|
this.remove(e.getKey(), e.getValue());
|
||||||
}
|
}
|
||||||
this.setListInSync(false);
|
// need not set out-of-sync: either remove did set, or nothing was removed
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAllFlat(final Iterable<T> flat) {
|
||||||
|
for (final T e : flat) {
|
||||||
|
this.remove(e);
|
||||||
|
}
|
||||||
|
// need not set out-of-sync: either remove did set, or nothing was removed
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -57,7 +57,9 @@ public abstract class Predicate<T> {
|
|||||||
/** The NOR. */
|
/** The NOR. */
|
||||||
NOR,
|
NOR,
|
||||||
/** The NAND. */
|
/** The NAND. */
|
||||||
NAND
|
NAND,
|
||||||
|
GT,
|
||||||
|
LT
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1016,6 +1018,10 @@ class Node<T> extends Predicate<T> {
|
|||||||
switch (this.operator) {
|
switch (this.operator) {
|
||||||
case AND:
|
case AND:
|
||||||
return this.getFilter1().isTrue(card) && this.getFilter2().isTrue(card);
|
return this.getFilter1().isTrue(card) && this.getFilter2().isTrue(card);
|
||||||
|
case GT:
|
||||||
|
return this.getFilter1().isTrue(card) && !this.getFilter2().isTrue(card);
|
||||||
|
case LT:
|
||||||
|
return !this.getFilter1().isTrue(card) && this.getFilter2().isTrue(card);
|
||||||
case NAND:
|
case NAND:
|
||||||
return !(this.getFilter1().isTrue(card) && this.getFilter2().isTrue(card));
|
return !(this.getFilter1().isTrue(card) && this.getFilter2().isTrue(card));
|
||||||
case OR:
|
case OR:
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package forge.deck.generate;
|
|||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import forge.CardList;
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by IntelliJ IDEA. User: dhudson
|
* Created by IntelliJ IDEA. User: dhudson
|
||||||
@@ -17,7 +18,7 @@ public class Generate2ColorDeckTest {
|
|||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
public void generate2ColorDeckTest1() {
|
public void generate2ColorDeckTest1() {
|
||||||
final Generate2ColorDeck gen = new Generate2ColorDeck("white", "blue");
|
final Generate2ColorDeck gen = new Generate2ColorDeck("white", "blue");
|
||||||
final CardList cardList = gen.get2ColorDeck(60, null);
|
final ItemPoolView<CardPrinted> cardList = gen.get2ColorDeck(60, null);
|
||||||
Assert.assertNotNull(cardList);
|
Assert.assertNotNull(cardList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package forge.deck.generate;
|
|||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import forge.CardList;
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by IntelliJ IDEA. User: dhudson
|
* Created by IntelliJ IDEA. User: dhudson
|
||||||
@@ -17,7 +18,7 @@ public class Generate3ColorDeckTest {
|
|||||||
@Test(timeOut = 1000, enabled = false)
|
@Test(timeOut = 1000, enabled = false)
|
||||||
public void generate3ColorDeckTest1() {
|
public void generate3ColorDeckTest1() {
|
||||||
final Generate3ColorDeck gen = new Generate3ColorDeck("white", "blue", "black");
|
final Generate3ColorDeck gen = new Generate3ColorDeck("white", "blue", "black");
|
||||||
final CardList cardList = gen.get3ColorDeck(60, null);
|
final ItemPoolView<CardPrinted> cardList = gen.get3ColorDeck(60, null);
|
||||||
Assert.assertNotNull(cardList);
|
Assert.assertNotNull(cardList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,8 @@ package forge.deck.generate;
|
|||||||
import org.testng.Assert;
|
import org.testng.Assert;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import forge.CardList;
|
import forge.item.CardPrinted;
|
||||||
|
import forge.item.ItemPoolView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by IntelliJ IDEA. User: dhudson
|
* Created by IntelliJ IDEA. User: dhudson
|
||||||
@@ -17,7 +18,7 @@ public class Generate5ColorDeckTest {
|
|||||||
@Test(timeOut = 1000, enabled = false)
|
@Test(timeOut = 1000, enabled = false)
|
||||||
public void generate5ColorDeckTest1() {
|
public void generate5ColorDeckTest1() {
|
||||||
final Generate5ColorDeck gen = new Generate5ColorDeck();
|
final Generate5ColorDeck gen = new Generate5ColorDeck();
|
||||||
final CardList cardList = gen.get5ColorDeck(60, null);
|
final ItemPoolView<CardPrinted> cardList = gen.get5ColorDeck(60, null);
|
||||||
Assert.assertNotNull(cardList);
|
Assert.assertNotNull(cardList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user