diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/examples/Example.java b/forge-gui-desktop/src/test/java/forge/deck/generate/lda/examples/Example.java deleted file mode 100644 index 2e7e3f610ed..00000000000 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/examples/Example.java +++ /dev/null @@ -1,59 +0,0 @@ -/* -* Copyright 2015 Kohei Yamamoto -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -package forge.deck.generate.lda.examples; - -import java.util.List; - -import com.google.common.base.Function; -import forge.GuiBase; -import forge.GuiDesktop; -import forge.deck.generate.lda.lda.LDA; -import static forge.deck.generate.lda.lda.inference.InferenceMethod.*; - -import forge.model.FModel; -import forge.properties.ForgePreferences; -import org.apache.commons.lang3.tuple.Pair; - -import forge.deck.generate.lda.dataset.Dataset; - -public class Example { - public static void main(String[] args) throws Exception { - GuiBase.setInterface(new GuiDesktop()); - FModel.initialize(null, new Function() { - @Override - public Void apply(ForgePreferences preferences) { - preferences.setPref(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY, false); - return null; - } - }); - Dataset dataset = new Dataset(FModel.getFormats().getStandard()); - - final int numTopics = 50; - LDA lda = new LDA(0.1, 0.1, numTopics, dataset, CGS); - lda.run(); - System.out.println(lda.computePerplexity(dataset)); - - for (int t = 0; t < numTopics; ++t) { - List> highRankVocabs = lda.getVocabsSortedByPhi(t); - System.out.print("t" + t + ": "); - for (int i = 0; i < 20; ++i) { - System.out.println("[" + highRankVocabs.get(i).getLeft() + "," + highRankVocabs.get(i).getRight() + "],"); - } - System.out.println(); - } - } -} diff --git a/forge-gui-desktop/src/test/java/forge/planarconquestgenerate/PlanarConquestCommanderGeneraterGA.java b/forge-gui-desktop/src/test/java/forge/planarconquestgenerate/PlanarConquestCommanderGeneraterGA.java new file mode 100644 index 00000000000..0596b1e9005 --- /dev/null +++ b/forge-gui-desktop/src/test/java/forge/planarconquestgenerate/PlanarConquestCommanderGeneraterGA.java @@ -0,0 +1,139 @@ +package forge.planarconquestgenerate; + +import com.google.common.base.Function; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import forge.GuiBase; +import forge.GuiDesktop; +import forge.LobbyPlayer; +import forge.StaticData; +import forge.card.CardRulesPredicates; +import forge.deck.*; +import forge.deck.io.DeckStorage; +import forge.game.GameFormat; +import forge.game.GameRules; +import forge.game.GameType; +import forge.game.Match; +import forge.game.player.RegisteredPlayer; +import forge.item.PaperCard; +import forge.limited.CardRanker; +import forge.model.FModel; +import forge.player.GamePlayerUtil; +import forge.properties.ForgeConstants; +import forge.properties.ForgePreferences; +import forge.tournament.system.AbstractTournament; +import forge.tournament.system.TournamentPairing; +import forge.tournament.system.TournamentPlayer; +import forge.tournament.system.TournamentSwiss; +import forge.util.AbstractGeneticAlgorithm; +import forge.util.MyRandom; +import forge.util.TextUtil; +import forge.view.SimulateMatch; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class PlanarConquestCommanderGeneraterGA extends PlanarConquestGeneraterGA { + + + private int deckCount = 0; + + public static void main(String[] args){ + test(); + } + + public static void test(){ + + GuiBase.setInterface(new GuiDesktop()); + FModel.initialize(null, new Function() { + @Override + public Void apply(ForgePreferences preferences) { + preferences.setPref(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY, false); + return null; + } + }); + List sets = new ArrayList<>(); + sets.add("XLN"); + sets.add("RIX"); + + PlanarConquestCommanderGeneraterGA ga = new PlanarConquestCommanderGeneraterGA(new GameRules(GameType.Constructed), + new GameFormat("conquest",sets,null), + DeckFormat.PlanarConquest, + 4, + 12, + 16); + ga.run(); + List winners = ga.listFinalPopulation(); + + DeckStorage storage = new DeckStorage(new File(ForgeConstants.DECK_CONSTRUCTED_DIR), ForgeConstants.DECK_BASE_DIR); + int i=1; + for(Deck deck:winners){ + storage.save(new Deck(deck,"GA"+i+"_"+deck.getName())); + i++; + } + } + + public PlanarConquestCommanderGeneraterGA(GameRules rules, GameFormat gameFormat, DeckFormat deckFormat, int cardsToUse, int decksPerCard, int generations){ + super(rules,gameFormat,deckFormat,cardsToUse,decksPerCard,generations); + } + + @Override + protected void initializeCards(){ + standardMap = CardRelationMatrixGenerator.cardPools.get(format.getName()); + List cardNames = new ArrayList<>(standardMap.keySet()); + List cards = new ArrayList<>(); + for(String cardName:cardNames){ + cards.add(StaticData.instance().getCommonCards().getUniqueByName(cardName)); + } + + Iterable filtered= Iterables.filter(cards, Predicates.and( + Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard.FN_GET_RULES), + Predicates.compose(CardRulesPredicates.Presets.IS_PLANESWALKER, PaperCard.FN_GET_RULES), + //Predicates.compose(CardRulesPredicates.Presets.IS_LEGENDARY, PaperCard.FN_GET_RULES), + gameFormat.getFilterPrinted())); + + List filteredList = Lists.newArrayList(filtered); + rankedList = CardRanker.rankCardsInDeck(filteredList); + List decks = new ArrayList<>(); + for(PaperCard card: rankedList.subList(0,cardsToUse)){ + System.out.println(card.getName()); + for( int i=0; i { + + private DeckGroup deckGroup; + private List players = new ArrayList<>(); + private TournamentSwiss tourney = null; + protected Map>> standardMap; + private GameRules rules; + protected GameFormat format = FModel.getFormats().getStandard(); + protected int generations; + protected GameFormat gameFormat; + protected DeckFormat deckFormat; + protected int cardsToUse; + protected int decksPerCard; + private int deckCount = 0; + protected List rankedList; + + public static void main(String[] args){ + test(); + } + + public static void test(){ + + GuiBase.setInterface(new GuiDesktop()); + FModel.initialize(null, new Function() { + @Override + public Void apply(ForgePreferences preferences) { + preferences.setPref(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY, false); + return null; + } + }); + List sets = new ArrayList<>(); + sets.add("XLN"); + sets.add("RIX"); + + PlanarConquestGeneraterGA ga = new PlanarConquestGeneraterGA(new GameRules(GameType.Constructed), + new GameFormat("conquest",sets,null), + DeckFormat.PlanarConquest, + 40, + 4, + 10); + ga.run(); + List winners = ga.listFinalPopulation(); + + DeckStorage storage = new DeckStorage(new File(ForgeConstants.DECK_CONSTRUCTED_DIR), ForgeConstants.DECK_BASE_DIR); + int i=1; + for(Deck deck:winners){ + storage.save(new Deck(deck,"GA"+i+"_"+deck.getName())); + i++; + } + } + + public PlanarConquestGeneraterGA(GameRules rules, GameFormat gameFormat, DeckFormat deckFormat, int cardsToUse, int decksPerCard, int generations){ + this.rules = rules; + rules.setGamesPerMatch(7); + this.gameFormat = gameFormat; + this.deckFormat = deckFormat; + this.cardsToUse = cardsToUse; + this.decksPerCard = decksPerCard; + this.generations = generations; + initializeCards(); + } + + + protected void initializeCards(){ + standardMap = CardRelationMatrixGenerator.cardPools.get(format.getName()); + List cardNames = new ArrayList<>(standardMap.keySet()); + List cards = new ArrayList<>(); + for(String cardName:cardNames){ + cards.add(StaticData.instance().getCommonCards().getUniqueByName(cardName)); + } + + Iterable filtered= Iterables.filter(cards, Predicates.and( + Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard.FN_GET_RULES), + Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES), + gameFormat.getFilterPrinted())); + + List filteredList = Lists.newArrayList(filtered); + setRankedList(CardRanker.rankCardsInDeck(filteredList)); + List decks = new ArrayList<>(); + for(PaperCard card: getRankedList().subList(0,cardsToUse)){ + System.out.println(card.getName()); + for( int i=0; i getRankedList(){ + return rankedList; + } + + protected void setRankedList(List list){ + rankedList = list; + } + + protected Deck getDeckForCard(PaperCard card){ + Deck genDeck = DeckgenUtil.buildPlanarConquestDeck(card, gameFormat, deckFormat); + Deck d = new Deck(genDeck,genDeck.getName()+"_"+deckCount+"_"+generationCount); + deckCount++; + return d; + } + + protected Deck getDeckForCard(PaperCard card, PaperCard card2){ + Deck genDeck = DeckgenUtil.buildPlanarConquestDeck(card, card2, gameFormat, deckFormat, false); + Deck d = new Deck(genDeck,genDeck.getName()+"_"+deckCount+"_"+generationCount); + deckCount++; + return d; + } + + @Override + protected void evaluateFitness() { + deckGroup = new DeckGroup("SimulatedTournament"); + players = new ArrayList<>(); + int i=0; + for(Deck d:population) { + deckGroup.addAiDeck(d); + players.add(new TournamentPlayer(GamePlayerUtil.createAiPlayer(d.getName(), 0), i)); + ++i; + } + tourney = new TournamentSwiss(players, 2); + tourney = runTournament(tourney, rules, players.size(), deckGroup); + population = new ArrayList<>(); + for (int k = 0; k < tourney.getAllPlayers().size(); k++) { + String deckName = tourney.getAllPlayers().get(k).getPlayer().getName(); + for (Deck sortedDeck : deckGroup.getAiDecks()) { + if (sortedDeck.getName().equals(deckName)) { + population.add(sortedDeck); + break; + } + } + } + deckCount=0; + } + + @Override + protected Deck mutateObject(Deck parent1) { + PaperCard allele = parent1.getMain().get(MyRandom.getRandom().nextInt(8)); + if(!standardMap.keySet().contains(allele.getName())){ + return null; + } + return getDeckForCard(allele); + } + + @Override + protected Deck createChild(Deck parent1, Deck parent2) { + PaperCard allele = parent1.getMain().get(MyRandom.getRandom().nextInt(8)); + PaperCard allele2 = parent2.getMain().get(MyRandom.getRandom().nextInt(8)); + if(!standardMap.keySet().contains(allele.getName()) + ||!standardMap.keySet().contains(allele2.getName()) + ||allele.getName().equals(allele2.getName())){ + return null; + } + return getDeckForCard(allele,allele2); + } + + @Override + protected Deck expandPool(){ + PaperCard seed = getRankedList().get(MyRandom.getRandom().nextInt(getRankedList().size())); + return getDeckForCard(seed); + } + + @Override + protected boolean shouldContinue() { + return generationCount regPlayers = AbstractTournament.registerTournamentPlayers(pairing, deckGroup); + + StringBuilder sb = new StringBuilder(); + sb.append("Round ").append(tourney.getActiveRound()).append(" - "); + sb.append(pairing.outputHeader()); + //System.out.println(sb.toString()); + + if (!pairing.isBye()) { + Match mc = new Match(rules, regPlayers, "TourneyMatch"); + + int exceptions = 0; + int iGame = 0; + while (!mc.isMatchOver()) { + // play games until the match ends + try{ + SimulateMatch.simulateSingleMatch(mc, iGame, false); + iGame++; + } catch(Exception e) { + exceptions++; + System.out.println(e.toString()); + if (exceptions > 5) { + System.out.println("Exceeded number of exceptions thrown. Abandoning match..."); + break; + } else { + System.out.println("Game threw exception. Abandoning game and continuing..."); + } + } + + } + LobbyPlayer winner = mc.getWinner().getPlayer(); + for (TournamentPlayer tp : pairing.getPairedPlayers()) { + if (winner.equals(tp.getPlayer())) { + pairing.setWinner(tp); + lastWinner = winner.getName(); + //System.out.println(TextUtil.concatNoSpace("Match Winner - ", lastWinner, "!")); + //System.out.println(""); + break; + } + } + } + + tourney.reportMatchCompletion(pairing); + } + tourney.outputTournamentResults(); + return tourney; + } +} diff --git a/forge-gui/res/deckgendecks/Commander.dat b/forge-gui/res/deckgendecks/Commander.dat index 32c6828833f..bb7961de7e1 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/Standard.dat b/forge-gui/res/deckgendecks/Standard.dat index d040eba991c..ac347513c32 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/CardRelationLDAGenerator.java b/forge-gui/src/main/java/forge/deck/CardRelationLDAGenerator.java new file mode 100644 index 00000000000..eb71e3b08b4 --- /dev/null +++ b/forge-gui/src/main/java/forge/deck/CardRelationLDAGenerator.java @@ -0,0 +1,247 @@ +package forge.deck; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import forge.StaticData; +import forge.card.CardRules; +import forge.card.CardRulesPredicates; +import forge.deck.io.CardThemedLDAIO; +import forge.deck.io.CardThemedMatrixIO; +import forge.deck.io.DeckStorage; +import forge.deck.lda.dataset.Dataset; +import forge.deck.lda.lda.LDA; +import forge.game.GameFormat; +import forge.item.PaperCard; +import forge.model.FModel; +import forge.properties.ForgeConstants; +import forge.util.storage.IStorage; +import forge.util.storage.StorageImmediatelySerialized; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.tuple.Pair; + +import java.io.File; +import java.util.*; + +import static forge.deck.lda.lda.inference.InferenceMethod.CGS; + +/** + * Created by maustin on 09/05/2017. + */ +public final class CardRelationLDAGenerator { + + public static Map>>> ldaPools = new HashMap(); + /** + To ensure that only cards with at least 14 connections (as 14*4+4=60) are included in the card based deck + generation pools + **/ + public static final int MIN_REQUIRED_CONNECTIONS = 14; + + public static boolean initialize(){ + List formatStrings = new ArrayList<>(); + formatStrings.add(FModel.getFormats().getStandard().getName()); + formatStrings.add(FModel.getFormats().getModern().getName()); + formatStrings.add(DeckFormat.Commander.toString()); + + for (String formatString : formatStrings){ + if(!initializeFormat(formatString)){ + return false; + } + } + + return true; + } + + /** Try to load matrix .dat files, otherwise check for deck folders and build .dat, otherwise return false **/ + public static boolean initializeFormat(String format){ + Map>> formatMap = CardThemedLDAIO.loadLDA(format); + if(formatMap==null) { + try { + if (CardThemedLDAIO.getMatrixFolder(format).exists()) { + if (format.equals(FModel.getFormats().getStandard().getName())) { + formatMap = initializeFormat(FModel.getFormats().getStandard()); + } else if (format.equals(FModel.getFormats().getModern().getName())) { + formatMap = initializeFormat(FModel.getFormats().getModern()); + } else { + //formatMap = initializeCommanderFormat(); + } + CardThemedLDAIO.saveLDA(format, formatMap); + } else { + return false; + } + }catch (Exception e){ + e.printStackTrace(); + return false; + } + } + ldaPools.put(format, formatMap); + return true; + } + + public static Map>> initializeFormat(GameFormat format) throws Exception{ + Dataset dataset = new Dataset(format); + + final int numTopics = dataset.getNumDocs()/50; + LDA lda = new LDA(0.1, 0.1, numTopics, dataset, CGS); + lda.run(); + System.out.println(lda.computePerplexity(dataset)); + List> topics = new ArrayList<>(); + Set cards = new HashSet(); + for (int t = 0; t < numTopics; ++t) { + List topic = new ArrayList<>(); + List> highRankVocabs = lda.getVocabsSortedByPhi(t); + if (highRankVocabs.get(0).getRight()<=0.001d){ + continue; + } + System.out.print("t" + t + ": "); + int i = 0; + while (topic.size()<=40) { + String cardName = highRankVocabs.get(i).getLeft();; + if(!StaticData.instance().getCommonCards().getUniqueByName(cardName).getRules().getType().isBasicLand()){ + if(highRankVocabs.get(i).getRight()>=0.0005d){ + cards.add(cardName); + } + System.out.println("[" + highRankVocabs.get(i).getLeft() + "," + highRankVocabs.get(i).getRight() + "],"); + topic.add(highRankVocabs.get(i).getLeft()); + } + i++; + } + System.out.println(); + topics.add(topic); + } + Map>> cardTopicMap = new HashMap<>(); + for (String card:cards){ + List> cardTopics = new ArrayList<>(); + for( List topic:topics){ + if(topic.contains(card)){ + cardTopics.add(topic); + } + } + cardTopicMap.put(card,cardTopics); + } + return cardTopicMap; + } + + public static HashMap>> initializeCommanderFormat(){ + + IStorage decks = new StorageImmediatelySerialized("Generator", + new DeckStorage(new File(ForgeConstants.DECK_GEN_DIR,DeckFormat.Commander.toString()), + ForgeConstants.DECK_GEN_DIR, false), + true); + + //get all cards + final Iterable cards = Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards() + , Predicates.compose(Predicates.not(CardRulesPredicates.Presets.IS_BASIC_LAND_NOT_WASTES), PaperCard.FN_GET_RULES)); + List cardList = Lists.newArrayList(cards); + cardList.add(FModel.getMagicDb().getCommonCards().getCard("Wastes")); + Map cardIntegerMap = new HashMap<>(); + Map integerCardMap = new HashMap<>(); + Map legendIntegerMap = new HashMap<>(); + Map integerLegendMap = new HashMap<>(); + //generate lookups for cards to link card names to matrix columns + for (int i=0; i legends = Lists.newArrayList(Iterables.filter(cardList,Predicates.compose( + new Predicate() { + @Override + public boolean apply(CardRules rules) { + return DeckFormat.Commander.isLegalCommander(rules); + } + }, PaperCard.FN_GET_RULES))); + + //generate lookups for legends to link commander names to matrix rows + for (int i=0; i>> cardPools = new HashMap<>(); + for (PaperCard card:legends){ + int col=legendIntegerMap.get(card.getName()); + int[] distances = matrix[col]; + int max = (Integer) Collections.max(Arrays.asList(ArrayUtils.toObject(distances))); + if (max>0) { + List> deckPool=new ArrayList<>(); + for(int k=0;k0){ + deckPool.add(new AbstractMap.SimpleEntry(integerCardMap.get(k),matrix[col][k])); + } + } + cardPools.put(card.getName(), deckPool); + } + } + return cardPools; + } + + //update the matrix by incrementing the connectivity count for each card in the deck + public static void updateLegendMatrix(Deck deck, PaperCard legend, Map cardIntegerMap, + Map legendIntegerMap, int[][] matrix){ + 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(legend.getName())){ + try { + int old = matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(pairCard.getName())]; + matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(pairCard.getName())] = old + 1; + }catch (NullPointerException ne){ + //Todo: Not sure what was failing here + ne.printStackTrace(); + } + } + + } + //add partner commanders to matrix + if(deck.getCommanders().size()>1){ + for(PaperCard partner:deck.getCommanders()){ + if(!partner.equals(legend)){ + int old = matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(partner.getName())]; + matrix[legendIntegerMap.get(legend.getName())][cardIntegerMap.get(partner.getName())] = old + 1; + } + } + } + } + + public static class ArrayIndexComparator implements Comparator + { + private final Integer[] array; + + public ArrayIndexComparator(Integer[] array) + { + this.array = array; + } + + public Integer[] createIndexArray() + { + Integer[] indexes = new Integer[array.length]; + for (int i = 0; i < array.length; i++) + { + indexes[i] = i; // Autoboxing + } + return indexes; + } + + @Override + public int compare(Integer index1, Integer index2) + { + // Autounbox from Integer to int to use as array indexes + return array[index1].compareTo(array[index2]); + } + } +} diff --git a/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java b/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java index ed0c54b276f..7424d64913d 100644 --- a/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java +++ b/forge-gui/src/main/java/forge/deck/CardRelationMatrixGenerator.java @@ -6,6 +6,7 @@ import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import forge.card.CardRules; import forge.card.CardRulesPredicates; +import forge.deck.io.CardThemedLDAIO; import forge.deck.io.CardThemedMatrixIO; import forge.deck.io.DeckStorage; import forge.game.GameFormat; @@ -25,6 +26,8 @@ import java.util.*; public final class CardRelationMatrixGenerator { public static HashMap>>> cardPools = new HashMap<>(); + + public static Map>>> ldaPools = new HashMap(); /** To ensure that only cards with at least 14 connections (as 14*4+4=60) are included in the card based deck generation pools @@ -34,6 +37,7 @@ public final class CardRelationMatrixGenerator { public static boolean initialize(){ List formatStrings = new ArrayList<>(); formatStrings.add(FModel.getFormats().getStandard().getName()); + ldaPools.put(FModel.getFormats().getStandard().getName(),CardThemedLDAIO.loadLDA(FModel.getFormats().getStandard().getName())); formatStrings.add(FModel.getFormats().getModern().getName()); formatStrings.add(DeckFormat.Commander.toString()); diff --git a/forge-gui/src/main/java/forge/deck/CardThemedDeckGenerator.java b/forge-gui/src/main/java/forge/deck/CardThemedDeckGenerator.java index c4b8b398e24..8547d53899f 100644 --- a/forge-gui/src/main/java/forge/deck/CardThemedDeckGenerator.java +++ b/forge-gui/src/main/java/forge/deck/CardThemedDeckGenerator.java @@ -14,13 +14,14 @@ import java.util.List; public class CardThemedDeckGenerator extends DeckProxy implements Comparable { public static List getMatrixDecks(GameFormat format, boolean isForAi){ final List decks = new ArrayList(); - for(String card: CardRelationMatrixGenerator.cardPools.get(format.getName()).keySet()) { - //exclude non AI playables as keycards for AI decks - if(isForAi&&FModel.getMagicDb().getCommonCards().getUniqueByName(card).getRules().getAiHints().getRemAIDecks()){ - continue; + for(String card: CardRelationLDAGenerator.ldaPools.get(format.getName()).keySet()) { + //exclude non AI playables as keycards for AI decks + if(isForAi&&FModel.getMagicDb().getCommonCards().getUniqueByName(card).getRules().getAiHints().getRemAIDecks()){ + continue; + } + decks.add(new CardThemedDeckGenerator(card, format, isForAi)); } - decks.add(new CardThemedDeckGenerator(card, format, isForAi)); - } + return decks; } private final String name; diff --git a/forge-gui/src/main/java/forge/deck/CommanderDeckGenerator.java b/forge-gui/src/main/java/forge/deck/CommanderDeckGenerator.java index 851fe4c0164..51cc8c09fe7 100644 --- a/forge-gui/src/main/java/forge/deck/CommanderDeckGenerator.java +++ b/forge-gui/src/main/java/forge/deck/CommanderDeckGenerator.java @@ -54,7 +54,7 @@ public class CommanderDeckGenerator extends DeckProxy implements Comparable(PaperCard.class); //TODO: upate to actual Brawl model from real Brawl decks - Iterable legendNames=CardRelationMatrixGenerator.cardPools.get(FModel.getFormats().getStandard().getName()).keySet(); + Iterable legendNames=CardRelationLDAGenerator.ldaPools.get(FModel.getFormats().getStandard().getName()).keySet(); for(String legendName:legendNames) { uniqueCards.add(FModel.getMagicDb().getCommonCards().getUniqueByName(legendName)); } diff --git a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java index 7636f166389..6fd1e118c3a 100644 --- a/forge-gui/src/main/java/forge/deck/DeckgenUtil.java +++ b/forge-gui/src/main/java/forge/deck/DeckgenUtil.java @@ -18,6 +18,7 @@ import forge.game.GameType; import forge.item.PaperCard; import forge.itemmanager.IItemManager; import forge.limited.CardThemedCommanderDeckBuilder; +import forge.limited.CardThemedConquestDeckBuilder; import forge.limited.CardThemedDeckBuilder; import forge.model.FModel; import forge.properties.ForgePreferences.FPref; @@ -31,6 +32,7 @@ import forge.util.MyRandom; import forge.util.gui.SOptionPane; import forge.util.storage.IStorage; +import java.awt.print.Paper; import java.util.*; /** @@ -45,7 +47,7 @@ public class DeckgenUtil { public static Deck buildCardGenDeck(GameFormat format, boolean isForAI){ try { - List keys = new ArrayList<>(CardRelationMatrixGenerator.cardPools.get(format.getName()).keySet()); + List keys = new ArrayList<>(CardRelationLDAGenerator.ldaPools.get(format.getName()).keySet()); String randomKey = keys.get( MyRandom.getRandom().nextInt(keys.size()) ); Predicate cardFilter = Predicates.and(format.getFilterPrinted(),PaperCard.Predicates.name(randomKey)); PaperCard keyCard = FModel.getMagicDb().getCommonCards().getAllCards(cardFilter).get(0); @@ -110,6 +112,98 @@ public class DeckgenUtil { } } + public static Deck buildPlanarConquestDeck(PaperCard card, GameFormat format, DeckFormat deckFormat){ + return buildPlanarConquestDeck(card, null, format, deckFormat, false); + } + + public static Deck buildPlanarConquestCommanderDeck(PaperCard card, GameFormat format, DeckFormat deckFormat){ + Deck deck = buildPlanarConquestDeck(card, null, format, deckFormat, true); + deck.getMain().removeAll(card); + deck.getOrCreate(DeckSection.Commander).add(card); + return deck; + } + + public static Deck buildPlanarConquestCommanderDeck(PaperCard card, PaperCard secondKeycard, GameFormat format, DeckFormat deckFormat){ + Deck deck = buildPlanarConquestDeck(card, secondKeycard, format, deckFormat, true); + deck.getMain().removeAll(card); + deck.getOrCreate(DeckSection.Commander).add(card); + return deck; + } + + public static Deck buildPlanarConquestDeck(PaperCard card, PaperCard secondKeycard, GameFormat format, DeckFormat deckFormat, boolean forCommander){ + final boolean isForAI = true; + Set uniqueCards = new HashSet<>(); + List selectedCards = new ArrayList<>(); + List> cardArchetypes = CardRelationLDAGenerator.ldaPools.get(FModel.getFormats().getStandard().getName()).get(card.getName()); + for(List archetype:cardArchetypes){ + for(String cardName:archetype){ + uniqueCards.add(cardName); + } + } + for(String cardName:uniqueCards){ + selectedCards.add(StaticData.instance().getCommonCards().getUniqueByName(cardName)); + } + /* + if(secondKeycard == null){ + //get second keycard + for(Map.Entry pair:potentialCards){ + preSelectedCards.add(pair.getKey()); + } + //filter out land cards and if for AI non-playable cards as potential second key cards and remove cards not legal in format + Iterable preSelectedNonLandCards; + preSelectedNonLandCards=Iterables.filter(preSelectedCards,Predicates.and( + Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard.FN_GET_RULES), + Predicates.compose(CardRulesPredicates.Presets.IS_NON_LAND, PaperCard.FN_GET_RULES), + format.getFilterPrinted())); + + preSelectedCards= Lists.newArrayList(preSelectedNonLandCards); + + //choose a second card randomly from the top 8 cards if possible + int randMax=4; + if(preSelectedCards.size()> potentialSecondCards = CardRelationMatrixGenerator.cardPools.get(FModel.getFormats().getStandard().getName()).get(secondKeycard.getName()); + + //combine card distances from second key card and re-sort + if(potentialSecondCards !=null && potentialSecondCards.size()>0) { + combineDistances(potentialCards, potentialSecondCards); + Collections.sort(potentialCards, new CardDistanceComparator()); + Collections.reverse(potentialCards); + } + + List selectedCards = new ArrayList<>(); + selectedCards.add(card); + selectedCards.add(secondKeycard); + for(Map.Entry pair:potentialCards){ + PaperCard potentialCard = pair.getKey(); + if (!potentialCard.getName().equals(card.getName()) + && (forCommander || !potentialCard.getName().equals(secondKeycard.getName())) + && format.getFilterPrinted().apply(potentialCard)) { + selectedCards.add(pair.getKey()); + } + }*/ + + //build deck from combined list + CardThemedDeckBuilder dBuilder; + + if(forCommander){ + dBuilder = new CardThemedConquestDeckBuilder(card, selectedCards, format ,isForAI, deckFormat); + }else{ + dBuilder = new CardThemedDeckBuilder(card,secondKeycard, selectedCards,format,isForAI, deckFormat); + } + + Deck deck = dBuilder.buildDeck(); + return deck; + } + + public static Deck buildCardGenDeck(PaperCard card, GameFormat format, boolean isForAI){ + return buildCardGenDeck(card, null, format, isForAI); + } + /** * Build a deck based on the chosen card. * @@ -118,9 +212,12 @@ public class DeckgenUtil { * @param isForAI * @return */ - public static Deck buildCardGenDeck(PaperCard card, GameFormat format, boolean isForAI){ - List> potentialCards = new ArrayList<>(); - potentialCards.addAll(CardRelationMatrixGenerator.cardPools.get(format.getName()).get(card.getName())); + public static Deck buildCardGenDeck(PaperCard card, PaperCard secondKeycard, GameFormat format, boolean isForAI){ + + return buildLDACardGenDeck(card, format, isForAI); + + /*List> potentialCards = new ArrayList<>(); + potentialCards.addAll(CardRelationLDAGenerator.ldaPools.get(format.getName()).get(card.getName())); Collections.sort(potentialCards,new CardDistanceComparator()); Collections.reverse(potentialCards); //get second keycard @@ -141,11 +238,14 @@ public class DeckgenUtil { preSelectedCards= Lists.newArrayList(preSelectedNonLandCards); //choose a second card randomly from the top 8 cards if possible - int randMax=8; - if(preSelectedCards.size()> potentialSecondCards = CardRelationMatrixGenerator.cardPools.get(format.getName()).get(secondKeycard.getName()); //combine card distances from second key card and re-sort @@ -159,7 +259,19 @@ public class DeckgenUtil { for(Map.Entry pair:potentialCards){ selectedCards.add(pair.getKey()); } - List toRemove = new ArrayList<>(); + */ + /*List toRemove = new ArrayList<>(); + Set uniqueCards = new HashSet<>(); + List selectedCards = new ArrayList<>(); + List> cardArchetypes = CardRelationLDAGenerator.ldaPools.get(FModel.getFormats().getStandard().getName()).get(card.getName()); + for(List archetype:cardArchetypes){ + for(String cardName:archetype){ + uniqueCards.add(cardName); + } + } + for(String cardName:uniqueCards){ + selectedCards.add(StaticData.instance().getCommonCards().getUniqueByName(cardName)); + } //randomly remove cards int removeCount=0; @@ -223,6 +335,82 @@ public class DeckgenUtil { while(deck.get(DeckSection.Sideboard).countAll()>15){ deck.get(DeckSection.Sideboard).remove(deck.get(DeckSection.Sideboard).get(0)); } + return deck;*/ + } + + /** + * Build a deck based on the chosen card. + * + * @param card + * @param format + * @param isForAI + * @return + */ + public static Deck buildLDACardGenDeck(PaperCard card,GameFormat format, boolean isForAI){ + + List> preSelectedCardLists = CardRelationLDAGenerator.ldaPools.get(format.getName()).get(card.getName()); + List preSelectedCardNames = preSelectedCardLists.get(MyRandom.getRandom().nextInt(preSelectedCardLists.size())); + List selectedCards = new ArrayList<>(); + for(String name:preSelectedCardNames){ + PaperCard cardToAdd = StaticData.instance().getCommonCards().getUniqueByName(name); + //for(int i=0; i<1;++i) { + if(!cardToAdd.getName().equals(card.getName())) { + selectedCards.add(cardToAdd); + } + //} + } + + List toRemove = new ArrayList<>(); + + //randomly remove cards + int removeCount=0; + int i=0; + for(PaperCard c:selectedCards){ + if(MyRandom.getRandom().nextInt(100)>70+(15-(i/selectedCards.size())*selectedCards.size()) && removeCount<4 //randomly remove some cards - more likely as distance increases + &&!c.getName().contains("Urza")){ //avoid breaking Tron decks + toRemove.add(c); + removeCount++; + } + if(c.getName().equals(card.getName())){//may have been added in secondary list + toRemove.add(c); + } + ++i; + } + selectedCards.removeAll(toRemove); + //Add keycard + List playsetList = new ArrayList<>(); + int keyCardCount=4; + if(card.getRules().getMainPart().getManaCost().getCMC()>7){ + keyCardCount=1+MyRandom.getRandom().nextInt(4); + }else if(card.getRules().getMainPart().getManaCost().getCMC()>5){ + keyCardCount=2+MyRandom.getRandom().nextInt(3); + } + for(int j=0;j27){ + System.out.println("Too many lands "+deck.getMain().countAll(Predicates.compose(CardRulesPredicates.Presets.IS_LAND, PaperCard.FN_GET_RULES))); + deck=buildCardGenDeck(format,isForAI); + } + while(deck.get(DeckSection.Sideboard).countAll()>15){ + deck.get(DeckSection.Sideboard).remove(deck.get(DeckSection.Sideboard).get(0)); + } return deck; } @@ -517,20 +705,31 @@ public class DeckgenUtil { IDeckGenPool cardDb; DeckGeneratorBase gen = null; PaperCard selectedPartner=null; + List preSelectedCards = new ArrayList<>(); if(isCardGen){ - List> potentialCards = new ArrayList<>(); if(format.equals(DeckFormat.Brawl)){//TODO: replace with actual Brawl based data - potentialCards.addAll(CardRelationMatrixGenerator.cardPools.get(FModel.getFormats().getStandard().getName()).get(commander.getName())); + Set uniqueCards = new HashSet<>(); + List> cardArchetypes = CardRelationLDAGenerator.ldaPools.get(FModel.getFormats().getStandard().getName()).get(commander.getName()); + for(List archetype:cardArchetypes){ + for(String cardName:archetype){ + uniqueCards.add(cardName); + } + } + for(String card:uniqueCards){ + preSelectedCards.add(StaticData.instance().getCommonCards().getUniqueByName(card)); + } }else { + List> potentialCards = new ArrayList<>(); potentialCards.addAll(CardRelationMatrixGenerator.cardPools.get(DeckFormat.Commander.toString()).get(commander.getName())); - } - //Collections.shuffle(potentialCards, r); - List preSelectedCards = new ArrayList<>(); - for(Map.Entry pair:potentialCards){ - if(format.isLegalCard(pair.getKey())) { - preSelectedCards.add(pair.getKey()); + for(Map.Entry pair:potentialCards){ + if(format.isLegalCard(pair.getKey())) { + preSelectedCards.add(pair.getKey()); + } } } + //Collections.shuffle(potentialCards, r); + + //check for partner commanders List partners=new ArrayList<>(); for(PaperCard c:preSelectedCards){ diff --git a/forge-gui/src/main/java/forge/deck/io/CardThemedLDAIO.java b/forge-gui/src/main/java/forge/deck/io/CardThemedLDAIO.java new file mode 100644 index 00000000000..ed82b095692 --- /dev/null +++ b/forge-gui/src/main/java/forge/deck/io/CardThemedLDAIO.java @@ -0,0 +1,66 @@ +package forge.deck.io; + +import forge.game.GameFormat; +import forge.item.PaperCard; +import forge.properties.ForgeConstants; + +import java.io.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by maustin on 11/05/2017. + */ +public class CardThemedLDAIO { + + /** suffix for all gauntlet data files */ + public static final String SUFFIX_DATA = ".lda.dat"; + + public static void saveLDA(String format, Map>> map){ + File file = getLDAFile(format); + ObjectOutputStream s = null; + try { + FileOutputStream f = new FileOutputStream(file); + s = new ObjectOutputStream(f); + s.writeObject(map); + s.close(); + } catch (IOException e) { + System.out.println("Error writing matrix data: " + e); + } finally { + if(s!=null) { + try { + s.close(); + }catch(Exception e){ + e.printStackTrace(); + } + } + } + } + + public static Map>> loadLDA(String format){ + try { + FileInputStream fin = new FileInputStream(getLDAFile(format)); + ObjectInputStream s = new ObjectInputStream(fin); + Map>> matrix = (Map>>) s.readObject(); + s.close(); + return matrix; + }catch (Exception e){ + System.out.println("Error reading LDA data: " + e); + return null; + } + + } + + public static File getLDAFile(final String name) { + return new File(ForgeConstants.DECK_GEN_DIR, name + SUFFIX_DATA); + } + + public static File getMatrixFolder(final String name) { + return new File(ForgeConstants.DECK_GEN_DIR, name); + } + + public static File getLDAFile(final GameFormat gf) { + return getLDAFile(gf.getName()); + } +} diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/BagOfWords.java b/forge-gui/src/main/java/forge/deck/lda/dataset/BagOfWords.java similarity index 99% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/BagOfWords.java rename to forge-gui/src/main/java/forge/deck/lda/dataset/BagOfWords.java index 1a16b834bc8..028ddd114ee 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/BagOfWords.java +++ b/forge-gui/src/main/java/forge/deck/lda/dataset/BagOfWords.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.dataset; +package forge.deck.lda.dataset; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Dataset.java b/forge-gui/src/main/java/forge/deck/lda/dataset/Dataset.java similarity index 97% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Dataset.java rename to forge-gui/src/main/java/forge/deck/lda/dataset/Dataset.java index 118ad6da489..fdd4c8f1920 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Dataset.java +++ b/forge-gui/src/main/java/forge/deck/lda/dataset/Dataset.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.dataset; +package forge.deck.lda.dataset; import forge.game.GameFormat; import forge.model.FModel; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Vocabularies.java b/forge-gui/src/main/java/forge/deck/lda/dataset/Vocabularies.java similarity index 96% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Vocabularies.java rename to forge-gui/src/main/java/forge/deck/lda/dataset/Vocabularies.java index c67b921c1e6..2a0d9a48da7 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Vocabularies.java +++ b/forge-gui/src/main/java/forge/deck/lda/dataset/Vocabularies.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.dataset; +package forge.deck.lda.dataset; import java.io.IOException; import java.nio.file.Files; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Vocabulary.java b/forge-gui/src/main/java/forge/deck/lda/dataset/Vocabulary.java similarity index 96% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Vocabulary.java rename to forge-gui/src/main/java/forge/deck/lda/dataset/Vocabulary.java index 6b9240bafb1..6181c988a78 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/dataset/Vocabulary.java +++ b/forge-gui/src/main/java/forge/deck/lda/dataset/Vocabulary.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.dataset; +package forge.deck.lda.dataset; public class Vocabulary { private final int id; diff --git a/forge-gui/src/main/java/forge/deck/lda/examples/Example.java b/forge-gui/src/main/java/forge/deck/lda/examples/Example.java new file mode 100644 index 00000000000..f7a5b6adc55 --- /dev/null +++ b/forge-gui/src/main/java/forge/deck/lda/examples/Example.java @@ -0,0 +1,87 @@ +/* +* Copyright 2015 Kohei Yamamoto +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package forge.deck.lda.examples; + +import java.util.*; + +import forge.StaticData; +import forge.deck.lda.lda.LDA; +import static forge.deck.lda.lda.inference.InferenceMethod.*; + +import forge.deck.io.CardThemedLDAIO; +import forge.game.GameFormat; +import forge.model.FModel; +import forge.properties.ForgePreferences; +import org.apache.commons.lang3.tuple.Pair; + +import forge.deck.lda.dataset.Dataset; + +public class Example { + public static void main(String[] args) throws Exception { + /*GuiBase.setInterface(new GuiDesktop()); + FModel.initialize(null, new Function() { + @Override + public Void apply(ForgePreferences preferences) { + preferences.setPref(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY, false); + return null; + } + });*/ + GameFormat format = FModel.getFormats().getStandard(); + Dataset dataset = new Dataset(format); + + final int numTopics = 50; + LDA lda = new LDA(0.1, 0.1, numTopics, dataset, CGS); + lda.run(); + System.out.println(lda.computePerplexity(dataset)); + List> topics = new ArrayList<>(); + Set cards = new HashSet(); + for (int t = 0; t < numTopics; ++t) { + List topic = new ArrayList<>(); + List> highRankVocabs = lda.getVocabsSortedByPhi(t); + System.out.print("t" + t + ": "); + int i = 0; + while (topic.size()<=40) { + String cardName = highRankVocabs.get(i).getLeft();; + if(!StaticData.instance().getCommonCards().getUniqueByName(cardName).getRules().getType().isBasicLand()){ + cards.add(cardName); + System.out.println("[" + highRankVocabs.get(i).getLeft() + "," + highRankVocabs.get(i).getRight() + "],"); + topic.add(cardName); + } + i++; + } + System.out.println(); + topics.add(topic); + } + Map>> cardTopicMap = new HashMap<>(); + for (String card:cards){ + List> cardTopics = new ArrayList<>(); + for( List topic:topics){ + if(topic.contains(card)){ + cardTopics.add(topic); + } + } + cardTopicMap.put(card,cardTopics); + } + CardThemedLDAIO.saveLDA(format.getName(), cardTopicMap); + + + Map>> cardTopicMapIn =CardThemedLDAIO.loadLDA(format.getName()); + System.out.println(cardTopicMapIn.get(cardTopicMapIn.keySet().iterator().next()).get(0).toString()); + + + } +} diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Alpha.java b/forge-gui/src/main/java/forge/deck/lda/lda/Alpha.java similarity index 97% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Alpha.java rename to forge-gui/src/main/java/forge/deck/lda/lda/Alpha.java index 3b999054f73..f7d3ec4a745 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Alpha.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/Alpha.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda; +package forge.deck.lda.lda; import java.util.List; import java.util.stream.Collectors; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Beta.java b/forge-gui/src/main/java/forge/deck/lda/lda/Beta.java similarity index 97% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Beta.java rename to forge-gui/src/main/java/forge/deck/lda/lda/Beta.java index 1809427b7e6..50f49e5868b 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Beta.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/Beta.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda; +package forge.deck.lda.lda; import java.util.Arrays; import java.util.List; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Hyperparameters.java b/forge-gui/src/main/java/forge/deck/lda/lda/Hyperparameters.java similarity index 97% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Hyperparameters.java rename to forge-gui/src/main/java/forge/deck/lda/lda/Hyperparameters.java index 6583a4acf27..c97ec8ff340 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/Hyperparameters.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/Hyperparameters.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda; +package forge.deck.lda.lda; class Hyperparameters { private Alpha alpha; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/LDA.java b/forge-gui/src/main/java/forge/deck/lda/lda/LDA.java similarity index 93% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/LDA.java rename to forge-gui/src/main/java/forge/deck/lda/lda/LDA.java index dea408753fd..52aa820bcc3 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/LDA.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/LDA.java @@ -14,21 +14,21 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda; +package forge.deck.lda.lda; import java.io.IOException; import java.util.List; -import forge.deck.generate.lda.lda.inference.Inference; -import forge.deck.generate.lda.lda.inference.InferenceFactory; -import forge.deck.generate.lda.lda.inference.InferenceMethod; -import forge.deck.generate.lda.lda.inference.InferenceProperties; +import forge.deck.lda.lda.inference.Inference; +import forge.deck.lda.lda.inference.InferenceFactory; +import forge.deck.lda.lda.inference.InferenceMethod; +import forge.deck.lda.lda.inference.InferenceProperties; import org.apache.commons.lang3.tuple.Pair; -import forge.deck.generate.lda.dataset.BagOfWords; -import forge.deck.generate.lda.dataset.Dataset; -import forge.deck.generate.lda.dataset.Vocabularies; +import forge.deck.lda.dataset.BagOfWords; +import forge.deck.lda.dataset.Dataset; +import forge.deck.lda.dataset.Vocabularies; public class LDA { private Hyperparameters hyperparameters; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/Inference.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/Inference.java similarity index 94% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/Inference.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/Inference.java index 40d64e10f60..31f2617ce1a 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/Inference.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/Inference.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference; +package forge.deck.lda.lda.inference; import java.util.List; -import forge.deck.generate.lda.lda.LDA; +import forge.deck.lda.lda.LDA; import org.apache.commons.lang3.tuple.Pair; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceFactory.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceFactory.java similarity index 95% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceFactory.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceFactory.java index 51db612ac0a..990846b1560 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceFactory.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceFactory.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference; +package forge.deck.lda.lda.inference; public class InferenceFactory { diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceMethod.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceMethod.java similarity index 86% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceMethod.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceMethod.java index e1053bb4e03..fad4663dc5d 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceMethod.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceMethod.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference; +package forge.deck.lda.lda.inference; public enum InferenceMethod { - CGS("forge.deck.generate.lda.lda.inference.internal.CollapsedGibbsSampler"), + CGS("forge.deck.lda.lda.inference.internal.CollapsedGibbsSampler"), // more ; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceProperties.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceProperties.java similarity index 97% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceProperties.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceProperties.java index df72d862d8d..0be15351c94 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/InferenceProperties.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/InferenceProperties.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference; +package forge.deck.lda.lda.inference; import java.io.FileInputStream; import java.io.FileNotFoundException; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/AssignmentCounter.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/AssignmentCounter.java similarity index 97% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/AssignmentCounter.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/AssignmentCounter.java index c7d2d9b3a83..de79e4a8a9b 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/AssignmentCounter.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/AssignmentCounter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; import java.util.List; import java.util.stream.Collectors; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/CollapsedGibbsSampler.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/CollapsedGibbsSampler.java similarity index 96% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/CollapsedGibbsSampler.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/CollapsedGibbsSampler.java index 6419787ff9e..a2c8e387f07 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/CollapsedGibbsSampler.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/CollapsedGibbsSampler.java @@ -14,21 +14,21 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; -import forge.deck.generate.lda.lda.LDA; -import forge.deck.generate.lda.lda.inference.Inference; -import forge.deck.generate.lda.lda.inference.InferenceProperties; +import forge.deck.lda.lda.LDA; +import forge.deck.lda.lda.inference.Inference; +import forge.deck.lda.lda.inference.InferenceProperties; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.math3.distribution.EnumeratedIntegerDistribution; import org.apache.commons.math3.distribution.IntegerDistribution; -import forge.deck.generate.lda.dataset.Vocabulary; +import forge.deck.lda.dataset.Vocabulary; public class CollapsedGibbsSampler implements Inference { private LDA lda; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Document.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Document.java similarity index 95% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Document.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Document.java index 81f35a8c21b..fe9870db147 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Document.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Document.java @@ -14,11 +14,11 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; import java.util.List; -import forge.deck.generate.lda.dataset.Vocabulary; +import forge.deck.lda.dataset.Vocabulary; public class Document { private final int id; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Documents.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Documents.java similarity index 92% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Documents.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Documents.java index 123f971be91..0c1073c5232 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Documents.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Documents.java @@ -14,17 +14,17 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import forge.deck.generate.lda.lda.LDA; -import forge.deck.generate.lda.dataset.BagOfWords; -import forge.deck.generate.lda.dataset.Vocabularies; -import forge.deck.generate.lda.dataset.Vocabulary; +import forge.deck.lda.lda.LDA; +import forge.deck.lda.dataset.BagOfWords; +import forge.deck.lda.dataset.Vocabularies; +import forge.deck.lda.dataset.Vocabulary; class Documents { private List documents; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Topic.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Topic.java similarity index 96% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Topic.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Topic.java index 4b339840f56..0f396512ef7 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Topic.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Topic.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; class Topic { private final int id; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/TopicAssignment.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/TopicAssignment.java similarity index 97% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/TopicAssignment.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/TopicAssignment.java index 6da439faa4d..78f568ca679 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/TopicAssignment.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/TopicAssignment.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; import java.util.ArrayList; import java.util.List; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/TopicCounter.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/TopicCounter.java similarity index 95% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/TopicCounter.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/TopicCounter.java index 609f23fb2d7..70894da2d2a 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/TopicCounter.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/TopicCounter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; class TopicCounter { private AssignmentCounter topicCount; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Topics.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Topics.java similarity index 94% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Topics.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Topics.java index 69faf74cc85..0eb20f25177 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Topics.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Topics.java @@ -14,19 +14,19 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; -import forge.deck.generate.lda.lda.LDA; +import forge.deck.lda.lda.LDA; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; -import forge.deck.generate.lda.dataset.Vocabularies; +import forge.deck.lda.dataset.Vocabularies; class Topics { private List topics; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/VocabularyCounter.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/VocabularyCounter.java similarity index 95% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/VocabularyCounter.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/VocabularyCounter.java index e1b1d0c48c3..dac316f8e75 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/VocabularyCounter.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/VocabularyCounter.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; class VocabularyCounter { private AssignmentCounter vocabCount; diff --git a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Words.java b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Words.java similarity index 91% rename from forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Words.java rename to forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Words.java index bea3ba44129..24f628ea170 100644 --- a/forge-gui-desktop/src/test/java/forge/deck/generate/lda/lda/inference/internal/Words.java +++ b/forge-gui/src/main/java/forge/deck/lda/lda/inference/internal/Words.java @@ -14,12 +14,12 @@ * limitations under the License. */ -package forge.deck.generate.lda.lda.inference.internal; +package forge.deck.lda.lda.inference.internal; import java.util.Collections; import java.util.List; -import forge.deck.generate.lda.dataset.Vocabulary; +import forge.deck.lda.dataset.Vocabulary; class Words { private List words; diff --git a/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java b/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java index 272720236e0..d902d8b6e66 100644 --- a/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java +++ b/forge-gui/src/main/java/forge/limited/CardThemedDeckBuilder.java @@ -60,7 +60,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { protected Iterable onColorNonCreatures; protected Iterable keyCards; - protected static final boolean logToConsole = false; + protected static final boolean logToConsole = true; protected static final boolean logColorsToConsole = false; protected Map targetCMCs; @@ -113,8 +113,10 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { if(!colors.hasAllColors(keyCard.getRules().getColorIdentity().getColor())){ colors = ColorSet.fromMask(colors.getColor() | keyCard.getRules().getColorIdentity().getColor()); } - if(!colors.hasAllColors(secondKeyCard.getRules().getColorIdentity().getColor())){ - colors = ColorSet.fromMask(colors.getColor() | secondKeyCard.getRules().getColorIdentity().getColor()); + if(secondKeyCard!=null) { + if (!colors.hasAllColors(secondKeyCard.getRules().getColorIdentity().getColor())) { + colors = ColorSet.fromMask(colors.getColor() | secondKeyCard.getRules().getColorIdentity().getColor()); + } } numSpellsNeeded = ((Double)Math.floor(targetSize*(getCreaturePercentage()+getSpellPercentage()))).intValue(); numCreaturesToStart = ((Double)Math.ceil(targetSize*(getCreaturePercentage()))).intValue(); @@ -337,7 +339,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { rankedColorList.removeAll(keyCardList); } // Add the second keycard if not land - if(!secondKeyCard.getRules().getMainPart().getType().isLand()) { + if(secondKeyCard!=null && !secondKeyCard.getRules().getMainPart().getType().isLand()) { Iterable secondKeyCards = Iterables.filter(aiPlayables,PaperCard.Predicates.name(secondKeyCard.getName())); final List keyCardList = Lists.newArrayList(secondKeyCards); deckList.addAll(keyCardList); @@ -357,7 +359,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { landsNeeded--; } // Add the deck card - if(secondKeyCard.getRules().getMainPart().getType().isLand()) { + if(secondKeyCard!=null && secondKeyCard.getRules().getMainPart().getType().isLand()) { Iterable secondKeyCards = Iterables.filter(aiPlayables,PaperCard.Predicates.name(secondKeyCard.getName())); final List keyCardList = Lists.newArrayList(secondKeyCards); deckList.addAll(keyCardList); @@ -480,7 +482,11 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase { * @return name */ protected String generateName() { - return keyCard.getName() + " - " + secondKeyCard.getName() +" based deck"; + if(secondKeyCard!=null ) { + return keyCard.getName() + " - " + secondKeyCard.getName() + " based deck"; + }else{ + return keyCard.getName() + " based deck"; + } } /** diff --git a/forge-gui/src/main/java/forge/model/FModel.java b/forge-gui/src/main/java/forge/model/FModel.java index 78b0ba61fd1..8435f087d5e 100644 --- a/forge-gui/src/main/java/forge/model/FModel.java +++ b/forge-gui/src/main/java/forge/model/FModel.java @@ -26,6 +26,7 @@ import forge.achievement.*; import forge.ai.AiProfileUtil; import forge.card.CardPreferences; import forge.card.CardType; +import forge.deck.CardRelationLDAGenerator; import forge.deck.CardRelationMatrixGenerator; import forge.deck.io.DeckPreferences; import forge.game.GameFormat; @@ -219,6 +220,7 @@ public final class FModel { if(!FModel.getPreferences().getPrefBoolean(FPref.LOAD_CARD_SCRIPTS_LAZILY) &&FModel.getPreferences().getPrefBoolean(FPref.DECKGEN_CARDBASED)) { deckGenMatrixLoaded=CardRelationMatrixGenerator.initialize(); + deckGenMatrixLoaded=CardRelationLDAGenerator.initialize(); } }