Closed #169: Make it possible to untap lands

This commit is contained in:
magenoxx 2013-03-29 20:35:16 +04:00
parent dd9aec6a49
commit 29b84e0d92
24 changed files with 244 additions and 207 deletions

View file

@ -43,7 +43,6 @@ import mage.client.util.gui.ArrowBuilder;
import mage.remote.Session; import mage.remote.Session;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.io.Serializable; import java.io.Serializable;
@ -117,6 +116,7 @@ public class FeedbackPanel extends javax.swing.JPanel {
this.btnRight.setVisible(true); this.btnRight.setVisible(true);
this.btnRight.setText("Cancel"); this.btnRight.setText("Cancel");
this.helper.setState("", false, "Cancel", true); this.helper.setState("", false, "Cancel", true);
this.helper.setUndoEnabled(false);
break; break;
case SELECT: case SELECT:
this.btnLeft.setVisible(false); this.btnLeft.setVisible(false);
@ -149,7 +149,7 @@ public class FeedbackPanel extends javax.swing.JPanel {
this.revalidate(); this.revalidate();
this.repaint(); this.repaint();
this.helper.setLinks(btnLeft, btnRight, btnSpecial); this.helper.setLinks(btnLeft, btnRight, btnSpecial, btnUndo);
this.helper.setVisible(true); this.helper.setVisible(true);
} }
@ -205,7 +205,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
} }
public void clear() { public void clear() {
// stopModal();
this.btnLeft.setVisible(false); this.btnLeft.setVisible(false);
this.btnRight.setVisible(false); this.btnRight.setVisible(false);
this.btnSpecial.setVisible(false); this.btnSpecial.setVisible(false);
@ -213,138 +212,14 @@ public class FeedbackPanel extends javax.swing.JPanel {
logger.debug("feedback - clear"); logger.debug("feedback - clear");
} }
// public void clear0() {
// stopModal();
// }
// private synchronized void startModal() {
//
// try {
// if (SwingUtilities.isEventDispatchThread()) {
// EventQueue theQueue = getToolkit().getSystemEventQueue();
// while (!selected) {
// AWTEvent event = theQueue.getNextEvent();
// Object source = event.getSource();
// boolean dispatch = true;
//
// if (event instanceof MouseEvent) {
// MouseEvent e = (MouseEvent) event;
// MouseEvent m = SwingUtilities.convertMouseEvent((Component) e.getSource(), e, this);
// if (!this.contains(m.getPoint()) && e.getID() != MouseEvent.MOUSE_DRAGGED) {
// dispatch = false;
// }
// }
//
// if (dispatch) {
// if (event instanceof ActiveEvent) {
// ((ActiveEvent) event).dispatch();
// } else if (source instanceof Component) {
// ((Component) source).dispatchEvent(event);
// } else if (source instanceof MenuComponent) {
// ((MenuComponent) source).dispatchEvent(event);
// } else {
// logger.warn("Unable to dispatch: " + event);
// }
// }
// }
// } else {
// while (!selected) {
// wait();
// }
// }
// } catch (InterruptedException ignored) {
// }
//
// }
//
// private synchronized void stopModal() {
// notifyAll();
// }
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
btnRight = new javax.swing.JButton();
btnLeft = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane();
//lblMessage = new javax.swing.JTextArea();
lblMessage = new MageTextArea();
btnSpecial = new javax.swing.JButton();
setBackground(new java.awt.Color(255,255,255,200));
btnRight.setText("Cancel");
btnRight.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnRightActionPerformed(evt);
}
});
btnLeft.setText("OK");
btnLeft.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnLeftActionPerformed(evt);
}
});
jScrollPane1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jScrollPane1.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
//lblMessage.setBackground(new java.awt.Color(204, 204, 204));
/*lblMessage.setColumns(20);
lblMessage.setEditable(false);
lblMessage.setLineWrap(true);
lblMessage.setRows(2);
lblMessage.setWrapStyleWord(true);*/
lblMessage.setBorder(null);
jScrollPane1.setViewportView(lblMessage);
jScrollPane1.setBorder(null);
btnSpecial.setText("Special");
btnSpecial.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnSpecialActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addContainerGap()
.addComponent(btnSpecial)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 31, Short.MAX_VALUE)
.addComponent(btnLeft)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnRight))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 224, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 81, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnRight)
.addComponent(btnLeft)
.addComponent(btnSpecial)))
);
}// </editor-fold>//GEN-END:initComponents
public void customInitComponents() { public void customInitComponents() {
btnRight = new javax.swing.JButton(); btnRight = new javax.swing.JButton();
btnLeft = new javax.swing.JButton(); btnLeft = new javax.swing.JButton();
jScrollPane1 = new javax.swing.JScrollPane(); jScrollPane1 = new javax.swing.JScrollPane();
lblMessage = new MageTextArea(); lblMessage = new MageTextArea();
btnSpecial = new javax.swing.JButton(); btnSpecial = new javax.swing.JButton();
btnUndo = new javax.swing.JButton();
btnUndo.setVisible(true);
setBackground(new java.awt.Color(0,0,0,80)); setBackground(new java.awt.Color(0,0,0,80));
@ -379,26 +254,18 @@ public class FeedbackPanel extends javax.swing.JPanel {
} }
}); });
JLabel jlabel = new JLabel(); btnUndo.setText("Undo");
jlabel.setLayout(new BorderLayout()); btnUndo.addActionListener(new java.awt.event.ActionListener() {
jlabel.add(jScrollPane1, BorderLayout.CENTER); @Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnUndoActionPerformed(evt);
}
});
setLayout(new BorderLayout());
JLabel jlabel2 = new JLabel();
jlabel2.setLayout(new FlowLayout());
jlabel2.add(btnSpecial);
jlabel2.add(btnLeft);
jlabel2.add(btnRight);
jlabel2.setPreferredSize(new Dimension(0, 35));
add(jlabel, BorderLayout.CENTER);
add(jlabel2, BorderLayout.PAGE_END);
} }
private void btnRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRightActionPerformed private void btnRightActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnRightActionPerformed
this.selected = true; this.selected = true;
// clear0();
if (connectedDialog != null) { if (connectedDialog != null) {
connectedDialog.hideDialog(); connectedDialog.hideDialog();
} }
@ -414,7 +281,6 @@ public class FeedbackPanel extends javax.swing.JPanel {
private void btnLeftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLeftActionPerformed private void btnLeftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLeftActionPerformed
this.selected = true; this.selected = true;
// clear0();
session.sendPlayerBoolean(gameId, true); session.sendPlayerBoolean(gameId, true);
AudioManager.playButtonCancel(); AudioManager.playButtonCancel();
}//GEN-LAST:event_btnLeftActionPerformed }//GEN-LAST:event_btnLeftActionPerformed
@ -423,6 +289,10 @@ public class FeedbackPanel extends javax.swing.JPanel {
session.sendPlayerString(gameId, "special"); session.sendPlayerString(gameId, "special");
}//GEN-LAST:event_btnSpecialActionPerformed }//GEN-LAST:event_btnSpecialActionPerformed
private void btnUndoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnSpecialActionPerformed
session.undo(gameId);
}
public void setHelperPanel(HelperPanel helper) { public void setHelperPanel(HelperPanel helper) {
this.helper = helper; this.helper = helper;
} }
@ -443,9 +313,18 @@ public class FeedbackPanel extends javax.swing.JPanel {
} }
} }
public void allowUndo(int bookmark) {
this.helper.setUndoEnabled(true);
}
public void disableUndo() {
this.helper.setUndoEnabled(false);
}
private javax.swing.JButton btnLeft; private javax.swing.JButton btnLeft;
private javax.swing.JButton btnRight; private javax.swing.JButton btnRight;
private javax.swing.JButton btnSpecial; private javax.swing.JButton btnSpecial;
private javax.swing.JButton btnUndo;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
//private javax.swing.JTextArea lblMessage; //private javax.swing.JTextArea lblMessage;
private MageTextArea lblMessage; private MageTextArea lblMessage;

