IEnumerator PieceMove(GameLogic.Move move) { var piece = m_pieces[move.pieceNr]; Vector3 newCoords; if (move.toPos < GameLogic.BoardSize) { newCoords = BoardCoords.getPositionCoords(move.toPos); } else { newCoords = BoardCoords.getTargetCoords(m_gameLogic.CurrentPlayer, move.toPos % 1000); } GameObject bumpedPiece = null; Vector3? bumpTargetPos = null; if (move.pieceOnTargetPos.HasValue) { var bumpedPieceIdx = move.pieceOnTargetPos.Value; var bumpedOwner = m_gameLogic.WhosePlayerIsPiece(bumpedPieceIdx); var bumpHomePos = (-m_gameLogic.FindFreeHomePos(bumpedOwner)) - 1; bumpedPiece = m_pieces[bumpedPieceIdx]; bumpTargetPos = BoardCoords.getHomeCoords(bumpedOwner, bumpHomePos); } m_move = new MovingPiece() { piece = piece, start = piece.transform.parent.position, target = newCoords, phase = 0f }; yield return(new WaitForSeconds(m_jumpLength)); if (bumpedPiece != null) { bumpedPiece.transform.parent.position = bumpTargetPos.Value; } var result = m_gameLogic.ExecuteMove(move); if (result.gameOver != null) { Debug.Log("Game over"); GameOver(); } else { StartCoroutine(NextPlayer()); } }
/** * Check if the move correlates to the userPiece and * that the destination square of the move is empty. */ private Boolean CheckMoveValidity(Move selectedMove) { Boolean moveValid = false; if (currentPosition.getPiece(selectedMove.origin) == userPiece) { if (currentPosition.getPiece(selectedMove.destination) == PieceType.Empty) { moveValid = true; } } return moveValid; }
public void OnPieceSelected(GameObject pieceParent) { // The mouse raycast returns the piece parent object // We want to find the actual piece GameObject piece = null; if (pieceParent.transform.childCount == 1) { piece = pieceParent.transform.GetChild(0).gameObject; } else { piece = pieceParent; } // find out the index of the selected piece int selectedPieceIdx = -1; for (var i = 0; i < m_pieces.Count; i++) { if (piece == m_pieces[i]) { selectedPieceIdx = i; break; } } if (selectedPieceIdx == -1) { return; } // check that the piece is playable GameLogic.Move selectedMove = null; foreach (var move in m_pendingMoves) { if (move.pieceNr == selectedPieceIdx) { selectedMove = move; break; } } if (selectedMove == null) { return; } DisablePlayerInput(); StartCoroutine(PieceMove(selectedMove)); }
/* * Returns true if a move is valid for a given position */ public static Boolean isMoveValid(Move move, Position position) { if (move == null) { return false; } ArrayList moves = new MoveGenerator().legalMoves(position); foreach (Move listMove in moves) { //Move is only valid if it appears in legal moves list if (move.Equals(listMove)) { return true; } } return false; }
public void TestUnMakeMove() { //arrange Move simpleMove = new Move(12, 28, PieceType.Empty); UnMakeInfo unMakeMove = new UnMakeInfo(); Position startPosition = FENConverter.convertFENToPosition(FENConverter.startPosition); //act startPosition.makeMove(simpleMove, unMakeMove); String fenString = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1"; //assert Assert.AreEqual(fenString, FENConverter.convertPositionToFEN(startPosition)); //act startPosition.unMakeMove(simpleMove, unMakeMove); //assert Assert.AreEqual(FENConverter.startPosition, FENConverter.convertPositionToFEN(startPosition)); }
public void TestMakeMove() { //arrange Move simpleMove = new Move(12, 28, PieceType.Empty); //e2e4 UnMakeInfo unMakeMove = new UnMakeInfo(); Position startPosition = FENConverter.convertFENToPosition(FENConverter.startPosition); //act startPosition.makeMove(simpleMove, unMakeMove); /* * This following string is technically incorrect as in FEN it should indicate e3 as * the en passant square. However, our implementation does not set the en passant square * if it cannot be used. */ String fenString = "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq - 0 1"; //assert Assert.AreEqual(fenString, FENConverter.convertPositionToFEN(startPosition)); }
public void TestLegalMovesWithCapture() { //arrange String positionB = "3k4/6p1/8/8/8/8/1B6/8 w - - 0 1"; String positionR = "3k4/6p1/8/8/8/8/6R1/8 w - - 0 1"; Position testPositionB = FENConverter.convertPiecePlacementToPosition(positionB); Position testPositionR = FENConverter.convertPiecePlacementToPosition(positionR); //act ArrayList legalMovesB = MoveGenerator.mgInstance.legalMoves(testPositionB); ArrayList legalMovesR = MoveGenerator.mgInstance.legalMoves(testPositionR); Move captureB = new Move(FENConverter.getSquare("b2"), FENConverter.getSquare("g7"), PieceType.Empty); Move captureR = new Move(FENConverter.getSquare("g2"), FENConverter.getSquare("g7"), PieceType.Empty); //assert Assert.AreEqual(8, legalMovesB.Count); Assert.AreEqual(13, legalMovesR.Count); Assert.AreEqual(true, MoveParser.isMoveCapture(captureB, testPositionB)); Assert.AreEqual(true, MoveParser.isMoveCapture(captureR, testPositionR)); }
/* * Returns true if a move results in a caputre for a given * position */ public static Boolean isMoveCapture(Move move, Position position) { if (position.getPiece(move.destination) == PieceType.Empty) { //Deal with En Passant capture PieceType piece = position.getPiece(move.origin); if ((piece == (position.whiteMove ? PieceType.P : PieceType.p)) && (move.destination == position.getEpSquare())) { return true; } else { return false; } } else { return true; } }
/* * Converts a move object into a UCI move string (long algebraic * notation), a move list can be supplied to search through. */ public static String moveObjectToString(Move move, Position position, ArrayList moves) { if ((move == null) || move.Equals(new Move(0, 0, 0))) { return "--"; } StringBuilder moveString = new StringBuilder(); int whiteKingOrigin = Position.getSquare(4, 0); int blackKingOrigin = Position.getSquare(4, 7); if ((move.origin == whiteKingOrigin) && (position.getPiece(whiteKingOrigin) == PieceType.K)) { //Check white castle if (move.destination == Position.getSquare(6, 0)) { moveString.Append("O-O"); } else if (move.destination == Position.getSquare(2, 0)) { moveString.Append("O-O-O"); } } else if ((move.origin == blackKingOrigin) && (position.getPiece(blackKingOrigin) == PieceType.k)) { //Check black castle if (move.destination == Position.getSquare(6, 7)) { moveString.Append("O-O"); } else if (move.destination == Position.getSquare(2, 7)) { moveString.Append("O-O-O"); } } if (moveString.Length == 0) { PieceType piece = position.getPiece(move.origin); moveString.Append("" + piece); int originFile = Position.getRank(move.origin); int originRank = Position.getFile(move.origin); int destinationFile = Position.getRank(move.destination); int destinationRank = Position.getFile(move.destination); //Long Algebraic Notation----- moveString.Append((char)(originFile + 'a')); moveString.Append((char)(originRank + '1')); moveString.Append(isMoveCapture(move, position) ? 'x' : '-'); //---------------------------- moveString.Append((char)(destinationFile + 'a')); moveString.Append((char)(destinationRank + '1')); if (move.promoteTo != PieceType.Empty) { moveString.Append("" + piece); } } UnMakeInfo unMake = new UnMakeInfo(); position.makeMove(move, unMake); Boolean inCheck = MoveGenerator.inCheck(position); if (inCheck) { ArrayList nextMoves = MoveGenerator.mgInstance.legalMoves(position); if (nextMoves.Count == 0) { moveString.Append('#'); } else { moveString.Append('+'); } } position.unMakeMove(move, unMake); return moveString.ToString(); }
/* * Converts a move object into a UCI move string (long algebraic * notation) */ public static String moveObjectToString(Move move, Position position) { return moveObjectToString(move, position, null); }
/* * Convert a move object to UCI string format */ public static String moveObjectToString(Move move) { String moveString = squareToString(move.origin); moveString += (squareToString(move.destination)); switch (move.promoteTo) { case PieceType.Q: case PieceType.q: moveString += "q"; break; case PieceType.R: case PieceType.r: moveString += "r"; break; case PieceType.B: case PieceType.b: moveString += "b"; break; case PieceType.N: case PieceType.n: moveString += "n"; break; default: break; } return moveString; }
public void StartGame() { myConsoleOut.WriteLine("Welcome, press enter to start a new game."); myConsoleOut.WriteLine("To quit, simply type quit and hit enter."); myConsoleOut.WriteLine("To undo the last move made, type undo and hit enter."); myConsoleOut.WriteLine("To make a move, type the move in long algebraic notation."); myConsoleOut.WriteLine("An example would be 'e2e4'."); myConsoleIn.ReadLine(); while (!gameFinished) { myConsoleOut.WriteLine(FENConverter.asciiBoard(currentPosition)); String userInput = myConsoleIn.ReadLine(); switch (userInput) { case ("quit"): case ("Quit"): gameFinished = true; break; case ("undo"): case ("Undo"): undoMove = true; break; default: break; } //Continue if user has not quit if (!gameFinished) { //undo previous moce if (undoMove) { if (unMakeInfo == null) { myConsoleOut.WriteLine("No move to undo."); } else { currentPosition.unMakeMove(currentMove, unMakeInfo); } } //performs valid move else { if (ParseMove(userInput)) { String originString = userInput.Substring(0, 2); String destinationString = userInput.Substring(2, 2); int origin = FENConverter.getSquare(originString); int destination = FENConverter.getSquare(destinationString); currentMove = new Move(origin, destination, PieceType.Empty); currentPosition.makeMove(currentMove, unMakeInfo); } } } } }
/* * Creates a Move object with given input */ public Move(Move m) { this.origin = m.origin; this.destination = m.destination; this.promoteTo = m.promoteTo; }
/* * Unmake a move to the current position */ public void unMakeMove(Move move, UnMakeInfo moveInfo) { if (!sameActiveColor) { setWhiteMove(!whiteMove); } PieceType piece = pieceLayout[move.destination]; setPiece(move.origin, piece); setPiece(move.destination, moveInfo.getCapturedPiece()); setCastleMask(moveInfo.getCastleRights()); setEpSquare(moveInfo.getEPSquare()); halfMoveClock = moveInfo.getHalfMoveClock(); Boolean whiteToMove = whiteMove; if (move.promoteTo != PieceType.Empty) { piece = whiteToMove ? PieceType.P : PieceType.p; setPiece(move.origin, piece); } if (!whiteToMove) { fullMoveCounter--; } //Handle Castling PieceType king = whiteToMove ? PieceType.K : PieceType.k; int kingOrigin = move.origin; if (piece == king) { if (move.destination == kingOrigin + 2) { setPiece(kingOrigin + 3, pieceLayout[kingOrigin + 1]); setPiece(kingOrigin + 1, PieceType.Empty); } else if (move.destination == kingOrigin - 2) { setPiece(kingOrigin - 4, pieceLayout[kingOrigin - 1]); setPiece(kingOrigin - 1, PieceType.Empty); } } //Handle En Passant if (move.destination == epSquare) { if (piece == PieceType.P) { setPiece(move.destination - 8, PieceType.p); } else if (piece == PieceType.p) { setPiece(move.destination + 8, PieceType.P); } } }
//-----------------Move Methods--------------------------- /* * Apply a move to the current position */ public void makeMove(Move move, UnMakeInfo moveInfo) { //Store info to undo move if needed moveInfo.setCapturedPiece(pieceLayout[move.destination]); moveInfo.setCastleRights(castleMask); moveInfo.setEPSquare(epSquare); moveInfo.setHalfMoveClock(halfMoveClock); Boolean whiteToMove = whiteMove; PieceType piece = pieceLayout[move.origin]; PieceType capturedPiece = pieceLayout[move.destination]; Boolean nullMove = (move.origin == 0) && (move.destination == 0); if (nullMove || (capturedPiece != PieceType.Empty) || (piece == (whiteToMove ? PieceType.P : PieceType.p))) { halfMoveClock = 0; } else { halfMoveClock++; } if (!whiteToMove) { fullMoveCounter++; } //Handle Castling PieceType king = whiteToMove ? PieceType.K : PieceType.k; int kingOrigin = move.origin; if (piece == king) { if (move.destination == kingOrigin + 2) { setPiece(kingOrigin + 1, pieceLayout[kingOrigin + 3]); setPiece(kingOrigin + 3, PieceType.Empty); } else if (move.destination == kingOrigin - 2) { setPiece(kingOrigin - 1, pieceLayout[kingOrigin - 4]); setPiece(kingOrigin - 4, PieceType.Empty); } if (whiteToMove) { setCastleMask(castleMask & ~(1 << Position.A1_CASTLE)); setCastleMask(castleMask & ~(1 << Position.H1_CASTLE)); } else { setCastleMask(castleMask & ~(1 << Position.A8_CASTLE)); setCastleMask(castleMask & ~(1 << Position.H8_CASTLE)); } } if (!nullMove) { PieceType rook = whiteToMove ? PieceType.R : PieceType.r; if (piece == rook) { removeCastleRights(move.origin); } PieceType opppositeRook = whiteToMove ? PieceType.r : PieceType.R; if (capturedPiece == opppositeRook) { removeCastleRights(move.destination); } } //Handle En Passant int prevEpSquare = epSquare; setEpSquare(-1); if (piece == PieceType.P) { if (move.destination - move.origin == 2 * 8) { int file = Position.getFile(move.destination); if (((file > 0) && (pieceLayout[move.destination - 1] == PieceType.p)) || ((file < 7) && (pieceLayout[move.destination + 1] == PieceType.p))) { setEpSquare(move.origin + 8); } } else if (move.destination == prevEpSquare) { setPiece(move.destination - 8, PieceType.Empty); } } else if (piece == PieceType.p) { if (move.destination - move.origin == -2 * 8) { int file = Position.getFile(move.destination); if (((file > 0) && (pieceLayout[move.destination - 1] == PieceType.P)) || ((file < 7) && (pieceLayout[move.destination + 1] == PieceType.P))) { setEpSquare(move.origin - 8); } } else if (move.destination == prevEpSquare) { setPiece(move.destination + 8, PieceType.Empty); } } //Perform Move setPiece(move.origin, PieceType.Empty); //Handle Promotion if (move.promoteTo != PieceType.Empty) { setPiece(move.destination, move.promoteTo); } else { setPiece(move.destination, piece); } if (!sameActiveColor) { setWhiteMove(!whiteToMove); } }
public void returnMove(Move move) { if (movesInCache < moveCache.Length) { moveCache[movesInCache++] = move; } }