public static String to_chinese_name(String audio_name, ChessColour player) { String chinese_name = ""; while (audio_name.Length > 0) { if (Char.IsDigit(audio_name[0])) { chinese_name += audio_name[0].to_chinese_submove(player); try { audio_name = audio_name.Substring(1); } catch (ArgumentOutOfRangeException) { break; } continue; } chinese_name += audio_name.Substring(0, 2).to_chinese_submove(player); try { audio_name = audio_name.Substring(2); } catch (ArgumentOutOfRangeException) { break; } continue; } return(chinese_name); }
private static MoveDirection get_move_direction( CoordinateDelta delta, ChessColour player) { switch (player) { default: throw new ArgumentOutOfRangeException("选手颜色越界!"); case ChessColour.BLACK: if (delta.y < 0) { return(MoveDirection.FORWARD); } if (delta.y == 0) { return(MoveDirection.SIDEWARD); } return(MoveDirection.BACKWARD); case ChessColour.RED: if (delta.y > 0) { return(MoveDirection.FORWARD); } if (delta.y == 0) { return(MoveDirection.SIDEWARD); } return(MoveDirection.BACKWARD); } }
public Boolean has_king(ChessColour lobby_player) { ChessColour current_player = this.current_player; if (lobby_player != current_player) { return(true); } for (Int32 y = 9; y >= 0; y--) { for (Int32 x = 0; x < 9; x++) { Coordinate cdn = new Coordinate(x, y); if (!is_inside_castle(cdn, current_player)) { continue; } if (this[cdn].colour == current_player && this[cdn].type == PieceType.KING) { return(true); } } } return(false); }
private static Boolean is_inside_castle(Coordinate cdn, ChessColour player) { if (cdn.x.value < 3 || cdn.x.value > 5) { return(false); } switch (player) { default: throw new ArgumentOutOfRangeException("选手颜色越界!"); case ChessColour.BLACK: if (cdn.y.value < 7) { return(false); } return(true); case ChessColour.RED: if (cdn.y.value > 2) { return(false); } return(true); } }
public static String to_chinese_submove(this String submove, ChessColour player) { switch (submove) { default: throw new ArgumentOutOfRangeException("Submove out of range!"); case "ba": return("士"); case "ra": return("仕"); case "bb": return("象"); case "rb": return("相"); case "bc": return("砲"); case "rc": return("炮"); case "bk": return("將"); case "rk": return("帥"); case "bn": return("傌"); case "rn": return("馬"); case "bp": return("卒"); case "rp": return("兵"); case "br": return("俥"); case "rr": return("車"); case "ad": return("进"); case "tr": return("平"); case "wi": return("退"); } }
public VerticalLine(Int32 col_num, ChessColour player) : base(col_num) { if (player == ChessColour.NONE) { throw new ArgumentOutOfRangeException("选手颜色越界!"); } this.player = player; }
public void gamestart(ChessColour colour) { this.initialize_pieces(); ReflectionType reflection = colour == ChessColour.RED ? ReflectionType.None : ReflectionType.PointReflection; reflect(this.reflection ^ reflection); this.lobby_player = colour; }
public static ChessColour GetOtherColour(ChessColour currentColour) { if(currentColour == ChessColour.Black) { return ChessColour.White; } else { return ChessColour.Black; } }
public static String to_chinese_format( this CoordinateDelta delta, ChessColour player) { Int32 value = Math.Abs(delta.y); if (player == ChessColour.RED) { return("一二三四五六七八九".Substring(value - 1, 1)); } return("123456789".Substring(value - 1, 1)); }
/// <summary> /// 获得棋步的音频字符串 /// </summary> /// <param name="start">起始坐标</param> /// <param name="end">终止坐标</param> /// <returns></returns> public String get_audio_string(Coordinate start, Coordinate end) { ChessColour player = this.current_player; PieceType piece = this[start].type; CoordinateDelta delta = end - start; VerticalLine start_line = ChessPosition.get_vertical_line( start, player); VerticalLine end_line = ChessPosition.get_vertical_line( end, player); MoveDirection direction = ChessPosition.get_move_direction( delta, player); PieceIdentifier id; switch (piece) { default: throw new ArgumentOutOfRangeException("棋子种类越界!"); case PieceType.ADVISOR: case PieceType.BISHOP: return(ChessMove.to_audio_name( player, piece, start_line, direction, end_line)); case PieceType.CANNON: case PieceType.ROOK: case PieceType.PAWN: id = this.get_identifier(start); if (direction == MoveDirection.SIDEWARD) { return(ChessMove.to_audio_name( id, player, piece, start_line, direction, end_line)); } return(ChessMove.to_audio_name( id, player, piece, start_line, direction, delta)); case PieceType.KING: if (direction == MoveDirection.SIDEWARD) { return(ChessMove.to_audio_name( player, piece, start_line, direction, end_line)); } return(ChessMove.to_audio_name( player, piece, start_line, direction, delta)); case PieceType.KNIGHT: id = this.get_identifier(start); return(ChessMove.to_audio_name( id, player, piece, start_line, direction, end_line)); } }
private void chessboard_gamestart(ChessColour colour) { if (chessboard_container.InvokeRequired) { ChessColourArgReturningVoidDelegate d = new ChessColourArgReturningVoidDelegate( chessboard_gamestart); this.Invoke(d, new object[] { colour }); } else { this.chessboard_container.chessboard.gamestart(colour); } }
/// <summary> /// 相三进五型 /// </summary> /// <returns></returns> public static String to_audio_name ( ChessColour player, PieceType piece, VerticalLine start, MoveDirection direction, VerticalLine end ) { if (player == ChessColour.NONE || piece == PieceType.NONE) { throw new ArgumentOutOfRangeException("越界!"); } return(($"{player.ToString()[0]}{(char)piece}{start.value}" + $"{direction.to_audio_string()}{end.value}").ToLower()); }
public static String to_chinese_submove(this Char submove, ChessColour player) { String red_nums = "一二三四五六七八九"; String black_nums = "123456789"; Int32 num = Int32.Parse(submove.ToString()) - 1; switch (player) { default: throw new ArgumentOutOfRangeException("Player out of range!"); case ChessColour.RED: return(red_nums.Substring(num, 1)); case ChessColour.BLACK: return(black_nums.Substring(num, 1)); } }
public (bool success, string errorMessage) Move(ChessColour chessColour, int xFrom, int yFrom, int xTo, int yTo) { var piece = ( from pcs in _chessPieces where pcs.X == xFrom && pcs.Y == yFrom select pcs ).FirstOrDefault(); // If no piece could be found on the given position (xFrom, yFrom), return false. if (piece == null) { return(false, "This position is empty"); } if (piece.Colour != chessColour) { return(false, "This piece is of the opposite colour"); } var(canMove, errorMessage) = piece.CanMove(xTo, yTo, _chessPieces); // If moving the chosen piece to the chosen field is not allowed according to the CanMove method implemented // in each ChessPiece subclass, return false. if (!canMove) { return(false, errorMessage); } // All checks succeeded // If on exists, remove the chess piece currently at the position the moving piece moves to var take = ( from pcs in _chessPieces where pcs.X == xTo && pcs.Y == yTo select pcs ).FirstOrDefault(); _chessPieces.Remove(take); // Update position of moving piece piece.X = xTo; piece.Y = yTo; return(true, null); }
private int AlphaBeta(Chessboard board, int depth, int alpha, int beta, ChessColour player) { recursiveCount += 1; if (depth == 0) { return Evaluator.Evaluate(board); } Chessboard originalBoard = new Chessboard(board); if(player == ChessColour.White) { foreach(var move in FindAllMoves(board, player)) { board.MakeMove(move.FromIndex, move.ToIndex); alpha = Math.Max(alpha, AlphaBeta(board, depth - 1, alpha, beta, ChessColour.Black)); board.UndoMove(move); if(beta <= alpha) { break; } } return alpha; } else { foreach (var move in FindAllMoves(board, player)) { board.MakeMove(move.FromIndex, move.ToIndex); beta = Math.Min(beta, AlphaBeta(board, depth - 1, alpha, beta, ChessColour.White)); board.UndoMove(move); if (beta <= alpha) { break; } } return beta; } }
/// <summary> /// 前炮进一型或炮五进一型 /// </summary> /// <returns></returns> public static String to_audio_name ( PieceIdentifier id, ChessColour player, PieceType piece, VerticalLine start, MoveDirection direction, CoordinateDelta delta ) { if (id == PieceIdentifier.NONE) { return(to_audio_name( player, piece, start, direction, delta)); } if (player == ChessColour.NONE || piece == PieceType.NONE) { throw new ArgumentOutOfRangeException("越界!"); } return(($"{id.to_audio_string()}{player.ToString()[0]}{(char)piece}" + $"{direction.to_audio_string()}{Math.Abs(delta.y)}").ToLower()); }
public ChessMove FindBestAlphaBetaMove(Chessboard board, ChessColour player) { var moves = new List<Tuple<int, ChessMove>>(); foreach(var move in FindAllMoves(board, player)) { var newBoard = new Chessboard(board); newBoard.MakeMove(move.FromIndex, move.ToIndex); var score = AlphaBeta(newBoard, MAX_PLY - 1, int.MinValue, int.MaxValue, Utils.GetOtherColour(player)); moves.Add(Tuple.Create( score, move)); } if(player == ChessColour.White) { return FindMax(moves).Item2; } else { return FindMin(moves).Item2; } }
/// <summary> /// 判断棋步是否合法 /// </summary> /// <param name="start">起始坐标</param> /// <param name="end">终止坐标</param> /// <returns></returns> private Boolean is_valid_move(Coordinate start, Coordinate end) { ChessColour player = this.current_player; PieceType piece = this[start].type; CoordinateDelta delta = end - start; // 筛选偏移量是否合法 if (!CoordinateDelta.is_valid(delta, piece)) { return(false); } // 筛选忽略棋规情况下是否合法 if (!this.is_raw_move(start, end)) { return(false); } // 棋规 if (!this.check_rules(start, end)) { return(false); } return(true); }
private void makeMovePieceAssertions(int fromIndex, int toIndex, Type pieceType, ChessColour pieceColour) { Assert.IsInstanceOfType(board.Locations[toIndex].Piece, pieceType); Assert.AreEqual(board.Locations[toIndex].PieceColour, pieceColour); Assert.IsNull(board.Locations[fromIndex].Piece); }
/// <summary> /// 返回相反的颜色. /// </summary> /// <param name="colour"></param> /// <returns></returns> public static ChessColour flip(this ChessColour colour) { return(ChessColour.NONE ^ colour); }
private Tuple<int, ChessMove> FindBestMove(Chessboard board, ChessColour player, int currentPly) { recursiveCount += 1; var movesAndScore = new List<Tuple<int, ChessMove>>(); foreach(var move in FindAllMoves(board, player)) { var newBoard = new Chessboard(board); newBoard.MakeMove(move.FromIndex, move.ToIndex); // base case if (currentPly == 1) { movesAndScore.Add(new Tuple<int, ChessMove>(Evaluator.Evaluate(newBoard), move)); } else //recursive case { var bestMove = FindBestMove(newBoard, Utils.GetOtherColour(player), currentPly - 1); movesAndScore.Add(Tuple.Create(bestMove.Item1, move)); } } if (player == ChessColour.Black) { return FindMin(movesAndScore); } else { return FindMax(movesAndScore); } }
public Knight(ChessColour colour) : base(colour) { }
/// <summary> /// 初始化<see cref="Piece"/>类的新实例 /// </summary> /// <param name="colour">棋子颜色</param> /// <param name="type">棋子种类</param> public Piece(ChessColour colour, PieceType type) { this._colour = colour; this._type = type; }
private BitArray GetAttackVectors(ChessColour chessColour) { BitArray result = new BitArray(Chessboard.NumLocations, false); for (int i = 0; i < this.Locations.Count; i++) { var piece = this.Locations[i].Piece; if (piece != null && piece.Colour == chessColour) { result.Or(piece.GetCorrectedRay(i, WhiteLocations, BlackLocations)); } } return result; }
/// <summary> /// Gets all of the board location objects with a piece of a specified colour /// </summary> /// <param name="pieceColour">The piece color to filter by</param> /// <returns></returns> public IEnumerable<BoardLocation> GetLocations(ChessColour pieceColour) { // TODO method needs to be renamed, I think return from location in Locations where location.HasPiece && location.PieceColour == pieceColour select location; }
public bool IsPlayerInCheck(ChessColour playerToCheck) { int kingIndex = FindKingIndex(playerToCheck); BitArray otherPlayerAttackVectors = GetAttackVectors(playerToCheck == ChessColour.Black ? ChessColour.White : ChessColour.Black); return otherPlayerAttackVectors[kingIndex]; }
public Bishop(ChessColour colour) : base(colour) { }
/// <summary> /// 判断<see cref="ChessColour"/>是否正在被将军. /// </summary> /// <param name="player">玩家</param> /// <returns></returns> private Boolean is_check(ChessColour player) { return(false); }
/// <summary> /// 判断棋步之后该<see cref="ChessColour"/>是否被将军 /// </summary> /// <param name="start">起始坐标</param> /// <param name="end">终止坐标</param> /// <returns></returns> private Boolean is_check( Coordinate start, Coordinate end, ChessColour player) { return(this.move(start, end).is_check(player)); }
/// <summary> /// 判断忽略棋规的情况下棋步是否合法 /// </summary> /// <param name="start">起始坐标</param> /// <param name="end">终止坐标</param> private Boolean is_raw_move(Coordinate start, Coordinate end) { ChessColour player = this.current_player; PieceType piece = this[start].type; CoordinateDelta delta = end - start; switch (piece) { default: throw new ArgumentOutOfRangeException("棋子种类越界!"); case PieceType.ADVISOR: case PieceType.KING: if (ChessPosition.is_inside_castle(end, player)) { return(true); } return(false); case PieceType.BISHOP: if (ChessPosition.is_castle_side(end, player)) { if (this.check_bishop_eye(start, delta)) { return(true); } } return(false); case PieceType.CANNON: if (this[end].type == PieceType.NONE) { if (this.count_piece(start, delta) == 0) { return(true); } return(false); } if (this.count_piece(start, delta) == 1) { return(true); } return(false); case PieceType.KNIGHT: if (this.check_knight_leg(start, delta)) { return(true); } return(false); case PieceType.PAWN: if (ChessPosition.get_move_direction(delta, player) == MoveDirection.BACKWARD) { return(false); } if (ChessPosition.is_castle_side(start, player)) { if (!delta.abs().Equals(new CoordinateDelta(0, 1))) { return(false); } } return(true); case PieceType.ROOK: if (this.count_piece(start, delta) == 0) { return(true); } return(false); } }
protected ChessPiece(ChessColour colour) { this._colour = colour; }
/// <summary> /// Given a ray of potential moves (assuming the player isn't in check), this method will generate a ray /// a new ray which eliminates any of the potential moves which result in check. /// </summary> /// <param name="potentialMoves">The potential moves of a piece</param> /// <param name="index">The location of the piece</param> /// <param name="pieceColour">The colour of the piece</param> /// <returns>A bit array of moves which will NOT result in check for <paramref name="pieceColour"/></returns> private BitArray GetCheckPreventionRay(BitArray potentialMoves, int index, ChessColour pieceColour) { var ray = new BitArray(potentialMoves.Count, false); var board = new Chessboard(this); for (int i = 0; i < potentialMoves.Count; i++) { var bit = potentialMoves[i]; if (bit) { var move = Utils.BuildMove(Locations, index, i); board.MakeMove(move); if (!board.IsPlayerInCheck(pieceColour)) { ray[i] = true; } board.UndoMove(move); } } return ray; }
public bool IsPlayerInCheckmate(ChessColour player) { if (IsPlayerInCheck(player)) { return !GetAllPossibleMoves(player).HasTrue(); } else { return false; } }
public King(ChessColour colour) : base(colour) { }
/// <summary> /// Performs minimax search for best move. No pruning /// </summary> /// <param name="board"></param> /// <param name="player"></param> /// <returns></returns> public ChessMove FindBestMove(Chessboard board, ChessColour player) { return FindBestMove(board, player, MAX_PLY).Item2; }
public BoardLocation(ChessColour color, ChessPiece piece = null) { this._colour = color; this.Piece = piece; }
private BitArray GetAllPossibleMoves(ChessColour colour) { var possibleMoves = new BitArray(Chessboard.NumLocations, false); foreach (var location in Locations) { if (location.HasPiece && location.PieceColour == colour) { possibleMoves.Or(GetRay(location)); } } return possibleMoves; }
private IEnumerable<ChessMove> FindAllMoves(Chessboard board, ChessColour player) { var pieceLocations = board.GetLocations(player); foreach (var location in pieceLocations) { var locationIndex = board.Locations.IndexOf(location); var ray = board.GetRay(location); for (int i = 0; i < ray.Count; i++) { if (ray[i]) { yield return new ChessMove(locationIndex, i, location.Piece, board.Locations[i].Piece); } } } }
public bool IsPlayerInStalemate(ChessColour player) { if (!IsPlayerInCheck(player)) { return !GetAllPossibleMoves(player).HasTrue(); } else { // if the player is in check he can't possibly be in a stalemate return false; } }
public Queen(ChessColour colour) : base(colour) { }
private static VerticalLine get_vertical_line( Coordinate cdn, ChessColour player) { return(new VerticalLine(cdn.x.value, player)); }
public Pawn(ChessColour color) : base(color) { }
private int FindKingIndex(ChessColour chessColour) { for (int i = 0; i < this.Locations.Count; i++) { var piece = this.Locations[i].Piece; if (piece is King && piece.Colour == chessColour) { return i; } } throw new System.InvalidOperationException("No king was found. A king should always be present."); }
public String get_chinese_string(Coordinate start, Coordinate end) { ChessColour player = this.current_player; return(ChessMove.to_chinese_name(get_audio_string(start, end), player)); }
public Rook(ChessColour colour) : base(colour) { }