mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 03:08:02 +00:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user