mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Added abstract GA code
(cherry picked from commit c534c14)
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
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.StaticData;
|
||||||
|
import forge.card.CardRulesPredicates;
|
||||||
|
import forge.deck.CardRelationMatrixGenerator;
|
||||||
|
import forge.deck.Deck;
|
||||||
|
import forge.deck.DeckFormat;
|
||||||
|
import forge.deck.io.DeckStorage;
|
||||||
|
import forge.game.GameFormat;
|
||||||
|
import forge.game.GameRules;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.limited.CardRanker;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgeConstants;
|
||||||
|
import forge.properties.ForgePreferences;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public class PlanarConquestGeneratorGATest {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test(){
|
||||||
|
|
||||||
|
GuiBase.setInterface(new GuiDesktop());
|
||||||
|
FModel.initialize(null, new Function<ForgePreferences, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void apply(ForgePreferences preferences) {
|
||||||
|
preferences.setPref(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY, false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
PlanarConquestGeneraterGA ga = new PlanarConquestGeneraterGA();
|
||||||
|
ga.initializeCards(40);
|
||||||
|
ga.run();
|
||||||
|
List<Deck> winners = ga.listFinalPopulation();
|
||||||
|
|
||||||
|
DeckStorage storage = new DeckStorage(new File(ForgeConstants.DECK_CONSTRUCTED_DIR), ForgeConstants.DECK_BASE_DIR);
|
||||||
|
|
||||||
|
for(Deck deck:winners){
|
||||||
|
storage.save(deck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -109,6 +109,114 @@ public class PlanarConquestGeneratorTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void generateBestDecksGA() {
|
||||||
|
|
||||||
|
GuiBase.setInterface(new GuiDesktop());
|
||||||
|
FModel.initialize(null, new Function<ForgePreferences, Void>() {
|
||||||
|
@Override
|
||||||
|
public Void apply(ForgePreferences preferences) {
|
||||||
|
preferences.setPref(ForgePreferences.FPref.LOAD_CARD_SCRIPTS_LAZILY, false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
int cardsToUse=40;
|
||||||
|
GameFormat format = FModel.getFormats().getStandard();
|
||||||
|
GameRules rules = new GameRules(GameType.Constructed);
|
||||||
|
standardMap = CardRelationMatrixGenerator.cardPools.get(format.getName());
|
||||||
|
List<String> cardNames = new ArrayList<>(standardMap.keySet());
|
||||||
|
List<PaperCard> cards = new ArrayList<>();
|
||||||
|
for(String cardName:cardNames){
|
||||||
|
cards.add(StaticData.instance().getCommonCards().getUniqueByName(cardName));
|
||||||
|
}
|
||||||
|
List<PaperCard> rankedList = CardRanker.rankCardsInDeck(cards);
|
||||||
|
List<String> sets = new ArrayList<>();
|
||||||
|
sets.add("XLN");
|
||||||
|
sets.add("RIX");
|
||||||
|
DeckStorage storage = new DeckStorage(new File(ForgeConstants.DECK_CONSTRUCTED_DIR), ForgeConstants.DECK_BASE_DIR);
|
||||||
|
GameFormat planarConquestFormat = new GameFormat("conquest",sets,null);
|
||||||
|
DeckFormat deckFormat = DeckFormat.PlanarConquest;
|
||||||
|
|
||||||
|
Iterable<PaperCard> filtered= Iterables.filter(rankedList, 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),
|
||||||
|
planarConquestFormat.getFilterPrinted()));
|
||||||
|
|
||||||
|
List<PaperCard> filteredList = Lists.newArrayList(filtered);
|
||||||
|
|
||||||
|
DeckGroup deckGroup = new DeckGroup("SimulatedTournament");
|
||||||
|
List<TournamentPlayer> players = new ArrayList<>();
|
||||||
|
int numPlayers=0;
|
||||||
|
for(PaperCard card: filteredList.subList(0,cardsToUse)){
|
||||||
|
System.out.println(card.getName());
|
||||||
|
|
||||||
|
|
||||||
|
for( int i=0; i<4;i++){
|
||||||
|
Deck genDeck = DeckgenUtil.buildPlanarConquestDeck(card, planarConquestFormat, deckFormat);
|
||||||
|
Deck d = new Deck(genDeck,genDeck.getName()+"_"+i+"_"+0);
|
||||||
|
deckGroup.addAiDeck(d);
|
||||||
|
players.add(new TournamentPlayer(GamePlayerUtil.createAiPlayer(d.getName(), 0), numPlayers));
|
||||||
|
numPlayers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TournamentSwiss tourney = null;
|
||||||
|
for (int m=1;m<10;++m) {
|
||||||
|
|
||||||
|
//get best decks in population
|
||||||
|
tourney = new TournamentSwiss(players, 2);
|
||||||
|
tourney = runTournament(tourney, rules, numPlayers, deckGroup);
|
||||||
|
players = new ArrayList<>();
|
||||||
|
DeckGroup newDeckGroup = new DeckGroup("SimulatedTournament"+m);
|
||||||
|
numPlayers=0;
|
||||||
|
int winnerCount = new Float(tourney.getAllPlayers().size()* .5f).intValue();
|
||||||
|
for (int k = 0; k < winnerCount; k++) {
|
||||||
|
String deckName = tourney.getAllPlayers().get(k).getPlayer().getName();
|
||||||
|
for (Deck winningDeck : deckGroup.getAiDecks()) {
|
||||||
|
if (winningDeck.getName().equals(deckName)) {
|
||||||
|
newDeckGroup.addAiDeck(winningDeck);
|
||||||
|
players.add(new TournamentPlayer(GamePlayerUtil.createAiPlayer(winningDeck.getName(), 0), numPlayers));
|
||||||
|
numPlayers++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deckGroup = newDeckGroup;
|
||||||
|
|
||||||
|
//add random decks
|
||||||
|
for(PaperCard card: filteredList.subList(0,cardsToUse)){
|
||||||
|
System.out.println(card.getName());
|
||||||
|
for( int i=0; i<2;i++){
|
||||||
|
Deck genDeck = DeckgenUtil.buildPlanarConquestDeck(card, planarConquestFormat, deckFormat);
|
||||||
|
Deck d = new Deck(genDeck,genDeck.getName()+"_"+i+"_"+m);
|
||||||
|
deckGroup.addAiDeck(d);
|
||||||
|
players.add(new TournamentPlayer(GamePlayerUtil.createAiPlayer(d.getName(), 0), numPlayers));
|
||||||
|
numPlayers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tourney = new TournamentSwiss(players, 2);
|
||||||
|
tourney = runTournament(tourney, rules, numPlayers, deckGroup);
|
||||||
|
|
||||||
|
int winnerCount = new Float(tourney.getAllPlayers().size()* 0.25f).intValue();
|
||||||
|
for (int k = 0; k < winnerCount; k++) {
|
||||||
|
String deckName = tourney.getAllPlayers().get(k).getPlayer().getName();
|
||||||
|
Deck winningDeck;
|
||||||
|
for(Deck deck:deckGroup.getAiDecks()){
|
||||||
|
if(deck.getName().equals(deckName)){
|
||||||
|
winningDeck=deck;
|
||||||
|
storage.save(winningDeck);
|
||||||
|
System.out.println(winningDeck.getName());
|
||||||
|
System.out.println(winningDeck.getAllCardsInASinglePool().toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void generatePlanarConquestCommanderDecks() {
|
public void generatePlanarConquestCommanderDecks() {
|
||||||
|
|
||||||
@@ -155,7 +263,7 @@ public class PlanarConquestGeneratorTest {
|
|||||||
DeckGroup deckGroup = new DeckGroup("SimulatedTournament");
|
DeckGroup deckGroup = new DeckGroup("SimulatedTournament");
|
||||||
List<TournamentPlayer> players = new ArrayList<>();
|
List<TournamentPlayer> players = new ArrayList<>();
|
||||||
int numPlayers=0;
|
int numPlayers=0;
|
||||||
for( int i=0; i<2;i++){
|
for( int i=0; i<16;i++){
|
||||||
Deck genDeck = DeckgenUtil.buildPlanarConquestCommanderDeck(card, planarConquestFormat, deckFormat);
|
Deck genDeck = DeckgenUtil.buildPlanarConquestCommanderDeck(card, planarConquestFormat, deckFormat);
|
||||||
Deck d = new Deck(genDeck,genDeck.getName()+"_"+i);
|
Deck d = new Deck(genDeck,genDeck.getName()+"_"+i);
|
||||||
deckGroup.addAiDeck(d);
|
deckGroup.addAiDeck(d);
|
||||||
|
|||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package forge.limited;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.card.CardRulesPredicates;
|
||||||
|
import forge.card.ColorSet;
|
||||||
|
import forge.deck.DeckFormat;
|
||||||
|
import forge.deck.generation.DeckGenPool;
|
||||||
|
import forge.game.GameFormat;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.model.FModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by maustin on 28/02/2018.
|
||||||
|
*/
|
||||||
|
public class CardThemedConquestDeckBuilder extends CardThemedDeckBuilder {
|
||||||
|
|
||||||
|
public CardThemedConquestDeckBuilder(PaperCard commanderCard0, final List<PaperCard> dList, GameFormat gameFormat, boolean isForAI, DeckFormat format) {
|
||||||
|
super(new DeckGenPool(
|
||||||
|
Iterables.filter(FModel.getMagicDb().getCommonCards().getUniqueCards(),
|
||||||
|
gameFormat.getFilterPrinted())
|
||||||
|
), format);
|
||||||
|
this.availableList = dList;
|
||||||
|
keyCard = commanderCard0;
|
||||||
|
secondKeyCard = null;
|
||||||
|
// remove Unplayables
|
||||||
|
if(isForAI) {
|
||||||
|
final Iterable<PaperCard> playables = Iterables.filter(availableList,
|
||||||
|
Predicates.compose(CardRulesPredicates.IS_KEPT_IN_AI_DECKS, PaperCard.FN_GET_RULES));
|
||||||
|
this.aiPlayables = Lists.newArrayList(playables);
|
||||||
|
}else{
|
||||||
|
this.aiPlayables = Lists.newArrayList(availableList);
|
||||||
|
}
|
||||||
|
this.availableList.removeAll(aiPlayables);
|
||||||
|
targetSize=format.getMainRange().getMinimum();
|
||||||
|
colors = keyCard.getRules().getColorIdentity();
|
||||||
|
colors = ColorSet.fromMask(colors.getColor() | keyCard.getRules().getColorIdentity().getColor());
|
||||||
|
if(secondKeyCard!=null) {
|
||||||
|
colors = ColorSet.fromMask(colors.getColor() | secondKeyCard.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("Pre Colors: " + colors.toEnumSet().toString());
|
||||||
|
}
|
||||||
|
findBasicLandSets();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addKeyCards(){
|
||||||
|
//do nothing as keycards are commander/partner and are added by the DeckGenUtils
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addLandKeyCards(){
|
||||||
|
//do nothing as keycards are commander/partner and are added by the DeckGenUtils
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addThirdColorCards(int num) {
|
||||||
|
//do nothing as we cannot add extra colours beyond commanders
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateColors(){
|
||||||
|
//do nothing as we cannot deviate from commander colours
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Generate a descriptive name.
|
||||||
|
*
|
||||||
|
* @return name
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String generateName() {
|
||||||
|
return keyCard.getName() +" based commander deck";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package forge.util;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import forge.StaticData;
|
||||||
|
import forge.card.CardRulesPredicates;
|
||||||
|
import forge.deck.CardRelationMatrixGenerator;
|
||||||
|
import forge.deck.DeckFormat;
|
||||||
|
import forge.deck.io.DeckStorage;
|
||||||
|
import forge.game.GameFormat;
|
||||||
|
import forge.game.GameRules;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.limited.CardRanker;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgeConstants;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class AbstractGeneticAlgorithm<T> {
|
||||||
|
|
||||||
|
protected List<T> population;
|
||||||
|
private int targetPopulationSize;
|
||||||
|
private float pruneRatio = 0.5f;
|
||||||
|
public int generationCount = 0;
|
||||||
|
|
||||||
|
public void initializePopulation(List<T> population){
|
||||||
|
this.population = population;
|
||||||
|
targetPopulationSize = population.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void evaluateFitness();
|
||||||
|
|
||||||
|
public void pruneWeakest(){
|
||||||
|
population = population.subList(0, new Float(population.size()*pruneRatio).intValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void generateChildren(){
|
||||||
|
while(population.size()<targetPopulationSize){
|
||||||
|
int randomIndex = new Double(population.size()*Math.pow(MyRandom.getRandom().nextDouble(), 0.25)/2d).intValue();
|
||||||
|
if(MyRandom.getRandom().nextBoolean()){
|
||||||
|
population.add(mutateObject(population.get(randomIndex)));
|
||||||
|
}else{
|
||||||
|
int secondIndex = randomIndex;
|
||||||
|
while(secondIndex != randomIndex){
|
||||||
|
secondIndex = new Double(population.size()*Math.pow(MyRandom.getRandom().nextDouble(), 0.25)/2d).intValue();
|
||||||
|
}
|
||||||
|
population.add(createChild(population.get(randomIndex)
|
||||||
|
, population.get(secondIndex)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract T mutateObject(T parent1);
|
||||||
|
|
||||||
|
protected abstract T createChild(T parent1, T parent2);
|
||||||
|
|
||||||
|
public void run(){
|
||||||
|
while(true){
|
||||||
|
evaluateFitness();
|
||||||
|
pruneWeakest();
|
||||||
|
generationCount++;
|
||||||
|
if(!shouldContinue()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
generateChildren();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<T> listFinalPopulation(){
|
||||||
|
pruneWeakest();
|
||||||
|
return population;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract boolean shouldContinue();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user