diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Historic.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Historic.java
new file mode 100644
index 00000000000..3be57050599
--- /dev/null
+++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Historic.java
@@ -0,0 +1,59 @@
+package mage.deck;
+
+import mage.cards.ExpansionSet;
+import mage.cards.Sets;
+import mage.cards.decks.Constructed;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+/**
+ * @author mikalinn777
+ *
+ * Historic is a nonrotating format in MTGA. https://mtg.gamepedia.com/Historic_(format)
+ */
+public class Historic extends Constructed {
+
+ public Historic() {
+ super("Constructed - Historic");
+
+ Date cutoff = new GregorianCalendar(2017, Calendar.SEPTEMBER, 29).getTime(); // XLN release date
+ for (ExpansionSet set : Sets.getInstance().values()) {
+ if (set.getSetType().isStandardLegal() && (set.getReleaseDate().after(cutoff) || set.getReleaseDate().equals(cutoff))) {
+ setCodes.add(set.getCode());
+ setCodes.add(mage.sets.HistoricAnthology1.getInstance().getCode());
+ setCodes.add(mage.sets.HistoricAnthology2.getInstance().getCode());
+ setCodes.add(mage.sets.HistoricAnthology3.getInstance().getCode());
+ singleCards.add("Rhys the Redeemed");
+ singleCards.add("Spiritual Guardian");
+ singleCards.add("Sanctuary Cat");
+ singleCards.add("Raging Goblin");
+ singleCards.add("Hanna, Ship's Navigator");
+ singleCards.add("Angelic Reward");
+ singleCards.add("Confront the Assault");
+ singleCards.add("Inspiring Commander");
+ singleCards.add("Shrine Keeper");
+ singleCards.add("Tactical Advantage");
+ singleCards.add("River's Favor");
+ singleCards.add("Shorecomber Crab");
+ singleCards.add("Zephyr Gull");
+ singleCards.add("Feral Roar");
+ singleCards.add("Treetop Warden");
+ singleCards.add("Angler Turtle");
+ singleCards.add("Vengeant Vampire");
+ singleCards.add("Rampaging Brontodon");
+ singleCards.add("Bladewing the Risen");
+ singleCards.add("The Gitrog Monster");
+ singleCards.add("Talrand, Sky Summoner");
+ }
+ }
+ banned.add("Fires of Invention");
+ banned.add("Agent of Treachery");
+ banned.add("Winota, Joiner of Forces");
+ banned.add("Nexus of Fate");
+ banned.add("Oko, Thief of Crowns");
+ banned.add("Once Upon a Time");
+ banned.add("Veil of Summer");
+ }
+}
diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml
index 64e7c995cbf..ceb13e9ece0 100644
--- a/Mage.Server/config/config.xml
+++ b/Mage.Server/config/config.xml
@@ -163,6 +163,7 @@
+
diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml
index 71c8638c23f..d8950d71a06 100644
--- a/Mage.Server/release/config/config.xml
+++ b/Mage.Server/release/config/config.xml
@@ -157,6 +157,7 @@
+
diff --git a/Mage.Sets/src/mage/sets/HistoricAnthology1.java b/Mage.Sets/src/mage/sets/HistoricAnthology1.java
new file mode 100644
index 00000000000..36e6dc8c9e4
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/HistoricAnthology1.java
@@ -0,0 +1,49 @@
+
+package mage.sets;
+
+import mage.cards.ExpansionSet;
+import mage.constants.Rarity;
+import mage.constants.SetType;
+
+/**
+ * @author mikalinn777
+ */
+public final class HistoricAnthology1 extends ExpansionSet {
+
+ private static final HistoricAnthology1 instance = new HistoricAnthology1();
+
+ public static HistoricAnthology1 getInstance() {
+ return instance;
+ }
+
+ private HistoricAnthology1() {
+ super("Historic Anthology 1", "HA1", ExpansionSet.buildDate(2019, 11, 21), SetType.SUPPLEMENTAL);
+ this.blockName = "Reprint";
+ this.hasBoosters = false;
+ this.hasBasicLands = false;
+ cards.add(new SetCardInfo("Burning Tree Emissary", 16, Rarity.UNCOMMON, mage.cards.b.BurningTreeEmissary.class));
+ cards.add(new SetCardInfo("Captain Sisay", 17, Rarity.RARE, mage.cards.c.CaptainSisay.class));
+ cards.add(new SetCardInfo("Cryptbreaker", 6, Rarity.RARE, mage.cards.c.Cryptbreaker.class));
+ cards.add(new SetCardInfo("Darksteel Reactor", 20, Rarity.RARE, mage.cards.d.DarksteelReactor.class));
+ cards.add(new SetCardInfo("Distant Melody", 5, Rarity.COMMON, mage.cards.d.DistantMelody.class));
+ cards.add(new SetCardInfo("Elvish Visionary", 13, Rarity.COMMON, mage.cards.e.ElvishVisionary.class));
+ cards.add(new SetCardInfo("Fauna Shaman", 14, Rarity.RARE, mage.cards.f.FaunaShaman.class));
+ cards.add(new SetCardInfo("Goblin Matron", 11, Rarity.UNCOMMON, mage.cards.g.GoblinMatron.class));
+ cards.add(new SetCardInfo("Hidetsugu's Second Rite", 12, Rarity.RARE, mage.cards.h.HidetsugusSecondRite.class));
+ cards.add(new SetCardInfo("Hypnotic Specter", 7, Rarity.RARE, mage.cards.h.HypnoticSpecter.class));
+ cards.add(new SetCardInfo("Imperious Perfect", 15, Rarity.UNCOMMON, mage.cards.i.ImperiousPerfect.class));
+ cards.add(new SetCardInfo("Kiln Fiend", 10, Rarity.COMMON, mage.cards.k.KilnFiend.class));
+ cards.add(new SetCardInfo("Kinsbaile Cavalier", 3, Rarity.COMMON, mage.cards.k.KinsbaileCavalier.class));
+ cards.add(new SetCardInfo("Mind Stone", 19, Rarity.COMMON, mage.cards.m.MindStone.class));
+ cards.add(new SetCardInfo("Ornithopter", 18, Rarity.UNCOMMON, mage.cards.o.Ornithopter.class));
+ cards.add(new SetCardInfo("Phrexian Arena", 8, Rarity.RARE, mage.cards.p.PhyrexianArena.class));
+ cards.add(new SetCardInfo("Serra Ascendant", 1, Rarity.RARE, mage.cards.s.SerraAscendant.class));
+ cards.add(new SetCardInfo("Soul Warden", 2, Rarity.COMMON, mage.cards.s.SoulWarden.class));
+ cards.add(new SetCardInfo("Swan Song", 55, Rarity.RARE, mage.cards.s.SwanSong.class));
+ cards.add(new SetCardInfo("Tendrils of Corruption", 9, Rarity.COMMON, mage.cards.t.TendrilsOfCorruption.class));
+ cards.add(new SetCardInfo("Treasure Hunt", 4, Rarity.COMMON, mage.cards.t.TreasureHunt.class));
+
+
+ }
+
+}
diff --git a/Mage.Sets/src/mage/sets/HistoricAnthology2.java b/Mage.Sets/src/mage/sets/HistoricAnthology2.java
new file mode 100644
index 00000000000..812b318e74f
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/HistoricAnthology2.java
@@ -0,0 +1,53 @@
+
+package mage.sets;
+
+import mage.cards.ExpansionSet;
+import mage.constants.Rarity;
+import mage.constants.SetType;
+
+/**
+ * @author mikalinn777
+ */
+public final class HistoricAnthology2 extends ExpansionSet {
+
+ private static final HistoricAnthology2 instance = new HistoricAnthology2();
+
+ public static HistoricAnthology2 getInstance() {
+ return instance;
+ }
+
+ private HistoricAnthology2() {
+ super("Historic Anthology 2", "HA2", ExpansionSet.buildDate(2020, 3, 12), SetType.SUPPLEMENTAL);
+ this.blockName = "Reprint";
+ this.hasBoosters = false;
+ this.hasBasicLands = false;
+ cards.add(new SetCardInfo("Ancestral Mask", 13, Rarity.COMMON, mage.cards.a.AncestralMask.class));
+ cards.add(new SetCardInfo("Barren Moor", 19, Rarity.COMMON, mage.cards.b.BarrenMoor.class));
+ cards.add(new SetCardInfo("Bojuka Bog", 20, Rarity.COMMON, mage.cards.b.BojukaBog.class));
+ cards.add(new SetCardInfo("Brain Maggot", 7, Rarity.UNCOMMON, mage.cards.b.BrainMaggot.class));
+ cards.add(new SetCardInfo("Dragonmaster Outcast", 11, Rarity.COMMON, mage.cards.d.DragonmasterOutcast.class));
+ cards.add(new SetCardInfo("Forgotten Cave", 21, Rarity.COMMON, mage.cards.f.ForgottenCave.class));
+ cards.add(new SetCardInfo("Ghost Quarter", 22, Rarity.UNCOMMON, mage.cards.g.GhostQuarter.class));
+ cards.add(new SetCardInfo("Goblin Ruinblaster", 12, Rarity.UNCOMMON, mage.cards.g.GoblinRuinblaster.class));
+ cards.add(new SetCardInfo("Inexorable Tide", 6, Rarity.RARE, mage.cards.i.InexorableTide.class));
+ cards.add(new SetCardInfo("Knight of the Reliquary", 15, Rarity.RARE, mage.cards.k.KnightOfTheReliquary.class));
+ cards.add(new SetCardInfo("Lonely Sandbar", 23, Rarity.COMMON, mage.cards.l.LonelySandbar.class));
+ cards.add(new SetCardInfo("Maelstrom Pulse", 16, Rarity.RARE, mage.cards.m.MaelstromPulse.class));
+ cards.add(new SetCardInfo("Meddling Mage", 17, Rarity.RARE, mage.cards.m.MeddlingMage.class));
+ cards.add(new SetCardInfo("Merrow Reejerey", 5, Rarity.UNCOMMON, mage.cards.m.MerrowReejerey.class));
+ cards.add(new SetCardInfo("Nyxfleece Ram", 1, Rarity.UNCOMMON, mage.cards.n.NyxFleeceRam.class));
+ cards.add(new SetCardInfo("Pack Rat", 8, Rarity.RARE, mage.cards.p.PackRat.class));
+ cards.add(new SetCardInfo("Platinum Angel", 18, Rarity.MYTHIC, mage.cards.p.PlatinumAngel.class));
+ cards.add(new SetCardInfo("Ranger of Eos", 2, Rarity.RARE, mage.cards.r.RangerOfEos.class));
+ cards.add(new SetCardInfo("Secluded Steppe", 24, Rarity.COMMON, mage.cards.s.SecludedSteppe.class));
+ cards.add(new SetCardInfo("Sigil of the Empty Throne", 3, Rarity.RARE, mage.cards.s.SigilOfTheEmptyThrone.class));
+ cards.add(new SetCardInfo("Terravore", 14, Rarity.RARE, mage.cards.t.Terravore.class));
+ cards.add(new SetCardInfo("Thalia, Guardian of Thraben", 4, Rarity.RARE, mage.cards.t.ThaliaGuardianOfThraben.class));
+ cards.add(new SetCardInfo("Tranquil Thicket", 25, Rarity.COMMON, mage.cards.t.TranquilThicket.class));
+ cards.add(new SetCardInfo("Virulent Plague", 9, Rarity.UNCOMMON, mage.cards.v.VirulentPlague.class));
+ cards.add(new SetCardInfo("Waste Not", 10, Rarity.RARE, mage.cards.w.WasteNot.class));
+
+
+ }
+
+}
diff --git a/Mage.Sets/src/mage/sets/HistoricAnthology3.java b/Mage.Sets/src/mage/sets/HistoricAnthology3.java
new file mode 100644
index 00000000000..5aa7c331d53
--- /dev/null
+++ b/Mage.Sets/src/mage/sets/HistoricAnthology3.java
@@ -0,0 +1,55 @@
+
+package mage.sets;
+
+import mage.cards.ExpansionSet;
+import mage.constants.Rarity;
+import mage.constants.SetType;
+
+/**
+ * @author mikalinn777
+ */
+public final class HistoricAnthology3 extends ExpansionSet {
+
+ private static final HistoricAnthology3 instance = new HistoricAnthology3();
+
+ public static HistoricAnthology3 getInstance() {
+ return instance;
+ }
+
+ private HistoricAnthology3() {
+ super("Historic Anthology 3", "HA3", ExpansionSet.buildDate(2020, 5, 21), SetType.SUPPLEMENTAL);
+ this.blockName = "Reprint";
+ this.hasBoosters = false;
+ this.hasBasicLands = false;
+ cards.add(new SetCardInfo("Ancient Ziggurat", 26, Rarity.UNCOMMON, mage.cards.a.AncientZiggurat.class));
+ cards.add(new SetCardInfo("Akroma's Memorial", 24, Rarity.MYTHIC, mage.cards.a.AkromasMemorial.class));
+ cards.add(new SetCardInfo("Body Double", 6, Rarity.RARE, mage.cards.b.BodyDouble.class));
+ cards.add(new SetCardInfo("Chainer's Edict", 10, Rarity.UNCOMMON, mage.cards.c.ChainersEdict.class));
+ cards.add(new SetCardInfo("Devil's Play", 15, Rarity.RARE, mage.cards.d.DevilsPlay.class));
+ cards.add(new SetCardInfo("Enchantress's Presence", 19, Rarity.RARE, mage.cards.e.EnchantresssPresence.class));
+ cards.add(new SetCardInfo("Gempalm Incinerator", 16, Rarity.UNCOMMON, mage.cards.g.GempalmIncinerator.class));
+ cards.add(new SetCardInfo("Gempalm Polluter", 11, Rarity.COMMON, mage.cards.g.GempalmPolluter.class));
+ cards.add(new SetCardInfo("Honden of Cleansing Fire", 2, Rarity.UNCOMMON, mage.cards.h.HondenOfCleansingFire.class));
+ cards.add(new SetCardInfo("Honden of Infinite Rage", 17, Rarity.UNCOMMON, mage.cards.h.HondenOfInfiniteRage.class));
+ cards.add(new SetCardInfo("Honden of Life's Web", 20, Rarity.UNCOMMON, mage.cards.h.HondenOfLifesWeb.class));
+ cards.add(new SetCardInfo("Honden of Night's Reach", 12, Rarity.UNCOMMON, mage.cards.h.HondenOfNightsReach.class));
+ cards.add(new SetCardInfo("Honden of Seeing Winds", 7, Rarity.UNCOMMON, mage.cards.h.HondenOfSeeingWinds.class));
+ cards.add(new SetCardInfo("Krosan Tusker", 21, Rarity.COMMON, mage.cards.k.KrosanTusker.class));
+ cards.add(new SetCardInfo("Maze's End", 27, Rarity.MYTHIC, mage.cards.m.MazesEnd.class));
+ cards.add(new SetCardInfo("Mirari's Wake", 23, Rarity.RARE, mage.cards.m.MirarisWake.class));
+ cards.add(new SetCardInfo("Momentary Blink", 3, Rarity.COMMON, mage.cards.m.MomentaryBlink.class));
+ cards.add(new SetCardInfo("Phyrexian Obliterator", 13, Rarity.MYTHIC, mage.cards.p.PhyrexianObliterator.class));
+ cards.add(new SetCardInfo("Ratchet Bomb", 25, Rarity.RARE, mage.cards.r.RatchetBomb.class));
+ cards.add(new SetCardInfo("Roar of the Wurm", 22, Rarity.UNCOMMON, mage.cards.r.RoarOfTheWurm.class));
+ cards.add(new SetCardInfo("Silent Departure", 8, Rarity.COMMON, mage.cards.s.SilentDeparture.class));
+ cards.add(new SetCardInfo("Swan Song", 9, Rarity.RARE, mage.cards.s.SwanSong.class));
+ cards.add(new SetCardInfo("Tectonic Reformation", 18, Rarity.RARE, mage.cards.t.TectonicReformation.class));
+ cards.add(new SetCardInfo("Tempered Steel", 4, Rarity.RARE, mage.cards.t.TemperedSteel.class));
+ cards.add(new SetCardInfo("Timely Reinforcements", 5, Rarity.UNCOMMON, mage.cards.t.TimelyReinforcements.class));
+ cards.add(new SetCardInfo("Ulamog, the Ceaseless Hunger", 1, Rarity.MYTHIC, mage.cards.u.UlamogTheCeaselessHunger.class));
+ cards.add(new SetCardInfo("Unburial Rites", 14, Rarity.UNCOMMON, mage.cards.u.UnburialRites.class));
+
+
+ }
+
+}
diff --git a/Mage/src/main/java/mage/cards/decks/Constructed.java b/Mage/src/main/java/mage/cards/decks/Constructed.java
index 7213b6b718c..84e3ea2f910 100644
--- a/Mage/src/main/java/mage/cards/decks/Constructed.java
+++ b/Mage/src/main/java/mage/cards/decks/Constructed.java
@@ -197,4 +197,4 @@ public class Constructed extends DeckValidator {
}
return valid;
}
-}
+}
\ No newline at end of file