diff options
Diffstat (limited to 'src/jrummikub/control/turn/AbstractTurnControl.java')
-rw-r--r-- | src/jrummikub/control/turn/AbstractTurnControl.java | 169 |
1 files changed, 165 insertions, 4 deletions
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<IHand, ITable, ITable> endOfTurnEvent = new Event3<IHand, ITable, ITable>(); + protected Event2<IRoundState, InvalidTurnInfo> endOfTurnEvent = new Event2<IRoundState, InvalidTurnInfo>(); protected Event redealEvent = new Event(); protected Event1<ITable> tableUpdateEvent = new Event1<ITable>(); protected TurnInfo turnInfo; @@ -33,7 +44,7 @@ public abstract class AbstractTurnControl implements ITurnControl { private boolean started = false; @Override - public IEvent3<IHand, ITable, ITable> getEndOfTurnEvent() { + public IEvent2<IRoundState, InvalidTurnInfo> 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.<StoneSet> 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<Stone> 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.<StoneSet> emptyList()); + } + + private List<StoneSet> invalidStoneSets() { + List<StoneSet> invalidSets = new ArrayList<StoneSet>(); + for (Pair<StoneSet, Position> set : turnInfo.getTable()) { + if (set.getFirst().isValid(turnInfo.getRoundState().getGameSettings())) { + continue; + } + invalidSets.add(set.getFirst()); + } + return invalidSets; + } + + private List<StoneSet> touchedStoneSets() { + List<StoneSet> touchedSets = new ArrayList<StoneSet>(); + 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<StoneSet> 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<Stone> 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<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; + } }
\ No newline at end of file |