blob: 536a0790b667d92be520078847a542ed531fc068 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2011, 2019 SAP SE
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* SAP SE - initial API, implementation and documentation
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.graphiti.examples.chess;
import org.eclipse.graphiti.examples.mm.chess.Board;
import org.eclipse.graphiti.examples.mm.chess.Colors;
import org.eclipse.graphiti.examples.mm.chess.Files;
import org.eclipse.graphiti.examples.mm.chess.Piece;
import org.eclipse.graphiti.examples.mm.chess.Ranks;
import org.eclipse.graphiti.examples.mm.chess.Square;
import org.eclipse.graphiti.examples.mm.chess.Types;
public final class MoveUtil {
public static final String PROPERTY_MOVE = "move"; //$NON-NLS-1$
private MoveUtil() {
super();
}
public static boolean isMoveAllowed(Piece piece, Square sourceSquare, Square targetSquare) {
// Moving onto a square occupied by another own piece is not allowed
if (targetSquare.getPiece() != null && targetSquare.getPiece().getOwner().equals(piece.getOwner())) {
return false;
}
// Determine number of steps taken in file and rank direction
int fileSteps = targetSquare.getFile().getValue() - sourceSquare.getFile().getValue();
int rankSteps = targetSquare.getRank().getValue() - sourceSquare.getRank().getValue();
// Check type specific moving rules
if (Types.PAWN.equals(piece.getType())) {
// Same file
if (fileSteps == 0) {
// White pawns move upwards to higher ranks
if (Colors.LIGHT.equals(piece.getOwner())) {
if (rankSteps == 1 || (rankSteps == 2 && Ranks.TWO.equals(sourceSquare.getRank()) && sourceSquare
.getBoard().getSquare(Ranks.THREE, sourceSquare.getFile()).getPiece() == null)) {
// Allow to move 1 to front or 2 to front in case of
// start position
return targetSquare.getPiece() == null;
}
}
// Black pawns move downwards to lower ranks
else {
if (rankSteps == -1
|| (rankSteps == -2 && Ranks.SEVEN.equals(sourceSquare.getRank()) && sourceSquare.getBoard()
.getSquare(Ranks.SIX, sourceSquare.getFile()).getPiece() == null)) {
// Allow to move 1 to front or 2 to front in case of
// start position
return targetSquare.getPiece() == null;
}
}
}
// Neighbour file
else if (fileSteps == 1 || fileSteps == -1) {
// White pawns move upwards to higher ranks
if (Colors.LIGHT.equals(piece.getOwner())) {
// Allow to move 1 to front
if (rankSteps == 1) {
// Allow taking diagonally
return targetSquare.getPiece() != null
&& targetSquare.getPiece().getOwner() != piece.getOwner();
}
}
// Black pawns move downwards to lower ranks
else {
// Allow to move 1 to front
if (rankSteps == -1) {
// Allow taking diagonally
return targetSquare.getPiece() != null
&& targetSquare.getPiece().getOwner() != piece.getOwner();
}
}
}
return false;
} else if (Types.KING.equals(piece.getType())) {
// Kings are allowed to move either horizontally, vertically or
// diagonally but just one step
if (rankSteps >= -1 && rankSteps <= 1 && fileSteps >= -1 && fileSteps <= 1) {
// Allow moving one to every side and diagonally and taking
// other owner's pieces
return targetSquare.getPiece() == null || targetSquare.getPiece().getOwner() != piece.getOwner();
}
return false;
} else if (Types.ROOK.equals(piece.getType())) {
// Rooks are allowed to move either horizontally or vertically
return allowMovingToSides(sourceSquare, targetSquare, fileSteps, rankSteps);
} else if (Types.BISHOP.equals(piece.getType())) {
// Bishops are allowed to move diagonally
return allowDiagonalMoving(sourceSquare, targetSquare, fileSteps, rankSteps);
} else if (Types.QUEEN.equals(piece.getType())) {
// Queens are allowed to move either horizontally, vertically or
// diagonally
return allowMovingToSides(sourceSquare, targetSquare, fileSteps, rankSteps)
|| allowDiagonalMoving(sourceSquare, targetSquare, fileSteps, rankSteps);
} else if (Types.KNIGHT.equals(piece.getType())) {
// For one direction the gap needs to be 1, for the other it
// needs to be 2. Jumping over other pieces is allowed for
// knights
if ((Math.abs(rankSteps) == 2 && Math.abs(fileSteps) == 1)
|| (Math.abs(rankSteps) == 1 && Math.abs(fileSteps) == 2)) {
return true;
}
return false;
}
// Should never get here
throw new IllegalStateException("Invalid Piece type: " + piece.getType()); //$NON-NLS-1$
}
private static boolean allowMovingToSides(Square sourceSquare, Square targetSquare, int fileGap, int rankGap) {
Board board = sourceSquare.getBoard();
// Same rank --> horizontal move
if (rankGap == 0) {
// Check if any square in between is occupied, if yes the move is
// not allowed
int from = Math.min(sourceSquare.getFile().getValue(), targetSquare.getFile().getValue());
int to = Math.max(sourceSquare.getFile().getValue(), targetSquare.getFile().getValue());
for (int i = from + 1; i < to; i++) {
if (board.getSquare(sourceSquare.getRank(), Files.get(i)).getPiece() != null) {
// Move over occupied square
return false;
}
}
// No occupied square in between --> allow
return true;
}
// Same file --> vertical move
if (fileGap == 0) {
// Check if any square in between is occupied, if yes the move is
// not allowed
int from = Math.min(sourceSquare.getRank().getValue(), targetSquare.getRank().getValue());
int to = Math.max(sourceSquare.getRank().getValue(), targetSquare.getRank().getValue());
for (int i = from + 1; i < to; i++) {
if (board.getSquare(Ranks.get(i), sourceSquare.getFile()).getPiece() != null) {
// Move over occupied square
return false;
}
}
// No occupied square in between --> allow
return true;
}
return false;
}
private static boolean allowDiagonalMoving(Square sourceSquare, Square targetSquare, int fileGap, int rankGap) {
Board board = sourceSquare.getBoard();
if (Math.abs(rankGap) == Math.abs(fileGap)) {
// Allow moving diagonally
int fromRank = Math.min(sourceSquare.getRank().getValue(), targetSquare.getRank().getValue());
int toRank = Math.max(sourceSquare.getRank().getValue(), targetSquare.getRank().getValue());
// Determine if the rank and file directions are the same (upward or
// downwards); in case not we need to reverse file direction
// counting
int fileDirection = 1;
if (sourceSquare.getFile().getValue() > targetSquare.getFile().getValue()) {
fileDirection = -1;
}
// Check if any square in between is occupied, if yes the move is
// not allowed
for (int i = 1; i < toRank - fromRank; i++) {
if (board
.getSquare(Ranks.get(fromRank + i),
Files.get(sourceSquare.getFile().getValue() + (i * fileDirection)))
.getPiece() != null) {
// Move over occupied square
return false;
}
}
// Move is ok
return true;
}
// Move is not diagonal, not ok
return false;
}
}