summaryrefslogtreecommitdiffstats
path: root/src/jrummikub/control
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2011-06-19 19:46:06 +0200
committerMatthias Schiffer <mschiffer@universe-factory.net>2011-06-19 19:46:06 +0200
commit45656861ab2e618938764f0c46f830184099a71d (patch)
tree8e5cd9ab28d47f242408d6dcfc29317902048605 /src/jrummikub/control
parent9b7aac51f58eb628978ed0e4d1a922a959917a3b (diff)
downloadJRummikub-45656861ab2e618938764f0c46f830184099a71d.tar
JRummikub-45656861ab2e618938764f0c46f830184099a71d.zip
Added NetworkRoundControlTest and started NetworkRoundControl and NetworkTurnControl implementation
git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@491 72836036-5685-4462-b002-a69064685172
Diffstat (limited to 'src/jrummikub/control')
-rw-r--r--src/jrummikub/control/RoundControl.java120
-rw-r--r--src/jrummikub/control/network/ConnectionControl.java69
-rw-r--r--src/jrummikub/control/network/IConnectionControl.java14
-rw-r--r--src/jrummikub/control/network/NetworkRoundControl.java55
-rw-r--r--src/jrummikub/control/network/NetworkTurnControl.java53
-rw-r--r--src/jrummikub/control/turn/AIControl.java6
-rw-r--r--src/jrummikub/control/turn/AbstractTurnControl.java19
-rw-r--r--src/jrummikub/control/turn/HumanTurnControl.java4
-rw-r--r--src/jrummikub/control/turn/ITurnControl.java2
9 files changed, 277 insertions, 65 deletions
diff --git a/src/jrummikub/control/RoundControl.java b/src/jrummikub/control/RoundControl.java
index d8435af..a19a2ab 100644
--- a/src/jrummikub/control/RoundControl.java
+++ b/src/jrummikub/control/RoundControl.java
@@ -8,6 +8,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import jrummikub.control.turn.AIControl;
+import jrummikub.control.turn.HumanTurnControl;
import jrummikub.control.turn.ITurnControl;
import jrummikub.control.turn.TurnControlFactory;
import jrummikub.control.turn.TurnMode;
@@ -16,6 +18,7 @@ import jrummikub.model.IHand;
import jrummikub.model.IPlayer;
import jrummikub.model.IRoundState;
import jrummikub.model.ITable;
+import jrummikub.model.PlayerSettings;
import jrummikub.model.Position;
import jrummikub.model.Score;
import jrummikub.model.Stone;
@@ -35,15 +38,15 @@ import jrummikub.view.IView.BottomPanelType;
* Controller that manages a single round of rummikub
*/
public class RoundControl {
- IRoundState roundState;
+ private ITurnControl turnControl;
+ protected IRoundState roundState;
private IView view;
private ITable clonedTable;
IHand clonedHand;
private Event restartRoundEvent = new Event();
+ private Event1<IRoundState> roundStateUpdateEvent = new Event1<IRoundState>();
private Event1<Score> endOfRoundEvent = new Event1<Score>();
- private Event1<ITable> tableUpdateEvent = new Event1<ITable>();
- private List<Connection> connections = new ArrayList<Connection>();
- private ITurnControl turnControl;
+ protected List<Connection> connections = new ArrayList<Connection>();
private boolean roundFinished;
private boolean lastTurnNotEnoughPoints;
private boolean lastTurnMeldError;
@@ -61,6 +64,10 @@ public class RoundControl {
this.view = view;
}
+ public IEvent1<IRoundState> getRoundStateUpdateEvent() {
+ return roundStateUpdateEvent;
+ }
+
/**
* End the round
*
@@ -70,10 +77,6 @@ public class RoundControl {
return endOfRoundEvent;
}
- public IEvent1<ITable> getTableUpdateEvent() {
- return tableUpdateEvent;
- }
-
/**
* Begin the round
*/
@@ -122,16 +125,11 @@ public class RoundControl {
clonedTable = (ITable) roundState.getTable().clone();
clonedHand = (IHand) roundState.getActivePlayer().getHand().clone();
- if (!oneHuman) {
- view.setBottomPanel(isHuman ? BottomPanelType.START_TURN_PANEL
- : BottomPanelType.COMPUTER_HAND_PANEL);
+ if (isHuman) {
+ view.setBottomPanel(oneHuman ? BottomPanelType.HUMAN_HAND_PANEL
+ : BottomPanelType.START_TURN_PANEL);
} else {
- if (!isHuman) {
- view.setBottomPanel(BottomPanelType.COMPUTER_HAND_PANEL);
- } else {
- view.setBottomPanel(BottomPanelType.HUMAN_HAND_PANEL);
- startTurn();
- }
+ view.setBottomPanel(BottomPanelType.NONHUMAN_HAND_PANEL);
}
view.getTablePanel().setStoneSets(clonedTable.clone());
@@ -141,13 +139,17 @@ public class RoundControl {
.getColor());
view.setCurrentPlayerHasLaidOut(roundState.getActivePlayer().getLaidOut());
- if (!isHuman)
+ turnControl = createTurnControl(roundState.getActivePlayer()
+ .getPlayerSettings());
+
+ boolean isAI = (turnControl instanceof AIControl);
+
+ if (isAI || (isHuman && oneHuman)) {
startTurn();
+ }
}
- private void startTurn() {
- if (turnControl != null)
- return;
+ protected void startTurn() {
boolean isHuman = roundState.getActivePlayer().getPlayerSettings()
.getType() == HUMAN;
@@ -164,34 +166,35 @@ public class RoundControl {
if (isHuman) {
view.getPlayerPanel().setEndTurnMode(turnMode);
}
- turnControl = TurnControlFactory.getFactory(
- roundState.getActivePlayer().getPlayerSettings().getType()).create();
+
turnControl.setup(new ITurnControl.TurnInfo(clonedTable, clonedHand,
roundState.getActivePlayer().getLaidOut(), turnMode), roundState
.getGameSettings(), view);
- turnControl.getEndOfTurnEvent().add(new IListener() {
+ turnControl.getEndOfTurnEvent().add(new IListener1<ITable>() {
@Override
- public void handle() {
- endOfTurn();
+ public void handle(ITable newTable) {
+ endOfTurn(newTable);
}
});
-
- turnControl.getTableUpdateEvent().add(new IListener1<ITable>() {
- @Override
- public void handle(ITable table) {
- tableUpdateEvent.emit(table);
- }
- });
-
turnControl.getRedealEvent().add(new IListener() {
@Override
public void handle() {
redeal();
}
});
+ addTurnControlListeners(turnControl);
+
turnControl.startTurn();
}
+ /** Override this */
+ protected void addTurnControlListeners(ITurnControl turnControl) {
+ }
+
+ protected ITurnControl createTurnControl(PlayerSettings playerSettings) {
+ return TurnControlFactory.getFactory(playerSettings.getType()).create();
+ }
+
void deal() {
for (int i = 0; i < roundState.getPlayerCount(); i++) {
IHand hand = roundState.getNthNextPlayer(i).getHand();
@@ -214,37 +217,44 @@ public class RoundControl {
|| totalValue >= roundState.getGameSettings().getInitialMeldThreshold();
}
- private void endOfTurn() {
+ private void endOfTurn(ITable newTable) {
+ boolean wasHuman = (turnControl instanceof HumanTurnControl);
+ boolean wasAI = (turnControl instanceof AIControl);
+
turnControl = null;
+
roundState.getActivePlayer().setHand(clonedHand);
boolean goToNextPlayer = true;
lastTurnNotEnoughPoints = false;
lastTurnMeldError = false;
if (roundState.getTurnNumber() >= 1) {
- goToNextPlayer = checkTurn();
+ goToNextPlayer = checkTurn(newTable);
}
- if (goToNextPlayer) {
+ if (goToNextPlayer || wasAI) {
nextPlayer();
} else {
- view.setBottomPanel(BottomPanelType.INVALID_TURN_PANEL);
+ if (wasHuman) {
+ view.setBottomPanel(BottomPanelType.INVALID_TURN_PANEL);
+ }
+
if (lastTurnNotEnoughPoints) {
view.setInitialMeldError(roundState.getGameSettings()
.getInitialMeldThreshold());
view.setInvalidStoneSets(tableSetDifference(roundState.getTable(),
- clonedTable));
+ newTable));
} else if (lastTurnMeldError) {
view.setInitialMeldFirstError();
- view.setInvalidStoneSets(touchedStoneSets());
+ view.setInvalidStoneSets(touchedStoneSets(newTable));
} else {
view.setStoneCollectionHidden(true);
- view.setInvalidStoneSets(invalidStoneSets());
+ view.setInvalidStoneSets(invalidStoneSets(newTable));
}
}
}
- private List<StoneSet> invalidStoneSets() {
+ private List<StoneSet> invalidStoneSets(ITable newTable) {
List<StoneSet> invalidSets = new ArrayList<StoneSet>();
- for (Pair<StoneSet, Position> set : clonedTable) {
+ for (Pair<StoneSet, Position> set : newTable) {
if (set.getFirst().isValid(roundState.getGameSettings())) {
continue;
}
@@ -253,9 +263,9 @@ public class RoundControl {
return invalidSets;
}
- private List<StoneSet> touchedStoneSets() {
+ private List<StoneSet> touchedStoneSets(ITable newTable) {
List<StoneSet> touchedSets = new ArrayList<StoneSet>();
- for (StoneSet set : tableSetDifference(roundState.getTable(), clonedTable)) {
+ for (StoneSet set : tableSetDifference(roundState.getTable(), newTable)) {
for (Stone stone : set) {
if (!roundState.getActivePlayer().getHand().contains(stone)) {
touchedSets.add(set);
@@ -293,27 +303,27 @@ public class RoundControl {
}
}
- private boolean checkTurn() {
- if (!clonedTable.isValid()) {
- rejectMove();
+ private boolean checkTurn(ITable newTable) {
+ if (!newTable.isValid()) {
+ rejectMove(newTable);
return false;
}
if (!roundState.getActivePlayer().getLaidOut()) {
// Player touched forbidden stones
- if (!tableSetDifference(clonedTable, roundState.getTable()).isEmpty()) {
- rejectMove();
+ if (!tableSetDifference(newTable, roundState.getTable()).isEmpty()) {
+ rejectMove(newTable);
lastTurnMeldError = true;
return false;
}
if (!laidOutValidPoints()) {
- rejectMove();
+ rejectMove(newTable);
lastTurnNotEnoughPoints = true;
return false;
}
}
- Set<Stone> tableDiff = tableDifference(roundState.getTable(), clonedTable);
+ Set<Stone> tableDiff = tableDifference(roundState.getTable(), newTable);
- roundState.setTable(clonedTable);
+ roundState.setTable(newTable);
if (tableDiff.isEmpty()) {
// Player hasn't made a move
@@ -327,8 +337,8 @@ public class RoundControl {
return true;
}
- private void rejectMove() {
- Set<Stone> tableDiff = tableDifference(roundState.getTable(), clonedTable);
+ private void rejectMove(ITable newTable) {
+ Set<Stone> tableDiff = tableDifference(roundState.getTable(), newTable);
// deal penalty, reset
roundState.getGameHeap().putBack(tableDiff);
dealPenalty(tableDiff.size());
diff --git a/src/jrummikub/control/network/ConnectionControl.java b/src/jrummikub/control/network/ConnectionControl.java
index 0a36ebd..acccbdc 100644
--- a/src/jrummikub/control/network/ConnectionControl.java
+++ b/src/jrummikub/control/network/ConnectionControl.java
@@ -6,6 +6,8 @@ import java.util.UUID;
import javax.swing.SwingUtilities;
import jrummikub.model.GameSettings;
+import jrummikub.model.IRoundState;
+import jrummikub.model.ITable;
import jrummikub.util.Event;
import jrummikub.util.Event1;
import jrummikub.util.Event2;
@@ -58,6 +60,10 @@ public class ConnectionControl implements IConnectionControl {
private Event gameStartEvent = new Event();
+ private Event1<ITable> tableUpdateEvent = new Event1<ITable>();
+ private Event1<ITable> turnEndEvent = new Event1<ITable>();
+ private Event1<IRoundState> turnStartEvent = new Event1<IRoundState>();
+
private GameData currentGame;
private volatile GameData offeredGame;
@@ -145,6 +151,21 @@ public class ConnectionControl implements IConnectionControl {
}
@Override
+ public IEvent1<ITable> getTableUpdateEvent() {
+ return tableUpdateEvent;
+ }
+
+ @Override
+ public IEvent1<ITable> getTurnEndEvent() {
+ return turnEndEvent;
+ }
+
+ @Override
+ public IEvent1<IRoundState> getTurnStartEvent() {
+ return turnStartEvent;
+ }
+
+ @Override
public void offerGame(GameData data) {
offeredGame = data;
currentGame = data;
@@ -235,7 +256,6 @@ public class ConnectionControl implements IConnectionControl {
Base64.encodeObject(color, Base64.GZIP));
}
});
-
}
@Override
@@ -248,7 +268,45 @@ public class ConnectionControl implements IConnectionControl {
extension.setValue("uuid", uuid.toString());
}
});
+ }
+
+ @Override
+ public void updateTable(final ITable table) {
+ final UUID uuid = currentGame.getGameID();
+ run(new SendRunner() {
+ @Override
+ protected void addData(DefaultPacketExtension extension) {
+ extension.setValue("messageType", "table_update");
+ extension.setValue("uuid", uuid.toString());
+ extension.setValue("table", Base64.encodeObject(table, Base64.GZIP));
+ }
+ });
+ }
+
+ @Override
+ public void endTurn(final ITable table) {
+ final UUID uuid = currentGame.getGameID();
+ run(new SendRunner() {
+ @Override
+ protected void addData(DefaultPacketExtension extension) {
+ extension.setValue("messageType", "turn_end");
+ extension.setValue("uuid", uuid.toString());
+ extension.setValue("table", Base64.encodeObject(table, Base64.GZIP));
+ }
+ });
+ }
+ @Override
+ public void startTurn(final IRoundState state) {
+ final UUID uuid = currentGame.getGameID();
+ run(new SendRunner() {
+ @Override
+ protected void addData(DefaultPacketExtension extension) {
+ extension.setValue("messageType", "turn_start");
+ extension.setValue("uuid", uuid.toString());
+ extension.setValue("state", Base64.encodeObject(state, Base64.GZIP));
+ }
+ });
}
private void sendGameOffer() {
@@ -348,6 +406,15 @@ public class ConnectionControl implements IConnectionControl {
(Color) Base64.decodeToObject(extension.getValue("color")));
} else if (messageType.equals("game_start")) {
gameStartEvent.emit();
+ } else if (messageType.equals("table_update")) {
+ tableUpdateEvent.emit((ITable) Base64.decodeToObject(extension
+ .getValue("table")));
+ } else if (messageType.equals("turn_end")) {
+ turnEndEvent.emit((ITable) Base64.decodeToObject(extension
+ .getValue("table")));
+ } else if (messageType.equals("turn_start")) {
+ turnStartEvent.emit((IRoundState) Base64.decodeToObject(extension
+ .getValue("state")));
} else {
System.err.println("Received unrecognized message of type '"
+ messageType + "'");
diff --git a/src/jrummikub/control/network/IConnectionControl.java b/src/jrummikub/control/network/IConnectionControl.java
index feacf19..b329b4c 100644
--- a/src/jrummikub/control/network/IConnectionControl.java
+++ b/src/jrummikub/control/network/IConnectionControl.java
@@ -3,6 +3,8 @@ package jrummikub.control.network;
import java.awt.Color;
import java.util.UUID;
+import jrummikub.model.IRoundState;
+import jrummikub.model.ITable;
import jrummikub.util.GameData;
import jrummikub.util.IEvent;
import jrummikub.util.IEvent1;
@@ -34,6 +36,12 @@ interface IConnectionControl {
public IEvent getGameStartEvent();
+ public IEvent1<ITable> getTableUpdateEvent();
+
+ public IEvent1<ITable> getTurnEndEvent();
+
+ public IEvent1<IRoundState> getTurnStartEvent();
+
public void offerGame(GameData data);
public void withdrawGame();
@@ -52,4 +60,10 @@ interface IConnectionControl {
public void startGame();
+ public void updateTable(ITable table);
+
+ public void endTurn(ITable table);
+
+ public void startTurn(IRoundState state);
+
} \ No newline at end of file
diff --git a/src/jrummikub/control/network/NetworkRoundControl.java b/src/jrummikub/control/network/NetworkRoundControl.java
new file mode 100644
index 0000000..d7de9ea
--- /dev/null
+++ b/src/jrummikub/control/network/NetworkRoundControl.java
@@ -0,0 +1,55 @@
+package jrummikub.control.network;
+
+import jrummikub.control.RoundControl;
+import jrummikub.control.turn.ITurnControl;
+import jrummikub.model.IRoundState;
+import jrummikub.model.ITable;
+import jrummikub.model.PlayerSettings;
+import jrummikub.util.IListener1;
+import jrummikub.view.IView;
+
+public class NetworkRoundControl extends RoundControl {
+ private IConnectionControl connectionControl;
+ private boolean currentlyActive;
+
+ public NetworkRoundControl(IRoundState roundState, IView view, IConnectionControl connectionControl, boolean startActive) {
+ super(roundState, view);
+
+ this.connectionControl = connectionControl;
+ currentlyActive = startActive;
+ }
+
+ @Override
+ protected void addTurnControlListeners(ITurnControl turnControl) {
+ turnControl.getTableUpdateEvent().add(new IListener1<ITable>() {
+ @Override
+ public void handle(ITable table) {
+ connectionControl.updateTable(table);
+ }
+ });
+ }
+
+ @Override
+ protected ITurnControl createTurnControl(PlayerSettings playerSettings) {
+ switch (playerSettings.getType()) {
+ case HUMAN:
+ currentlyActive = true;
+ break;
+ case NETWORK:
+ currentlyActive = false;
+ break;
+ }
+
+ if (!currentlyActive) {
+ return new NetworkTurnControl(connectionControl);
+ }
+
+ return super.createTurnControl(playerSettings);
+ }
+
+ @Override
+ protected void startTurn() {
+ connectionControl.startTurn(roundState);
+ super.startTurn();
+ }
+}
diff --git a/src/jrummikub/control/network/NetworkTurnControl.java b/src/jrummikub/control/network/NetworkTurnControl.java
new file mode 100644
index 0000000..d80c9b3
--- /dev/null
+++ b/src/jrummikub/control/network/NetworkTurnControl.java
@@ -0,0 +1,53 @@
+package jrummikub.control.network;
+
+import jrummikub.control.turn.AbstractTurnControl;
+import jrummikub.model.IRoundState;
+import jrummikub.model.ITable;
+import jrummikub.util.Event1;
+import jrummikub.util.IEvent1;
+import jrummikub.util.IListener1;
+
+public class NetworkTurnControl extends AbstractTurnControl {
+ private IConnectionControl connectionControl;
+ private Event1<IRoundState> stateUpdateEvent = new Event1<IRoundState>();
+
+
+ public NetworkTurnControl(IConnectionControl connectionControl) {
+ this.connectionControl = connectionControl;
+ }
+
+ public IEvent1<IRoundState> getStateUpdateEvent() {
+ return stateUpdateEvent;
+ }
+
+ @Override
+ public void doStartTurn() {
+ connections.add(connectionControl.getTableUpdateEvent().add(new IListener1<ITable>() {
+ @Override
+ public void handle(ITable table) {
+ view.getTablePanel().setStoneSets(table);
+ }
+ }));
+ connections.add(connectionControl.getTurnEndEvent().add(new IListener1<ITable>() {
+ @Override
+ public void handle(ITable table) {
+ endOfTurn(table);
+ }
+ }));
+
+ timer.startTimer();
+ }
+
+ private void endOfTurn(ITable newTable) {
+ cleanUp();
+ endOfTurnEvent.emit(newTable);
+ }
+
+ @Override
+ protected void timeOut() {
+ }
+
+ @Override
+ protected void pauseTurn() {
+ }
+}
diff --git a/src/jrummikub/control/turn/AIControl.java b/src/jrummikub/control/turn/AIControl.java
index b69d72b..ba222ea 100644
--- a/src/jrummikub/control/turn/AIControl.java
+++ b/src/jrummikub/control/turn/AIControl.java
@@ -21,7 +21,7 @@ import jrummikub.util.Pair;
*/
public class AIControl extends AbstractTurnControl {
private TurnLogic logic;
- boolean useBackgroundThread = true;
+ public static boolean useBackgroundThread = true;
long startTime;
private boolean isPaused = false;
@@ -30,7 +30,7 @@ public class AIControl extends AbstractTurnControl {
private boolean aborted = false;
@Override
- public void startTurn() {
+ protected void doStartTurn() {
timer.startTimer();
startTime = System.currentTimeMillis();
compute();
@@ -221,7 +221,7 @@ public class AIControl extends AbstractTurnControl {
return;
}
cleanUp();
- endOfTurnEvent.emit();
+ endOfTurnEvent.emit(turnInfo.getTable());
}
/**
diff --git a/src/jrummikub/control/turn/AbstractTurnControl.java b/src/jrummikub/control/turn/AbstractTurnControl.java
index fd88370..f129f24 100644
--- a/src/jrummikub/control/turn/AbstractTurnControl.java
+++ b/src/jrummikub/control/turn/AbstractTurnControl.java
@@ -19,7 +19,7 @@ import jrummikub.view.IView;
* Abstract base class for TurnControls
*/
public abstract class AbstractTurnControl implements ITurnControl {
- protected Event endOfTurnEvent = new Event();
+ protected Event1<ITable> endOfTurnEvent = new Event1<ITable>();
protected Event redealEvent = new Event();
protected Event1<ITable> tableUpdateEvent = new Event1<ITable>();
protected TurnInfo turnInfo;
@@ -27,9 +27,10 @@ public abstract class AbstractTurnControl implements ITurnControl {
protected IView view;
protected ITurnTimer timer;
protected List<Connection> connections = new ArrayList<Connection>();
+ private boolean started = false;
@Override
- public IEvent getEndOfTurnEvent() {
+ public IEvent1<ITable> getEndOfTurnEvent() {
return endOfTurnEvent;
}
@@ -37,7 +38,7 @@ public abstract class AbstractTurnControl implements ITurnControl {
public IEvent getRedealEvent() {
return redealEvent;
}
-
+
@Override
public IEvent1<ITable> getTableUpdateEvent() {
return tableUpdateEvent;
@@ -53,6 +54,18 @@ public abstract class AbstractTurnControl implements ITurnControl {
view.enablePauseMode(false);
}
+ @Override
+ public void startTurn() {
+ if (started) {
+ return;
+ }
+
+ started = true;
+ doStartTurn();
+ }
+
+ protected abstract void doStartTurn();
+
protected abstract void timeOut();
@Override
diff --git a/src/jrummikub/control/turn/HumanTurnControl.java b/src/jrummikub/control/turn/HumanTurnControl.java
index 3efad2f..51f77e4 100644
--- a/src/jrummikub/control/turn/HumanTurnControl.java
+++ b/src/jrummikub/control/turn/HumanTurnControl.java
@@ -54,7 +54,7 @@ public class HumanTurnControl extends AbstractTurnControl {
}
@Override
- public void startTurn() {
+ public void doStartTurn() {
addButtonHandlers();
addHandPanelHandlers();
@@ -449,7 +449,7 @@ public class HumanTurnControl extends AbstractTurnControl {
if (redeal) {
redealEvent.emit();
} else {
- endOfTurnEvent.emit();
+ endOfTurnEvent.emit(turnInfo.getTable());
}
}
diff --git a/src/jrummikub/control/turn/ITurnControl.java b/src/jrummikub/control/turn/ITurnControl.java
index 0039a42..1860d69 100644
--- a/src/jrummikub/control/turn/ITurnControl.java
+++ b/src/jrummikub/control/turn/ITurnControl.java
@@ -30,7 +30,7 @@ public interface ITurnControl {
*
* @return end of turn event
*/
- public IEvent getEndOfTurnEvent();
+ public IEvent1<ITable> getEndOfTurnEvent();
/**
* Emitted when the round is aborted and needs to be restarted