toSan method
Returns the SAN (Standard Algebraic Notation) representation of a move.
Optionally, provide moves
- a list of legal moves in the current position, which
is used to determine the disambiguator. Use this if you need speed and have already
generated the list of moves elsewhere.
If checks
is false, the '+' or '#' part of the SAN string will not be
computed, which vastly increases efficiency in cases like PGN parsing.
Implementation
String toSan(Move move, {List<Move>? moves, bool checks = true}) {
if (move is PassMove) return move.algebraic();
if (move is GatingMove) {
String san = '${toSan(move.child, checks: checks)}/'
'${variant.pieces[move.dropPiece].symbol}';
if (move.castling) {
String dropSq = move.dropOnRookSquare
? size.squareName(move.child.castlingPieceSquare!)
: size.squareName(move.from);
san = '$san$dropSq';
}
// a hack, will be reworked eventually
if (san.contains('+')) {
san = '${san.replaceAll('+', '')}+';
}
if (san.contains('#')) {
san = '${san.replaceAll('#', '')}#';
}
return san;
}
if (move is! StandardMove && move is! DropMove) return '';
String san = '';
if (move.castling) {
move = move as StandardMove;
// if queenside is the only castling option, render it as 'O-O'
String kingside = 'O-O';
String queenside = variant.castlingOptions.kingside ? 'O-O-O' : kingside;
san = ([Castling.k, Castling.bk].contains(move.castlingDir))
? kingside
: queenside;
} else {
if (move is DropMove) {
PieceDefinition pieceDef = variant.pieces[move.piece];
san = move.algebraic(size);
if (!pieceDef.type.noSanSymbol) {
san = '${pieceDef.symbol.toUpperCase()}$san';
}
} else {
move = move as StandardMove;
int piece = board[move.from].type;
PieceDefinition pieceDef = variant.pieces[piece];
String disambiguator = getDisambiguator(move, moves);
if (pieceDef.type.noSanSymbol) {
if (move.capture) san = size.squareName(move.from)[0];
} else {
san = pieceDef.symbol;
}
if (disambiguator.isNotEmpty) {
san =
pieceDef.type.noSanSymbol ? disambiguator : '$san$disambiguator';
}
if (move.capture) san = '${san}x';
san = '$san${size.squareName(move.to)}';
if (move.promotion) {
san = '$san=${variant.pieces[move.promoPiece!].symbol}';
}
}
}
if (checks) {
bool ok = makeMove(move, false);
if (!ok) return 'invalid';
if (inCheck || won) {
san = '$san${won ? '#' : '+'}';
}
undo();
}
return san;
}