hyperchess-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +83 -0
- package/dist/board/create.d.ts +13 -0
- package/dist/board/create.d.ts.map +1 -0
- package/dist/board/create.js +21 -0
- package/dist/board/create.js.map +1 -0
- package/dist/board/hfen.d.ts +31 -0
- package/dist/board/hfen.d.ts.map +1 -0
- package/dist/board/hfen.js +181 -0
- package/dist/board/hfen.js.map +1 -0
- package/dist/board/index.d.ts +6 -0
- package/dist/board/index.d.ts.map +1 -0
- package/dist/board/index.js +11 -0
- package/dist/board/index.js.map +1 -0
- package/dist/board/move.d.ts +16 -0
- package/dist/board/move.d.ts.map +1 -0
- package/dist/board/move.js +43 -0
- package/dist/board/move.js.map +1 -0
- package/dist/board/undo.d.ts +4 -0
- package/dist/board/undo.d.ts.map +1 -0
- package/dist/board/undo.js +22 -0
- package/dist/board/undo.js.map +1 -0
- package/dist/board/validate.d.ts +7 -0
- package/dist/board/validate.d.ts.map +1 -0
- package/dist/board/validate.js +14 -0
- package/dist/board/validate.js.map +1 -0
- package/dist/game/add-move.d.ts +7 -0
- package/dist/game/add-move.d.ts.map +1 -0
- package/dist/game/add-move.js +78 -0
- package/dist/game/add-move.js.map +1 -0
- package/dist/game/index.d.ts +21 -0
- package/dist/game/index.d.ts.map +1 -0
- package/dist/game/index.js +58 -0
- package/dist/game/index.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/io/hsan-exporter.d.ts +10 -0
- package/dist/io/hsan-exporter.d.ts.map +1 -0
- package/dist/io/hsan-exporter.js +70 -0
- package/dist/io/hsan-exporter.js.map +1 -0
- package/dist/io/hsan-parser.d.ts +12 -0
- package/dist/io/hsan-parser.d.ts.map +1 -0
- package/dist/io/hsan-parser.js +118 -0
- package/dist/io/hsan-parser.js.map +1 -0
- package/dist/io/index.d.ts +3 -0
- package/dist/io/index.d.ts.map +1 -0
- package/dist/io/index.js +8 -0
- package/dist/io/index.js.map +1 -0
- package/dist/moves/index.d.ts +22 -0
- package/dist/moves/index.d.ts.map +1 -0
- package/dist/moves/index.js +39 -0
- package/dist/moves/index.js.map +1 -0
- package/dist/standalone.d.ts +64 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/standalone.js +323 -0
- package/dist/standalone.js.map +1 -0
- package/dist/types/board.d.ts +38 -0
- package/dist/types/board.d.ts.map +1 -0
- package/dist/types/board.js +7 -0
- package/dist/types/board.js.map +1 -0
- package/dist/types/game.d.ts +45 -0
- package/dist/types/game.d.ts.map +1 -0
- package/dist/types/game.js +7 -0
- package/dist/types/game.js.map +1 -0
- package/dist/types/move.d.ts +24 -0
- package/dist/types/move.d.ts.map +1 -0
- package/dist/types/move.js +7 -0
- package/dist/types/move.js.map +1 -0
- package/dist/types/piece.d.ts +50 -0
- package/dist/types/piece.d.ts.map +1 -0
- package/dist/types/piece.js +29 -0
- package/dist/types/piece.js.map +1 -0
- package/dist/utils/square-notation.d.ts +14 -0
- package/dist/utils/square-notation.d.ts.map +1 -0
- package/dist/utils/square-notation.js +27 -0
- package/dist/utils/square-notation.js.map +1 -0
- package/dist/wasm/engine.d.ts +23 -0
- package/dist/wasm/engine.d.ts.map +1 -0
- package/dist/wasm/engine.js +37 -0
- package/dist/wasm/engine.js.map +1 -0
- package/dist/wasm/snapshot.d.ts +47 -0
- package/dist/wasm/snapshot.d.ts.map +1 -0
- package/dist/wasm/snapshot.js +125 -0
- package/dist/wasm/snapshot.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/game/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAQlD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAIhE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAoB/C;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAEpD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// HyperChess Core — hyperchess-core
|
|
3
|
+
// File: packages/core/src/game/index.ts
|
|
4
|
+
// Version: 1.0.0
|
|
5
|
+
// Copyright (c) 2026 HyperChess Developer Team
|
|
6
|
+
import { createBoard } from '../board/create';
|
|
7
|
+
import { addMoveToGame } from './add-move';
|
|
8
|
+
/**
|
|
9
|
+
* Create a new game from optional starting HFEN
|
|
10
|
+
*/
|
|
11
|
+
export function createGame(hfen) {
|
|
12
|
+
return {
|
|
13
|
+
board: createBoard(hfen),
|
|
14
|
+
moves: [],
|
|
15
|
+
metadata: {},
|
|
16
|
+
status: 'active',
|
|
17
|
+
startHfen: hfen,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Add a move to the game (in algebraic or HSAN notation)
|
|
22
|
+
* Returns new Game state or null if move is invalid
|
|
23
|
+
*/
|
|
24
|
+
export function addMove(game, moveStr) {
|
|
25
|
+
const result = addMoveToGame(game, moveStr);
|
|
26
|
+
if (!result)
|
|
27
|
+
return null;
|
|
28
|
+
return { ...result, startHfen: game.startHfen };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Remove the last move from the game
|
|
32
|
+
* Reconstructs the game state from move list
|
|
33
|
+
*/
|
|
34
|
+
export function removeLastMove(game) {
|
|
35
|
+
if (game.moves.length === 0) {
|
|
36
|
+
throw new Error('No moves to remove');
|
|
37
|
+
}
|
|
38
|
+
// Reconstruct from the game's actual starting position (not always the
|
|
39
|
+
// default!) + all moves except the last.
|
|
40
|
+
let reconstructedGame = createGame(game.startHfen);
|
|
41
|
+
reconstructedGame.metadata = game.metadata;
|
|
42
|
+
const movesToReplay = game.moves.slice(0, -1);
|
|
43
|
+
for (const moveStr of movesToReplay) {
|
|
44
|
+
const result = addMove(reconstructedGame, moveStr);
|
|
45
|
+
if (!result) {
|
|
46
|
+
throw new Error(`Failed to reconstruct game: invalid move ${moveStr}`);
|
|
47
|
+
}
|
|
48
|
+
reconstructedGame = result;
|
|
49
|
+
}
|
|
50
|
+
return reconstructedGame;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Get current game status
|
|
54
|
+
*/
|
|
55
|
+
export function getGameStatus(game) {
|
|
56
|
+
return game.status;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/game/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,oCAAoC;AACpC,wCAAwC;AACxC,iBAAiB;AACjB,+CAA+C;AAG/C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,IAAiB;IAC1C,OAAO;QACL,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC;QACxB,KAAK,EAAE,EAAE;QACT,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,QAAQ;QAChB,SAAS,EAAE,IAAI;KAChB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,IAAU,EAAE,OAAe;IACjD,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,OAAO,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC;AAClD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,IAAU;IACvC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;IACxC,CAAC;IAED,uEAAuE;IACvE,yCAAyC;IACzC,IAAI,iBAAiB,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnD,iBAAiB,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAE9C,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,4CAA4C,OAAO,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,iBAAiB,GAAG,MAAM,CAAC;IAC7B,CAAC;IAED,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,IAAU;IACtC,OAAO,IAAI,CAAC,MAAM,CAAC;AACrB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { type Board, type CastlingRights, type BoardState, type HfenString } from './types/board';
|
|
2
|
+
export { type Color, type Square, type Move, type AlgebraicMove, type HsanMove, type PromotionPiece } from './types/move';
|
|
3
|
+
export { type Piece, type PieceType, type PiecePlacement, PIECE_SYMBOLS } from './types/piece';
|
|
4
|
+
export { type Game, type GameMetadata, type GameStatus, type GameResult, type GameInfo } from './types/game';
|
|
5
|
+
export { createBoard } from './board/create';
|
|
6
|
+
export { applyMove } from './board/move';
|
|
7
|
+
export { isLegalMove } from './board/validate';
|
|
8
|
+
export { undoMove } from './board/undo';
|
|
9
|
+
export { getBoardHfen } from './board/hfen';
|
|
10
|
+
export { generateLegalMoves, isInCheck, isCheckmate, isStalemate } from './moves/index';
|
|
11
|
+
export { createGame, addMove, removeLastMove, getGameStatus } from './game/index';
|
|
12
|
+
export { parseHsanMove, moveToHsan } from './io/index';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAClG,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,MAAM,EAAE,KAAK,IAAI,EAAE,KAAK,aAAa,EAAE,KAAK,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1H,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC/F,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7G,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAGxF,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// HyperChess Core — hyperchess-core
|
|
3
|
+
// File: packages/core/src/index.ts
|
|
4
|
+
// Version: 1.0.0
|
|
5
|
+
// Copyright (c) 2026 HyperChess Developer Team
|
|
6
|
+
export { PIECE_SYMBOLS } from './types/piece';
|
|
7
|
+
// Board operations
|
|
8
|
+
export { createBoard } from './board/create';
|
|
9
|
+
export { applyMove } from './board/move';
|
|
10
|
+
export { isLegalMove } from './board/validate';
|
|
11
|
+
export { undoMove } from './board/undo';
|
|
12
|
+
export { getBoardHfen } from './board/hfen';
|
|
13
|
+
// Move generation
|
|
14
|
+
export { generateLegalMoves, isInCheck, isCheckmate, isStalemate } from './moves/index';
|
|
15
|
+
// Game state
|
|
16
|
+
export { createGame, addMove, removeLastMove, getGameStatus } from './game/index';
|
|
17
|
+
// I/O & notation
|
|
18
|
+
export { parseHsanMove, moveToHsan } from './io/index';
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,oCAAoC;AACpC,mCAAmC;AACnC,iBAAiB;AACjB,+CAA+C;AAK/C,OAAO,EAAmD,aAAa,EAAE,MAAM,eAAe,CAAC;AAG/F,mBAAmB;AACnB,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,kBAAkB;AAClB,OAAO,EAAE,kBAAkB,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAExF,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElF,iBAAiB;AACjB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Board } from '../types/board';
|
|
2
|
+
import { Move } from '../types/move';
|
|
3
|
+
/**
|
|
4
|
+
* Convert a move to HSAN (this SDK's algebraic notation — named distinctly
|
|
5
|
+
* from standard chess's SAN, since piece letters/disambiguation/square range
|
|
6
|
+
* all differ on this 12x12 board with Eagle/Hawk pieces).
|
|
7
|
+
* Examples: e4, Nf3, Bxc5, O-O, e8=Q
|
|
8
|
+
*/
|
|
9
|
+
export declare function moveToHsan(board: Board, move: Move): string;
|
|
10
|
+
//# sourceMappingURL=hsan-exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsan-exporter.d.ts","sourceRoot":"","sources":["../../src/io/hsan-exporter.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAoE3D"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// HyperChess Core — hyperchess-core
|
|
3
|
+
// File: packages/core/src/io/hsan-exporter.ts
|
|
4
|
+
// Version: 1.0.0
|
|
5
|
+
// Copyright (c) 2026 HyperChess Developer Team
|
|
6
|
+
import { generateLegalMoves } from '../moves/index';
|
|
7
|
+
/**
|
|
8
|
+
* Convert a move to HSAN (this SDK's algebraic notation — named distinctly
|
|
9
|
+
* from standard chess's SAN, since piece letters/disambiguation/square range
|
|
10
|
+
* all differ on this 12x12 board with Eagle/Hawk pieces).
|
|
11
|
+
* Examples: e4, Nf3, Bxc5, O-O, e8=Q
|
|
12
|
+
*/
|
|
13
|
+
export function moveToHsan(board, move) {
|
|
14
|
+
// Handle castling. The king always ends on file 8 (kingside) or file 4
|
|
15
|
+
// (queenside), regardless of its home square, so there's no need to know
|
|
16
|
+
// where the king started to tell the sides apart.
|
|
17
|
+
if (move.isCastling) {
|
|
18
|
+
const toFile = move.to % 12;
|
|
19
|
+
if (toFile === 8)
|
|
20
|
+
return 'O-O';
|
|
21
|
+
if (toFile === 4)
|
|
22
|
+
return 'O-O-O';
|
|
23
|
+
}
|
|
24
|
+
let hsan = '';
|
|
25
|
+
const piece = board.pieces[move.from];
|
|
26
|
+
if (!piece) {
|
|
27
|
+
return ''; // Invalid move
|
|
28
|
+
}
|
|
29
|
+
// Piece prefix (omit for pawns)
|
|
30
|
+
if (piece.type !== 'P') {
|
|
31
|
+
hsan += piece.type;
|
|
32
|
+
}
|
|
33
|
+
// Disambiguation (if needed)
|
|
34
|
+
const legalMoves = generateLegalMoves(board);
|
|
35
|
+
const samePieceMoves = legalMoves.filter((m) => board.pieces[m.from]?.type === piece.type &&
|
|
36
|
+
m.to === move.to &&
|
|
37
|
+
m.from !== move.from);
|
|
38
|
+
if (samePieceMoves.length > 0) {
|
|
39
|
+
// Need disambiguation
|
|
40
|
+
const moveFromFile = move.from % 12;
|
|
41
|
+
const moveFromRank = Math.floor(move.from / 12);
|
|
42
|
+
// Check if file disambiguation is enough
|
|
43
|
+
const fileConflicts = samePieceMoves.some((m) => (m.from % 12) === moveFromFile);
|
|
44
|
+
if (fileConflicts) {
|
|
45
|
+
// Use rank
|
|
46
|
+
hsan += (moveFromRank + 1).toString();
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
// Use file
|
|
50
|
+
hsan += String.fromCharCode('a'.charCodeAt(0) + moveFromFile);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Capture indicator
|
|
54
|
+
if (board.pieces[move.to] || move.isEnPassant) {
|
|
55
|
+
hsan += 'x';
|
|
56
|
+
}
|
|
57
|
+
// Destination square
|
|
58
|
+
const toFile = String.fromCharCode('a'.charCodeAt(0) + (move.to % 12));
|
|
59
|
+
const toRank = (Math.floor(move.to / 12) + 1).toString();
|
|
60
|
+
hsan += toFile + toRank;
|
|
61
|
+
// Promotion
|
|
62
|
+
if (move.promotion) {
|
|
63
|
+
hsan += '=' + move.promotion;
|
|
64
|
+
}
|
|
65
|
+
// Check/checkmate marker
|
|
66
|
+
// Note: This requires making the move first to check the resulting position
|
|
67
|
+
// For now, omit this for performance
|
|
68
|
+
return hsan;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=hsan-exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsan-exporter.js","sourceRoot":"","sources":["../../src/io/hsan-exporter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Board } from '../types/board';
|
|
2
|
+
import { Move } from '../types/move';
|
|
3
|
+
/**
|
|
4
|
+
* Parse an HSAN move (this SDK's algebraic notation — named distinctly from
|
|
5
|
+
* standard chess's SAN, since piece letters/disambiguation/square range all
|
|
6
|
+
* differ on this 12x12 board with Eagle/Hawk pieces).
|
|
7
|
+
* Examples: e4, Nf3, Bxc5, O-O (castling), e8=Q
|
|
8
|
+
*
|
|
9
|
+
* Returns Move object or null if invalid
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseHsanMove(board: Board, hsanStr: string): Move | null;
|
|
12
|
+
//# sourceMappingURL=hsan-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsan-parser.d.ts","sourceRoot":"","sources":["../../src/io/hsan-parser.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CA4FxE"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// HyperChess Core — hyperchess-core
|
|
3
|
+
// File: packages/core/src/io/hsan-parser.ts
|
|
4
|
+
// Version: 1.0.0
|
|
5
|
+
// Copyright (c) 2026 HyperChess Developer Team
|
|
6
|
+
import { generateLegalMoves } from '../moves/index';
|
|
7
|
+
/**
|
|
8
|
+
* Parse an HSAN move (this SDK's algebraic notation — named distinctly from
|
|
9
|
+
* standard chess's SAN, since piece letters/disambiguation/square range all
|
|
10
|
+
* differ on this 12x12 board with Eagle/Hawk pieces).
|
|
11
|
+
* Examples: e4, Nf3, Bxc5, O-O (castling), e8=Q
|
|
12
|
+
*
|
|
13
|
+
* Returns Move object or null if invalid
|
|
14
|
+
*/
|
|
15
|
+
export function parseHsanMove(board, hsanStr) {
|
|
16
|
+
let hsan = hsanStr.trim();
|
|
17
|
+
// Handle castling
|
|
18
|
+
if (hsan === 'O-O' || hsan === '0-0') {
|
|
19
|
+
return parseKingSideCastling(board);
|
|
20
|
+
}
|
|
21
|
+
if (hsan === 'O-O-O' || hsan === '0-0-0') {
|
|
22
|
+
return parseQueenSideCastling(board);
|
|
23
|
+
}
|
|
24
|
+
// Strip trailing check/checkmate marker.
|
|
25
|
+
hsan = hsan.replace(/[+#]$/, '');
|
|
26
|
+
// Strip trailing promotion suffix (=Q, =E, ...).
|
|
27
|
+
let promotion = '';
|
|
28
|
+
const promoMatch = hsan.match(/=([QRBNEH])$/);
|
|
29
|
+
if (promoMatch) {
|
|
30
|
+
promotion = promoMatch[1];
|
|
31
|
+
hsan = hsan.slice(0, -promoMatch[0].length);
|
|
32
|
+
}
|
|
33
|
+
// The destination square is always at the tail: a file letter followed by
|
|
34
|
+
// a rank of 1-12 (this is a 12x12 board, so ranks 10-12 are two digits —
|
|
35
|
+
// parsing left-to-right with a single-digit rank regex would silently
|
|
36
|
+
// truncate "e10" to "e1"; anchoring on the end avoids that ambiguity).
|
|
37
|
+
const destMatch = hsan.match(/([a-l])(1[0-2]|[1-9])$/);
|
|
38
|
+
if (!destMatch) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const toFile = destMatch[1].charCodeAt(0) - 'a'.charCodeAt(0);
|
|
42
|
+
const toRank = parseInt(destMatch[2], 10) - 1;
|
|
43
|
+
const toSquare = toRank * 12 + toFile;
|
|
44
|
+
hsan = hsan.slice(0, -destMatch[0].length);
|
|
45
|
+
// Piece indicator (optional, pawn if missing) — always leads.
|
|
46
|
+
let piece = '';
|
|
47
|
+
if (hsan.length && /[PNBRQKEH]/.test(hsan[0])) {
|
|
48
|
+
piece = hsan[0];
|
|
49
|
+
hsan = hsan.slice(1);
|
|
50
|
+
}
|
|
51
|
+
// Capture indicator — always immediately precedes the destination.
|
|
52
|
+
if (hsan.endsWith('x')) {
|
|
53
|
+
hsan = hsan.slice(0, -1);
|
|
54
|
+
}
|
|
55
|
+
// Whatever remains is disambiguation: an optional source file letter
|
|
56
|
+
// followed by an optional source rank (1-12).
|
|
57
|
+
let srcFile = -1;
|
|
58
|
+
let srcRank = -1;
|
|
59
|
+
const disMatch = hsan.match(/^([a-l])?(1[0-2]|[1-9])?$/);
|
|
60
|
+
if (hsan.length && !disMatch) {
|
|
61
|
+
return null; // malformed leftover text
|
|
62
|
+
}
|
|
63
|
+
if (disMatch) {
|
|
64
|
+
if (disMatch[1])
|
|
65
|
+
srcFile = disMatch[1].charCodeAt(0) - 'a'.charCodeAt(0);
|
|
66
|
+
if (disMatch[2])
|
|
67
|
+
srcRank = parseInt(disMatch[2], 10) - 1;
|
|
68
|
+
}
|
|
69
|
+
if (toFile < 0 || toFile >= 12 || toRank < 0 || toRank >= 12) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
// Find matching legal move
|
|
73
|
+
const legalMoves = generateLegalMoves(board);
|
|
74
|
+
for (const move of legalMoves) {
|
|
75
|
+
if (move.to !== toSquare)
|
|
76
|
+
continue;
|
|
77
|
+
const sourcePiece = board.pieces[move.from];
|
|
78
|
+
if (!sourcePiece || sourcePiece.color !== board.toMove)
|
|
79
|
+
continue;
|
|
80
|
+
// Check piece type matches (pawn if no piece specified)
|
|
81
|
+
const expectedPiece = piece || 'P';
|
|
82
|
+
if (sourcePiece.type !== expectedPiece)
|
|
83
|
+
continue;
|
|
84
|
+
// Check disambiguation if specified
|
|
85
|
+
const moveFromRank = Math.floor(move.from / 12);
|
|
86
|
+
const moveFromFile = move.from % 12;
|
|
87
|
+
if (srcFile >= 0 && moveFromFile !== srcFile)
|
|
88
|
+
continue;
|
|
89
|
+
if (srcRank >= 0 && moveFromRank !== srcRank)
|
|
90
|
+
continue;
|
|
91
|
+
// Check promotion if specified
|
|
92
|
+
if (promotion && move.promotion !== promotion)
|
|
93
|
+
continue;
|
|
94
|
+
return move;
|
|
95
|
+
}
|
|
96
|
+
return null; // No matching move found
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Parse king-side castling (O-O).
|
|
100
|
+
*
|
|
101
|
+
* The king always ends on file 8 for kingside castling (this board's king
|
|
102
|
+
* starts on the g-file/file 6, not e-file, so the destination isn't the
|
|
103
|
+
* standard-chess g-file either). Matching on the destination file rather
|
|
104
|
+
* than hardcoded absolute squares keeps this correct for both colors
|
|
105
|
+
* without re-deriving the king's home square here.
|
|
106
|
+
*/
|
|
107
|
+
function parseKingSideCastling(board) {
|
|
108
|
+
const legalMoves = generateLegalMoves(board);
|
|
109
|
+
return legalMoves.find((move) => move.isCastling && move.to % 12 === 8) ?? null;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Parse queen-side castling (O-O-O). The king always ends on file 4.
|
|
113
|
+
*/
|
|
114
|
+
function parseQueenSideCastling(board) {
|
|
115
|
+
const legalMoves = generateLegalMoves(board);
|
|
116
|
+
return legalMoves.find((move) => move.isCastling && move.to % 12 === 4) ?? null;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=hsan-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hsan-parser.js","sourceRoot":"","sources":["../../src/io/hsan-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/io/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// HyperChess Core — hyperchess-core
|
|
3
|
+
// File: packages/core/src/io/index.ts
|
|
4
|
+
// Version: 1.0.0
|
|
5
|
+
// Copyright (c) 2026 HyperChess Developer Team
|
|
6
|
+
export { parseHsanMove } from './hsan-parser';
|
|
7
|
+
export { moveToHsan } from './hsan-exporter';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/io/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,oCAAoC;AACpC,sCAAsC;AACtC,iBAAiB;AACjB,+CAA+C;AAE/C,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Board } from '../types/board';
|
|
2
|
+
import { Move } from '../types/move';
|
|
3
|
+
/**
|
|
4
|
+
* Generate all legal moves for the current position.
|
|
5
|
+
*
|
|
6
|
+
* Delegates to the Rust engine via WASM — this used to be 8 hand-written
|
|
7
|
+
* per-piece move generators plus a separate check-filtering pass, which
|
|
8
|
+
* drifted out of sync with the canonical rules (wrong Eagle/Hawk rule, wrong
|
|
9
|
+
* castling geometry, a sliding-piece own-capture bug, a board-edge
|
|
10
|
+
* wraparound bug — see docs/sdk-plan/WASM-MIGRATION-PLAN.md for the full
|
|
11
|
+
* list). The Rust engine's `generate_moves()` already returns fully legal
|
|
12
|
+
* moves (king safety included), so no separate "would this leave my king in
|
|
13
|
+
* check" filter is needed here anymore either.
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateLegalMoves(board: Board): Move[];
|
|
16
|
+
/** Check if the current player's king is in check. */
|
|
17
|
+
export declare function isInCheck(board: Board): boolean;
|
|
18
|
+
/** Check if the current position is checkmate. */
|
|
19
|
+
export declare function isCheckmate(board: Board): boolean;
|
|
20
|
+
/** Check if the current position is stalemate. */
|
|
21
|
+
export declare function isStalemate(board: Board): boolean;
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/moves/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAIrC;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,CAKvD;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE/C;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAEjD;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAEjD"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
+
// HyperChess Core — hyperchess-core
|
|
3
|
+
// File: packages/core/src/moves/index.ts
|
|
4
|
+
// Version: 1.0.0
|
|
5
|
+
// Copyright (c) 2026 HyperChess Developer Team
|
|
6
|
+
import { getBoardHfen } from '../board/hfen';
|
|
7
|
+
import { loadWasmBoard, uciToMove } from '../wasm/engine';
|
|
8
|
+
/**
|
|
9
|
+
* Generate all legal moves for the current position.
|
|
10
|
+
*
|
|
11
|
+
* Delegates to the Rust engine via WASM — this used to be 8 hand-written
|
|
12
|
+
* per-piece move generators plus a separate check-filtering pass, which
|
|
13
|
+
* drifted out of sync with the canonical rules (wrong Eagle/Hawk rule, wrong
|
|
14
|
+
* castling geometry, a sliding-piece own-capture bug, a board-edge
|
|
15
|
+
* wraparound bug — see docs/sdk-plan/WASM-MIGRATION-PLAN.md for the full
|
|
16
|
+
* list). The Rust engine's `generate_moves()` already returns fully legal
|
|
17
|
+
* moves (king safety included), so no separate "would this leave my king in
|
|
18
|
+
* check" filter is needed here anymore either.
|
|
19
|
+
*/
|
|
20
|
+
export function generateLegalMoves(board) {
|
|
21
|
+
const wasmBoard = loadWasmBoard(getBoardHfen(board));
|
|
22
|
+
const uci = wasmBoard.legal_moves();
|
|
23
|
+
if (uci === '')
|
|
24
|
+
return [];
|
|
25
|
+
return uci.split(' ').map((m) => uciToMove(m, board));
|
|
26
|
+
}
|
|
27
|
+
/** Check if the current player's king is in check. */
|
|
28
|
+
export function isInCheck(board) {
|
|
29
|
+
return loadWasmBoard(getBoardHfen(board)).in_check();
|
|
30
|
+
}
|
|
31
|
+
/** Check if the current position is checkmate. */
|
|
32
|
+
export function isCheckmate(board) {
|
|
33
|
+
return loadWasmBoard(getBoardHfen(board)).termination() === 'checkmate';
|
|
34
|
+
}
|
|
35
|
+
/** Check if the current position is stalemate. */
|
|
36
|
+
export function isStalemate(board) {
|
|
37
|
+
return loadWasmBoard(getBoardHfen(board)).termination() === 'stalemate';
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/moves/index.ts"],"names":[],"mappings":"AAAA,4CAA4C;AAC5C,oCAAoC;AACpC,yCAAyC;AACzC,iBAAiB;AACjB,+CAA+C;AAI/C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE1D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAY;IAC7C,MAAM,SAAS,GAAG,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACrD,MAAM,GAAG,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;IACpC,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IAC1B,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,SAAS,CAAC,KAAY;IACpC,OAAO,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;AACvD,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,OAAO,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC;AAC1E,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,OAAO,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,WAAW,CAAC;AAC1E,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundler-free browser entry point — for a bare `<script type="module">`
|
|
3
|
+
* import with no build step at all (no webpack/vite/esbuild/etc.).
|
|
4
|
+
*
|
|
5
|
+
* `hyperchess-core`'s main entry point (`index.ts`) works with zero explicit
|
|
6
|
+
* init in Node and in any real bundler (see docs/sdk-plan/WASM-MIGRATION-PLAN.md,
|
|
7
|
+
* Phase 5) — but it statically imports `hyperchess-wasm`, which resolves to
|
|
8
|
+
* the `bundler` wasm-pack target outside Node. That target does a raw
|
|
9
|
+
* `import ... from "./hyperchess_wasm_bg.wasm"`, which only a bundler can handle —
|
|
10
|
+
* loading it directly in a browser fails outright ("Failed to fetch
|
|
11
|
+
* dynamically imported module"), before any application code even runs.
|
|
12
|
+
* So this module deliberately does NOT import `../board/create`,
|
|
13
|
+
* `../moves/index`, etc. (all of which transitively import `wasm/engine.ts`
|
|
14
|
+
* → `hyperchess-wasm`) — it's a self-contained parallel implementation of
|
|
15
|
+
* just the core primitives, backed by the `web` wasm-pack target instead,
|
|
16
|
+
* which needs one explicit async init call and is otherwise inert at import
|
|
17
|
+
* time (safe to statically import from anywhere, including a raw browser).
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* import { initHyperchessCoreStandalone, createBoard } from 'hyperchess-core/standalone';
|
|
21
|
+
* await initHyperchessCoreStandalone();
|
|
22
|
+
* const board = createBoard();
|
|
23
|
+
*
|
|
24
|
+
* Node and bundler-based apps should use the main `hyperchess-core` entry
|
|
25
|
+
* point instead — nothing here is needed there.
|
|
26
|
+
*
|
|
27
|
+
* Scope: only the WASM-backed primitives (board creation/moves/legality),
|
|
28
|
+
* not the HSAN notation or `Game` convenience layer (`io/`, `game/`) — those
|
|
29
|
+
* import from `../moves/index` too and would need the same forking to be
|
|
30
|
+
* no-bundler-safe. Add them here the same way if that's ever needed.
|
|
31
|
+
*/
|
|
32
|
+
import { Board } from './types/board';
|
|
33
|
+
import { Move } from './types/move';
|
|
34
|
+
import { getBoardHfen } from './board/hfen';
|
|
35
|
+
import { undoMove } from './board/undo';
|
|
36
|
+
export { getBoardHfen, undoMove };
|
|
37
|
+
/**
|
|
38
|
+
* Load and initialize the `web` wasm-pack target. Must be called once, and
|
|
39
|
+
* awaited, before any other function in this module is used.
|
|
40
|
+
*
|
|
41
|
+
* `wasmInput` is forwarded to the wasm-pack `web`-target's own default init
|
|
42
|
+
* export, which normally resolves `hyperchess_wasm_bg.wasm` relative to its own
|
|
43
|
+
* module URL and `fetch()`s it — the right default for a real browser. Pass
|
|
44
|
+
* this explicitly (e.g. raw bytes read via `fs.readFileSync`) in contexts
|
|
45
|
+
* where that fetch doesn't work, such as plain Node (its built-in `fetch`
|
|
46
|
+
* doesn't support `file://` URLs) — useful for testing this module without
|
|
47
|
+
* a real browser.
|
|
48
|
+
*/
|
|
49
|
+
export declare function initHyperchessCoreStandalone(wasmInput?: import('hyperchess-wasm/web').InitInput): Promise<void>;
|
|
50
|
+
/** Create a board from HFEN-I notation, or the default starting position. */
|
|
51
|
+
export declare function createBoard(hfen?: string): Board;
|
|
52
|
+
/** Apply a move to the board, returning a new board state. Does NOT validate legality. */
|
|
53
|
+
export declare function applyMove(board: Board, move: Move): Board;
|
|
54
|
+
/** Generate all legal moves for the current position. */
|
|
55
|
+
export declare function generateLegalMoves(board: Board): Move[];
|
|
56
|
+
/** Check if a move is legal (in the set of all legal moves for the position). */
|
|
57
|
+
export declare function isLegalMove(board: Board, move: Move): boolean;
|
|
58
|
+
/** Check if the current player's king is in check. */
|
|
59
|
+
export declare function isInCheck(board: Board): boolean;
|
|
60
|
+
/** Check if the current position is checkmate. */
|
|
61
|
+
export declare function isCheckmate(board: Board): boolean;
|
|
62
|
+
/** Check if the current position is stalemate. */
|
|
63
|
+
export declare function isStalemate(board: Board): boolean;
|
|
64
|
+
//# sourceMappingURL=standalone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"standalone.d.ts","sourceRoot":"","sources":["../src/standalone.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGxC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AAelC;;;;;;;;;;;GAWG;AACH,wBAAsB,4BAA4B,CAChD,SAAS,CAAC,EAAE,OAAO,qBAAqB,EAAE,SAAS,GAClD,OAAO,CAAC,IAAI,CAAC,CAIf;AAyBD,6EAA6E;AAC7E,wBAAgB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAEhD;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,KAAK,CAyBzD;AAED,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,CAKvD;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,GAAG,OAAO,CAE7D;AAED,sDAAsD;AACtD,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAE/C;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAEjD;AAED,kDAAkD;AAClD,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAEjD"}
|