package gameengine.operations; import PBFT.TChineseCheckersOperation; import PBFT.TOperation; import gameengine.*; /** * Created by andrew on 11/30/14. */ public class MovePiece implements statemachine.Operation<ChineseCheckersState> { private final HexPoint start; public HexPoint getStart() { return start; } public HexPoint getEnd() { return end; } public int getReplicaID() { return replicaID; } private final HexPoint end; private final int replicaID; public MovePiece(int replicaID, HexPoint start, HexPoint end) { this.replicaID = replicaID; this.start = start; this.end = end; } public MovePiece(int replicaID, int q1, int r1, int q2, int r2) { this.replicaID = replicaID; this.start = new HexPoint(q1, r1); this.end = new HexPoint(q2, r2); } @Override public void apply(ChineseCheckersState state) { boolean lastMove = start.equals(end) || start.isNeighbor(end); state.getSpot(start).moveOccupantTo(state.getSpot(end)); if(lastMove) state.nextActivePlayer(); } @Override public void undo(ChineseCheckersState state) { boolean lastMove = start.equals(end) || start.isNeighbor(end); state.getSpot(end).moveOccupantTo(state.getSpot(start)); if(lastMove) state.prevActivePlayer(); } @Override public boolean isValid(ChineseCheckersState state) { ChineseCheckersSpot startSpot = state.getSpot(start); ChineseCheckersSpot endSpot = state.getSpot(end); if(startSpot == null || endSpot == null) return false; // Both spots must be within board bounds if(startSpot.getOccupant() == null) return false; // Must move from full spot Player current = state.getCurrentPlayer(); if(this.replicaID != current.getReplicaId()) return false; // Only current player may request a move if(startSpot.getOccupant() != current) return false; // And player can only move own piece HexPoint moveDelta = end.subtract(start); if (moveDelta.isZero()) return true; // Player passes // If not passing must move to empty spot if(endSpot.getOccupant() != null) return false; // Step to adjacent hex if (end.isNeighbor(start)) return true; // Jump over hex for(HexDirection dir : HexDirection.values()){ HexPoint dirOffset = dir.getOffset(); // If jump in this direction: allowed iff middle spot not empty if(dirOffset.scale(2).equals(moveDelta)){ HexPoint midpoint = start.add(dirOffset); return !state.getSpot(midpoint).isEmpty(); } } return false; } @Override public TOperation serialize() { TOperation tOperation = new TOperation(); tOperation.setArguments(start.toString() + "," + end.toString() + "," + replicaID); tOperation.setOperationType(TChineseCheckersOperation.MOVE_PIECE.getValue()); return tOperation; } @Override public String toString() { return "MOVE," + start.toString() + "," + end.toString(); } }