diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java index 1513b4d27e8..d76f52543eb 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java @@ -52,14 +52,10 @@ public class CLobby { public void update() { SwingUtilities.invokeLater(new Runnable() { @Override public final void run() { - final Iterable commanderDecks = DeckProxy.getAllCommanderDecks(); - final Iterable tinyLeadersDecks = DeckProxy.getAllTinyLeadersDecks(); final Iterable schemeDecks = DeckProxy.getAllSchemeDecks(); final Iterable 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; } } diff --git a/forge-gui-mobile/src/forge/deck/FDeckChooser.java b/forge-gui-mobile/src/forge/deck/FDeckChooser.java index eb34f6bcd95..68231957cb6 100644 --- a/forge-gui-mobile/src/forge/deck/FDeckChooser.java +++ b/forge-gui-mobile/src/forge/deck/FDeckChooser.java @@ -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; diff --git a/forge-gui/res/deckgendecks/Commander.dat b/forge-gui/res/deckgendecks/Commander.dat index ed223c418eb..a44829f6074 100644 Binary files a/forge-gui/res/deckgendecks/Commander.dat and b/forge-gui/res/deckgendecks/Commander.dat differ diff --git a/forge-gui/res/deckgendecks/Modern.dat b/forge-gui/res/deckgendecks/Modern.dat index 9f55e712f9f..fb9d8386f63 100644 Binary files a/forge-gui/res/deckgendecks/Modern.dat and b/forge-gui/res/deckgendecks/Modern.dat differ diff --git a/forge-gui/res/deckgendecks/Standard.dat b/forge-gui/res/deckgendecks/Standard.dat index 424b4edd377..7d6cf358756 100644 Binary files a/forge-gui/res/deckgendecks/Standard.dat and b/forge-gui/res/deckgendecks/Standard.dat differ diff --git a/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java b/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java index 50e2565241f..b3b44f78aa9 100644 --- a/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java +++ b/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java @@ -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> deckPool=new ArrayList<>(); + for(int k=0;k0){ + deckPool.add(new AbstractMap.SimpleEntry(integerCardMap.get(k),matrix[col][k])); + } + } +/* ArrayIndexComparator comparator = new ArrayIndexComparator(ArrayUtils.toObject(distances)); Integer[] indices = comparator.createIndexArray(); Arrays.sort(indices, comparator); List> deckPool=new ArrayList<>(); @@ -197,7 +211,7 @@ public final class CardRelationMatrixGenerator { } deckPool.add(new AbstractMap.SimpleEntry(cardToAdd,distances[indices[cardList.size()-1-k]])); }; - /*if(excludeThisCard){ + *//*if(excludeThisCard){ continue; }*/ cardPools.put(card.getName(),deckPool); diff --git a/forge-gui/src/main/java/forge/deck/DeckType.java b/forge-gui/src/main/java/forge/deck/DeckType.java index 0685b2be8ed..91ce25d9792 100644 --- a/forge-gui/src/main/java/forge/deck/DeckType.java +++ b/forge-gui/src/main/java/forge/deck/DeckType.java @@ -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; diff --git a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java index ce2b324de38..1b48fc05bf7 100644 --- a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java +++ b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java @@ -539,33 +539,51 @@ public class DeckgenUtil { final Deck deck; IDeckGenPool cardDb; DeckGeneratorBase gen = null; + PaperCard selectedPartner=null; if(isCardGen){ List> 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 preSelectedCards = new ArrayList<>(); for(Map.Entry pair:potentialCards){ - preSelectedCards.add(pair.getKey()); + if(format.isLegalCard(pair.getKey())) { + preSelectedCards.add(pair.getKey()); + } + } + //check for partner commanders + List 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 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; } diff --git a/forge-gui/src/main/java/forge/limited/CardThemedCommanderDeckBuilder.java b/forge-gui/src/main/java/forge/limited/CardThemedCommanderDeckBuilder.java index 5c42fbd5fdf..a35fa3bbff7 100644 --- a/forge-gui/src/main/java/forge/limited/CardThemedCommanderDeckBuilder.java +++ b/forge-gui/src/main/java/forge/limited/CardThemedCommanderDeckBuilder.java @@ -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 hasColor; protected final List availableList; @@ -53,10 +55,9 @@ public class CardThemedCommanderDeckBuilder extends DeckGeneratorBase { // Views for aiPlayable protected Iterable onColorCreatures; protected Iterable onColorNonCreatures; - protected Iterable 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 dList, boolean isForAI) { - super(FModel.getMagicDb().getCommonCards(), DeckFormat.Commander); + public CardThemedCommanderDeckBuilder(PaperCard commanderCard0,PaperCard partner0, final List 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 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 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 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 nonLands = Iterables.filter(rankedColorList, + final Iterable 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 possibleFromFullPool = new Predicate() { + @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 randomPool = Lists.newArrayList(pool.getAllCards(possibleFromFullPool)); + Collections.shuffle(randomPool,new Random()); + Iterator 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 toAdd = Lists.newArrayList(Iterables.filter(aiPlayables,PaperCard.Predicates.name("Wastes"))); - deckList.addAll(toAdd); - aiPlayables.removeAll(toAdd); - rankedColorList.removeAll(toAdd); - landsNeeded = landsNeeded - toAdd.size(); + Iterable 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 lands = Iterables.filter(aiPlayables, Predicates.compose(CardRulesPredicates.Presets.IS_NONBASIC_LAND, PaperCard.FN_GET_RULES)); List 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 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 rankedOthers = CardRanker.rankCardsInPack(others, deckList, colors, true); - List 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 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 others = Iterables.filter(aiPlayables, - Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES)); - List 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 possibleFromFullPool = new Predicate() { + @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 randomPool = Lists.newArrayList(pool.getAllCards(possibleFromFullPool)); + Collections.shuffle(randomPool,new Random()); + Iterator iRandomPool=randomPool.iterator(); + for(int i=0;i nonCreatures, int num) { - List 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 creatures, int num) { - List creaturesToAdd = new ArrayList<>(); - for (final PaperCard card : creatures) { - if (num > 0) { - creaturesToAdd.add(card); - num--; + private void addCards(final Iterable cards, int num) { + List 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 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 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 keyCardList = Lists.newArrayList(keyCards); deckList.addAll(keyCardList); aiPlayables.removeAll(keyCardList); rankedColorList.removeAll(keyCardList); - } + }*/ final Map 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 creatureCosts = new HashMap(); @@ -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) {