public void Set(PGNChessGame g) { idx = -1; move = null; total_moves = 0; player = g.HasTag ("FEN") ? ChessGamePlayer. CreateFromFEN (g. GetTagValue ("FEN", null)) : ChessGamePlayer.CreatePlayer (); game = g; int n = game.Moves.Count; if (n > 0) { total_moves = (n - 1) * 2; // now see the last move ChessMove lastmove = (ChessMove) game.Moves[n - 1]; if (lastmove.blackmove == null) total_moves += 1; else total_moves += 2; } if (total_moves == 0) hasNext = false; else hasNext = true; }
/// <summary> /// Checks if the white knight move is valid /// </summary> /// <param name="board"></param> /// <param name="move"></param> /// <returns></returns> public static bool BlackKnight(ChessBoard board, ChessMove move) { //if not killing or empty space throw error if (!KillOrEmpty(move.To.X, move.To.Y, board, ChessColor.Black)) return false; //if not in a style of knight movement throw error if (Math.Abs(move.To.X - move.From.X) == 2) { if (Math.Abs(move.To.Y - move.From.Y) != 1) return false; } else if (Math.Abs(move.To.X - move.From.X) == 1) { if (Math.Abs(move.To.Y - move.From.Y) != 2) return false; } else { return false; } //all good return true; }
public bool CanMove(ChessGameField.Cell[,] field, Point posFrom, Point posTo, ChessMove lastMove) { Figure targetFig = field[posTo.X, posTo.Y].figure; if (targetFig == null || targetFig.GetOwner() != GetOwner()) { return Rook.IsPathFree(field, posFrom, posTo) || Bishop.IsPathFree(field, posFrom, posTo); } return false; }
private DecisionTree(DecisionTree parent, ChessBoard board, ChessMove move) { UvsChess.Framework.Profiler.AddToMainProfile((int)ProfilerMethodKey.DecisionTree_ctor_DecisionTree_ChessBoard_ChessMove); Children = new List<DecisionTree>(); Parent = parent; Board = board; Move = move; BestChildMove = null; }
/// <summary> /// this will define BoardAfterMove, TheMove, and HValue based on move /// </summary> /// <param name="board"></param> /// <param name="move"></param> /// <param name="colorofEnemy"></param> public Hueristic(ChessBoard board, ChessMove move, ChessColor colorofEnemy) { BoardBeforeMove = board.Clone(); BoardAfterMove = board.Clone(); BoardAfterMove.MakeMove(move); TheMove = move; //HValue = CalculateHueristicBasic(board, colorofEnemy); HValue = CalculateHueristicAdvanced(colorofEnemy); }
/// <summary> /// Returns the state after making the specified move /// </summary> /// <param name="state">The state before making the move</param> /// <param name="move">The move to make</param> /// <returns>The state after the move</returns> public int[,] GetStateAfterMove(int[,] state, ChessMove move) { int[,] newState = (int[,])state.Clone(); newState[move.To.X, move.To.Y] = newState[move.From.X, move.From.Y]; newState[move.From.X, move.From.Y] = SimpleState.Empty; if (newState[move.To.X, move.To.Y] == SimpleState.Pawn && move.To.Y == state.GetLength(1) - 1) newState[move.To.X, move.To.Y] = SimpleState.Queen; return newState; }
/// <summary> /// Checks if the move the black king wants to make is valid /// </summary> /// <param name="board">board state before move</param> /// <param name="move">move the piece wants to make</param> /// <returns>true if valid move, false is invalid</returns> public static bool BlackKing(ChessBoard board, ChessMove move) { // ensure new move is onto an enemy piece or empty space if (!KillOrEmpty(move.To.X, move.To.Y, board, ChessColor.Black)) return false; //validate the move is only one space away for a king if (Math.Abs(move.To.X - move.From.X) > 1 || Math.Abs(move.To.Y - move.From.Y) > 1) return false; //if all checks pass then return true; }
/// <summary> /// Checks if the move the white king wants to make is valid /// </summary> /// <param name="board">board state before move</param> /// <param name="move">move the piece wants to make</param> /// <returns>true if valid move, false is invalid</returns> public static bool WhiteKing(ChessBoard board, ChessMove move) { //TODO NOT DONE, still need to finish this //validate the move is still on the board as well as // ensure new move is onto an enemy piece or empty space if (!OnBoardAndKillOrEmpty(move.To.X, move.To.Y,board,ChessColor.White)) return false; //validate it doesn't put self into check //if all checks pass then return true; }
public Node(ChessColor c, ChessMove m, Node p) { color = c; move = m; parent = p; if (parent == null) { depth = 0; } else { depth = parent.depth + 1; } }
public bool CanMove(ChessGameField.Cell[,] field, Point posFrom, Point posTo, ChessMove lastMove) { Figure targetFig = field[posTo.X, posTo.Y].figure; if (targetFig == null || targetFig.GetOwner() != GetOwner()) { int difX = Math.Abs(posTo.X - posFrom.X); int difY = Math.Abs(posTo.Y - posFrom.Y); if (difX <= 1 && difY <= 1) { return true; } } return false; }
/// <summary> /// Checks if black bishop move is valid /// </summary> /// <param name="board"></param> /// <param name="move"></param> /// <returns></returns> public static bool BlackBishop(ChessBoard board, ChessMove move) { //if he tries to move diagonal throw an error if (Math.Abs(move.From.X - move.To.X) != Math.Abs(move.From.Y - move.To.Y)) { return false; } //if the path is not clear or they are not moving to kill then no good if (!PathClear(move.From.X, move.From.Y, move.To.X, move.To.Y, board) || !KillOrEmpty(move.To.X, move.To.Y, board, ChessColor.Black)) return false; //all good return true; }
public ChessMove Move(ref ChessGameField.Cell[,] field, Point posFrom, Point posTo, ChessMove lastMove) { if (CanMove(field, posFrom, posTo, lastMove)) { ChessMove move = new ChessMove(); if (field[posTo.X, posTo.Y].figure != null) { move.AddAction(new ChessMove.RemoveAction(posTo)); } move.AddAction(new ChessMove.MoveAction(posFrom, posTo)); return move; } return null; }
/// <summary> /// Converts a state based move to a ChessBoard move /// </summary> /// <param name="stateMove">The move the convert</param> /// <param name="playerColor">The color of hte player</param> /// <returns>The move corrected to work with ChessBoard</returns> public static ChessMove GetGameMove(ChessMove stateMove, ChessColor playerColor) { if (stateMove == null) return null; ChessMove gameMove = stateMove.Clone(); if (playerColor == ChessColor.White) { gameMove.From.X = Columns - gameMove.From.X - 1; gameMove.From.Y = Rows - gameMove.From.Y - 1; gameMove.To.X = Columns - gameMove.To.X - 1; gameMove.To.Y = Rows - gameMove.To.Y - 1; } return gameMove; }
public ChessMove Parse(String anRecord) { var mv = RxMove.Match(anRecord); if (mv.Success) { var m = new ChessMove(mv.Groups["Move"].Value); ParsePromotion(m, mv); if (mv.Groups["Kingside"].Success || mv.Groups["Queenside"].Success) ParseCastling(m, mv); else ParseRegular(m, mv); return m; } throw new ArgumentException(String.Format("\"{0}\" is not a valid AN string.", anRecord)); }
private void RunAiInThread() { // This is the only place that IsRunning should be set to true. this._isTurnOver = false; _hasAIEndedTurn = false; if (_isGetNextMoveCall) { _moveToReturn = this.AI.GetNextMove(_currentBoard, this.Color); } else { _isValidMove = this.AI.IsValidMove(_currentBoard, _moveToCheck, (this.Color == ChessColor.White ? ChessColor.Black : ChessColor.White)); } _hasAIEndedTurn = true; }
private bool loadMoves(string initialtoken, ArrayList tagList, ref bool tagFound) { string token; StringBuilder commentBuffer = new StringBuilder (); int moveidx = -1; ArrayList moves = new ArrayList (); ChessMove move = null; string initialComment = null; if (initialtoken == null) token = tokenizer.nextToken (); else token = initialtoken; for (; token != null; token = tokenizer.nextToken ()) { // if(token.Equals("{") || token.Equals("(") || token.Equals("<")) { if (token.Equals ("%")) { ignoreLine (token, tokenizer); continue; } else if (token.Equals (";")) { string comment = readLineComment (token, tokenizer); commentBuffer. Append (comment); continue; } else if (token.Equals ("{") || token.Equals ("(")) { string comment = readComment (token, tokenizer); commentBuffer. Append (comment); continue; } else if (isNAG (token)) { /* TODO: convert comment into a nag */ commentBuffer. Append (" " + token + " "); continue; } else if (tokenIsATermination (token)) { /* end of game */ break; } else if (token.Equals ("[")) { Console.WriteLine ("Abrupt end of the game. Didnt find the termination"); tagFound = true; break; } if (moveidx > 0 && token.Equals (".")) continue; /* process moves */ bool token_is_a_number = isNumber (token); if (!token_is_a_number && moveidx < 0) throw new PGNParserException ("Line " + tokenizer. currentLine () + ": Expecting a number. Got this token: [" + token + "]"); if (token_is_a_number) { int val = Int32. Parse (token); if (moveidx < 0) { // first time moveidx = val; move = new ChessMove (moveidx); /* if there is a comment here.. add it to the previous move * If there is no previous move.. then the comment is at the * beginning of the game. So, create a dummy chess move. */ if (commentBuffer.Length > 0) { if (moves.Count == 0) { initialComment = commentBuffer. ToString (); commentBuffer. Remove (0, commentBuffer. Length); } else { ChessMove previousmove = (ChessMove) moves [moves. Count - 1]; previousmove. blackComment = commentBuffer. ToString (); commentBuffer. Remove (0, commentBuffer. Length); } } } else if (moveidx != val) throw new PGNParserException ("Line: " + tokenizer. currentLine ()); } else if (move.whitemove == null) { /* first token after move number */ move.whitemove = token; } else if (move.blackmove == null) { move.blackmove = token; if (commentBuffer.Length > 0) { move.whiteComment = commentBuffer.ToString (); commentBuffer. Remove (0, commentBuffer. Length); } /* at this point we have the moveidx, whitemove and blackmove * Now create a chessmove. If there is any comment after this * it will be added later. */ moves.Add (move); moveidx = -1; move = null; } } if (commentBuffer.Length > 0) { if (move == null) { ChessMove previousmove = (ChessMove) moves[moves. Count - 1]; previousmove. blackComment = commentBuffer. ToString (); commentBuffer.Remove (0, commentBuffer. Length); } else { if (move.blackmove == null) move.whiteComment = commentBuffer. ToString (); else move.blackComment = commentBuffer. ToString (); } } if (move != null) moves.Add (move); PGNChessGame game = new PGNChessGame (initialComment, tagList, moves); if (GameLoaded != null) { GameLoaded (this, new GameLoadedEventArgs (game)); } return true; }
public void Next() { idx++; move = (ChessMove) game.Moves[idx / 2]; if (idx == total_moves - 1) // we have reached the last move. no more moves hasNext = false; }
private int MaxValue(int[,] state, ChessMove move, int depth, int alpha, int beta) { // If we return here, the move passed in represents the enemy's move, so we need to negate the value to obtain an evaluation of the board as it relates to us if (depth < 0 || move.Flag == ChessFlag.Checkmate) return -move.ValueOfMove; state = moveGenerator.GetEnemyState(state); int value = int.MinValue; List<ChessMove> allPossibleMoves = moveGenerator.GetAllMoves(state, true, boardEvaluator); // Sort the moves to get the most out of Alpha Beta Pruning allPossibleMoves.Sort((x, y) => y.ValueOfMove.CompareTo(x.ValueOfMove)); for (int i = 0; i < allPossibleMoves.Count && !timesUp(); i++) { ChessMove currentMove = allPossibleMoves[i]; value = Math.Max(value, MinValue(moveGenerator.GetStateAfterMove(state, currentMove), currentMove, depth - 1, alpha, beta)); if (value >= beta) return value; alpha = Math.Max(alpha, value); } return value; }
protected bool Equals(ChessMove other) { return(From.Equals(other.From) && To.Equals(other.To)); }
/// <summary> /// Adds a child decision to the decision tree. /// </summary> /// <param name="board">The board the decision was made from</param> /// <param name="move">The move decided.</param> public void AddChild(ChessBoard board, ChessMove move) { UvsChess.Framework.Profiler.AddToMainProfile((int)ProfilerMethodKey.DecisionTree_AddChild_ChessBoard_ChessMove); this.Children.Add(new DecisionTree(this, board, move)); }
public void undo() { if (history.Count == 0) { return; } ChessMove move = (ChessMove)history[history.Count - 1]; history.RemoveAt(history.Count - 1); if (move.castling) { board[Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)].moved = false; board[Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)].pieceSquare = board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].pieceSquare; board[Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)].sideSquare = board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].sideSquare; board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].moved = false; board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].pieceSquare = piece.None; board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].sideSquare = side.None; paintPiece(Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)); showPiece(Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)); hidePiece(Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)); board[Mathf.RoundToInt(move.initialPosRook.x), Mathf.RoundToInt(move.initialPosRook.y)].moved = false; board[Mathf.RoundToInt(move.initialPosRook.x), Mathf.RoundToInt(move.initialPosRook.y)].pieceSquare = board[Mathf.RoundToInt(move.finalPosRook.x), Mathf.RoundToInt(move.finalPosRook.y)].pieceSquare; board[Mathf.RoundToInt(move.initialPosRook.x), Mathf.RoundToInt(move.initialPosRook.y)].sideSquare = board[Mathf.RoundToInt(move.finalPosRook.x), Mathf.RoundToInt(move.finalPosRook.y)].sideSquare; board[Mathf.RoundToInt(move.finalPosRook.x), Mathf.RoundToInt(move.finalPosRook.y)].moved = false; board[Mathf.RoundToInt(move.finalPosRook.x), Mathf.RoundToInt(move.finalPosRook.y)].pieceSquare = piece.None; board[Mathf.RoundToInt(move.finalPosRook.x), Mathf.RoundToInt(move.finalPosRook.y)].sideSquare = side.None; paintPiece(Mathf.RoundToInt(move.initialPosRook.x), Mathf.RoundToInt(move.initialPosRook.y)); showPiece(Mathf.RoundToInt(move.initialPosRook.x), Mathf.RoundToInt(move.initialPosRook.y)); hidePiece(Mathf.RoundToInt(move.finalPosRook.x), Mathf.RoundToInt(move.finalPosRook.y)); } else { board[Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)].moved = move.moved; board[Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)].pieceSquare = board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].pieceSquare; board[Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)].sideSquare = board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].sideSquare; paintPiece(Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)); showPiece(Mathf.RoundToInt(move.initialPos.x), Mathf.RoundToInt(move.initialPos.y)); if (move.eatenPiece != piece.None) { board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].moved = move.eatenMoved; board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].pieceSquare = move.eatenPiece; board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].sideSquare = move.eatenSide; paintPiece(Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)); showPiece(Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)); } else { board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].moved = false; board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].pieceSquare = piece.None; board[Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)].sideSquare = side.None; hidePiece(Mathf.RoundToInt(move.finalPos.x), Mathf.RoundToInt(move.finalPos.y)); } } changeTurn(); }
public BoardState TryApplyMove(ChessMove newMove, out bool putsUserInCheck) { var newBoardState = new BoardState(this, newMove); if (newBoardState.KingIsCapturable()) { putsUserInCheck = true; return this; } else { putsUserInCheck = false; return newBoardState; } }
public async Task <ChessMatchStatus> Move(Stream stream, ulong channel, ulong player, string rawMove) { return(await Task.Run(async() => { var moveInput = rawMove.Replace(" ", "").ToUpper(); if (!Regex.IsMatch(moveInput, "^[A-H][1-8][A-H][1-8][Q|N|B|R]?$")) { throw new ChessException("Error parsing move. Example move: a2a4"); } var match = _chessMatches.SingleOrDefault(x => x.Channel == channel && x.Players.Contains(player)); if (match == null) { throw new ChessException("You are not currently in a game"); } var whoseTurn = match.Game.WhoseTurn; var otherPlayer = whoseTurn == Player.White ? Player.Black : Player.White; if ((whoseTurn == Player.White && player != match.Challenger) || (whoseTurn == Player.Black && player != match.Challenged)) { throw new ChessException("It's not your turn."); } var sourceX = moveInput[0].ToString(); var sourceY = moveInput[1].ToString(); var destX = moveInput[2].ToString(); var destY = moveInput[3].ToString(); char?promotionChar = moveInput.Length > 4 ? moveInput[4].ToString().ToLower()[0] : 'q'; var positionEnumValues = (IEnumerable <ChessDotNet.File>)Enum.GetValues(typeof(ChessDotNet.File)); var sourcePositionX = positionEnumValues.Single(x => x.ToString("g") == sourceX); var destPositionX = positionEnumValues.Single(x => x.ToString("g") == destX); var originalPosition = new ChessDotNet.Position(sourcePositionX, int.Parse(sourceY)); var destPosition = new ChessDotNet.Position(destPositionX, int.Parse(destY)); var piece = match.Game.GetPieceAt(originalPosition); if (piece != null && !(piece is Pawn)) { promotionChar = null; } var move = new Move(originalPosition, destPosition, whoseTurn, promotionChar); if (!match.Game.IsValidMove(move)) { throw new ChessException("Invalid move."); } var chessMove = new ChessMove { NewRank = move.NewPosition.Rank, NewFile = move.NewPosition.File, OriginalFile = move.OriginalPosition.File, OriginalRank = move.OriginalPosition.Rank, MoveDate = DateTime.Now, PreviousWhoseTurn = match.Game.WhoseTurn }; var board = match.Game.GetBoard(); for (var column = 0; column < board.Length; column++) { for (var row = 0; row < board[column].Length; row++) { chessMove.PreviousBoardState[column][row] = board[column][row]; } } match.Game.ApplyMove(move, true); match.History.Add(chessMove); match.UndoRequest = null; var checkMated = match.Game.IsCheckmated(otherPlayer); var isOver = checkMated || match.Game.IsStalemated(otherPlayer); var winner = isOver && checkMated ? player : (ulong?)null; var status = new ChessMatchStatus { IsOver = isOver, Winner = winner, IsCheck = match.Game.IsInCheck(otherPlayer) }; await WriteBoard(channel, player, stream); if (isOver) { #pragma warning disable 4014 Task.Run(async() => { using (Db db = _services.GetService <Db>()) { await db.EndMatch(match, (long?)winner); db.SaveChanges(); } }); #pragma warning restore 4014 _chessMatches.Remove(match); } else { #pragma warning disable 4014 Task.Run(async() => { using (Db db = _services.GetService <Db>()) { await db.SaveOrUpdateMatch(match); db.SaveChanges(); } }); #pragma warning restore 4014 } return await Task.FromResult(status); })); }
public bool move(int i, int j) { ChessMove move = new ChessMove(); move.castling = false; move.initialPos = new Vector2(selectedI, selectedJ); move.finalPos = new Vector2(i, j); move.eatenPiece = board[i, j].pieceSquare; move.moved = board[selectedI, selectedJ].moved; move.eatenSide = board[i, j].sideSquare; move.eatenMoved = board[i, j].moved; move.movingPiece = board[selectedI, selectedJ].pieceSquare; //把数据赋值 ChessSquare oldInitial = board[selectedI, selectedJ].Clone(); ChessSquare oldNext = board[i, j].Clone(); //复制的数据记录 board[i, j].sideSquare = board[selectedI, selectedJ].sideSquare; board[i, j].pieceSquare = board[selectedI, selectedJ].pieceSquare; board[i, j].moved = true; //旧的棋子位置需要更新状态,也就是格式化 board[selectedI, selectedJ].sideSquare = side.None; board[selectedI, selectedJ].pieceSquare = piece.None; board[selectedI, selectedJ].moved = true; //检查是否可以移动 AttacksTable t = new AttacksTable(board, !white); if (checkCheck(board, oldInitial.sideSquare, t)) { board[i, j].sideSquare = oldNext.sideSquare; board[i, j].pieceSquare = oldNext.pieceSquare; board[i, j].moved = oldNext.moved; board[selectedI, selectedJ].sideSquare = oldInitial.sideSquare; board[selectedI, selectedJ].pieceSquare = oldInitial.pieceSquare; board[selectedI, selectedJ].moved = oldInitial.moved; checkedCooldown = Time.time; return(false); } //棋子移动以及棋子移动后的状态调整 board[i, j].obj.GetComponent <Bouncy>().stopBounce(); //棋子动画停止 paintPiece(i, j); //棋子移动,具体操作将棋子的贴图赋给选择的棋盘位置上的棋子 showPiece(i, j); //让选择的棋盘为指导上的棋子显示出来 hidePiece(selectedI, selectedJ); //棋子移动后,原位置上的棋子隐藏 if (board[i, j].pieceSquare == piece.Pawn && (i == 9 || i == 2)) { selectedI = i; selectedJ = j; promotion = true; playing = false; Deselect(); board[i, j].square.GetComponent <Square>().range(); } else { changeTurn(); if (oldNext.pieceSquare == piece.King) { theEnd(); } } history.Add(move); return(true); }
private void UpdateGame() { // If the user presses a button, unhide the screen if (events.Any(e => e.type == SDL.SDL_EventType.SDL_KEYUP || e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONUP) && screenHidden && !pressedSomething) { screenHidden = false; pressedSomething = true; } // Check if the user is done preparing in skaktego if (gameState.gameType == GameTypes.SkaktegoPrep && events.Any(e => e.type == SDL.SDL_EventType.SDL_KEYUP && e.key.keysym.sym == SDL.SDL_Keycode.SDLK_RETURN) && !pressedSomething) { if (storedMove.HasValue) { storedMove.TakeMVar(x => x); } storedMove.Var = Game.DONE_PREPARING_MOVE; pressedSomething = true; } int mouseX, mouseY; SDL.SDL_GetMouseState(out mouseX, out mouseY); if (events.Any(e => e.type == SDL.SDL_EventType.SDL_KEYUP && e.key.keysym.sym == SDL.SDL_Keycode.SDLK_ESCAPE) && !pressedSomething) { isMenuActive = !isMenuActive; pressedSomething = true; } Rect boardRect = new Rect(0, 0, 0, 0); { // Board size int bs = gameState.board.Size; boardRect.W = Math.Min(screenRect.H / bs * bs, screenRect.W / bs * bs); boardRect.H = Math.Min(screenRect.H / bs * bs, screenRect.W / bs * bs); } boardRect.X = (int)Math.Round((screenRect.W - boardRect.W) * 0.5); boardRect.Y = (int)Math.Round((screenRect.H - boardRect.H) * 0.5); int boardMouseX = (int)Math.Floor((mouseX - boardRect.X) / (double)boardRect.W * gameState.board.Size); int boardMouseY = -1 + gameState.board.Size - ((int)Math.Floor((mouseY - boardRect.Y) / (double)boardRect.H * gameState.board.Size)); if (isMenuActive) { foreach (Button button in buttons) { if (pressedSomething) { break; } pressedSomething |= button.Update(mouseX, mouseY, boardRect, events); } } else if (!screenHidden) { Rect xButtonRect = new Rect(0, 0, 0, 0); xButtonRect.W = (Math.Min(screenRect.H, screenRect.W) / 16); xButtonRect.H = (Math.Min(screenRect.H, screenRect.W) / 16); xButtonRect.X = screenRect.W - (Math.Min(screenRect.H, screenRect.W) / 12); xButtonRect.Y = (Math.Min(screenRect.H, screenRect.W) / 50); foreach (Button button in gameButtons) { if (pressedSomething) { break; } pressedSomething |= button.Update(mouseX, mouseY, xButtonRect, events); } if (!doneGaming) { if (0 <= boardMouseX && boardMouseX < gameState.board.Size) { if (0 <= boardMouseY && boardMouseY < gameState.board.Size) { highlightedTile = new BoardPosition(boardMouseX, boardMouseY); } else { highlightedTile = null; } } else { highlightedTile = null; } if (events.Any(e => e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONUP && e.button.button == SDL.SDL_BUTTON_LEFT) && !pressedSomething ) { pressedSomething = true; // If a tile is already selected, attempt to apply the move if (selectedTile.HasValue && highlightedTile.HasValue ) { ChessMove move = new ChessMove(selectedTile.Value, highlightedTile.Value); bool isMoveLegal = false; foreach (BoardPosition legalPos in legalMoves) { if (move.to == legalPos) { isMoveLegal = true; } } if (isMoveLegal) { if (storedMove.HasValue) { storedMove.TakeMVar(x => x); } storedMove.Var = move; legalMoves.Clear(); selectedTile = null; highlightedTile = null; } } SelectTile(gameState, highlightedTile); } else if (events.Any(e => e.type == SDL.SDL_EventType.SDL_MOUSEBUTTONUP && e.button.button == SDL.SDL_BUTTON_RIGHT) && !pressedSomething ) { selectedTile = null; legalMoves.Clear(); pressedSomething = true; } } if (doneGaming) { foreach (Button button in endButtons) { if (pressedSomething) { break; } pressedSomething |= button.Update(mouseX, mouseY, screenRect, events); } } } DrawGame(gameState); }
public void WhenThereIsCapture_MovingPieceAndReversingTheMoveWillReaddRemovedPieceToAvailablePieces() { var whiteKingMock = new Mock <IChessPiece>(MockBehavior.Strict); var blackKingMock = new Mock <IChessPiece>(MockBehavior.Strict); var pawnMock = new Mock <IChessPiece>(MockBehavior.Strict); var pieceMoverMock = new Mock <IPieceMover>(MockBehavior.Strict); var piecesFactoryMock = new Mock <IPiecesFactory>(MockBehavior.Strict); var whiteKingPosition = new Position(4, 0); var blackKingPosition = new Position(4, 7); var pawnPosition = new Position(4, 1); var chessMove = new ChessMove(whiteKingPosition, new Position(4, 1), true); whiteKingMock .SetupGet(k => k.Color) .Returns(ChessColor.White); whiteKingMock .SetupGet(k => k.PieceType) .Returns(ChessPieceType.King); whiteKingMock .SetupGet(k => k.Position) .Returns(whiteKingPosition); blackKingMock .SetupGet(k => k.Color) .Returns(ChessColor.Black); blackKingMock .SetupGet(k => k.PieceType) .Returns(ChessPieceType.King); blackKingMock .SetupGet(k => k.Position) .Returns(blackKingPosition); pawnMock .SetupGet(k => k.Color) .Returns(ChessColor.Black); pawnMock .SetupGet(k => k.PieceType) .Returns(ChessPieceType.Pawn); pawnMock .SetupGet(k => k.Position) .Returns(pawnPosition); pieceMoverMock .Setup(p => p.Move(chessMove, It.IsAny <IEnumerable <IChessPiece> >())) .Returns(pawnMock.Object); pieceMoverMock .Setup(p => p.ReverseLastMove(It.IsAny <IEnumerable <IChessPiece> >())) .Returns(chessMove.IsCapture); var pieces = new HashSet <IChessPiece>(); pieces.Add(whiteKingMock.Object); pieces.Add(blackKingMock.Object); pieces.Add(pawnMock.Object); piecesFactoryMock .Setup(f => f.Create()) .Returns(pieces); var chessBoard = new ChessBoard(piecesFactoryMock.Object, pieceMoverMock.Object); chessBoard.Move(chessMove); chessBoard.ReverseLastMove(); Assert.AreEqual(3, chessBoard.Pieces.Count()); Assert.Contains(whiteKingMock.Object, chessBoard.Pieces.ToList()); Assert.Contains(blackKingMock.Object, chessBoard.Pieces.ToList()); Assert.Contains(pawnMock.Object, chessBoard.Pieces.ToList()); }
public ChessMove Get(string id) { string connstr = Environment.GetEnvironmentVariable("DWKDBConnectionString"); using (DWKDBDataContext DB = new DWKDBDataContext(connstr)) { id = id.Replace("x", "."); var parms = id.Split('|'); Player player = null; ChessMove move = new ChessMove(); move.WebID = parms[0]; move.ThisMove = parms[1]; // here we will want to do some validation // first we will want to validate that the parameters look correct. // TODO: verify parameters var movesList = DB.GetGameByWebID(move.WebID).ToList(); CastleCriteria cc = CheckForCastleCriteria(movesList); if (cc.lastPlayerIsWhite) { //if last player was white then player is black player = new Player(SQLChess.PlayerColor.Black); player.KingHasMoved = cc.BlackKingHasMoved; player.KingsRookHasMoved = cc.BlackKingsRookHasMoved; player.QueensRookHasMoved = cc.BlackQueensRookHasMoved; move.Color = "B"; } else { player = new Player(SQLChess.PlayerColor.White); player.KingHasMoved = cc.WhiteKingHasMoved; player.KingsRookHasMoved = cc.WhiteKingsRookHasMoved; player.QueensRookHasMoved = cc.WhiteQueensRookHasMoved; move.Color = "W"; } if (movesList.Count == 0) { player.OpponentsMove = "RNBKQBNRPPPPPPPP................................pppppppprnbkqbnr"; player.MyLastMove = ""; } else if (movesList.Count == 1) { player.OpponentsMove = movesList.Last().Board; player.MyLastMove = ""; } else { player.OpponentsMove = movesList.Last().Board; player.MyLastMove = movesList.Skip(movesList.Count - 2).First().Board; } List <string> legalMoves = player.FindLegalMoves(); if (legalMoves.Count < 1) { bool inCheck = player.AmIChecked(player.OpponentsMove); if (inCheck) { move.ThisMove = string.Format("Checkmate: {0} loses.", player.PlayerIsWhite ? "White" : "Black"); move.IsCheckmate = true; DB.SaveMove(move.WebID, move.ThisMove); DB.SaveGameByWebID(move.WebID); return(move); } else { move.ThisMove = string.Format("Stalemate: {0} out of legal moves.", player.PlayerIsWhite ? "White" : "Black"); move.IsStalemate = true; DB.SaveMove(move.WebID, move.ThisMove); DB.SaveGameByWebID(move.WebID); return(move); } } else if (legalMoves.Contains(move.ThisMove)) { DB.SaveMove(move.WebID, move.ThisMove); move.MyLastMove = player.MyLastMove; move.IsLegalMove = true; } else { move.MyLastMove = player.MyLastMove; move.ThisMove = player.OpponentsMove.Replace(".", "x"); move.IsLegalMove = false; return(move); } //*------------------------------------------- movesList = DB.GetGameByWebID(move.WebID).ToList(); cc = CheckForCastleCriteria(movesList); if (cc.lastPlayerIsWhite) { //if last player was white then player is black player = new Player(SQLChess.PlayerColor.Black); player.KingHasMoved = cc.BlackKingHasMoved; player.KingsRookHasMoved = cc.BlackKingsRookHasMoved; player.QueensRookHasMoved = cc.BlackQueensRookHasMoved; move.Color = "B"; } else { player = new Player(SQLChess.PlayerColor.White); player.KingHasMoved = cc.WhiteKingHasMoved; player.KingsRookHasMoved = cc.WhiteKingsRookHasMoved; player.QueensRookHasMoved = cc.WhiteQueensRookHasMoved; move.Color = "W"; } if (movesList.Count > 1) { player.MyLastMove = movesList.Skip(movesList.Count - 2).First().Board; } else { player.MyLastMove = ""; } player.OpponentsMove = movesList.Skip(movesList.Count - 2).Last().Board; move.ThisMove = player.Move(); if (move.ThisMove == string.Format("Checkmate: {0} loses.", player.PlayerIsWhite ? "White" : "Black")) { move.IsCheckmate = true; DB.SaveMove(move.WebID, move.ThisMove); DB.SaveGameByWebID(move.WebID); return(move); } else if (move.ThisMove == string.Format("Stalemate: {0} out of legal moves.", player.PlayerIsWhite ? "White" : "Black")) { move.IsStalemate = true; DB.SaveMove(move.WebID, move.ThisMove); DB.SaveGameByWebID(move.WebID); return(move); } else { DB.SaveMove(move.WebID, move.ThisMove); move.IsLegalMove = true; move.ThisMove = move.ThisMove.Replace(".", "x"); return(move); } } }
/// <summary> /// Validates a move. The framework uses this to validate the opponents move. /// </summary> /// <param name="currentBoard">The board as it currently is.</param> /// <param name="moveToCheck">This is the move that needs to be checked to see if it's valid.</param> /// <param name="colorOfPlayerMoving">This is the color of the player who's making the move.</param> /// <returns>Returns true if the move was valid</returns> public bool? IsValidMove(ChessBoard currentBoard, ChessMove moveToCheck) { _moveToReturn = null; _isGetNextMoveCall = false; _isValidMove = false; if (this.IsHuman) { // Humans don't check the AI's moves, so just always return true return true; } _currentBoard = currentBoard.Clone(); _moveToCheck = moveToCheck.Clone(); StartAiInTimedThread(UvsChess.Gui.Preferences.CheckMoveTimeout); if ((_moveToReturn != null) && (_moveToReturn.Flag == ChessFlag.AIWentOverTime)) { // The AI Went over time while validating the move. Signal ChessGame of this. return null; } return _isValidMove; }
// Recursively find best moves private static float Minimax(List <ChessMove> allMoves, Dictionary <Square, AiChessPiece> board, float[,] strength, Stack <ChessMove> moveStack, Player currentPlayer, int turnDepth, int moveDepth, int threadIndex, int turnIndex) { // Base case if (turnDepth == 0) { return(EvaluationValues.BoardEvaluate(board, strength, false)); } // If new turn, switch players if (moveDepth == 0) { Player opposite = currentPlayer.Name == "player1" ? Game.Controller.Player2 : Game.Controller.Player1; opposite.Commanders["M"].Moved = false; opposite.Commanders["R"].Moved = false; opposite.Commanders["L"].Moved = false; _ratings[threadIndex][turnIndex] += Minimax(GetMovesForPlayer(board, strength, opposite), board, strength, moveStack, opposite, turnDepth - 1, 3, threadIndex, turnIndex); } else { int movesSearched = 0; // Iterate over possible moves for (int i = 0; i < allMoves.Count; i++) { if (i >= allMoves.Count || movesSearched >= PossibleMoveDepth) { break; } ChessMove move = allMoves[i]; if (!board.ContainsKey(move.InitialSquare) || move.Attack && !board.ContainsKey(move.TargetSquare)) { continue; } int parentNodes = 3 - moveDepth; // Store results in _turns if (turnDepth == TurnSearchDepth) { turnIndex = GetIndex(_turns[threadIndex], _ratings[threadIndex]); for (int j = 0; j < parentNodes; j++) { _turns[threadIndex][turnIndex][j] = moveStack.Skip(parentNodes - j - 1).First(); _ratings[threadIndex][turnIndex] += _ratings[threadIndex][turnIndex - (j + 1)]; } } movesSearched++; _totalMovesSearched++; if (turnDepth == TurnSearchDepth) { _turns[threadIndex][turnIndex][parentNodes] = move; } // Save state of piece/board before making a move AiChessPiece holder = null; float[,] holderStrength = null; bool[] commanderState = new bool[3]; // Make a move MakeMove(board, ref strength, moveStack, move, ref holder, ref holderStrength, currentPlayer, ref commanderState); // Determine next best move _ratings[threadIndex][turnIndex] += Minimax(GetMovesForPlayer(board, strength, currentPlayer), board, strength, moveStack, currentPlayer, turnDepth, moveDepth - 1, threadIndex, turnIndex); // Unmake move UnmakeMove(board, ref strength, moveStack, ref holder, ref holderStrength, currentPlayer, ref commanderState); } } return(EvaluationValues.BoardEvaluate(board, strength, false)); }
private void RunAiInThread() { // This is the only place that IsRunning should be set to true. this._isTurnOver = false; _hasAIEndedTurn = false; if (_isGetNextMoveCall) { try { _moveToReturn = this.AI.GetNextMove(_currentBoard, this.Color); } catch (Exception e) { throw (new Exception("StudentAI.GetNextMove() threw exception: " + e.Message)); } } else { try { _isValidMove = this.AI.IsValidMove(_currentBoard, _moveToCheck, (this.Color == ChessColor.White ? ChessColor.Black : ChessColor.White)); } catch (Exception e) { throw (new Exception("StudentAI.IsValidMove() threw exception: " + e.Message)); } } _hasAIEndedTurn = true; }
// Logic for handling a move being made in AI evaluation private static void MakeMove(Dictionary <Square, AiChessPiece> board, ref float[,] strength, Stack <ChessMove> moves, ChessMove move, ref AiChessPiece holder, ref float[,] holderStrength, Player player, ref bool[] commanderState) { holderStrength = strength.Clone() as float[, ]; moves.Push(move); AiChessPiece piece = board[move.InitialSquare]; // make the next move if (move.Attack) { holder = board[move.TargetSquare]; board.Remove(move.TargetSquare); if (!move.AttackOnly) { board.Remove(move.InitialSquare); board.Add(move.TargetSquare, piece); piece.Position = move.TargetSquare; } } else { board.Remove(move.InitialSquare); board.Add(move.TargetSquare, piece); piece.Position = move.TargetSquare; } player.Commanders[piece.GetDivision()].Moved = true; //player.RemainingMoves--; commanderState[0] = player.Commanders["M"].Moved; commanderState[1] = player.Commanders["R"].Moved; commanderState[2] = player.Commanders["L"].Moved; }
/// <summary> /// gets move for a specfic piece /// </summary> public static List<ChessMove> getmovesofpiece(StudentAI ai,ChessColor color, ChessBoard board,ChessLocation location) { List<ChessMove> piecemoves = new List<ChessMove>(); ChessMove move = new ChessMove(location,location); switch (board[location]) { case ChessPiece.BlackPawn: ChessMove bdiag1 = new ChessMove(location,new ChessLocation((location.X)-1,(location.Y)+1)); ChessMove bdown = new ChessMove(location,new ChessLocation((location.X),(location.Y)+1)); ChessMove bdown2 = new ChessMove(location, new ChessLocation((location.X), (location.Y) + 2)); ChessMove bdiag2 = new ChessMove(location,new ChessLocation((location.X)+1,(location.Y)+1)); if (ai.IsValidMove(board, bdiag1, color)) piecemoves.Add(bdiag1); if (ai.IsValidMove(board, bdown, color)) piecemoves.Add(bdown); if (ai.IsValidMove(board, bdiag2, color)) piecemoves.Add(bdiag2); if (ai.IsValidMove(board, bdown2, color)) piecemoves.Add(bdown2); break; case ChessPiece.WhitePawn: ChessMove wdiag1 = new ChessMove(location,new ChessLocation((location.X)-1,(location.Y)-1)); ChessMove wup = new ChessMove(location,new ChessLocation((location.X),(location.Y)-1)); ChessMove wup2 = new ChessMove(location, new ChessLocation((location.X), (location.Y) - 2)); ChessMove wdiag2 = new ChessMove(location,new ChessLocation((location.X)+1,(location.Y)-1)); if (ai.IsValidMove(board, wdiag1, color)) piecemoves.Add(wdiag1); if (ai.IsValidMove(board, wup, color)) piecemoves.Add(wup); if (ai.IsValidMove(board, wdiag2, color)) piecemoves.Add(wdiag2); if (ai.IsValidMove(board, wup2, color)) piecemoves.Add(wup2); break; case ChessPiece.BlackKing: for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { move = new ChessMove(location, new ChessLocation(location.X + i, location.Y + j)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); } } break; case ChessPiece.WhiteKing: for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { move = new ChessMove(location, new ChessLocation(location.X + i, location.Y + j)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); } } break; case ChessPiece.BlackKnight: move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + 1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + -1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + 2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + -2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + 1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + -1)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + 2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + -2)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); break; case ChessPiece.WhiteKnight: move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + 1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 2, location.Y + -1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + 2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + 1, location.Y + -2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + 1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -2, location.Y + -1)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + 2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); move = new ChessMove(location, new ChessLocation(location.X + -1, location.Y + -2)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); break; case ChessPiece.BlackBishop: case ChessPiece.WhiteBishop: bool flag = true; int x = 1; while(flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y + x)); if(ai.IsValidMove(board,move,color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } break; case ChessPiece.BlackRook: case ChessPiece.WhiteRook: flag = true; x = 1; while(flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while(flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while(flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y+x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while(flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y-x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } break; case ChessPiece.BlackQueen: case ChessPiece.WhiteQueen: flag = true; x = 1; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X + x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X - x, location.Y)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y + x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } x = 1; flag = true; while (flag) { move = new ChessMove(location, new ChessLocation(location.X, location.Y - x)); if (ai.IsValidMove(board, move, color)) piecemoves.Add(move); else flag = false; x++; } break; default: return piecemoves; } return piecemoves; }
// copy constructor public ChessMove(ChessMove cm) { this.move = cm.move; }
/// <summary> /// This is an end-game heuristic used only when we're down to only a few select pieces /// </summary> /// <param name="state">The state to generate the heursitic for</param> /// <param name="move">The state move that was made to create this new state</param> /// <returns>Numeric value indicating a value for this state</returns> public int Endgame(int[,] state, ChessMove move) { int result = 0; // ek = enemyKing, k = our king, r = rook/queen int ekRow = -1, ekCol = -1, kRow = -1, kCol = -1, rRow = -1, rCol = -1; bool isQueen = true; for (int column = 0; column < ChessBoard.NumberOfColumns; column++) { for (int row = 0; row < ChessBoard.NumberOfRows; row++) { switch (state[column, row]) { case -SimpleState.King: ekCol = column; ekRow = row; break; case SimpleState.King: kCol = column; kRow = row; break; case SimpleState.Rook: rCol = column; rRow = row; isQueen = false; break; case SimpleState.Queen: rCol = column; rRow = row; break; } } } // only evaluate if there is a rook/queen if (rCol != -1) { // if rook is by our king, add 64 points if ((rCol == kCol && rRow == kRow + 1) || (rCol == kCol && rRow == kRow - 1) || (rRow == kRow && rCol == kCol + 1) || (rRow == kRow && rCol == kCol - 1) || (rCol == kCol + 1 && rRow == kRow + 1) || (rCol == kCol + 1 && rRow == kRow - 1) || (rCol == kCol - 1 && rRow == kRow + 1) || (rCol == kCol - 1 && rRow == kRow - 1)) { result += 1000; // if rook is by our king and between our king and his king, add 64 more points if ((!((ekCol < rCol && kCol < rCol) || (ekCol > rCol && kCol > rCol))) || (!((ekRow < rRow && kRow < rRow) || (ekRow > rRow && kRow > rRow)))) { result += 1000; } } else { if (moveGenerator.InDanger(state, new ChessLocation(rCol, rRow))) result = int.MinValue + 1; // If our king is nearing their king and our Rook/Queen is not by our king, so move it closer to our king else if (Math.Abs(ekCol - kCol) == 2 || Math.Abs(ekRow - kRow) == 2 && ((Math.Abs(kCol - rCol) == 1) || (Math.Abs(kRow - rRow) == 1))) result += 1500; // Move our king closer to thier king else result += ((700 - Math.Abs(ekCol - kCol) * 100) + (700 - Math.Abs(ekRow - kRow) * 100)); } // find the area his king is restricted to. Add 64 - area so that the smaller the area, the better the move int area = 0; if (rCol > ekCol && rRow < ekRow) // ek is to right and above rook { area = (rCol) * (ChessBoard.NumberOfRows - 1 - rRow); result += (64 - area); } else if (rCol > ekCol && rRow > ekRow)// ek is to the right and below rook { area = rCol * rRow; result += (64 - area); } else if (rCol < ekCol && rRow < ekRow) // ek is to the left and above rook { area = (ChessBoard.NumberOfColumns - 1 - rCol) * (ChessBoard.NumberOfRows - 1 - rRow); result += (64 - area); } else if (rCol < ekCol && rRow > ekRow) // ek is to the left and below rook { area = (ChessBoard.NumberOfColumns - 1 - rCol) * rRow; result += (64 - area); } #region Top Right Checkmate // checkmate king in top right corner if ((ekCol == 0 || ekCol == 1) && (ekRow == 6 || ekRow == 7)) { if (isQueen) { if (kCol == 0 || kRow == 7) result = 0; else if (ekRow == 7 && ekCol == 0 && rRow == 5 && rCol == 1) result = 0; else if (ekRow == 7 && ekCol == 0 && rRow == 6 && rCol == 2) result = 0; else if (ekCol == 0 && ekRow == 6 && kCol == 2 && kRow == 6 && rCol == 2 && (rRow == 7 || rRow == 5)) result = 0; else if (ekCol == 1 && ekRow == 7 && kCol == 1 && kRow == 5 && (rCol == 2 || rCol == 0) && rRow == 5) result = 0; else if (ekCol == 0 && (ekRow == 6 || ekRow == 7) && kCol == 2 && (kRow == 5 || kRow == 6) && rCol == 1 && rRow != 7) // mate in one result += 1000; else if ((ekCol == 0 || ekCol == 1) && ekRow == 7 && (kCol == 1 || kCol == 2) && kRow == 5 && rRow == 6) result += 1000; } if (ekRow == 7 && ekCol == 0 && kRow == 5 && kCol == 0) result = 0; else if (!isQueen && ekRow == 7 && ekCol == 0 && rRow == 6 && rCol == 1) result = 0; else if ((ekRow == 7 || ekRow == 6) && ekCol == 0 && kRow == 5 && kCol == 2 && rRow == 5 && rCol == 1) result += 500; else if (ekRow == 7 && ekCol == 0 && kRow == 5 && kCol == 2 && rRow == 5 && rCol == 1) result += 1000; else if (ekRow == 7 && (ekCol == 0 || ekCol == 1) && kRow == 5 && kCol == 2 && rRow == 6 && rCol == 2) result += 500; else if (ekRow == 7 && ekCol == 1 && rRow == 6 && rCol == 2 && kRow == 5 && kCol == 1) // mate in one result += 1000; else if (ekRow == 7 && ekCol == 0 && rRow == 6 && rCol == 2 && kRow == 4 && kCol == 1) // mate in two result += 4000; else if (ekRow == 7 && ekCol == 0 && kRow == 6 && kCol == 3 && rRow == 5 && rCol == 1) // mate in two result += 4000; else if (ekRow == 6 && ekCol == 0 && kRow == 6 && kCol == 2 && rRow == 5 && rCol == 1) // mate in one result += 1000; } #endregion #region Top Left Checkmate // checkmate king in top left corner else if ((ekCol == 7 || ekCol == 6) && (ekRow == 6 || ekRow == 7)) { if (isQueen) { if (kCol == 7 || kRow == 7) result = 0; else if (ekRow == 7 && ekCol == 7 && rRow == 5 && rCol == 6) result = 0; else if (ekCol == 7 && ekRow == 6 && kCol == 5 && kRow == 6 && rCol == 5 && (rRow == 7 || rRow == 5)) result = 0; else if (ekCol == 6 && ekRow == 7 && kCol == 6 && kRow == 5 && (rCol == 5 || rCol == 7) && rRow == 5) result = 0; else if (ekRow == 7 && ekCol == 7 && rRow == 6 && rCol == 5) result = 0; else if (ekCol == 7 && (ekRow == 6 || ekRow == 7) && kCol == 5 && (kRow == 5 || kRow == 6) && rCol == 6 && rRow != 7) // mate in one result += 1000; else if ((ekCol == 7 || ekCol == 6) && ekRow == 7 && (kCol == 6 || kCol == 5) && kRow == 5 && rRow == 6) result += 1000; } if (ekRow == 7 && ekCol == 7 && kRow == 5 && kCol == 7 && rCol == 6) result = 0; else if (!isQueen && ekRow == 7 && ekCol == 7 && rRow == 6 && rCol == 6) result = 0; else if ((ekRow == 7 || ekRow == 6) && ekCol == 7 && kRow == 5 && kCol == 5 && rRow == 5 && rCol == 6) result += 500; else if (ekRow == 7 && ekCol == 7 && kRow == 5 && kCol == 5 && rRow == 5 && rCol == 6) result += 1000; else if (ekRow == 7 && (ekCol == 7 || ekCol == 6) && kRow == 5 && kCol == 5 && rRow == 6 && rCol == 5) result += 500; else if (ekRow == 7 && ekCol == 6 && rRow == 6 && rCol == 5 && kRow == 5 && kCol == 6) result += 1000; else if (ekRow == 7 && ekCol == 7 && rRow == 6 && rCol == 5 && kRow == 4 && kCol == 6) result += 4000; else if (ekRow == 6 && ekCol == 7 && kRow == 6 && kCol == 5 && rRow == 5 && rCol == 6) result += 1000; else if (ekRow == 7 && ekCol == 7 && kRow == 6 && kCol == 4 && rRow == 5 && rCol == 6) result += 4000; } #endregion #region Bottom Left checkmate // checkmate king in bottom left corner else if ((ekCol == 7 || ekCol == 6) && (ekRow == 1 || ekRow == 0)) { if (isQueen) { if (kCol == 7 || kRow == 0) result = 0; else if (ekRow == 0 && ekCol == 7 && rRow == 2 && rCol == 6) result = 0; else if (ekCol == 7 && ekRow == 1 && kCol == 5 && kRow == 1 && rCol == 5 && (rRow == 0 || rRow == 2)) result = 0; else if (ekCol == 6 && ekRow == 0 && kCol == 6 && kRow == 2 && (rCol == 5 || rCol == 7) && rRow == 2) result = 0; else if (ekRow == 0 && ekCol == 7 && rRow == 1 && rCol == 5) result = 0; else if (ekCol == 7 && (ekRow == 1 || ekRow == 0) && kCol == 5 && (kRow == 2 || kRow == 1) && rCol == 6 && rRow != 0) // mate in one result += 1000; else if ((ekCol == 7 || ekCol == 6) && ekRow == 0 && (kCol == 6 || kCol == 5) && kRow == 2 && rRow == 1) result += 1000; } if (ekRow == 0 && ekCol == 7 && kRow == 2 && kCol == 7) result = 0; else if (!isQueen && ekRow == 0 && ekCol == 7 && rRow == 1 && rCol == 6) result = 0; else if ((ekRow == 0 || ekRow == 1) && ekCol == 7 && kRow == 2 && kCol == 5 && rRow == 2 && rCol == 6) result += 500; else if (ekRow == 0 && ekCol == 7 && kRow == 2 && kCol == 5 && rRow == 2 && rCol == 6) result += 1000; else if (ekRow == 0 && (ekCol == 7 || ekCol == 6) && kRow == 2 && kCol == 5 && rRow == 1 && rCol == 5) result += 500; else if (ekRow == 0 && ekCol == 6 && rRow == 1 && rCol == 5 && kRow == 2 && kCol == 6) result += 1000; else if (ekRow == 0 && ekCol == 7 && rRow == 1 && rCol == 5 && kRow == 3 && kCol == 6) result += 4000; else if (ekRow == 1 && ekCol == 7 && kRow == 1 && kCol == 5 && rRow == 2 && rCol == 6) result += 1000; else if (ekRow == 0 && ekCol == 7 && kRow == 1 && kCol == 4 && rRow == 2 && rCol == 6) result += 4000; } #endregion #region Bottom Right Checkmate // checkmate king in bottom right corner else if ((ekCol == 0 || ekCol == 1) && (ekRow == 1 || ekRow == 0)) { if (isQueen) { if (kCol == 0 || kRow == 0) result = 0; else if (ekRow == 0 && ekCol == 0 && rRow == 2 && rCol == 1) result = 0; else if (ekCol == 0 && ekRow == 1 && kCol == 2 && kRow == 1 && rCol == 2 && (rRow == 0 || rRow == 2)) result = 0; else if (ekCol == 1 && ekRow == 0 && kCol == 1 && kRow == 2 && (rCol == 2 || rCol == 0) && rRow == 2) result = 0; else if (ekRow == 0 && ekCol == 0 && rRow == 1 && rCol == 2) result = 0; else if (ekCol == 0 && (ekRow == 1 || ekRow == 0) && kCol == 2 && (kRow == 2 || kRow == 1) && rCol == 1 && rRow != 0) // mate in one result += 1000; else if ((ekCol == 0 || ekCol == 1) && ekRow == 0 && (kCol == 1 || kCol == 2) && kRow == 2 && rRow == 1) result += 1000; } if (ekRow == 0 && ekCol == 0 && kRow == 2 && kCol == 0) result = 0; else if (!isQueen && ekRow == 0 && ekCol == 0 && rRow == 1 && rCol == 1) result = 0; else if ((ekRow == 0 || ekRow == 1) && ekCol == 0 && kRow == 2 && kCol == 2 && rRow == 2 && rCol == 1) result += 500; else if (ekRow == 0 && ekCol == 0 && kRow == 2 && kCol == 2 && rRow == 2 && rCol == 1) result += 1000; else if (ekRow == 0 && (ekCol == 0 || ekCol == 1) && kRow == 2 && kCol == 2 && rRow == 1 && rCol == 2) result += 500; else if (ekRow == 0 && ekCol == 1 && rRow == 1 && rCol == 2 && kRow == 2 && kCol == 1) result += 1000; else if (ekRow == 0 && ekCol == 0 && rRow == 1 && rCol == 2 && kRow == 3 && kCol == 1) result += 4000; else if (ekRow == 1 && ekCol == 0 && kRow == 1 && kCol == 2 && rRow == 2 && rCol == 1) result += 1000; else if (ekRow == 0 && ekCol == 0 && kRow == 1 && kCol == 3 && rRow == 2 && rCol == 1) result += 4000; } #endregion } else result = 0; if (move.Flag == ChessFlag.Checkmate) { result += 5000; } return result; }
public Hueristic getMinimax(StudentAI AI, ChessBoard board, ChessColor color, int depth, ChessColor maxColor, int alpha = -999999, int beta = 999999) { //TODO update to return heuristic instead of move and update get next move to return move of heuristic. if (depth > maxdepth) { return(new Hueristic(board, new ChessMove(null, null), color)); } List <ChessMove> allmoves = new List <ChessMove>(); allmoves.AddRange(PieceMoves.getmovesofcolor(AI, color, board)); List <Hueristic> HueristicMoves = new List <Hueristic>(); //DecisionTree descisions = new DecisionTree(board); //descisions. ChessColor oppositeColor = color == ChessColor.Black ? ChessColor.White : ChessColor.Black; //set check/checkmate flag and calculate hueristic on each move foreach (var move in allmoves) { var tempBoard = board.Clone(); tempBoard.MakeMove(move); if (StudentAI.IsKingInCheck(tempBoard, oppositeColor)) { move.Flag = ChessFlag.Check; //check for checkmate if (PieceMoves.getmovesofcolor(AI, oppositeColor, tempBoard).Count == 0) { move.Flag = ChessFlag.Checkmate; return(new Hueristic(board, move, color)); } } HueristicMoves.Add(new Hueristic(board, move, color)); if (color == maxColor && move.Flag == ChessFlag.Check) { HueristicMoves[HueristicMoves.Count - 1].HValue += 2; } if (color == maxColor && move.Flag == ChessFlag.Checkmate) { HueristicMoves[HueristicMoves.Count - 1].HValue = 10000; return(HueristicMoves[HueristicMoves.Count - 1]); } } HueristicMoves.Sort((x, y) => y.HValue.CompareTo(x.HValue)); if (AI.IsMyTurnOver() && HueristicMoves.Count > 0) { return(HueristicMoves[0]); } //if (depth == maxdepth && HueristicMoves.Count>0) // return HueristicMoves[0]; List <Hueristic> updatedhueristic = new List <Hueristic>(); //minimax and alpha beta pruning bool defined = false; var temp = new List <Hueristic>(); do { //TODO, store previous move and if we ran out of time use that one since we don't know if optimal on the next one temp = new List <Hueristic>(); foreach (var hmove in HueristicMoves) { var tempBoard = board.Clone(); if (hmove.TheMove != null) { tempBoard.MakeMove(hmove.TheMove); if (depth != maxdepth) { var oppositemove = getMinimax(AI, tempBoard, oppositeColor, depth + 1, maxColor, alpha, beta); //get best move of the other color if (oppositemove.TheMove.To != null && oppositemove.TheMove.From != null) { hmove.HValue -= oppositemove.HValue; // update our moves score based on return of projected other move } } temp.Add(hmove); // add new scored hueristic to new list if (AI.IsMyTurnOver()) { break; } //a=max(a,hueristic) if (maxColor == color) { alpha = alpha > hmove.HValue ? alpha : hmove.HValue; if (beta <= alpha) { break; } } else { beta = beta < hmove.HValue ? beta : hmove.HValue; if (beta <= alpha) { break; } } } } if (!AI.IsMyTurnOver()) { if (depth == 0) { maxdepth += 1; defined = true; updatedhueristic = temp; } } } while (!AI.IsMyTurnOver() && depth == 0); if (!defined) { updatedhueristic = temp; } updatedhueristic.Sort((x, y) => y.HValue.CompareTo(x.HValue)); // sort the new list if (color == maxColor) { if (updatedhueristic.Count == 0) { var game_over = new ChessMove(null, null); game_over.Flag = ChessFlag.Stalemate; var game_overhueristic = new Hueristic(board, game_over, color); return(game_overhueristic); } int tiecount = -1; foreach (var x in updatedhueristic) { if (x.HValue == updatedhueristic[0].HValue) { tiecount++; } } if (tiecount > 0) { return(updatedhueristic[rand.Next(0, tiecount)]); } } if (updatedhueristic.Count == 0) { return(new Hueristic(board, new ChessMove(null, null), color)); } return(updatedhueristic[0]); //return the best value from the new list }
/// <summary> /// Converts a string representation of a move into a ChessMove object. /// Must work with any string representation created by MoveToString. /// </summary> public ChessMove ParseMove(string moveText) { // BoardPosition start = ParsePosition(moveText.Substring(0,2)); // BoardPosition end = ParsePosition(moveText.Substring(4,2)); moveText = moveText.Replace(" ", ""); if (moveText.StartsWith("(") && moveText.EndsWith(")")) { moveText = moveText.Replace("(", ""); moveText = moveText.Replace(")", ""); } else if (moveText.StartsWith("(")) { moveText = moveText.Replace("(", ""); } string[] movesArr = moveText.Split(','); BoardPosition start = ParsePosition(movesArr[0]); BoardPosition end = ParsePosition(movesArr[1]); if (movesArr.Length > 2) { String moveType = movesArr[2]; moveType.ToLower(); ChessMove move = new ChessMove(start, end, ChessMoveType.Normal); switch (moveType) { case "queen": move = new ChessMove(start, end, ChessPieceType.Queen); break; case "rook": move = new ChessMove(start, end, ChessPieceType.Rook); break; case "bishop": move = new ChessMove(start, end, ChessPieceType.Bishop); break; case "knight": move = new ChessMove(start, end, ChessPieceType.Knight); break; case "castlequeenside": move = new ChessMove(start, end, ChessMoveType.CastleQueenSide); break; case "castlekingside": move = new ChessMove(start, end, ChessMoveType.CastleKingSide); break; case "enpassant": move = new ChessMove(start, end, ChessMoveType.EnPassant); break; case "Queen": move = new ChessMove(start, end, ChessPieceType.Queen); break; case "Rook": move = new ChessMove(start, end, ChessPieceType.Rook); break; case "Bishop": move = new ChessMove(start, end, ChessPieceType.Bishop); break; case "Knight": move = new ChessMove(start, end, ChessPieceType.Knight); break; case "Castlequeenside": move = new ChessMove(start, end, ChessMoveType.CastleQueenSide); break; case "Castlekingside": move = new ChessMove(start, end, ChessMoveType.CastleKingSide); break; case "Enpassant": move = new ChessMove(start, end, ChessMoveType.EnPassant); break; } return(move); } else if (moveText.Equals("e1,g1") || moveText.Equals("e8,g8")) { return(new ChessMove(start, end, ChessMoveType.CastleKingSide)); } else if (moveText.Equals("e1,c1") || moveText.Equals("e8,c8")) { return(new ChessMove(start, end, ChessMoveType.CastleQueenSide)); } else { return(new ChessMove(start, end, ChessMoveType.Normal)); } }
/// <summary> /// Applies a move for the current player at the given position. /// </summary> public void ApplyMove(BoardPosition position) { var possMoves = mBoard.GetPossibleMoves() as IEnumerable <ChessMove>; // Validate the move as possible. foreach (var move in possMoves) { if (SelectedSquare.Position.Equals(move.StartPosition) && move.EndPosition.Equals(position)) { if (move.MoveType == ChessMoveType.PawnPromote) { var window = new PawnPromotionWindow(this, move.StartPosition, move.EndPosition); window.ShowDialog(); Promote = window.promotePicked; ChessMove m = new ChessMove(move.StartPosition, move.EndPosition, ChessMove.StringToPromoType(Promote), ChessMoveType.PawnPromote); mBoard.ApplyMove(m); foreach (var s in mSquares) { s.KingInCheck = false; } SelectedState = false; break; } else { mBoard.ApplyMove(move); foreach (var s in mSquares) { s.KingInCheck = false; } SelectedState = false; break; } } } RebindState(); if (mBoard.IsFinished) { GameFinished?.Invoke(this, new EventArgs()); } }
public bool CheckAndMakeAMove(ChessMove move) { return((chessClient.InvokeMethod <bool?>("CheckAndMakeAMove", new object[] { move })).Value); }
public async Task WriteBoard(ChessMove lastMove, ChessGame chessGame, Stream stream) { await Task.Run(() => { var board = SixLabors.ImageSharp.Image.Load(_assetService.GetImagePath("board.png")); var boardPieces = chessGame.GetBoard(); Dictionary <int, int> RankToRowMap = new Dictionary <int, int> { { 1, 7 }, { 2, 6 }, { 3, 5 }, { 4, 4 }, { 5, 3 }, { 6, 2 }, { 7, 1 }, { 8, 0 } }; board.Mutate(processor => { for (var columnIndex = 0; columnIndex < boardPieces.Length; columnIndex++) { for (var rowIndex = 0; rowIndex < boardPieces[columnIndex].Length; rowIndex++) { if ( lastMove != null && ( ((int)lastMove.OriginalFile == columnIndex && RankToRowMap[lastMove.OriginalRank] == rowIndex) || ((int)lastMove.NewFile == columnIndex && RankToRowMap[lastMove.NewRank] == rowIndex) ) ) { DrawImage(processor, "yellow_square", columnIndex, rowIndex); } var piece = boardPieces[rowIndex][columnIndex]; if (piece != null) { var fenCharacter = piece.GetFenCharacter(); if (fenCharacter.ToString().ToUpper() == "K" && chessGame.IsInCheck(piece.Owner)) { DrawImage(processor, "red_square", columnIndex, rowIndex); } var prefix = "white"; if (new[] { 'r', 'n', 'b', 'q', 'k', 'p' }.Contains(fenCharacter)) { prefix = "black"; } DrawImage(processor, $"{prefix}_{fenCharacter.ToString().ToLower()}", columnIndex, rowIndex); } } } }); board.SaveAsPng(stream); }); }
private int MinValue(int[,] state, ChessMove move, int depth, int alpha, int beta) { if (depth < 0 || move.Flag == ChessFlag.Checkmate) return move.ValueOfMove; state = moveGenerator.GetEnemyState(state); int value = int.MaxValue; List<ChessMove> allPossibleMoves = moveGenerator.GetAllMoves(state, true, boardEvaluator); // Sort the moves to get the most out of Alpha Beta Pruning allPossibleMoves.Sort((x, y) => y.ValueOfMove.CompareTo(x.ValueOfMove)); for (int i = 0; i < allPossibleMoves.Count && !timesUp(); i++) { ChessMove currentMove = allPossibleMoves[i]; value = Math.Min(value, MaxValue(moveGenerator.GetStateAfterMove(state, currentMove), currentMove, depth - 1, alpha, beta)); if (value <= alpha) return value; beta = Math.Min(beta, value); } return value; }
/// <summary> /// Applies a move for the current player at the given position. /// </summary> public async Task ApplyMove(BoardPosition position) { var possMoves = mBoard.GetPossibleMoves() as IEnumerable <ChessMove>; // Validate the move as possible. foreach (var move in possMoves) { if (SelectedSquare.Position.Equals(move.StartPosition) && move.EndPosition.Equals(position)) { if (move.MoveType == ChessMoveType.PawnPromote) { var window = new PawnPromotionWindow(this, move.StartPosition, move.EndPosition); window.ShowDialog(); Promote = window.promotePicked; ChessMove m = new ChessMove(move.StartPosition, move.EndPosition, ChessMove.StringToPromoType(Promote), ChessMoveType.PawnPromote); mBoard.ApplyMove(m); foreach (var s in mSquares) { s.KingInCheck = false; } SelectedState = false; break; } else { mBoard.ApplyMove(move); foreach (var s in mSquares) { s.KingInCheck = false; } SelectedState = false; break; } } } RebindState(); if (Players == NumberOfPlayers.One && !mBoard.IsFinished) { var bestMove = await Task.Run(() => mGameAi.FindBestMove(mBoard)); if (bestMove != null) { mBoard.ApplyMove(bestMove as ChessMove); } } RebindState(); if (mBoard.IsFinished) { GameFinished?.Invoke(this, new EventArgs()); } //Show Boardweight in a message box when a move is applied //MessageBox.Show("Board Weight: " + mBoard.BoardWeight); }
public void WhenBlackKingIsCheckedReturnsTrue() { //BK - black king //WP - white pawn //7 BK //6 WP //5 //4 //3 //2 //1 //0 // 0 1 2 3 4 5 6 7 var boardMock = new Mock <IChessBoard>(MockBehavior.Strict); var movementMock = new Mock <IMovement>(MockBehavior.Strict); var kingColor = ChessColor.Black; var kingMock = new Mock <IReadOnlyChessPiece>(MockBehavior.Strict); var enemyMock = new Mock <IReadOnlyChessPiece>(MockBehavior.Strict); var kingPosition = new Position(4, 7); var enemyPosition = new Position(3, 6); var enemyChessMove1 = new ChessMove(enemyPosition, kingPosition, true); var enemyChessMove2 = new ChessMove(enemyPosition, new Position(3, 7), false); kingMock .SetupGet(k => k.Position) .Returns(kingPosition); kingMock .SetupGet(k => k.Color) .Returns(kingColor); enemyMock .SetupGet(e => e.Position) .Returns(enemyPosition); enemyMock .SetupGet(e => e.Color) .Returns(kingColor.Opposite()); boardMock .Setup(b => b.GetKing(kingColor)) .Returns(kingMock.Object); boardMock .SetupGet(b => b.Pieces) .Returns(new List <IReadOnlyChessPiece>() { kingMock.Object, enemyMock.Object }); movementMock .Setup(m => m.GetAvailableMoves(enemyMock.Object)) .Returns(new List <ChessMove>() { enemyChessMove1, enemyChessMove2 }); var checkDetector = new CheckDetector(boardMock.Object, movementMock.Object); var isChecked = checkDetector.IsChecked(kingColor); Assert.AreEqual(true, isChecked); }
public bool move(int i, int j) { ChessMove move = new ChessMove(); move.castling = false; move.initialPos = new Vector2(selectedI, selectedJ); move.finalPos = new Vector2(i, j); move.eatenPiece = board [i, j].pieceSquare; move.moved = board [selectedI, selectedJ].moved; move.eatenSide = board [i, j].sideSquare; move.eatenMoved = board [i, j].moved; move.movingPiece = board [selectedI, selectedJ].pieceSquare; /* Guardamos los datos de las 2 */ ChessSquare oldInitial = board [selectedI, selectedJ].Clone(); ChessSquare oldNext = board [i, j].Clone(); /* Se copian los datos de la ficha */ board [i, j].sideSquare = board [selectedI, selectedJ].sideSquare; board [i, j].pieceSquare = board [selectedI, selectedJ].pieceSquare; board [i, j].moved = true; /* Se formatea la antigua celda */ board [selectedI, selectedJ].sideSquare = side.None; board [selectedI, selectedJ].pieceSquare = piece.None; board [selectedI, selectedJ].moved = true; /* Comprobamos futuro jaque. Restablecemos si es invalido el movimiento. */ AttacksTable t = new AttacksTable(board, !white); if (checkCheck(board, oldInitial.sideSquare, t)) { board [i, j].sideSquare = oldNext.sideSquare; board [i, j].pieceSquare = oldNext.pieceSquare; board [i, j].moved = oldNext.moved; board [selectedI, selectedJ].sideSquare = oldInitial.sideSquare; board [selectedI, selectedJ].pieceSquare = oldInitial.pieceSquare; board [selectedI, selectedJ].moved = oldInitial.moved; checkedCooldown = Time.time; return(false); } /* Se paran los botecitos y se desplaza la ficha */ board [i, j].obj.GetComponent <Bouncy>().stopBounce(); paintPiece(i, j); showPiece(i, j); hidePiece(selectedI, selectedJ); /* Se comprueba coronamiento y se efectua */ if (board [i, j].pieceSquare == piece.Pawn && (i == 9 || i == 2)) { selectedI = i; selectedJ = j; promotion = true; playing = false; Deselect(); board [i, j].square.GetComponent <Square>().range(); } else { changeTurn(); if (oldNext.pieceSquare == piece.King) { theEnd(); } } history.Add(move); return(true); }
public void HumanMovedPieceEvent(ChessMove move) { if (this.IsHuman) { _moveToReturn = move; _waitForPlayerEvent.Set(); } }
//This function is called each time it is your turn //Return true to end your turn, return false to ask the server for updated information public override bool run() { // Print out the current board state Console.WriteLine("+---+---+---+---+---+---+---+---+"); for (int rank = 8; rank > 0; rank--) { Console.Write("|"); for (int file = 1; file <= 8; file++) { bool found = false; // Loops through all of the pieces for (int p = 0; !found && p < pieces.Length; p++) { // determines if that piece is at the current rank and file if (pieces[p].getRank() == rank && pieces[p].getFile() == file) { found = true; // Checks if the piece is black if (pieces[p].getOwner() == 1) { Console.Write("*"); } else { Console.Write(" "); } // prints the piece's type Console.Write((char)pieces[p].getType() + " "); } } if (!found) { Console.Write(" "); } Console.Write("|"); } Console.WriteLine("\n+---+---+---+---+---+---+---+---+"); } // Looks through information about the players for (int p = 0; p < players.Length; p++) { Console.Write(players[p].getPlayerName()); // if playerID is 0, you're white, if its 1, you're black if (players[p].getId() == myID) { Console.Write(" (ME)"); // update timeRemaining timeRemaining = players[p].getTime(); } Console.WriteLine(" time remaining: " + players[p].getTime()); } // if there has been a move, print the most recent move if (moves.Length > 0) { Console.Write("Last Move Was: "); Console.WriteLine(files[moves[0].getFromFile() - 1] + "" + moves[0].getFromRank() + "-" + files[moves[0].getToFile() - 1] + "" + moves[0].getToRank()); } ///////////////////////////////////// // <-- END OF STOCK AI.cs CODE --> // ///////////////////////////////////// // print current move number Console.WriteLine("\nMove " + turnNumber().ToString("D3") + "\n========\n"); // add to GameState List and update ChessBoard if (moves.Length <= 1) { board = new ChessBoard(ref pieces, myID); states.Add(new GameState(null, null)); } else { ChessMove lastMove = ChessMove.GetChessMove(moves[0].getFromFile(), moves[0].getToFile(), moves[0].getFromRank(), moves[0].getToRank(), moves[0].getPromoteType(), states[states.Count - 1].enPassant); board = new ChessBoard(ref pieces, myID); states.Add(new GameState(states[states.Count - 1], lastMove)); } // display current score information for player Console.Write("Score for "); if (myID == ChessBoard.WHITE) { Console.WriteLine("WHITE:\n"); } else if (myID == ChessBoard.BLACK) { Console.WriteLine("BLACK:\n"); } int material = Score.GetMaterialScore(myID); int position = Score.GetPositionScore(myID); // int mobility = Score.GetPositionScore(myID); int pawn_structure = Score.GetPawnStructureScore(myID); int king_safety = Score.GetKingSafetyScore(myID); Console.WriteLine("Net Material = " + material); Console.WriteLine("Net Position = " + position); //Console.WriteLine("Net Mobility = " + mobility); Console.WriteLine("Net Pawn Structure = " + pawn_structure); Console.WriteLine("Net King Safety = " + king_safety + "\n"); Console.WriteLine("Overall Score = " + (material + position + /*mobility +*/ pawn_structure + king_safety) + "\n"); // if playing as human, get move from console prompt while (HUMAN_PLAYER) { // get legal moves for this position List <ChessMove> legalMoves = MoveGen.GenerateMoves(myID, false); // prompt user for move Console.Write("Enter a move ([from] [to] <promotion type>): "); string[] humanMove = Console.ReadLine().Split(' '); // get origin square int humanFromFile = 0, humanFromRank = 0; for (int i = 0; i < 8; i++) { if (humanMove[0][0] == files[i]) { humanFromFile = i + 1; break; } } humanFromRank = (int)Char.GetNumericValue(humanMove[0][1]); // get destination square int humanToFile = 0, humanToRank = 0; for (int i = 0; i < 8; i++) { if (humanMove[1][0] == files[i]) { humanToFile = i + 1; break; } } humanToRank = (int)Char.GetNumericValue(humanMove[1][1]); // if promotion type is specified, get the promotion piece from move int humanPromote = 0; if (humanMove.Length > 2) { humanPromote = (int)humanMove[2][0]; } // check for legality of human move bool isLegal = false; for (int i = 0; i < legalMoves.Count; i++) { ChessMove m = legalMoves[i]; if ((ChessMove.GetFile(m.GetFromSq()) + 1) == (uint)humanFromFile && (ChessMove.GetRank(m.GetFromSq()) + 1) == (uint)humanFromRank && (ChessMove.GetFile(m.GetToSq()) + 1) == (uint)humanToFile && (ChessMove.GetRank(m.GetToSq()) + 1) == (uint)humanToRank) { isLegal = true; break; } } // if move is legal, make move if (isLegal) { // get Piece associated with move Piece humanPiece = pieces[FindPiece(humanFromFile, humanFromRank)]; // make move humanPiece.move(humanToFile, humanToRank, humanPromote); return(true); } else if (!isLegal) { Console.WriteLine("ILLEGAL MOVE. Please input a legal move.\n"); } } // reset TIME_EXPIRED and timer TIME_EXPIRED = false; timer.Reset(); // reset history table history = new HistoryTable(); // run ABMiniMax int moveScore = 0, n = 0, toFile = -1, toRank = -1; uint fromSq = 0, toSq = 0, thePiece = 0; depth = 0; List <ChessMove> completeBestMoves = new List <ChessMove>(0); Search.UpdateTimePerMove(moves.Length); timer.Start(); while (!TIME_EXPIRED) { depth += 1; nodes = 0; Search.MAX_DEPTH = depth; Search.NULLMOVE_ALLOWED = true; Search.FOLLOW_PV = true; Search.PV = new List <ChessMove>(0); int score = Search.PVABMiniMax(0, Search.SMALL_NUM, Search.LARGE_NUM); if (score != Score.TIME_EXPIRED_SCORE) { moveScore = score; completeBestMoves = new List <ChessMove>(Search.PV); } // select random move from bestMoves List if (completeBestMoves.Count > 0) { n = generator.Next(0, completeBestMoves.Count - 1); // get bestMove info fromSq = completeBestMoves[n].GetFromSq(); thePiece = completeBestMoves[n].GetPiece(); toSq = completeBestMoves[n].GetToSq(); toFile = (int)((toSq % 8) + 1); toRank = (int)((toSq / 8) + 1); // print bestMove info Console.WriteLine("Best Move: " + completeBestMoves[n].GetMoveString() + ", Score: " + moveScore + ", Depth: " + depth + " (t = " + (timer.ElapsedMilliseconds / 1000.0).ToString("F3") + "s, nodes = " + nodes + ")"); } // if checkmate is found, stop searching if (score == Score.CHECKMATE_WIN_SCORE) { break; } } timer.Stop(); // output number of best moves Console.WriteLine("completeBestMoves = " + completeBestMoves.Count); // make bestMove pieces[FindPiece(fromSq, thePiece)].move(toFile, toRank, completeBestMoves[n].GetPromoteType()); // update ChessBoard and GameState List completeBestMoves[n].DoMove(Search.MAKE); return(true); }
private void GracePeriodTimer(object state) { if (! _hasAIEndedTurn) { // The AI is still running, even after the grace period. // They've now lost! _moveToReturn = new ChessMove(null, null); _moveToReturn.Flag = ChessFlag.AIWentOverTime; _aiThread.Abort(); } }
public void WhenThereIsCapture_Move_ReturnsCapturedPiece_IncrementsMoveCounter_AndAddsMoveToMovmentHistory() { var movementHistory = new Mock <IMovementHistory>(MockBehavior.Strict); var promoterMock = new Mock <IPiecePromoter>(MockBehavior.Strict); var castlingMoverMock = new Mock <ICastlingMover>(MockBehavior.Strict); var enPassantMoverMock = new Mock <IEnPassantMover>(MockBehavior.Strict); var movedPieceMock = new Mock <IChessPiece>(MockBehavior.Strict); var otherPieceMock = new Mock <IChessPiece>(MockBehavior.Strict); var capturedPieceMock = new Mock <IChessPiece>(MockBehavior.Strict); var piecePosition = new Position(3, 1); var destination = new Position(3, 3); var chessMove = new ChessMove(piecePosition, destination); movedPieceMock .SetupGet(p => p.Position) .Returns(piecePosition); movedPieceMock .SetupSet(p => p.Position = destination); movedPieceMock .Setup(p => p.IncrementMoveCounter()); otherPieceMock .SetupGet(p => p.Position) .Returns(new Position(1, 1)); capturedPieceMock .SetupGet(p => p.Position) .Returns(destination); var pieces = new List <IChessPiece>() { movedPieceMock.Object, otherPieceMock.Object, capturedPieceMock.Object }; promoterMock .Setup(p => p.PromoteIfPromotionMove(chessMove, pieces)) .Returns(false); castlingMoverMock .Setup(c => c.PerformCastlingIfCastlingMove(chessMove, pieces)) .Returns(false); enPassantMoverMock .Setup(e => e.PerformEnPassantIfApplicable(chessMove, pieces)) .Returns <IChessPiece>(null); movementHistory .Setup(h => h.Add(chessMove.ReturnWithCaptureAsTrue())); var pieceMover = new PieceMover(movementHistory.Object, promoterMock.Object, castlingMoverMock.Object, enPassantMoverMock.Object); var result = pieceMover.Move(chessMove, pieces); Assert.AreEqual(capturedPieceMock.Object, result); movedPieceMock .VerifySet(p => p.Position = destination); movedPieceMock .Verify(p => p.IncrementMoveCounter()); movementHistory .Verify(h => h.Add(chessMove.ReturnWithCaptureAsTrue())); }
// Make a new board state by applying a new move to an already existing board state. public BoardState(BoardState previousState, ChessMove newMove, bool lookForCheck = true) { BoardGrid = new ChessPiece[8, 8]; if (!newMove.KingsideCastle && !newMove.QueensideCastle) { HashSet<ChessMove> previousPossibleMoves = previousState.GetPossibleMoves(newMove.From); if (!previousPossibleMoves.Contains(newMove)) { throw new BoardStateException("Illegal move."); } } // Copy elements. for (int row = 0; row < 8; row++) { for (int column = 0; column < 8; column++) { Coordinate coordinate = new Coordinate(row, column); SetPieceAtCoordinate(previousState.GetPieceAtCoordinate(coordinate), coordinate); } } // Copy other board state values. BlackKingsideCastling = previousState.BlackKingsideCastling; BlackQueensideCastling = previousState.BlackQueensideCastling; WhiteKingsideCastling = previousState.WhiteKingsideCastling; WhiteQueensideCastling = previousState.WhiteQueensideCastling; // Turn color will be flipped and fullmove/halfmove will be incremented after move is applied. TurnColor = previousState.TurnColor; FullMove = previousState.FullMove; HalfMove = previousState.HalfMove; // Reset En Passant. EnPassantTarget = new Coordinate(-1, -1); // Castling special case. if (newMove.KingsideCastle || newMove.QueensideCastle) { int row = TurnColor == ChessPieceColor.White ? FirstRowWhite : FirstRowBlack; int rookStartColumn = newMove.KingsideCastle ? KingsideRookColumn : QueensideRookColumn; int kingEndColumn = newMove.KingsideCastle ? KingsideCastledKingColumn : QueensideCastledKingColumn; int rookEndColumn = newMove.KingsideCastle ? KingsideCastledRookColumn : QueensideCastledRookColumn; var kingStart = new Coordinate(row, KingStartColumn); var kingEnd = new Coordinate(row, kingEndColumn); var rookStart = new Coordinate(row, rookStartColumn); var rookEnd = new Coordinate(row, rookEndColumn); SetPieceAtCoordinate(new ChessPiece(ChessPieceColor.None, ChessPieceType.None), kingStart); SetPieceAtCoordinate(new ChessPiece(ChessPieceColor.None, ChessPieceType.None), rookStart); SetPieceAtCoordinate(new ChessPiece(TurnColor, ChessPieceType.King), kingEnd); SetPieceAtCoordinate(new ChessPiece(TurnColor, ChessPieceType.Rook), rookEnd); if (TurnColor == ChessPieceColor.White) { WhiteKingsideCastling = false; WhiteQueensideCastling = false; } else { BlackKingsideCastling = false; BlackQueensideCastling = false; } } // All other move types. else { // If en passant if (newMove.PieceType == ChessPieceType.Pawn) { if (previousState.EnPassantTarget.Equals(newMove.To)) { if (TurnColor == ChessPieceColor.White) { SetPieceAtCoordinate(new ChessPiece(ChessPieceColor.None, ChessPieceType.None), new Coordinate(newMove.To, -1, 0)); } else { SetPieceAtCoordinate(new ChessPiece(ChessPieceColor.None, ChessPieceType.None), new Coordinate(newMove.To, 1, 0)); } } // Mark if the new move triggers the possibilty of an En Passant from the following turn. int pawnDoubleFromRow = TurnColor == ChessPieceColor.White ? 1 : 6; int pawnDoubleToRow = TurnColor == ChessPieceColor.White ? 3 : 4; int enPassantTargetTargetRow = TurnColor == ChessPieceColor.White ? 2 : 5; if (newMove.From.Row == pawnDoubleFromRow && newMove.To.Row == pawnDoubleToRow) { EnPassantTarget = new Coordinate(enPassantTargetTargetRow, newMove.From.Column); } } // King movements disable castling. else if (newMove.PieceType == ChessPieceType.King) { if (TurnColor == ChessPieceColor.White) { WhiteKingsideCastling = false; WhiteQueensideCastling = false; } else { BlackKingsideCastling = false; BlackQueensideCastling = false; } } // Rook movements disable on their side. else if (newMove.PieceType == ChessPieceType.Rook) { if (TurnColor == ChessPieceColor.White) { if (newMove.From.Equals(new Coordinate(FirstRowWhite, KingsideRookColumn))) { WhiteKingsideCastling = false; } else if (newMove.From.Equals(new Coordinate(FirstRowWhite, QueensideRookColumn))) { WhiteQueensideCastling = false; } } else { if (newMove.From.Equals(new Coordinate(FirstRowBlack, KingsideRookColumn))) { BlackKingsideCastling = false; } else if (newMove.From.Equals(new Coordinate(FirstRowBlack, QueensideRookColumn))) { BlackQueensideCastling = false; } } } // Set square that the piece is moving from to empty, and moving to to have the piece. SetPieceAtCoordinate(new ChessPiece(ChessPieceColor.None, ChessPieceType.None), newMove.From); SetPieceAtCoordinate(new ChessPiece(TurnColor, newMove.IsPromotionToQueen ? ChessPieceType.Queen : newMove.PieceType), newMove.To); } // Reset or increment halfMove. if (newMove.IsCapture || newMove.PieceType == ChessPieceType.Pawn) { HalfMove = 0; } else { HalfMove++; } // Set applied move to be the previous move. PreviousMove = newMove; // Increment fullMove after blacks turn; if (TurnColor == ChessPieceColor.Black) { FullMove++; } // Switch turns. TurnColor = previousState.TurnColor == ChessPieceColor.White ? ChessPieceColor.Black : ChessPieceColor.White; bool isCheck = false; bool isCheckMate = false; if (lookForCheck) { new BoardState(this, out isCheck, out isCheckMate); PreviousMove = new ChessMove(PreviousMove.From, PreviousMove.To, PreviousMove.PieceType, PreviousMove.IsCapture, PreviousMove.IsPromotionToQueen, PreviousMove.DrawOfferExtended, isCheck, isCheckMate, PreviousMove.KingsideCastle, PreviousMove.QueensideCastle); } // Finally, determine the list of legal moves. InitializeAllPossibleMoves(); }
public ChessOption(ChessMove move, int score) { this.move = move; this.points = score; }
// Determine what the previous move was using Long Algebraic Notation, for example: Rd3xd7Q. private void ParseLongAlgebraicNotation(string moveString) { moveString = moveString.Trim(); int rowFrom, columnFrom, rowTo, columnTo; ChessPieceType movePieceType; bool isCapture = false, isPromotionToQueen = false, drawOfferExtended = false, isCheck = false, isCheckMate = false; int i = 0; int minLength; bool moveIsKingsideCastle = false; bool moveIsQueensideCastle = false; // Special case: no moves yet. if (moveString.Length == 0) { PreviousMove = new ChessMove(new Coordinate(-1, -1), new Coordinate(-1, -1), ChessPieceType.None, false, false, false, false, false, false, false); return; } // Special case: castling moves. Must be done in this order because QUEENSIDE_CASTLING_STRING ("0-0-0") starts with KINGSIDE_CASTLING_STRING("0-0"). if (moveString.StartsWith(QueensideCastlingString)) { movePieceType = ChessPieceType.King; moveIsQueensideCastle = true; i += QueensideCastlingString.Length; // Set to invalid values for special case of castling. rowFrom = -1; columnFrom = -1; rowTo = -1; columnTo = -1; } else if (moveString.StartsWith(KingsideCastlingString)) { movePieceType = ChessPieceType.King; moveIsKingsideCastle = true; i += KingsideCastlingString.Length; // Set to invalid values for special case of castling. rowFrom = -1; columnFrom = -1; rowTo = -1; columnTo = -1; } else { // Check to see if the first character refers to the type of piece. If it is not, it is implicity a pawn. if (moveString.Length > 0 && CharToChessPieceType.ContainsKey(moveString[i])) { movePieceType = CharToChessPieceType[moveString[i]]; i++; // How many characters to inspect depends on whether or not the piece type was implicitly a pawn minLength = MinimumAlgebraicNotationLength + 1; } else { movePieceType = ChessPieceType.Pawn; minLength = MinimumAlgebraicNotationLength; } if (moveString.Length < minLength) { throw new BoardStateException(string.Format("Invalid Long Algebraic Notation '{0}'. Long Algebraic Notation is too few characters to be valid.", moveString)); } if (FileToColumn.ContainsKey(moveString[i])) { columnFrom = FileToColumn[moveString[i]]; i++; } else { throw new BoardStateException(string.Format("Invalid Long Algebraic Notation '{0}'. Ivalid file character '{1}'", moveString, moveString[i])); } if (Char.IsNumber(moveString[i]) && moveString[i] != '0' && moveString[i] != '9') { rowFrom = Convert.ToInt32(Char.GetNumericValue(moveString[i])) - 1; i++; } else { throw new BoardStateException(string.Format("Invalid Long Algebraic Notation '{0}'. Ivalid rank character '{1}'", moveString, moveString[i])); } if (moveString[i] == '-') { isCapture = false; i++; } else if (moveString[i] == 'x') { isCapture = true; i++; } else { throw new BoardStateException(string.Format("Invalid Long Algebraic Notation '{0}'. Ivalid capture character '{1}'", moveString, moveString[i])); } if (FileToColumn.ContainsKey(moveString[i])) { columnTo = FileToColumn[moveString[i]]; i++; } else { throw new BoardStateException(string.Format("Invalid Long Algebraic Notation '{0}'. Ivalid file character '{1}'", moveString, moveString[i])); } if (Char.IsNumber(moveString[i]) && moveString[i] != '0' && moveString[i] != '9') { rowTo = Convert.ToInt32(Char.GetNumericValue(moveString[i])) - 1; i++; } else { throw new BoardStateException(string.Format("Invalid Long Algebraic Notation '{0}'. Ivalid rank character '{1}'", moveString, moveString[i])); } } // Loop the rest of the characters, if any, which are flags that can be in any order while (i < moveString.Length) { if (moveString[i] == 'Q') { isPromotionToQueen = true; } else if (moveString[i] == '=') { drawOfferExtended = true; } else if (moveString[i] == '+') { isCheck = true; } else if (moveString[i] == '#') { isCheckMate = true; } else { throw new BoardStateException(string.Format("Invalid Long Algebraic Notation '{0}'. Invalid flag character '{1}'", moveString, moveString[i])); } i++; } PreviousMove = new ChessMove(new Coordinate(rowFrom, columnFrom), new Coordinate(rowTo, columnTo), movePieceType, isCapture, isPromotionToQueen, drawOfferExtended, isCheck, isCheckMate, moveIsKingsideCastle, moveIsQueensideCastle); }
public ChessMoveWrapper(ChessMove chessMove) { ChessMove = chessMove; }
public void MakeMove(ChessMove move) { PreviousMove = move; PreviousBoard = CurrentBoard.Clone(); CurrentBoard.MakeMove(move); if (CurrentPlayerColor == ChessColor.White) { CurrentPlayerColor = ChessColor.Black; } else { CurrentPlayerColor = ChessColor.White; } }
private async void Border_MouseUpAsync(object sender, MouseButtonEventArgs e) { Border b = sender as Border; var square = b.DataContext as ChessSquare; var currentlySelected = ChessViewModel.CurrentlySelected; if (currentlySelected != null) { if (currentlySelected.Position.Equals(square.Position)) { square.IsSelected = false; square.IsHighlighted = true; ChessViewModel.CurrentlySelected = null; } else { var possibleMoves = from ChessMove m in GetPossibleMovesByStartPosition(currentlySelected) where m.EndPosition.Equals(square.Position) select m; if (possibleMoves.Any()) { ChessMove move = possibleMoves.First(); if (move.MoveType == ChessMoveType.PawnPromote) { PawnPromotion window = new PawnPromotion(ChessViewModel, currentlySelected.Position, square.Position) { ResizeMode = ResizeMode.NoResize, WindowStyle = WindowStyle.None }; window.ShowDialog(); } else { if (ChessViewModel.IsCheck) { ChessViewModel.FindKingSquareInCheck().IsInCheck = false; } var window = Window.GetWindow(this); window.IsEnabled = false; await ChessViewModel.ApplyMove(move); window.IsEnabled = true; } square.IsHighlighted = false; } else { ChessViewModel.CurrentlySelected.IsSelected = false; if (IncomingSelectionIsValidChessPiece(square)) { square.IsSelected = true; ChessViewModel.CurrentlySelected = square; } else { ChessViewModel.CurrentlySelected = null; } } } } else { if (IncomingSelectionIsValidChessPiece(square)) { square.IsHighlighted = false; square.IsSelected = true; ChessViewModel.CurrentlySelected = square; } } }