Completed random commander deck generation refactoring to work on Desktop, to support partner commanders and corrected a number of bugs found during testing. Full support on android and desktop for saving of selected deck states for the new features added.

This commit is contained in:
austinio7116
2018-02-21 09:28:17 +00:00
committed by maustin
parent 66763e537d
commit e8f257d2cf
9 changed files with 227 additions and 221 deletions

View File

@@ -52,14 +52,10 @@ public class CLobby {
public void update() {
SwingUtilities.invokeLater(new Runnable() {
@Override public final void run() {
final Iterable<DeckProxy> commanderDecks = DeckProxy.getAllCommanderDecks();
final Iterable<DeckProxy> tinyLeadersDecks = DeckProxy.getAllTinyLeadersDecks();
final Iterable<DeckProxy> schemeDecks = DeckProxy.getAllSchemeDecks();
final Iterable<DeckProxy> planarDecks = DeckProxy.getAllPlanarDecks();
for (int i = 0; i < VLobby.MAX_PLAYERS; i++) {
//addDecks(commanderDecks, view.getCommanderDeckLists().get(i));
//addDecks(tinyLeadersDecks, view.getTinyLeadersDeckLists().get(i));
addDecks(schemeDecks, view.getSchemeDeckLists().get(i),
"Use deck's scheme section (random if unavailable)");
addDecks(planarDecks, view.getPlanarDeckLists().get(i),
@@ -84,7 +80,7 @@ public class CLobby {
}
});*/
final FDeckChooser fdccom = view.getCommanderDeckChooser(iSlot);
fdccom.initialize(FPref.CONSTRUCTED_DECK_STATES[iSlot], defaultDeckTypeForSlot(iSlot));
fdccom.initialize(FPref.COMMANDER_DECK_STATES[iSlot], defaultDeckTypeForCommanderSlot(iSlot));
fdccom.populate();
fdccom.getDecksComboBox().addListener(new IDecksComboBoxListener() {
@Override public final void deckTypeSelected(final DecksComboBoxEvent ev) {
@@ -92,7 +88,7 @@ public class CLobby {
}
});
final FDeckChooser fdtlcom = view.getTinyLeaderDeckChooser(iSlot);
fdtlcom.initialize(FPref.CONSTRUCTED_DECK_STATES[iSlot], defaultDeckTypeForSlot(iSlot));
fdtlcom.initialize(FPref.TINY_LEADER_DECK_STATES[iSlot], defaultDeckTypeForTinyLeaderSlot(iSlot));
fdtlcom.populate();
fdtlcom.getDecksComboBox().addListener(new IDecksComboBoxListener() {
@Override public final void deckTypeSelected(final DecksComboBoxEvent ev) {
@@ -125,6 +121,14 @@ public class CLobby {
}
private static DeckType defaultDeckTypeForSlot(final int iSlot) {
return iSlot == 0 ? DeckType.RANDOM_COMMANDER_DECK : DeckType.RANDOM_CARDGEN_COMMANDER_DECK;
return iSlot == 0 ? DeckType.PRECONSTRUCTED_DECK : DeckType.COLOR_DECK;
}
private static DeckType defaultDeckTypeForCommanderSlot(final int iSlot) {
return iSlot == 0 ? DeckType.COMMANDER_DECK : DeckType.RANDOM_CARDGEN_COMMANDER_DECK;
}
private static DeckType defaultDeckTypeForTinyLeaderSlot(final int iSlot) {
return iSlot == 0 ? DeckType.TINY_LEADERS_DECKS : DeckType.RANDOM_CARDGEN_COMMANDER_DECK;
}
}

View File

@@ -148,7 +148,8 @@ public class FDeckChooser extends FScreen {
public void handleEvent(FEvent e) {
if (selectedDeckType != DeckType.STANDARD_COLOR_DECK && selectedDeckType != DeckType.STANDARD_CARDGEN_DECK
&& selectedDeckType != DeckType.MODERN_CARDGEN_DECK && selectedDeckType != DeckType.MODERN_COLOR_DECK &&
selectedDeckType != DeckType.COLOR_DECK && selectedDeckType != DeckType.THEME_DECK) {
selectedDeckType != DeckType.COLOR_DECK && selectedDeckType != DeckType.THEME_DECK
&& selectedDeckType != DeckType.RANDOM_COMMANDER_DECK && selectedDeckType != DeckType.RANDOM_CARDGEN_COMMANDER_DECK) {
FDeckViewer.show(getDeck());
}
}
@@ -269,6 +270,8 @@ public class FDeckChooser extends FScreen {
case COLOR_DECK:
case STANDARD_COLOR_DECK:
case STANDARD_CARDGEN_DECK:
case RANDOM_CARDGEN_COMMANDER_DECK:
case RANDOM_COMMANDER_DECK:
case MODERN_CARDGEN_DECK:
case MODERN_COLOR_DECK:
case THEME_DECK:
@@ -453,7 +456,9 @@ public class FDeckChooser extends FScreen {
case TinyLeaders:
cmbDeckTypes.addItem(DeckType.CUSTOM_DECK);
cmbDeckTypes.addItem(DeckType.RANDOM_DECK);
cmbDeckTypes.addItem(DeckType.RANDOM_CARDGEN_COMMANDER_DECK);
if(!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY)) {
cmbDeckTypes.addItem(DeckType.RANDOM_CARDGEN_COMMANDER_DECK);
}
cmbDeckTypes.addItem(DeckType.RANDOM_COMMANDER_DECK);
cmbDeckTypes.addItem(DeckType.NET_DECK);
break;

View File

@@ -155,21 +155,29 @@ public final class CardRelationMatrixGenerator {
for (PaperCard card:legends){
for (Deck deck:decks){
if (deck.getCommanders().size()==1&&deck.getCommanders().contains(card)){
if (deck.getCommanders().contains(card)){
for (PaperCard pairCard:Iterables.filter(deck.getMain().toFlatList(),
Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES))){
if (!pairCard.getName().equals(card.getName())&&
new DeckGeneratorBase.MatchColorIdentity(card.getRules().getColorIdentity()).apply(pairCard.getRules())){
if (!pairCard.getName().equals(card.getName())){
try {
int old = matrix[legendIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())];
matrix[legendIntegerMap.get(card.getName())][cardIntegerMap.get(pairCard.getName())] = old + 1;
}catch (NullPointerException ne){
//Todo: Not sure what was failing here
ne.printStackTrace();
}
}
}
if(deck.getCommanders().size()>1){//add partner commanders to matrix
for(PaperCard commander:deck.getCommanders()){
if(!commander.equals(card)){
int old = matrix[legendIntegerMap.get(card.getName())][cardIntegerMap.get(commander.getName())];
matrix[legendIntegerMap.get(card.getName())][cardIntegerMap.get(commander.getName())] = old + 1;
}
}
}
}
}
}
@@ -180,7 +188,13 @@ public final class CardRelationMatrixGenerator {
int[] distances = matrix[col];
int max = (Integer) Collections.max(Arrays.asList(ArrayUtils.toObject(distances)));
if (max>0) {
ArrayIndexComparator comparator = new ArrayIndexComparator(ArrayUtils.toObject(distances));
List<Map.Entry<PaperCard,Integer>> deckPool=new ArrayList<>();
for(int k=0;k<cardList.size(); k++){
if(matrix[col][k]>0){
deckPool.add(new AbstractMap.SimpleEntry<PaperCard, Integer>(integerCardMap.get(k),matrix[col][k]));
}
}
/* ArrayIndexComparator comparator = new ArrayIndexComparator(ArrayUtils.toObject(distances));
Integer[] indices = comparator.createIndexArray();
Arrays.sort(indices, comparator);
List<Map.Entry<PaperCard,Integer>> deckPool=new ArrayList<>();
@@ -197,7 +211,7 @@ public final class CardRelationMatrixGenerator {
}
deckPool.add(new AbstractMap.SimpleEntry<PaperCard, Integer>(cardToAdd,distances[indices[cardList.size()-1-k]]));
};
/*if(excludeThisCard){
*//*if(excludeThisCard){
continue;
}*/
cardPools.put(card.getName(),deckPool);

View File

@@ -59,13 +59,23 @@ public enum DeckType {
}
}
static {
CommanderOptions = new DeckType[]{
DeckType.COMMANDER_DECK,
DeckType.RANDOM_COMMANDER_DECK,
DeckType.RANDOM_CARDGEN_COMMANDER_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_COMMANDER_DECK
};
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY)) {
CommanderOptions = new DeckType[]{
DeckType.COMMANDER_DECK,
DeckType.RANDOM_COMMANDER_DECK,
DeckType.RANDOM_CARDGEN_COMMANDER_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_COMMANDER_DECK
};
}else{
CommanderOptions = new DeckType[]{
DeckType.COMMANDER_DECK,
DeckType.RANDOM_COMMANDER_DECK,
DeckType.RANDOM_DECK,
DeckType.NET_COMMANDER_DECK
};
}
}
private String value;

View File

@@ -539,33 +539,51 @@ public class DeckgenUtil {
final Deck deck;
IDeckGenPool cardDb;
DeckGeneratorBase gen = null;
PaperCard selectedPartner=null;
if(isCardGen){
List<Map.Entry<PaperCard,Integer>> potentialCards = new ArrayList<>();
potentialCards.addAll(CardRelationMatrixGenerator.cardPools.get(DeckFormat.Commander.toString()).get(commander.getName()));
Collections.shuffle(potentialCards);
//get second keycard
Random r = new Random();
//Collections.shuffle(potentialCards, r);
List<PaperCard> preSelectedCards = new ArrayList<>();
for(Map.Entry<PaperCard,Integer> pair:potentialCards){
preSelectedCards.add(pair.getKey());
if(format.isLegalCard(pair.getKey())) {
preSelectedCards.add(pair.getKey());
}
}
//check for partner commanders
List<PaperCard> partners=new ArrayList<>();
for(PaperCard c:preSelectedCards){
if(c.getRules().canBePartnerCommander()){
partners.add(c);
}
}
if(partners.size()>0&&commander.getRules().canBePartnerCommander()){
selectedPartner=partners.get(MyRandom.getRandom().nextInt(partners.size()));
preSelectedCards.remove(selectedPartner);
}
//randomly remove cards
int removeCount=0;
int i=0;
List<PaperCard> toRemove = new ArrayList<>();
for(PaperCard c:preSelectedCards){
if(preSelectedCards.size()<80){
if(!format.isLegalCard(c)){
toRemove.add(c);
removeCount++;
}
if(preSelectedCards.size()<75){
break;
}
if(r.nextInt(100)>70+(15-(i/preSelectedCards.size())*preSelectedCards.size()) && removeCount<4 //randomly remove some cards - more likely as distance increases
&&!c.getName().contains("Urza")){ //avoid breaking Tron decks
if(r.nextInt(100)>60+(15-(i/preSelectedCards.size())*preSelectedCards.size()) && removeCount<4 //randomly remove some cards - more likely as distance increases
&&!c.getName().contains("Urza")&&!c.getName().contains("Wastes")){ //avoid breaking Tron decks
toRemove.add(c);
removeCount++;
}
++i;
}
preSelectedCards.removeAll(toRemove);
gen = new CardThemedCommanderDeckBuilder(commander,preSelectedCards,forAi);
gen = new CardThemedCommanderDeckBuilder(commander, selectedPartner,preSelectedCards,forAi,format);
}else{
cardDb = FModel.getMagicDb().getCommonCards();
ColorSet colorID;
@@ -598,10 +616,18 @@ public class DeckgenUtil {
CardPool cards = gen.getDeck(format.getMainRange().getMaximum(), forAi);
// After generating card lists, build deck.
deck = new Deck("Generated " + format.toString() + " deck (" + commander.getName() + ")");
if(selectedPartner!=null){
deck = new Deck("Generated " + format.toString() + " deck (" + commander.getName() +
"--" + selectedPartner.getName() + ")");
}else{
deck = new Deck("Generated " + format.toString() + " deck (" + commander.getName() + ")");
}
deck.setDirectory("generated/commander");
deck.getMain().addAll(cards);
deck.getOrCreate(DeckSection.Commander).add(commander);
if(selectedPartner!=null){
deck.getOrCreate(DeckSection.Commander).add(selectedPartner);
}
return deck;
}

View File

@@ -13,7 +13,6 @@ import forge.deck.DeckFormat;
import forge.deck.DeckSection;
import forge.deck.generation.DeckGenPool;
import forge.deck.generation.DeckGeneratorBase;
import forge.game.GameFormat;
import forge.item.IPaperCard;
import forge.item.PaperCard;
import forge.model.FModel;
@@ -38,10 +37,13 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
return 0.23f;
}
protected int numSpellsNeeded = 55;
protected int landsNeeded = 44;
protected int targetSize;
protected int numSpellsNeeded;
protected int numCreaturesToStart;
protected int landsNeeded;
protected final PaperCard keyCard;
protected final PaperCard commanderCard;
protected final PaperCard partnerCard;
protected Predicate<CardRules> hasColor;
protected final List<PaperCard> availableList;
@@ -53,10 +55,9 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
// Views for aiPlayable
protected Iterable<PaperCard> onColorCreatures;
protected Iterable<PaperCard> onColorNonCreatures;
protected Iterable<PaperCard> keyCards;
protected static final boolean logToConsole = true;
protected static final boolean logColorsToConsole = true;
protected static final boolean logToConsole = false;
protected static final boolean logColorsToConsole = false;
/**
@@ -66,10 +67,11 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
* @param dList
* Cards to build the deck from.
*/
public CardThemedCommanderDeckBuilder(PaperCard keyCard0, final List<PaperCard> dList, boolean isForAI) {
super(FModel.getMagicDb().getCommonCards(), DeckFormat.Commander);
public CardThemedCommanderDeckBuilder(PaperCard commanderCard0,PaperCard partner0, final List<PaperCard> dList, boolean isForAI, DeckFormat format) {
super(FModel.getMagicDb().getCommonCards(), format);
this.availableList = dList;
keyCard=keyCard0;
commanderCard = commanderCard0;
partnerCard = partner0;
// remove Unplayables
if(isForAI) {
final Iterable<PaperCard> playables = Iterables.filter(availableList,
@@ -79,16 +81,18 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
this.aiPlayables = Lists.newArrayList(availableList);
}
this.availableList.removeAll(aiPlayables);
colors = keyCard.getRules().getColorIdentity();
if (logColorsToConsole) {
System.out.println(keyCard.getName());
System.out.println("Pre Colors: " + colors.toEnumSet().toString());
}
if(!colors.hasAllColors(keyCard.getRules().getColorIdentity().getColor())){
colors = ColorSet.fromMask(colors.getColor() | keyCard.getRules().getColorIdentity().getColor());
targetSize=format.getMainRange().getMinimum();
colors = commanderCard.getRules().getColorIdentity();
colors = ColorSet.fromMask(colors.getColor() | commanderCard.getRules().getColorIdentity().getColor());
if(partnerCard!=null) {
colors = ColorSet.fromMask(colors.getColor() | partnerCard.getRules().getColorIdentity().getColor());
targetSize--;
}
numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue();
numCreaturesToStart = ((Double)Math.ceil(targetSize*(getCreaturePercentage()))).intValue();
landsNeeded = ((Double)Math.ceil(targetSize*(getLandPercentage()))).intValue();;
if (logColorsToConsole) {
System.out.println(keyCard.getName());
System.out.println(commanderCard.getName());
System.out.println("Pre Colors: " + colors.toEnumSet().toString());
}
findBasicLandSets();
@@ -113,7 +117,7 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
// 1. Prepare
hasColor = Predicates.or(new MatchColorIdentity(colors), COLORLESS_CARDS);
if (logColorsToConsole) {
System.out.println(keyCard.getName());
System.out.println(commanderCard.getName());
System.out.println("Colors: " + colors.toEnumSet().toString());
}
Iterable<PaperCard> colorList = Iterables.filter(aiPlayables,
@@ -131,19 +135,19 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
// 3. Add creatures, trying to follow mana curve
addManaCurveCreatures(onColorCreatures, 30);
addManaCurveCards(onColorCreatures, numCreaturesToStart, "Creatures");
if (logToConsole) {
System.out.println("Post Creatures : " + deckList.size());
}
// 4.Try to fill up to num needed with on-color non-creature cards
addNonCreatures(onColorNonCreatures, numSpellsNeeded - deckList.size());
addManaCurveCards(onColorNonCreatures, numSpellsNeeded - deckList.size(), "Spells");
if (logToConsole) {
System.out.println("Post Spells : " + deckList.size());
}
// 5.If we couldn't get enough, try to fill up with on-color creature cards
addCreatures(onColorCreatures, numSpellsNeeded - deckList.size());
// 5.If we couldn't get enough, try to fill up with on-color cards
addCards(rankedColorList, numSpellsNeeded - deckList.size());
if (logToConsole) {
System.out.println("Post more creatures : " + deckList.size());
}
@@ -154,24 +158,30 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
int maxCMC=getMaxCMC(deckList);
if (deckList.size() == numSpellsNeeded && avCMC < 4) {
addLowCMCCard();
if(targetSize>60){
addLowCMCCard();
}
}
if (deckList.size() >= numSpellsNeeded && avCMC < 3 && maxCMC<6) {
addLowCMCCard();
}
if (deckList.size() >= numSpellsNeeded && avCMC < 2.5 && maxCMC<5) {
addLowCMCCard();
if(targetSize>60){
addLowCMCCard();
}
}
if (logToConsole) {
System.out.println("Post lowcoc : " + deckList.size());
}
// 7. If not enough cards yet, try to add a third color,
/* // 7. If not enough cards yet, try to add a third color,
// to try and avoid adding purely random cards.
addThirdColorCards(numSpellsNeeded - deckList.size());
if (logColorsToConsole) {
System.out.println("Post 3rd colour : " + deckList.size());
System.out.println("Colors: " + colors.toEnumSet().toString());
}
}*/
// 8. Check for DeckNeeds cards.
//checkRemRandomDeckCards(); - no need
@@ -182,19 +192,7 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
if (logToConsole) {
System.out.println("Post Randoms : " + deckList.size());
}
//update colors
FullDeckColors finalDeckColors = new FullDeckColors();
for(PaperCard c:deckList){
if(finalDeckColors.canChoseMoreColors()){
finalDeckColors.addColorsOf(c);
}
}
colors = finalDeckColors.getChosenColors();
if (logColorsToConsole) {
System.out.println("Final Colors: " + colors.toEnumSet().toString());
}
// 10. Add non-basic lands that were drafted.
addWastesIfRequired();
List<String> duals = getDualLandList();
addNonBasicLands();
if (logToConsole) {
@@ -221,7 +219,11 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
if (logToConsole) {
System.out.println("Post Lands : " + deckList.size());
}
fixDeckSize(clrCnts);
if (commanderCard.getRules().getColorIdentity().isColorless()&&landsNeeded>0){
// 10. Add non-basic lands that were drafted.
addWastesIfRequired();
}
fixDeckSize();
if (logToConsole) {
System.out.println("Post Size fix : " + deckList.size());
}
@@ -240,6 +242,8 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
PaperCard sbCard = potentialSideboard.iterator().next();
cp.add(sbCard);
aiPlayables.remove(sbCard);
rankedColorList.remove(sbCard);
++i;
}
@@ -264,12 +268,14 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
protected void addLowCMCCard(){
final Iterable<PaperCard> nonLands = Iterables.filter(rankedColorList,
final Iterable<PaperCard> nonLands = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
final PaperCard card = Iterables.getFirst(nonLands, null);
if (card != null) {
deckList.add(card);
aiPlayables.remove(card);
rankedColorList.remove(card);
landsNeeded--;
if (logToConsole) {
System.out.println("Low CMC: " + card.getName());
@@ -301,7 +307,7 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
* @return name
*/
private String generateName() {
return keyCard.getName() +" based commander deck";
return commanderCard.getName() +" based commander deck";
}
/**
@@ -332,11 +338,9 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
* If the deck does not have 40 cards, fix it. This method should not be
* called if the stuff above it is working correctly.
*
* @param clrCnts
* color counts needed
*/
private void fixDeckSize(final int[] clrCnts) {
while (deckList.size() > 99) {
private void fixDeckSize() {
while (deckList.size() > targetSize) {
if (logToConsole) {
System.out.println("WARNING: Fixing deck size, currently " + deckList.size() + " cards.");
}
@@ -347,37 +351,33 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
System.out.println(" - Removed " + c.getName() + " randomly.");
}
}
if(deckList.size()==targetSize){
return;
}
while (deckList.size() < 99) {
Predicate<PaperCard> possibleFromFullPool = new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
return format.isLegalCard(card)
&&!card.getRules().getManaCost().isPureGeneric()
&& colors.containsAllColorsFrom(card.getRules().getColorIdentity().getColor())
&& !deckList.contains(card)
&&!card.getRules().getAiHints().getRemAIDecks()
&&!card.getRules().getAiHints().getRemRandomDecks()
&&!card.getRules().getMainPart().getType().isLand();
}
};
List<PaperCard> randomPool = Lists.newArrayList(pool.getAllCards(possibleFromFullPool));
Collections.shuffle(randomPool,new Random());
Iterator<PaperCard> iRandomPool=randomPool.iterator();
while (deckList.size() < targetSize) {
if (logToConsole) {
System.out.println("WARNING: Fixing deck size, currently " + deckList.size() + " cards.");
}
if (aiPlayables.size() > 1) {
final PaperCard c = aiPlayables.get(MyRandom.getRandom().nextInt(aiPlayables.size() - 1));
deckList.add(c);
aiPlayables.remove(c);
if (logToConsole) {
System.out.println(" - Added " + c.getName() + " randomly.");
}
} else if (aiPlayables.size() == 1) {
final PaperCard c = aiPlayables.get(0);
deckList.add(c);
aiPlayables.remove(c);
if (logToConsole) {
System.out.println(" - Added " + c.getName() + " randomly.");
}
} else {
// if no playable cards remain fill up with basic lands
for (int i = 0; i < 5; i++) {
if (clrCnts[i] > 0) {
final PaperCard cp = getBasicLand(i);
deckList.add(cp);
if (logToConsole) {
System.out.println(" - Added " + cp.getName() + " as last resort.");
}
break;
}
}
PaperCard randomCard = iRandomPool.next();
deckList.add(randomCard);
if (logToConsole) {
System.out.println(" - Added " + randomCard.getName() + " randomly.");
}
}
}
@@ -419,9 +419,11 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
numColors++;
}
}
if (totalColor == 0) {
throw new RuntimeException("Add Lands to empty deck list!");
}
/*if (totalColor == 0) {
for (int j = 0; j < nLand; j++) {
deckList.add(getBasicLand(i));
}
}*/
// do not update landsNeeded until after the loop, because the
// calculation involves landsNeeded
@@ -458,12 +460,13 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
// and nLand rounded up for both colors, so that one too many lands was added.
// So if the deck size is > 60, remove the last land added.
// Otherwise, the fixDeckSize() method would remove random cards.
while (deckList.size() > 99) {
while (deckList.size() > targetSize) {
deckList.remove(deckList.size() - 1);
}
deckList.addAll(snowLands);
aiPlayables.removeAll(snowLands);
rankedColorList.remove(snowLands);
}
/**
@@ -487,11 +490,16 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
* Only adds wastes if present in the card pool but if present adds them all
*/
private void addWastesIfRequired(){
List<PaperCard> toAdd = Lists.newArrayList(Iterables.filter(aiPlayables,PaperCard.Predicates.name("Wastes")));
deckList.addAll(toAdd);
aiPlayables.removeAll(toAdd);
rankedColorList.removeAll(toAdd);
landsNeeded = landsNeeded - toAdd.size();
Iterable<PaperCard> wastes = Iterables.filter(aiPlayables,PaperCard.Predicates.name("Wastes"));
if(wastes.iterator().hasNext()){
PaperCard waste = wastes.iterator().next();
while(landsNeeded>0) {
deckList.add(waste);
landsNeeded--;
}
aiPlayables.remove(waste);
rankedColorList.remove(waste);
}
}
/**
@@ -529,7 +537,8 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
final Iterable<PaperCard> lands = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NONBASIC_LAND, PaperCard.FN_GET_RULES));
List<PaperCard> landsToAdd = new ArrayList<>();
int minBasics=r.nextInt(6)+3;//Keep a minimum number of basics to ensure playable decks
int minBasics=Math.round(r.nextInt(6)+3)*targetSize/60;//Keep a minimum number of basics to ensure playable decks
for (final PaperCard card : lands) {
if (landsNeeded > minBasics) {
// Throw out any dual-lands for the wrong colors. Assume
@@ -555,51 +564,9 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
}
deckList.addAll(landsToAdd);
aiPlayables.removeAll(landsToAdd);
rankedColorList.removeAll(landsToAdd);
}
/**
* Add a third color to the deck.
*
* @param num
* number to add
*/
private void addThirdColorCards(int num) {
if (num > 0) {
final Iterable<PaperCard> others = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
// We haven't yet ranked the off-color cards.
// Compare them to the cards already in the deckList.
//List<PaperCard> rankedOthers = CardRanker.rankCardsInPack(others, deckList, colors, true);
List<PaperCard> toAdd = new ArrayList<>();
for (final PaperCard card : others) {
// Want a card that has just one "off" color.
final ColorSet off = colors.getOffColors(card.getRules().getColor());
if (off.isMonoColor()) {
colors = ColorSet.fromMask(colors.getColor() | off.getColor());
break;
}
}
hasColor = Predicates.and(CardRulesPredicates.Presets.IS_NON_LAND,Predicates.or(new MatchColorIdentity(colors),
DeckGeneratorBase.COLORLESS_CARDS));
final Iterable<PaperCard> threeColorList = Iterables.filter(aiPlayables,
Predicates.compose(hasColor, PaperCard.FN_GET_RULES));
for (final PaperCard card : threeColorList) {
if (num > 0) {
toAdd.add(card);
num--;
if (logToConsole) {
System.out.println("Third Color[" + num + "]:" + card.getName() + "("
+ card.getRules().getManaCost() + ")");
}
} else {
break;
}
}
deckList.addAll(toAdd);
aiPlayables.removeAll(toAdd);
}
}
/**
* Add random cards to the deck.
@@ -608,81 +575,61 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
* number to add
*/
private void addRandomCards(int num) {
final Iterable<PaperCard> others = Iterables.filter(aiPlayables,
Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES));
List <PaperCard> toAdd = new ArrayList<>();
for (final PaperCard card : others) {
if (num > 0) {
toAdd.add(card);
num--;
if (logToConsole) {
System.out.println("Random[" + num + "]:" + card.getName() + "("
+ card.getRules().getManaCost() + ")");
}
} else {
break;
Predicate<PaperCard> possibleFromFullPool = new Predicate<PaperCard>() {
@Override
public boolean apply(PaperCard card) {
return format.isLegalCard(card)
&&!card.getRules().getManaCost().isPureGeneric()
&& colors.containsAllColorsFrom(card.getRules().getColorIdentity().getColor())
&& !deckList.contains(card)
&&!card.getRules().getAiHints().getRemAIDecks()
&&!card.getRules().getAiHints().getRemRandomDecks()
&&!card.getRules().getMainPart().getType().isLand();
}
};
List<PaperCard> randomPool = Lists.newArrayList(pool.getAllCards(possibleFromFullPool));
Collections.shuffle(randomPool,new Random());
Iterator<PaperCard> iRandomPool=randomPool.iterator();
for(int i=0;i<num;++i){
PaperCard randomCard=iRandomPool.next();
deckList.add(randomCard);
if(logToConsole) {
System.out.println("Random Card[" + i + "]:" + randomCard.getName() + " (" + randomCard.getRules().getManaCost() + ")");
}
}
deckList.addAll(toAdd);
aiPlayables.removeAll(toAdd);
rankedColorList.removeAll(toAdd);
}
/**
* Add highest ranked non-creatures to the deck.
*
* @param nonCreatures
* cards to choose from
* @param num
* number to add
*/
private void addNonCreatures(final Iterable<PaperCard> nonCreatures, int num) {
List<PaperCard> toAdd = new ArrayList<>();
for (final PaperCard card : nonCreatures) {
if (num > 0) {
toAdd.add(card);
num--;
if (logToConsole) {
System.out.println("Others[" + num + "]:" + card.getName() + " ("
+ card.getRules().getManaCost() + ")");
}
} else {
break;
}
}
deckList.addAll(toAdd);
aiPlayables.removeAll(toAdd);
rankedColorList.removeAll(toAdd);
}
/**
* Add creatures to the deck.
*
* @param creatures
* @param cards
* cards to choose from
* @param num
* number to add
*/
private void addCreatures(final Iterable<PaperCard> creatures, int num) {
List<PaperCard> creaturesToAdd = new ArrayList<>();
for (final PaperCard card : creatures) {
if (num > 0) {
creaturesToAdd.add(card);
num--;
private void addCards(final Iterable<PaperCard> cards, int num) {
List<PaperCard> cardsToAdd = new ArrayList<>();
for (final PaperCard card : cards) {
if(card.getRules().getMainPart().getType().isLand()){
continue;
}
if (num +1 > 0) {
cardsToAdd.add(card);
if (logToConsole) {
System.out.println("Creature[" + num + "]:" + card.getName() + " (" + card.getRules().getManaCost() + ")");
System.out.println("Extra needed[" + num + "]:" + card.getName() + " (" + card.getRules().getManaCost() + ")");
}
num--;
} else {
break;
}
}
deckList.addAll(creaturesToAdd);
aiPlayables.removeAll(creaturesToAdd);
rankedColorList.removeAll(creaturesToAdd);
deckList.addAll(cardsToAdd);
aiPlayables.removeAll(cardsToAdd);
rankedColorList.removeAll(cardsToAdd);
}
/**
* Add creatures to the deck, trying to follow some mana curve. Trying to
* Add cards to the deck, trying to follow some mana curve. Trying to
* have generous limits at each cost, but perhaps still too strict. But
* we're trying to prevent the AI from adding everything at a single cost.
*
@@ -691,22 +638,22 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
* @param num
* number to add
*/
private void addManaCurveCreatures(final Iterable<PaperCard> creatures, int num) {
// Add the deck card
if(keyCard.getRules().getMainPart().getType().isCreature()) {
keyCards = Iterables.filter(aiPlayables,PaperCard.Predicates.name(keyCard.getName()));
private void addManaCurveCards(final Iterable<PaperCard> creatures, int num, String nameForLog) {
/* // Add the deck card
if(commanderCard.getRules().getMainPart().getType().isCreature()) {
keyCards = Iterables.filter(aiPlayables,PaperCard.Predicates.name(commanderCard.getName()));
final List<PaperCard> keyCardList = Lists.newArrayList(keyCards);
deckList.addAll(keyCardList);
aiPlayables.removeAll(keyCardList);
rankedColorList.removeAll(keyCardList);
}
}*/
final Map<Integer,Integer> targetCMCs = new HashMap<>();
targetCMCs.put(1,r.nextInt(4)+2);//2
targetCMCs.put(2,r.nextInt(5)+5);//6
targetCMCs.put(3,r.nextInt(5)+6);//7
targetCMCs.put(4,r.nextInt(3)+3);//4
targetCMCs.put(5,r.nextInt(3)+3);//3
targetCMCs.put(6,r.nextInt(3)+1);//2
targetCMCs.put(1,Math.round((r.nextInt(4)+2)*targetSize/60));//2
targetCMCs.put(2,Math.round((r.nextInt(5)+5)*targetSize/60));//6
targetCMCs.put(3,Math.round((r.nextInt(5)+6)*targetSize/60));//7
targetCMCs.put(4,Math.round((r.nextInt(3)+3)*targetSize/60));//4
targetCMCs.put(5,Math.round((r.nextInt(3)+3)*targetSize/60));//3
targetCMCs.put(6,Math.round((r.nextInt(3)+1)*targetSize/60));//2
final Map<Integer, Integer> creatureCosts = new HashMap<Integer, Integer>();
@@ -754,7 +701,7 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase {
num--;
creatureCosts.put(cmc, creatureCosts.get(cmc) + 1);
if (logToConsole) {
System.out.println("Creature[" + num + "]:" + card.getName() + " (" + card.getRules().getManaCost() + ")");
System.out.println(nameForLog+"[" + num + "]:" + card.getName() + " (" + card.getRules().getManaCost() + ")");
}
} else {
if (logToConsole) {