Merge pull request #1154 from marthinwurer/master

Added two Historical Standard deck validators
This commit is contained in:
Justin Godesky 2015-07-27 06:27:26 -04:00
commit 79dd62fefc
2 changed files with 438 additions and 0 deletions

View file

@ -0,0 +1,227 @@
package mage.deck;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.decks.Constructed;
import mage.cards.decks.Deck;
import mage.constants.SetType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
/**
* This class represents a deck from any past standard.
*
* This class was originally made to work with the historical standard ruleset.
* Data taken from http://thattournament.website/historic-tournament.php
* (site changed, originally thtp://mtgt.nfshost.com/historic-tournament.php)
*
* If there are any questions or corrections, feel free to contact me.
*
* @author Marthinwurer (at gmail.com)
*/
public class HistoricalStandard extends Constructed {
/*
* This array stores the set codes of each standard up to
* Kamigawa/Ravnica standard, where rotation stabilized.
*/
protected static final String[][] standards = {
// 1st standard: The Dark, Fallen Empires, and 4th.
{ "DRK", "FEM", "4ED" },
// 2nd standard: 4th, Fallen Empires, Ice Age, Chronicles, Homelands,
// Alliances, and Mirage.
{"FEM", "4ED", "ICE", "HML", "ALL", "MIR"},
// 3rd standard: 4th, Chronicles, Alliances, Mirage, Visions.
{"4ED", "ALL", "MIR", "VIS"},
// 4th Standard: Ice Age, Homelands, Alliances, Mirage, Visions, 5th,
// and Weatherlight.
{"ICE", "HML", "ALL", "MIR", "VIS", "5ED", "WTH"},
// 5th Standard: Mirage, Visions, 5th, Weatherlight, Tempest,
// Stronghold, and Exodus.
{"MIR", "VIS", "5ED", "WTH", "TMP", "STH", "EXO"},
// 6th Standard: 5th, Tempest, Stronghold, Exodus, Urza's Saga, Urza's
// Legacy, Urza's Destiny.
{"5ED", "TMP", "STH", "EXO", "USG", "ULG"},
// 7th Standard: Tempest, Stronghold, Exodus, Urza's Saga, Urza's
// Legacy, 6th, Urza's Destiny.
{"TMP", "STH", "EXO", "USG", "ULG", "6ED", "UDS"},
// 8th Standard: Urza's Saga, Urza's Legacy, 6th, Urza's Destiny,
// Mercadian Masques, Nemesis, Prophecy.
{"USG", "ULG", "6ED", "UDS", "MMQ", "NMS", "PCY"},
// 9th Standard
{"6ED", "MMQ", "NMS", "PCY", "INV", "PLS"},
// 10th Standard
{"7ED", "MMQ", "NMS", "PCY", "INV", "PLS", "APC"},
// 11th Standard
{"7ED", "INV", "APC", "PLS", "ODY", "TOR", "JUD"},
// 12th Standard
{"7ED", "ODY", "TOR", "JUD", "ONS", "LGN", "LGN"},
// 13th Standard
{"8ED", "ODY", "TOR", "JUD", "ONS", "LGN", "LGN"},
// 14th Standard
{"8ED", "ONS", "LGN", "LGN", "MRD", "DST", "5DN"},
// 15th Standard
{"8ED", "MRD", "DST", "5DN", "CHK", "BOK", "SOK"},
// 16th Standard
{"9ED", "MRD", "DST", "5DN", "CHK", "BOK", "SOK"},
// 17th Standard
{"9ED", "CHK", "BOK", "SOK", "RAV", "GPT", "DIS", "CSP"},
// 18th Standard
{"9ED", "RAV", "GPT", "DIS", "CSP", "TSP", "TSB", "PLC", "FUT"},
// 19th Standard
{"10E", "RAV", "GPT", "DIS", "CSP", "TSP", "PLC", "FUT"},
// 20th Standard
{"10E", "CSP", "TSP", "PLC", "FUT", "LRW", "MOR", "SHM", "EVE"},
// 21st Standard
{"10E", "LRW", "MOR", "SHM", "EVE", "ALA", "CON", "ARB"}
};
/**
* Constructor. Don't need to mess with any of the sets yet; that will be
* done in the overridden validate function.
*/
public HistoricalStandard() {
super("Constructed - Historical Standard");
// banned cards
banned.add("Balance");
// Not banned in the format, but it is either this or Misty, and most
// people choose Misty.
banned.add("Batterskull");
banned.add("Memory Jar");
banned.add("Mind Over Matter");
banned.add("Mind Twist");
banned.add("Skullclamp");
banned.add("Tolarian Academy");
banned.add("Yawgmoth's Bargain");
}
/**
* Overridden validate function. Changes the standard sets, then uses the
* regular validation function to test validity.
* @param deck - the deck to validate.
* @return
*/
@Override
public boolean validate(Deck deck) {
Map<String, String> leastInvalid = null;
boolean valid = false;
// up to Lorwyn/Alara, standards will have to be hard-coded.
// iterate through the array of standards.
for (String[] sets : standards) {
// clear the invalid list
invalid.clear();
// add the sets to the setCodes.
setCodes = new ArrayList<>(Arrays.asList(sets));
// validate it. If it validates, clear the invalid cards and break.
if (super.validate(deck)) {
valid = true;
break;
}
// if the map holding the invalid cards is empty, set it to a
// copy of the current invalid list.
if (leastInvalid == null) {
leastInvalid = new HashMap<>(this.getInvalid());
continue;
}
// see how many invalid cards there are. if there are less invalid
// cards than the stored invalid list, assign the current invalid
// to leastInvalid.
if (leastInvalid.size() > this.getInvalid().size()) {
leastInvalid = new HashMap<>(this.getInvalid());
}
}
// After testing the first few standards, do the regular ones.
// set the initial starting and ending date, as well as the current.
GregorianCalendar start = new GregorianCalendar(2006,
Calendar.SEPTEMBER, 1);
GregorianCalendar end = new GregorianCalendar(2008,
Calendar.SEPTEMBER, 1);
GregorianCalendar current = new GregorianCalendar();
// use the method for determining regular standard legality, but change
// the date for each standard.
while (end.before(current) && !valid) {
// clear the invalid list and set codes.
setCodes.clear();
invalid.clear();
// increment the start and end dates.
start.set(Calendar.YEAR, start.get(Calendar.YEAR) + 1);
end.set(Calendar.YEAR, start.get(Calendar.YEAR) + 2);
// Get the sets in that time period.
// (code taken from standard.java)
for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getReleaseDate().after(start.getTime())
&& set.getReleaseDate().before(end.getTime())
&& (set.getSetType() == SetType.CORE || set.getSetType() == SetType.EXPANSION)) {
setCodes.add(set.getCode());
}
}
// validate it. If it validates, clear the invalid cards and break.
if (super.validate(deck)) {
invalid.clear();
valid = true;
break;
}
// see how many invalid cards there are. if there are less invalid
// cards than the stored invalid list, assign the current invalid
// to leastInvalid.
if (leastInvalid == null){
leastInvalid = new HashMap<>(this.getInvalid());
}else if (leastInvalid.size() > this.getInvalid().size()) {
leastInvalid = new HashMap<>(this.getInvalid());
}
}
// if no standard environment is valid, set the invalid to the
// invalid that had the least errors.
if( !valid ){
this.invalid = new HashMap<>(leastInvalid);
}
// return the validity.
return valid;
}
}