View file

@ -490,6 +490,14 @@ public final class GamePanel extends javax.swing.JPanel {
} else { } else {
CombatManager.getInstance().hideCombat(gameId); CombatManager.getInstance().hideCombat(gameId);
} }
System.out.println("Size: " + game.getStatesSavedSize());
if (game.getStatesSavedSize() > 0) {
feedbackPanel.allowUndo(game.getStatesSavedSize());
} else {
feedbackPanel.disableUndo();
}
this.revalidate(); this.revalidate();
this.repaint(); this.repaint();
} }

View file

@ -29,10 +29,11 @@
package mage.client.game; package mage.client.game;
import java.awt.*;
import javax.swing.*;
import mage.client.components.MageTextArea; import mage.client.components.MageTextArea;
import javax.swing.*;
import java.awt.*;
/** /**
* Panel with buttons that copy the state of feedback panel. * Panel with buttons that copy the state of feedback panel.
* *
@ -43,6 +44,7 @@ public class HelperPanel extends JPanel {
private javax.swing.JButton btnLeft; private javax.swing.JButton btnLeft;
private javax.swing.JButton btnRight; private javax.swing.JButton btnRight;
private javax.swing.JButton btnSpecial; private javax.swing.JButton btnSpecial;
private javax.swing.JButton btnUndo;
//private javax.swing.JButton btnEndTurn; //private javax.swing.JButton btnEndTurn;
//private javax.swing.JButton btnStopTimer; //private javax.swing.JButton btnStopTimer;
@ -52,6 +54,7 @@ public class HelperPanel extends JPanel {
private javax.swing.JButton linkLeft; private javax.swing.JButton linkLeft;
private javax.swing.JButton linkRight; private javax.swing.JButton linkRight;
private javax.swing.JButton linkSpecial; private javax.swing.JButton linkSpecial;
private javax.swing.JButton linkUndo;
public HelperPanel() { public HelperPanel() {
initComponents(); initComponents();
@ -89,6 +92,9 @@ public class HelperPanel extends JPanel {
btnRight = new JButton("Cancel"); btnRight = new JButton("Cancel");
btnRight.setVisible(false); btnRight.setVisible(false);
container.add(btnRight); container.add(btnRight);
btnUndo = new JButton("Undo");
btnUndo.setVisible(false);
container.add(btnUndo);
btnLeft.addActionListener(new java.awt.event.ActionListener() { btnLeft.addActionListener(new java.awt.event.ActionListener() {
@Override @Override
@ -122,6 +128,15 @@ public class HelperPanel extends JPanel {
}} }}
} }
}); });
btnUndo.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
if (linkUndo != null) {{
linkUndo.doClick();
}}
}
});
} }
public void setState(String txtLeft, boolean leftVisible, String txtRight, boolean rightVisible) { public void setState(String txtLeft, boolean leftVisible, String txtRight, boolean rightVisible) {
@ -140,6 +155,10 @@ public class HelperPanel extends JPanel {
this.btnSpecial.setText(txtSpecial); this.btnSpecial.setText(txtSpecial);
} }
public void setUndoEnabled(boolean enabled) {
this.btnUndo.setVisible(enabled);
}
public void setRight(String txtRight, boolean rightVisible) { public void setRight(String txtRight, boolean rightVisible) {
this.btnRight.setVisible(rightVisible); this.btnRight.setVisible(rightVisible);
if (!txtRight.isEmpty()) { if (!txtRight.isEmpty()) {
@ -147,10 +166,11 @@ public class HelperPanel extends JPanel {
} }
} }
public void setLinks(JButton left, JButton right, JButton special) { public void setLinks(JButton left, JButton right, JButton special, JButton undo) {
this.linkLeft = left; this.linkLeft = left;
this.linkRight = right; this.linkRight = right;
this.linkSpecial = special; this.linkSpecial = special;
this.linkUndo = undo;
} }
public void setMessage(String message) { public void setMessage(String message) {

View file

@ -100,6 +100,7 @@ public interface MageServer {
void sendPlayerBoolean(UUID gameId, String sessionId, Boolean data) throws MageException; void sendPlayerBoolean(UUID gameId, String sessionId, Boolean data) throws MageException;
void sendPlayerInteger(UUID gameId, String sessionId, Integer data) throws MageException; void sendPlayerInteger(UUID gameId, String sessionId, Integer data) throws MageException;
void concedeGame(UUID gameId, String sessionId) throws MageException; void concedeGame(UUID gameId, String sessionId) throws MageException;
void undo(UUID gameId, String sessionId) throws MageException;
GameView getGameView(UUID gameId, String sessionId, UUID playerId) throws MageException; GameView getGameView(UUID gameId, String sessionId, UUID playerId) throws MageException;
//priority methods //priority methods

View file

@ -929,6 +929,21 @@ public class SessionImpl implements Session {
return false; return false;
} }
@Override
public boolean undo(UUID gameId) {
try {
if (isConnected()) {
server.undo(gameId, sessionId);
return true;
}
} catch (MageException ex) {
handleMageException(ex);
} catch (Throwable t) {
handleThrowable(t);
}
return false;
}
@Override @Override
public boolean passPriorityUntilNextYourTurn(UUID gameId) { public boolean passPriorityUntilNextYourTurn(UUID gameId) {
try { try {

View file

@ -59,6 +59,8 @@ public interface GamePlay {
DraftPickView sendCardPick(UUID draftId, UUID cardId); DraftPickView sendCardPick(UUID draftId, UUID cardId);
boolean undo(UUID gameId);
/*** Separate methods for priority handling ***/ /*** Separate methods for priority handling ***/
/** /**
* magenoxx: * magenoxx:

View file

@ -74,10 +74,17 @@ public class GameView implements Serializable {
private String priorityPlayerName = ""; private String priorityPlayerName = "";
private int turn; private int turn;
private boolean special = false; private boolean special = false;
private int statesSavedSize;
public GameView(GameState state, Game game) { public GameView(GameState state, Game game) {
for (Player player: state.getPlayers().values()) { for (Player player: state.getPlayers().values()) {
players.add(new PlayerView(player, state, game)); players.add(new PlayerView(player, state, game));
if (player.getStoredBookmark() > 0) {
if (this.statesSavedSize > 0) {
throw new IllegalStateException("This shouldn't happen");
}
this.statesSavedSize = player.getStoredBookmark();
}
} }
for (StackObject stackObject: state.getStack()) { for (StackObject stackObject: state.getStack()) {
if (stackObject instanceof StackAbility) { if (stackObject instanceof StackAbility) {
@ -254,7 +261,7 @@ public class GameView implements Serializable {
return special; return special;
} }
/*public List<UUID> getStackOrder() { public int getStatesSavedSize() {
return stackOrder; return statesSavedSize;
}*/ }
} }

