/// <summary> /// Write move to log. /// </summary> /// <param name="move"></param> private void _writeLog(cgSimpleMove move) { if (moveLog != null) { if (NotationType == cgNotation.NotationType.Coordinate) { if (_loggedMoves % 2 == 0) { moveLog.text += "\n"; } else { moveLog.text += " | "; } moveLog.text += _abstractBoard.SquareNames[move.from] + "-" + _abstractBoard.SquareNames[move.to]; } else if (NotationType == cgNotation.NotationType.Algebraic) { moveLog.text = "Moves:\n"; cgNotation note = new cgNotation(_abstractBoard.duplicate()); moveLog.text = note.getLogFriendlyNotation(); } _loggedMoves++; } }
public void OnPieceMove(cgSimpleMove _move) { isChanged = true; Btn_Save.enabled = true; if (curMove < moveList.Count) { moveList.RemoveRange(curMove, moveList.Count - curMove); } moveList.Add(_move); board.move(_move); if (board.isChecked(board.whiteTurnToMove)) { AudioSource.PlayClipAtPoint(Check_Sound, Vector3.zero, 1.0f); } else { AudioSource.PlayClipAtPoint(MovePiece_Sound, Vector3.zero, 1.0f); } curMove++; UpdateInfos(); Wnd_Board.UpdateBoard(); }
/// <summary> /// The engine returns with its prefered move. /// </summary> /// <param name="move">The prefered move.</param> private void _engineCallback(List <cgSimpleMove> moves) { if (!playerCanMove) { cgSimpleMove move = moves[0]; if (this._abstractBoard.moves.Count < 10 && randomizeEarlyEngineMoves) //We are in the very early game and we should randomize the engine moves early, so we will make a random-ish choice here instad of the prefered choice. //random-ish in the sense, that we will take a random move of one of the moves that are in the better half of all possible moves. { List <cgSimpleMove> candidates = _findAllMovesNear(moves, 24); UnityEngine.Debug.Log("Candidates: " + candidates.Count); int choice = UnityEngine.Random.Range(0, candidates.Count); move = moves[choice]; } if (_abstractBoard.verifyLegality(move)) { _makeMove(move); } else { moves.Remove(move); if (_engine.moves.Count > 0) { _engineCallback(moves); } else { _checkGameOver(); } } } }
public void OnPieceMove(cgSimpleMove _move) { if (isRightMove(_move)) { if (!m_MissedThisLine) { m_Score++; m_TotalScore++; } moveNextMove(); } else { m_MissedThisLine = true; if (m_Missed) { WndManager.Singleton.OpenMsgBox("Incorrect move. The Right move is " + cgNotation.NotationFromMove(m_Board, m_CurLine.moveList[m_CurMoveIdx]) /*, CallBackIncorrectMove*/); } else { WndManager.Singleton.OpenMsgBox("Incorrect move."); //revertMove(); m_Missed = true; } } UpdateInfos(); }
/// <summary> /// Final verification, checks if the kings is attempting to perform a capture that leads to the king being taken next, which is the only illegal move findLegalMoves does not check. /// </summary> /// <param name="testMove">The move to be verified</param> /// <returns>Is this an illegal king capture?</returns> public bool verifyLegality(cgSimpleMove testMove) { if (testMove.to == 65) { return(false); } else if (Mathf.Abs(squares[testMove.from]) != 6) { return(true); } else { move(testMove); foreach (cgSimpleMove mov in findLegalMoves(_whiteTurnToMove)) { if (mov.to == testMove.to) { revert(); return(false); } } revert(); return(true); } }
private void _testBoard() { bool asWhite = true; int tryMoves = 200; UnityEngine.Debug.Log("testing board.."); for (int i = 0; i < tryMoves; i++) { List <cgSimpleMove> moves = _board.findLegalMoves(asWhite); cgSimpleMove move = moves[UnityEngine.Random.Range(0, moves.Count)]; UnityEngine.Debug.Log("trying move:" + cgGlobal.MoveToString(move)); if (moves.Count < 2) { break; } _board.move(move); asWhite = !asWhite; _debugReadBoard(); } _debugReadBoard(); UnityEngine.Debug.Log("^^pre reversion."); for (int u = tryMoves; u > 0; u--) { _board.revert(); } _debugReadBoard(); UnityEngine.Debug.Log("moves:" + _board.moveCount + " reverts:" + _board.revertCount); }
public void OnSquareSelected(int _pos) { if (m_SelectedPiece == -1) { return; } List <cgSimpleMove> moveSet = m_Board.findStrictLegalMoves(m_Board.whiteTurnToMove); foreach (cgSimpleMove move in moveSet) { if (move.from == m_SelectedPiece && move.to == _pos) { if (IsPromotionMove(move)) { m_CurMove = move; WndManager.Singleton.OpenPromotionSelectWnd(m_Board.whiteTurnToMove, CallbackPromotionSelect); } else { OnMovePiece(move); } break; } } UnselectAllSquare(); m_SelectedPiece = -1; }
/// <summary> /// Add a move based on a notation type. /// </summary> /// <param name="move">the string representation of the move(e4, bxd3 or e2-e4 etc.)</param> /// <param name="notationType"></param> public void AddMove(string move, NotationType notationType) { if (notationType == NotationType.Coordinate) { if (move == "0-0") { //cgSimpleMove smove = new cgCastlingMove(0,0,0,0,0); } else if (move == "0-0-0") { } else { byte start = 0; byte end = 0; for (byte i = 0; i < board.SquareNames.Length; i++) { string str = board.SquareNames[i]; if (str == move.Substring(0, 2)) { start = i; } if (str == move.Substring(3, 2)) { end = i; } } cgSimpleMove smove = new cgSimpleMove(start, end); moves.Add(smove); } } }
/** * 0 1 2 3 4 5 6 7 * 8 9 10 11 12 13 14 15 * 16 17 18 19 20 21 22 23 * 24 25 26 27 28 29 30 31 * 32 33 34 35 36 37 38 39 * 40 41 42 43 44 45 46 47 * 48 49 50 51 52 53 54 55 * 56 57 58 59 60 61 62 63 * */ public static string MoveToString(cgSimpleMove move) { if (move == null) { return(""); } return(SquareNames[move.from] + "->" + SquareNames[move.to]); }
private void _suggestMove(cgSimpleMove move) { cgSquareScript departingSquare = _getSquare(cgGlobal.SquareNames[move.from]); cgSquareScript arrivalSquare = _getSquare(cgGlobal.SquareNames[move.to]); departingSquare.highlightTemporarily(new Color(0, .5f, 0)); arrivalSquare.highlightTemporarily(new Color(0, .5f, 0)); }
void OnMovePiece(cgSimpleMove _move) { m_PieceMoveHandler(_move); // if (m_Board.isChecked(m_Board.whiteTurnToMove)) // AudioSource.PlayClipAtPoint(m_CheckSound, Vector3.zero, 1.0f); // else // AudioSource.PlayClipAtPoint(m_MoveSound, Vector3.zero, 1.0f); }
/// <summary> /// Duplicate this move. Used when duplicating a board which has had moves performed on it, said moves are also duplicated. /// </summary> /// <returns></returns> public virtual cgSimpleMove duplicate() { cgSimpleMove dup = new cgSimpleMove(this.from, this.to, this.positionalVal); dup.capturedType = this.capturedType; dup.val = this.val; dup.bestResponse = bestResponse; dup.queened = this.queened; return(dup); }
/// <summary> /// The user has released a dragged piece. Verify that its a legal move, if so perform the move and perform the next move if appropriate mode. /// </summary> /// <param name="piece"></param> private void _pieceUp(cgChessPieceScript piece) { if (_downPiece != null) { if (playerCanMove || Mode == BoardMode.PlayerVsPlayer) { cgSimpleMove legalMove = null; cgSquareScript closestSquare = _findSquareAt(_downPiece.transform.position); List <cgSimpleMove> legalMoves = _abstractBoard.findLegalMoves(whiteTurnToMove); foreach (cgSimpleMove move in legalMoves) { if (cgGlobal.SquareNames[move.from] == _downPiece.square.uniqueName && cgGlobal.SquareNames[move.to] == closestSquare.uniqueName) { legalMove = move; } } //test legality of move here. if (legalMove != null && _abstractBoard.verifyLegality(legalMove)) { //piece.moveToSquare(closestSquare); _makeMove(legalMove); if (Mode == BoardMode.PlayerVsEngine) { _engine.MakeMove(_abstractBoard, false, _engineCallback); } else if (Mode == BoardMode.EngineVsPlayer) { _engine.MakeMove(_abstractBoard, true, _engineCallback); } } else { piece.moveToSquare(piece.square); } } else { piece.moveToSquare(piece.square); } _downPiece = null; } else { piece.moveToSquare(piece.square); _downPiece = null; } if (highlightLastMove) {//revert colors if highlighting is active foreach (cgSquareScript square in _squares) { square.changeColor(square.startColor); } } }
bool isRightMove(cgSimpleMove _move) { cgSimpleMove curMove = m_CurLine.moveList[m_CurMoveIdx]; if (curMove.from == _move.from && curMove.to == _move.to) { return(true); } return(false); }
/// <summary> /// Returns all squares the block the provided move. /// </summary> /// <param name="forMove">The move that should be blocked</param> /// <returns>The squares that block the move.</returns> private List <byte> _getBlockAttackSquares(cgSimpleMove forMove) { List <byte> returns = new List <byte>(); returns.Add(forMove.from); int type = Mathf.Abs(squares[forMove.from]); if (type == 2 || type == 4 || type == 5) { returns.AddRange(_getRayIn(_findMoveSetFor(type, forMove.from), forMove.to)); } return(returns); }
/// <summary> /// Utilizing an AlphaBeta searching algorithm, we generate moves evaluate them, prune and decide which is best. /// https://en.wikipedia.org/wiki/Alpha%E2%80%93beta_pruning /// </summary> /// <param name="node">the move to analyze</param> /// <param name="depth">The max depth to search to, execution time increases exponentially the higher the depth</param> /// <param name="alpha"></param> /// <param name="beta"></param> /// <param name="maximizing"></param> /// <returns>The value of the provided node</returns> private int _alfaBeta(cgSimpleMove node, int depth, int alpha = int.MinValue, int beta = int.MaxValue, bool maximizing = true) { _board.move(node); if (depth == 0) { int val = _board.Evaluate(); _board.revert(); return(val); } if (maximizing) { int v = int.MinValue; List <cgSimpleMove> replies = _board.findLegalMoves(true); foreach (cgSimpleMove reply in replies) { int candidate = _alfaBeta(reply, depth - 1, alpha, beta, false); v = candidate > v ? candidate : v; alpha = alpha > v ? alpha : v; if (beta < alpha) { break; } } _board.revert(); return(v); } else { int v = int.MaxValue; List <cgSimpleMove> replies = _board.findLegalMoves(false); foreach (cgSimpleMove reply in replies) { int candidate = _alfaBeta(reply, depth - 1, alpha, beta, true); v = candidate < v ? candidate : v; if (beta > v) { beta = v; //node.bestResponse = reply; } if (beta < alpha) { break; } } _board.revert(); return(v); } }
/// <summary> /// Peform the provided move on the visual board and the abstract board, with no legality checks - thus should be performed prior to calling this. /// </summary> /// <param name="move"></param> private void _makeMove(cgSimpleMove move) { UnityEngine.Debug.Log("White: " + _abstractBoard.whiteTurnToMove); movesMade++; playSound(moveSound); _abstractBoard.move(move); _writeLog(move); //_abstractBoard.debugReadBoard(); if (_getPieceOn(_abstractBoard.SquareNames[move.to]) != null && !(move is cgCastlingMove)) { _setDeadPiece(_getPieceOn(_abstractBoard.SquareNames[move.to])); } cgChessPieceScript piece = _getPieceOn(_abstractBoard.SquareNames[move.from]); if (move.queened) { piece.SetType(_abstractBoard.squares[move.to] > 0 ? cgChessPieceScript.Type.WhiteQueen : cgChessPieceScript.Type.BlackQueen); } if (move is cgCastlingMove) { cgChessPieceScript piece2 = _getPieceOn(_abstractBoard.SquareNames[(move as cgCastlingMove).secondFrom]); if (piece2) { piece2.moveToSquare(_getSquare(_abstractBoard.SquareNames[(move as cgCastlingMove).secondTo])); } } else if (move is cgEnPassantMove) { cgChessPieceScript piece2 = _getPieceOn(_abstractBoard.SquareNames[(move as cgEnPassantMove).attackingSquare]); piece2.dead = true; } piece.moveToSquare(_getSquare(_abstractBoard.SquareNames[move.to])); whiteTurnToMove = _abstractBoard.whiteTurnToMove; _checkGameOver(); if (highlightLastMove) { //Color copyFrom = _getSquare(cgGlobal.SquareNames[move.to]).startColor; Color color = _getSquare(_abstractBoard.SquareNames[move.to]).recentMoveColor; _getSquare(_abstractBoard.SquareNames[move.to]).highlightTemporarily(color); } //Debug.Log("making move. " + _abstractBoard.whiteTurnToMove+" moves "+_abstractBoard.moves.Count); //UnityEngine.Debug.Log("Time elapsed: " + stopwatch.Elapsed); if (Mode == BoardMode.EngineVsEngine) { MakeEngineMove(_abstractBoard.duplicate(), _abstractBoard.whiteTurnToMove, _engineCallback); } }
public void OnPieceSelected(int _pos) { bool canMove = false; Debug.Log("source pos = " + m_SelectedPiece.ToString() + ", target pos = " + _pos.ToString()); if ((m_SelectedPiece != -1) && (m_SelectedPiece != _pos)) { List <cgSimpleMove> moveSet = m_Board.findStrictLegalMoves(m_Board.whiteTurnToMove); foreach (cgSimpleMove move in moveSet) { if (move.from == m_SelectedPiece && move.to == _pos) { if (IsPromotionMove(move)) { m_CurMove = move; WndManager.Singleton.OpenPromotionSelectWnd(m_Board.whiteTurnToMove, CallbackPromotionSelect); } else { OnMovePiece(move); canMove = true; } break; } } UnselectAllSquare(); m_SelectedPiece = -1; } if (m_SelectedPiece == -1 || !canMove) { UnselectAllSquare(); // List<cgSimpleMove> moveSet = m_Board.findStrictLegalMoves(m_Board.whiteTurnToMove); // foreach (cgSimpleMove move in moveSet) // if (move.from == _pos) // SelectSquare(move.to); if (m_Board.squares[_pos] != 0 && ((m_Board.squares[_pos] > 0 && m_Board.whiteTurnToMove && (m_CanMove == CanMove.All || (m_CanMove == CanMove.White))) || (m_Board.squares[_pos] < 0 && !m_Board.whiteTurnToMove && (m_CanMove == CanMove.All || (m_CanMove == CanMove.Black))))) { SelectSquare(_pos); m_SelectedPiece = _pos; } else { m_SelectedPiece = -1; } } }
void UnselectAllSquare() { for (int i = 0; i < m_SquarePoses.Length; i++) { Image img = m_SquarePoses[i].GetComponent <Image>(); img.color = Col_None; } if (m_Board.moves.Count > 0) { cgSimpleMove lastMove = m_Board.moves[m_Board.moves.Count - 1]; Image img = m_SquarePoses[lastMove.to].GetComponent <Image>(); img.color = Col_LastMove; } }
private void _engineSuggestion(cgSimpleMove move) { if (playerCanMove) { if (_abstractBoard.verifyLegality(move)) { _suggestMove(move); } else { _engine.Moves.Remove(move); if (_engine.Moves.Count > 0) { _engineSuggestion(_engine.Moves[0]); } } } }
/// <summary> /// Add a move based on a notation type. /// </summary> /// <param name="move">the string representation of the move(e4, bxd3 or e2-e4 etc.)</param> /// <param name="notationType"></param> public void AddMove(string move, NotationType notationType) { if (notationType == NotationType.Coordinate) { if (move == "0-0") { //cgSimpleMove smove = new cgCastlingMove(0,0,0,0,0); } else if (move == "0-0-0") { } else { cgSimpleMove smove = new cgSimpleMove(cgGlobal.IndexFromCellName(move.Substring(0, 2)), cgGlobal.IndexFromCellName(move.Substring(3, 2))); moves.Add(smove); } } }
/// <summary> /// Peform the provided move on the visual board and the abstract board, with no legality checks - thus should be performed prior to calling this. /// </summary> /// <param name="move"></param> private void _makeMove(cgSimpleMove move) { //Debug.Log("making move:" + cgGlobal.MoveToString(move)); movesMade++; playSound(moveSound); _abstractBoard.move(move); _writeLog(move); //_abstractBoard.debugReadBoard(); if (_getPieceOn(cgGlobal.SquareNames[move.to]) != null) { _setDeadPiece(_getPieceOn(cgGlobal.SquareNames[move.to])); } cgChessPieceScript piece = _getPieceOn(cgGlobal.SquareNames[move.from]); piece.moveToSquare(_getSquare(cgGlobal.SquareNames[move.to])); if (move.promoted) { piece.SetType(_abstractBoard.squares[move.to] > 0 ? cgChessPieceScript.Type.WhiteQueen : cgChessPieceScript.Type.BlackQueen); } if (move is cgCastlingMove) { cgChessPieceScript piece2 = _getPieceOn(cgGlobal.SquareNames[(move as cgCastlingMove).secondFrom]); if (piece2) { piece2.moveToSquare(_getSquare(cgGlobal.SquareNames[(move as cgCastlingMove).secondTo])); } } else if (move is cgEnPassantMove) { cgChessPieceScript piece2 = _getPieceOn(cgGlobal.SquareNames[(move as cgEnPassantMove).attackingSquare]); piece2.dead = true; } whiteTurnToMove = _abstractBoard.whiteTurnToMove; _checkGameOver(); if (highlightLastMove) { //Color copyFrom = _getSquare(cgGlobal.SquareNames[move.to]).startColor; Color color = _getSquare(cgGlobal.SquareNames[move.to]).recentMoveColor; _getSquare(cgGlobal.SquareNames[move.to]).highlightTemporarily(color); } }
/// <summary> /// Called when the analysis starts. /// </summary> /// <returns></returns> private IEnumerator _startAnalysis(Action <float> progressCallback = null) { yield return(null); //Console.WriteLine("Starting analysis."); finished = false; moves = _board.findStrictLegalMoves(moveAsWhite); if (moves.Count > 1) { movesLeftToAnalyze = moves.Count; totalMovesToAnalyze = moves.Count; int alpha = int.MinValue; int beta = int.MaxValue; for (int i = 0; i < moves.Count; i++) { cgSimpleMove possibleMove = moves[i]; byte depth = (cgValueModifiers.AlphaBeta_Strong_Delineation < possibleMove.positionalVal ? searchDepthStrong : searchDepthWeak); if (moves.Count < 10) { depth = searchDepthEndGame; } //determining whether move looks weak or strong based on positional value, if its strong we use strong depth otherwise we use weak depth. possibleMove.val = _alfaBeta(possibleMove, depth, alpha, beta, !moveAsWhite); movesLeftToAnalyze--; yield return(null); if (progressCallback != null) { float progress = (float)((float)totalMovesToAnalyze - (float)movesLeftToAnalyze) / (float)totalMovesToAnalyze; progressCallback(progress); } //UnityEngine.Debug.Log("Moves left: " + MovesLeftToAnalyze + " total: " + TotalMovesToAnalyze); } _sortMovesOnBoardValue(moves, moveAsWhite); } yield return(null); _analysisComplete(); }
/// <summary> /// The engine returns with its prefered move. /// </summary> /// <param name="move">The prefered move.</param> private void _engineCallback(cgSimpleMove move) { //Debug.Log("move:" + move.from.name + " to:" + move.to.name); if (!playerCanMove) { if (_abstractBoard.verifyLegality(move)) { _makeMove(move); } else { _engine.Moves.Remove(move); if (_engine.Moves.Count > 0) { _engineCallback(_engine.Moves[0]); } else { _checkGameOver(); } } } }
/// <summary> /// Called when the analysis starts. /// </summary> /// <returns></returns> IEnumerator _startAnalysis() { yield return(null); Finished = false; Moves = _board.findStrictLegalMoves(MoveAsWhite); if (Moves.Count > 1) { MovesLeftToAnalyze = Moves.Count; TotalMovesToAnalyze = Moves.Count; if (LoadBar != null) { LoadBar.transform.localScale = new Vector3(0, LoadBar.transform.localScale.y, 1); } int alpha = int.MinValue; int beta = int.MaxValue; for (int i = 0; i < Moves.Count; i++) { cgSimpleMove possibleMove = Moves[i]; byte depth = (cgValueModifiers.AlphaBeta_Strong_Delineation < possibleMove.positionalVal ? SearchDepthStrong : SearchDepthWeak); if (Moves.Count < 10) { depth = SearchDepthEndGame; } //determining whether move looks weak or strong based on positional value, if its strong we use strong depth otherwise we use weak depth. possibleMove.val = _alfaBeta(possibleMove, depth, alpha, beta, !MoveAsWhite); MovesLeftToAnalyze--; yield return(null); } _sortMovesOnBoardValue(Moves, MoveAsWhite); } yield return(null); _analysisComplete(); }
// Update is called once per frame void Update() { lock (_engineCallbackParams) { if (_engineCallbackParams.Count > 0) { UnityEngine.Debug.Log(": " + _engineCallbackFunctions); _engineCallbackFunctions[0](_engineCallbackParams[0]); _engineCallbackParams.RemoveAt(0); _engineCallbackFunctions.RemoveAt(0); //threadListener.Stop(); } } lock (_engineProgress) { if (_engineProgress.Count > 0 && engineProgressBar != null) { float progress = _engineProgress[0]; _engineProgress.RemoveAt(0); Vector3 nscale = engineProgressBar.transform.localScale; nscale.x = progress; engineProgressBar.transform.localScale = nscale; } } foreach (cgChessPieceScript cp in _livePieces) { if (cp.dead && !_deadPieces.Contains(cp)) { _setDeadPiece(cp); } } for (int i = _deadPieces.Count; i > 0; i--) { if (_livePieces.Contains(_deadPieces[i - 1])) { _livePieces.Remove(_deadPieces[i - 1]); } } if (_downPiece != null) { Vector3 cursorPoint = new Vector3(Input.mousePosition.x, Input.mousePosition.y, Input.mousePosition.z); Ray cursorRay = Camera.main.ScreenPointToRay(cursorPoint); RaycastHit hit; if (Physics.Raycast(cursorRay, out hit, 100.0f)) { _downPiece.transform.position = hit.point; } } if (Input.GetKey(KeyCode.C) && Input.GetKeyDown(KeyCode.LeftControl)) { _copyGameToClipboard(); } else if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.C)) { _copyGameToClipboard(); } if (Input.GetKey(KeyCode.V) && Input.GetKeyDown(KeyCode.LeftControl)) { _pasteGameFromClipboard(); } else if (Input.GetKey(KeyCode.LeftControl) && Input.GetKeyDown(KeyCode.V)) { _pasteGameFromClipboard(); } if (Input.GetKey(KeyCode.F1)) { UnityEngine.Debug.Break(); } if (Input.GetKey(KeyCode.A)) { //_abstractBoard.boardToString() UnityEngine.Debug.Log(_abstractBoard.boardToString()); //UnityEngine.Debug.Log(_abstractBoard._blackKingStart); } if (Input.GetKey(KeyCode.U)) { _abstractBoard.revert(); UnityEngine.Debug.Log(_abstractBoard.boardToString()); } if (Input.GetKey(KeyCode.V)) //Perform long castling move. { List <cgSimpleMove> moves = _abstractBoard.findStrictLegalMoves(_abstractBoard.whiteTurnToMove); cgSimpleMove move = null; foreach (cgSimpleMove mv in moves) { if (mv is cgCastlingMove) { if (move == null) { move = mv; } else if (Math.Abs(move.to - move.from) < Math.Abs(mv.to - mv.to)) { move = mv; } } } _makeMove(move); } }
/// <summary> /// Add a move to the list of moves. /// </summary> /// <param name="move"></param> public void AddMove(cgSimpleMove move) { moves.Add(move); }
/// <summary> /// Perform the provided move, capturing if necessary. /// </summary> /// <param name="move">The move to perform.</param> public void move(cgSimpleMove move) { moves.Add(move); moveCount++; if (move.to == 65) { return; } move.capturedType = squares[move.to]; squares[move.to] = squares[move.from]; squares[move.from] = 0; //_enPassantSquare = 0; //Pawn auto-promote to queen // if (move.to < 8 && squares[move.to] == 1) // { // move.promoted = true; // // squares[move.to] = (sbyte)move.promotionType; // } // else if (move.to > 55 && squares[move.to] == -1) // { // move.promoted = true; // squares[move.to] = (sbyte)move.promotionType; // } if (move.promoted) { bool isWhite = (squares[move.to] == 1); switch (move.promotionType) { case 2: squares[move.to] = (sbyte)(isWhite ? 2 : -2); break; case 3: squares[move.to] = (sbyte)(isWhite ? 3 : -3); break; case 4: squares[move.to] = (sbyte)(isWhite ? 4 : -4); break; case 5: squares[move.to] = (sbyte)(isWhite ? 5 : -5); break; } } if (move is cgCastlingMove) { //if move is castling there is a secondary move to also perform. squares[(move as cgCastlingMove).secondTo] = squares[(move as cgCastlingMove).secondFrom]; squares[(move as cgCastlingMove).secondFrom] = 0; if (_whiteTurnToMove) { whiteHasCastled = true; } else { blackHasCastled = true; } } else if (move is cgEnPassantMove) { move.capturedType = squares[(move as cgEnPassantMove).attackingSquare]; squares[(move as cgEnPassantMove).attackingSquare] = 0; } if (squares[move.to] == -2 && move.from == 0) { _blackARookMoves++; } else if (squares[move.to] == -2 && move.from == 7) { _blackHRookMoves++; } else if (squares[move.to] == 2 && move.from == 56) { _whiteARookMoves++; } else if (squares[move.to] == 2 && move.from == 63) { _whiteHRookMoves++; } //if(squares[move.to]==1) if (squares[move.to] == 6) { _whiteKingMoves++; } else if (squares[move.to] == -6) { _blackKingMoves++; } _whiteTurnToMove = !_whiteTurnToMove; }
public static string NotationFromMove(cgBoard _board, cgSimpleMove _move) { string str = ""; if (_board.moves.Count % 2 == 0) { str += (Math.Floor(_board.moves.Count / 2f) + 1).ToString() + ". "; } int typ = Mathf.Abs(_board.squares[_move.from]); List <cgSimpleMove> othermoves = _board.findLegalMoves(_board.whiteTurnToMove); List <cgSimpleMove> ambiguousMoves = new List <cgSimpleMove>(); foreach (cgSimpleMove othermove in othermoves) { if (othermove.to == _move.to && othermove.from != _move.from && Mathf.Abs(_board.squares[othermove.from]) == typ) { ambiguousMoves.Add(othermove); } } if (typ == 1 && _move.capturedType != 0) { str += cgGlobal.SquareNames[_move.from].Substring(0, 1); } if (typ == 2) { str += "R"; } if (typ == 3) { str += "N"; } if (typ == 4) { str += "B"; } if (typ == 5) { str += "Q"; } if (typ == 6 && !(_move is cgCastlingMove)) { str += "K"; } //if (typ == 6) str += "K"; if (ambiguousMoves.Count > 0 && typ != 1) { bool fileMatch = false; bool rankMatch = false; foreach (cgSimpleMove ambiguousMove in ambiguousMoves) { if (cgGlobal.SquareNames[ambiguousMove.from].Substring(0, 1) == cgGlobal.SquareNames[_move.from].Substring(0, 1)) { fileMatch = true; } if (cgGlobal.SquareNames[ambiguousMove.from].Substring(1, 1) == cgGlobal.SquareNames[_move.from].Substring(1, 1)) { rankMatch = true; } } if (!fileMatch) { str += cgGlobal.SquareNames[_move.from].Substring(0, 1); } else if (fileMatch && !rankMatch) { str += cgGlobal.SquareNames[_move.from].Substring(1, 1); } else if (fileMatch && rankMatch) { str += cgGlobal.SquareNames[_move.from]; } } if (_move.capturedType != 0) { str += "x"; } if (_move is cgCastlingMove) { if (_move.to == 2 || _move.to == 58) { str += "O-O-O"; } else { str += "O-O"; } } else { str += cgGlobal.SquareNames[_move.to]; } if (_move.promoted) { switch (_move.promotionType) { case 2: str += "=R"; break; case 3: str += "=N"; break; case 4: str += "=B"; break; case 5: str += "=Q"; break; default: break; } } return(str); }
/// <summary> /// Perform the provided move, capturing if necessary. /// </summary> /// <param name="move">The move to perform.</param> public void move(cgSimpleMove move) { moves.Add(move); moveCount++; if (move.to == 65) { return; } move.capturedType = squares[move.to]; squares[move.to] = squares[move.from]; squares[move.from] = 0; //_enPassantSquare = 0; //Pawn auto-promote to queen if (move.to < 8 && squares[move.to] == 1) { move.queened = true; squares[move.to] = 5; } else if (move.to > 55 && squares[move.to] == -1) { move.queened = true; squares[move.to] = -5; } if (move is cgCastlingMove) { //if move is castling there is a secondary move to also perform. squares[(move as cgCastlingMove).secondTo] = squares[(move as cgCastlingMove).secondFrom]; squares[(move as cgCastlingMove).secondFrom] = 0; if (_whiteTurnToMove) { whiteHasCastled = true; } else { blackHasCastled = true; } } else if (move is cgEnPassantMove) { move.capturedType = squares[(move as cgEnPassantMove).attackingSquare]; squares[(move as cgEnPassantMove).attackingSquare] = 0; } if (squares[move.to] == -2 && move.from == 0) { _blackARookMoves++; } else if (squares[move.to] == -2 && move.from == 7) { _blackHRookMoves++; } else if (squares[move.to] == 2 && move.from == 56) { _whiteARookMoves++; } else if (squares[move.to] == 2 && move.from == 63) { _whiteHRookMoves++; } //if(squares[move.to]==1) if (squares[move.to] == 6) { _whiteKingMoves++; } else if (squares[move.to] == -6) { _blackKingMoves++; } _whiteTurnToMove = !_whiteTurnToMove; }