mirror of
https://github.com/correl/mage.git
synced 2024-12-26 03:00:11 +00:00
commit
738c11a0e3
64 changed files with 751 additions and 261 deletions
|
@ -378,7 +378,7 @@ public class NewTableDialog extends MageDialog {
|
|||
|
||||
private void btnOKActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOKActionPerformed
|
||||
GameTypeView gameType = (GameTypeView) cbGameType.getSelectedItem();
|
||||
MatchOptions options = new MatchOptions(this.txtName.getText(), gameType.getName());
|
||||
MatchOptions options = new MatchOptions(this.txtName.getText(), gameType.getName(), false, 2);
|
||||
options.getPlayerTypes().add("Human");
|
||||
for (TablePlayerPanel player : players) {
|
||||
options.getPlayerTypes().add(player.getPlayerType());
|
||||
|
|
|
@ -29,11 +29,8 @@
|
|||
<Component id="pnlPacks" alignment="1" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lblNbrPlayers" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="spnNumPlayers" min="-2" pref="46" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0"> <Component id="lblNbrPlayers" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> <Component id="spnNumPlayers" min="-2" pref="46" max="-2" attributes="0"/> </Group>
|
||||
<Group type="102" alignment="0" attributes="0"> <Component id="lblNbrSeats" min="-2" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/> <Component id="spnNumSeats" min="-2" pref="46" max="-2" attributes="0"/> </Group>
|
||||
<Component id="lblPacks" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lblPlayer1" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -175,6 +172,7 @@
|
|||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblPacks" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="pnlPacks" min="-2" max="-2" attributes="0"/>
|
||||
|
@ -192,6 +190,11 @@
|
|||
<Component id="pnlDraftOptions" alignment="1" pref="0" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="lblNbrSeats" alignment="1" max="32767" attributes="0"/>
|
||||
<Component id="spnNumSeats" alignment="1" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lblPlayer1" min="-2" pref="25" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
|
@ -200,6 +203,7 @@
|
|||
<Component id="chkRollbackTurnsAllowed" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="player1Panel" min="-2" pref="62" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
|
@ -377,15 +381,17 @@
|
|||
<Property name="rows" type="int" value="0"/>
|
||||
</Layout>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="lblNbrPlayers">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" value="Players:"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lblNbrPlayers"> <Properties> <Property name="text" type="java.lang.String" value="Players:"/> </Properties> </Component>
|
||||
<Component class="javax.swing.JLabel" name="lblNbrSeats"> <Properties> <Property name="text" type="java.lang.String" value="Seats:"/> </Properties> </Component>
|
||||
<Component class="javax.swing.JSpinner" name="spnNumPlayers">
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spnNumPlayersStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JSpinner" name="spnNumSeats">
|
||||
<Events>
|
||||
<EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spnNumSeatsStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Container class="javax.swing.JPanel" name="pnlDraftOptions">
|
||||
|
||||
|
|
|
@ -170,6 +170,8 @@ public class NewTournamentDialog extends MageDialog {
|
|||
pnlPacks = new javax.swing.JPanel();
|
||||
lblNbrPlayers = new javax.swing.JLabel();
|
||||
spnNumPlayers = new javax.swing.JSpinner();
|
||||
lblNbrSeats = new javax.swing.JLabel();
|
||||
spnNumSeats = new javax.swing.JSpinner();
|
||||
pnlDraftOptions = new javax.swing.JPanel();
|
||||
jLabel6 = new javax.swing.JLabel();
|
||||
cbDraftTiming = new javax.swing.JComboBox();
|
||||
|
@ -277,6 +279,14 @@ public class NewTournamentDialog extends MageDialog {
|
|||
}
|
||||
});
|
||||
|
||||
lblNbrSeats.setText("Seats:");
|
||||
|
||||
spnNumSeats.addChangeListener(new javax.swing.event.ChangeListener() {
|
||||
public void stateChanged(javax.swing.event.ChangeEvent evt) {
|
||||
spnNumSeatsStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
jLabel6.setText("Timing:");
|
||||
|
||||
cbDraftTiming.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));
|
||||
|
@ -358,6 +368,8 @@ public class NewTournamentDialog extends MageDialog {
|
|||
lblQuitRatio.setText("Allowed quit %:");
|
||||
|
||||
spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table");
|
||||
spnNumSeats.setToolTipText("The number of seats for each duel. If more than 2, will set number of wins to 1");
|
||||
spnNumPlayers.setToolTipText("The total number of players who will draft");
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
|
@ -373,7 +385,11 @@ public class NewTournamentDialog extends MageDialog {
|
|||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(lblNbrPlayers)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(spnNumPlayers, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblNbrSeats)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(spnNumSeats, javax.swing.GroupLayout.PREFERRED_SIZE, 46, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(lblPacks)
|
||||
.addComponent(lblPlayer1))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
|
@ -504,6 +520,8 @@ public class NewTournamentDialog extends MageDialog {
|
|||
.addComponent(lblNumRounds))
|
||||
.addComponent(lblNbrPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(spnNumPlayers)
|
||||
.addComponent(lblNbrSeats, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(spnNumSeats)
|
||||
.addComponent(pnlDraftOptions, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lblPlayer1, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
|
@ -533,7 +551,8 @@ public class NewTournamentDialog extends MageDialog {
|
|||
|
||||
private void btnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnOkActionPerformed
|
||||
TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem();
|
||||
TournamentOptions tOptions = new TournamentOptions(this.txtName.getText());
|
||||
int numSeats = (Integer)this.spnNumSeats.getValue();
|
||||
TournamentOptions tOptions = new TournamentOptions(this.txtName.getText(), "", numSeats);
|
||||
tOptions.setTournamentType(tournamentType.getName());
|
||||
tOptions.setPassword(txtPassword.getText());
|
||||
tOptions.getPlayerTypes().add("Human");
|
||||
|
@ -653,13 +672,51 @@ public class NewTournamentDialog extends MageDialog {
|
|||
this.hideDialog();
|
||||
}//GEN-LAST:event_btnCancelActionPerformed
|
||||
|
||||
private void updateNumSeats() {
|
||||
int numPlayers = (Integer)this.spnNumPlayers.getValue();
|
||||
int numSeats = (Integer)this.spnNumSeats.getValue();
|
||||
|
||||
if (numSeats > 2) {
|
||||
TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem();
|
||||
if (numSeats >= tournamentType.getMinPlayers()) {
|
||||
createPlayers(numSeats - 1);
|
||||
spnNumPlayers.setValue(numSeats);
|
||||
} else {
|
||||
numSeats = tournamentType.getMinPlayers();
|
||||
createPlayers(numSeats - 1);
|
||||
spnNumPlayers.setValue(numSeats);
|
||||
spnNumSeats.setValue(numSeats);
|
||||
}
|
||||
spnNumWins.setValue(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void spnNumPlayersStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spnNumPlayersStateChanged
|
||||
int numPlayers = (Integer)this.spnNumPlayers.getValue() - 1;
|
||||
createPlayers(numPlayers);
|
||||
int numPlayers = (Integer)this.spnNumPlayers.getValue();
|
||||
createPlayers(numPlayers - 1);
|
||||
int numSeats = (Integer)this.spnNumSeats.getValue();
|
||||
if (numSeats > 2 && numPlayers != numSeats) {
|
||||
updateNumSeats();
|
||||
}
|
||||
}//GEN-LAST:event_spnNumPlayersStateChanged
|
||||
|
||||
private void spnNumSeatsStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spnNumSeatsStateChanged
|
||||
int numSeats = (Integer)this.spnNumSeats.getValue();
|
||||
if (numSeats > 2) {
|
||||
this.spnNumPlayers.setEnabled(false);
|
||||
} else {
|
||||
this.spnNumPlayers.setEnabled(true);
|
||||
}
|
||||
updateNumSeats();
|
||||
}//GEN-LAST:event_spnNumSeatsStateChanged
|
||||
|
||||
|
||||
private void spnNumWinsnumPlayersChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spnNumWinsnumPlayersChanged
|
||||
// TODO add your handling code here:
|
||||
int numSeats = (Integer)this.spnNumSeats.getValue();
|
||||
int numWins = (Integer)this.spnNumSeats.getValue();
|
||||
if (numSeats > 2) {
|
||||
spnNumWins.setValue(1);
|
||||
}
|
||||
}//GEN-LAST:event_spnNumWinsnumPlayersChanged
|
||||
|
||||
private JFileChooser fcSelectDeck = null;
|
||||
|
@ -726,6 +783,8 @@ public class NewTournamentDialog extends MageDialog {
|
|||
this.spnNumPlayers.setEnabled(tournamentType.getMinPlayers() != tournamentType.getMaxPlayers());
|
||||
createPlayers((Integer) spnNumPlayers.getValue() - 1);
|
||||
|
||||
this.spnNumSeats.setModel(new SpinnerNumberModel(2, 2, tournamentType.getMaxPlayers(), 1));
|
||||
|
||||
if (tournamentType.isLimited()) {
|
||||
this.isRandom = tournamentType.isRandom();
|
||||
this.isRichMan = tournamentType.isRichMan();
|
||||
|
@ -914,6 +973,8 @@ public class NewTournamentDialog extends MageDialog {
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void drawPlayers() {
|
||||
this.pnlOtherPlayers.removeAll();
|
||||
for (TournamentPlayerPanel panel: players) {
|
||||
|
@ -1119,6 +1180,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
private javax.swing.JLabel lblGameType;
|
||||
private javax.swing.JLabel lblName;
|
||||
private javax.swing.JLabel lblNbrPlayers;
|
||||
private javax.swing.JLabel lblNbrSeats;
|
||||
private javax.swing.JLabel lblNumRounds;
|
||||
private javax.swing.JLabel lblNumWins;
|
||||
private javax.swing.JLabel lblPacks;
|
||||
|
@ -1135,6 +1197,7 @@ public class NewTournamentDialog extends MageDialog {
|
|||
private javax.swing.JSpinner spnConstructTime;
|
||||
private javax.swing.JSpinner spnFreeMulligans;
|
||||
private javax.swing.JSpinner spnNumPlayers;
|
||||
private javax.swing.JSpinner spnNumSeats;
|
||||
private javax.swing.JSpinner spnNumRounds;
|
||||
private javax.swing.JSpinner spnNumWins;
|
||||
private javax.swing.JSpinner spnQuitRatio;
|
||||
|
|
|
@ -1272,7 +1272,7 @@ public class TablesPanel extends javax.swing.JPanel {
|
|||
return;
|
||||
}
|
||||
|
||||
MatchOptions options = new MatchOptions("1", "Two Player Duel");
|
||||
MatchOptions options = new MatchOptions("1", "Two Player Duel", false, 2);
|
||||
options.getPlayerTypes().add("Human");
|
||||
options.getPlayerTypes().add("Computer - mad");
|
||||
options.setDeckType("Limited");
|
||||
|
|
|
@ -13,8 +13,6 @@ import javax.swing.JMenuItem;
|
|||
import javax.swing.JPopupMenu;
|
||||
import mage.client.MageFrame;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.sets.avacynrestored.GuiseOfFire;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.mage.card.arcane.CardRenderer;
|
||||
|
||||
/**
|
||||
|
@ -145,13 +143,11 @@ public class GUISizeHelper {
|
|||
otherZonesCardDimension = new Dimension(CARD_IMAGE_WIDTH * otherZonesCardSize / 42, CARD_IMAGE_HEIGHT * otherZonesCardSize / 42);
|
||||
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_FALLBACK, "false").equals("false")) {
|
||||
otherZonesCardVerticalOffset = CardRenderer.getCardTopHeight(otherZonesCardDimension.width);
|
||||
} else {
|
||||
if (otherZonesCardSize > 29) {
|
||||
} else if (otherZonesCardSize > 29) {
|
||||
otherZonesCardVerticalOffset = otherZonesCardDimension.height / 8;
|
||||
} else {
|
||||
otherZonesCardVerticalOffset = otherZonesCardDimension.height / 10;
|
||||
}
|
||||
}
|
||||
|
||||
int battlefieldCardMinSize = PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GUI_CARD_BATTLEFIELD_MIN_SIZE, 10);
|
||||
battlefieldCardMinDimension = new Dimension(CARD_IMAGE_WIDTH * battlefieldCardMinSize / 42, CARD_IMAGE_HEIGHT * battlefieldCardMinSize / 42);
|
||||
|
|
|
@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable<MageVersion> {
|
|||
public final static int MAGE_VERSION_MAJOR = 1;
|
||||
public final static int MAGE_VERSION_MINOR = 4;
|
||||
public final static int MAGE_VERSION_PATCH = 15;
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "v4";
|
||||
public final static String MAGE_VERSION_MINOR_PATCH = "v5";
|
||||
public final static String MAGE_VERSION_INFO = "";
|
||||
|
||||
private final int major;
|
||||
|
|
|
@ -30,7 +30,6 @@ package mage.view;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.ObjectColor;
|
||||
import mage.abilities.Mode;
|
||||
|
@ -55,7 +54,6 @@ import mage.game.stack.Spell;
|
|||
import mage.game.stack.StackAbility;
|
||||
import mage.target.Target;
|
||||
import mage.target.Targets;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
|
@ -323,7 +321,8 @@ public class CardView extends SimpleCardView {
|
|||
this.mageObjectType = MageObjectType.SPELL;
|
||||
Spell spell = (Spell) card;
|
||||
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
||||
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||
Mode mode = spellAbility.getModes().get(modeId);
|
||||
if (mode.getTargets().size() > 0) {
|
||||
setTargets(spellAbility.getTargets());
|
||||
}
|
||||
|
@ -331,7 +330,8 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
// show for modal spell, which mode was choosen
|
||||
if (spell.getSpellAbility().isModal()) {
|
||||
for (Mode mode : spell.getSpellAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spell.getSpellAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = spell.getSpellAbility().getModes().get(modeId);
|
||||
this.rules.add("<span color='green'><i>Chosen mode: " + mode.getEffects().getText(mode) + "</i></span>");
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ public class CardView extends SimpleCardView {
|
|||
this.mageObjectType = MageObjectType.PERMANENT;
|
||||
this.power = Integer.toString(object.getPower().getValue());
|
||||
this.toughness = Integer.toString(object.getToughness().getValue());
|
||||
this.loyalty = Integer.toString(((Permanent) object).getCounters((Game)null).getCount(CounterType.LOYALTY));
|
||||
this.loyalty = Integer.toString(((Permanent) object).getCounters((Game) null).getCount(CounterType.LOYALTY));
|
||||
} else {
|
||||
this.power = object.getPower().toString();
|
||||
this.toughness = object.getToughness().toString();
|
||||
|
@ -807,4 +807,3 @@ public class CardView extends SimpleCardView {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,8 @@ public class StackAbilityView extends CardView {
|
|||
|
||||
private void updateTargets(Game game, StackAbility ability) {
|
||||
List<String> names = new ArrayList<>();
|
||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||
Mode mode = ability.getModes().get(modeId);
|
||||
if (mode.getTargets().size() > 0) {
|
||||
setTargets(mode.getTargets());
|
||||
} else {
|
||||
|
@ -132,7 +133,8 @@ public class StackAbilityView extends CardView {
|
|||
// show for modal ability, which mode was choosen
|
||||
if (ability.isModal()) {
|
||||
Modes modes = ability.getModes();
|
||||
for (Mode mode : modes.getSelectedModes()) {
|
||||
for (UUID modeId : modes.getSelectedModes()) {
|
||||
Mode mode = modes.get(modeId);
|
||||
this.rules.add("<span color='green'><i>Chosen mode: " + mode.getEffects().getText(mode) + "</i></span>");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1516,7 +1516,8 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
//TODO: improve this;
|
||||
AvailableMode:
|
||||
for (Mode mode : modes.getAvailableModes(source, game)) {
|
||||
for (Mode selectedMode : modes.getSelectedModes()) {
|
||||
for (UUID selectedModeId : modes.getSelectedModes()) {
|
||||
Mode selectedMode = modes.get(selectedModeId);
|
||||
if (selectedMode.getId().equals(mode.getId())) {
|
||||
continue AvailableMode;
|
||||
}
|
||||
|
|
|
@ -1326,7 +1326,8 @@ public class HumanPlayer extends PlayerImpl {
|
|||
AvailableModes:
|
||||
for (Mode mode : modes.getAvailableModes(source, game)) {
|
||||
int timesSelected = 0;
|
||||
for (Mode selectedMode : modes.getSelectedModes()) {
|
||||
for (UUID selectedModeId : modes.getSelectedModes()) {
|
||||
Mode selectedMode = modes.get(selectedModeId);
|
||||
if (mode.getId().equals(selectedMode.getId())) {
|
||||
if (modes.isEachModeMoreThanOnce()) {
|
||||
timesSelected++;
|
||||
|
|
|
@ -43,6 +43,7 @@ import mage.game.events.TableEvent;
|
|||
import mage.game.match.Match;
|
||||
import mage.game.match.MatchOptions;
|
||||
import mage.game.result.ResultProtos.TourneyQuitStatus;
|
||||
import mage.game.tournament.MultiplayerRound;
|
||||
import mage.game.tournament.Tournament;
|
||||
import mage.game.tournament.TournamentPairing;
|
||||
import mage.game.tournament.TournamentPlayer;
|
||||
|
@ -114,6 +115,19 @@ public class TournamentController {
|
|||
startMatch(event.getPair(), event.getMatchOptions());
|
||||
}
|
||||
break;
|
||||
case START_MULTIPLAYER_MATCH:
|
||||
if (!isAbort()) {
|
||||
initTournament(); // set state
|
||||
MatchOptions matchOptions = event.getMatchOptions();
|
||||
if (matchOptions != null && event.getMultiplayerRound() != null) {
|
||||
for (TournamentPlayer player : event.getMultiplayerRound().getAllPlayers()) {
|
||||
matchOptions.getPlayerTypes().add(player.getPlayerType());
|
||||
}
|
||||
}
|
||||
|
||||
startMultiplayerMatch(event.getMultiplayerRound(), event.getMatchOptions());
|
||||
}
|
||||
break;
|
||||
case END:
|
||||
endTournament();
|
||||
break;
|
||||
|
@ -265,6 +279,31 @@ public class TournamentController {
|
|||
}
|
||||
}
|
||||
|
||||
private void startMultiplayerMatch(MultiplayerRound round, MatchOptions matchOptions) {
|
||||
try {
|
||||
TableManager tableManager = TableManager.getInstance();
|
||||
Table table = tableManager.createTable(GamesRoomManager.getInstance().getMainRoomId(), matchOptions);
|
||||
table.setTournamentSubTable(true);
|
||||
table.setTournament(tournament);
|
||||
table.setState(TableState.WAITING);
|
||||
|
||||
for (TournamentPlayer player : round.getAllPlayers()) {
|
||||
tableManager.addPlayer(getPlayerUserId(player.getPlayer().getId()), table.getId(), player.getPlayer(), player.getPlayerType(), player.getDeck());
|
||||
}
|
||||
table.setState(TableState.STARTING);
|
||||
tableManager.startTournamentSubMatch(null, table.getId());
|
||||
Match match = tableManager.getMatch(table.getId());
|
||||
match.setTableId(tableId);
|
||||
round.setMatch(match);
|
||||
round.setTableId(table.getId());
|
||||
for (TournamentPlayer player : round.getAllPlayers()) {
|
||||
player.setState(TournamentPlayerState.DUELING);
|
||||
}
|
||||
} catch (GameException ex) {
|
||||
logger.fatal("TournamentController startMatch error", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private void startDraft(Draft draft) {
|
||||
TableManager.getInstance().startDraft(tableId, draft);
|
||||
}
|
||||
|
|
|
@ -104,7 +104,8 @@ class ZadaHedronGrinderTriggeredAbility extends TriggeredAbilityImpl {
|
|||
if (isControlledInstantOrSorcery(spell)) {
|
||||
boolean targetsSource = false;
|
||||
for (Ability ability : spell.getSpellAbilities()) {
|
||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||
Mode mode = ability.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
if (!target.isNotTarget()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
|
@ -167,7 +168,8 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
|||
Target usedTarget = null;
|
||||
setUsedTarget:
|
||||
for (Ability ability : spell.getSpellAbilities()) {
|
||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||
Mode mode = ability.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
if (!target.isNotTarget() && target.getFirstTarget().equals(source.getSourceId())) {
|
||||
usedTarget = target.copy();
|
||||
|
@ -185,7 +187,8 @@ class ZadaHedronGrinderEffect extends OneShotEffect {
|
|||
Spell copy = spell.copySpell(source.getControllerId());
|
||||
game.getStack().push(copy);
|
||||
setTarget:
|
||||
for (Mode mode : copy.getSpellAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : copy.getSpellAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = copy.getSpellAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
if (target.getClass().equals(usedTarget.getClass())) {
|
||||
target.clearChosen(); // For targets with Max > 1 we need to clear before the text is comapred
|
||||
|
|
|
@ -83,7 +83,6 @@ public class GoblinArtisans extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
class GoblinArtisansEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterPermanent filter = new FilterPermanent("permanent named Goblin Artisans");
|
||||
|
@ -109,16 +108,17 @@ class GoblinArtisansEffect extends OneShotEffect {
|
|||
controller.drawCards(1, game);
|
||||
} else {
|
||||
List<Permanent> artifacts = game.getBattlefield().getActivePermanents(new FilterControlledArtifactPermanent(), source.getControllerId(), game);
|
||||
if (artifacts.isEmpty()){//Don't even bother if there is no artifact to 'counter'/sacrifice
|
||||
if (artifacts.isEmpty()) {//Don't even bother if there is no artifact to 'counter'/sacrifice
|
||||
return true;
|
||||
}
|
||||
|
||||
filter.add(Predicates.not(new PermanentIdPredicate(source.getSourceId())));
|
||||
//removed the activating instance of Artisans, btw, wasn't that filter declared as static final? How come I can do this here? :)
|
||||
List<Permanent> list = game.getBattlefield().getAllActivePermanents(filter, game);
|
||||
for (Permanent perm : list){ // should I limit below for a particular kind of ability? Going for the most general, it's unlikely there'll be any other artisans anyway, so not concerned about efficiency :p
|
||||
for (Ability abil : perm.getAbilities(game)){//below is copied from TargetsPermanentPredicate, but why only "selectedModes"? Shouldnt be more general as well?
|
||||
for (Mode mode : abil.getModes().getSelectedModes()){
|
||||
for (Permanent perm : list) { // should I limit below for a particular kind of ability? Going for the most general, it's unlikely there'll be any other artisans anyway, so not concerned about efficiency :p
|
||||
for (Ability abil : perm.getAbilities(game)) {//below is copied from TargetsPermanentPredicate, but why only "selectedModes"? Shouldnt be more general as well?
|
||||
for (UUID modeId : abil.getModes().getSelectedModes()) {
|
||||
Mode mode = abil.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
artifacts.remove(game.getPermanentOrLKIBattlefield(targetId));
|
||||
|
@ -127,9 +127,9 @@ class GoblinArtisansEffect extends OneShotEffect {
|
|||
}//closing bracers
|
||||
}// pyramid, if it's bothering anyone
|
||||
} //they are all one-liners after all :)
|
||||
if (!artifacts.isEmpty()){
|
||||
Cards cards=new CardsImpl();
|
||||
for (Permanent perm : artifacts){
|
||||
if (!artifacts.isEmpty()) {
|
||||
Cards cards = new CardsImpl();
|
||||
for (Permanent perm : artifacts) {
|
||||
cards.add(perm.getId());
|
||||
}
|
||||
TargetCard target = new TargetCard(Zone.BATTLEFIELD, new FilterCard());
|
||||
|
|
|
@ -120,7 +120,7 @@ class JelevaNephaliasScourgeEffect extends OneShotEffect {
|
|||
for (int i = 0; i < cardsToExile; i++) {
|
||||
Card card = player.getLibrary().removeFromTop(game);
|
||||
if (card != null) {
|
||||
card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceCard.getName(), source.getSourceId(), game);
|
||||
card.moveToExile(CardUtil.getCardExileZoneId(game, source), sourceCard.getIdName(), source.getSourceId(), game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,7 +227,8 @@ class IcefallRegentCostIncreaseEffect extends CostModificationEffectImpl {
|
|||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify instanceof SpellAbility) {
|
||||
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||
Mode mode = abilityToModify.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetUUID : target.getTargets()) {
|
||||
if (targetUUID.equals(source.getSourceId())) {
|
||||
|
|
|
@ -109,7 +109,8 @@ class MonasterySiegeCostIncreaseEffect extends CostModificationEffectImpl {
|
|||
if (new ModeChoiceSourceCondition("Dragons").apply(game, source)) {
|
||||
if (abilityToModify instanceof SpellAbility) {
|
||||
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||
Mode mode = abilityToModify.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetUUID : target.getTargets()) {
|
||||
if (targetUUID.equals(source.getControllerId())) {
|
||||
|
|
|
@ -45,7 +45,6 @@ import mage.constants.Zone;
|
|||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.Player;
|
||||
import mage.players.PlayerList;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -103,31 +102,30 @@ class ZursWeirdingReplacementEffect extends ReplacementEffectImpl {
|
|||
Card card = player.getLibrary().getFromTop(game);
|
||||
if (card != null) {
|
||||
// reveals it instead
|
||||
player.revealCards(sourceObject.getIdName() + " next draw of " + player.getName() + " (" + game.getTurnNum()+"|"+game.getPhase().getType() +")", new CardsImpl(card), game);
|
||||
player.revealCards(sourceObject.getIdName() + " next draw of " + player.getName() + " (" + game.getTurnNum() + "|" + game.getPhase().getType() + ")", new CardsImpl(card), game);
|
||||
|
||||
// Then any other player may pay 2 life. If a player does, put that card into its owner's graveyard
|
||||
PlayerList playerList = game.getPlayerList().copy();
|
||||
playerList.setCurrent(player.getId());
|
||||
Player currentPlayer = playerList.getNext(game);
|
||||
String message = new StringBuilder("Pay 2 life to put ").append(card.getLogName()).append(" into graveyard?").toString();
|
||||
while (!currentPlayer.getId().equals(player.getId())) {
|
||||
if (currentPlayer.canPayLifeCost() &&
|
||||
currentPlayer.getLife() >= 2 &&
|
||||
currentPlayer.chooseUse(Outcome.Benefit, message, source, game)) {
|
||||
currentPlayer.loseLife(2, game);
|
||||
String message = "Pay 2 life to put " + card.getLogName() + " into graveyard?";
|
||||
for (UUID playerId : game.getState().getPlayersInRange(player.getId(), game)) {
|
||||
if (playerId.equals(player.getId())) {
|
||||
continue;
|
||||
}
|
||||
Player otherPlayer = game.getPlayer(playerId);
|
||||
if (otherPlayer.canPayLifeCost()
|
||||
&& otherPlayer.getLife() >= 2
|
||||
&& otherPlayer.chooseUse(Outcome.Benefit, message, source, game)) {
|
||||
otherPlayer.loseLife(2, game);
|
||||
player.moveCards(card, Zone.GRAVEYARD, source, game);
|
||||
// game.getState().getRevealed().reset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
currentPlayer = playerList.getNext(game);
|
||||
}
|
||||
|
||||
// game.getState().getRevealed().reset();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checksEventType(GameEvent event, Game game) {
|
||||
return event.getType() == GameEvent.EventType.DRAW_CARD;
|
||||
|
|
|
@ -141,7 +141,8 @@ class CapturedByTheConsulateTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
if (stackObject != null) {
|
||||
int numberOfTargets = 0;
|
||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
numberOfTargets += target.getTargets().size();
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ class DeadlockTrapCantActivateEffect extends RestrictionEffect {
|
|||
|
||||
@Override
|
||||
public boolean applies(Permanent permanent, Ability source, Game game) {
|
||||
return getTargetPointer().getFirst(game, source).equals(permanent.getId());
|
||||
return permanent.getId().equals(getTargetPointer().getFirst(game, source));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -135,7 +135,8 @@ class PsychicRebuttalPredicate implements ObjectPlayerPredicate<ObjectPlayer<Sta
|
|||
if (controllerId == null) {
|
||||
return false;
|
||||
}
|
||||
for (Mode mode : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = input.getObject().getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
if (controllerId.equals(targetId)) {
|
||||
|
|
|
@ -106,7 +106,8 @@ class ElderwoodScionCostReductionEffect extends CostModificationEffectImpl {
|
|||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
|
||||
if (abilityToModify.getControllerId().equals(source.getControllerId())) {
|
||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||
Mode mode = abilityToModify.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetUUID : target.getTargets()) {
|
||||
if (targetUUID.equals(source.getSourceId())) {
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
package mage.sets.scourge;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
|
@ -108,7 +107,8 @@ class GripOfChaosTriggeredAbility extends TriggeredAbilityImpl {
|
|||
}
|
||||
if (stackObject != null) {
|
||||
int numberOfTargets = 0;
|
||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
numberOfTargets += target.getTargets().size();
|
||||
}
|
||||
|
@ -149,7 +149,8 @@ class GripOfChaosEffect extends OneShotEffect {
|
|||
public boolean apply(Game game, Ability source) {
|
||||
StackObject stackObject = game.getStack().getStackObject(this.getTargetPointer().getFirst(game, source));
|
||||
if (stackObject != null) {
|
||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
UUID oldTargetId = target.getFirstTarget();
|
||||
Set<UUID> possibleTargets = target.possibleTargets(source.getSourceId(), source.getControllerId(), game);
|
||||
|
|
|
@ -140,7 +140,8 @@ class AccursedWitchSpellsCostReductionEffect extends CostModificationEffectImpl
|
|||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify instanceof SpellAbility) {
|
||||
if (game.getOpponents(source.getControllerId()).contains(abilityToModify.getControllerId())) {
|
||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||
Mode mode = abilityToModify.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetUUID : target.getTargets()) {
|
||||
Permanent permanent = game.getPermanent(targetUUID);
|
||||
|
|
|
@ -100,9 +100,11 @@ class ForkInTheRoadEffect extends OneShotEffect {
|
|||
if (target.getTargets().size() > 0) {
|
||||
Cards revealed = new CardsImpl();
|
||||
for (UUID cardId : target.getTargets()) {
|
||||
Card card = controller.getLibrary().getCard(cardId, game);
|
||||
Card card = game.getCard(cardId);
|
||||
if (card != null) {
|
||||
revealed.add(card);
|
||||
}
|
||||
}
|
||||
controller.revealCards(sourceObject.getIdName(), revealed, game);
|
||||
if (target.getTargets().size() > 0) {
|
||||
TargetCard target2 = new TargetCard(Zone.LIBRARY, filter);
|
||||
|
|
|
@ -155,7 +155,8 @@ class InfectiousCurseCostReductionEffect extends CostModificationEffectImpl {
|
|||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify instanceof SpellAbility) {
|
||||
if (source.getControllerId().equals(abilityToModify.getControllerId())) {
|
||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||
Mode mode = abilityToModify.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetUUID : target.getTargets()) {
|
||||
Permanent enchantment = game.getPermanent(source.getSourceId());
|
||||
|
|
|
@ -84,7 +84,8 @@ class HinderingLightPredicate implements ObjectPlayerPredicate<ObjectPlayer<Stac
|
|||
if (controllerId == null) {
|
||||
return false;
|
||||
}
|
||||
for (Mode mode : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : input.getObject().getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = input.getObject().getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
if (controllerId.equals(targetId)) {
|
||||
|
|
|
@ -113,13 +113,13 @@ class TorchlingTargetPredicate implements Predicate<MageObject> {
|
|||
if (spell != null) {
|
||||
int numberOfTargets = 0;
|
||||
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
||||
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||
Mode mode = spellAbility.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
if (!targetId.equals(sourceId)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
numberOfTargets++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,7 +96,8 @@ class KaerveksTorchCostIncreaseEffect extends CostModificationEffectImpl {
|
|||
@Override
|
||||
public boolean applies(Ability abilityToModify, Ability source, Game game) {
|
||||
if (abilityToModify instanceof SpellAbility || abilityToModify instanceof FlashbackAbility) {
|
||||
for (Mode mode : abilityToModify.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : abilityToModify.getModes().getSelectedModes()) {
|
||||
Mode mode = abilityToModify.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
if (targetId.equals(source.getSourceObject(game).getId())) {
|
||||
|
|
|
@ -28,12 +28,6 @@
|
|||
package mage.sets.worldwake;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility;
|
||||
import mage.abilities.common.SimpleStaticAbility;
|
||||
import mage.abilities.condition.common.SourceHasCounterCondition;
|
||||
|
@ -41,6 +35,11 @@ import mage.abilities.decorator.ConditionalContinuousEffect;
|
|||
import mage.abilities.effects.common.continuous.BoostAllEffect;
|
||||
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Duration;
|
||||
import mage.constants.Rarity;
|
||||
import mage.constants.TargetController;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterControlledCreaturePermanent;
|
||||
|
@ -54,7 +53,7 @@ import mage.filter.predicate.permanent.ControllerPredicate;
|
|||
*/
|
||||
public class QuestForTheGoblinLord extends CardImpl {
|
||||
|
||||
private static final String rule = "As long as Quest for the Goblin Lord has five or more quest counters on it, creatures you control get +2/+0.";
|
||||
private static final String rule = "As long as {this} has five or more quest counters on it, creatures you control get +2/+0";
|
||||
private static final FilterCreaturePermanent filter = new FilterCreaturePermanent();
|
||||
private static final FilterPermanent goblinFilter = new FilterControlledCreaturePermanent();
|
||||
|
||||
|
@ -67,7 +66,6 @@ public class QuestForTheGoblinLord extends CardImpl {
|
|||
super(ownerId, 86, "Quest for the Goblin Lord", Rarity.UNCOMMON, new CardType[]{CardType.ENCHANTMENT}, "{R}");
|
||||
this.expansionSetCode = "WWK";
|
||||
|
||||
|
||||
// Whenever a Goblin enters the battlefield under your control, you may put a quest counter on Quest for the Goblin Lord.
|
||||
this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.QUEST.createInstance()), goblinFilter, true));
|
||||
|
||||
|
|
|
@ -38,10 +38,6 @@ import org.mage.test.serverside.base.CardTestPlayerBaseAI;
|
|||
*/
|
||||
public class CastDestroySpellsTest extends CardTestPlayerBaseAI {
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testOrzhovCharm() {
|
||||
// Choose one -
|
||||
|
@ -58,6 +54,8 @@ public class CastDestroySpellsTest extends CardTestPlayerBaseAI {
|
|||
// Cycling abilities you activate cost you up to {2} less to activate.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Orzhov Charm", "Silvercoat Lion");
|
||||
setModeChoice(playerA, "2");
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
|
|
@ -367,6 +367,31 @@ public class FlashbackTest extends CardTestPlayerBase {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSnapcasterMageWithBuyback() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 8);
|
||||
addCard(Zone.HAND, playerA, "Snapcaster Mage", 1);
|
||||
|
||||
// Buyback {5}(You may pay an additional {5} as you cast this spell. If you do, put this card into your hand as it resolves.)
|
||||
// Draw a card.
|
||||
addCard(Zone.GRAVEYARD, playerA, "Whispers of the Muse", 1); // {U}
|
||||
|
||||
// When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
|
||||
setChoice(playerA, "Whispers of the Muse");
|
||||
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback"); // Flashback Whispers of the Muse
|
||||
setChoice(playerA, "Yes");
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Snapcaster Mage", 1);
|
||||
assertGraveyardCount(playerA, "Whispers of the Muse", 0);
|
||||
assertHandCount(playerA, 1);
|
||||
assertExileCount("Whispers of the Muse", 1);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep Analysis doesn't cost mana when flashbacked.
|
||||
*/
|
||||
|
|
|
@ -219,7 +219,7 @@ public class UndyingTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tatterkite is getting counters on it, i have him in a edh deck with
|
||||
* Tatterkite is getting counters on it, I have him in a edh deck with
|
||||
* Mikaeus, the Lunarch and when Tatterkite dies it triggers the undying and
|
||||
* he gets the +1/+1 counters
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
package org.mage.test.cards.modal;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class OneOrBothTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void testSubtleStrikeFirstMode() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
// Choose one or both —
|
||||
// • Target creature gets -1/-1 until end of turn.
|
||||
// • Put a +1/+1 counter on target creature.
|
||||
addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, null);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, "Silvercoat Lion", 2, 2);
|
||||
assertPowerToughness(playerB, "Pillarfield Ox", 1, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubtleStrikeSecondMode() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
// Choose one or both —
|
||||
// • Target creature gets -1/-1 until end of turn.
|
||||
// • Put a +1/+1 counter on target creature.
|
||||
addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, null);
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, "Silvercoat Lion", 2, 2);
|
||||
assertPowerToughness(playerB, "Pillarfield Ox", 3, 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSubtleStrikeBothModes() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
|
||||
// Choose one or both —
|
||||
// • Target creature gets -1/-1 until end of turn.
|
||||
// • Put a +1/+1 counter on target creature.
|
||||
addCard(Zone.HAND, playerA, "Subtle Strike"); // Instant {1}{B}
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Subtle Strike", "Pillarfield Ox");
|
||||
addTarget(playerA, "Silvercoat Lion");
|
||||
setModeChoice(playerA, "1");
|
||||
setModeChoice(playerA, "2");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPowerToughness(playerA, "Silvercoat Lion", 3, 3);
|
||||
assertPowerToughness(playerB, "Pillarfield Ox", 1, 3);
|
||||
}
|
||||
}
|
|
@ -39,20 +39,22 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
public class BrutalExpulsionTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
* Brutal Expulsion targeting Gideon, Ally of Zendikar. Gideon has 3 loyalty. Brutal Expulsion resolves,
|
||||
* leaves 1 loyalty. I attack Gideon for 1 with a Scion token, Gideon dies. Instead of going to graveyard,
|
||||
* Expulsion sends Gideon to exile. However, in game Gideon went to graveyard.
|
||||
* Brutal Expulsion targeting Gideon, Ally of Zendikar. Gideon has 3
|
||||
* loyalty. Brutal Expulsion resolves, leaves 1 loyalty. I attack Gideon for
|
||||
* 1 with a Scion token, Gideon dies. Instead of going to graveyard,
|
||||
* Expulsion sends Gideon to exile. However, in game Gideon went to
|
||||
* graveyard.
|
||||
*/
|
||||
@Test
|
||||
public void testPlaneswalkerExile() {
|
||||
// Choose one or both
|
||||
// - Return target spell or creature to its owner's hand;
|
||||
// or Brutal Expulsion deals 2 damage to target creature or planeswalker. If that permanent would be put into a graveyard this turn, exile it instead.
|
||||
addCard(Zone.HAND, playerA, "Brutal Expulsion");
|
||||
addCard(Zone.HAND, playerA, "Brutal Expulsion"); // {2}{U}{R}
|
||||
// Shock deals 2 damage to target creature or player.
|
||||
addCard(Zone.HAND, playerA, "Shock");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
|
||||
addCard(Zone.HAND, playerA, "Shock"); // {R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
|
||||
// Planeswalker with 4 loyalty.
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Gideon, Ally of Zendikar");
|
||||
|
@ -60,12 +62,12 @@ public class BrutalExpulsionTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brutal Expulsion", playerB);
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, null);
|
||||
setChoice(playerA, "Yes");
|
||||
setChoice(playerA, "Yes"); // Redirect to planeswalker
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shock", playerB);
|
||||
setChoice(playerA, "Yes");
|
||||
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Shock", playerB);
|
||||
setChoice(playerA, "Yes"); // Redirect to planeswalker
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
setStopAt(1, PhaseStep.END_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerB, "Gideon, Ally of Zendikar", 0);
|
||||
|
|
|
@ -267,7 +267,7 @@ public class LoadTest {
|
|||
* @return
|
||||
*/
|
||||
private MatchOptions createGameOptions(GameTypeView gameTypeView, Session session) {
|
||||
MatchOptions options = new MatchOptions("Test game", gameTypeView.getName());
|
||||
MatchOptions options = new MatchOptions("Test game", gameTypeView.getName(), false, 2);
|
||||
|
||||
options.getPlayerTypes().add("Human");
|
||||
options.getPlayerTypes().add("Human");
|
||||
|
|
|
@ -287,7 +287,8 @@ public class TestPlayer implements Player {
|
|||
}
|
||||
UUID modeId = ability.getModes().getModeId(modeNr);
|
||||
|
||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||
for (UUID currentModeId : ability.getModes().getSelectedModes()) {
|
||||
Mode mode = ability.getModes().get(currentModeId);
|
||||
if (mode.getId().equals(modeId)) {
|
||||
selectedMode = mode;
|
||||
ability.getModes().setActiveMode(mode);
|
||||
|
|
|
@ -306,7 +306,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
&& game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) {
|
||||
return false;
|
||||
}
|
||||
for (Mode mode : this.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : this.getModes().getSelectedModes()) {
|
||||
Mode mode = this.getModes().get(modeId);
|
||||
this.getModes().setActiveMode(mode);
|
||||
//20121001 - 601.2c
|
||||
// 601.2c The player announces his or her choice of an appropriate player, object, or zone for
|
||||
|
@ -1060,7 +1061,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
} else if (object instanceof Spell && ((Spell) object).getSpellAbility().getModes().size() > 1) {
|
||||
Modes spellModes = ((Spell) object).getSpellAbility().getModes();
|
||||
for (Mode selectedMode : spellModes.getSelectedModes()) {
|
||||
for (UUID selectedModeId : spellModes.getSelectedModes()) {
|
||||
Mode selectedMode = spellModes.get(selectedModeId);
|
||||
int item = 0;
|
||||
for (Mode mode : spellModes.values()) {
|
||||
item++;
|
||||
|
|
|
@ -41,7 +41,6 @@ import mage.constants.TargetController;
|
|||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -49,8 +48,8 @@ import mage.util.CardUtil;
|
|||
*/
|
||||
public class Modes extends LinkedHashMap<UUID, Mode> {
|
||||
|
||||
private Mode mode; // the current mode of the selected modes
|
||||
private final ArrayList<Mode> selectedModes = new ArrayList<>();
|
||||
private Mode currentMode; // the current mode of the selected modes
|
||||
private final ArrayList<UUID> selectedModes = new ArrayList<>();
|
||||
private int minModes;
|
||||
private int maxModes;
|
||||
private TargetController modeChooser;
|
||||
|
@ -58,11 +57,11 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists
|
||||
|
||||
public Modes() {
|
||||
this.mode = new Mode();
|
||||
this.put(mode.getId(), mode);
|
||||
this.currentMode = new Mode();
|
||||
this.put(currentMode.getId(), currentMode);
|
||||
this.minModes = 1;
|
||||
this.maxModes = 1;
|
||||
this.selectedModes.add(mode);
|
||||
this.selectedModes.add(currentMode.getId());
|
||||
this.modeChooser = TargetController.YOU;
|
||||
this.eachModeOnlyOnce = false;
|
||||
this.eachModeMoreThanOnce = false;
|
||||
|
@ -75,23 +74,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
this.minModes = modes.minModes;
|
||||
this.maxModes = modes.maxModes;
|
||||
|
||||
if (modes.size() == 1) {
|
||||
this.mode = values().iterator().next();
|
||||
this.selectedModes.add(mode);
|
||||
} else {
|
||||
// probably there is still a problem with copying modes with the same mode selected multiple times.
|
||||
for (Mode selectedMode : modes.getSelectedModes()) {
|
||||
Mode copiedMode = selectedMode.copy();
|
||||
this.selectedModes.add(copiedMode);
|
||||
if (modes.getSelectedModes().size() == 1) {
|
||||
this.mode = copiedMode;
|
||||
} else {
|
||||
if (selectedMode.equals(modes.getMode())) {
|
||||
this.mode = copiedMode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.currentMode = values().iterator().next();
|
||||
selectedModes.addAll(modes.getSelectedModes());
|
||||
this.modeChooser = modes.modeChooser;
|
||||
this.eachModeOnlyOnce = modes.eachModeOnlyOnce;
|
||||
this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce;
|
||||
|
@ -102,21 +86,21 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
}
|
||||
|
||||
public Mode getMode() {
|
||||
return mode;
|
||||
return currentMode;
|
||||
}
|
||||
|
||||
public UUID getModeId(int index) {
|
||||
int idx = 0;
|
||||
for (Mode currentMode : this.values()) {
|
||||
for (Mode mode : this.values()) {
|
||||
idx++;
|
||||
if (idx == index) {
|
||||
return currentMode.getId();
|
||||
return mode.getId();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public ArrayList<Mode> getSelectedModes() {
|
||||
public ArrayList<UUID> getSelectedModes() {
|
||||
return selectedModes;
|
||||
}
|
||||
|
||||
|
@ -145,8 +129,8 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
}
|
||||
|
||||
public void setActiveMode(Mode mode) {
|
||||
if (selectedModes.contains(mode)) {
|
||||
this.mode = mode;
|
||||
if (selectedModes.contains(mode.getId())) {
|
||||
this.currentMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,7 +159,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
for (Mode mode : this.values()) {
|
||||
if ((!isEachModeOnlyOnce() || onceSelectedModes == null || !onceSelectedModes.contains(mode.getId()))
|
||||
&& mode.getTargets().canChoose(source.getSourceId(), source.getControllerId(), game)) {
|
||||
this.selectedModes.add(mode.copy());
|
||||
this.selectedModes.add(mode.getId());
|
||||
}
|
||||
}
|
||||
if (isEachModeOnlyOnce()) {
|
||||
|
@ -203,7 +187,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
Player player = game.getPlayer(playerId);
|
||||
|
||||
// player chooses modes manually
|
||||
this.mode = null;
|
||||
this.currentMode = null;
|
||||
while (this.selectedModes.size() < this.getMaxModes()) {
|
||||
Mode choice = player.chooseMode(this, source, game);
|
||||
if (choice == null) {
|
||||
|
@ -212,9 +196,9 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
}
|
||||
return this.selectedModes.size() >= this.getMinModes();
|
||||
}
|
||||
this.selectedModes.add(choice.copy());
|
||||
if (mode == null) {
|
||||
mode = choice;
|
||||
this.selectedModes.add(choice.getId());
|
||||
if (currentMode == null) {
|
||||
currentMode = choice;
|
||||
}
|
||||
}
|
||||
if (isEachModeOnlyOnce()) {
|
||||
|
@ -222,10 +206,10 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
}
|
||||
return true;
|
||||
}
|
||||
if (mode == null) {
|
||||
if (currentMode == null) {
|
||||
this.selectedModes.clear();
|
||||
Mode copiedMode = this.values().iterator().next().copy();
|
||||
this.selectedModes.add(copiedMode);
|
||||
this.selectedModes.add(copiedMode.getId());
|
||||
this.setActiveMode(copiedMode);
|
||||
}
|
||||
if (isEachModeOnlyOnce()) {
|
||||
|
@ -234,27 +218,46 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void setAlreadySelectedModes(ArrayList<Mode> selectedModes, Ability source, Game game) {
|
||||
String key = getKey(source, game);
|
||||
Set<UUID> onceSelectedModes = (Set<UUID>) game.getState().getValue(key);
|
||||
if (onceSelectedModes == null) {
|
||||
onceSelectedModes = new HashSet<>();
|
||||
/**
|
||||
* Saves the already selected modes to the state value
|
||||
*
|
||||
* @param selectedModes
|
||||
* @param source
|
||||
* @param game
|
||||
*/
|
||||
private void setAlreadySelectedModes(ArrayList<UUID> selectedModes, Ability source, Game game) {
|
||||
for (UUID modeId : selectedModes) {
|
||||
String key = getKey(source, game, modeId);
|
||||
game.getState().setValue(key, true);
|
||||
}
|
||||
for (Mode mode : selectedModes) {
|
||||
onceSelectedModes.add(mode.getId());
|
||||
}
|
||||
|
||||
game.getState().setValue(key, onceSelectedModes);
|
||||
}
|
||||
|
||||
// The already once selected modes for a modal card are stored as a state value
|
||||
// That's important for modal abilities with modes that can only selected once while the object stays in its zone
|
||||
@SuppressWarnings("unchecked")
|
||||
private Set<UUID> getAlreadySelectedModes(Ability source, Game game) {
|
||||
return (Set<UUID>) game.getState().getValue(getKey(source, game));
|
||||
Set<UUID> onceSelectedModes = new HashSet<>();
|
||||
for (UUID modeId : this.keySet()) {
|
||||
Object exist = game.getState().getValue(getKey(source, game, modeId));
|
||||
if (exist != null) {
|
||||
onceSelectedModes.add(modeId);
|
||||
}
|
||||
}
|
||||
return onceSelectedModes;
|
||||
}
|
||||
|
||||
private String getKey(Ability source, Game game) {
|
||||
return CardUtil.getObjectZoneString("selectedModes", source.getSourceId(), game, game.getState().getZoneChangeCounter(source.getSourceId()), false);
|
||||
// creates the key the selected modes are saved with to the state values
|
||||
private String getKey(Ability source, Game game, UUID modeId) {
|
||||
return source.getSourceId().toString() + game.getState().getZoneChangeCounter(source.getSourceId()) + modeId.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all (still) available modes of the ability
|
||||
*
|
||||
* @param source
|
||||
* @param game
|
||||
* @return
|
||||
*/
|
||||
public List<Mode> getAvailableModes(Ability source, Game game) {
|
||||
List<Mode> availableModes = new ArrayList<>();
|
||||
Set<UUID> nonAvailableModes;
|
||||
|
|
|
@ -56,6 +56,9 @@ public abstract class StaticAbility extends AbilityImpl {
|
|||
if (game.getShortLivingLKI(getSourceId(), zone)) {
|
||||
return true; // maybe this can be a problem if effects removed the ability from the object
|
||||
}
|
||||
if (game.getPermanentEntering(getSourceId()) != null && zone.equals(Zone.BATTLEFIELD)) {
|
||||
return true; // abilities of permanents entering battlefield are countes as on battlefield
|
||||
}
|
||||
return super.isInUseableZone(game, source, event);
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
MageObject object = game.getObject(getSourceId());
|
||||
Player player = game.getPlayer(this.getControllerId());
|
||||
if (player != null && object != null) {
|
||||
if (!player.chooseUse(getEffects().get(0).getOutcome(), (object != null ? this.getRule(object.getLogName()) : this.getRule()), this, game)) {
|
||||
if (!player.chooseUse(getEffects().get(0).getOutcome(), this.getRule(object.getLogName()), this, game)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
|
@ -216,7 +216,7 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge
|
|||
|
||||
/*
|
||||
603.6c,603.6d
|
||||
This has to be set, if the triggered ability has to check back in time if the permanent the ability is connected to had the ability on the battlefeild while the trigger is checked
|
||||
This has to be set, if the triggered ability has to check back in time if the permanent the ability is connected to had the ability on the battlefield while the trigger is checked
|
||||
*/
|
||||
@Override
|
||||
public final void setLeavesTheBattlefieldTrigger(boolean leavesTheBattlefieldTrigger) {
|
||||
|
|
|
@ -51,7 +51,8 @@ public class ChangeATargetOfTargetSpellAbilityToSourceEffect extends OneShotEffe
|
|||
} else {
|
||||
return false;
|
||||
}
|
||||
for (Mode mode : sourceAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : sourceAbility.getModes().getSelectedModes()) {
|
||||
Mode mode = sourceAbility.getModes().get(modeId);
|
||||
targets.addAll(mode.getTargets());
|
||||
}
|
||||
|
||||
|
@ -102,13 +103,11 @@ public class ChangeATargetOfTargetSpellAbilityToSourceEffect extends OneShotEffe
|
|||
}
|
||||
if (oldTargetName != null) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Changed target of " + stackObject.getLogName() + " from " + oldTargetName + " to " + sourceObject.getLogName());
|
||||
} else {
|
||||
if (twoTimesTarget) {
|
||||
} else if (twoTimesTarget) {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its not valid to target it twice for " + stackObject.getLogName());
|
||||
} else {
|
||||
game.informPlayers(sourceObject.getLogName() + ": Target not changed to " + sourceObject.getLogName() + " because its no valid target for " + stackObject.getLogName());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -186,7 +186,7 @@ class BuybackEffect extends ReplacementEffectImpl {
|
|||
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||
if (event.getTargetId().equals(source.getSourceId())) {
|
||||
ZoneChangeEvent zEvent = (ZoneChangeEvent) event;
|
||||
if (zEvent.getFromZone() == Zone.STACK
|
||||
if (zEvent.getFromZone() == Zone.STACK && zEvent.getToZone() == Zone.GRAVEYARD
|
||||
&& source.getSourceId().equals(event.getSourceId())) { // if spell fizzled, the sourceId is null
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -274,7 +274,8 @@ class FlashbackReplacementEffect extends ReplacementEffectImpl {
|
|||
if (controller != null) {
|
||||
Card card = game.getCard(event.getTargetId());
|
||||
if (card != null) {
|
||||
return controller.moveCards(card, Zone.EXILED, source, game);
|
||||
return controller.moveCards(
|
||||
card, Zone.EXILED, source, game, false, false, false, event.getAppliedEffects());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
|
@ -82,7 +82,8 @@ public class HeroicAbility extends TriggeredAbilityImpl {
|
|||
private boolean checkSpell(Spell spell, Game game) {
|
||||
if (spell != null) {
|
||||
SpellAbility sa = spell.getSpellAbility();
|
||||
for (Mode mode : sa.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : sa.getModes().getSelectedModes()) {
|
||||
Mode mode = sa.getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
if (!target.isNotTarget() && target.getTargets().contains(this.getSourceId())) {
|
||||
return true;
|
||||
|
|
|
@ -63,7 +63,7 @@ public enum CardRepository {
|
|||
// raise this if db structure was changed
|
||||
private static final long CARD_DB_VERSION = 47;
|
||||
// raise this if new cards were added to the server
|
||||
private static final long CARD_CONTENT_VERSION = 61;
|
||||
private static final long CARD_CONTENT_VERSION = 62;
|
||||
|
||||
private Dao<CardInfo, Object> cardDao;
|
||||
private Set<String> classNames;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
package mage.filter.predicate.mageobject;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Mode;
|
||||
import mage.filter.predicate.Predicate;
|
||||
|
@ -51,7 +52,8 @@ public class NumberOfTargetsPredicate implements Predicate<MageObject> {
|
|||
StackObject stackObject = game.getState().getStack().getStackObject(input.getId());
|
||||
if (stackObject != null) {
|
||||
int numberOfTargets = 0;
|
||||
for (Mode mode : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : stackObject.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = stackObject.getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
numberOfTargets += target.getTargets().size();
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ public class TargetsPermanentPredicate implements ObjectSourcePlayerPredicate<Ob
|
|||
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
|
||||
StackObject object = game.getStack().getStackObject(input.getObject().getId());
|
||||
if (object != null) {
|
||||
for (Mode mode : object.getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : object.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = object.getStackAbility().getModes().get(modeId);
|
||||
for (Target target : mode.getTargets()) {
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
Permanent permanent = game.getPermanentOrLKIBattlefield(targetId);
|
||||
|
|
|
@ -314,7 +314,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
for (StackObject spell : stack) {
|
||||
sb.append(spell.getControllerId()).append(spell.getName());
|
||||
sb.append(spell.getStackAbility().toString());
|
||||
for (Mode mode : spell.getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spell.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = spell.getStackAbility().getModes().get(modeId);
|
||||
if (!mode.getTargets().isEmpty()) {
|
||||
sb.append("targets");
|
||||
for (Target target : mode.getTargets()) {
|
||||
|
@ -366,7 +367,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
for (StackObject spell : stack) {
|
||||
sb.append(spell.getControllerId()).append(spell.getName());
|
||||
sb.append(spell.getStackAbility().toString());
|
||||
for (Mode mode : spell.getStackAbility().getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spell.getStackAbility().getModes().getSelectedModes()) {
|
||||
Mode mode = spell.getStackAbility().getModes().get(modeId);
|
||||
if (!mode.getTargets().isEmpty()) {
|
||||
sb.append("targets");
|
||||
for (Target target : mode.getTargets()) {
|
||||
|
@ -784,7 +786,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
|
||||
public void addAbility(Ability ability, MageObject attachedTo) {
|
||||
if (ability instanceof StaticAbility) {
|
||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||
Mode mode = ability.getModes().get(modeId);
|
||||
for (Effect effect : mode.getEffects()) {
|
||||
if (effect instanceof ContinuousEffect) {
|
||||
addEffect((ContinuousEffect) effect, ability);
|
||||
|
@ -806,7 +809,8 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
*/
|
||||
public void addAbility(Ability ability, UUID sourceId, Card attachedTo) {
|
||||
if (ability instanceof StaticAbility) {
|
||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||
Mode mode = ability.getModes().get(modeId);
|
||||
for (Effect effect : mode.getEffects()) {
|
||||
if (effect instanceof ContinuousEffect) {
|
||||
addEffect((ContinuousEffect) effect, sourceId, ability);
|
||||
|
|
|
@ -237,6 +237,9 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
possibleDefenders = new HashSet<>(defenders);
|
||||
}
|
||||
Player player = game.getPlayer(attackerId);
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
if (possibleDefenders.size() == 1) {
|
||||
addAttackerToCombat(creatureId, possibleDefenders.iterator().next(), game);
|
||||
return true;
|
||||
|
@ -866,6 +869,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
blockIsValid = true;
|
||||
break CombatGroups;
|
||||
} else // check if the blocker blocks a attacker that must be blocked at least by one and is the only blocker, this block is also valid
|
||||
{
|
||||
if (combatGroup.getBlockers().size() == 1) {
|
||||
if (mustBeBlockedByAtLeastOne.containsKey(forcingAttackerId)) {
|
||||
if (mustBeBlockedByAtLeastOne.get(forcingAttackerId).contains(creatureForcedToBlock.getId())) {
|
||||
|
@ -877,6 +881,7 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (!blockIsValid) {
|
||||
|
@ -921,8 +926,8 @@ public class Combat implements Serializable, Copyable<Combat> {
|
|||
if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) {
|
||||
// blocks a creature that has to be blocked by at least one
|
||||
if (combatGroupOfPossibleBlocker.getBlockers().size() == 1) {
|
||||
Set <UUID> blockedSet = mustBeBlockedByAtLeastOne.get(blockedAttackerId);
|
||||
Set <UUID> toBlockSet = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId);
|
||||
Set<UUID> blockedSet = mustBeBlockedByAtLeastOne.get(blockedAttackerId);
|
||||
Set<UUID> toBlockSet = mustBeBlockedByAtLeastOne.get(toBeBlockedCreatureId);
|
||||
if (toBlockSet == null) {
|
||||
// This should never happen.
|
||||
return null;
|
||||
|
|
|
@ -36,6 +36,7 @@ import mage.cards.decks.Deck;
|
|||
import mage.game.Game;
|
||||
import mage.game.draft.Draft;
|
||||
import mage.game.match.MatchOptions;
|
||||
import mage.game.tournament.MultiplayerRound;
|
||||
import mage.game.tournament.TournamentPairing;
|
||||
|
||||
/**
|
||||
|
@ -46,7 +47,7 @@ public class TableEvent extends EventObject implements ExternalEvent, Serializab
|
|||
|
||||
public enum EventType {
|
||||
UPDATE, INFO, STATUS, START_DRAFT, START_MATCH, SIDEBOARD, CONSTRUCT, SUBMIT_DECK, END, END_GAME_INFO, ERROR,
|
||||
INIT_TIMER, RESUME_TIMER, PAUSE_TIMER, CHECK_STATE_PLAYERS
|
||||
INIT_TIMER, RESUME_TIMER, PAUSE_TIMER, CHECK_STATE_PLAYERS, START_MULTIPLAYER_MATCH
|
||||
}
|
||||
|
||||
private Game game;
|
||||
|
@ -58,6 +59,7 @@ public class TableEvent extends EventObject implements ExternalEvent, Serializab
|
|||
private UUID playerId;
|
||||
private Deck deck;
|
||||
private TournamentPairing pair;
|
||||
private MultiplayerRound round;
|
||||
private MatchOptions options;
|
||||
private int timeout;
|
||||
private boolean withTime;
|
||||
|
@ -116,6 +118,13 @@ public class TableEvent extends EventObject implements ExternalEvent, Serializab
|
|||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public TableEvent(EventType eventType, MultiplayerRound round, MatchOptions options) {
|
||||
super(options);
|
||||
this.round = round;
|
||||
this.options = options;
|
||||
this.eventType = eventType;
|
||||
}
|
||||
|
||||
public Game getGame() {
|
||||
return game;
|
||||
}
|
||||
|
@ -152,6 +161,10 @@ public class TableEvent extends EventObject implements ExternalEvent, Serializab
|
|||
return pair;
|
||||
}
|
||||
|
||||
public MultiplayerRound getMultiplayerRound() {
|
||||
return round;
|
||||
}
|
||||
|
||||
public MatchOptions getMatchOptions() {
|
||||
return options;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import mage.game.tournament.TournamentPairing;
|
|||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import mage.game.tournament.MultiplayerRound;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -93,4 +94,8 @@ public class TableEventSource implements EventSource<TableEvent>, Serializable {
|
|||
public void fireTableEvent(EventType eventType, TournamentPairing pair, MatchOptions options) {
|
||||
dispatcher.fireEvent(new TableEvent(eventType, pair, options));
|
||||
}
|
||||
|
||||
public void fireTableEvent(EventType eventType, MultiplayerRound round, MatchOptions options) {
|
||||
dispatcher.fireEvent(new TableEvent(eventType, round, options));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,21 +52,50 @@ public class MatchOptions implements Serializable {
|
|||
protected String deckType;
|
||||
protected boolean limited;
|
||||
protected List<String> playerTypes = new ArrayList<>();
|
||||
protected boolean multiPlayer;
|
||||
protected int numSeats;
|
||||
protected String password;
|
||||
protected SkillLevel skillLevel;
|
||||
protected boolean rollbackTurnsAllowed;
|
||||
protected int quitRatio;
|
||||
protected boolean rated;
|
||||
protected int numSeatsForMatch;
|
||||
|
||||
/**
|
||||
* Time each player has during the game to play using his\her priority.
|
||||
*/
|
||||
protected MatchTimeLimit matchTimeLimit; // 0 = no priorityTime handling
|
||||
|
||||
public MatchOptions(String name, String gameType) {
|
||||
/*public MatchOptions(String name, String gameType) {
|
||||
this.name = name;
|
||||
this.gameType = gameType;
|
||||
this.password = "";
|
||||
this.multiPlayer = false;
|
||||
this.numSeats = 2;
|
||||
}*/
|
||||
|
||||
public MatchOptions(String name, String gameType, boolean multiPlayer, int numSeats ) {
|
||||
this.name = name;
|
||||
this.gameType = gameType;
|
||||
this.password = "";
|
||||
this.multiPlayer = multiPlayer;
|
||||
this.numSeats = numSeats;
|
||||
}
|
||||
|
||||
public void setNumSeats (int numSeats) {
|
||||
this.numSeats = numSeats;
|
||||
}
|
||||
|
||||
public int getNumSeats () {
|
||||
return numSeats;
|
||||
}
|
||||
|
||||
public void setMultiPlayer(boolean multiPlayer) {
|
||||
this.multiPlayer = multiPlayer;
|
||||
}
|
||||
|
||||
public boolean getMultiPlayer() {
|
||||
return multiPlayer;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -210,7 +210,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
if (notTargeted || legalParts) {
|
||||
for (SpellAbility spellAbility : this.spellAbilities) {
|
||||
if (spellAbilityHasLegalParts(spellAbility, game)) {
|
||||
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||
Mode mode = spellAbility.getModes().get(modeId);
|
||||
spellAbility.getModes().setActiveMode(mode);
|
||||
if (mode.getTargets().stillLegal(spellAbility, game)) {
|
||||
if (!spellAbility.getSpellAbilityType().equals(SpellAbilityType.SPLICE)) {
|
||||
|
@ -283,7 +284,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
|
||||
private boolean hasTargets(SpellAbility spellAbility, Game game) {
|
||||
if (spellAbility.getModes().getSelectedModes().size() > 1) {
|
||||
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||
Mode mode = spellAbility.getModes().get(modeId);
|
||||
if (!mode.getTargets().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -299,7 +301,8 @@ public class Spell extends StackObjImpl implements Card {
|
|||
if (spellAbility.getModes().getSelectedModes().size() > 1) {
|
||||
boolean targetedMode = false;
|
||||
boolean legalTargetedMode = false;
|
||||
for (Mode mode : spellAbility.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : spellAbility.getModes().getSelectedModes()) {
|
||||
Mode mode = spellAbility.getModes().get(modeId);
|
||||
if (mode.getTargets().size() > 0) {
|
||||
targetedMode = true;
|
||||
if (mode.getTargets().stillLegal(spellAbility, game)) {
|
||||
|
|
|
@ -117,7 +117,8 @@ public abstract class StackObjImpl implements StackObject {
|
|||
}
|
||||
for (Ability ability : objectAbilities) {
|
||||
// Some spells can have more than one mode
|
||||
for (Mode mode : ability.getModes().getSelectedModes()) {
|
||||
for (UUID modeId : ability.getModes().getSelectedModes()) {
|
||||
Mode mode = ability.getModes().get(modeId);
|
||||
ability.getModes().setActiveMode(mode);
|
||||
oldTargetDescription.append(ability.getTargetDescription(mode.getTargets(), game));
|
||||
for (Target target : mode.getTargets()) {
|
||||
|
@ -210,7 +211,6 @@ public abstract class StackObjImpl implements StackObject {
|
|||
again = true;
|
||||
}
|
||||
} else // if possible add the alternate Target - it may not be included in the old definition nor in the already selected targets of the new definition
|
||||
{
|
||||
if (newTarget.getTargets().contains(tempTarget.getFirstTarget()) || target.getTargets().contains(tempTarget.getFirstTarget())) {
|
||||
if (targetController.isHuman()) {
|
||||
if (targetController.chooseUse(Outcome.Benefit, "This target was already selected from origin spell. Reset to original target?", ability, game)) {
|
||||
|
@ -240,7 +240,6 @@ public abstract class StackObjImpl implements StackObject {
|
|||
// valid target was selected, add it to the new target definition
|
||||
newTarget.addTarget(tempTarget.getFirstTarget(), target.getTargetAmount(targetId), ability, game, false);
|
||||
}
|
||||
}
|
||||
} while (again && targetController.canRespond());
|
||||
}
|
||||
} // keep the target
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import mage.game.match.Match;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author spjspj
|
||||
*/
|
||||
public class MultiplayerRound {
|
||||
|
||||
private final int roundNum;
|
||||
private final Tournament tournament;
|
||||
private final int numSeats;
|
||||
private final List<TournamentPlayer> allPlayers = new ArrayList<>();
|
||||
private Match match;
|
||||
private UUID tableId;
|
||||
|
||||
|
||||
public MultiplayerRound(int roundNum, Tournament tournament, int numSeats) {
|
||||
this.roundNum = roundNum;
|
||||
this.tournament = tournament;
|
||||
this.numSeats = numSeats;
|
||||
}
|
||||
|
||||
public List<TournamentPlayer> getAllPlayers () {
|
||||
return allPlayers;
|
||||
}
|
||||
|
||||
public TournamentPlayer getPlayer (int i) {
|
||||
if (i >= 0 && i < numSeats && i < allPlayers.size()) {
|
||||
return allPlayers.get(i);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void addPairing(TournamentPairing match) {
|
||||
this.allPlayers.add(match.getPlayer1());
|
||||
this.allPlayers.add(match.getPlayer2());
|
||||
}
|
||||
|
||||
public void addPlayer(TournamentPlayer player) {
|
||||
this.allPlayers.add(player);
|
||||
}
|
||||
|
||||
public int getRoundNumber() {
|
||||
return this.roundNum;
|
||||
}
|
||||
|
||||
public void setMatch (Match match) {
|
||||
this.match = match;
|
||||
}
|
||||
|
||||
public void setTableId (UUID tableId) {
|
||||
this.tableId = tableId;
|
||||
}
|
||||
|
||||
public boolean isRoundOver() {
|
||||
boolean roundIsOver = true;
|
||||
if (this.match != null) {
|
||||
if (!this.match.hasEnded()) {
|
||||
roundIsOver = false;
|
||||
}
|
||||
}
|
||||
return roundIsOver;
|
||||
}
|
||||
}
|
|
@ -262,6 +262,12 @@ public abstract class TournamentImpl implements Tournament {
|
|||
updateResults();
|
||||
}
|
||||
|
||||
protected void playMultiplayerRound(MultiplayerRound round) {
|
||||
playMultiPlayerMatch(round);
|
||||
|
||||
updateResults(); // show points from byes
|
||||
}
|
||||
|
||||
protected List<TournamentPlayer> getActivePlayers() {
|
||||
List<TournamentPlayer> activePlayers = new ArrayList<>();
|
||||
for (TournamentPlayer player : players.values()) {
|
||||
|
@ -457,6 +463,10 @@ public abstract class TournamentImpl implements Tournament {
|
|||
tableEventSource.fireTableEvent(EventType.START_MATCH, pair, options.getMatchOptions());
|
||||
}
|
||||
|
||||
public void playMultiPlayerMatch(MultiplayerRound round) {
|
||||
tableEventSource.fireTableEvent(EventType.START_MULTIPLAYER_MATCH, round, options.getMatchOptions());
|
||||
}
|
||||
|
||||
public void end() {
|
||||
endTime = new Date();
|
||||
tableEventSource.fireTableEvent(EventType.END);
|
||||
|
|
|
@ -41,15 +41,16 @@ public class TournamentOptions implements Serializable {
|
|||
protected String name;
|
||||
protected String tournamentType;
|
||||
protected List<String> playerTypes = new ArrayList<>();
|
||||
protected MatchOptions matchOptions = new MatchOptions("", "Two Player Duel");
|
||||
protected MatchOptions matchOptions;
|
||||
protected LimitedOptions limitedOptions;
|
||||
protected boolean watchingAllowed = true;
|
||||
protected int numberRounds;
|
||||
protected String password;
|
||||
protected int quitRatio;
|
||||
|
||||
public TournamentOptions(String name) {
|
||||
public TournamentOptions(String name, String matchType, int numSeats) {
|
||||
this.name = name;
|
||||
this.matchOptions = new MatchOptions("", matchType, numSeats > 2, numSeats);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -34,8 +34,8 @@ package mage.game.tournament;
|
|||
*/
|
||||
public class TournamentSealedOptions extends TournamentOptions {
|
||||
|
||||
public TournamentSealedOptions(String name) {
|
||||
super(name);
|
||||
public TournamentSealedOptions(String name, String matchType, int numSeats) {
|
||||
super(name, matchType, numSeats);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
package mage.game.tournament;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.game.events.TableEvent;
|
||||
|
@ -50,6 +51,7 @@ public abstract class TournamentSingleElimination extends TournamentImpl {
|
|||
entry.getValue().setResults("Auto Eliminated");
|
||||
}
|
||||
}
|
||||
if (options.matchOptions.getNumSeats() == 2) {
|
||||
while (this.getActivePlayers().size() > 1) {
|
||||
// check if some player got killed / disconnected meanwhile and update their state
|
||||
tableEventSource.fireTableEvent(TableEvent.EventType.CHECK_STATE_PLAYERS);
|
||||
|
@ -57,6 +59,14 @@ public abstract class TournamentSingleElimination extends TournamentImpl {
|
|||
playRound(round);
|
||||
eliminatePlayers(round);
|
||||
}
|
||||
} else {
|
||||
MultiplayerRound round = new MultiplayerRound(0, this, options.matchOptions.getNumSeats());
|
||||
for (TournamentPlayer player : getActivePlayers()) {
|
||||
round.addPlayer(player);
|
||||
}
|
||||
playMultiplayerRound(round);
|
||||
}
|
||||
|
||||
nextStep();
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,7 @@ public abstract class TournamentSwiss extends TournamentImpl {
|
|||
}
|
||||
}
|
||||
|
||||
if (options.matchOptions.getNumSeats() == 2) {
|
||||
while (this.getActivePlayers().size() > 1 && this.getNumberRounds() > this.getRounds().size()) {
|
||||
// check if some player got killed / disconnected meanwhile and update their state
|
||||
tableEventSource.fireTableEvent(TableEvent.EventType.CHECK_STATE_PLAYERS);
|
||||
|
@ -63,6 +64,11 @@ public abstract class TournamentSwiss extends TournamentImpl {
|
|||
Round round = createRoundSwiss();
|
||||
playRound(round);
|
||||
}
|
||||
} else {
|
||||
MultiplayerRound round = createMultiplayerRound();
|
||||
playMultiplayerRound(round);
|
||||
}
|
||||
|
||||
nextStep();
|
||||
}
|
||||
|
||||
|
@ -70,6 +76,8 @@ public abstract class TournamentSwiss extends TournamentImpl {
|
|||
List<TournamentPlayer> roundPlayers = getActivePlayers();
|
||||
boolean isLastRound = (rounds.size() + 1 == getNumberRounds());
|
||||
|
||||
Round round = null;
|
||||
if (options.matchOptions.getNumSeats() == 2) {
|
||||
RoundPairings roundPairings;
|
||||
if (roundPlayers.size() <= 16) {
|
||||
SwissPairingMinimalWeightMatching swissPairing = new SwissPairingMinimalWeightMatching(roundPlayers, rounds, isLastRound);
|
||||
|
@ -79,7 +87,7 @@ public abstract class TournamentSwiss extends TournamentImpl {
|
|||
roundPairings = swissPairing.getRoundPairings();
|
||||
}
|
||||
|
||||
Round round = new Round(rounds.size() + 1, this);
|
||||
round = new Round(rounds.size() + 1, this);
|
||||
rounds.add(round);
|
||||
for (TournamentPairing pairing : roundPairings.getPairings()) {
|
||||
round.addPairing(pairing);
|
||||
|
@ -95,8 +103,33 @@ public abstract class TournamentSwiss extends TournamentImpl {
|
|||
playerBye.setStateInfo("Round Bye");
|
||||
updateResults();
|
||||
}
|
||||
}
|
||||
|
||||
return round;
|
||||
}
|
||||
|
||||
public MultiplayerRound createMultiplayerRound() {
|
||||
List<TournamentPlayer> roundPlayers = getActivePlayers();
|
||||
boolean isLastRound = (rounds.size() + 1 == getNumberRounds());
|
||||
|
||||
MultiplayerRound round = null;
|
||||
if (options.matchOptions.getNumSeats() > 2) {
|
||||
RoundPairings roundPairings;
|
||||
if (roundPlayers.size() <= 16) {
|
||||
SwissPairingMinimalWeightMatching swissPairing = new SwissPairingMinimalWeightMatching(roundPlayers, rounds, isLastRound);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
} else {
|
||||
SwissPairingSimple swissPairing = new SwissPairingSimple(roundPlayers, rounds);
|
||||
roundPairings = swissPairing.getRoundPairings();
|
||||
}
|
||||
|
||||
round = new MultiplayerRound(rounds.size() + 1, this, options.matchOptions.getNumSeats());
|
||||
for (TournamentPairing pairing : roundPairings.getPairings()) {
|
||||
round.addPairing(pairing);
|
||||
}
|
||||
|
||||
}
|
||||
return round;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2870,7 +2870,7 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
for (Mode mode : option.getModes().values()) {
|
||||
Ability newOption = option.copy();
|
||||
newOption.getModes().getSelectedModes().clear();
|
||||
newOption.getModes().getSelectedModes().add(mode);
|
||||
newOption.getModes().getSelectedModes().add(mode.getId());
|
||||
newOption.getModes().setActiveMode(mode);
|
||||
if (newOption.getTargets().getUnchosen().size() > 0) {
|
||||
if (newOption.getManaCosts().getVariableCosts().size() > 0) {
|
||||
|
|
|
@ -25,10 +25,13 @@
|
|||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package mage.target.common;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.Ability;
|
||||
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetPermanent;
|
||||
|
||||
/**
|
||||
|
@ -38,7 +41,7 @@ import mage.target.TargetPermanent;
|
|||
public class TargetCreatureOrPlaneswalker extends TargetPermanent {
|
||||
|
||||
public TargetCreatureOrPlaneswalker() {
|
||||
this(1, 1 ,new FilterCreatureOrPlaneswalkerPermanent(), false);
|
||||
this(1, 1, new FilterCreatureOrPlaneswalkerPermanent(), false);
|
||||
}
|
||||
|
||||
public TargetCreatureOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterCreatureOrPlaneswalkerPermanent filter, boolean notTarget) {
|
||||
|
@ -55,4 +58,16 @@ public class TargetCreatureOrPlaneswalker extends TargetPermanent {
|
|||
return new TargetCreatureOrPlaneswalker(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLegal(Ability source, Game game) {
|
||||
for (UUID playerId : targets.keySet()) {
|
||||
Player targetPlayer = game.getPlayer(playerId);
|
||||
if (targetPlayer != null) {
|
||||
// there seems to be no possibility to add more predicates for theplayer so return here true
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.isLegal(source, game); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public class TargetAddress {
|
|||
|
||||
protected Iterator<SpellAbility> spellAbilityIterator;
|
||||
protected Integer lastSpellAbilityIndex = null;
|
||||
protected Iterator<Mode> modeIterator = null;
|
||||
protected Iterator<UUID> modeIterator = null;
|
||||
protected Modes modes = null;
|
||||
protected UUID lastMode = null;
|
||||
protected Iterator<Target> targetIterator = null;
|
||||
|
@ -127,7 +127,7 @@ public class TargetAddress {
|
|||
}
|
||||
|
||||
if (modeIterator != null && modeIterator.hasNext()) {
|
||||
lastMode = modeIterator.next().getId();
|
||||
lastMode = modeIterator.next();
|
||||
targetIterator = modes.get(lastMode).getTargets().iterator();
|
||||
} else {
|
||||
lastMode = null;
|
||||
|
|
|
@ -102,6 +102,9 @@ git log 79f8617cd3c997d89770094d7a44294b0a48731f..head --diff-filter=A --name-st
|
|||
since 1.4.15v2
|
||||
git log d9c804602ea116d80a74d53eaf07ee7a15cd7d81..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||
|
||||
since 1.4.15v5
|
||||
git log 73a2ccda9b36552a09cb2b6a5aef37559866d7fc..head --diff-filter=A --name-status | sed -ne "s/^A[^u]Mage.Sets\/src\/mage\/sets\///p" | sort > added_cards.txt
|
||||
|
||||
3. Copy added_cards.txt to trunk\Utils folder
|
||||
4. Run script:
|
||||
> perl extract_in_wiki_format.perl
|
||||
|
|
Loading…
Reference in a new issue