Add Freeform Unlimited Commander game type

Currently there's no multiplayer format that allows players to cast
spells from the command zone and also allows any deck size.

This is a problem for players who want to test EDH Cube decks. These
decks:
- can have any size - often between 40 and 100 - with no standard
- can have cards outside the commander's color identity
- may break the singleton rule

Create a game and deck type to accommodate these types of decks.

Notable differences from Freeform Commander in addition to the above:
- Decks can have any number of cards in the maindeck or sideboard
- Sideboard cards can be any type
- There are no illegal expansions
- Games can have a minimum 2 players
This commit is contained in:
michaelrfarcasin 2020-01-20 22:47:27 -06:00
parent 217517feee
commit c3cb54f371
15 changed files with 426 additions and 1 deletions

View file

@ -650,6 +650,12 @@ public class NewTableDialog extends MageDialog {
return false;
}
break;
case "Variant Magic - Freeform Unlimited Commander":
if (!options.getGameType().startsWith("Freeform Unlimited Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Freeform+ Commander needs also a Freeform Unlimited Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
return false;
}
break;
case "Variant Magic - Brawl":
case "Variant Magic - Duel Brawl":
if (!options.getGameType().startsWith("Brawl")) {
@ -698,6 +704,12 @@ public class NewTableDialog extends MageDialog {
return false;
}
break;
case "Freeform Unlimited Commander":
if (!options.getDeckType().equals("Variant Magic - Freeform Unlimited Commander")) {
JOptionPane.showMessageDialog(MageFrame.getDesktop(), "Deck type Freeform Unlimited Commander needs also a Freeform Unlimited Commander game type", "Error", JOptionPane.ERROR_MESSAGE);
return false;
}
break;
case "Brawl Two Player Duel":
case "Brawl Free For All":
if (!options.getDeckType().equals("Variant Magic - Brawl")

View file

@ -818,7 +818,7 @@ public class TablesPanel extends javax.swing.JPanel {
formatFilterList.add(RowFilter.regexFilter("^Constructed - Premodern", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatCommander.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Centurion Commander|^Penny Dreadful Commander|^Freeform Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE));
formatFilterList.add(RowFilter.regexFilter("^Commander|^Duel Commander|^Centurion Commander|^Penny Dreadful Commander|^Freeform Commander|^Freeform Unlimited Commander|^MTGO 1v1 Commander|^Duel Brawl|^Brawl", TablesTableModel.COLUMN_DECK_TYPE));
}
if (btnFormatTinyLeader.isSelected()) {
formatFilterList.add(RowFilter.regexFilter("^Tiny", TablesTableModel.COLUMN_DECK_TYPE));

View file

@ -0,0 +1,37 @@
package mage.deck;
import mage.cards.ExpansionSet;
import mage.cards.Sets;
import mage.cards.decks.Deck;
public class FreeformUnlimitedCommander extends FreeformCommander {
public FreeformUnlimitedCommander() {
this("Freeform Unlimited Commander");
}
public FreeformUnlimitedCommander(String name) {
super(name);
for (ExpansionSet set : Sets.getInstance().values()) {
setCodes.add(set.getCode());
}
// no banned cards
this.banned.clear();
}
@Override
public int getDeckMinSize() {
return 0;
}
@Override
public int getSideboardMinSize() {
return 0;
}
@Override
public boolean validate(Deck deck) {
return true;
}
}

View file

@ -0,0 +1,61 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.mage</groupId>
<artifactId>mage-server-plugins</artifactId>
<version>1.4.42</version>
</parent>
<artifactId>mage-game-freeformunlimitedcommander</artifactId>
<packaging>jar</packaging>
<name>Mage Game Freeform Unlimited Commander</name>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.mage</groupId>
<artifactId>mage-game-freeformunlimitedcommander</artifactId>
<version>1.4.42</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mage</groupId>
<artifactId>mage-game-freeformcommanderfreeforall</artifactId>
<version>1.4.42</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<finalName>mage-game-freeformunlimitedcommander</finalName>
</build>
<properties/>
</project>

View file

@ -0,0 +1,19 @@
package mage.game;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.mulligan.Mulligan;
public class FreeformUnlimitedCommander extends FreeformCommanderFreeForAll {
protected int numPlayers;
public FreeformUnlimitedCommander(MultiplayerAttackOption attackOption, RangeOfInfluence range, Mulligan mulligan, int startLife) {
super(attackOption, range, mulligan, startLife);
}
public FreeformUnlimitedCommander(final FreeformUnlimitedCommander game) {
super(game);
this.numPlayers = game.numPlayers;
}
}

View file

@ -0,0 +1,10 @@
package mage.game;
import mage.game.match.MatchOptions;
public class FreeformUnlimitedCommanderMatch extends FreeformCommanderFreeForAllMatch {
public FreeformUnlimitedCommanderMatch(MatchOptions options) {
super(options);
}
}

View file

@ -0,0 +1,24 @@
package mage.game;
public class FreeformUnlimitedCommanderType extends FreeformCommanderFreeForAllType {
public FreeformUnlimitedCommanderType() {
this.name = "Freeform Unlimited Commander";
this.maxPlayers = 10;
this.minPlayers = 2;
this.numTeams = 0;
this.playersPerTeam = 0;
this.useAttackOption = true;
this.useRange = true;
this.sideboardingAllowed = false;
}
protected FreeformUnlimitedCommanderType(final FreeformUnlimitedCommanderType matchType) {
super(matchType);
}
@Override
public FreeformUnlimitedCommanderType copy() {
return new FreeformUnlimitedCommanderType(this);
}
}

View file

@ -28,6 +28,7 @@
<module>Mage.Game.PennyDreadfulCommanderFreeForAll</module>
<module>Mage.Game.FreeformCommanderDuel</module>
<module>Mage.Game.FreeformCommanderFreeForAll</module>
<module>Mage.Game.FreeformUnlimitedCommander</module>
<module>Mage.Game.BrawlDuel</module>
<module>Mage.Game.BrawlFreeForAll</module>
<module>Mage.Game.OathbreakerDuel</module>

View file

@ -81,6 +81,7 @@
<gameType name="Penny Dreadful Commander Free For All" jar="mage-game-pennydreadfulcommanderfreeforall.jar" className="mage.game.PennyDreadfulCommanderFreeForAllMatch" typeName="mage.game.PennyDreadfulCommanderFreeForAllType"/>
<gameType name="Freeform Commander Two Player Duel" jar="mage-game-freeformcommanderduel.jar" className="mage.game.FreeformCommanderDuelMatch" typeName="mage.game.FreeformCommanderDuelType"/>
<gameType name="Freeform Commander Free For All" jar="mage-game-freeformcommanderfreeforall.jar" className="mage.game.FreeformCommanderFreeForAllMatch" typeName="mage.game.FreeformCommanderFreeForAllType"/>
<gameType name="Freeform Unlimited Commander" jar="mage-game-freeformunlimitedcommander.jar" className="mage.game.FreeformUnlimitedCommanderMatch" typeName="mage.game.FreeformUnlimitedCommanderType"/>
<gameType name="Oathbreaker Two Player Duel" jar="mage-game-oathbreakerduel.jar" className="mage.game.OathbreakerDuelMatch" typeName="mage.game.OathbreakerDuelType"/>
<gameType name="Oathbreaker Free For All" jar="mage-game-oathbreakerfreeforall.jar" className="mage.game.OathbreakerFreeForAllMatch" typeName="mage.game.OathbreakerFreeForAllType"/>
<gameType name="Brawl Two Player Duel" jar="mage-game-brawlduel.jar" className="mage.game.BrawlDuelMatch" typeName="mage.game.BrawlDuelType"/>
@ -176,6 +177,7 @@
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed.jar" className="mage.deck.Momir"/>
<deckType name="Variant Magic - Penny Dreadful Commander" jar="mage-deck-constructed.jar" className="mage.deck.PennyDreadfulCommander"/>
<deckType name="Variant Magic - Freeform Commander" jar="mage-deck-constructed.jar" className="mage.deck.FreeformCommander"/>
<deckType name="Variant Magic - Freeform Unlimited Commander" jar="mage-deck-constructed.jar" className="mage.deck.FreeformUnlimitedCommander"/>
<deckType name="Variant Magic - Brawl" jar="mage-deck-constructed.jar" className="mage.deck.Brawl"/>
<deckType name="Variant Magic - Oathbreaker" jar="mage-deck-constructed.jar" className="mage.deck.Oathbreaker"/>
<deckType name="Block Constructed - Amonkhet" jar="mage-deck-constructed.jar" className="mage.deck.AmonkhetBlock"/>

View file

@ -191,6 +191,12 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-freeformunlimitedcommander</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-game-freeformcommanderduel</artifactId>

View file

@ -75,6 +75,7 @@
<gameType name="Penny Dreadful Commander Free For All" jar="mage-game-pennydreadfulcommanderfreeforall-${project.version}.jar" className="mage.game.PennyDreadfulCommanderFreeForAllMatch" typeName="mage.game.PennyDreadfulCommanderFreeForAllType"/>
<gameType name="Freeform Commander Two Player Duel" jar="mage-game-freeformcommanderduel-${project.version}.jar" className="mage.game.FreeformCommanderDuelMatch" typeName="mage.game.FreeformCommanderDuelType"/>
<gameType name="Freeform Commander Free For All" jar="mage-game-freeformcommanderfreeforall-${project.version}.jar" className="mage.game.FreeformCommanderFreeForAllMatch" typeName="mage.game.FreeformCommanderFreeForAllType"/>
<gameType name="Freeform Unlimited Commander" jar="mage-game-freeformunlimitedcommander-${project.version}.jar" className="mage.game.FreeformUnlimitedCommanderMatch" typeName="mage.game.FreeformUnlimitedCommanderType"/>
<gameType name="Oathbreaker Two Player Duel" jar="mage-game-oathbreakerduel-${project.version}.jar" className="mage.game.OathbreakerDuelMatch" typeName="mage.game.OathbreakerDuelType"/>
<gameType name="Oathbreaker Free For All" jar="mage-game-oathbreakerfreeforall-${project.version}.jar" className="mage.game.OathbreakerFreeForAllMatch" typeName="mage.game.OathbreakerFreeForAllType"/>
<gameType name="Brawl Two Player Duel" jar="mage-game-brawlduel-${project.version}.jar" className="mage.game.BrawlDuelMatch" typeName="mage.game.BrawlDuelType"/>
@ -170,6 +171,7 @@
<deckType name="Variant Magic - Momir Basic" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Momir"/>
<deckType name="Variant Magic - Penny Dreadful Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.PennyDreadfulCommander"/>
<deckType name="Variant Magic - Freeform Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.FreeformCommander"/>
<deckType name="Variant Magic - Freeform Unlimited Commander" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.FreeformUnlimitedCommander"/>
<deckType name="Variant Magic - Brawl" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Brawl"/>
<deckType name="Variant Magic - Oathbreaker" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.Oathbreaker"/>
<deckType name="Block Constructed - Amonkhet" jar="mage-deck-constructed-${project.version}.jar" className="mage.deck.AmonkhetBlock"/>

View file

@ -0,0 +1,56 @@
package org.mage.test.deck;
import mage.cards.decks.Deck;
import mage.deck.FreeformUnlimitedCommander;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.MageTestPlayerBase;
public class FreeformUnlimitedCommanderTest extends MageTestPlayerBase {
@Test
public void test_construct_returnsFreeformPlusCommander() {
// Act
FreeformUnlimitedCommander deck = new FreeformUnlimitedCommander();
// Assert
Assert.assertEquals(FreeformUnlimitedCommander.class, deck.getClass());
}
@Test
public void test_getDeckMinSize_returns0() {
// Arrange
FreeformUnlimitedCommander deck = new FreeformUnlimitedCommander();
// Act
int actual = deck.getDeckMinSize();
// Assert
Assert.assertEquals(0, actual);
}
@Test
public void test_getSideboardMinSize_returns0() {
// Arrange
FreeformUnlimitedCommander deck = new FreeformUnlimitedCommander();
// Act
int actual = deck.getSideboardMinSize();
// Assert
Assert.assertEquals(0, actual);
}
@Test
public void test_validate_returnsTrue() {
// Arrange
FreeformUnlimitedCommander deck = new FreeformUnlimitedCommander();
Deck example = new Deck();
// Act
boolean actual = deck.validate(example);
// Assert
Assert.assertTrue(actual);
}
}

View file

@ -0,0 +1,64 @@
package org.mage.test.game.FreeformUnlimitedCommander;
import mage.game.FreeformUnlimitedCommanderMatch;
import mage.game.match.Match;
import mage.game.match.MatchOptions;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.MageTestPlayerBase;
public class FreeformUnlimitedCommanderMatchTest extends MageTestPlayerBase {
@Test
public void test_construct_returnsFreeformPlusCommanderMatch() {
// Arrange
MatchOptions options = new MatchOptions(
"test name",
"test match name",
false,
2
);
// Act
Match match = new FreeformUnlimitedCommanderMatch(options);
// Assert
Assert.assertEquals(FreeformUnlimitedCommanderMatch.class, match.getClass());
}
@Test
public void test_getName_returnsTestName() {
// Arrange
MatchOptions options = new MatchOptions(
"test name",
"test match name",
false,
2
);
Match match = new FreeformUnlimitedCommanderMatch(options);
// Act
String actual = match.getName();
// Assert
Assert.assertEquals("test name", actual);
}
@Test
public void test_getOptions_returnsOriginalOptions() {
// Arrange
MatchOptions options = new MatchOptions(
"test name",
"test match name",
false,
2
);
Match match = new FreeformUnlimitedCommanderMatch(options);
// Act
MatchOptions actual = match.getOptions();
// Assert
Assert.assertEquals(options, actual);
}
}

View file

@ -0,0 +1,31 @@
package org.mage.test.game.FreeformUnlimitedCommander;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.FreeformUnlimitedCommander;
import mage.game.mulligan.LondonMulligan;
import mage.game.mulligan.Mulligan;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.MageTestPlayerBase;
public class FreeformUnlimitedCommanderTest extends MageTestPlayerBase {
@Test
public void test_construct_returnsFreeformPlusCommander() {
// Arrange
Mulligan mulligan = new LondonMulligan(1);
int startLife = 40;
// Assert
FreeformUnlimitedCommander game = new FreeformUnlimitedCommander(
MultiplayerAttackOption.MULTIPLE,
RangeOfInfluence.ALL,
mulligan,
startLife
);
// Assert
Assert.assertEquals(FreeformUnlimitedCommander.class, game.getClass());
}
}

View file

@ -0,0 +1,100 @@
package org.mage.test.game.FreeformUnlimitedCommander;
import mage.game.FreeformUnlimitedCommanderType;
import mage.game.match.MatchType;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.MageTestPlayerBase;
public class FreeformUnlimitedCommanderTypeTest extends MageTestPlayerBase {
@Test
public void test_construct_returnsFreeformPlusCommanderType() {
// Act
MatchType gameType = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertEquals(FreeformUnlimitedCommanderType.class, gameType.getClass());
}
@Test
public void test_toString_returnsFreeformPlusCommander() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertEquals("Freeform Unlimited Commander", gametype.toString());
}
@Test
public void test_getName_returnsFreeformPlusCommander() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertEquals("Freeform Unlimited Commander", gametype.getName());
}
@Test
public void test_getMinPlayers_returns3() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertEquals(2, gametype.getMinPlayers());
}
@Test
public void test_getMaxPlayers_returns10() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertEquals(10, gametype.getMaxPlayers());
}
@Test
public void test_getNumTeams_returns0() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertEquals(0, gametype.getNumTeams());
}
@Test
public void test_getPlayersPerTeam_returns0() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertEquals(0, gametype.getPlayersPerTeam());
}
@Test
public void test_isUseRange_returnsTrue() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertTrue(gametype.isUseRange());
}
@Test
public void test_isUseAttackOption_returnsTrue() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertTrue(gametype.isUseAttackOption());
}
@Test
public void test_isSideboardingAllowed_returnsFalse() {
// Arrange
MatchType gametype = new FreeformUnlimitedCommanderType();
// Assert
Assert.assertFalse(gametype.isSideboardingAllowed());
}
}