/// <summary> /// Executes a command and returns a corresponding response. /// </summary> /// <param name="command">The command.</param> protected virtual Response ExecuteCommand(Command command) { switch (command.Name) { case "protocol_version": return(new Response(command, "2")); case "name": return(new Response(command, this.Name.Replace('\n', ' '))); case "version": return(new Response(command, this.Version.Replace('\n', ' '))); case "list_commands": return(new Response(command, string.Join("\n", this.SupportedCommands))); case "known_command": return(new Response( command, command.Arguments.Count > 0 && SupportedCommands.Contains(command.Arguments[0]) ? "true" : "false" )); case "quit": return(new Response(command)); case "boardsize": try { int size = int.Parse(command.Arguments[0]); if (size > 25) { throw new Exception(); } this.Board = new Board(size); return(new Response(command)); } catch {} return(new Response(command, "unacceptable size", true)); case "clear_board": this.MoveHistory.Clear(); this.Board.Clear(); return(new Response(command)); case "komi": try { this.Komi = float.Parse(command.Arguments[0]); return(new Response(command)); } catch {} return(new Response(command, "syntax error", true)); case "fixed_handicap": if (!this.Board.IsEmpty()) { return(new Response(command, "board not empty", true)); } try { int count = int.Parse(command.Arguments[0]); if (count < 2 || count > 9 || this.Board.Size < 7) { return(new Response(command, "invalid number of stones", true)); } foreach (Vertex v in Board.GetHandicapPlacement(count)) { Board[v] = 1; } return(new Response(command)); } catch {} return(new Response(command, "syntax error", true)); case "set_free_handicap": if (!this.Board.IsEmpty()) { return(new Response(command, "board not empty", true)); } try { List <Vertex> vs = new List <Vertex>(); foreach (string input in command.Arguments) { Vertex v = new Vertex(input); if (v == Vertex.Pass || vs.Contains(v)) { return(new Response(command, "bad vertex list", true)); } vs.Add(v); } foreach (Vertex v in vs) { this.Board[v] = 1; } return(new Response(command)); } catch {} return(new Response(command, "syntax error", true)); case "play": try { Move move = Move.Parse(string.Join(" ", command.Arguments)); this.Play(move); return(new Response(command)); } catch (FormatException) { return(new Response(command, "syntax error", true)); } catch (InvalidOperationException) { return(new Response(command, "illegal move", true)); } case "genmove": try { Color color = (Color)Enum.Parse(typeof(Color), command.Arguments[0], true); Vertex?vertex = GenerateMove(color); if (vertex.HasValue) { // Make move and add to move history Move move = new Move(color, vertex.Value); this.Play(move); } return(new Response(command, vertex.HasValue ? vertex.ToString() : "resign")); } catch {} return(new Response(command, "syntax error", true)); case "undo": if (MoveHistory.Count == 0) { return(new Response(command, "cannot undo", true)); } Tuple <Move, Board> tuple = MoveHistory.Pop(); this.Board = tuple.Item2; return(new Response(command)); case "showboard": string result = this.Board.ToString() + "\n-\n"; result += "(X) captured " + this.Board.Captures[Color.Black] + "\n"; result += "(O) captured " + this.Board.Captures[Color.White]; return(new Response(command, result)); } return(new Response(command, "unknown command", true)); }
public void UnMake() { if (!MoveHistory.Any()) { throw new Exception("No move to unmake"); } int MoveToUnmake = MoveHistory.Pop(); int ColorMadeMove = 1 - ColorToMove; int fromSquare = Move.FromSquare(MoveToUnmake); int toSquare = Move.ToSquare(MoveToUnmake); int fromPiece = Move.FromPiece(MoveToUnmake); int toPiece = Move.ToPiece(MoveToUnmake); MovesFiftyHistory.Pop(); //Moving Back And Cancelling Capturing SquarePiece[toSquare] = toPiece; SquarePiece[fromSquare] = fromPiece; PieceBitboard[fromPiece] ^= 1UL << fromSquare; //no changes PieceBitboard[fromPiece] ^= 1UL << toSquare; //no changes PieceBitboard[fromPiece & Color.Mask] ^= 1UL << fromSquare; //no changes PieceBitboard[fromPiece & Color.Mask] ^= 1UL << toSquare; //no changes OccupiedBB ^= 1UL << fromSquare; //no changes if (toPiece != 0) { PieceBitboard[toPiece] ^= 1UL << toSquare; PieceBitboard[toPiece & Color.Mask] ^= 1UL << toSquare; int EnemyLeftRookIndex = 56 * ColorMadeMove; if (toSquare == EnemyLeftRookIndex && toPiece == Piece.Rook && CastleShortIndex[1 - ColorMadeMove] <= 0) { CastleShortIndex[1 - ColorMadeMove]++; } else if (toSquare == EnemyLeftRookIndex + 7 && toPiece == Piece.Rook && CastleLongIndex[1 - ColorMadeMove] <= 0) { CastleShortIndex[1 - ColorMadeMove]++; } } else { OccupiedBB ^= 1UL << toSquare; } if (CastleShortIndex[ColorMadeMove] <= 0) { CastleShortIndex[ColorMadeMove]++; } if (CastleLongIndex[ColorMadeMove] <= 0) { CastleLongIndex[ColorMadeMove]++; } if (CastleShortIndex[1 - ColorMadeMove] <= 0) { CastleShortIndex[1 - ColorMadeMove]++; } if (CastleLongIndex[1 - ColorMadeMove] <= 0) { CastleLongIndex[1 - ColorMadeMove]++; } //Castling Back if (Move.Castling(MoveToUnmake)) { int sidePreIndex = 56 * ColorMadeMove; int rookSquare, rookToSquare; //Short castling (getting rook position) if (File(toSquare) == 6) { rookSquare = sidePreIndex + 7; rookToSquare = fromSquare + 1; } //Long castling (getting rook position) else { rookSquare = sidePreIndex; rookToSquare = fromSquare - 1; } //Moving the rook back SquarePiece[rookSquare] = SquarePiece[rookToSquare]; SquarePiece[rookToSquare] = 0; OccupiedBB ^= 1UL << rookSquare; OccupiedBB ^= 1UL << rookToSquare; PieceBitboard[Piece.Rook | ColorMadeMove] ^= 1UL << rookSquare; PieceBitboard[Piece.Rook | ColorMadeMove] ^= 1UL << rookToSquare; PieceBitboard[ColorMadeMove] ^= 1UL << rookSquare; PieceBitboard[ColorMadeMove] ^= 1UL << rookToSquare; } //Promotion if (Move.Promotion(MoveToUnmake)) { int PromotedTo = Move.PromotionPiece(MoveToUnmake); //Either queen, knight, bishop or rook //SquarePiece[toSquare] = PromotedTo; //If we are here, we've just set the PieceBitboard[fromPiece] to 1 at the toSquare thinking of doing the opposite, so we need to cancel that PieceBitboard[fromPiece] ^= 1UL << toSquare; PieceBitboard[PromotedTo] ^= 1UL << toSquare; //Color maps do not change, as well as occupied (we're just replacing the piece) } //Enpassant if (Move.EnPassant(MoveToUnmake)) { //Restoring the pawn int EnPassantVictimSquare = toSquare + 16 * ColorMadeMove - 8; UInt64 enPassantVictimBitboard = 1UL << EnPassantVictimSquare; OccupiedBB ^= enPassantVictimBitboard; PieceBitboard[Piece.Pawn | ColorToMove] ^= enPassantVictimBitboard; PieceBitboard[ColorToMove] ^= enPassantVictimBitboard; SquarePiece[EnPassantVictimSquare] = Piece.Pawn | ColorToMove; } ColorToMove = ColorMadeMove; EnPassantHistory.Pop(); }