@datamoc/mw_games 0.20.0 → 0.23.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.
Files changed (151) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/dist/audio/Channels.d.ts +19 -0
  3. package/dist/audio/Channels.d.ts.map +1 -1
  4. package/dist/audio/Channels.js +33 -4
  5. package/dist/audio/Channels.js.map +1 -1
  6. package/dist/audio/LoopTags.d.ts +37 -0
  7. package/dist/audio/LoopTags.d.ts.map +1 -0
  8. package/dist/audio/LoopTags.js +116 -0
  9. package/dist/audio/LoopTags.js.map +1 -0
  10. package/dist/audio/Midi.d.ts +29 -0
  11. package/dist/audio/Midi.d.ts.map +1 -1
  12. package/dist/audio/Midi.js +30 -1
  13. package/dist/audio/Midi.js.map +1 -1
  14. package/dist/audio/MidiRender.d.ts +3 -2
  15. package/dist/audio/MidiRender.d.ts.map +1 -1
  16. package/dist/audio/MidiRender.js +2 -2
  17. package/dist/audio/MidiRender.js.map +1 -1
  18. package/dist/audio/humanize/Groove.d.ts +80 -0
  19. package/dist/audio/humanize/Groove.d.ts.map +1 -0
  20. package/dist/audio/humanize/Groove.js +102 -0
  21. package/dist/audio/humanize/Groove.js.map +1 -0
  22. package/dist/audio/humanize/GrooveConverter.d.ts +49 -0
  23. package/dist/audio/humanize/GrooveConverter.d.ts.map +1 -0
  24. package/dist/audio/humanize/GrooveConverter.js +344 -0
  25. package/dist/audio/humanize/GrooveConverter.js.map +1 -0
  26. package/dist/audio/humanize/GrooveExtractor.d.ts +49 -0
  27. package/dist/audio/humanize/GrooveExtractor.d.ts.map +1 -0
  28. package/dist/audio/humanize/GrooveExtractor.js +179 -0
  29. package/dist/audio/humanize/GrooveExtractor.js.map +1 -0
  30. package/dist/audio/humanize/GrooveHumanizer.d.ts +34 -0
  31. package/dist/audio/humanize/GrooveHumanizer.d.ts.map +1 -0
  32. package/dist/audio/humanize/GrooveHumanizer.js +37 -0
  33. package/dist/audio/humanize/GrooveHumanizer.js.map +1 -0
  34. package/dist/audio/humanize/Humanize.d.ts +54 -0
  35. package/dist/audio/humanize/Humanize.d.ts.map +1 -0
  36. package/dist/audio/humanize/Humanize.js +239 -0
  37. package/dist/audio/humanize/Humanize.js.map +1 -0
  38. package/dist/audio/humanize/HumanizerFactory.d.ts +68 -0
  39. package/dist/audio/humanize/HumanizerFactory.d.ts.map +1 -0
  40. package/dist/audio/humanize/HumanizerFactory.js +84 -0
  41. package/dist/audio/humanize/HumanizerFactory.js.map +1 -0
  42. package/dist/audio/humanize/LiteHumanizer.d.ts +30 -0
  43. package/dist/audio/humanize/LiteHumanizer.d.ts.map +1 -0
  44. package/dist/audio/humanize/LiteHumanizer.js +35 -0
  45. package/dist/audio/humanize/LiteHumanizer.js.map +1 -0
  46. package/dist/audio/humanize/Onsets.d.ts +26 -0
  47. package/dist/audio/humanize/Onsets.d.ts.map +1 -0
  48. package/dist/audio/humanize/Onsets.js +164 -0
  49. package/dist/audio/humanize/Onsets.js.map +1 -0
  50. package/dist/audio/index.d.ts +14 -1
  51. package/dist/audio/index.d.ts.map +1 -1
  52. package/dist/audio/index.js +7 -0
  53. package/dist/audio/index.js.map +1 -1
  54. package/dist/board/bitboard.d.ts +132 -0
  55. package/dist/board/bitboard.d.ts.map +1 -0
  56. package/dist/board/bitboard.js +495 -0
  57. package/dist/board/bitboard.js.map +1 -0
  58. package/dist/board/chess.d.ts +16 -0
  59. package/dist/board/chess.d.ts.map +1 -1
  60. package/dist/board/chess.js +43 -0
  61. package/dist/board/chess.js.map +1 -1
  62. package/dist/board/index.d.ts +9 -1
  63. package/dist/board/index.d.ts.map +1 -1
  64. package/dist/board/index.js +5 -1
  65. package/dist/board/index.js.map +1 -1
  66. package/dist/board/openings.d.ts +58 -0
  67. package/dist/board/openings.d.ts.map +1 -0
  68. package/dist/board/openings.js +45 -0
  69. package/dist/board/openings.js.map +1 -0
  70. package/dist/board/tablebase.d.ts +118 -0
  71. package/dist/board/tablebase.d.ts.map +1 -0
  72. package/dist/board/tablebase.js +414 -0
  73. package/dist/board/tablebase.js.map +1 -0
  74. package/dist/board/tourney.d.ts +90 -0
  75. package/dist/board/tourney.d.ts.map +1 -0
  76. package/dist/board/tourney.js +1013 -0
  77. package/dist/board/tourney.js.map +1 -0
  78. package/dist/core/JavaRandom.d.ts +55 -0
  79. package/dist/core/JavaRandom.d.ts.map +1 -0
  80. package/dist/core/JavaRandom.js +81 -0
  81. package/dist/core/JavaRandom.js.map +1 -0
  82. package/dist/core/index.d.ts +2 -0
  83. package/dist/core/index.d.ts.map +1 -1
  84. package/dist/core/index.js +1 -0
  85. package/dist/core/index.js.map +1 -1
  86. package/dist/mw_games.global.js +123 -116
  87. package/dist/rpg/EventRunner.d.ts +7 -0
  88. package/dist/rpg/EventRunner.d.ts.map +1 -1
  89. package/dist/rpg/EventRunner.js +6 -0
  90. package/dist/rpg/EventRunner.js.map +1 -1
  91. package/dist/rpg/MoveRoute.d.ts +35 -4
  92. package/dist/rpg/MoveRoute.d.ts.map +1 -1
  93. package/dist/rpg/MoveRoute.js +40 -11
  94. package/dist/rpg/MoveRoute.js.map +1 -1
  95. package/dist/two-d/render/FogLayer.d.ts +68 -0
  96. package/dist/two-d/render/FogLayer.d.ts.map +1 -0
  97. package/dist/two-d/render/FogLayer.js +83 -0
  98. package/dist/two-d/render/FogLayer.js.map +1 -0
  99. package/dist/two-d/render/LiquidLayer.d.ts +62 -0
  100. package/dist/two-d/render/LiquidLayer.d.ts.map +1 -0
  101. package/dist/two-d/render/LiquidLayer.js +102 -0
  102. package/dist/two-d/render/LiquidLayer.js.map +1 -0
  103. package/dist/two-d/render/RpgmAutotile.d.ts +42 -0
  104. package/dist/two-d/render/RpgmAutotile.d.ts.map +1 -1
  105. package/dist/two-d/render/RpgmAutotile.js +71 -4
  106. package/dist/two-d/render/RpgmAutotile.js.map +1 -1
  107. package/dist/two-d/render/TileMap.d.ts +50 -2
  108. package/dist/two-d/render/TileMap.d.ts.map +1 -1
  109. package/dist/two-d/render/TileMap.js +120 -2
  110. package/dist/two-d/render/TileMap.js.map +1 -1
  111. package/dist/two-d/render/index.d.ts +7 -3
  112. package/dist/two-d/render/index.d.ts.map +1 -1
  113. package/dist/two-d/render/index.js +3 -1
  114. package/dist/two-d/render/index.js.map +1 -1
  115. package/dist/two-d/ui/Label.d.ts.map +1 -1
  116. package/dist/two-d/ui/Label.js +11 -2
  117. package/dist/two-d/ui/Label.js.map +1 -1
  118. package/dist/two-d/ui/ListView.d.ts +24 -0
  119. package/dist/two-d/ui/ListView.d.ts.map +1 -1
  120. package/dist/two-d/ui/ListView.js +97 -4
  121. package/dist/two-d/ui/ListView.js.map +1 -1
  122. package/dist/two-d/ui/MessageLog.d.ts +62 -0
  123. package/dist/two-d/ui/MessageLog.d.ts.map +1 -0
  124. package/dist/two-d/ui/MessageLog.js +114 -0
  125. package/dist/two-d/ui/MessageLog.js.map +1 -0
  126. package/dist/two-d/ui/RadioGroup.d.ts +68 -0
  127. package/dist/two-d/ui/RadioGroup.d.ts.map +1 -0
  128. package/dist/two-d/ui/RadioGroup.js +177 -0
  129. package/dist/two-d/ui/RadioGroup.js.map +1 -0
  130. package/dist/two-d/ui/TextModel.d.ts +26 -1
  131. package/dist/two-d/ui/TextModel.d.ts.map +1 -1
  132. package/dist/two-d/ui/TextModel.js +56 -7
  133. package/dist/two-d/ui/TextModel.js.map +1 -1
  134. package/dist/two-d/ui/TextSharpness.d.ts +33 -0
  135. package/dist/two-d/ui/TextSharpness.d.ts.map +1 -0
  136. package/dist/two-d/ui/TextSharpness.js +56 -0
  137. package/dist/two-d/ui/TextSharpness.js.map +1 -0
  138. package/dist/two-d/ui/index.d.ts +5 -0
  139. package/dist/two-d/ui/index.d.ts.map +1 -1
  140. package/dist/two-d/ui/index.js +3 -0
  141. package/dist/two-d/ui/index.js.map +1 -1
  142. package/dist/version.d.ts +1 -1
  143. package/dist/version.js +1 -1
  144. package/package.json +19 -7
  145. package/sbom.cdx.json +194 -32
  146. package/tools/build-tablebases.d.mts +22 -0
  147. package/tools/build-tablebases.mjs +549 -0
  148. package/tools/compile-openings.d.mts +20 -0
  149. package/tools/compile-openings.mjs +130 -0
  150. package/tools/play-uci.d.mts +26 -0
  151. package/tools/play-uci.mjs +194 -0