View file

@ -27,9 +27,6 @@
*/ */
package mage.player.ai; package mage.player.ai;
import java.io.File;
import java.util.*;
import java.util.concurrent.*;
import mage.Constants.Outcome; import mage.Constants.Outcome;
import mage.Constants.PhaseStep; import mage.Constants.PhaseStep;
import mage.Constants.RangeOfInfluence; import mage.Constants.RangeOfInfluence;
@ -62,6 +59,10 @@ import mage.target.Target;
import mage.target.TargetCard; import mage.target.TargetCard;
import mage.target.Targets; import mage.target.Targets;
import java.io.File;
import java.util.*;
import java.util.concurrent.*;
/** /**
* *
@ -132,7 +133,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
switch (game.getTurn().getStepType()) { switch (game.getTurn().getStepType()) {
case UPKEEP: case UPKEEP:
case DRAW: case DRAW:
pass(); pass(game);
return false; return false;
case PRECOMBAT_MAIN: case PRECOMBAT_MAIN:
case POSTCOMBAT_MAIN: case POSTCOMBAT_MAIN:
@ -146,36 +147,36 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
act(game); act(game);
return true; return true;
} else { } else {
pass(); pass(game);
} }
return false; return false;
case BEGIN_COMBAT: case BEGIN_COMBAT:
case FIRST_COMBAT_DAMAGE: case FIRST_COMBAT_DAMAGE:
case COMBAT_DAMAGE: case COMBAT_DAMAGE:
case END_COMBAT: case END_COMBAT:
pass(); pass(game);
return false; return false;
case DECLARE_ATTACKERS: case DECLARE_ATTACKERS:
if (game.getActivePlayerId().equals(playerId)) { if (game.getActivePlayerId().equals(playerId)) {
//declareAttackers(game, playerId); //declareAttackers(game, playerId);
pass(); pass(game);
} else { } else {
pass(); pass(game);
} }
return false; return false;
case DECLARE_BLOCKERS: case DECLARE_BLOCKERS:
if (!game.getActivePlayerId().equals(playerId)) { if (!game.getActivePlayerId().equals(playerId)) {
declareBlockers(game, playerId); declareBlockers(game, playerId);
pass(); pass(game);
} else { } else {
pass(); pass(game);
} }
return false; return false;
case END_TURN: case END_TURN:
pass(); pass(game);
return false; return false;
case CLEANUP: case CLEANUP:
pass(); pass(game);
return false; return false;
} }
return false; return false;
@ -222,7 +223,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
protected void act(Game game) { protected void act(Game game) {
if (actions == null || actions.size() == 0) { if (actions == null || actions.size() == 0) {
pass(); pass(game);
} else { } else {
boolean usedStack = false; boolean usedStack = false;
while (actions.peek() != null) { while (actions.peek() != null) {
@ -257,7 +258,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
} }
if (usedStack) { if (usedStack) {
pass(); pass(game);
} }
} }
} }
@ -536,7 +537,7 @@ public class ComputerPlayer6 extends ComputerPlayer<ComputerPlayer6> implements
} }
if (!sim.isGameOver() && action.isUsesStack()) { if (!sim.isGameOver() && action.isUsesStack()) {
// only pass if the last action uses the stack // only pass if the last action uses the stack
sim.getPlayer(currentPlayer.getId()).pass(); sim.getPlayer(currentPlayer.getId()).pass(game);
sim.getPlayerList().getNext(); sim.getPlayerList().getNext();
} }
SimulationNode2 newNode = new SimulationNode2(node, sim, action, depth, currentPlayer.getId()); SimulationNode2 newNode = new SimulationNode2(node, sim, action, depth, currentPlayer.getId());

View file

@ -28,7 +28,6 @@
package mage.player.ai; package mage.player.ai;
import java.util.*;
import mage.Constants; import mage.Constants;
import mage.Constants.RangeOfInfluence; import mage.Constants.RangeOfInfluence;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -40,6 +39,10 @@ import mage.game.turn.*;
import mage.players.Player; import mage.players.Player;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
/** /**
* *
@ -77,7 +80,7 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
switch (game.getTurn().getStepType()) { switch (game.getTurn().getStepType()) {
case UPKEEP: case UPKEEP:
case DRAW: case DRAW:
pass(); pass(game);
return false; return false;
case PRECOMBAT_MAIN: case PRECOMBAT_MAIN:
if (game.getActivePlayerId().equals(playerId)) { if (game.getActivePlayerId().equals(playerId)) {
@ -89,11 +92,11 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
return true; return true;
} }
else { else {
pass(); pass(game);
} }
return false; return false;
case BEGIN_COMBAT: case BEGIN_COMBAT:
pass(); pass(game);
return false; return false;
case DECLARE_ATTACKERS: case DECLARE_ATTACKERS:
if (!game.getActivePlayerId().equals(playerId)) { if (!game.getActivePlayerId().equals(playerId)) {
@ -105,14 +108,14 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
return true; return true;
} }
else { else {
pass(); pass(game);
} }
return false; return false;
case DECLARE_BLOCKERS: case DECLARE_BLOCKERS:
case FIRST_COMBAT_DAMAGE: case FIRST_COMBAT_DAMAGE:
case COMBAT_DAMAGE: case COMBAT_DAMAGE:
case END_COMBAT: case END_COMBAT:
pass(); pass(game);
return false; return false;
case POSTCOMBAT_MAIN: case POSTCOMBAT_MAIN:
// if (game.getActivePlayerId().equals(playerId)) { // if (game.getActivePlayerId().equals(playerId)) {
@ -124,13 +127,13 @@ public class ComputerPlayer7 extends ComputerPlayer6 implements Player {
return true; return true;
// } // }
// else { // else {
// pass(); // pass(game);
// } // }
// return false; // return false;
case END_TURN: case END_TURN:
case CLEANUP: case CLEANUP:
actionCache.clear(); actionCache.clear();
pass(); pass(game);
return false; return false;
} }
return false; return false;

View file

@ -721,7 +721,7 @@ public class ComputerPlayer<T extends ComputerPlayer<T>> extends PlayerImpl<T> i
break; break;
} }
} }
pass(); pass(game);
return true; return true;
} }

View file

@ -106,7 +106,7 @@ public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements
switch (game.getTurn().getStepType()) { switch (game.getTurn().getStepType()) {
case UPKEEP: case UPKEEP:
case DRAW: case DRAW:
pass(); pass(game);
return false; return false;
case PRECOMBAT_MAIN: case PRECOMBAT_MAIN:
case BEGIN_COMBAT: case BEGIN_COMBAT:
@ -123,7 +123,7 @@ public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements
return true; return true;
case END_TURN: case END_TURN:
case CLEANUP: case CLEANUP:
pass(); pass(game);
return false; return false;
} }
return false; return false;
@ -131,7 +131,7 @@ public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements
protected void act(Game game) { protected void act(Game game) {
if (actions == null || actions.size() == 0) if (actions == null || actions.size() == 0)
pass(); pass(game);
else { else {
boolean usedStack = false; boolean usedStack = false;
while (actions.peek() != null) { while (actions.peek() != null) {
@ -143,7 +143,7 @@ public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements
usedStack = true; usedStack = true;
} }
if (usedStack) if (usedStack)
pass(); pass(game);
} }
logger.info("Turn " + game.getTurnNum() + " Step " + game.getStep().toString() + " Player " + name + " Life " + life); logger.info("Turn " + game.getTurnNum() + " Step " + game.getStep().toString() + " Player " + name + " Life " + life);
} }
@ -405,7 +405,7 @@ public class ComputerPlayer2 extends ComputerPlayer<ComputerPlayer2> implements
} }
if (!sim.isGameOver() && action.isUsesStack()) { if (!sim.isGameOver() && action.isUsesStack()) {
// only pass if the last action uses the stack // only pass if the last action uses the stack
sim.getPlayer(currentPlayer.getId()).pass(); sim.getPlayer(currentPlayer.getId()).pass(game);
sim.getPlayerList().getNext(); sim.getPlayerList().getNext();
} }
SimulationNode newNode = new SimulationNode(node, sim, action, currentPlayer.getId()); SimulationNode newNode = new SimulationNode(node, sim, action, currentPlayer.getId());

View file

@ -74,7 +74,7 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
switch (game.getTurn().getStepType()) { switch (game.getTurn().getStepType()) {
case UPKEEP: case UPKEEP:
case DRAW: case DRAW:
pass(); pass(game);
return false; return false;
case PRECOMBAT_MAIN: case PRECOMBAT_MAIN:
if (game.getActivePlayerId().equals(playerId)) { if (game.getActivePlayerId().equals(playerId)) {
@ -85,10 +85,10 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
return true; return true;
} }
else else
pass(); pass(game);
return false; return false;
case BEGIN_COMBAT: case BEGIN_COMBAT:
pass(); pass(game);
return false; return false;
case DECLARE_ATTACKERS: case DECLARE_ATTACKERS:
if (!game.getActivePlayerId().equals(playerId)) { if (!game.getActivePlayerId().equals(playerId)) {
@ -99,13 +99,13 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
return true; return true;
} }
else else
pass(); pass(game);
return false; return false;
case DECLARE_BLOCKERS: case DECLARE_BLOCKERS:
case FIRST_COMBAT_DAMAGE: case FIRST_COMBAT_DAMAGE:
case COMBAT_DAMAGE: case COMBAT_DAMAGE:
case END_COMBAT: case END_COMBAT:
pass(); pass(game);
return false; return false;
case POSTCOMBAT_MAIN: case POSTCOMBAT_MAIN:
if (game.getActivePlayerId().equals(playerId)) { if (game.getActivePlayerId().equals(playerId)) {
@ -116,11 +116,11 @@ public class ComputerPlayer3 extends ComputerPlayer2 implements Player {
return true; return true;
} }
else else
pass(); pass(game);
return false; return false;
case END_TURN: case END_TURN:
case CLEANUP: case CLEANUP:
pass(); pass(game);
return false; return false;
} }
return false; return false;

View file

@ -391,24 +391,24 @@ public class HumanPlayer extends PlayerImpl<HumanPlayer> {
passed = false; passed = false;
if (!abort) { if (!abort) {
if (passedAllTurns) { if (passedAllTurns) {
pass(); pass(game);
return false; return false;
} }
if (passedTurn && game.getStack().isEmpty()) { if (passedTurn && game.getStack().isEmpty()) {
pass(); pass(game);
return false; return false;
} }
updateGameStatePriority("priority", game); updateGameStatePriority("priority", game);
game.firePriorityEvent(playerId); game.firePriorityEvent(playerId);
waitForResponse(); waitForResponse();
if (response.getBoolean() != null) { if (response.getBoolean() != null) {
pass(); pass(game);
return false; return false;
} else if (response.getInteger() != null) { } else if (response.getInteger() != null) {
/*if (response.getInteger() == -9999) { /*if (response.getInteger() == -9999) {
passedAllTurns = true; passedAllTurns = true;
}*/ }*/
pass(); pass(game);
//passedTurn = true; //passedTurn = true;
return false; return false;
} else if (response.getString() != null && response.getString().equals("special")) { } else if (response.getString() != null && response.getString().equals("special")) {

View file

@ -570,6 +570,17 @@ public class MageServerImpl implements MageServer {
}); });
} }
@Override
public void undo(final UUID gameId, final String sessionId) throws MageException {
execute("undo", sessionId, new Action() {
@Override
public void execute() {
UUID userId = SessionManager.getInstance().getSession(sessionId).getUserId();
GameManager.getInstance().undo(gameId, userId);
}
});
}
@Override @Override
public void passPriorityUntilNextYourTurn(final UUID gameId, final String sessionId) throws MageException { public void passPriorityUntilNextYourTurn(final UUID gameId, final String sessionId) throws MageException {
execute("passPriorityUntilNextYourTurn", sessionId, new Action() { execute("passPriorityUntilNextYourTurn", sessionId, new Action() {

View file

@ -255,6 +255,10 @@ public class GameController implements GameCallback {
game.concede(getPlayerId(userId)); game.concede(getPlayerId(userId));
} }
public void undo(UUID userId) {
game.undo(getPlayerId(userId));
}
public void passPriorityUntilNextYourTurn(UUID userId) { public void passPriorityUntilNextYourTurn(UUID userId) {
game.passPriorityUntilNextYourTurn(getPlayerId(userId)); game.passPriorityUntilNextYourTurn(getPlayerId(userId));
} }

View file

@ -96,6 +96,11 @@ public class GameManager {
gameControllers.get(gameId).concede(userId); gameControllers.get(gameId).concede(userId);
} }
public void undo(UUID gameId, UUID userId) {
if (gameControllers.containsKey(gameId))
gameControllers.get(gameId).undo(userId);
}
public void passPriorityUntilNextYourTurn(UUID gameId, UUID userId) { public void passPriorityUntilNextYourTurn(UUID gameId, UUID userId) {
if (gameControllers.containsKey(gameId)) if (gameControllers.containsKey(gameId))
gameControllers.get(gameId).passPriorityUntilNextYourTurn(userId); gameControllers.get(gameId).passPriorityUntilNextYourTurn(userId);

View file

@ -45,6 +45,7 @@ import mage.player.ai.ComputerPlayer;
import mage.players.Player; import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanentAmount;
import org.junit.Ignore; import org.junit.Ignore;
import java.io.Serializable; import java.io.Serializable;
@ -52,7 +53,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import mage.target.common.TargetCreaturePermanentAmount;
/** /**
* *
@ -124,7 +124,7 @@ public class TestPlayer extends ComputerPlayer<TestPlayer> {
} }
} }
} }
pass(); pass(game);
return false; return false;
} }

View file

@ -51,7 +51,7 @@ public class PassEffect extends OneShotEffect<PassEffect> {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
player.pass(); player.pass(game);
return true; return true;
} }

View file

@ -164,6 +164,7 @@ public interface Game extends MageItem, Serializable {
void mulligan(UUID playerId); void mulligan(UUID playerId);
void quit(UUID playerId); void quit(UUID playerId);
void concede(UUID playerId); void concede(UUID playerId);
void undo(UUID playerId);
void emptyManaPools(); void emptyManaPools();
void addEffect(ContinuousEffect continuousEffect, Ability source); void addEffect(ContinuousEffect continuousEffect, Ability source);
void addEmblem(Emblem emblem, Ability source); void addEmblem(Emblem emblem, Ability source);
@ -200,6 +201,7 @@ public interface Game extends MageItem, Serializable {
int bookmarkState(); int bookmarkState();
void restoreState(int bookmark); void restoreState(int bookmark);
void removeBookmark(int bookmark); void removeBookmark(int bookmark);
int getSavedStateSize();
// game options // game options
void setGameOptions(GameOptions options); void setGameOptions(GameOptions options);

View file

@ -420,7 +420,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
savedStates.push(gameStates.getSize() - 1); savedStates.push(gameStates.getSize() - 1);
return savedStates.size(); return savedStates.size();
} }
return 0; return savedStates.size();
} }
@Override @Override
@ -444,10 +444,31 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
while (savedStates.size() > bookmark) { while (savedStates.size() > bookmark) {
savedStates.pop(); savedStates.pop();
} }
gameStates.remove(bookmark);
} }
} }
} }
private void clearAllBookmarks() {
if (!simulation) {
while (!savedStates.isEmpty()) {
savedStates.pop();
}
gameStates.remove(0);
for (Player player : getPlayers().values()) {
player.setStoredBookmark(-1);
}
}
}
@Override
public int getSavedStateSize() {
if (!simulation) {
return savedStates.size();
}
return 0;
}
@Override @Override
public void start(UUID choosingPlayerId) { public void start(UUID choosingPlayerId) {
start(choosingPlayerId, this.gameOptions != null ? gameOptions : GameOptions.getDefault()); start(choosingPlayerId, this.gameOptions != null ? gameOptions : GameOptions.getDefault());
@ -721,6 +742,19 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
} }
} }
@Override
public synchronized void undo(UUID playerId) {
Player player = state.getPlayer(playerId);
if (player != null) {
int bookmark = player.getStoredBookmark();
if (bookmark != -1) {
restoreState(bookmark);
player.setStoredBookmark(-1);
fireUpdatePlayersEvent();
}
}
}
@Override @Override
public synchronized void passPriorityUntilNextYourTurn(UUID playerId) { public synchronized void passPriorityUntilNextYourTurn(UUID playerId) {
Player player = state.getPlayer(playerId); Player player = state.getPlayer(playerId);
@ -748,6 +782,7 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
@Override @Override
public void playPriority(UUID activePlayerId, boolean resuming) { public void playPriority(UUID activePlayerId, boolean resuming) {
int bookmark = 0; int bookmark = 0;
clearAllBookmarks();
try { try {
while (!isPaused() && !isGameOver()) { while (!isPaused() && !isGameOver()) {
if (!resuming) { if (!resuming) {

View file

@ -28,10 +28,11 @@
package mage.game; package mage.game;
import org.apache.log4j.Logger;
import java.io.Serializable; import java.io.Serializable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import org.apache.log4j.Logger;
/** /**
* *
@ -66,6 +67,15 @@ public class GameStates implements Serializable {
return null; return null;
} }
public int remove(int index) {
if (states.size() > 0 && index < states.size()) {
while (states.size() > index && states.size() > 0) {
states.remove(states.size() - 1);
}
}
return states.size();
}
public GameState get(int index) { public GameState get(int index) {
if (index < states.size()) if (index < states.size())
// return new Copier<GameState>().uncompressCopy(states.get(index)); // return new Copier<GameState>().uncompressCopy(states.get(index));

View file

@ -28,17 +28,18 @@
package mage.game.turn; package mage.game.turn;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import mage.Constants.PhaseStep; import mage.Constants.PhaseStep;
import mage.Constants.TurnPhase; import mage.Constants.TurnPhase;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.players.Player; import mage.players.Player;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
/** /**
* *
@ -161,7 +162,7 @@ public class Turn implements Serializable {
if (phase.resumePlay(game, stepType, wasPaused)) { if (phase.resumePlay(game, stepType, wasPaused)) {
//20091005 - 500.4/703.4n //20091005 - 500.4/703.4n
game.emptyManaPools(); game.emptyManaPools();
game.saveState(); //game.saveState();
//20091005 - 500.8 //20091005 - 500.8
playExtraPhases(game, phase.getType()); playExtraPhases(game, phase.getType());
} }
@ -175,7 +176,7 @@ public class Turn implements Serializable {
if (phase.play(game, activePlayerId)) { if (phase.play(game, activePlayerId)) {
//20091005 - 500.4/703.4n //20091005 - 500.4/703.4n
game.emptyManaPools(); game.emptyManaPools();
game.saveState(); //game.saveState();
//20091005 - 500.8 //20091005 - 500.8
playExtraPhases(game, phase.getType()); playExtraPhases(game, phase.getType());
} }

View file

@ -94,7 +94,7 @@ public interface Player extends MageItem, Copyable<Player> {
void setMaxHandSize(int maxHandSize); void setMaxHandSize(int maxHandSize);
boolean isPassed(); boolean isPassed();
boolean isEmptyDraw(); boolean isEmptyDraw();
void pass(); void pass(Game game);
void resetPassed(); void resetPassed();
boolean hasLost(); boolean hasLost();
boolean hasWon(); boolean hasWon();
@ -202,6 +202,10 @@ public interface Player extends MageItem, Copyable<Player> {
void passPriorityUntilNextYourTurn(Game game); void passPriorityUntilNextYourTurn(Game game);
void passTurnPriority(Game game); void passTurnPriority(Game game);
void restorePriority(Game game); void restorePriority(Game game);
int getStoredBookmark();
void setStoredBookmark(int bookmark);
void resetStoredBookmark(Game game);
void revealCards(String name, Cards cards, Game game); void revealCards(String name, Cards cards, Game game);
void lookAtCards(String name, Cards cards, Game game); void lookAtCards(String name, Cards cards, Game game);

View file

@ -101,6 +101,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
protected boolean passed; protected boolean passed;
protected boolean passedTurn; protected boolean passedTurn;
protected int turns; protected int turns;
protected int storedBookmark = -1;
/** /**
* This indicates that player passed all turns until his own turn starts. * This indicates that player passed all turns until his own turn starts.
@ -175,6 +176,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
this.userData = player.userData; this.userData = player.userData;
this.canPayLifeCost = player.canPayLifeCost; this.canPayLifeCost = player.canPayLifeCost;
this.canPaySacrificeCost = player.canPaySacrificeCost; this.canPaySacrificeCost = player.canPaySacrificeCost;
this.storedBookmark = player.storedBookmark;
} }
@Override @Override
@ -537,6 +539,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
game.fireEvent(event); game.fireEvent(event);
game.fireInformEvent(name + spellAbility.getActivatedMessage(game)); game.fireInformEvent(name + spellAbility.getActivatedMessage(game));
game.removeBookmark(bookmark); game.removeBookmark(bookmark);
resetStoredBookmark(game);
return true; return true;
} }
game.restoreState(bookmark); game.restoreState(bookmark);
@ -556,6 +559,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), playerId)); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LAND_PLAYED, card.getId(), playerId));
game.fireInformEvent(name + " plays " + card.getName()); game.fireInformEvent(name + " plays " + card.getName());
game.removeBookmark(bookmark); game.removeBookmark(bookmark);
resetStoredBookmark(game);
return true; return true;
} }
game.restoreState(bookmark); game.restoreState(bookmark);
@ -568,7 +572,11 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
int bookmark = game.bookmarkState(); int bookmark = game.bookmarkState();
if (ability.activate(game, false)) { if (ability.activate(game, false)) {
ability.resolve(game); ability.resolve(game);
game.removeBookmark(bookmark); // #169
if (storedBookmark == -1) {
setStoredBookmark(bookmark);
}
//game.removeBookmark(bookmark);
return true; return true;
} }
game.restoreState(bookmark); game.restoreState(bookmark);
@ -587,6 +595,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ACTIVATED_ABILITY, ability.getId(), ability.getSourceId(), playerId)); game.fireEvent(GameEvent.getEvent(GameEvent.EventType.ACTIVATED_ABILITY, ability.getId(), ability.getSourceId(), playerId));
game.fireInformEvent(name + ability.getActivatedMessage(game)); game.fireInformEvent(name + ability.getActivatedMessage(game));
game.removeBookmark(bookmark); game.removeBookmark(bookmark);
resetStoredBookmark(game);
return true; return true;
} }
game.restoreState(bookmark); game.restoreState(bookmark);
@ -596,6 +605,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
if (ability.activate(game, false)) { if (ability.activate(game, false)) {
ability.resolve(game); ability.resolve(game);
game.removeBookmark(bookmark); game.removeBookmark(bookmark);
resetStoredBookmark(game);
return true; return true;
} }
game.restoreState(bookmark); game.restoreState(bookmark);
@ -612,6 +622,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
game.fireInformEvent(name + action.getActivatedMessage(game)); game.fireInformEvent(name + action.getActivatedMessage(game));
if (action.resolve(game)) { if (action.resolve(game)) {
game.removeBookmark(bookmark); game.removeBookmark(bookmark);
resetStoredBookmark(game);
return true; return true;
} }
} }
@ -628,7 +639,7 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
} }
if (ability instanceof PassAbility) { if (ability instanceof PassAbility) {
pass(); pass(game);
return true; return true;
} }
else if (ability instanceof PlayLandAbility) { else if (ability instanceof PlayLandAbility) {
@ -1055,8 +1066,9 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
} }
@Override @Override
public void pass() { public void pass(Game game) {
this.passed = true; this.passed = true;
resetStoredBookmark(game);
} }
@Override @Override
@ -1598,4 +1610,21 @@ public abstract class PlayerImpl<T extends PlayerImpl<T>> implements Player, Ser
return turns; return turns;
} }
@Override
public int getStoredBookmark() {
return storedBookmark;
}
@Override
public void setStoredBookmark(int storedBookmark) {
this.storedBookmark = storedBookmark;
}
@Override
public synchronized void resetStoredBookmark(Game game) {
if (this.storedBookmark != -1) {
game.removeBookmark(this.storedBookmark);
}
setStoredBookmark(-1);
}
} }