View file

@ -0,0 +1,211 @@
package mage.deck;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.decks.Constructed;
import mage.cards.decks.Deck;
import mage.constants.SetType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;
/**
* This class represents a deck conforming to the rules contained in the
subreddit /r/SuperStandard.
*
* This class was originally made to work with the historical standard ruleset.
* Data taken from http://thattournament.website/historic-tournament.php
* (site changed, originally thtp://mtgt.nfshost.com/historic-tournament.php)
*
* If there are any questions or corrections, feel free to contact me.
*
* @author Marthinwurer (at gmail.com)
*/
public class SuperStandard extends Constructed {
/*
* This array stores the set codes of each standard up to
* Kamigawa/Ravnica standard, where rotation stabilized.
* Data taken from http://thattournament.website/historic-tournament.php
*/
protected static final String[][] standards = {
// 11th Standard
{"7ED", "INV", "APC", "PLS", "ODY", "TOR", "JUD"},
// 12th Standard
{"7ED", "ODY", "TOR", "JUD", "ONS", "LGN", "LGN"},
// 13th Standard
{"8ED", "ODY", "TOR", "JUD", "ONS", "LGN", "LGN"},
// 14th Standard
{"8ED", "ONS", "LGN", "LGN", "MRD", "DST", "5DN"},
// 15th Standard
{"8ED", "MRD", "DST", "5DN", "CHK", "BOK", "SOK"},
// 16th Standard
{"9ED", "MRD", "DST", "5DN", "CHK", "BOK", "SOK"},
// 17th Standard
{"9ED", "CHK", "BOK", "SOK", "RAV", "GPT", "DIS", "CSP"},
// 18th Standard
{"9ED", "RAV", "GPT", "DIS", "CSP", "TSP", "TSB", "PLC", "FUT"},
// 19th Standard
{"10E", "RAV", "GPT", "DIS", "CSP", "TSP", "PLC", "FUT"},
// 20th Standard
{"10E", "CSP", "TSP", "PLC", "FUT", "LRW", "MOR", "SHM", "EVE"},
// 21st Standard
{"10E", "LRW", "MOR", "SHM", "EVE", "ALA", "CON", "ARB"}
};
/**
* Constructor. Don't need to mess with any of the sets yet; that will be
* done in the overridden validate function.
*/
public SuperStandard() {
super("Constructed - All Standards");
banned.add("Ancient Den");
banned.add("Arcbound Ravager");
banned.add("Disciple of the Vault");
banned.add("Great Furnace");
banned.add("Jace, the Mind Sculptor");
banned.add("Seat of the Synod");
banned.add("Skullclamp");
banned.add("Tree of Tales");
banned.add("Vault of Whispers");
}
/**
* Overridden validate function. Changes the standard sets, then uses the
* regular validation function to test validity.
* @param deck - the deck to validate.
* @return
*/
@Override
public boolean validate(Deck deck) {
Map<String, String> leastInvalid = null;
boolean valid = false;
// up to Lorwyn/Alara, standards will have to be hard-coded.
// iterate through the array of standards.
for (String[] sets : standards) {
// clear the invalid list
invalid.clear();
// add the sets to the setCodes.
setCodes = new ArrayList<>(Arrays.asList(sets));
// if either of the mirrodin blocks are in the time period, ban
// misty and darksteel citadel
if( setCodes.contains("MRD") || setCodes.contains("SOM")){
banned.add("Darksteel Citadel");
banned.add("Stoneforge Mystic");
}else{
banned.remove("Darksteel Citadel");
banned.remove("Stoneforge Mystic");
}
// validate it. If it validates, clear the invalid cards and break.
if (super.validate(deck)) {
valid = true;
break;
}
// if the map holding the invalid cards is empty, set it to a
// copy of the current invalid list.
if (leastInvalid == null) {
leastInvalid = new HashMap<>(this.getInvalid());
continue;
}
// see how many invalid cards there are. if there are less invalid
// cards than the stored invalid list, assign the current invalid
// to leastInvalid.
if (leastInvalid.size() > this.getInvalid().size()) {
leastInvalid = new HashMap<>(this.getInvalid());
}
}
// After testing the first few standards, do the regular ones.
// set the initial starting and ending date, as well as the current.
GregorianCalendar start = new GregorianCalendar(2006,
Calendar.SEPTEMBER, 1);
GregorianCalendar end = new GregorianCalendar(2008,
Calendar.SEPTEMBER, 1);
GregorianCalendar current = new GregorianCalendar();
// use the method for determining regular standard legality, but change
// the date for each standard.
while (end.before(current) && !valid) {
// clear the invalid list and set codes.
setCodes.clear();
invalid.clear();
// increment the start and end dates.
start.set(Calendar.YEAR, start.get(Calendar.YEAR) + 1);
end.set(Calendar.YEAR, start.get(Calendar.YEAR) + 2);
// Get the sets in that time period.
// (code taken from standard.java)
for (ExpansionSet set : Sets.getInstance().values()) {
if (set.getReleaseDate().after(start.getTime())
&& set.getReleaseDate().before(end.getTime())
&& (set.getSetType() == SetType.CORE || set.getSetType() == SetType.EXPANSION)) {
setCodes.add(set.getCode());
}
}
// if either of the mirrodin blocks are in the time period, ban
// misty and darksteel citadel
if( setCodes.contains("MRD") || setCodes.contains("SOM")){
banned.add("Darksteel Citadel");
banned.add("Stoneforge Mystic");
}else{
banned.remove("Darksteel Citadel");
banned.remove("Stoneforge Mystic");
}
// validate it. If it validates, clear the invalid cards and break.
if (super.validate(deck)) {
invalid.clear();
valid = true;
break;
}
// see how many invalid cards there are. if there are less invalid
// cards than the stored invalid list, assign the current invalid
// to leastInvalid.
if (leastInvalid == null){
leastInvalid = new HashMap<>(this.getInvalid());
}else if (leastInvalid.size() > this.getInvalid().size()) {
leastInvalid = new HashMap<>(this.getInvalid());
}
}
// if no standard environment is valid, set the invalid to the
// invalid that had the least errors.
if( !valid ){
this.invalid = new HashMap<>(leastInvalid);
}
// return the validity.
return valid;
}
}