protected virtual string GetSanForMove(Move move, Piece movingPiece, bool isCapture, CastlingType castle, List <Position> ambiguities) { if (castle == CastlingType.KingSide) { return("O-O"); } if (castle == CastlingType.QueenSide) { return("O-O-O"); } bool needsUnambigFile = false; bool needsUnambigRank = false; if (ambiguities.Count > 0) { foreach (Position amb in ambiguities) { if (amb.Rank == move.OriginalPosition.Rank) { needsUnambigFile = true; } if (amb.File == move.OriginalPosition.File) { needsUnambigRank = true; } } if (!needsUnambigFile && !needsUnambigRank) { needsUnambigFile = true; } } StringBuilder sanBuilder = new StringBuilder(); if (!(movingPiece is Pawn)) { sanBuilder.Append(char.ToUpperInvariant(movingPiece.GetFenCharacter())); } else if (isCapture) { sanBuilder.Append(move.OriginalPosition.File.ToString().ToLowerInvariant()); needsUnambigFile = false; needsUnambigRank = false; } if (needsUnambigFile) { sanBuilder.Append(move.OriginalPosition.File.ToString().ToLowerInvariant()); } if (needsUnambigRank) { sanBuilder.Append(move.OriginalPosition.Rank.ToString()); } if (isCapture) { sanBuilder.Append("x"); } sanBuilder.Append(move.NewPosition.ToString().ToLowerInvariant()); if (move.Promotion.HasValue) { sanBuilder.Append("="); sanBuilder.Append(move.Promotion.Value); } if (IsWinner(ChessUtilities.GetOpponentOf(WhoseTurn))) { sanBuilder.Append("#"); } else if (IsInCheck(WhoseTurn)) { sanBuilder.Append("+"); } return(sanBuilder.ToString()); }
/// <summary> /// 生成 SAN 字符串。 /// </summary> /// <param name="gameBeforeTheMove"></param> /// <returns></returns> public string GenerateSANString(ChessGame gameBeforeTheMove) { string SANResult; if (Castling.Equals(CastlingType.KingSide)) { SANResult = "O-O"; } else if (Castling.Equals(CastlingType.QueenSide)) { SANResult = "O-O-O"; } else { var sb = new System.Text.StringBuilder(); if (!(Piece is Pieces.Pawn)) { sb.Append(char.ToUpper(Piece.GetFenCharacter())); } Piece[][] board = gameBeforeTheMove.GetBoard(); List<Move> validMoves = new List<Move>(); for (int r = 0; r < 8; r++) { for (int f = 0; f < 8; f++) { if (board[r][f] != Piece) continue; Move m = new Move(new Position((File)f, 8 - r), this.NewPosition, this.Player, this.Promotion); if (gameBeforeTheMove.IsValidMove(m)) { validMoves.Add(m); } } } if (validMoves.Count == 0) throw new PgnException("This move " + this.ToString() + " is not valid for gameBeforeTheMove."); else if (validMoves.Count > 1) { bool fileUnique = true; bool rankUnique = true; foreach (var move in validMoves) { if(!(move.OriginalPosition.Equals(this.OriginalPosition))) { if (move.OriginalPosition.File == this.OriginalPosition.File) { fileUnique = false; } if (move.OriginalPosition.Rank == this.OriginalPosition.Rank) { rankUnique = false; } } } if (fileUnique) sb.Append((char)((int)'a' + (int)this.OriginalPosition.File)); else if (rankUnique) sb.Append(this.OriginalPosition.Rank.ToString()); else { sb.Append((char)((int)'a' + (int)this.OriginalPosition.File)); sb.Append(this.OriginalPosition.Rank.ToString()); } } if (IsCapture) sb.Append("x"); sb.Append(this.NewPosition.ToString().ToLower()); if (Promotion.HasValue) { sb.Append("="); sb.Append(Promotion.Value); } if (IsCheckmate.HasValue && IsCheckmate.Value) { sb.Append("#"); } else if (IsChecking.HasValue && IsChecking.Value) { sb.Append("+"); } SANResult = sb.ToString(); } try { ChessDotNet.PgnMoveReader.ParseMove(SANResult, Player, gameBeforeTheMove); } catch (PgnException) { throw new System.ArgumentException("This move " + SANResult + " is not valid for gameBeforeTheMove."); } catch (System.ArgumentException) { throw new System.ArgumentException("This move " + SANResult + " is not valid for gameBeforeTheMove."); } this._storedSANString = SANResult; return SANResult; }