package chess; import java.util.Vector; /* * ProcessedLine.java * * Created on February 10, 2007, 5:10 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ /** * * @author Stanislav Hromek */ public class Move { // indicates number of move, eg 5. private int moveNumber; // the move of white, eg. Ke2-e3 private String whiteMove; // the move of black, eg. Qa1xh8 private String blackMove; // flag if this is short (Kxe3) or long (Ke2xe3) notation public static final int UNKNOWN = 0; public static final int SHORT_NOTATION = 1; public static final int LONG_NOTATION = 2; // public static int notationType = UNKNOWN; /** Creates a new instance of ProcessedLine */ public Move(int moveNumber, String whiteMove, String blackMove) { this.moveNumber = moveNumber; this.whiteMove = whiteMove; this.blackMove = blackMove; } public Move(int moveNumber, String whiteMove) { this.moveNumber = moveNumber; this.whiteMove = whiteMove; } protected int getMoveNumber() { return moveNumber; } protected String getWhiteMove() { return whiteMove; } protected String getBlackMove() { return blackMove; } /** * checks the possibility of the move * * rem should be treated with exceptions (pieceInTheLineOfMoveException), but i don't know * how its in JavaScript, so we have only setting of error message */ protected boolean isMovePossible(Board board, String color, CurrentMoveInfo currentMoveInfo) { // get all the info from string if( ! extractInfoFromString(color, currentMoveInfo).result) return false; System.out.println("currentMoveInfo="+currentMoveInfo); // tests if end move board square contains st. and if yes if it is opponent piece (should be exchange) if( ! isEndingPositionOk(board, color, currentMoveInfo).result) return false; if(currentMoveInfo.notation == Move.LONG_NOTATION){ // tests if start move board square contains piece (by O-O king no move yet and so on) if( ! isStartingPositionOk(board, color, currentMoveInfo).result) return false; // test if move is according to chess rules, eg. rook moves horizontal, bishop diagonal, ... if( ! isPossibleToMoveToEndSquare(board, color, currentMoveInfo).result) return false; // tests if it can move (nothing in line of move, correct move of pieces, ...) if( ! isRoadOk(board, color, currentMoveInfo).result) return false; } else if(currentMoveInfo.notation == Move.SHORT_NOTATION){ if( ! isMovePossibleShort(board, color, currentMoveInfo).result) return false; } return true; } protected CurrentMoveInfo isMovePossibleShort(Board board, String color, CurrentMoveInfo currentMoveInfo) { // test ending position ok, done before Square[][] squares = board.getSquares(); Vector foundSquares = new Vector(); CurrentMoveInfo tempCurrentMoveInfo = currentMoveInfo.clone(); tempCurrentMoveInfo.isErrorMessageAllowed = false; // go through all squares for (int i = 0; i < squares.length; i++) { for (int j = 0; j < squares.length; j++) { // take square tempCurrentMoveInfo.movePieceFrom = squares[i][j].getName(); //System.out.println("squares[i][j].getName()="+squares[i][j].getName()); // find out, if it contains piece, and if piece and color matches from currentMoveInfo if( ! isStartingPositionOk(board, color, tempCurrentMoveInfo).result) // go to the next square continue; // test if this square fits to movePieceFrom (eg. from R3xe5 we will have 3) // (is test starting position ok), we have to take into account info in currentMoveInfo movePieceFrom if( ! additionalInfoFitsToSquareName(currentMoveInfo.movePieceFrom, tempCurrentMoveInfo.movePieceFrom)) continue; // if yes, test if possible to move to end square if( ! isPossibleToMoveToEndSquare(board, color, tempCurrentMoveInfo).result) continue; // test is road ok if( ! isRoadOk(board, color, tempCurrentMoveInfo).result) continue; // we have a square with current moving color and current moving piece // if(debug) System.out.println("correct square found"); foundSquares.add(squares[i][j].getName()); } } // if after all squares only one fits, is ok if(foundSquares.size() == 0){ Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". was not found piece to move to " + currentMoveInfo.movePieceTo; currentMoveInfo.result = false; return currentMoveInfo; } else if(foundSquares.size() == 1){ currentMoveInfo.movePieceFrom = (String)foundSquares.get(0); currentMoveInfo.result = true; return currentMoveInfo; } else{ Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is possible to move more pieces to " + currentMoveInfo.movePieceTo; currentMoveInfo.result = false; return currentMoveInfo; } } // should we check also the move number ? (like in enter 1, 2, 4, error message no move 3 ?, not now) protected boolean playMove(Board board, int moveNumber, String color) { CurrentMoveInfo currentMoveInfo = new CurrentMoveInfo(); Game.errorMessage = ""; // is this move possible ? if(isMovePossible(board, color, currentMoveInfo)) { // do the move doMove(board, currentMoveInfo); // set if last mowe was pawn by two setFlagForPawnExchange(board, currentMoveInfo, color); // do we have a check ? if(isCheck(board, color)) Game.errorMessage = "Move not allowed, king is in check."; if(isCheck(board, getOppositeColor(color))) Game.errorMessage = "Check."; // everything ok return true; } else { // some error occured return false; } } protected String getOppositeColor(String color){ if(color.equals("white")){ return "black"; } else{ return "white"; } } // todo, if move piece to some place next to board protected void doMove(Board board, CurrentMoveInfo currentMoveInfo) { // todo, if pawn exchange and previous pawn move two square, need to get rid of that pawn if(currentMoveInfo.getAction().endsWith("castle")) { // king Piece piece = board.getSquare(currentMoveInfo.movePieceFrom).getPiece(); board.getSquare(currentMoveInfo.movePieceFrom).setPiece(null); board.getSquare(currentMoveInfo.movePieceTo).setPiece(piece); // rook Piece pieceTwo = board.getSquare(currentMoveInfo.movePieceFromTwo).getPiece(); board.getSquare(currentMoveInfo.movePieceFromTwo).setPiece(null); board.getSquare(currentMoveInfo.movePieceToTwo).setPiece(pieceTwo); } else{ Piece piece = board.getSquare(currentMoveInfo.movePieceFrom).getPiece(); board.getSquare(currentMoveInfo.movePieceFrom).setPiece(null); if(currentMoveInfo.promotingPiece != null) board.getSquare(currentMoveInfo.movePieceTo).setPiece(currentMoveInfo.promotingPiece); else board.getSquare(currentMoveInfo.movePieceTo).setPiece(piece); } } protected boolean setFlagForPawnExchange(Board board, CurrentMoveInfo currentMoveInfo, String color){ // was it pawn if( ! currentMoveInfo.currentMovingPiece.equals("pawn")) return false; // did it move by two ? if( ! board.isTwoForward(color, currentMoveInfo.movePieceFrom, currentMoveInfo.movePieceTo)) return false; // it pawn and it moved by two, set flag Game.previousPawnMove = board.getSquaresVertical(currentMoveInfo.movePieceFrom, currentMoveInfo.movePieceTo)[0].getName(); return true; } /** for color returns move string eg. white gives result e2-e4 */ protected String blackOrWhite(String color) { if(color.equals("white")) return whiteMove; else if(color.equals("black")) return blackMove; else { assert false; return null; } } public static void setPiecesSymbols(String king, String queen, String rook, String bishop, String knight, String pawn){ pawnSymbol = pawn; rookSymbol = rook; knightSymbol = knight; bishopSymbol = bishop; queenSymbol = queen; kingSymbol = king; } // careful, pawn symbol is not done, see for example next method, if pawn symbol is not "", // it would give wrong output, does any country has a symbol for pawn in notation ? static String pawnSymbol = ""; static String rookSymbol = "R"; static String knightSymbol = "Kn"; static String bishopSymbol = "B"; static String queenSymbol = "Q"; static String kingSymbol = "K"; // todo, chande to return piece, get rid of castle, and move approp. things from this class to pieces // eg. piece.isStartingPositionOk and so on // i tried it, but didn't like it protected String getMovingPiece(String move) { // its dummy, doesn't matter if its black or white' String color = "white"; if(move.startsWith(knightSymbol)) return new Knight(color).getName(); // need some dummy color else if(move.startsWith(kingSymbol)) return new King(color).getName(); else if(move.startsWith(rookSymbol)) return new Rook(color).getName(); else if(move.startsWith(bishopSymbol)) return new Bishop(color).getName(); else if(move.startsWith(queenSymbol)) return new Queen(color).getName(); else if(move.startsWith("0") || move.startsWith("O")){ // zero and big o, look the same, but are different return "castle"; } else if(move.startsWith("a") || move.startsWith("b") || move.startsWith("c") || move.startsWith("d") || move.startsWith("e") || move.startsWith("f") || move.startsWith("g") || move.startsWith("h")) return new Pawn(color).getName(); else return null; } protected CurrentMoveInfo extractInfoFromString(String color, CurrentMoveInfo currentMoveInfo) { // get move for color String move = blackOrWhite(color); if(move == null) return null; // remove not important chars at the end (like -/+!?), solution: go from back until letter or number found // if we use length of string for getting the start square, we have to trim all '!?+=' chars String trimmedMove = trimNotUsedChars(move); // test from end if its piece (by promoting pawn it can be queen, knight, ...) currentMoveInfo.promotingPiece = getPromotingPiece(trimmedMove, color); // if found, cut piece from the end of the string String moveWithoutPromotingPiece = trimmedMove; if(currentMoveInfo.promotingPiece != null) moveWithoutPromotingPiece = removePromotingPiece(trimmedMove, currentMoveInfo.promotingPiece.getName()); // test from beginning if its piece currentMoveInfo.currentMovingPiece = getMovingPiece(trimmedMove); // was error ? if(currentMoveInfo.currentMovingPiece == null) { Game.errorMessage = "Unknown piece in " + color + " move " + this.getMoveNumber() + ". "; currentMoveInfo.result = false; return currentMoveInfo; } // if found, cut piece from the beginning of the string String moveWithoutPiece = removePiece(moveWithoutPromotingPiece, currentMoveInfo.currentMovingPiece); // the rest can be: e2-e4 or exf7 or f7 or gg7 or 0-0 // exchange or move or castle if(this.isCastle(trimmedMove)){ // or use current moving piece = castle, .contains("castle") // handle O-O currentMoveInfo.setAction(this.getCastleType(trimmedMove)); if(currentMoveInfo.getAction() == null) { Game.errorMessage = "Unknown castle type in "+color+" move " + this.getMoveNumber() + ". "; currentMoveInfo.result = false; return currentMoveInfo; } // from, two pieces getStartSquaresForCastle(color, currentMoveInfo); getEndSquaresForCastle(color, currentMoveInfo); } else{ // get end square, solution: take 2 chars from the end // to currentMoveInfo.movePieceTo = getEndSquare(moveWithoutPiece); // was error ? if(currentMoveInfo.movePieceTo == null) { Game.errorMessage = "Unknown ending square in "+color+" move " + this.getMoveNumber() + ". "; currentMoveInfo.result = false; return currentMoveInfo; } // cut last 2 chars, test if last not letter or number (can be x or - ), if not, get action String moveWithoutEndSquare = removeEndSquare(moveWithoutPiece); // what left can be (e4 or e or 4 or nothing), by 2 chars its long notation, otherwise is short notation // action is always something, default is move currentMoveInfo.setAction(getAction(moveWithoutEndSquare, currentMoveInfo)); String moveWithoutAction = removeActionSquare(moveWithoutEndSquare); // now we will get type of notation too, defaault is short, only sometimes is long or error // from, one piece currentMoveInfo.movePieceFrom = getStartSquare(moveWithoutAction); // was error ? if(currentMoveInfo.movePieceFrom == null) { Game.errorMessage = "Unknown starting square in "+color+" move " + this.getMoveNumber() + ". "; currentMoveInfo.result = false; return currentMoveInfo; } if(currentMoveInfo.movePieceFrom.length() == 0){ currentMoveInfo.notation = Move.SHORT_NOTATION; } else if(currentMoveInfo.movePieceFrom.length() == 1){ currentMoveInfo.notation = Move.SHORT_NOTATION; } else if(currentMoveInfo.movePieceFrom.length() == 2){ currentMoveInfo.notation = Move.LONG_NOTATION; } else{ Game.errorMessage = "Unknown notation in "+color+" move " + this.getMoveNumber() + ". "; currentMoveInfo.result = false; return currentMoveInfo; } // if pawn reached the last line, it should be promoted, here find out for what if(currentMoveInfo.currentMovingPiece.equals("pawn")) { // its pawn, now find out, if it reached last line if(isLastLine(color, currentMoveInfo)){ // there should be set info about promoting piece already } else{ currentMoveInfo.promotingPiece = null; } } } currentMoveInfo.result = true; return currentMoveInfo; } protected boolean isLastLine(String color, CurrentMoveInfo currentMoveInfo){ if(color.equals("white") && currentMoveInfo.movePieceTo.substring(1,2).equals("8")) return true; else if(color.equals("black") && currentMoveInfo.movePieceTo.substring(1,2).equals("1")) return true; else return false; } protected CurrentMoveInfo getStartSquaresForCastle(String color, CurrentMoveInfo currentMoveInfo) { if(color.equals("white")) { if(currentMoveInfo.getAction().equals("small castle")) { currentMoveInfo.movePieceFrom = "e1"; currentMoveInfo.movePieceFromTwo = "h1"; } else if(currentMoveInfo.getAction().equals("big castle")) { currentMoveInfo.movePieceFrom = "e1"; currentMoveInfo.movePieceFromTwo = "a1"; } else assert false; } else if(color.equals("black")){ if(currentMoveInfo.getAction().equals("small castle")) { currentMoveInfo.movePieceFrom = "e8"; currentMoveInfo.movePieceFromTwo = "h8"; } else if(currentMoveInfo.getAction().equals("big castle")) { currentMoveInfo.movePieceFrom = "e8"; currentMoveInfo.movePieceFromTwo = "a8"; } else assert false; } else // unknown color assert false; return currentMoveInfo; } protected CurrentMoveInfo getEndSquaresForCastle(String color, CurrentMoveInfo currentMoveInfo) { if(color.equals("white")) { if(currentMoveInfo.getAction().equals("small castle")) { currentMoveInfo.movePieceTo = "g1"; currentMoveInfo.movePieceToTwo = "f1"; } else if(currentMoveInfo.getAction().equals("big castle")) { currentMoveInfo.movePieceTo = "c1"; currentMoveInfo.movePieceToTwo = "d1"; } else assert false; } else if(color.equals("black")){ if(currentMoveInfo.getAction().equals("small castle")) { currentMoveInfo.movePieceTo = "g8"; currentMoveInfo.movePieceToTwo = "f8"; } else if(currentMoveInfo.getAction().equals("big castle")) { currentMoveInfo.movePieceTo = "c8"; currentMoveInfo.movePieceToTwo = "d8"; } else assert false; } else // unknown color assert false; return currentMoveInfo; } protected String getStartSquare(String move) { if(move.length() == 0){ return move; } else if(move.length() == 1){ return move; } else if(move.length() == 2){ return move; } else return null; } protected String getEndSquare(String move) { // index should be already checked if(move.length() >= 2) return move.substring(move.length()-2, move.length()); else return move; } protected boolean isCastle(String move){ if(move.equals("0-0") || move.equals("O-O") || move.equals("0-0-0") || move.equals("O-O-O")) return true; else return false; } protected String getCastleType(String move){ if(move.equals("0-0") || move.equals("O-O") ) return "small castle"; else if(move.equals("0-0-0") || move.equals("O-O-O")) return "big castle"; else return null; } /** * extracts action depending on the last char * @return move or exchange, move returned by default */ protected String getAction(String move, CurrentMoveInfo currentMoveInfo) { if(move.endsWith("-")) return "move"; else if(move.endsWith("x")) return "exchange"; else return "move"; } protected CurrentMoveInfo isStartingPositionOk(Board board, String color, CurrentMoveInfo currentMoveInfo) { //result currentMoveInfo.result = true; Square startSquare = board.getSquare(currentMoveInfo.movePieceFrom); Piece piece = startSquare.getPiece(); if(currentMoveInfo.getAction().endsWith("castle")) { // test if king is on the starting position and has not moved yet if(! isStartingPositionOkTwo(new King(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } // not very safe, casting without check of class, but has it javascript ? if(((King)piece).hasMoved() ) { Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is error, "+piece.getName()+" already moved"; currentMoveInfo.result = false; return currentMoveInfo; } // the same with rook, test if rook is on the starting position and has not moved yet startSquare = board.getSquare(currentMoveInfo.movePieceFromTwo); piece = startSquare.getPiece(); if(! isStartingPositionOkTwo(new Rook(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } if(((Rook)piece).hasMoved() ) { Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is error, "+piece.getName()+" already moved"; currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("king")) { // king if(! isStartingPositionOkTwo(new King(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("queen")) { // queen if(! isStartingPositionOkTwo(new Queen(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("rook")) { // rook if(! isStartingPositionOkTwo(new Rook(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("knight")) { // knight if(! isStartingPositionOkTwo(new Knight(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("bishop")) { // bishop if(! isStartingPositionOkTwo(new Bishop(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("pawn")) { // pawn // todo, if on last line (eg. white e8, change to another piece) if(! isStartingPositionOkTwo(new Pawn(color).getName(), color, piece, startSquare, currentMoveInfo.isErrorMessageAllowed)) { currentMoveInfo.result = false; return currentMoveInfo; } } else{ currentMoveInfo.result = false; assert false; } return currentMoveInfo; } protected boolean isStartingPositionOkTwo(String name, String color, Piece piece, Square startSquare, boolean isErrorMessageAllowed) { if(piece == null) { if(isErrorMessageAllowed) Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is "+ name +" not at " + startSquare.getName(); return false; } if(! piece.getPieceColor().equals(color)) { if(isErrorMessageAllowed) Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is wrong piece color"; return false; } if(! (piece.getName().equals(name))) { // can this happen ? , sure, in short notation by testing all squares if(isErrorMessageAllowed) Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is wrong piece on "+piece.getName()+"s position"; return false; } return true; } // todo, if exchange, there should be opposite color piece // todo, should check, if end square reachable according to rules for moving piece protected CurrentMoveInfo isEndingPositionOk(Board board, String color, CurrentMoveInfo currentMoveInfo) { //result currentMoveInfo.result = true; Square endSquare = board.getSquare(currentMoveInfo.movePieceTo); Piece piece = endSquare.getPiece(); if(currentMoveInfo.getAction().endsWith("castle")) { // test if end square for king is empty if(piece != null){ Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is " + endSquare.getName() + "not empty"; currentMoveInfo.result = false; return currentMoveInfo; } // test if end square for rook is empty endSquare = board.getSquare(currentMoveInfo.movePieceToTwo); piece = endSquare.getPiece(); if(piece != null){ Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is " + endSquare.getName() + "not empty"; currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("king")) { // king if(! isEndingPositionOkTwo(color, piece, endSquare)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("queen")) { // queen if( ! isEndingPositionOkTwo(color, piece, endSquare)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("rook")) { // rook if( ! isEndingPositionOkTwo(color, piece, endSquare)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("knight")) { // knight if( ! isEndingPositionOkTwo(color, piece, endSquare)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("bishop")) { // bishop if( ! isEndingPositionOkTwo(color, piece, endSquare)) { currentMoveInfo.result = false; return currentMoveInfo; } } else if(currentMoveInfo.currentMovingPiece.equals("pawn")) { // pawn // pawn is somehow difficult, all cases of pawn should be checked by isPossibleToMoveToEndSquare // eg. // todo, if pawn moves vertical, the end square must be emty (not piece of opposite color) // todo, can be exchange to square, where is nothing, if previous opposite move was pawn two squares } else{ currentMoveInfo.result = false; assert false; } return currentMoveInfo; } protected boolean isEndingPositionOkTwo(String color, Piece piece, Square endSquare) { if(piece == null) { // square is empty, ok return true; } else{ // square is not empty if( piece.pieceColor.equals(color)){ Game.errorMessage = "In " + color + " move " + this.getMoveNumber() + ". is the same color piece at square " + endSquare.getName(); return false; } else // piece of opposite color, exchange return true; } } // empty squares between start and end squares protected CurrentMoveInfo isRoadOk(Board board, String color, CurrentMoveInfo currentMoveInfo) { //result currentMoveInfo.result = true; Square startSquare = board.getSquare(currentMoveInfo.movePieceFrom); Piece piece = startSquare.getPiece(); if(currentMoveInfo.currentMovingPiece.equals("castle")) { // we should test the squares between rook and king and if king is not moving over checked square Square[] squares = board.getSquaresHorizontal(board.getSquare(currentMoveInfo.movePieceFrom).getName(), board.getSquare(currentMoveInfo.movePieceFromTwo).getName()); for (int i = 0; i < squares.length; i++) { if(squares[i].getPiece() != null) currentMoveInfo.result = false; } } else{ // there should be piece on square, was tested in isStartingPositionOk currentMoveInfo.result = piece.isRoadOk(board, currentMoveInfo.movePieceFrom, currentMoveInfo.movePieceTo); } return currentMoveInfo; } // test if move is according to chess rules, eg. rook moves horizontal, bishop diagonal, ... protected CurrentMoveInfo isPossibleToMoveToEndSquare(Board board, String color, CurrentMoveInfo currentMoveInfo) { currentMoveInfo.result = true; // castle is ok if(! currentMoveInfo.currentMovingPiece.equals("castle")) { Square startSquare = board.getSquare(currentMoveInfo.movePieceFrom); Piece piece = startSquare.getPiece(); if(piece.possibleToMoveToEndSquare(board, currentMoveInfo.movePieceFrom, currentMoveInfo.movePieceTo)) currentMoveInfo.result = true; else currentMoveInfo.result = false; } return currentMoveInfo; } protected Piece getPromotingPiece(String move, String color) { // its dummy, doesn't matter if its black or white' // String color = "white"; if(move.length() >= knightSymbol.length() && move.endsWith(knightSymbol)) return new Knight(color); // need some dummy color, really !!!, test it else if(move.length() >= rookSymbol.length() && move.endsWith(rookSymbol)) return new Rook(color); else if(move.length() >= bishopSymbol.length() && move.endsWith(bishopSymbol)) return new Bishop(color); else if(move.length() >= queenSymbol.length() && move.endsWith(queenSymbol)) return new Queen(color); else return null; } /** * test if it is a check, test is for both kings, * first if by moving piece doesn't allow a check (move invalid) * second if its not check to opposite color king * (this should be devided to two independent methods ?) */ protected boolean isCheck(Board board, String color) { Square[][] squares = board.getSquares(); Square kingsSquare; CurrentMoveInfo currentMoveInfo = new CurrentMoveInfo(); boolean foundKing = false; // where are the kings ? for (int i = 0; i < squares.length; i++) { for (int j = 0; j < squares.length; j++) { if(squares[i][j].getPiece() != null && squares[i][j].getPiece().getName().equals("king") && squares[i][j].getPiece().getPieceColor().equals(color)){ // we have a king with current moving color (there must be a king), save his square, is where oposite piece want to go to currentMoveInfo.movePieceTo = squares[i][j].getName(); // todo, we should jump out of both loops foundKing = true; break; } } if(foundKing) break; } // in test we dont set a king, causes null pointer, so handle it if(! foundKing) return false; // now test if opposite color pieces dont check this king // (no need for pawn, careful, in next test is needed, done so, that both colors can use this, so with pawn) for (int i = 0; i < squares.length; i++) { for (int j = 0; j < squares.length; j++) { if(squares[i][j].getPiece() != null && ! squares[i][j].getPiece().getPieceColor().equals(color)){ // we have opposite piece currentMoveInfo.currentMovingPiece = squares[i][j].getPiece().getName(); // must be from, as tested piece will go from this square to found kings square currentMoveInfo.movePieceFrom = squares[i][j].getName(); if(squares[i][j].getPiece().getName().equals("pawn")){ System.out.println("squares[i][j] = "+squares[i][j]); if(board.isExchange(color, currentMoveInfo.movePieceFrom, currentMoveInfo.movePieceTo)){ // pawn road by exchange is always true return true; } } // test if move is according to chess rules, eg. rook moves horizontal, bishop diagonal, ... if(isPossibleToMoveToEndSquare(board, color, currentMoveInfo).result){ // tests if it can move (nothing in line of move, correct move of pieces, ...) if(isRoadOk(board, color, currentMoveInfo).result) return true; } } } } return false; } protected boolean additionalInfoFitsToSquareName(String movePieceFrom, String movePieceFromTemp) { //System.out.println("movePieceFrom="+movePieceFrom+" movePieceFromTemp="+movePieceFromTemp); if(movePieceFrom.length() == 0 ) return true; if(movePieceFrom.length() == 1 && movePieceFromTemp.length() >= 1){ if(Character.isLetter(movePieceFrom.charAt(0)) ){ if(movePieceFrom.charAt(0) == movePieceFromTemp.charAt(0)) return true; } else if(Character.isDigit(movePieceFrom.charAt(0)) ){ if(movePieceFrom.charAt(0) == movePieceFromTemp.charAt(1)) return true; } } if(movePieceFrom.length() == 2 && movePieceFromTemp.length() == 2 && movePieceFrom.equals(movePieceFromTemp)) return true; return false; } protected String trimNotUsedChars(String move) { int i = 0; for (i = move.length()-1; i >= 0; i--) { if(Character.isDigit(move.charAt(i)) || Character.isLetter(move.charAt(i)) ){ i++; break; } } return move.substring(0, i); } public String toString(){ return this.getMoveNumber() +" "+ this.getWhiteMove() +" "+ this.getBlackMove(); } /** * removes promoted piece from the end of the string, eg. g1Q will be g1 * problem, in pgn format is in between =, eg. g1=Q, todo * * @return String, move without the promoted piece */ protected String removePromotingPiece(String move, String currentPromotingPiece) { if(currentPromotingPiece.equals("knight")) { // check for length, should be done in all others if(move.length() >= knightSymbol.length()){ String moveWithoutPromotingPiece = move.substring(0, move.length() - knightSymbol.length()); if(moveWithoutPromotingPiece.endsWith("=")) return moveWithoutPromotingPiece.substring(0, moveWithoutPromotingPiece.length()-1); else return moveWithoutPromotingPiece; } } else if(currentPromotingPiece.equals("bishop")) { String moveWithoutPromotingPiece = move.substring(0, move.length() - bishopSymbol.length()); if(moveWithoutPromotingPiece.endsWith("=")) return moveWithoutPromotingPiece.substring(0, moveWithoutPromotingPiece.length()-1); else return moveWithoutPromotingPiece; } else if(currentPromotingPiece.equals("queen")) { String moveWithoutPromotingPiece = move.substring(0, move.length() - queenSymbol.length()); if(moveWithoutPromotingPiece.endsWith("=")) return moveWithoutPromotingPiece.substring(0, moveWithoutPromotingPiece.length()-1); else return moveWithoutPromotingPiece; } else if(currentPromotingPiece.equals("rook")) { String moveWithoutPromotingPiece = move.substring(0, move.length() - rookSymbol.length()); if(moveWithoutPromotingPiece.endsWith("=")) return moveWithoutPromotingPiece.substring(0, moveWithoutPromotingPiece.length()-1); else return moveWithoutPromotingPiece; } return move; } protected String removePiece(String move, String currentMovingPiece) { if(currentMovingPiece.equals("knight")) { // check for length, should be done in all others if(move.length() >= knightSymbol.length()) return move.substring(knightSymbol.length(), move.length()); } else if(currentMovingPiece.equals("pawn")) { if(move.length() >= pawnSymbol.length()) return move.substring(pawnSymbol.length(), move.length()); } else if(currentMovingPiece.equals("bishop")) { return move.substring(bishopSymbol.length(), move.length()); } else if(currentMovingPiece.equals("queen")) { return move.substring(queenSymbol.length(), move.length()); } else if(currentMovingPiece.equals("rook")) { return move.substring(rookSymbol.length(), move.length()); } else if(currentMovingPiece.equals("king")) { return move.substring(kingSymbol.length(), move.length()); } return move; } protected String removeEndSquare(String move) { return move.substring(0, move.length() - 2); } protected String removeActionSquare(String moveWithoutEndSquare) { if(moveWithoutEndSquare.endsWith("-") || moveWithoutEndSquare.endsWith("x")) return moveWithoutEndSquare.substring(0, moveWithoutEndSquare.length() - 1); else return moveWithoutEndSquare; } }