public HeapGround GetMoves(bool capturesOnly, bool pseudolegal, bool autoSetMoveColour = true) // autoset move colour means move colour will be taken from current position. Otherwise can be custom set using SetMoveColour method { pseudolegalMode = pseudolegal; moves = new HeapGround(128); // I imagine that most positions will yield less than 128 psuedolegal moves. (The greatest known number of legal moves available in a position is 218) if (autoSetMoveColour) { moveColour = BoardGround.currentGamestate & 1; } opponentColour = 1 - moveColour; friendlyKingIndex = (moveColour == 1)?BoardGround.whiteKingIndex:BoardGround.blackKingIndex; inCheck = SquareAttackedByEnemy(friendlyKingIndex); if (capturesOnly) { GenerateCaptureMoves(); } else { GenerateAllMoves(); } return(moves); }
/// <summary> /// Makes the move after confirming that it is legal /// </summary> public void TryMakeMove(string algebraicMove) { if (isWhite == BoardGround.IsWhiteToPlay()) { legalMoves = moveGenerator.GetMoves(false, false); for (int i = 0; i < legalMoves.Count; i++) { int moveFromIndex = legalMoves.GetMove(i) & 127; int moveToIndex = (legalMoves.GetMove(i) >> 7) & 127; int moveFromX = BoardGround.Convert128to64(moveFromIndex) % 8; int moveFromY = BoardGround.Convert128to64(moveFromIndex) / 8; int moveToX = BoardGround.Convert128to64(moveToIndex) % 8; int moveToY = BoardGround.Convert128to64(moveToIndex) / 8; string fromAlgebraic = DefinitionsGround.fileNames[moveFromX].ToString() + DefinitionsGround.rankNames[moveFromY].ToString(); string toAlgebraic = DefinitionsGround.fileNames[moveToX].ToString() + DefinitionsGround.rankNames[moveToY].ToString(); string moveCoords = fromAlgebraic + toAlgebraic; if (moveCoords == algebraicMove) // move confirmed as legal //Debug.Log(algebraicMove); { MakeMove(legalMoves.GetMove(i)); break; } } } }
public override void RequestMove() { base.RequestMove(); legalMoves = moveGenerator.GetMoves(false, false); }
int AlphaBetaSearch(int plyRemaining, int alpha, int beta, bool isWhite) { HeapGround moveHeap = moveGenerator.GetMoves(false, false); int count = moveHeap.Count; if (moveHeap.Count == 0) { return(((isWhite)?-1:1) * (10000000 + plyRemaining)); // if no moves available, side has been checkmated. Return best score for opponent. Checkmating sooner (higher depth) is rewarded. } if (plyRemaining == 0) { nodesSearched++; return(Evaluate()); //QuiescenceSearch(int.MinValue,int.MaxValue,!isWhite,true); //return quiescenceScore; } if (isWhite) // white is trying to attain the highest evaluation possible { for (int i = 0; i < count; i++) { ushort move = moveHeap.RemoveFirst(); BoardGround.MakeMove(move); alpha = Math.Max(alpha, AlphaBetaSearch(plyRemaining - 1, alpha, beta, false)); BoardGround.UnmakeMove(move); if (plyRemaining == searchDepth) // has searched full depth and is now looking at top layer of moves to select the best { if (alpha > bestScoreThisIteration) { bestScoreThisIteration = alpha; bestMoveThisIteration = move; } } if (beta <= alpha) // break { breakCount++; break; } } return(alpha); } else { // black is trying to obtain the lowest evaluation possible for (int i = 0; i < count; i++) { ushort move = moveHeap.RemoveFirst(); BoardGround.MakeMove(move); beta = Math.Min(beta, AlphaBetaSearch(plyRemaining - 1, alpha, beta, true)); BoardGround.UnmakeMove(move); if (plyRemaining == searchDepth) // has searched full depth and is now looking at top layer of moves to select the best { if (beta < bestScoreThisIteration) { bestScoreThisIteration = beta; bestMoveThisIteration = move; } } if (beta <= alpha) // break { breakCount++; break; } } return(beta); } return(0); }
void Update() { if (!active) { // input is active if one or more players have been assigned to it (or game is over) return; } Vector3 endPointerPosition = GvrPointerInputModule.CurrentRaycastResult.worldPosition; // Vector2 mousePosition = (Vector2)viewCamera.ScreenToWorldPoint (Input.mousePosition); // Pick up piece // If not holding any Piece and clicked anywhere if (!holdingPiece && Input.GetMouseButtonDown(0)) // if (/*Input.GetKeyDown(KeyCode.Mouse0)*/ Input.GetMouseButtonDown(0) && !holdingPiece) { ChessUIGround.instance.ResetHighlights(); // isPlayerMove just checks if any HumanPlayerGround has his chance // If so then we will highlight the regions bool isPlayerMove = false; for (int i = 0; i < players.Count; i++) { if (players[i].isMyMove) { isPlayerMove = true; break; } } holdingPiece = TryGetPieceUIAtPoint(endPointerPosition, out pieceHeld); // This line improves efficiency if (!isThereAPiece) { holdingPiece = false; } // Debug.Log("holding piece: " + holdingPiece + " isPlayerMove: " + isP); if (holdingPiece && isPlayerMove) { // highlight legal moves for held piece HeapGround legalMoveHeap = HumanPlayerGround.legalMoves; for (int i = 0; i < legalMoveHeap.Count; i++) { HighlightSquare(legalMoveHeap.GetMove(i), pieceHeld.algebraicCoordinate); } } } // Let go of piece // If holding anything and clicked somewhere else if (Input.GetMouseButtonDown(0) && holdingPiece) // else if (/*Input.GetKeyUp(KeyCode.Mouse0)*/Input.GetMouseButtonUp(0) && holdingPiece) { PieceUIGround dropSquare; ChessUIGround.instance.ResetHighlights(); if (TryGetPieceUIAtPoint(endPointerPosition, out dropSquare)) { string algebraicMove = pieceHeld.algebraicCoordinate + dropSquare.algebraicCoordinate; for (int i = 0; i < players.Count; i++) { players[i].TryMakeMove(algebraicMove); } } pieceHeld.Release(); holdingPiece = false; } // Drag piece // else if (/*Input.GetKey(KeyCode.Mouse0)*/ Input.GetMouseButton(0) && holdingPiece) // { // pieceHeld.Move(endPointerPosition); // } }
public static string NotationFromMove(ushort move) { BoardGround.UnmakeMove(move); // unmake move on board MoveGeneratorGround moveGen = new MoveGeneratorGround(); int moveFromIndex = move & 127; int moveToIndex = (move >> 7) & 127; int promotionPieceIndex = (move >> 14) & 3; // 0 = queen, 1 = rook, 2 = knight, 3 = bishop int colourToMove = BoardGround.boardColourArray[moveFromIndex]; int movePieceCode = BoardGround.boardArray [moveFromIndex]; // get move piece code int movePieceType = movePieceCode & ~1; // get move piece type code (no colour info) int capturedPieceCode = BoardGround.boardArray [moveToIndex]; // get capture piece code int promotionPieceType = BoardGround.pieceCodeArray [promotionPieceIndex]; if (movePieceType == BoardGround.kingCode) { if (moveToIndex - moveFromIndex == 2) { BoardGround.MakeMove(move); // remake move return("O-O"); } else if (moveToIndex - moveFromIndex == -2) { BoardGround.MakeMove(move); // remake move return("O-O-O"); } } string moveNotation = GetSymbolFromPieceType(movePieceType); // check if any ambiguity exists in notation (e.g if e2 can be reached via Nfe2 and Nbe2) if (movePieceType != BoardGround.pawnCode && movePieceType != BoardGround.kingCode) { HeapGround allMoves = moveGen.GetMoves(false, false); for (int i = 0; i < allMoves.Count; i++) { int alternateMoveFromIndex = allMoves.moves[i] & 127; int alternateMoveToIndex = (allMoves.moves[i] >> 7) & 127; int alternateMovePieceCode = BoardGround.boardArray [alternateMoveFromIndex]; if (alternateMoveFromIndex != moveFromIndex && alternateMoveToIndex == moveToIndex) // if moving to same square from different square { if (alternateMovePieceCode == movePieceCode) // same piece type { int fromFileIndex = BoardGround.FileFrom128(moveFromIndex) - 1; int alternateFromFileIndex = BoardGround.FileFrom128(alternateMoveFromIndex) - 1; int fromRankIndex = BoardGround.RankFrom128(moveFromIndex) - 1; int alternateFromRankIndex = BoardGround.RankFrom128(alternateMoveFromIndex) - 1; if (fromFileIndex != alternateFromFileIndex) // pieces on different files, thus ambiguity can be resolved by specifying file { moveNotation += DefinitionsGround.fileNames[fromFileIndex]; break; // ambiguity resolved } else if (fromRankIndex != alternateFromRankIndex) { moveNotation += DefinitionsGround.rankNames[fromRankIndex]; break; // ambiguity resolved } } } } } if (capturedPieceCode != 0) // add 'x' to indicate capture { if (movePieceType == BoardGround.pawnCode) { moveNotation += DefinitionsGround.fileNames[BoardGround.FileFrom128(moveFromIndex) - 1]; } moveNotation += "x"; } else // check if capturing ep { if (movePieceType == BoardGround.pawnCode) { if (System.Math.Abs(moveToIndex - moveFromIndex) != 16 && System.Math.Abs(moveToIndex - moveFromIndex) != 32) { moveNotation += DefinitionsGround.fileNames[BoardGround.FileFrom128(moveFromIndex) - 1] + "x"; } } } moveNotation += DefinitionsGround.fileNames [BoardGround.FileFrom128(moveToIndex) - 1]; moveNotation += DefinitionsGround.rankNames [BoardGround.RankFrom128(moveToIndex) - 1]; // add = piece type if promotion if (movePieceType == BoardGround.pawnCode) { if (moveToIndex >= 112 || moveToIndex <= 7) // pawn has reached first/eighth rank { moveNotation += "=" + GetSymbolFromPieceType(promotionPieceType); } } // add check/mate symbol if applicable BoardGround.MakeMove(move); // remake move if (moveGen.PositionIsMate()) { moveNotation += "#"; } else if (moveGen.PositionIsCheck()) { moveNotation += "+"; } return(moveNotation); }