@@ -0,0 +1,495 @@
1
+ import { startingChess } from './chess.js';
2
+ const KIND_INDEX = { pawn: 0, knight: 1, bishop: 2, rook: 3, queen: 4, king: 5 };
3
+ const PROMOTION_ORDER = ['queen', 'rook', 'bishop', 'knight'];
4
+ const KNIGHT_STEPS = [
5
+ [1, 2],
6
+ [2, 1],
7
+ [2, -1],
8
+ [1, -2],
9
+ [-1, -2],
10
+ [-2, -1],
11
+ [-2, 1],
12
+ [-1, 2],
13
+ ];
14
+ const KING_STEPS = [
15
+ [1, 0],
16
+ [1, 1],
17
+ [0, 1],
18
+ [-1, 1],
19
+ [-1, 0],
20
+ [-1, -1],
21
+ [0, -1],
22
+ [1, -1],
23
+ ];
24
+ const DIAGONALS = [
25
+ [1, 1],
26
+ [-1, 1],
27
+ [-1, -1],
28
+ [1, -1],
29
+ ];
30
+ const STRAIGHTS = [
31
+ [1, 0],
32
+ [0, 1],
33
+ [-1, 0],
34
+ [0, -1],
35
+ ];
36
+ /** the single bit for a square */
37
+ function bit(square) {
38
+ return 1n << BigInt(square);
39
+ }
40
+ /** exact index of a single-bit board: powers of two survive the trip through Number */
41
+ function bitIndex(single) {
42
+ return Math.log2(Number(single));
43
+ }
44
+ function leaperTable(steps) {
45
+ return Array.from({ length: 64 }, (_, square) => {
46
+ const file = square & 7;
47
+ const rank = square >> 3;
48
+ let attacks = 0n;
49
+ for (const [df, dr] of steps) {
50
+ const f = file + df;
51
+ const r = rank + dr;
52
+ if (f >= 0 && f < 8 && r >= 0 && r < 8)
53
+ attacks |= bit(r * 8 + f);
54
+ }
55
+ return attacks;
56
+ });
57
+ }
58
+ const KNIGHT_TABLE = leaperTable(KNIGHT_STEPS);
59
+ const KING_TABLE = leaperTable(KING_STEPS);
60
+ function occupancyOf(board, colorBase) {
61
+ return (board.pieces[colorBase] |
62
+ board.pieces[colorBase + 1] |
63
+ board.pieces[colorBase + 2] |
64
+ board.pieces[colorBase + 3] |
65
+ board.pieces[colorBase + 4] |
66
+ board.pieces[colorBase + 5]);
67
+ }
68
+ /** piece-board index holding the square, or -1 */
69
+ function squareBoard(board, square) {
70
+ const mask = bit(square);
71
+ for (let i = 0; i < 12; i++) {
72
+ if (board.pieces[i] & mask)
73
+ return i;
74
+ }
75
+ return -1;
76
+ }
77
+ /** true when `byWhite` attacks the square, whatever its own king thinks of the move */
78
+ function isAttacked(board, square, byWhite) {
79
+ const by = byWhite ? 0 : 6;
80
+ const file = square & 7;
81
+ const rank = square >> 3;
82
+ //pawns attack one step diagonally towards the other side
83
+ const pawnRank = byWhite ? rank - 1 : rank + 1;
84
+ for (const df of [-1, 1]) {
85
+ const f = file + df;
86
+ if (pawnRank >= 0 && pawnRank < 8 && f >= 0 && f < 8 && board.pieces[by] & bit(pawnRank * 8 + f))
87
+ return true;
88
+ }
89
+ if (KNIGHT_TABLE[square] & board.pieces[by + 1])
90
+ return true;
91
+ if (KING_TABLE[square] & board.pieces[by + 5])
92
+ return true;
93
+ //sliders see until something stands in the way
94
+ const rays = [
95
+ { steps: DIAGONALS, kinds: [2, 4] },
96
+ { steps: STRAIGHTS, kinds: [3, 4] },
97
+ ];
98
+ for (const { steps, kinds } of rays) {
99
+ for (const [df, dr] of steps) {
100
+ let f = file + df;
101
+ let r = rank + dr;
102
+ while (f >= 0 && f < 8 && r >= 0 && r < 8) {
103
+ const found = squareBoard(board, r * 8 + f);
104
+ if (found !== -1) {
105
+ if (found >= by && found < by + 6 && kinds.includes(found - by))
106
+ return true;
107
+ break;
108
+ }
109
+ f += df;
110
+ r += dr;
111
+ }
112
+ }
113
+ }
114
+ return false;
115
+ }
116
+ function rightBit(side, kingside) {
117
+ return side === 'white' ? (kingside ? 1 : 2) : kingside ? 4 : 8;
118
+ }
119
+ /**
120
+ * Reads a `chess.ts` position onto bitboards: the bridge the differential tests cross
121
+ * in both directions, and the way a FEN reaches the fast board.
122
+ *
123
+ * @example
124
+ * ```ts
125
+ * import { bitboardFromChess, bitboardMoves, startingChess } from '@datamoc/mw_games/board';
126
+ *
127
+ * const moves = bitboardMoves(bitboardFromChess(startingChess()));
128
+ * console.log(moves.length); // 20 - the opening position's own count
129
+ * ```
130
+ */
131
+ export function bitboardFromChess(state) {
132
+ const pieces = new Array(12).fill(0n);
133
+ const kings = [-1, -1];
134
+ state.board.forEach((piece, square) => {
135
+ if (!piece)
136
+ return;
137
+ const index = (piece.side === 'white' ? 0 : 6) + KIND_INDEX[piece.kind];
138
+ pieces[index] |= bit(square);
139
+ if (piece.kind === 'king')
140
+ kings[piece.side === 'white' ? 0 : 1] = square;
141
+ });
142
+ if (kings[0] === -1 || kings[1] === -1)
143
+ throw new Error('a position without both kings cannot go on bitboards');
144
+ return {
145
+ pieces,
146
+ turn: state.turn,
147
+ castling: (state.castling.whiteKingside ? 1 : 0) |
148
+ (state.castling.whiteQueenside ? 2 : 0) |
149
+ (state.castling.blackKingside ? 4 : 0) |
150
+ (state.castling.blackQueenside ? 8 : 0),
151
+ enPassant: state.enPassant,
152
+ halfmove: 0,
153
+ kings,
154
+ };
155
+ }
156
+ /**
157
+ * The standard opening array on bitboards, white to move with every right intact.
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * import { bitboardMoves, startingBitboard } from '@datamoc/mw_games/board';
162
+ *
163
+ * console.log(bitboardMoves(startingBitboard()).length); // 20 - 16 pawn moves, 4 knight moves
164
+ * ```
165
+ */
166
+ export function startingBitboard() {
167
+ return bitboardFromChess(startingChess());
168
+ }
169
+ /**
170
+ * Every legal move for the side to play, in stable square order: pseudo-moves that leave
171
+ * their own king safe, each tried with `makeMove` and taken back with `unmakeMove`.
172
+ * Castling needs its rights, an empty passage and no check on the way over; en passant
173
+ * pins fall out of the make-and-test filter rather than special-casing.
174
+ *
175
+ * @example
176
+ * ```ts
177
+ * import { bitboardMoves, startingBitboard } from '@datamoc/mw_games/board';
178
+ *
179
+ * const moves = bitboardMoves(startingBitboard());
180
+ * console.log(moves.every((move) => move.from >= 0 && move.to < 64)); // true
181
+ * ```
182
+ */
183
+ export function bitboardMoves(board) {
184
+ const white = board.turn === 'white';
185
+ const us = white ? 0 : 6;
186
+ const own = occupancyOf(board, us);
187
+ const enemy = occupancyOf(board, us === 0 ? 6 : 0);
188
+ const all = own | enemy;
189
+ const out = [];
190
+ const pseudo = [];
191
+ for (let from = 0; from < 64; from++) {
192
+ if (!(own & bit(from)))
193
+ continue;
194
+ let kind = -1;
195
+ for (let k = 0; k < 6; k++) {
196
+ if (board.pieces[us + k] & bit(from)) {
197
+ kind = k;
198
+ break;
199
+ }
200
+ }
201
+ pseudo.length = 0;
202
+ pseudoMoves(board, from, kind, all, enemy, pseudo);
203
+ for (const move of pseudo) {
204
+ const undo = makeMove(board, move);
205
+ if (!isAttacked(board, board.kings[white ? 0 : 1], !white))
206
+ out.push({ ...move });
207
+ unmakeMove(board, move, undo);
208
+ }
209
+ }
210
+ return out;
211
+ }
212
+ /** pseudo-moves for the piece on `from`, ignoring its own king; castling checks rights and passage */
213
+ function pseudoMoves(board, from, kind, all, enemy, out) {
214
+ const white = board.turn === 'white';
215
+ const file = from & 7;
216
+ const rank = from >> 3;
217
+ const push = (to, promotion) => {
218
+ out.push(promotion ? { from, to, promotion } : { from, to });
219
+ };
220
+ const slide = (steps) => {
221
+ for (const [df, dr] of steps) {
222
+ let f = file + df;
223
+ let r = rank + dr;
224
+ while (f >= 0 && f < 8 && r >= 0 && r < 8) {
225
+ const to = r * 8 + f;
226
+ const mask = bit(to);
227
+ if (!(all & mask))
228
+ push(to);
229
+ else {
230
+ if (enemy & mask)
231
+ push(to);
232
+ break;
233
+ }
234
+ f += df;
235
+ r += dr;
236
+ }
237
+ }
238
+ };
239
+ switch (kind) {
240
+ case 0: {
241
+ const dir = white ? 8 : -8;
242
+ const home = white ? 1 : 6;
243
+ const last = white ? 7 : 0;
244
+ const one = from + dir;
245
+ if (one >= 0 && one < 64 && !(all & bit(one))) {
246
+ if (one >> 3 === last) {
247
+ for (const promotion of PROMOTION_ORDER)
248
+ push(one, promotion);
249
+ }
250
+ else {
251
+ push(one);
252
+ const two = from + 2 * dir;
253
+ if (rank === home && !(all & bit(two)))
254
+ push(two);
255
+ }
256
+ }
257
+ for (const df of [-1, 1]) {
258
+ const f = file + df;
259
+ if (f < 0 || f > 7)
260
+ continue;
261
+ const to = from + dir + df;
262
+ if (to < 0 || to >= 64)
263
+ continue;
264
+ const mask = bit(to);
265
+ if (enemy & mask) {
266
+ if (to >> 3 === last) {
267
+ for (const promotion of PROMOTION_ORDER)
268
+ push(to, promotion);
269
+ }
270
+ else
271
+ push(to);
272
+ }
273
+ else if (to === board.enPassant)
274
+ push(to);
275
+ }
276
+ break;
277
+ }
278
+ case 1: {
279
+ let targets = KNIGHT_TABLE[from] & ~occupancyOf(board, white ? 0 : 6);
280
+ while (targets) {
281
+ const single = targets & -targets;
282
+ push(bitIndex(single));
283
+ targets ^= single;
284
+ }
285
+ break;
286
+ }
287
+ case 2:
288
+ slide(DIAGONALS);
289
+ break;
290
+ case 3:
291
+ slide(STRAIGHTS);
292
+ break;
293
+ case 4:
294
+ slide(DIAGONALS);
295
+ slide(STRAIGHTS);
296
+ break;
297
+ case 5: {
298
+ let targets = KING_TABLE[from] & ~occupancyOf(board, white ? 0 : 6);
299
+ //never capture the other king: kings are never adjacent after a legal move
300
+ targets &= ~board.pieces[white ? 11 : 5];
301
+ while (targets) {
302
+ const single = targets & -targets;
303
+ push(bitIndex(single));
304
+ targets ^= single;
305
+ }
306
+ const home = white ? 0 : 56;
307
+ const rights = board.castling;
308
+ const kingside = white ? rights & 1 : rights & 4;
309
+ const queenside = white ? rights & 2 : rights & 8;
310
+ if (from === home + 4 && !isAttacked(board, from, !white)) {
311
+ if (kingside &&
312
+ !(all & bit(home + 5)) &&
313
+ !(all & bit(home + 6)) &&
314
+ !isAttacked(board, home + 5, !white) &&
315
+ !isAttacked(board, home + 6, !white)) {
316
+ push(home + 6);
317
+ }
318
+ if (queenside &&
319
+ !(all & bit(home + 3)) &&
320
+ !(all & bit(home + 2)) &&
321
+ !(all & bit(home + 1)) &&
322
+ !isAttacked(board, home + 3, !white) &&
323
+ !isAttacked(board, home + 2, !white)) {
324
+ push(home + 2);
325
+ }
326
+ }
327
+ break;
328
+ }
329
+ }
330
+ }
331
+ /**
332
+ * Plays a move, mutating the position, and returns what `unmakeMove` needs to take it
333
+ * back. Special moves are read off the position rather than flagged on the move: a pawn
334
+ * onto the en passant square captures the pawn behind it, a king stepping two squares
335
+ * swings its rook, a pawn stride of sixteen leaves a square behind it.
336
+ *
337
+ * @example
338
+ * ```ts
339
+ * import { bitboardMoves, makeMove, startingBitboard, unmakeMove } from '@datamoc/mw_games/board';
340
+ *
341
+ * const board = startingBitboard();
342
+ * const move = bitboardMoves(board)[0];
343
+ * const undo = makeMove(board, move);
344
+ * console.log(board.turn); // 'black' - the move is played
345
+ * unmakeMove(board, move, undo);
346
+ * ```
347
+ */
348
+ export function makeMove(board, move) {
349
+ const white = board.turn === 'white';
350
+ const us = white ? 0 : 1;
351
+ const colorBase = us * 6;
352
+ const fromBit = bit(move.from);
353
+ const toBit = bit(move.to);
354
+ let kind = -1;
355
+ for (let k = 0; k < 6; k++) {
356
+ if (board.pieces[colorBase + k] & fromBit) {
357
+ kind = k;
358
+ break;
359
+ }
360
+ }
361
+ if (kind === -1)
362
+ throw new Error(`no piece on ${move.from} to move`);
363
+ const undo = {
364
+ captured: null,
365
+ castling: board.castling,
366
+ enPassant: board.enPassant,
367
+ halfmove: board.halfmove,
368
+ kingSquare: board.kings[us],
369
+ };
370
+ const themBase = (1 - us) * 6;
371
+ const dir = white ? 8 : -8;
372
+ //a pawn onto the en passant square takes the pawn behind it, not the empty square
373
+ let capturedSquare = move.to;
374
+ if (kind === 0 && move.to === board.enPassant)
375
+ capturedSquare = move.to - dir;
376
+ const capturedBit = bit(capturedSquare);
377
+ for (let k = 0; k < 6; k++) {
378
+ if (board.pieces[themBase + k] & capturedBit) {
379
+ undo.captured = { color: (1 - us), kind: k };
380
+ board.pieces[themBase + k] ^= capturedBit;
381
+ break;
382
+ }
383
+ }
384
+ //castling rights die with the king's first step, a rook's, or a captured rook's
385
+ const home = white ? 0 : 56;
386
+ const themHome = white ? 56 : 0;
387
+ if (kind === 5)
388
+ board.castling &= ~(rightBit(board.turn, true) | rightBit(board.turn, false));
389
+ if (kind === 3 && (move.from === home || move.from === home + 7)) {
390
+ board.castling &= ~rightBit(board.turn, move.from === home + 7);
391
+ }
392
+ if (undo.captured?.kind === 3 && (capturedSquare === themHome || capturedSquare === themHome + 7)) {
393
+ board.castling &= ~rightBit(white ? 'black' : 'white', capturedSquare === themHome + 7);
394
+ }
395
+ board.pieces[colorBase + kind] ^= fromBit;
396
+ if (move.promotion)
397
+ board.pieces[colorBase + KIND_INDEX[move.promotion]] |= toBit;
398
+ else
399
+ board.pieces[colorBase + kind] |= toBit;
400
+ if (kind === 5 && Math.abs(move.to - move.from) === 2) {
401
+ const rook = colorBase + 3;
402
+ if (move.to > move.from)
403
+ board.pieces[rook] ^= bit(home + 7) | bit(home + 5);
404
+ else
405
+ board.pieces[rook] ^= bit(home) | bit(home + 3);
406
+ }
407
+ board.enPassant = kind === 0 && Math.abs(move.to - move.from) === 16 ? (move.from + move.to) / 2 : null;
408
+ board.halfmove = kind === 0 || undo.captured ? 0 : board.halfmove + 1;
409
+ if (kind === 5)
410
+ board.kings[us] = move.to;
411
+ board.turn = white ? 'black' : 'white';
412
+ return undo;
413
+ }
414
+ /**
415
+ * Takes back exactly what `makeMove` played: the mover returns, the taken piece (or the
416
+ * en passant pawn behind the landing square) is restored, and rights, en passant
417
+ * square, halfmove clock and king square come back from the undo.
418
+ *
419
+ * @example
420
+ * ```ts
421
+ * import { bitboardMoves, makeMove, startingBitboard, unmakeMove } from '@datamoc/mw_games/board';
422
+ *
423
+ * const board = startingBitboard();
424
+ * const move = bitboardMoves(board)[0];
425
+ * const undo = makeMove(board, move);
426
+ * unmakeMove(board, move, undo);
427
+ * console.log(board.turn, bitboardMoves(board).length); // 'white' 20 - taken back whole
428
+ * ```
429
+ */
430
+ export function unmakeMove(board, move, undo) {
431
+ board.turn = board.turn === 'white' ? 'black' : 'white';
432
+ const white = board.turn === 'white';
433
+ const us = white ? 0 : 1;
434
+ const colorBase = us * 6;
435
+ const toBit = bit(move.to);
436
+ //a promotion leaves a pawn to restore, anything else the piece standing on `to`
437
+ const kind = move.promotion
438
+ ? 0
439
+ : (() => {
440
+ for (let k = 0; k < 6; k++) {
441
+ if (board.pieces[colorBase + k] & toBit)
442
+ return k;
443
+ }
444
+ throw new Error(`nothing on ${move.to} to take back`);
445
+ })();
446
+ if (move.promotion)
447
+ board.pieces[colorBase + KIND_INDEX[move.promotion]] ^= toBit;
448
+ else
449
+ board.pieces[colorBase + kind] ^= toBit;
450
+ board.pieces[colorBase + kind] |= bit(move.from);
451
+ if (kind === 5 && Math.abs(move.to - move.from) === 2) {
452
+ const home = white ? 0 : 56;
453
+ const rook = colorBase + 3;
454
+ if (move.to > move.from)
455
+ board.pieces[rook] ^= bit(home + 7) | bit(home + 5);
456
+ else
457
+ board.pieces[rook] ^= bit(home) | bit(home + 3);
458
+ }
459
+ if (undo.captured) {
460
+ const dir = white ? 8 : -8;
461
+ const square = kind === 0 && move.to === undo.enPassant ? move.to - dir : move.to;
462
+ board.pieces[(1 - us) * 6 + undo.captured.kind] |= bit(square);
463
+ }
464
+ board.castling = undo.castling;
465
+ board.enPassant = undo.enPassant;
466
+ board.halfmove = undo.halfmove;
467
+ board.kings[us] = undo.kingSquare;
468
+ }
469
+ /**
470
+ * Move-generation node count: 1 at depth 0, else the sum over every legal move. The
471
+ * position is played and taken back as it goes, so it reads identical afterwards.
472
+ * Counts match the published perft numbers, which is the whole point: a wrong move
473
+ * generator cannot hide from them.
474
+ *
475
+ * @example
476
+ * ```ts
477
+ * import { perft, startingBitboard } from '@datamoc/mw_games/board';
478
+ *
479
+ * console.log(perft(startingBitboard(), 2)); // 400 - the opening's two-ply count
480
+ * ```
481
+ */
482
+ export function perft(board, depth) {
483
+ if (!Number.isInteger(depth) || depth < 0)
484
+ throw new RangeError('perft depth must be a non-negative integer');
485
+ if (depth === 0)
486
+ return 1;
487
+ let nodes = 0;
488
+ for (const move of bitboardMoves(board)) {
489
+ const undo = makeMove(board, move);
490
+ nodes += perft(board, depth - 1);
491
+ unmakeMove(board, move, undo);
492
+ }
493
+ return nodes;
494
+ }
495
+ //# sourceMappingURL=bitboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bitboard.js","sourceRoot":"","sources":["../../src/board/bitboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAuE,MAAM,YAAY,CAAC;AA6ChH,MAAM,UAAU,GAA8B,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC5G,MAAM,eAAe,GAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AAE/E,MAAM,YAAY,GAA6C;IAC9D,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACR,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACR,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CACP,CAAC;AACF,MAAM,UAAU,GAA6C;IAC5D,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACR,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACP,CAAC;AACF,MAAM,SAAS,GAA6C;IAC3D,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACR,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACP,CAAC;AACF,MAAM,SAAS,GAA6C;IAC3D,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,EAAE,CAAC,CAAC;IACN,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACP,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACP,CAAC;AAEF,kCAAkC;AAClC,SAAS,GAAG,CAAC,MAAc;IAC1B,OAAO,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAED,uFAAuF;AACvF,SAAS,QAAQ,CAAC,MAAc;IAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,WAAW,CAAC,KAA+C;IACnE,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC;QACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC;QACzB,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YACpB,MAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,CAAC,CAAC;AAC/C,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;AAE3C,SAAS,WAAW,CAAC,KAAoB,EAAE,SAAiB;IAC3D,OAAO,CACN,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC;QACvB,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;QAC3B,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;QAC3B,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;QAC3B,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;QAC3B,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,CAC3B,CAAC;AACH,CAAC;AAED,kDAAkD;AAClD,SAAS,WAAW,CAAC,KAAoB,EAAE,MAAc;IACxD,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI;YAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACX,CAAC;AAED,uFAAuF;AACvF,SAAS,UAAU,CAAC,KAAoB,EAAE,MAAc,EAAE,OAAgB;IACzE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,CAAC;IACzB,yDAAyD;IACzD,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IAC/C,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;QACpB,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,QAAQ,GAAG,CAAC,GAAG,CAAC,CAAC;YAAE,OAAO,IAAI,CAAC;IAC/G,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7D,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,+CAA+C;IAC/C,MAAM,IAAI,GAAgF;QACzF,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;QACnC,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE;KACnC,CAAC;IACF,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC;QACrC,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YAClB,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5C,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;oBAClB,IAAI,KAAK,IAAI,EAAE,IAAI,KAAK,GAAG,EAAE,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,GAAG,EAAE,CAAC;wBAAE,OAAO,IAAI,CAAC;oBAC7E,MAAM;gBACP,CAAC;gBACD,CAAC,IAAI,EAAE,CAAC;gBACR,CAAC,IAAI,EAAE,CAAC;YACT,CAAC;QACF,CAAC;IACF,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,IAAe,EAAE,QAAiB;IACnD,OAAO,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAiB;IAClD,MAAM,MAAM,GAAG,IAAI,KAAK,CAAS,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAqB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;IAChH,OAAO;QACN,MAAM;QACN,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EACP,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvC,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtC,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,CAAC;QACX,KAAK;KACL,CAAC;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB;IAC/B,OAAO,iBAAiB,CAAC,aAAa,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAAC,KAAoB;IACjD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;IACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,GAAG,GAAG,KAAK,CAAC;IACxB,MAAM,GAAG,GAAmB,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAmB,EAAE,CAAC;IAClC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC;YAAE,SAAS;QACjC,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,IAAI,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtC,IAAI,GAAG,CAAC,CAAC;gBACT,MAAM;YACP,CAAC;QACF,CAAC;QACD,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAClB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QACnD,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACnC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;YAClF,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QAC/B,CAAC;IACF,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,sGAAsG;AACtG,SAAS,WAAW,CACnB,KAAoB,EACpB,IAAY,EACZ,IAAY,EACZ,GAAW,EACX,KAAa,EACb,GAAmB;IAEnB,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC;IACtB,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IACvB,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,SAAyB,EAAQ,EAAE;QAC5D,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,KAA+C,EAAQ,EAAE;QACvE,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YAClB,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3C,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACrB,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;gBACrB,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC;oBAAE,IAAI,CAAC,EAAE,CAAC,CAAC;qBACvB,CAAC;oBACL,IAAI,KAAK,GAAG,IAAI;wBAAE,IAAI,CAAC,EAAE,CAAC,CAAC;oBAC3B,MAAM;gBACP,CAAC;gBACD,CAAC,IAAI,EAAE,CAAC;gBACR,CAAC,IAAI,EAAE,CAAC;YACT,CAAC;QACF,CAAC;IACF,CAAC,CAAC;IACF,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,CAAC,EAAE,CAAC;YACR,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,GAAG,CAAC;YACvB,IAAI,GAAG,IAAI,CAAC,IAAI,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;gBAC/C,IAAI,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;oBACvB,KAAK,MAAM,SAAS,IAAI,eAAe;wBAAE,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;gBAC/D,CAAC;qBAAM,CAAC;oBACP,IAAI,CAAC,GAAG,CAAC,CAAC;oBACV,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC;oBAC3B,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;wBAAE,IAAI,CAAC,GAAG,CAAC,CAAC;gBACnD,CAAC;YACF,CAAC;YACD,KAAK,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;gBAC1B,MAAM,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;gBACpB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;oBAAE,SAAS;gBAC7B,MAAM,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;gBAC3B,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE;oBAAE,SAAS;gBACjC,MAAM,IAAI,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;gBACrB,IAAI,KAAK,GAAG,IAAI,EAAE,CAAC;oBAClB,IAAI,EAAE,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;wBACtB,KAAK,MAAM,SAAS,IAAI,eAAe;4BAAE,IAAI,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;oBAC9D,CAAC;;wBAAM,IAAI,CAAC,EAAE,CAAC,CAAC;gBACjB,CAAC;qBAAM,IAAI,EAAE,KAAK,KAAK,CAAC,SAAS;oBAAE,IAAI,CAAC,EAAE,CAAC,CAAC;YAC7C,CAAC;YACD,MAAM;QACP,CAAC;QACD,KAAK,CAAC,EAAE,CAAC;YACR,IAAI,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtE,OAAO,OAAO,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,OAAO,CAAC;gBAClC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;gBACvB,OAAO,IAAI,MAAM,CAAC;YACnB,CAAC;YACD,MAAM;QACP,CAAC;QACD,KAAK,CAAC;YACL,KAAK,CAAC,SAAS,CAAC,CAAC;YACjB,MAAM;QACP,KAAK,CAAC;YACL,KAAK,CAAC,SAAS,CAAC,CAAC;YACjB,MAAM;QACP,KAAK,CAAC;YACL,KAAK,CAAC,SAAS,CAAC,CAAC;YACjB,KAAK,CAAC,SAAS,CAAC,CAAC;YACjB,MAAM;QACP,KAAK,CAAC,EAAE,CAAC;YACR,IAAI,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACpE,2EAA2E;YAC3E,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACzC,OAAO,OAAO,EAAE,CAAC;gBAChB,MAAM,MAAM,GAAG,OAAO,GAAG,CAAC,OAAO,CAAC;gBAClC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;gBACvB,OAAO,IAAI,MAAM,CAAC;YACnB,CAAC;YACD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC;YAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YACjD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YAClD,IAAI,IAAI,KAAK,IAAI,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3D,IACC,QAAQ;oBACR,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;oBACtB,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;oBACtB,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC;oBACpC,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EACnC,CAAC;oBACF,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;gBAChB,CAAC;gBACD,IACC,SAAS;oBACT,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;oBACtB,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;oBACtB,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;oBACtB,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC;oBACpC,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EACnC,CAAC;oBACF,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;gBAChB,CAAC;YACF,CAAC;YACD,MAAM;QACP,CAAC;IACF,CAAC;AACF,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAoB,EAAE,IAAkB;IAChE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;IACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;IACzB,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3B,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC;YAC3C,IAAI,GAAG,CAAC,CAAC;YACT,MAAM;QACP,CAAC;IACF,CAAC;IACD,IAAI,IAAI,KAAK,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,eAAe,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC;IACrE,MAAM,IAAI,GAAiB;QAC1B,QAAQ,EAAE,IAAI;QACd,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;KAC3B,CAAC;IACF,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,kFAAkF;IAClF,IAAI,cAAc,GAAG,IAAI,CAAC,EAAE,CAAC;IAC7B,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,KAAK,CAAC,SAAS;QAAE,cAAc,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC;IAC9E,MAAM,WAAW,GAAG,GAAG,CAAC,cAAc,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,CAAC;YAC9C,IAAI,CAAC,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,CAAU,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;YACtD,KAAK,CAAC,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,IAAI,WAAW,CAAC;YAC1C,MAAM;QACP,CAAC;IACF,CAAC;IACD,gFAAgF;IAChF,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,IAAI,KAAK,CAAC;QAAE,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9F,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QAClE,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC;IACjE,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,QAAQ,IAAI,cAAc,KAAK,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC;QACnG,KAAK,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,cAAc,KAAK,QAAQ,GAAG,CAAC,CAAC,CAAC;IACzF,CAAC;IACD,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,OAAO,CAAC;IAC1C,IAAI,IAAI,CAAC,SAAS;QAAE,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,CAAC;;QAC7E,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC;IAC7C,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI;YAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;;YACxE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,KAAK,CAAC,SAAS,GAAG,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxG,KAAK,CAAC,QAAQ,GAAG,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;IACtE,IAAI,IAAI,KAAK,CAAC;QAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;IAC1C,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACvC,OAAO,IAAI,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,UAAU,CAAC,KAAoB,EAAE,IAAkB,EAAE,IAAkB;IACtF,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;IACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzB,MAAM,SAAS,GAAG,EAAE,GAAG,CAAC,CAAC;IACzB,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3B,gFAAgF;IAChF,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS;QAC1B,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,CAAC,GAAG,EAAE;YACN,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,KAAK;oBAAE,OAAO,CAAC,CAAC;YACnD,CAAC;YACD,MAAM,IAAI,KAAK,CAAC,cAAc,IAAI,CAAC,EAAE,eAAe,CAAC,CAAC;QACvD,CAAC,CAAC,EAAE,CAAC;IACP,IAAI,IAAI,CAAC,SAAS;QAAE,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,KAAK,CAAC;;QAC7E,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC;IAC7C,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjD,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACvD,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC;QAC3B,IAAI,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,IAAI;YAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;;YACxE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACtD,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;QAClF,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAChE,CAAC;IACD,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACjC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,KAAK,CAAC,KAAoB,EAAE,KAAa;IACxD,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,4CAA4C,CAAC,CAAC;IAC9G,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC1B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACnC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;QACjC,UAAU,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -61,6 +61,22 @@ export declare function sq(name: string): ChessSquare;
61
61
  * ```
62
62
  */
63
63
  export declare function squareName(sq: ChessSquare): string;
64
+ /**
65
+ * The position half of FEN: placement, side to move, castling rights and en passant
66
+ * square, without either move clock. Two positions share a key exactly when the same
67
+ * moves are legal from both, which is what makes it the lookup key for an opening
68
+ * book (`board/openings.ts` builds and probes keys with this function on both sides,
69
+ * so the en passant square is taken as stored rather than re-derived).
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * import { positionKey, startingChess } from '@datamoc/mw_games/board';
74
+ *
75
+ * console.log(positionKey(startingChess()));
76
+ * // 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -'
77
+ * ```
78
+ */
79
+ export declare function positionKey(state: ChessState): string;
64
80
  /**
65
81
  * Reads a position in Forsyth-Edwards Notation - the shape puzzles come in.
66
82
  *
@@ -1 +1 @@
1
- {"version":3,"file":"chess.d.ts","sourceRoot":"","sources":["../../src/board/chess.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAC1C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjF,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;CAChB;AAED,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,uEAAuE;IACvE,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;AAEhF;;;;;;;;;;;GAWG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAO5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAqDhD;AAkBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAe1C;AAED,mEAAmE;AACnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAOxD;AA6FD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAEnE;AA+LD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,CAYzD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAelE;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAIzD"}
1
+ {"version":3,"file":"chess.d.ts","sourceRoot":"","sources":["../../src/board/chess.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAC;AAC1C,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjF,MAAM,WAAW,UAAU;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,SAAS,CAAC;CAChB;AAED,0DAA0D;AAC1D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnE,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,WAAW,CAAC;IAClB,EAAE,EAAE,WAAW,CAAC;IAChB,SAAS,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC7B,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,cAAc,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IAC1B,KAAK,EAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,uEAAuE;IACvE,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,YAAY,GAAG,WAAW,CAAC;AAEhF;;;;;;;;;;;GAWG;AACH,wBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAO5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CA2BrD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAqDhD;AAkBD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,UAAU,CAe1C;AAED,mEAAmE;AACnE;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU,CAOxD;AA6FD;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CAEnE;AA+LD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,EAAE,CAYzD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,CAelE;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,WAAW,CAIzD"}
@@ -42,6 +42,49 @@ export function sq(name) {
42
42
  export function squareName(sq) {
43
43
  return String.fromCharCode(97 + (sq & 7)) + String.fromCharCode(49 + (sq >> 3));
44
44
  }
45
+ /**
46
+ * The position half of FEN: placement, side to move, castling rights and en passant
47
+ * square, without either move clock. Two positions share a key exactly when the same
48
+ * moves are legal from both, which is what makes it the lookup key for an opening
49
+ * book (`board/openings.ts` builds and probes keys with this function on both sides,
50
+ * so the en passant square is taken as stored rather than re-derived).
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * import { positionKey, startingChess } from '@datamoc/mw_games/board';
55
+ *
56
+ * console.log(positionKey(startingChess()));
57
+ * // 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -'
58
+ * ```
59
+ */
60
+ export function positionKey(state) {
61
+ const rows = [];
62
+ for (let rank = 7; rank >= 0; rank--) {
63
+ let row = '';
64
+ let empty = 0;
65
+ for (let file = 0; file < 8; file++) {
66
+ const piece = state.board[rank * 8 + file];
67
+ if (!piece) {
68
+ empty++;
69
+ continue;
70
+ }
71
+ if (empty > 0) {
72
+ row += String(empty);
73
+ empty = 0;
74
+ }
75
+ const letter = { pawn: 'p', knight: 'n', bishop: 'b', rook: 'r', queen: 'q', king: 'k' }[piece.kind];
76
+ row += piece.side === 'white' ? letter.toUpperCase() : letter;
77
+ }
78
+ if (empty > 0)
79
+ row += String(empty);
80
+ rows.push(row);
81
+ }
82
+ const rights = (state.castling.whiteKingside ? 'K' : '') +
83
+ (state.castling.whiteQueenside ? 'Q' : '') +
84
+ (state.castling.blackKingside ? 'k' : '') +
85
+ (state.castling.blackQueenside ? 'q' : '');
86
+ return `${rows.join('/')} ${state.turn === 'white' ? 'w' : 'b'} ${rights || '-'} ${state.enPassant === null ? '-' : squareName(state.enPassant)}`;
87
+ }
45
88
  /**
46
89
  * Reads a position in Forsyth-Edwards Notation - the shape puzzles come in.
47
90
  *