From f5cff88ec9177b23dc8979aa9645a427a78c6f46 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 21 Jun 2011 00:04:16 +0200 Subject: Major refactoring of RoundControl and TurnControl git-svn-id: svn://sunsvr01.isp.uni-luebeck.de/swproj13/trunk@516 72836036-5685-4462-b002-a69064685172 --- .../control/network/MockConnectionControl.java | 16 +- src/jrummikub/control/RoundControl.java | 254 ++++++--------------- .../control/network/ConnectionControl.java | 53 ++--- .../control/network/IConnectionControl.java | 12 +- .../control/network/NetworkRoundControl.java | 27 +-- .../control/network/NetworkTurnControl.java | 18 +- src/jrummikub/control/turn/AIControl.java | 2 +- .../control/turn/AbstractTurnControl.java | 169 +++++++++++++- src/jrummikub/control/turn/HumanTurnControl.java | 2 +- src/jrummikub/control/turn/ITurnControl.java | 68 ++++-- test/jrummikub/control/GameControlTest.java | 6 +- test/jrummikub/control/RoundControlTest.java | 204 +++++------------ test/jrummikub/control/turn/TurnControlTest.java | 100 +++++++- 13 files changed, 486 insertions(+), 445 deletions(-) diff --git a/mock/jrummikub/control/network/MockConnectionControl.java b/mock/jrummikub/control/network/MockConnectionControl.java index 94a5e27..61c6a37 100644 --- a/mock/jrummikub/control/network/MockConnectionControl.java +++ b/mock/jrummikub/control/network/MockConnectionControl.java @@ -3,18 +3,16 @@ package jrummikub.control.network; import java.awt.Color; import java.util.UUID; -import jrummikub.model.IHand; +import jrummikub.control.RoundControl.InvalidTurnInfo; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.GameData; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IEvent2; -import jrummikub.util.IEvent3; import jrummikub.util.MockEvent; import jrummikub.util.MockEvent1; import jrummikub.util.MockEvent2; -import jrummikub.util.MockEvent3; import jrummikub.view.LoginError; /** */ @@ -44,9 +42,9 @@ public class MockConnectionControl implements IConnectionControl { /** */ public MockEvent1 tableUpdateEvent = new MockEvent1(); /** */ - public MockEvent3 turnEndEvent = new MockEvent3(); + public MockEvent2 turnEndEvent = new MockEvent2(); /** */ - public MockEvent1 turnStartEvent = new MockEvent1(); + public MockEvent turnStartEvent = new MockEvent(); /** */ public GameData currentGame; /** */ @@ -140,12 +138,12 @@ public class MockConnectionControl implements IConnectionControl { } @Override - public IEvent3 getTurnEndEvent() { + public IEvent2 getTurnEndEvent() { return turnEndEvent; } @Override - public IEvent1 getTurnStartEvent() { + public IEvent getTurnStartEvent() { return turnStartEvent; } @@ -205,12 +203,12 @@ public class MockConnectionControl implements IConnectionControl { } @Override - public void endTurn(IHand oldHand, ITable oldTable, ITable newTable) { + public void endTurn(IRoundState state, InvalidTurnInfo invalidTurnInfo) { turnEnded = true; } @Override - public void startTurn(IRoundState state) { + public void startTurn() { turnStarted = true; } diff --git a/src/jrummikub/control/RoundControl.java b/src/jrummikub/control/RoundControl.java index 778c3d0..aeff095 100644 --- a/src/jrummikub/control/RoundControl.java +++ b/src/jrummikub/control/RoundControl.java @@ -2,18 +2,17 @@ package jrummikub.control; import static jrummikub.model.PlayerSettings.Type.*; +import java.io.Serializable; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; -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; -import jrummikub.model.Hand; import jrummikub.model.IHand; import jrummikub.model.IPlayer; import jrummikub.model.IRoundState; @@ -29,7 +28,7 @@ import jrummikub.util.Event1; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IListener; -import jrummikub.util.IListener3; +import jrummikub.util.IListener2; import jrummikub.util.Pair; import jrummikub.view.IView; import jrummikub.view.IView.BottomPanelType; @@ -38,18 +37,45 @@ import jrummikub.view.IView.BottomPanelType; * Controller that manages a single round of rummikub */ public class RoundControl { + public enum InvalidTurnType { + INVALID_SETS, INITIAL_MELD_ERROR, NOT_ENOUGH_POINTS + } + + public static class InvalidTurnInfo implements Serializable { + private static final long serialVersionUID = -3591000741414366776L; + + private ITable table; + private InvalidTurnType type; + private ArrayList invalidSets; + + public InvalidTurnInfo(ITable table, InvalidTurnType type, + Collection invalidSets) { + this.table = (ITable) table.clone(); + this.type = type; + this.invalidSets = new ArrayList(invalidSets); + } + + public ITable getTable() { + return table; + } + + public InvalidTurnType getType() { + return type; + } + + public List getInvalidSets() { + return invalidSets; + } + } + private ITurnControl turnControl; protected IRoundState roundState; private IView view; - private ITable clonedTable; - IHand clonedHand; private Event restartRoundEvent = new Event(); private Event1 roundStateUpdateEvent = new Event1(); private Event1 endOfRoundEvent = new Event1(); protected List connections = new ArrayList(); private boolean roundFinished; - private boolean lastTurnNotEnoughPoints; - private boolean lastTurnMeldError; /** * Create a new RoundControl using the given gameState and view @@ -183,13 +209,10 @@ public class RoundControl { view.getTablePanel().setStoneSets(roundState.getTable().clone()); - clonedTable = (ITable) roundState.getTable().clone(); - clonedHand = (IHand) roundState.getActivePlayer().getHand().clone(); - if (roundState.getTurnNumber() < 1) { view.setStoneCollectionHidden(true); turnMode = TurnMode.INSPECT_ONLY; - if (clonedHand.getIdenticalStoneCount() >= 3) { + if (roundState.getActivePlayer().getHand().getIdenticalStoneCount() >= 3) { turnMode = TurnMode.MAY_REDEAL; } } @@ -198,21 +221,15 @@ public class RoundControl { view.getPlayerPanel().setEndTurnMode(turnMode); } - turnControl.setup(new ITurnControl.TurnInfo(clonedTable, clonedHand, - roundState.getActivePlayer().getLaidOut(), turnMode), roundState - .getGameSettings(), view); + turnControl.setup(new ITurnControl.TurnInfo(roundState, turnMode), + roundState.getGameSettings(), view); turnControl.getEndOfTurnEvent().add( - new IListener3() { + new IListener2() { @Override - public void handle(IHand oldHand, ITable oldTable, ITable newTable) { - if (oldHand == null) { - oldHand = roundState.getActivePlayer().getHand(); - } - if (oldTable == null) { - oldTable = roundState.getTable(); - } - - endOfTurn(oldHand, oldTable, newTable); + public void handle(IRoundState newState, + InvalidTurnInfo invalidTurnInfo) { + setRoundState(newState); + endOfTurn(invalidTurnInfo); } }); turnControl.getRedealEvent().add(new IListener() { @@ -258,87 +275,46 @@ public class RoundControl { view.getSidePanel().setHeapSize(roundState.getGameHeap().getSize()); } - private boolean laidOutValidPoints(ITable oldTable, ITable newTable) { - List newSets = tableSetDifference(oldTable, newTable); - - int totalValue = 0; - for (StoneSet set : newSets) { - totalValue += set.classify(roundState.getGameSettings()).getSecond(); - } - - return totalValue == 0 - || totalValue >= roundState.getGameSettings().getInitialMeldThreshold(); - } - - protected void endOfTurn(IHand oldHand, ITable oldTable, ITable newTable) { + protected void endOfTurn(InvalidTurnInfo invalidTurnInfo) { boolean wasHuman = (turnControl instanceof HumanTurnControl); boolean wasAI = (turnControl instanceof AIControl); - - view.setBottomPanel(BottomPanelType.NONHUMAN_HAND_PANEL); - turnControl = null; - roundState.getActivePlayer().setLastTurnInvalid(false); - roundState.getActivePlayer() - .setLastTurnStoneCount( - roundState.getActivePlayer().getHand().getSize() - - clonedHand.getSize()); - - roundState.getActivePlayer().setHand(clonedHand); - boolean goToNextPlayer = true; - lastTurnNotEnoughPoints = false; - lastTurnMeldError = false; - if (roundState.getTurnNumber() >= 1) { - goToNextPlayer = checkTurn(oldTable, newTable); - } - if (goToNextPlayer || wasAI) { - nextPlayer(); - } else { + view.getTablePanel().setStoneSets(invalidTurnInfo.getTable()); + + if (invalidTurnInfo.getType() != null) { if (wasHuman) { view.setBottomPanel(BottomPanelType.INVALID_TURN_PANEL); } - if (lastTurnNotEnoughPoints) { - view.setInitialMeldError(roundState.getGameSettings() - .getInitialMeldThreshold()); - view.getTablePanel().setStoneSets(newTable); - view.setInvalidStoneSets(tableSetDifference(oldTable, newTable)); - } else if (lastTurnMeldError) { - view.setInitialMeldFirstError(); - view.getTablePanel().setStoneSets(newTable); - view.setInvalidStoneSets(touchedStoneSets(oldHand, oldTable, newTable)); - } else { - view.setStoneCollectionHidden(true); - view.getTablePanel().setStoneSets(newTable); - view.setInvalidStoneSets(invalidStoneSets(newTable)); + view.setInvalidStoneSets(invalidTurnInfo.getInvalidSets()); + + switch (invalidTurnInfo.getType()) { + case INITIAL_MELD_ERROR: + view.setInitialMeldFirstError(); + break; + case INVALID_SETS: + view.setStoneCollectionHidden(true); + break; + case NOT_ENOUGH_POINTS: + view.setInitialMeldError(roundState.getGameSettings() + .getInitialMeldThreshold()); + break; } - } - } - private List invalidStoneSets(ITable newTable) { - List invalidSets = new ArrayList(); - for (Pair set : newTable) { - if (set.getFirst().isValid(roundState.getGameSettings())) { - continue; + if (wasAI) { + nextPlayer(); } - invalidSets.add(set.getFirst()); + return; } - return invalidSets; - } - private List touchedStoneSets(IHand oldHand, ITable oldTable, - ITable newTable) { - List touchedSets = new ArrayList(); - for (StoneSet set : tableSetDifference(oldTable, newTable)) { - for (Stone stone : set) { - if (!oldHand.contains(stone)) { - touchedSets.add(set); - break; - } - } + if (roundState.getActivePlayer().getHand().getSize() == 0) { + endOfRound(); + return; } - return touchedSets; + view.setBottomPanel(BottomPanelType.NONHUMAN_HAND_PANEL); + nextPlayer(); } private void nextPlayer() { @@ -347,7 +323,7 @@ public class RoundControl { view.setStoneCollectionHidden(false); if (roundState.getLastPlayer() == null) { if (roundState.getGameHeap().getSize() == 0) { - roundState.setLastPlayer(roundState.getNthNextPlayer(0)); + roundState.setLastPlayer(roundState.getActivePlayer()); roundState.nextPlayer(); roundState.nextTurn(); } else { @@ -367,100 +343,6 @@ public class RoundControl { } } - private boolean checkTurn(ITable oldTable, ITable newTable) { - if (!newTable.isValid()) { - rejectMove(oldTable, newTable); - return false; - } - if (!roundState.getActivePlayer().getLaidOut()) { - // Player touched forbidden stones - if (!tableSetDifference(newTable, oldTable).isEmpty()) { - rejectMove(oldTable, newTable); - lastTurnMeldError = true; - return false; - } - if (!laidOutValidPoints(oldTable, newTable)) { - rejectMove(oldTable, newTable); - lastTurnNotEnoughPoints = true; - return false; - } - } - Set tableDiff = tableDifference(oldTable, newTable); - - roundState.setTable(newTable); - - if (tableDiff.isEmpty()) { - // Player hasn't made a move - dealStone(); - } else { - roundState.getActivePlayer().setLaidOut(true); - if (roundState.getActivePlayer().getHand().getSize() == 0) { - endOfRound(); - } - } - return true; - } - - private void rejectMove(ITable oldTable, ITable newTable) { - Set tableDiff = tableDifference(oldTable, newTable); - // deal penalty, reset - roundState.getGameHeap().putBack(tableDiff); - roundState.getActivePlayer().setLastTurnInvalid(true); - dealPenalty(tableDiff.size()); - - } - - static Set tableDifference(ITable oldTable, ITable newTable) { - Set ret = new HashSet(); - - for (Pair entry : newTable) { - for (Stone stone : entry.getFirst()) { - ret.add(stone); - } - } - for (Pair entry : oldTable) { - for (Stone stone : entry.getFirst()) { - ret.remove(stone); - } - } - return ret; - } - - static List tableSetDifference(ITable oldTable, ITable newTable) { - List ret = new ArrayList(); - - for (Pair entry : newTable) { - ret.add(entry.getFirst()); - } - for (Pair entry : oldTable) { - ret.remove(entry.getFirst()); - } - return ret; - } - - void dealStones(int count) { - IHand hand = roundState.getActivePlayer().getHand(); - int rowCount = hand.getRowCount(); - - for (int i = 0; i < count; ++i) { - if (hand.getFreeRowSpace(rowCount - 1) == 0) { - rowCount++; - } - - hand.drop(roundState.getGameHeap().drawStone(), new Position( - Hand.WIDTH - 1, rowCount - 1)); - } - - } - - private void dealStone() { - dealStones(1); - } - - private void dealPenalty(int count) { - dealStones(count + 3); - } - void endOfRound() { removeListeners(); Score roundScore = score(); diff --git a/src/jrummikub/control/network/ConnectionControl.java b/src/jrummikub/control/network/ConnectionControl.java index 76b430a..4ed160a 100644 --- a/src/jrummikub/control/network/ConnectionControl.java +++ b/src/jrummikub/control/network/ConnectionControl.java @@ -6,19 +6,17 @@ import java.util.UUID; import javax.swing.SwingUtilities; +import jrummikub.control.RoundControl.InvalidTurnInfo; import jrummikub.model.GameSettings; -import jrummikub.model.IHand; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.Event; import jrummikub.util.Event1; import jrummikub.util.Event2; -import jrummikub.util.Event3; import jrummikub.util.GameData; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IEvent2; -import jrummikub.util.IEvent3; import jrummikub.util.LoginData; import jrummikub.view.LoginError; @@ -48,26 +46,20 @@ public class ConnectionControl implements IConnectionControl { private static class TurnEndData implements Serializable { private static final long serialVersionUID = -3800572117130220737L; - private IHand oldHand; - private ITable oldTable; - private ITable newTable; + private IRoundState roundState; + private InvalidTurnInfo invalidTurnInfo; - TurnEndData(IHand oldHand, ITable oldTable, ITable newTable) { - this.oldHand = oldHand; - this.oldTable = oldTable; - this.newTable = newTable; + TurnEndData(IRoundState roundState, InvalidTurnInfo invalidTurnInfo) { + this.roundState = roundState; + this.invalidTurnInfo = invalidTurnInfo; } - IHand getOldHand() { - return oldHand; + IRoundState getRoundState() { + return roundState; } - ITable getOldTable() { - return oldTable; - } - - ITable getNewTable() { - return newTable; + InvalidTurnInfo getInvalidTurnInfo() { + return invalidTurnInfo; } } @@ -95,8 +87,8 @@ public class ConnectionControl implements IConnectionControl { private Event roundStartEvent = new Event(); private Event1 tableUpdateEvent = new Event1(); - private Event3 turnEndEvent = new Event3(); - private Event1 turnStartEvent = new Event1(); + private Event2 turnEndEvent = new Event2(); + private Event turnStartEvent = new Event(); private GameData currentGame; @@ -195,12 +187,12 @@ public class ConnectionControl implements IConnectionControl { } @Override - public IEvent3 getTurnEndEvent() { + public IEvent2 getTurnEndEvent() { return turnEndEvent; } @Override - public IEvent1 getTurnStartEvent() { + public IEvent getTurnStartEvent() { return turnStartEvent; } @@ -334,29 +326,28 @@ public class ConnectionControl implements IConnectionControl { } @Override - public void endTurn(final IHand oldHand, final ITable oldTable, - final ITable newTable) { + public void endTurn(final IRoundState state, + final InvalidTurnInfo invalidTurnInfo) { 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("data", Base64.encodeObject(new TurnEndData(oldHand, - oldTable, newTable), Base64.GZIP)); + extension.setValue("data", Base64.encodeObject(new TurnEndData(state, + invalidTurnInfo), Base64.GZIP)); } }); } @Override - public void startTurn(final IRoundState state) { + public void startTurn() { 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)); } }); } @@ -474,11 +465,9 @@ public class ConnectionControl implements IConnectionControl { } else if (messageType.equals("turn_end")) { TurnEndData data = (TurnEndData) Base64.decodeToObject(extension .getValue("data")); - turnEndEvent.emit(data.getOldHand(), data.getOldTable(), - data.getNewTable()); + turnEndEvent.emit(data.getRoundState(), data.getInvalidTurnInfo()); } else if (messageType.equals("turn_start")) { - turnStartEvent.emit((IRoundState) Base64.decodeToObject(extension - .getValue("state"))); + turnStartEvent.emit(); } 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 38bc05c..b93748c 100644 --- a/src/jrummikub/control/network/IConnectionControl.java +++ b/src/jrummikub/control/network/IConnectionControl.java @@ -3,14 +3,13 @@ package jrummikub.control.network; import java.awt.Color; import java.util.UUID; -import jrummikub.model.IHand; +import jrummikub.control.RoundControl.InvalidTurnInfo; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.GameData; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; import jrummikub.util.IEvent2; -import jrummikub.util.IEvent3; import jrummikub.view.LoginError; interface IConnectionControl { @@ -43,9 +42,9 @@ interface IConnectionControl { public IEvent1 getTableUpdateEvent(); - public IEvent3 getTurnEndEvent(); + public IEvent2 getTurnEndEvent(); - public IEvent1 getTurnStartEvent(); + public IEvent getTurnStartEvent(); public void offerGame(GameData data); @@ -69,7 +68,8 @@ interface IConnectionControl { public void updateTable(ITable table); - public void endTurn(IHand oldHand, ITable oldTable, ITable newTable); + public void endTurn(IRoundState state, InvalidTurnInfo invalidTurnInfo); + + public void startTurn(); - 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 index 81820e7..64faebb 100644 --- a/src/jrummikub/control/network/NetworkRoundControl.java +++ b/src/jrummikub/control/network/NetworkRoundControl.java @@ -2,10 +2,10 @@ package jrummikub.control.network; import jrummikub.control.RoundControl; import jrummikub.control.turn.ITurnControl; -import jrummikub.model.IHand; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.model.PlayerSettings.Type; +import jrummikub.util.IListener; import jrummikub.util.IListener1; import jrummikub.view.IView; @@ -20,17 +20,12 @@ public class NetworkRoundControl extends RoundControl { this.connectionControl = connectionControl; currentlyActive = startActive; - connections.add(connectionControl.getTurnStartEvent().add( - new IListener1() { - @Override - public void handle(IRoundState state) { - NetworkControl.fixGameSettings(state.getGameSettings(), - connectionControl.getNickname()); - setRoundState(state); - - startTurn(); - } - })); + connections.add(connectionControl.getTurnStartEvent().add(new IListener() { + @Override + public void handle() { + startTurn(); + } + })); } @Override @@ -68,16 +63,16 @@ public class NetworkRoundControl extends RoundControl { doPrepareTurn(); if (wasActive) { - connectionControl.startTurn(roundState); + connectionControl.startTurn(); } } @Override - protected void endOfTurn(IHand oldHand, ITable oldTable, ITable newTable) { + protected void endOfTurn(InvalidTurnInfo invalidTurnInfo) { if (currentlyActive) { - connectionControl.endTurn(oldHand, oldTable, newTable); + connectionControl.endTurn(roundState, invalidTurnInfo); } - super.endOfTurn(oldHand, oldTable, newTable); + super.endOfTurn(invalidTurnInfo); } } diff --git a/src/jrummikub/control/network/NetworkTurnControl.java b/src/jrummikub/control/network/NetworkTurnControl.java index 57851a2..7b0bcbb 100644 --- a/src/jrummikub/control/network/NetworkTurnControl.java +++ b/src/jrummikub/control/network/NetworkTurnControl.java @@ -1,13 +1,13 @@ package jrummikub.control.network; +import jrummikub.control.RoundControl.InvalidTurnInfo; import jrummikub.control.turn.AbstractTurnControl; -import jrummikub.model.IHand; import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.Event1; import jrummikub.util.IEvent1; import jrummikub.util.IListener1; -import jrummikub.util.IListener3; +import jrummikub.util.IListener2; public class NetworkTurnControl extends AbstractTurnControl { private IConnectionControl connectionControl; @@ -31,20 +31,24 @@ public class NetworkTurnControl extends AbstractTurnControl { } })); connections.add(connectionControl.getTurnEndEvent().add( - new IListener3() { + new IListener2() { @Override - public void handle(IHand oldHand, ITable oldTable, ITable newTable) { - endOfTurn(oldHand, oldTable, newTable); + public void handle(IRoundState state, + InvalidTurnInfo invalidTurnInfo) { + NetworkControl.fixGameSettings(state.getGameSettings(), + connectionControl.getNickname()); + + endOfTurn(state, invalidTurnInfo); } })); timer.startTimer(); } - private void endOfTurn(IHand oldHand, ITable oldTable, ITable newTable) { + private void endOfTurn(IRoundState roundState, InvalidTurnInfo invalidTurnInfo) { cleanUp(); - endOfTurnEvent.emit(oldHand, oldTable, newTable); + endOfTurnEvent.emit(roundState, invalidTurnInfo); } @Override diff --git a/src/jrummikub/control/turn/AIControl.java b/src/jrummikub/control/turn/AIControl.java index b633f96..f480143 100644 --- a/src/jrummikub/control/turn/AIControl.java +++ b/src/jrummikub/control/turn/AIControl.java @@ -225,7 +225,7 @@ public class AIControl extends AbstractTurnControl { return; } cleanUp(); - endOfTurnEvent.emit(null, null, turnInfo.getTable()); + endOfTurnEvent.emit(turnInfo.getRoundState(), checkTurn()); } /** diff --git a/src/jrummikub/control/turn/AbstractTurnControl.java b/src/jrummikub/control/turn/AbstractTurnControl.java index 8b481bc..d64ee62 100644 --- a/src/jrummikub/control/turn/AbstractTurnControl.java +++ b/src/jrummikub/control/turn/AbstractTurnControl.java @@ -1,28 +1,39 @@ package jrummikub.control.turn; import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import jrummikub.control.ITurnTimer; +import jrummikub.control.RoundControl.InvalidTurnInfo; +import jrummikub.control.RoundControl.InvalidTurnType; import jrummikub.control.TurnTimer; import jrummikub.model.GameSettings; +import jrummikub.model.Hand; import jrummikub.model.IHand; +import jrummikub.model.IRoundState; import jrummikub.model.ITable; +import jrummikub.model.Position; +import jrummikub.model.Stone; +import jrummikub.model.StoneSet; import jrummikub.util.Connection; import jrummikub.util.Event; import jrummikub.util.Event1; -import jrummikub.util.Event3; +import jrummikub.util.Event2; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; -import jrummikub.util.IEvent3; +import jrummikub.util.IEvent2; import jrummikub.util.IListener; +import jrummikub.util.Pair; import jrummikub.view.IView; /** * Abstract base class for TurnControls */ public abstract class AbstractTurnControl implements ITurnControl { - protected Event3 endOfTurnEvent = new Event3(); + protected Event2 endOfTurnEvent = new Event2(); protected Event redealEvent = new Event(); protected Event1 tableUpdateEvent = new Event1(); protected TurnInfo turnInfo; @@ -33,7 +44,7 @@ public abstract class AbstractTurnControl implements ITurnControl { private boolean started = false; @Override - public IEvent3 getEndOfTurnEvent() { + public IEvent2 getEndOfTurnEvent() { return endOfTurnEvent; } @@ -114,4 +125,154 @@ public abstract class AbstractTurnControl implements ITurnControl { cleanUp(); } + protected InvalidTurnInfo checkTurn() { + turnInfo.getRoundState().getActivePlayer().setLastTurnInvalid(false); + turnInfo + .getRoundState() + .getActivePlayer() + .setLastTurnStoneCount( + turnInfo.getOldHand().getSize() - turnInfo.getHand().getSize()); + + turnInfo.getRoundState().getActivePlayer().setHand(turnInfo.getHand()); + + if (turnInfo.getRoundState().getTurnNumber() < 1) { + return new InvalidTurnInfo(turnInfo.getTable(), null, + Collections. emptyList()); + } + + if (!turnInfo.getTable().isValid()) { + rejectMove(); + return new InvalidTurnInfo(turnInfo.getTable(), + InvalidTurnType.INVALID_SETS, invalidStoneSets()); + } + if (!turnInfo.getLaidOut()) { + // Player touched forbidden stones + if (!tableSetDifference(turnInfo.getTable(), turnInfo.getOldTable()) + .isEmpty()) { + rejectMove(); + return new InvalidTurnInfo(turnInfo.getTable(), + InvalidTurnType.INITIAL_MELD_ERROR, touchedStoneSets()); + } + if (!laidOutValidPoints()) { + rejectMove(); + return new InvalidTurnInfo(turnInfo.getTable(), + InvalidTurnType.NOT_ENOUGH_POINTS, tableSetDifference( + turnInfo.getOldTable(), turnInfo.getTable())); + } + } + Set tableDiff = tableDifference(turnInfo.getOldTable(), + turnInfo.getTable()); + + turnInfo.getRoundState().setTable(turnInfo.getTable()); + + if (tableDiff.isEmpty()) { + // Player hasn't made a move + dealStone(); + } else { + turnInfo.getRoundState().getActivePlayer().setLaidOut(true); + } + return new InvalidTurnInfo(turnInfo.getTable(), null, + Collections. emptyList()); + } + + private List invalidStoneSets() { + List invalidSets = new ArrayList(); + for (Pair set : turnInfo.getTable()) { + if (set.getFirst().isValid(turnInfo.getRoundState().getGameSettings())) { + continue; + } + invalidSets.add(set.getFirst()); + } + return invalidSets; + } + + private List touchedStoneSets() { + List touchedSets = new ArrayList(); + for (StoneSet set : tableSetDifference(turnInfo.getOldTable(), + turnInfo.getTable())) { + for (Stone stone : set) { + if (!turnInfo.getOldHand().contains(stone)) { + touchedSets.add(set); + break; + } + } + } + + return touchedSets; + } + + private boolean laidOutValidPoints() { + List newSets = tableSetDifference(turnInfo.getOldTable(), + turnInfo.getTable()); + + int totalValue = 0; + for (StoneSet set : newSets) { + totalValue += set.classify(turnInfo.getRoundState().getGameSettings()) + .getSecond(); + } + + return totalValue == 0 + || totalValue >= turnInfo.getRoundState().getGameSettings() + .getInitialMeldThreshold(); + } + + private void rejectMove() { + Set tableDiff = tableDifference(turnInfo.getOldTable(), + turnInfo.getTable()); + // deal penalty, reset + turnInfo.getRoundState().getGameHeap().putBack(tableDiff); + turnInfo.getRoundState().getActivePlayer().setLastTurnInvalid(true); + dealPenalty(tableDiff.size()); + } + + private void dealStones(int count) { + IHand hand = turnInfo.getRoundState().getActivePlayer().getHand(); + int rowCount = hand.getRowCount(); + + for (int i = 0; i < count; ++i) { + if (hand.getFreeRowSpace(rowCount - 1) == 0) { + rowCount++; + } + + hand.drop(turnInfo.getRoundState().getGameHeap().drawStone(), + new Position(Hand.WIDTH - 1, rowCount - 1)); + } + + } + + private void dealStone() { + dealStones(1); + } + + private void dealPenalty(int count) { + dealStones(count + 3); + } + + static Set tableDifference(ITable oldTable, ITable newTable) { + Set ret = new HashSet(); + + for (Pair entry : newTable) { + for (Stone stone : entry.getFirst()) { + ret.add(stone); + } + } + for (Pair entry : oldTable) { + for (Stone stone : entry.getFirst()) { + ret.remove(stone); + } + } + return ret; + } + + static List tableSetDifference(ITable oldTable, ITable newTable) { + List ret = new ArrayList(); + + for (Pair entry : newTable) { + ret.add(entry.getFirst()); + } + for (Pair entry : oldTable) { + ret.remove(entry.getFirst()); + } + return ret; + } } \ No newline at end of file diff --git a/src/jrummikub/control/turn/HumanTurnControl.java b/src/jrummikub/control/turn/HumanTurnControl.java index e43ec5b..43c2317 100644 --- a/src/jrummikub/control/turn/HumanTurnControl.java +++ b/src/jrummikub/control/turn/HumanTurnControl.java @@ -448,7 +448,7 @@ public class HumanTurnControl extends AbstractTurnControl { if (redeal) { redealEvent.emit(); } else { - endOfTurnEvent.emit(null, null, turnInfo.getTable()); + endOfTurnEvent.emit(turnInfo.getRoundState(), checkTurn()); } } diff --git a/src/jrummikub/control/turn/ITurnControl.java b/src/jrummikub/control/turn/ITurnControl.java index 5c91c0c..6994466 100644 --- a/src/jrummikub/control/turn/ITurnControl.java +++ b/src/jrummikub/control/turn/ITurnControl.java @@ -1,11 +1,13 @@ package jrummikub.control.turn; +import jrummikub.control.RoundControl.InvalidTurnInfo; import jrummikub.model.GameSettings; import jrummikub.model.IHand; +import jrummikub.model.IRoundState; import jrummikub.model.ITable; import jrummikub.util.IEvent; import jrummikub.util.IEvent1; -import jrummikub.util.IEvent3; +import jrummikub.util.IEvent2; import jrummikub.view.IView; /** @@ -17,12 +19,12 @@ public interface ITurnControl { * Start the turn * * @param info - * the current turn state + * the current turn state * * @param settings - * the game settings + * the game settings * @param view - * view for user interaction. + * view for user interaction. */ public void setup(TurnInfo info, GameSettings settings, IView view); @@ -31,7 +33,7 @@ public interface ITurnControl { * * @return end of turn event */ - public IEvent3 getEndOfTurnEvent(); + public IEvent2 getEndOfTurnEvent(); /** * Emitted when the round is aborted and needs to be restarted @@ -58,35 +60,61 @@ public interface ITurnControl { public IEvent1 getTableUpdateEvent(); /** - * The TurnInfo class encapsulates all information concerning the current - * turn + * The TurnInfo class encapsulates all information concerning the current turn */ public class TurnInfo { + private IRoundState roundState; + + private ITable oldTable; + private IHand oldHand; + private ITable table; private IHand hand; - private boolean hasLaidOut; + private TurnMode turnMode; /** * Creates a new TurnInfo instance * - * @param table - * the current table - * @param hand - * the current player's hand * @param hasLaidOut - * has the player laid out yet? + * has the player laid out yet? * @param turnMode - * the turn mode + * the turn mode */ - public TurnInfo(ITable table, IHand hand, boolean hasLaidOut, - TurnMode turnMode) { - this.table = table; - this.hand = hand; - this.hasLaidOut = hasLaidOut; + public TurnInfo(IRoundState roundState, TurnMode turnMode) { + this.roundState = roundState; + + oldTable = roundState.getTable(); + oldHand = roundState.getActivePlayer().getHand(); + + this.table = (ITable) oldTable.clone(); + this.hand = (IHand) oldHand.clone(); + this.turnMode = turnMode; } + public IRoundState getRoundState() { + return roundState; + } + + /** + * Gets the table at the beginning of the turn + * + * @return the table + */ + public ITable getOldTable() { + return oldTable; + } + + /** + * Gets the current player's hand at the beginning of the turn + * + * @return the hand + */ + public IHand getOldHand() { + return oldHand; + } + /** * Gets the current table * @@ -111,7 +139,7 @@ public interface ITurnControl { * @return if the player has laid out */ public boolean getLaidOut() { - return hasLaidOut; + return roundState.getActivePlayer().getLaidOut(); } /** diff --git a/test/jrummikub/control/GameControlTest.java b/test/jrummikub/control/GameControlTest.java index e1af261..7555714 100644 --- a/test/jrummikub/control/GameControlTest.java +++ b/test/jrummikub/control/GameControlTest.java @@ -49,10 +49,8 @@ public class GameControlTest { public void testEndOfRound() { gameControl.startGame(); - view.startTurnEvent.emit(); - // Manipulate first player's hand, to allow player1 to win - IHand playerHand = gameControl.roundControl.clonedHand; + IHand playerHand = gameControl.roundControl.roundState.getActivePlayer().getHand(); for (Pair entry : playerHand.clone()) { playerHand.pickUp(entry.getFirst()); } @@ -64,6 +62,8 @@ public class GameControlTest { playerHand.drop(stone3, new Position(0, 0)); // Done setting up first players hand + view.startTurnEvent.emit(); + view.playerPanel.endTurnEvent.emit(); view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); diff --git a/test/jrummikub/control/RoundControlTest.java b/test/jrummikub/control/RoundControlTest.java index edcb57f..8785fba 100644 --- a/test/jrummikub/control/RoundControlTest.java +++ b/test/jrummikub/control/RoundControlTest.java @@ -4,11 +4,7 @@ import static jrummikub.model.StoneColor.*; import static org.junit.Assert.*; import java.awt.Color; -import java.util.Arrays; -import java.util.HashSet; import java.util.Iterator; -import java.util.List; -import java.util.Set; import jrummikub.control.turn.TurnMode; import jrummikub.model.GameSettings; @@ -16,7 +12,6 @@ import jrummikub.model.Hand; import jrummikub.model.IHand; import jrummikub.model.IPlayer; import jrummikub.model.IRoundState; -import jrummikub.model.ITable; import jrummikub.model.MockRoundState; import jrummikub.model.MockTable; import jrummikub.model.PlayerSettings; @@ -25,7 +20,6 @@ import jrummikub.model.RoundState; import jrummikub.model.Score; import jrummikub.model.Stone; import jrummikub.model.StoneSet; -import jrummikub.model.Table; import jrummikub.util.IListener; import jrummikub.util.IListener1; import jrummikub.util.Pair; @@ -172,12 +166,12 @@ public class RoundControlTest { view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); } - view.startTurnEvent.emit(); - IHand hand = roundControl.clonedHand; + IHand hand = roundState.getActivePlayer().getHand(); hand.drop(blueOne, new Position(0, 0)); hand.drop(blueTwo, new Position(0, 0)); hand.drop(blueThree, new Position(0, 0)); + view.startTurnEvent.emit(); assertFalse(roundState.getActivePlayer().getLaidOut()); @@ -191,7 +185,7 @@ public class RoundControlTest { assertFalse(roundState.getNthNextPlayer(roundState.getPlayerCount() - 1) .getLaidOut()); assertEquals(0, roundState.getTable().getSize()); - assertEquals(14 + 6, hand.getSize()); + assertEquals(14 + 6, roundState.getActivePlayer().getHand().getSize()); } /** */ @@ -202,17 +196,16 @@ public class RoundControlTest { view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); } - view.startTurnEvent.emit(); - IHand hand = roundControl.clonedHand; + view.startTurnEvent.emit(); assertFalse(roundState.getActivePlayer().getLaidOut()); view.playerPanel.endTurnEvent.emit(); - assertFalse(roundState.getNthNextPlayer(roundState.getPlayerCount() - 1) - .getLaidOut()); + assertFalse(roundState.getNthNextPlayer(-1).getLaidOut()); assertEquals(0, roundState.getTable().getSize()); - assertEquals(14 + 1, hand.getSize()); + + assertEquals(14 + 1, roundState.getNthNextPlayer(-1).getHand().getSize()); } /** Threshold=30 */ @@ -223,12 +216,15 @@ public class RoundControlTest { view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); } - view.startTurnEvent.emit(); - IHand hand = roundControl.clonedHand; + IHand hand = roundState.getActivePlayer().getHand(); hand.drop(blueOne, new Position(0, 0)); hand.drop(blueTwo, new Position(0, 0)); hand.drop(blueThree, new Position(0, 0)); + hand.drop(blueTen, new Position(0, 0)); + hand.drop(redTen, new Position(0, 0)); + hand.drop(blueEleven, new Position(0, 0)); + view.startTurnEvent.emit(); view.handPanel.stoneClickEvent.emit(blueOne, false); view.handPanel.stoneClickEvent.emit(blueTwo, true); @@ -238,10 +234,6 @@ public class RoundControlTest { assertFalse(roundState.getActivePlayer().getLaidOut()); - hand.drop(blueTen, new Position(0, 0)); - hand.drop(redTen, new Position(0, 0)); - hand.drop(blueEleven, new Position(0, 0)); - view.handPanel.stoneClickEvent.emit(blueTen, false); view.handPanel.stoneClickEvent.emit(redTen, true); view.handPanel.stoneClickEvent.emit(blueEleven, true); @@ -249,10 +241,12 @@ public class RoundControlTest { view.tablePanel.clickEvent.emit(new Position(0, 0)); view.playerPanel.endTurnEvent.emit(); - assertFalse(roundState.getNthNextPlayer(roundState.getPlayerCount() - 1) - .getLaidOut()); + view.acknowledgeInvalidEvent.emit(); + + assertFalse(roundState.getNthNextPlayer(-1).getLaidOut()); assertEquals(0, roundState.getTable().getSize()); - assertEquals(14 + 9, hand.getSize()); + + assertEquals(14 + 9, roundState.getNthNextPlayer(-1).getHand().getSize()); } /** Threshold=30 */ @@ -263,9 +257,8 @@ public class RoundControlTest { view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); } - view.startTurnEvent.emit(); // Fake Turn to put stones on the table - IHand hand = roundControl.clonedHand; + IHand hand = roundState.getActivePlayer().getHand(); hand.drop(blueOne, new Position(0, 0)); hand.drop(blueTwo, new Position(0, 0)); hand.drop(blueThree, new Position(0, 0)); @@ -274,6 +267,7 @@ public class RoundControlTest { hand.drop(blueSeven, new Position(0, 0)); hand.drop(blackSeven, new Position(0, 0)); hand.drop(orangeSeven, new Position(0, 0)); + view.startTurnEvent.emit(); view.handPanel.stoneClickEvent.emit(redSeven, false); view.handPanel.stoneClickEvent.emit(blueSeven, true); @@ -290,12 +284,12 @@ public class RoundControlTest { view.playerPanel.endTurnEvent.emit(); assertEquals(2, roundState.getTable().getSize()); - view.startTurnEvent.emit(); - hand = roundControl.clonedHand; + hand = roundState.getActivePlayer().getHand(); hand.drop(redEight, new Position(0, 0)); hand.drop(redNine, new Position(0, 0)); hand.drop(redTen, new Position(0, 0)); + view.startTurnEvent.emit(); view.tablePanel.stoneClickEvent.emit(redSeven, false); view.handPanel.stoneClickEvent.emit(redEight, true); @@ -308,10 +302,9 @@ public class RoundControlTest { view.playerPanel.endTurnEvent.emit(); view.acknowledgeInvalidEvent.emit(); - assertFalse(roundState.getNthNextPlayer(roundState.getPlayerCount() - 1) - .getLaidOut()); + assertFalse(roundState.getNthNextPlayer(-1).getLaidOut()); assertEquals(2, roundState.getTable().getSize()); - assertEquals(14 + 6, hand.getSize()); + assertEquals(14 + 6, roundState.getNthNextPlayer(-1).getHand().getSize()); } /** Threshold=30 */ @@ -322,9 +315,8 @@ public class RoundControlTest { view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); } - view.startTurnEvent.emit(); // Fake Turn to put stones on the table - IHand hand = roundControl.clonedHand; + IHand hand = roundState.getActivePlayer().getHand(); hand.drop(blueOne, new Position(0, 0)); hand.drop(blueTwo, new Position(0, 0)); hand.drop(blueThree, new Position(0, 0)); @@ -333,6 +325,7 @@ public class RoundControlTest { hand.drop(blueSeven, new Position(0, 0)); hand.drop(blackSeven, new Position(0, 0)); hand.drop(orangeSeven, new Position(0, 0)); + view.startTurnEvent.emit(); view.handPanel.stoneClickEvent.emit(redSeven, false); view.handPanel.stoneClickEvent.emit(blueSeven, true); @@ -349,13 +342,13 @@ public class RoundControlTest { view.playerPanel.endTurnEvent.emit(); assertEquals(2, roundState.getTable().getSize()); - view.startTurnEvent.emit(); - hand = roundControl.clonedHand; + hand = roundState.getActivePlayer().getHand(); hand.drop(redEight, new Position(0, 0)); hand.drop(redNine, new Position(0, 0)); hand.drop(redTen, new Position(0, 0)); hand.drop(redEleven, new Position(0, 0)); + view.startTurnEvent.emit(); view.tablePanel.stoneClickEvent.emit(redSeven, false); view.handPanel.stoneClickEvent.emit(redEight, true); @@ -369,10 +362,9 @@ public class RoundControlTest { view.playerPanel.endTurnEvent.emit(); view.acknowledgeInvalidEvent.emit(); - assertFalse(roundState.getNthNextPlayer(roundState.getPlayerCount() - 1) - .getLaidOut()); + assertFalse(roundState.getNthNextPlayer(-1).getLaidOut()); assertEquals(2, roundState.getTable().getSize()); - assertEquals(14 + 7, hand.getSize()); + assertEquals(14 + 7, roundState.getNthNextPlayer(-1).getHand().getSize()); } /** */ @@ -383,9 +375,8 @@ public class RoundControlTest { view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); } - view.startTurnEvent.emit(); // Fake Turn to put stones on the table - IHand hand = roundControl.clonedHand; + IHand hand = roundState.getActivePlayer().getHand(); hand.drop(blueFive, new Position(0, 0)); hand.drop(blueSix, new Position(0, 0)); hand.drop(blueSeven, new Position(0, 0)); @@ -394,6 +385,7 @@ public class RoundControlTest { hand.drop(blueFour, new Position(0, 0)); hand.drop(blackFour, new Position(0, 0)); hand.drop(orangeFour, new Position(0, 0)); + view.startTurnEvent.emit(); view.handPanel.stoneClickEvent.emit(redFour, false); view.handPanel.stoneClickEvent.emit(blueFour, true); @@ -410,10 +402,8 @@ public class RoundControlTest { view.playerPanel.endTurnEvent.emit(); assertEquals(2, roundState.getTable().getSize()); - view.startTurnEvent.emit(); - - hand = roundControl.clonedHand; + view.startTurnEvent.emit(); view.tablePanel.stoneClickEvent.emit(blueFour, false); view.tablePanel.stoneClickEvent.emit(blueFive, true); view.tablePanel.stoneClickEvent.emit(blueSix, true); @@ -425,10 +415,9 @@ public class RoundControlTest { view.playerPanel.endTurnEvent.emit(); view.acknowledgeInvalidEvent.emit(); - assertFalse(roundState.getNthNextPlayer(roundState.getPlayerCount() - 1) - .getLaidOut()); + assertFalse(roundState.getNthNextPlayer(-1).getLaidOut()); assertEquals(2, roundState.getTable().getSize()); - assertEquals(14 + 3, hand.getSize()); + assertEquals(14 + 3, roundState.getNthNextPlayer(-1).getHand().getSize()); } /** Threshold=30 */ @@ -439,9 +428,8 @@ public class RoundControlTest { view.startTurnEvent.emit(); view.playerPanel.endTurnEvent.emit(); } - view.startTurnEvent.emit(); // Fake Turn to put stones on the table - IHand hand = roundControl.clonedHand; + IHand hand = roundState.getActivePlayer().getHand(); hand.drop(blueOne, new Position(0, 0)); hand.drop(blueTwo, new Position(0, 0)); hand.drop(blueThree, new Position(0, 0)); @@ -450,6 +438,7 @@ public class RoundControlTest { hand.drop(blueSeven, new Position(0, 0)); hand.drop(blackSeven, new Position(0, 0)); hand.drop(orangeSeven, new Position(0, 0)); + view.startTurnEvent.emit(); view.handPanel.stoneClickEvent.emit(redSeven, false); view.handPanel.stoneClickEvent.emit(blueSeven, true); @@ -465,22 +454,9 @@ public class RoundControlTest { view.tablePanel.clickEvent.emit(new Position(0, 0)); view.playerPanel.endTurnEvent.emit(); - assertTrue(roundState.getNthNextPlayer(roundState.getPlayerCount() - 1) - .getLaidOut()); + assertTrue(roundState.getNthNextPlayer(-1).getLaidOut()); assertEquals(2, roundState.getTable().getSize()); - assertEquals(14, hand.getSize()); - } - - /** */ - @Test - public void testDealStones() { - testRound.deal(); - checkCorrectlyDealt(); - for (int i = 0; i < 14; i++) { - testRound.dealStones(2); - } - assertEquals(2 * 14 + 14, testRoundState.getActivePlayer().getHand() - .getSize()); + assertEquals(14, roundState.getNthNextPlayer(-1).getHand().getSize()); } /** */ @@ -512,6 +488,7 @@ public class RoundControlTest { /** */ @Test public void testTableValidHandChanged() { + fail(); testRoundState.players.get(0).setLaidOut(true); testRound.startRound(); for (int i = 0; i < 4; i++) { @@ -539,6 +516,7 @@ public class RoundControlTest { /** */ @Test public void testTableInvalidHandChanged() { + fail(); testRound.startRound(); for (int i = 0; i < 4; i++) { view.startTurnEvent.emit(); @@ -548,9 +526,9 @@ public class RoundControlTest { testTable.valid = false; oldTable.clonedTable = testTable; + IHand hand = testRoundState.getActivePlayer().getHand(); view.startTurnEvent.emit(); assertSame(BottomPanelType.HUMAN_HAND_PANEL, view.bottomPanelType); - IHand hand = testRound.clonedHand; Stone stone = hand.iterator().next().getFirst(); hand.pickUp(stone); testTable.drop(new StoneSet(stone), new Position(0, 0)); @@ -567,6 +545,7 @@ public class RoundControlTest { /** */ @Test public void testTableValidHandUnchanged() { + fail(); testRoundState.players.get(0).setLaidOut(true); testRound.startRound(); for (int i = 0; i < 4; i++) { @@ -592,6 +571,7 @@ public class RoundControlTest { /** */ @Test public void testTableInvalidHandUnchanged() { + fail(); testRoundState.players.get(1).setLaidOut(true); testRound.startRound(); for (int i = 0; i < 4; i++) { @@ -618,7 +598,6 @@ public class RoundControlTest { /** */ @Test public void testWinning() { - testRound.getEndOfRoundEvent().add(new IListener1() { @Override public void handle(Score roundScore) { @@ -635,14 +614,14 @@ public class RoundControlTest { testTable.valid = true; oldTable.clonedTable = testTable; - view.startTurnEvent.emit(); - assertSame(BottomPanelType.HUMAN_HAND_PANEL, view.bottomPanelType); - IHand hand = testRound.clonedHand; + IHand hand = testRoundState.getActivePlayer().getHand(); hand.drop(redEight, new Position(0, 0)); hand.drop(blueEight, new Position(0, 0)); hand.drop(blackEight, new Position(0, 0)); hand.drop(orangeEight, new Position(0, 0)); + view.startTurnEvent.emit(); + assertSame(BottomPanelType.HUMAN_HAND_PANEL, view.bottomPanelType); view.handPanel.stoneClickEvent.emit(redEight, false); view.handPanel.stoneClickEvent.emit(blueEight, true); @@ -651,91 +630,21 @@ public class RoundControlTest { view.tablePanel.clickEvent.emit(new Position(0, 0)); - for (int i = 0; i < 4; i++) { - testRoundState.players.get(i).hand = new Hand(); + view.playerPanel.endTurnEvent.emit(); + + for (int i = 0; i < 3; i++) { + view.startTurnEvent.emit(); + view.playerPanel.endTurnEvent.emit(); } - testRound.clonedHand = (IHand) testRoundState.players.get(3).hand.clone(); - resetTurnStart(); + + testRoundState.getActivePlayer().setHand(new Hand()); + view.startTurnEvent.emit(); assertFalse(roundEnded); view.playerPanel.endTurnEvent.emit(); assertTrue(roundEnded); } - /** */ - @Test - public void testTableDifference() { - MockTable oldTable = new MockTable(); - MockTable newTable = new MockTable(); - StoneSet oldSet1 = new StoneSet(Arrays.asList(blueOne, redOne, blackOne)); - StoneSet oldSet2 = new StoneSet(blueTwo); - oldTable.drop(oldSet1, new Position(0, 0)); - oldTable.drop(oldSet2, new Position(0, 0)); - StoneSet newSet1 = new StoneSet(Arrays.asList(blueOne, blueTwo, blueFour)); - StoneSet newSet2 = new StoneSet(Arrays.asList(redOne, blackOne, blueThree)); - newTable.drop(newSet1, new Position(0, 0)); - newTable.drop(newSet2, new Position(0, 0)); - - Set expectedStones = new HashSet(); - expectedStones.add(blueThree); - expectedStones.add(blueFour); - - Set stones = RoundControl.tableDifference(oldTable, newTable); - - assertTrue(expectedStones.containsAll(stones)); - assertTrue(stones.containsAll(expectedStones)); - } - - /** */ - @Test - public void testTableSetDifference() { - ITable oldTable = new Table(gameSettings); - Stone blueOne = new Stone(1, BLUE); - Stone redOne = new Stone(1, RED); - Stone blackOne = new Stone(1, BLACK); - Stone orangeOne = new Stone(1, ORANGE); - Stone blueTwo = new Stone(2, BLUE); - Stone blueThree = new Stone(3, BLUE); - Stone blueFour = new Stone(4, BLUE); - StoneSet oldSet1 = new StoneSet(Arrays.asList(blueOne, redOne, blackOne, - orangeOne)); - StoneSet oldSet2 = new StoneSet(Arrays.asList(blueTwo, blueThree, blueFour)); - oldTable.drop(oldSet1, new Position(0, 0)); - oldTable.drop(oldSet2, new Position(0, 0)); - ITable newTable = (Table) oldTable.clone(); - List newSets = RoundControl - .tableSetDifference(oldTable, newTable); - List vanishedSets = RoundControl.tableSetDifference(newTable, - oldTable); - - assertTrue(newSets.isEmpty()); - assertTrue(vanishedSets.isEmpty()); - - newTable.pickUp(oldSet2); - newTable.drop(oldSet2.join(new StoneSet(new Stone(5, BLUE))), new Position( - 0, 0)); - newSets = RoundControl.tableSetDifference(oldTable, newTable); - vanishedSets = RoundControl.tableSetDifference(newTable, oldTable); - - assertFalse(newSets.isEmpty()); - assertFalse(vanishedSets.isEmpty()); - assertEquals(1, newSets.size()); - assertEquals(1, vanishedSets.size()); - - Stone redTwo = new Stone(2, RED); - Stone redThree = new Stone(3, RED); - Stone redFour = new Stone(4, RED); - StoneSet oldSet3 = new StoneSet(Arrays.asList(redTwo, redThree, redFour)); - ITable newTable2 = (Table) oldTable.clone(); - newTable2.drop(oldSet3, new Position(0, 0)); - newSets = RoundControl.tableSetDifference(oldTable, newTable2); - vanishedSets = RoundControl.tableSetDifference(newTable2, oldTable); - - assertFalse(newSets.isEmpty()); - assertTrue(vanishedSets.isEmpty()); - assertEquals(1, newSets.size()); - } - /** */ @Test public void heapIsEmpty() { @@ -899,12 +808,12 @@ public class RoundControlTest { @Test public void testRedealDisallowed() { testRound.startRound(); - view.startTurnEvent.emit(); Hand hand = new Hand(); hand.drop(new Stone(1, RED), new Position(0, 0)); hand.drop(new Stone(1, BLACK), new Position(0, 0)); hand.drop(new Stone(1, BLUE), new Position(0, 0)); - testRound.clonedHand = hand; + testRoundState.players.get(0).hand = hand; + view.startTurnEvent.emit(); assertEquals(TurnMode.INSPECT_ONLY, view.playerPanel.turnMode); for (int i = 0; i < 4; i++) { view.playerPanel.endTurnEvent.emit(); @@ -922,7 +831,6 @@ public class RoundControlTest { hand.drop(new Stone(i / 2 + 1, RED), new Position(0, 0)); } testRoundState.players.get(0).hand = hand; - testRound.clonedHand = (IHand) hand.clone(); view.startTurnEvent.emit(); assertEquals(TurnMode.MAY_REDEAL, view.playerPanel.turnMode); for (int i = 0; i < 4; i++) { diff --git a/test/jrummikub/control/turn/TurnControlTest.java b/test/jrummikub/control/turn/TurnControlTest.java index 98b1852..9e89a57 100644 --- a/test/jrummikub/control/turn/TurnControlTest.java +++ b/test/jrummikub/control/turn/TurnControlTest.java @@ -182,12 +182,13 @@ public class TurnControlTest { eventFired = false; mockTimer.timerRunning = true; - testControl.getEndOfTurnEvent().add(new IListener3() { - @Override - public void handle(IHand oldHand, ITable oldTable, ITable newTable) { - eventFired = true; - } - }); + testControl.getEndOfTurnEvent().add( + new IListener3() { + @Override + public void handle(IHand oldHand, ITable oldTable, ITable newTable) { + eventFired = true; + } + }); mockView.playerPanel.endTurnEvent.emit(); @@ -204,12 +205,13 @@ public class TurnControlTest { eventFired = false; mockTimer.timerRunning = true; - testControl.getEndOfTurnEvent().add(new IListener3() { - @Override - public void handle(IHand oldHand, ITable oldTable, ITable newTable) { - eventFired = true; - } - }); + testControl.getEndOfTurnEvent().add( + new IListener3() { + @Override + public void handle(IHand oldHand, ITable oldTable, ITable newTable) { + eventFired = true; + } + }); mockTimer.timeRunOutEvent.emit(); @@ -1013,4 +1015,78 @@ public class TurnControlTest { assertEquals(expected, handStones); } + /** */ + @Test + public void testTableDifference() { + MockTable oldTable = new MockTable(); + MockTable newTable = new MockTable(); + StoneSet oldSet1 = new StoneSet(Arrays.asList(blueOne, redOne, blackOne)); + StoneSet oldSet2 = new StoneSet(blueTwo); + oldTable.drop(oldSet1, new Position(0, 0)); + oldTable.drop(oldSet2, new Position(0, 0)); + StoneSet newSet1 = new StoneSet(Arrays.asList(blueOne, blueTwo, blueFour)); + StoneSet newSet2 = new StoneSet(Arrays.asList(redOne, blackOne, blueThree)); + newTable.drop(newSet1, new Position(0, 0)); + newTable.drop(newSet2, new Position(0, 0)); + + Set expectedStones = new HashSet(); + expectedStones.add(blueThree); + expectedStones.add(blueFour); + + Set stones = AbstractTurnControl.tableDifference(oldTable, newTable); + + assertTrue(expectedStones.containsAll(stones)); + assertTrue(stones.containsAll(expectedStones)); + } + + /** */ + @Test + public void testTableSetDifference() { + ITable oldTable = new AccessibleTable(); + Stone blueOne = new Stone(1, BLUE); + Stone redOne = new Stone(1, RED); + Stone blackOne = new Stone(1, BLACK); + Stone orangeOne = new Stone(1, ORANGE); + Stone blueTwo = new Stone(2, BLUE); + Stone blueThree = new Stone(3, BLUE); + Stone blueFour = new Stone(4, BLUE); + StoneSet oldSet1 = new StoneSet(Arrays.asList(blueOne, redOne, blackOne, + orangeOne)); + StoneSet oldSet2 = new StoneSet(Arrays.asList(blueTwo, blueThree, blueFour)); + oldTable.drop(oldSet1, new Position(0, 0)); + oldTable.drop(oldSet2, new Position(0, 0)); + ITable newTable = (Table) oldTable.clone(); + List newSets = AbstractTurnControl.tableSetDifference(oldTable, + newTable); + List vanishedSets = AbstractTurnControl.tableSetDifference( + newTable, oldTable); + + assertTrue(newSets.isEmpty()); + assertTrue(vanishedSets.isEmpty()); + + newTable.pickUp(oldSet2); + newTable.drop(oldSet2.join(new StoneSet(new Stone(5, BLUE))), new Position( + 0, 0)); + newSets = AbstractTurnControl.tableSetDifference(oldTable, newTable); + vanishedSets = AbstractTurnControl.tableSetDifference(newTable, oldTable); + + assertFalse(newSets.isEmpty()); + assertFalse(vanishedSets.isEmpty()); + assertEquals(1, newSets.size()); + assertEquals(1, vanishedSets.size()); + + Stone redTwo = new Stone(2, RED); + Stone redThree = new Stone(3, RED); + Stone redFour = new Stone(4, RED); + StoneSet oldSet3 = new StoneSet(Arrays.asList(redTwo, redThree, redFour)); + ITable newTable2 = (Table) oldTable.clone(); + newTable2.drop(oldSet3, new Position(0, 0)); + newSets = AbstractTurnControl.tableSetDifference(oldTable, newTable2); + vanishedSets = AbstractTurnControl.tableSetDifference(newTable2, oldTable); + + assertFalse(newSets.isEmpty()); + assertTrue(vanishedSets.isEmpty()); + assertEquals(1, newSets.size()); + } + } -- cgit v1.2.3