/******************************************************************************* * <copyright> * * Copyright (c) 2011, 2011 SAP AG. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * SAP AG - initial API, implementation and documentation * * </copyright> * *******************************************************************************/ 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; } }