summaryrefslogtreecommitdiffstats
path: root/src/jrummikub/control/turn/AbstractTurnControl.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jrummikub/control/turn/AbstractTurnControl.java')
-rw-r--r--src/jrummikub/control/turn/AbstractTurnControl.java169
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