diff options
Diffstat (limited to 'src/jrummikub/control/RoundControl.java')
-rw-r--r-- | src/jrummikub/control/RoundControl.java | 254 |
1 files changed, 68 insertions, 186 deletions
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<StoneSet> invalidSets; + + public InvalidTurnInfo(ITable table, InvalidTurnType type, + Collection<StoneSet> invalidSets) { + this.table = (ITable) table.clone(); + this.type = type; + this.invalidSets = new ArrayList<StoneSet>(invalidSets); + } + + public ITable getTable() { + return table; + } + + public InvalidTurnType getType() { + return type; + } + + public List<StoneSet> getInvalidSets() { + return invalidSets; + } + } + 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>(); protected List<Connection> connections = new ArrayList<Connection>(); 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<IHand, ITable, ITable>() { + new IListener2<IRoundState, InvalidTurnInfo>() { @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<StoneSet> 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<StoneSet> invalidStoneSets(ITable newTable) { - List<StoneSet> invalidSets = new ArrayList<StoneSet>(); - for (Pair<StoneSet, Position> set : newTable) { - if (set.getFirst().isValid(roundState.getGameSettings())) { - continue; + if (wasAI) { + nextPlayer(); } - invalidSets.add(set.getFirst()); + return; } - return invalidSets; - } - private List<StoneSet> touchedStoneSets(IHand oldHand, ITable oldTable, - ITable newTable) { - List<StoneSet> touchedSets = new ArrayList<StoneSet>(); - 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<Stone> 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<Stone> tableDiff = tableDifference(oldTable, newTable); - // deal penalty, reset - roundState.getGameHeap().putBack(tableDiff); - roundState.getActivePlayer().setLastTurnInvalid(true); - dealPenalty(tableDiff.size()); - - } - - static Set<Stone> tableDifference(ITable oldTable, ITable newTable) { - Set<Stone> ret = new HashSet<Stone>(); - - for (Pair<StoneSet, Position> entry : newTable) { - for (Stone stone : entry.getFirst()) { - ret.add(stone); - } - } - for (Pair<StoneSet, Position> entry : oldTable) { - for (Stone stone : entry.getFirst()) { - ret.remove(stone); - } - } - return ret; - } - - static List<StoneSet> tableSetDifference(ITable oldTable, ITable newTable) { - List<StoneSet> ret = new ArrayList<StoneSet>(); - - for (Pair<StoneSet, Position> entry : newTable) { - ret.add(entry.getFirst()); - } - for (Pair<StoneSet, Position> 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(); |