diff --git a/lib/src/model/common/node.dart b/lib/src/model/common/node.dart index d8fd12ff3a..75c7ed8b93 100644 --- a/lib/src/model/common/node.dart +++ b/lib/src/model/common/node.dart @@ -192,14 +192,24 @@ abstract class Node { bool prepend = false, }) { final pos = nodeAt(path).position; - final (newPos, newSan) = pos.makeSan(move); + final (newPos, newSan) = pos.makeSan(convertAltCastlingMove(move) ?? move); final newNode = Branch( - sanMove: SanMove(newSan, move), + sanMove: SanMove(newSan, convertAltCastlingMove(move) ?? move), position: newPos, ); return addNodeAt(path, newNode, prepend: prepend); } + /// The function `convertAltCastlingMove` checks if a move is an alternative + /// castling move and converts it to the corresponding standard castling move if so. + Move? convertAltCastlingMove(Move move) { + return altCastles.containsValue(move.uci) + ? Move.fromUci( + altCastles.entries.firstWhere((e) => e.value == move.uci).key, + ) + : move; + } + /// Deletes the node at the given path. void deleteAt(UciPath path) { parentAt(path).children.removeWhere((child) => child.id == path.last); diff --git a/test/model/common/node_test.dart b/test/model/common/node_test.dart index e06a8340df..4261e32f8d 100644 --- a/test/model/common/node_test.dart +++ b/test/model/common/node_test.dart @@ -453,6 +453,59 @@ void main() { ), ); }); + group('convert alternative castling move', () { + void makeTestAltCastlingMove(String pgn, String alt1, String alt2) { + final root = Root.fromPgnGame(PgnGame.parsePgn(pgn)); + final initialPath = root.mainlinePath; + final initialPng = root.makePgn(); + + final move = Move.fromUci(alt1); + expect(move, isNotNull); + + final newMove = root.convertAltCastlingMove(move!); + expect(newMove, isNotNull); + expect(newMove, Move.fromUci(alt2)); + expect(root.mainline.last.sanMove.move, newMove); + + final previousUciPath = root.mainlinePath.penultimate; + final (newPath, isNewNode) = root.addMoveAt(previousUciPath, move); + expect(newPath, initialPath); + expect(isNewNode, isFalse); + expect(root.makePgn(), initialPng); + } + + test('e1g1 -> e1h1', () { + makeTestAltCastlingMove( + '1. e4 e5 2. Nf3 Nf6 3. Bc4 Bc5 4. O-O', + 'e1g1', + 'e1h1', + ); + }); + + test('e8g8 -> e8h8', () { + makeTestAltCastlingMove( + '1. e4 e5 2. Nf3 Nf6 3. Bc4 Bc5 4. O-O O-O', + 'e8g8', + 'e8h8', + ); + }); + + test('e1c1 -> e1a1', () { + makeTestAltCastlingMove( + '1. d4 d5 2. Nc3 Nc6 3. Be3 Be6 4. Qd3 Qd6 5. O-O-O', + 'e1c1', + 'e1a1', + ); + }); + + test('e8c8 -> e8a8', () { + makeTestAltCastlingMove( + '1. d4 d5 2. Nc3 Nc6 3. Be3 Be6 4. Qd3 Qd6 5. O-O-O O-O-O', + 'e8c8', + 'e8a8', + ); + }); + }); }); }