First simple attempt at planar conquest generation code and example

(cherry picked from commit b11aa9b)
This commit is contained in:
austinio7116
2018-04-24 23:13:25 +01:00
committed by maustin
parent ed76e62d56
commit d96d1f2ee9
17 changed files with 599 additions and 5 deletions

View File

@@ -160,7 +160,7 @@ public class SimulateMatch {
private static void simulateSingleMatch(final Match mc, int iGame, boolean outputGamelog) {
public static void simulateSingleMatch(final Match mc, int iGame, boolean outputGamelog) {
final StopWatch sw = new StopWatch();
sw.start();

View File

@@ -0,0 +1,168 @@
package forge.planarconquestgenerate;
import com.google.common.base.Function;
import forge.GuiBase;
import forge.GuiDesktop;
import forge.LobbyPlayer;
import forge.StaticData;
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.TextUtil;
import forge.view.SimulateMatch;
import org.apache.commons.lang3.text.WordUtils;
import org.testng.annotations.Test;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Test
public class PlanarConquestGeneratorTest {
Map<String,List<Map.Entry<PaperCard,Integer>>> standardMap;
@Test
public void generatePlanarConquestDecks() {
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;
}
});
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;
for(PaperCard card: rankedList.subList(0,20)){
if(planarConquestFormat.getFilterPrinted().apply(card)) {
System.out.println(card.getName());
if(true) {
continue;
}
DeckGroup deckGroup = new DeckGroup("SimulatedTournament");
List<TournamentPlayer> players = new ArrayList<>();
int numPlayers=0;
for( int i=0; i<16;i++){
Deck genDeck = DeckgenUtil.buildPlanarConquestDeck(card, planarConquestFormat, deckFormat);
Deck d = new Deck(genDeck,genDeck.getName()+"_"+i);
deckGroup.addAiDeck(d);
players.add(new TournamentPlayer(GamePlayerUtil.createAiPlayer(d.getName(), 0), numPlayers));
numPlayers++;
}
TournamentSwiss tourney = new TournamentSwiss(players, 2);
tourney.initializeTournament();
String lastWinner = "";
int curRound = 0;
System.out.println(TextUtil.concatNoSpace("Starting a tournament with ",
String.valueOf(numPlayers), " players over ",
String.valueOf(tourney.getTotalRounds()), " rounds"));
while(!tourney.isTournamentOver()) {
if (tourney.getActiveRound() != curRound) {
if (curRound != 0) {
System.out.println(TextUtil.concatNoSpace("End Round - ", String.valueOf(curRound)));
}
curRound = tourney.getActiveRound();
System.out.println("");
System.out.println(TextUtil.concatNoSpace("Round ", String.valueOf(curRound) ," Pairings:"));
for(TournamentPairing pairing : tourney.getActivePairings()) {
System.out.println(pairing.outputHeader());
}
System.out.println("");
}
TournamentPairing pairing = tourney.getNextPairing();
List<RegisteredPlayer> 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();
String deckName = tourney.getAllPlayers().get(0).getPlayer().getName();
Deck winningDeck;
for(Deck deck:deckGroup.getAiDecks()){
if(deck.getName().equals(deckName)){
winningDeck=deck;
storage.save(winningDeck);
System.out.println(card.toString());
System.out.println(winningDeck.getName());
System.out.println(winningDeck.getAllCardsInASinglePool().toString());
break;
}
}
}
}
}
}

View File

@@ -0,0 +1,32 @@
[metadata]
Name=Champion of Dusk - Legion's Landing based deck_9
[Main]
1 Bishop of Binding|RIX
1 Bishop of the Bloodstained|XLN
1 Call to the Feast|XLN
1 Champion of Dusk|RIX
1 Dusk Legion Zealot|RIX
1 Fathom Fleet Captain|XLN
1 Fell Flagship|XLN
1 Field of Ruin|XLN
1 Forerunner of the Legion|RIX
1 Ixalan's Binding|XLN
1 Legion Lieutenant|RIX
1 Legion's Landing|XLN
1 Martyr of Dusk|RIX
1 Mavren Fein, Dusk Apostle|XLN
7 Plains|RIX
1 Queen's Commission|XLN
1 Radiant Destiny|RIX
1 Sadistic Skymarcher|RIX
1 Sanctum Seeker|XLN
1 Settle the Wreckage|XLN
1 Skymarcher Aspirant|RIX
8 Swamp|RIX
1 The Immortal Sun|RIX
1 Twilight Prophet|RIX
1 Unclaimed Territory|XLN
1 Walk the Plank|XLN
1 Wanted Scoundrels|XLN
[Sideboard]

View File

@@ -0,0 +1,31 @@
[metadata]
Name=Duskborne Skymarcher - Radiant Destiny based deck_2
[Main]
1 Bishop of Binding|RIX
1 Bishop of the Bloodstained|XLN
1 Call to the Feast|XLN
1 Champion of Dusk|RIX
1 Dusk Legion Zealot|RIX
1 Duskborne Skymarcher|XLN
1 Elenda, the Dusk Rose|RIX
1 Forerunner of the Legion|RIX
1 Ixalan's Binding|XLN
1 Legion Conquistador|XLN
1 Legion Lieutenant|RIX
1 Legion's Landing|XLN
1 Martyr of Dusk|RIX
1 Mavren Fein, Dusk Apostle|XLN
1 Pirate's Cutlass|XLN
8 Plains|RIX
1 Queen's Commission|XLN
1 Radiant Destiny|RIX
1 Sadistic Skymarcher|RIX
1 Sanctum Seeker|XLN
1 Skymarcher Aspirant|RIX
8 Swamp|RIX
1 Temple Altisaur|RIX
1 Tetzimoc, Primal Death|RIX
1 Unclaimed Territory|XLN
1 Vicious Conquistador|XLN
[Sideboard]

View File

@@ -0,0 +1,30 @@
[metadata]
Name=Elenda, the Dusk Rose - Legion Lieutenant based deck_4
[Main]
1 Bishop of the Bloodstained|XLN
1 Call to the Feast|XLN
1 Champion of Dusk|RIX
1 Dire Fleet Poisoner|RIX
1 Dusk Legion Zealot|RIX
1 Duskborne Skymarcher|XLN
1 Elenda, the Dusk Rose|RIX
1 Fathom Fleet Captain|XLN
1 Forerunner of the Coalition|RIX
1 Ixalan's Binding|XLN
1 Legion Lieutenant|RIX
1 Legion's Landing|XLN
1 Martyr of Dusk|RIX
1 Mavren Fein, Dusk Apostle|XLN
1 Pirate's Cutlass|XLN
8 Plains|RIX
1 Queen's Commission|XLN
1 Radiant Destiny|RIX
1 Sadistic Skymarcher|RIX
1 Settle the Wreckage|XLN
1 Skymarcher Aspirant|RIX
9 Swamp|RIX
1 Tetzimoc, Primal Death|RIX
1 The Immortal Sun|RIX
1 Walk the Plank|XLN
[Sideboard]

View File

@@ -0,0 +1,31 @@
[metadata]
Name=Forerunner of the Legion - Radiant Destiny based deck_10
[Main]
1 Bishop of Binding|RIX
1 Bishop of the Bloodstained|XLN
1 Call to the Feast|XLN
1 Champion of Dusk|RIX
1 Dusk Legion Zealot|RIX
1 Duskborne Skymarcher|XLN
1 Elenda, the Dusk Rose|RIX
1 Fell Flagship|XLN
1 Forerunner of the Coalition|RIX
1 Forerunner of the Legion|RIX
1 Ixalan's Binding|XLN
1 Legion Conquistador|XLN
1 Legion Lieutenant|RIX
1 Legion's Landing|XLN
1 Martyr of Dusk|RIX
1 Mavren Fein, Dusk Apostle|XLN
8 Plains|RIX
1 Queen's Commission|XLN
1 Radiant Destiny|RIX
1 Sadistic Skymarcher|RIX
1 Sanctum Seeker|XLN
1 Skymarcher Aspirant|RIX
8 Swamp|RIX
1 The Immortal Sun|RIX
1 Twilight Prophet|RIX
1 Unclaimed Territory|XLN
[Sideboard]

View File

@@ -0,0 +1,32 @@
[metadata]
Name=Legion Lieutenant - Skymarcher Aspirant based deck_3
[Main]
1 Bishop of the Bloodstained|XLN
1 Call to the Feast|XLN
1 Champion of Dusk|RIX
1 Crashing Tide|RIX
1 Curious Obsession|RIX
1 Dusk Legion Zealot|RIX
1 Duskborne Skymarcher|XLN
1 Elenda, the Dusk Rose|RIX
1 Forerunner of the Legion|RIX
1 Hostage Taker|XLN
2 Island|RIX
1 Ixalan's Binding|XLN
1 Kinjalli's Sunwing|XLN
1 Legion Lieutenant|RIX
1 Legion's Landing|XLN
1 Martyr of Dusk|RIX
1 Mavren Fein, Dusk Apostle|XLN
1 Pirate's Cutlass|XLN
7 Plains|RIX
1 Pride of Conquerors|RIX
1 Queen's Commission|XLN
1 Radiant Destiny|RIX
1 Skymarcher Aspirant|RIX
7 Swamp|RIX
1 Unclaimed Territory|XLN
1 Vraska's Contempt|XLN
1 Walk the Plank|XLN
[Sideboard]

View File

@@ -0,0 +1,32 @@
[metadata]
Name=Mavren Fein, Dusk Apostle - Call to the Feast based deck_15
[Main]
1 Bishop of Binding|RIX
1 Bishop of the Bloodstained|XLN
1 Call to the Feast|XLN
1 Champion of Dusk|RIX
1 Dusk Legion Zealot|RIX
1 Duskborne Skymarcher|XLN
1 Fell Flagship|XLN
1 Field of Ruin|XLN
1 Forerunner of the Coalition|RIX
1 Forerunner of the Legion|RIX
1 Ixalan's Binding|XLN
1 Legion Conquistador|XLN
1 Legion Lieutenant|RIX
1 Legion's Landing|XLN
1 Martyr of Dusk|RIX
1 Mavren Fein, Dusk Apostle|XLN
9 Plains|RIX
1 Profane Procession|RIX
1 Queen's Commission|XLN
1 Radiant Destiny|RIX
1 Sanctum Seeker|XLN
1 Settle the Wreckage|XLN
1 Skymarcher Aspirant|RIX
6 Swamp|RIX
1 Temple Altisaur|RIX
1 Tetzimoc, Primal Death|RIX
1 Unclaimed Territory|XLN
[Sideboard]

View File

@@ -0,0 +1,33 @@
[metadata]
Name=Crashing Tide - Jadelight Ranger based deck_12
[Main]
1 Carnage Tyrant|XLN
1 Champion of Dusk|RIX
1 Crashing Tide|RIX
1 Deeproot Elite|RIX
1 Drover of the Mighty|XLN
1 Fell Flagship|XLN
7 Forest|RIX
1 Hostage Taker|XLN
5 Island|RIX
1 Jade Bearer|RIX
1 Jadelight Ranger|RIX
1 Jungleborn Pioneer|RIX
1 Kumena's Speaker|XLN
1 Kumena, Tyrant of Orazca|RIX
1 Merfolk Branchwalker|XLN
1 Merfolk Mistbinder|RIX
1 Shapers of Nature|XLN
1 Silvergill Adept|RIX
1 Spell Pierce|XLN
3 Swamp|RIX
1 Swift Warden|RIX
1 Tempest Caller|XLN
1 Tendershoot Dryad|RIX
1 The Immortal Sun|RIX
1 Unclaimed Territory|XLN
1 Vraska's Contempt|XLN
1 Wanted Scoundrels|XLN
1 Watertrap Weaver|XLN
[Sideboard]

View File

@@ -0,0 +1,31 @@
[metadata]
Name=Kumena, Tyrant of Orazca - Kumena's Speaker based deck_11
[Main]
1 Air Elemental|XLN
1 Aquatic Incursion|RIX
1 Carnage Tyrant|XLN
1 Commune with Dinosaurs|XLN
1 Crashing Tide|RIX
1 Deeproot Elite|RIX
1 Deeproot Waters|XLN
8 Forest|RIX
8 Island|RIX
1 Jade Bearer|RIX
1 Jungleborn Pioneer|RIX
1 Kumena's Speaker|XLN
1 Kumena, Tyrant of Orazca|RIX
1 Merfolk Branchwalker|XLN
1 Merfolk Mistbinder|RIX
1 Mist-Cloaked Herald|RIX
1 Nezahal, Primal Tide|RIX
1 Ripjaw Raptor|XLN
1 River's Rebuke|XLN
1 Savage Stomp|XLN
1 Seafloor Oracle|RIX
1 Silvergill Adept|RIX
1 Snapping Sailback|XLN
1 Spell Pierce|XLN
1 Swift Warden|RIX
1 Unclaimed Territory|XLN
[Sideboard]

View File

@@ -0,0 +1,31 @@
[metadata]
Name=Merfolk Mistbinder - Kumena, Tyrant of Orazca based deck_11
[Main]
1 Aquatic Incursion|RIX
1 Carnage Tyrant|XLN
1 Crested Herdcaller|RIX
1 Deeproot Elite|RIX
1 Deeproot Waters|XLN
9 Forest|RIX
7 Island|RIX
1 Jade Bearer|RIX
1 Jungleborn Pioneer|RIX
1 Kumena's Speaker|XLN
1 Kumena, Tyrant of Orazca|RIX
1 Merfolk Branchwalker|XLN
1 Merfolk Mistbinder|RIX
1 Mist-Cloaked Herald|RIX
1 Pirate's Cutlass|XLN
1 Ripjaw Raptor|XLN
1 River's Rebuke|XLN
1 Savage Stomp|XLN
1 Seafloor Oracle|RIX
1 Shapers of Nature|XLN
1 Silvergill Adept|RIX
1 Spell Pierce|XLN
1 The Immortal Sun|RIX
1 Thrashing Brontodon|RIX
1 Unclaimed Territory|XLN
1 Vanquisher's Banner|XLN
[Sideboard]

View File

@@ -0,0 +1,31 @@
[metadata]
Name=Swift Warden - Merfolk Mistbinder based deck_2
[Main]
1 Cherished Hatchling|RIX
1 Deeproot Elite|RIX
1 Deeproot Waters|XLN
1 Fell Flagship|XLN
9 Forest|RIX
7 Island|RIX
1 Jade Bearer|RIX
1 Jadelight Ranger|RIX
1 Jungleborn Pioneer|RIX
1 Kopala, Warden of Waves|XLN
1 Kumena's Speaker|XLN
1 Kumena, Tyrant of Orazca|RIX
1 Merfolk Branchwalker|XLN
1 Merfolk Mistbinder|RIX
1 Mist-Cloaked Herald|RIX
1 Nezahal, Primal Tide|RIX
1 Ripjaw Raptor|XLN
1 Seafloor Oracle|RIX
1 Silvergill Adept|RIX
1 Spell Pierce|XLN
1 Swift Warden|RIX
1 Tendershoot Dryad|RIX
1 The Immortal Sun|RIX
1 Unclaimed Territory|XLN
1 Vanquisher's Banner|XLN
1 Warkite Marauder|RIX
[Sideboard]

View File

@@ -0,0 +1,33 @@
[metadata]
Name=Gishath, Sun's Avatar - Commune with Dinosaurs based deck_12
[Main]
1 Atzocan Seer|RIX
1 Bishop of Binding|RIX
1 Captivating Crew|XLN
1 Carnage Tyrant|XLN
1 Commune with Dinosaurs|XLN
1 Deathgorge Scavenger|XLN
1 Drover of the Mighty|XLN
8 Forest|RIX
1 Ghalta, Primal Hunger|RIX
1 Gishath, Sun's Avatar|XLN
1 Ixalan's Binding|XLN
1 Mavren Fein, Dusk Apostle|XLN
1 Merfolk Branchwalker|XLN
3 Mountain|RIX
1 Otepec Huntmaster|XLN
4 Plains|RIX
1 Regisaur Alpha|XLN
1 Rekindling Phoenix|RIX
1 Ripjaw Raptor|XLN
1 Rootbound Crag|XLN
1 Settle the Wreckage|XLN
1 Sunpetal Grove|XLN
1 Swift Warden|RIX
1 Temple Altisaur|RIX
1 Thrashing Brontodon|RIX
1 Thunderherd Migration|RIX
1 Tilonalli's Knight|XLN
1 Zacama, Primal Calamity|RIX
[Sideboard]

View File

@@ -0,0 +1,33 @@
[metadata]
Name=Otepec Huntmaster - Thunderherd Migration based deck_10
[Main]
1 Carnage Tyrant|XLN
1 Charging Monstrosaur|XLN
1 Commune with Dinosaurs|XLN
1 Deathgorge Scavenger|XLN
1 Dire Fleet Captain|XLN
1 Drover of the Mighty|XLN
7 Forest|RIX
1 Ghalta, Primal Hunger|RIX
1 Lightning Strike|XLN
4 Mountain|RIX
1 Otepec Huntmaster|XLN
1 Pirate's Cutlass|XLN
1 Ranging Raptors|XLN
1 Reckless Rage|RIX
1 Regisaur Alpha|XLN
1 Rekindling Phoenix|RIX
1 Ripjaw Raptor|XLN
1 Rootbound Crag|XLN
1 Sanctum Seeker|XLN
1 Savage Stomp|XLN
4 Swamp|RIX
1 Thrashing Brontodon|RIX
1 Thunderherd Migration|RIX
1 Unclaimed Territory|XLN
1 Vraska's Contempt|XLN
1 Vraska, Relic Seeker|XLN
1 Walk the Plank|XLN
1 Wayward Swordtooth|RIX
[Sideboard]

View File

@@ -0,0 +1,33 @@
[metadata]
Name=Savage Stomp - Carnage Tyrant based deck_2
[Main]
1 Angrath, the Flame-Chained|RIX
1 Captivating Crew|XLN
1 Carnage Tyrant|XLN
1 Commune with Dinosaurs|XLN
1 Deathgorge Scavenger|XLN
1 Dire Fleet Daredevil|RIX
1 Dire Fleet Neckbreaker|RIX
1 Dire Fleet Poisoner|RIX
1 Drover of the Mighty|XLN
1 Fell Flagship|XLN
1 Forerunner of the Coalition|RIX
8 Forest|RIX
1 Ghalta, Primal Hunger|RIX
1 Jadelight Ranger|RIX
1 Merfolk Branchwalker|XLN
4 Mountain|RIX
1 Otepec Huntmaster|XLN
1 Ranging Raptors|XLN
1 Regisaur Alpha|XLN
1 Rekindling Phoenix|RIX
1 Ripjaw Raptor|XLN
1 Rootbound Crag|XLN
1 Savage Stomp|XLN
3 Swamp|RIX
1 Thrashing Brontodon|RIX
1 Thunderherd Migration|RIX
1 Unclaimed Territory|XLN
1 Vraska's Contempt|XLN
[Sideboard]

View File

@@ -70,6 +70,11 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase {
super(pool,format);
}
public CardThemedDeckBuilder(PaperCard keyCard0, PaperCard secondKeyCard0, final List<PaperCard> dList, GameFormat format, boolean isForAI){
this(keyCard0,secondKeyCard0, dList, format, isForAI, DeckFormat.Constructed);
}
/**
*
* Constructor.
@@ -77,7 +82,7 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase {
* @param dList
* Cards to build the deck from.
*/
public CardThemedDeckBuilder(PaperCard keyCard0, PaperCard secondKeyCard0, final List<PaperCard> dList, GameFormat format, boolean isForAI) {
public CardThemedDeckBuilder(PaperCard keyCard0, PaperCard secondKeyCard0, final List<PaperCard> dList, GameFormat format, boolean isForAI, DeckFormat deckFormat) {
super(new DeckGenPool(FModel.getMagicDb().getCommonCards().getUniqueCards()), DeckFormat.Constructed, format.getFilterPrinted());
this.availableList = dList;
keyCard=keyCard0;
@@ -91,16 +96,20 @@ public class CardThemedDeckBuilder extends DeckGeneratorBase {
this.aiPlayables = Lists.newArrayList(availableList);
}
this.availableList.removeAll(aiPlayables);
targetSize=DeckFormat.Constructed.getMainRange().getMinimum();
targetSize=deckFormat.getMainRange().getMinimum();
FullDeckColors deckColors = new FullDeckColors();
int cardCount=0;
//get colours for first 20 cards
int colourCheckAmount = 20;
if (targetSize < 60){
colourCheckAmount = 10;//lower amount for planar decks
}
//get colours for first few cards
for(PaperCard c:getAiPlayables()){
if(deckColors.canChoseMoreColors()){
deckColors.addColorsOf(c);
cardCount++;
}
if(cardCount>20){
if(cardCount > colourCheckAmount){
break;
}
}

View File

@@ -145,6 +145,10 @@ public abstract class AbstractTournament implements Serializable {
}
}
public List<TournamentPlayer> getAllPlayers(){
return allPlayers;
}
public static List<RegisteredPlayer> registerTournamentPlayers(TournamentPairing pairing, DeckGroup decks) {
List<RegisteredPlayer> registered = Lists.newArrayList();
for (TournamentPlayer pl : pairing.getPairedPlayers()) {