@ankhorage/zora 25.11.1 → 26.0.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 (82) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +1 -4
  3. package/dist/capabilities/index.js +65 -41
  4. package/dist/capabilities/index.js.map +3 -3
  5. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts +1 -1
  6. package/dist/features/chess/adapters/inbound/ChessBoard.d.ts.map +1 -1
  7. package/dist/features/chess/adapters/inbound/ChessBoard.js +130 -83
  8. package/dist/features/chess/adapters/inbound/ChessBoard.js.map +1 -1
  9. package/dist/features/chess/meta.d.ts +97 -72
  10. package/dist/features/chess/meta.d.ts.map +1 -1
  11. package/dist/features/chess/meta.js +64 -40
  12. package/dist/features/chess/meta.js.map +1 -1
  13. package/dist/features/chess/public.d.ts +1 -7
  14. package/dist/features/chess/public.d.ts.map +1 -1
  15. package/dist/features/chess/public.js +0 -6
  16. package/dist/features/chess/public.js.map +1 -1
  17. package/dist/features/chess/utils/createChessBoardCellPressHandler.d.ts +6 -0
  18. package/dist/features/chess/utils/createChessBoardCellPressHandler.d.ts.map +1 -0
  19. package/dist/features/chess/utils/createChessBoardCellPressHandler.js +17 -0
  20. package/dist/features/chess/utils/createChessBoardCellPressHandler.js.map +1 -0
  21. package/dist/features/chess/utils/createChessBoardCells.d.ts +12 -0
  22. package/dist/features/chess/utils/createChessBoardCells.d.ts.map +1 -0
  23. package/dist/features/chess/utils/createChessBoardCells.js +28 -0
  24. package/dist/features/chess/utils/createChessBoardCells.js.map +1 -0
  25. package/dist/readerFree.d.ts +2 -2
  26. package/dist/readerFree.d.ts.map +1 -1
  27. package/dist/readerFree.js +1 -1
  28. package/dist/readerFree.js.map +1 -1
  29. package/dist/types/authoring.d.ts +2 -1
  30. package/dist/types/authoring.d.ts.map +1 -1
  31. package/dist/types/authoring.js.map +1 -1
  32. package/dist/types/chess.d.ts +27 -20
  33. package/dist/types/chess.d.ts.map +1 -1
  34. package/dist/types/chess.js.map +1 -1
  35. package/package.json +31 -92
  36. package/src/features/chess/adapters/inbound/ChessBoard.tsx +263 -112
  37. package/src/features/chess/meta.ts +64 -40
  38. package/src/features/chess/public.test.tsx +77 -228
  39. package/src/features/chess/public.ts +2 -9
  40. package/src/features/chess/utils/createChessBoardCellPressHandler.ts +30 -0
  41. package/src/features/chess/utils/createChessBoardCells.ts +54 -0
  42. package/src/features/chessTabletopOwnership.test.ts +3 -7
  43. package/src/features/registry/componentMeta.test.ts +12 -1
  44. package/src/readerFree.ts +3 -15
  45. package/src/types/authoring.ts +2 -1
  46. package/src/types/chess.ts +28 -21
  47. package/web-dist/chunks/Accordion-91sjb3zh.js +453 -0
  48. package/web-dist/components/chess-board/ChessBoard.js +2 -1
  49. package/web-dist/components/opening-book/OpeningBook.js +2 -1
  50. package/web-dist/manifest.json +8 -4
  51. package/dist/features/chess/utils/chessEngine.d.ts +0 -8
  52. package/dist/features/chess/utils/chessEngine.d.ts.map +0 -1
  53. package/dist/features/chess/utils/chessEngine.js +0 -71
  54. package/dist/features/chess/utils/chessEngine.js.map +0 -1
  55. package/dist/features/chess/utils/chessSquares.d.ts +0 -4
  56. package/dist/features/chess/utils/chessSquares.d.ts.map +0 -1
  57. package/dist/features/chess/utils/chessSquares.js +0 -3
  58. package/dist/features/chess/utils/chessSquares.js.map +0 -1
  59. package/dist/features/chess/utils/createBoardSquares.d.ts +0 -4
  60. package/dist/features/chess/utils/createBoardSquares.d.ts.map +0 -1
  61. package/dist/features/chess/utils/createBoardSquares.js +0 -9
  62. package/dist/features/chess/utils/createBoardSquares.js.map +0 -1
  63. package/dist/features/chess/utils/getSquareFile.d.ts +0 -4
  64. package/dist/features/chess/utils/getSquareFile.d.ts.map +0 -1
  65. package/dist/features/chess/utils/getSquareFile.js +0 -5
  66. package/dist/features/chess/utils/getSquareFile.js.map +0 -1
  67. package/dist/features/chess/utils/getSquareRank.d.ts +0 -4
  68. package/dist/features/chess/utils/getSquareRank.d.ts.map +0 -1
  69. package/dist/features/chess/utils/getSquareRank.js +0 -5
  70. package/dist/features/chess/utils/getSquareRank.js.map +0 -1
  71. package/dist/features/chess/utils/isLightSquare.d.ts +0 -4
  72. package/dist/features/chess/utils/isLightSquare.d.ts.map +0 -1
  73. package/dist/features/chess/utils/isLightSquare.js +0 -6
  74. package/dist/features/chess/utils/isLightSquare.js.map +0 -1
  75. package/src/features/chess/utils/chessEngine.test.ts +0 -35
  76. package/src/features/chess/utils/chessEngine.ts +0 -83
  77. package/src/features/chess/utils/chessSquares.ts +0 -6
  78. package/src/features/chess/utils/createBoardSquares.ts +0 -13
  79. package/src/features/chess/utils/getSquareFile.ts +0 -6
  80. package/src/features/chess/utils/getSquareRank.ts +0 -6
  81. package/src/features/chess/utils/isLightSquare.ts +0 -8
  82. package/web-dist/chunks/Accordion-xcm1qc39.js +0 -3813
@@ -1,3813 +0,0 @@
1
- 'use client';
2
- import {
3
- withZoraThemeScope
4
- } from "./Accordion-vj1m2wck.js";
5
- import {
6
- useZoraTheme2
7
- } from "./Accordion-srjya6dz.js";
8
- import {
9
- require_cjs
10
- } from "./Accordion-xgpzh4wq.js";
11
- import {
12
- __toESM
13
- } from "./Accordion-nh0cs9hq.js";
14
-
15
- // src/features/chess/adapters/inbound/ChessBoard.tsx
16
- var import_react_native = __toESM(require_cjs(), 1);
17
-
18
- // node_modules/chess.js/dist/esm/chess.js
19
- function rootNode(comment) {
20
- return comment !== null ? { comment, variations: [] } : { variations: [] };
21
- }
22
- function node(move, suffix, nag, comment, variations) {
23
- const node = { move, variations };
24
- if (suffix) {
25
- node.suffix = suffix;
26
- }
27
- if (nag) {
28
- node.nag = nag;
29
- }
30
- if (comment !== null) {
31
- node.comment = comment;
32
- }
33
- return node;
34
- }
35
- function lineToTree(...nodes) {
36
- const [root, ...rest] = nodes;
37
- let parent = root;
38
- for (const child of rest) {
39
- if (child !== null) {
40
- parent.variations = [child, ...child.variations];
41
- child.variations = [];
42
- parent = child;
43
- }
44
- }
45
- return root;
46
- }
47
- function pgn(headers, game) {
48
- if (game.marker && game.marker.comment) {
49
- let node = game.root;
50
- while (true) {
51
- const next = node.variations[0];
52
- if (!next) {
53
- node.comment = game.marker.comment;
54
- break;
55
- }
56
- node = next;
57
- }
58
- }
59
- return {
60
- headers,
61
- root: game.root,
62
- result: (game.marker && game.marker.result) ?? undefined
63
- };
64
- }
65
- function peg$subclass(child, parent) {
66
- function C() {
67
- this.constructor = child;
68
- }
69
- C.prototype = parent.prototype;
70
- child.prototype = new C;
71
- }
72
- function peg$SyntaxError(message, expected, found, location) {
73
- var self = Error.call(this, message);
74
- if (Object.setPrototypeOf) {
75
- Object.setPrototypeOf(self, peg$SyntaxError.prototype);
76
- }
77
- self.expected = expected;
78
- self.found = found;
79
- self.location = location;
80
- self.name = "SyntaxError";
81
- return self;
82
- }
83
- peg$subclass(peg$SyntaxError, Error);
84
- function peg$padEnd(str, targetLength, padString) {
85
- padString = padString || " ";
86
- if (str.length > targetLength) {
87
- return str;
88
- }
89
- targetLength -= str.length;
90
- padString += padString.repeat(targetLength);
91
- return str + padString.slice(0, targetLength);
92
- }
93
- peg$SyntaxError.prototype.format = function(sources) {
94
- var str = "Error: " + this.message;
95
- if (this.location) {
96
- var src = null;
97
- var k;
98
- for (k = 0;k < sources.length; k++) {
99
- if (sources[k].source === this.location.source) {
100
- src = sources[k].text.split(/\r\n|\n|\r/g);
101
- break;
102
- }
103
- }
104
- var s = this.location.start;
105
- var offset_s = this.location.source && typeof this.location.source.offset === "function" ? this.location.source.offset(s) : s;
106
- var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column;
107
- if (src) {
108
- var e = this.location.end;
109
- var filler = peg$padEnd("", offset_s.line.toString().length, " ");
110
- var line = src[s.line - 1];
111
- var last = s.line === e.line ? e.column : line.length + 1;
112
- var hatLen = last - s.column || 1;
113
- str += `
114
- --> ` + loc + `
115
- ` + filler + ` |
116
- ` + offset_s.line + " | " + line + `
117
- ` + filler + " | " + peg$padEnd("", s.column - 1, " ") + peg$padEnd("", hatLen, "^");
118
- } else {
119
- str += `
120
- at ` + loc;
121
- }
122
- }
123
- return str;
124
- };
125
- peg$SyntaxError.buildMessage = function(expected, found) {
126
- var DESCRIBE_EXPECTATION_FNS = {
127
- literal: function(expectation) {
128
- return '"' + literalEscape(expectation.text) + '"';
129
- },
130
- class: function(expectation) {
131
- var escapedParts = expectation.parts.map(function(part) {
132
- return Array.isArray(part) ? classEscape(part[0]) + "-" + classEscape(part[1]) : classEscape(part);
133
- });
134
- return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]";
135
- },
136
- any: function() {
137
- return "any character";
138
- },
139
- end: function() {
140
- return "end of input";
141
- },
142
- other: function(expectation) {
143
- return expectation.description;
144
- }
145
- };
146
- function hex(ch) {
147
- return ch.charCodeAt(0).toString(16).toUpperCase();
148
- }
149
- function literalEscape(s) {
150
- return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
151
- return "\\x0" + hex(ch);
152
- }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
153
- return "\\x" + hex(ch);
154
- });
155
- }
156
- function classEscape(s) {
157
- return s.replace(/\\/g, "\\\\").replace(/\]/g, "\\]").replace(/\^/g, "\\^").replace(/-/g, "\\-").replace(/\0/g, "\\0").replace(/\t/g, "\\t").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/[\x00-\x0F]/g, function(ch) {
158
- return "\\x0" + hex(ch);
159
- }).replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) {
160
- return "\\x" + hex(ch);
161
- });
162
- }
163
- function describeExpectation(expectation) {
164
- return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation);
165
- }
166
- function describeExpected(expected) {
167
- var descriptions = expected.map(describeExpectation);
168
- var i, j;
169
- descriptions.sort();
170
- if (descriptions.length > 0) {
171
- for (i = 1, j = 1;i < descriptions.length; i++) {
172
- if (descriptions[i - 1] !== descriptions[i]) {
173
- descriptions[j] = descriptions[i];
174
- j++;
175
- }
176
- }
177
- descriptions.length = j;
178
- }
179
- switch (descriptions.length) {
180
- case 1:
181
- return descriptions[0];
182
- case 2:
183
- return descriptions[0] + " or " + descriptions[1];
184
- default:
185
- return descriptions.slice(0, -1).join(", ") + ", or " + descriptions[descriptions.length - 1];
186
- }
187
- }
188
- function describeFound(found) {
189
- return found ? '"' + literalEscape(found) + '"' : "end of input";
190
- }
191
- return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found.";
192
- };
193
- function peg$parse(input, options) {
194
- options = options !== undefined ? options : {};
195
- var peg$FAILED = {};
196
- var peg$source = options.grammarSource;
197
- var peg$startRuleFunctions = { pgn: peg$parsepgn };
198
- var peg$startRuleFunction = peg$parsepgn;
199
- var peg$c0 = "[";
200
- var peg$c1 = '"';
201
- var peg$c2 = "]";
202
- var peg$c3 = ".";
203
- var peg$c4 = "O-O-O";
204
- var peg$c5 = "O-O";
205
- var peg$c6 = "0-0-0";
206
- var peg$c7 = "0-0";
207
- var peg$c8 = "$";
208
- var peg$c9 = "{";
209
- var peg$c10 = "}";
210
- var peg$c11 = ";";
211
- var peg$c12 = "(";
212
- var peg$c13 = ")";
213
- var peg$c14 = "1-0";
214
- var peg$c15 = "0-1";
215
- var peg$c16 = "1/2-1/2";
216
- var peg$c17 = "*";
217
- var peg$r0 = /^[a-zA-Z]/;
218
- var peg$r1 = /^[^"]/;
219
- var peg$r2 = /^[0-9]/;
220
- var peg$r3 = /^[.]/;
221
- var peg$r4 = /^[a-zA-Z1-8\-=]/;
222
- var peg$r5 = /^[+#]/;
223
- var peg$r6 = /^[!?]/;
224
- var peg$r7 = /^[^}]/;
225
- var peg$r8 = /^[^\r\n]/;
226
- var peg$r9 = /^[ \t\r\n]/;
227
- var peg$e0 = peg$otherExpectation("tag pair");
228
- var peg$e1 = peg$literalExpectation("[", false);
229
- var peg$e2 = peg$literalExpectation('"', false);
230
- var peg$e3 = peg$literalExpectation("]", false);
231
- var peg$e4 = peg$otherExpectation("tag name");
232
- var peg$e5 = peg$classExpectation([["a", "z"], ["A", "Z"]], false, false);
233
- var peg$e6 = peg$otherExpectation("tag value");
234
- var peg$e7 = peg$classExpectation(['"'], true, false);
235
- var peg$e8 = peg$otherExpectation("move number");
236
- var peg$e9 = peg$classExpectation([["0", "9"]], false, false);
237
- var peg$e10 = peg$literalExpectation(".", false);
238
- var peg$e11 = peg$classExpectation(["."], false, false);
239
- var peg$e12 = peg$otherExpectation("standard algebraic notation");
240
- var peg$e13 = peg$literalExpectation("O-O-O", false);
241
- var peg$e14 = peg$literalExpectation("O-O", false);
242
- var peg$e15 = peg$literalExpectation("0-0-0", false);
243
- var peg$e16 = peg$literalExpectation("0-0", false);
244
- var peg$e17 = peg$classExpectation([["a", "z"], ["A", "Z"], ["1", "8"], "-", "="], false, false);
245
- var peg$e18 = peg$classExpectation(["+", "#"], false, false);
246
- var peg$e19 = peg$otherExpectation("suffix annotation");
247
- var peg$e20 = peg$classExpectation(["!", "?"], false, false);
248
- var peg$e21 = peg$otherExpectation("NAG");
249
- var peg$e22 = peg$literalExpectation("$", false);
250
- var peg$e23 = peg$otherExpectation("brace comment");
251
- var peg$e24 = peg$literalExpectation("{", false);
252
- var peg$e25 = peg$classExpectation(["}"], true, false);
253
- var peg$e26 = peg$literalExpectation("}", false);
254
- var peg$e27 = peg$otherExpectation("rest of line comment");
255
- var peg$e28 = peg$literalExpectation(";", false);
256
- var peg$e29 = peg$classExpectation(["\r", `
257
- `], true, false);
258
- var peg$e30 = peg$otherExpectation("variation");
259
- var peg$e31 = peg$literalExpectation("(", false);
260
- var peg$e32 = peg$literalExpectation(")", false);
261
- var peg$e33 = peg$otherExpectation("game termination marker");
262
- var peg$e34 = peg$literalExpectation("1-0", false);
263
- var peg$e35 = peg$literalExpectation("0-1", false);
264
- var peg$e36 = peg$literalExpectation("1/2-1/2", false);
265
- var peg$e37 = peg$literalExpectation("*", false);
266
- var peg$e38 = peg$otherExpectation("whitespace");
267
- var peg$e39 = peg$classExpectation([" ", "\t", "\r", `
268
- `], false, false);
269
- var peg$f0 = function(headers, game) {
270
- return pgn(headers, game);
271
- };
272
- var peg$f1 = function(tagPairs) {
273
- return Object.fromEntries(tagPairs);
274
- };
275
- var peg$f2 = function(tagName, tagValue) {
276
- return [tagName, tagValue];
277
- };
278
- var peg$f3 = function(root, marker) {
279
- return { root, marker };
280
- };
281
- var peg$f4 = function(comment, moves) {
282
- return lineToTree(rootNode(comment), ...moves.flat());
283
- };
284
- var peg$f5 = function(san, suffix, nag, comment, variations) {
285
- return node(san, suffix, nag, comment, variations);
286
- };
287
- var peg$f6 = function(nag) {
288
- return nag;
289
- };
290
- var peg$f7 = function(comment) {
291
- return comment.replace(/[\r\n]+/g, " ");
292
- };
293
- var peg$f8 = function(comment) {
294
- return comment.trim();
295
- };
296
- var peg$f9 = function(line) {
297
- return line;
298
- };
299
- var peg$f10 = function(result, comment) {
300
- return { result, comment };
301
- };
302
- var peg$currPos = options.peg$currPos | 0;
303
- var peg$posDetailsCache = [{ line: 1, column: 1 }];
304
- var peg$maxFailPos = peg$currPos;
305
- var peg$maxFailExpected = options.peg$maxFailExpected || [];
306
- var peg$silentFails = options.peg$silentFails | 0;
307
- var peg$result;
308
- if (options.startRule) {
309
- if (!(options.startRule in peg$startRuleFunctions)) {
310
- throw new Error(`Can't start parsing from rule "` + options.startRule + '".');
311
- }
312
- peg$startRuleFunction = peg$startRuleFunctions[options.startRule];
313
- }
314
- function peg$literalExpectation(text, ignoreCase) {
315
- return { type: "literal", text, ignoreCase };
316
- }
317
- function peg$classExpectation(parts, inverted, ignoreCase) {
318
- return { type: "class", parts, inverted, ignoreCase };
319
- }
320
- function peg$endExpectation() {
321
- return { type: "end" };
322
- }
323
- function peg$otherExpectation(description) {
324
- return { type: "other", description };
325
- }
326
- function peg$computePosDetails(pos) {
327
- var details = peg$posDetailsCache[pos];
328
- var p;
329
- if (details) {
330
- return details;
331
- } else {
332
- if (pos >= peg$posDetailsCache.length) {
333
- p = peg$posDetailsCache.length - 1;
334
- } else {
335
- p = pos;
336
- while (!peg$posDetailsCache[--p]) {}
337
- }
338
- details = peg$posDetailsCache[p];
339
- details = {
340
- line: details.line,
341
- column: details.column
342
- };
343
- while (p < pos) {
344
- if (input.charCodeAt(p) === 10) {
345
- details.line++;
346
- details.column = 1;
347
- } else {
348
- details.column++;
349
- }
350
- p++;
351
- }
352
- peg$posDetailsCache[pos] = details;
353
- return details;
354
- }
355
- }
356
- function peg$computeLocation(startPos, endPos, offset) {
357
- var startPosDetails = peg$computePosDetails(startPos);
358
- var endPosDetails = peg$computePosDetails(endPos);
359
- var res = {
360
- source: peg$source,
361
- start: {
362
- offset: startPos,
363
- line: startPosDetails.line,
364
- column: startPosDetails.column
365
- },
366
- end: {
367
- offset: endPos,
368
- line: endPosDetails.line,
369
- column: endPosDetails.column
370
- }
371
- };
372
- return res;
373
- }
374
- function peg$fail(expected) {
375
- if (peg$currPos < peg$maxFailPos) {
376
- return;
377
- }
378
- if (peg$currPos > peg$maxFailPos) {
379
- peg$maxFailPos = peg$currPos;
380
- peg$maxFailExpected = [];
381
- }
382
- peg$maxFailExpected.push(expected);
383
- }
384
- function peg$buildStructuredError(expected, found, location) {
385
- return new peg$SyntaxError(peg$SyntaxError.buildMessage(expected, found), expected, found, location);
386
- }
387
- function peg$parsepgn() {
388
- var s0, s1, s2;
389
- s0 = peg$currPos;
390
- s1 = peg$parsetagPairSection();
391
- s2 = peg$parsemoveTextSection();
392
- s0 = peg$f0(s1, s2);
393
- return s0;
394
- }
395
- function peg$parsetagPairSection() {
396
- var s0, s1, s2;
397
- s0 = peg$currPos;
398
- s1 = [];
399
- s2 = peg$parsetagPair();
400
- while (s2 !== peg$FAILED) {
401
- s1.push(s2);
402
- s2 = peg$parsetagPair();
403
- }
404
- s2 = peg$parse_();
405
- s0 = peg$f1(s1);
406
- return s0;
407
- }
408
- function peg$parsetagPair() {
409
- var s0, s2, s4, s6, s7, s8, s10;
410
- peg$silentFails++;
411
- s0 = peg$currPos;
412
- peg$parse_();
413
- if (input.charCodeAt(peg$currPos) === 91) {
414
- s2 = peg$c0;
415
- peg$currPos++;
416
- } else {
417
- s2 = peg$FAILED;
418
- if (peg$silentFails === 0) {
419
- peg$fail(peg$e1);
420
- }
421
- }
422
- if (s2 !== peg$FAILED) {
423
- peg$parse_();
424
- s4 = peg$parsetagName();
425
- if (s4 !== peg$FAILED) {
426
- peg$parse_();
427
- if (input.charCodeAt(peg$currPos) === 34) {
428
- s6 = peg$c1;
429
- peg$currPos++;
430
- } else {
431
- s6 = peg$FAILED;
432
- if (peg$silentFails === 0) {
433
- peg$fail(peg$e2);
434
- }
435
- }
436
- if (s6 !== peg$FAILED) {
437
- s7 = peg$parsetagValue();
438
- if (input.charCodeAt(peg$currPos) === 34) {
439
- s8 = peg$c1;
440
- peg$currPos++;
441
- } else {
442
- s8 = peg$FAILED;
443
- if (peg$silentFails === 0) {
444
- peg$fail(peg$e2);
445
- }
446
- }
447
- if (s8 !== peg$FAILED) {
448
- peg$parse_();
449
- if (input.charCodeAt(peg$currPos) === 93) {
450
- s10 = peg$c2;
451
- peg$currPos++;
452
- } else {
453
- s10 = peg$FAILED;
454
- if (peg$silentFails === 0) {
455
- peg$fail(peg$e3);
456
- }
457
- }
458
- if (s10 !== peg$FAILED) {
459
- s0 = peg$f2(s4, s7);
460
- } else {
461
- peg$currPos = s0;
462
- s0 = peg$FAILED;
463
- }
464
- } else {
465
- peg$currPos = s0;
466
- s0 = peg$FAILED;
467
- }
468
- } else {
469
- peg$currPos = s0;
470
- s0 = peg$FAILED;
471
- }
472
- } else {
473
- peg$currPos = s0;
474
- s0 = peg$FAILED;
475
- }
476
- } else {
477
- peg$currPos = s0;
478
- s0 = peg$FAILED;
479
- }
480
- peg$silentFails--;
481
- if (s0 === peg$FAILED) {
482
- if (peg$silentFails === 0) {
483
- peg$fail(peg$e0);
484
- }
485
- }
486
- return s0;
487
- }
488
- function peg$parsetagName() {
489
- var s0, s1, s2;
490
- peg$silentFails++;
491
- s0 = peg$currPos;
492
- s1 = [];
493
- s2 = input.charAt(peg$currPos);
494
- if (peg$r0.test(s2)) {
495
- peg$currPos++;
496
- } else {
497
- s2 = peg$FAILED;
498
- if (peg$silentFails === 0) {
499
- peg$fail(peg$e5);
500
- }
501
- }
502
- if (s2 !== peg$FAILED) {
503
- while (s2 !== peg$FAILED) {
504
- s1.push(s2);
505
- s2 = input.charAt(peg$currPos);
506
- if (peg$r0.test(s2)) {
507
- peg$currPos++;
508
- } else {
509
- s2 = peg$FAILED;
510
- if (peg$silentFails === 0) {
511
- peg$fail(peg$e5);
512
- }
513
- }
514
- }
515
- } else {
516
- s1 = peg$FAILED;
517
- }
518
- if (s1 !== peg$FAILED) {
519
- s0 = input.substring(s0, peg$currPos);
520
- } else {
521
- s0 = s1;
522
- }
523
- peg$silentFails--;
524
- if (s0 === peg$FAILED) {
525
- s1 = peg$FAILED;
526
- if (peg$silentFails === 0) {
527
- peg$fail(peg$e4);
528
- }
529
- }
530
- return s0;
531
- }
532
- function peg$parsetagValue() {
533
- var s0, s1, s2;
534
- peg$silentFails++;
535
- s0 = peg$currPos;
536
- s1 = [];
537
- s2 = input.charAt(peg$currPos);
538
- if (peg$r1.test(s2)) {
539
- peg$currPos++;
540
- } else {
541
- s2 = peg$FAILED;
542
- if (peg$silentFails === 0) {
543
- peg$fail(peg$e7);
544
- }
545
- }
546
- while (s2 !== peg$FAILED) {
547
- s1.push(s2);
548
- s2 = input.charAt(peg$currPos);
549
- if (peg$r1.test(s2)) {
550
- peg$currPos++;
551
- } else {
552
- s2 = peg$FAILED;
553
- if (peg$silentFails === 0) {
554
- peg$fail(peg$e7);
555
- }
556
- }
557
- }
558
- s0 = input.substring(s0, peg$currPos);
559
- peg$silentFails--;
560
- s1 = peg$FAILED;
561
- if (peg$silentFails === 0) {
562
- peg$fail(peg$e6);
563
- }
564
- return s0;
565
- }
566
- function peg$parsemoveTextSection() {
567
- var s0, s1, s3;
568
- s0 = peg$currPos;
569
- s1 = peg$parseline();
570
- peg$parse_();
571
- s3 = peg$parsegameTerminationMarker();
572
- if (s3 === peg$FAILED) {
573
- s3 = null;
574
- }
575
- peg$parse_();
576
- s0 = peg$f3(s1, s3);
577
- return s0;
578
- }
579
- function peg$parseline() {
580
- var s0, s1, s2, s3;
581
- s0 = peg$currPos;
582
- s1 = peg$parsecomment();
583
- if (s1 === peg$FAILED) {
584
- s1 = null;
585
- }
586
- s2 = [];
587
- s3 = peg$parsemove();
588
- while (s3 !== peg$FAILED) {
589
- s2.push(s3);
590
- s3 = peg$parsemove();
591
- }
592
- s0 = peg$f4(s1, s2);
593
- return s0;
594
- }
595
- function peg$parsemove() {
596
- var s0, s4, s5, s6, s7, s8, s9, s10;
597
- s0 = peg$currPos;
598
- peg$parse_();
599
- peg$parsemoveNumber();
600
- peg$parse_();
601
- s4 = peg$parsesan();
602
- if (s4 !== peg$FAILED) {
603
- s5 = peg$parsesuffixAnnotation();
604
- if (s5 === peg$FAILED) {
605
- s5 = null;
606
- }
607
- s6 = [];
608
- s7 = peg$parsenag();
609
- while (s7 !== peg$FAILED) {
610
- s6.push(s7);
611
- s7 = peg$parsenag();
612
- }
613
- s7 = peg$parse_();
614
- s8 = peg$parsecomment();
615
- if (s8 === peg$FAILED) {
616
- s8 = null;
617
- }
618
- s9 = [];
619
- s10 = peg$parsevariation();
620
- while (s10 !== peg$FAILED) {
621
- s9.push(s10);
622
- s10 = peg$parsevariation();
623
- }
624
- s0 = peg$f5(s4, s5, s6, s8, s9);
625
- } else {
626
- peg$currPos = s0;
627
- s0 = peg$FAILED;
628
- }
629
- return s0;
630
- }
631
- function peg$parsemoveNumber() {
632
- var s0, s1, s2, s3, s4, s5;
633
- peg$silentFails++;
634
- s0 = peg$currPos;
635
- s1 = [];
636
- s2 = input.charAt(peg$currPos);
637
- if (peg$r2.test(s2)) {
638
- peg$currPos++;
639
- } else {
640
- s2 = peg$FAILED;
641
- if (peg$silentFails === 0) {
642
- peg$fail(peg$e9);
643
- }
644
- }
645
- while (s2 !== peg$FAILED) {
646
- s1.push(s2);
647
- s2 = input.charAt(peg$currPos);
648
- if (peg$r2.test(s2)) {
649
- peg$currPos++;
650
- } else {
651
- s2 = peg$FAILED;
652
- if (peg$silentFails === 0) {
653
- peg$fail(peg$e9);
654
- }
655
- }
656
- }
657
- if (input.charCodeAt(peg$currPos) === 46) {
658
- s2 = peg$c3;
659
- peg$currPos++;
660
- } else {
661
- s2 = peg$FAILED;
662
- if (peg$silentFails === 0) {
663
- peg$fail(peg$e10);
664
- }
665
- }
666
- if (s2 !== peg$FAILED) {
667
- s3 = peg$parse_();
668
- s4 = [];
669
- s5 = input.charAt(peg$currPos);
670
- if (peg$r3.test(s5)) {
671
- peg$currPos++;
672
- } else {
673
- s5 = peg$FAILED;
674
- if (peg$silentFails === 0) {
675
- peg$fail(peg$e11);
676
- }
677
- }
678
- while (s5 !== peg$FAILED) {
679
- s4.push(s5);
680
- s5 = input.charAt(peg$currPos);
681
- if (peg$r3.test(s5)) {
682
- peg$currPos++;
683
- } else {
684
- s5 = peg$FAILED;
685
- if (peg$silentFails === 0) {
686
- peg$fail(peg$e11);
687
- }
688
- }
689
- }
690
- s1 = [s1, s2, s3, s4];
691
- s0 = s1;
692
- } else {
693
- peg$currPos = s0;
694
- s0 = peg$FAILED;
695
- }
696
- peg$silentFails--;
697
- if (s0 === peg$FAILED) {
698
- s1 = peg$FAILED;
699
- if (peg$silentFails === 0) {
700
- peg$fail(peg$e8);
701
- }
702
- }
703
- return s0;
704
- }
705
- function peg$parsesan() {
706
- var s0, s1, s2, s3, s4, s5;
707
- peg$silentFails++;
708
- s0 = peg$currPos;
709
- s1 = peg$currPos;
710
- if (input.substr(peg$currPos, 5) === peg$c4) {
711
- s2 = peg$c4;
712
- peg$currPos += 5;
713
- } else {
714
- s2 = peg$FAILED;
715
- if (peg$silentFails === 0) {
716
- peg$fail(peg$e13);
717
- }
718
- }
719
- if (s2 === peg$FAILED) {
720
- if (input.substr(peg$currPos, 3) === peg$c5) {
721
- s2 = peg$c5;
722
- peg$currPos += 3;
723
- } else {
724
- s2 = peg$FAILED;
725
- if (peg$silentFails === 0) {
726
- peg$fail(peg$e14);
727
- }
728
- }
729
- if (s2 === peg$FAILED) {
730
- if (input.substr(peg$currPos, 5) === peg$c6) {
731
- s2 = peg$c6;
732
- peg$currPos += 5;
733
- } else {
734
- s2 = peg$FAILED;
735
- if (peg$silentFails === 0) {
736
- peg$fail(peg$e15);
737
- }
738
- }
739
- if (s2 === peg$FAILED) {
740
- if (input.substr(peg$currPos, 3) === peg$c7) {
741
- s2 = peg$c7;
742
- peg$currPos += 3;
743
- } else {
744
- s2 = peg$FAILED;
745
- if (peg$silentFails === 0) {
746
- peg$fail(peg$e16);
747
- }
748
- }
749
- if (s2 === peg$FAILED) {
750
- s2 = peg$currPos;
751
- s3 = input.charAt(peg$currPos);
752
- if (peg$r0.test(s3)) {
753
- peg$currPos++;
754
- } else {
755
- s3 = peg$FAILED;
756
- if (peg$silentFails === 0) {
757
- peg$fail(peg$e5);
758
- }
759
- }
760
- if (s3 !== peg$FAILED) {
761
- s4 = [];
762
- s5 = input.charAt(peg$currPos);
763
- if (peg$r4.test(s5)) {
764
- peg$currPos++;
765
- } else {
766
- s5 = peg$FAILED;
767
- if (peg$silentFails === 0) {
768
- peg$fail(peg$e17);
769
- }
770
- }
771
- if (s5 !== peg$FAILED) {
772
- while (s5 !== peg$FAILED) {
773
- s4.push(s5);
774
- s5 = input.charAt(peg$currPos);
775
- if (peg$r4.test(s5)) {
776
- peg$currPos++;
777
- } else {
778
- s5 = peg$FAILED;
779
- if (peg$silentFails === 0) {
780
- peg$fail(peg$e17);
781
- }
782
- }
783
- }
784
- } else {
785
- s4 = peg$FAILED;
786
- }
787
- if (s4 !== peg$FAILED) {
788
- s3 = [s3, s4];
789
- s2 = s3;
790
- } else {
791
- peg$currPos = s2;
792
- s2 = peg$FAILED;
793
- }
794
- } else {
795
- peg$currPos = s2;
796
- s2 = peg$FAILED;
797
- }
798
- }
799
- }
800
- }
801
- }
802
- if (s2 !== peg$FAILED) {
803
- s3 = input.charAt(peg$currPos);
804
- if (peg$r5.test(s3)) {
805
- peg$currPos++;
806
- } else {
807
- s3 = peg$FAILED;
808
- if (peg$silentFails === 0) {
809
- peg$fail(peg$e18);
810
- }
811
- }
812
- if (s3 === peg$FAILED) {
813
- s3 = null;
814
- }
815
- s2 = [s2, s3];
816
- s1 = s2;
817
- } else {
818
- peg$currPos = s1;
819
- s1 = peg$FAILED;
820
- }
821
- if (s1 !== peg$FAILED) {
822
- s0 = input.substring(s0, peg$currPos);
823
- } else {
824
- s0 = s1;
825
- }
826
- peg$silentFails--;
827
- if (s0 === peg$FAILED) {
828
- s1 = peg$FAILED;
829
- if (peg$silentFails === 0) {
830
- peg$fail(peg$e12);
831
- }
832
- }
833
- return s0;
834
- }
835
- function peg$parsesuffixAnnotation() {
836
- var s0, s1, s2;
837
- peg$silentFails++;
838
- s0 = peg$currPos;
839
- s1 = [];
840
- s2 = input.charAt(peg$currPos);
841
- if (peg$r6.test(s2)) {
842
- peg$currPos++;
843
- } else {
844
- s2 = peg$FAILED;
845
- if (peg$silentFails === 0) {
846
- peg$fail(peg$e20);
847
- }
848
- }
849
- while (s2 !== peg$FAILED) {
850
- s1.push(s2);
851
- if (s1.length >= 2) {
852
- s2 = peg$FAILED;
853
- } else {
854
- s2 = input.charAt(peg$currPos);
855
- if (peg$r6.test(s2)) {
856
- peg$currPos++;
857
- } else {
858
- s2 = peg$FAILED;
859
- if (peg$silentFails === 0) {
860
- peg$fail(peg$e20);
861
- }
862
- }
863
- }
864
- }
865
- if (s1.length < 1) {
866
- peg$currPos = s0;
867
- s0 = peg$FAILED;
868
- } else {
869
- s0 = s1;
870
- }
871
- peg$silentFails--;
872
- if (s0 === peg$FAILED) {
873
- s1 = peg$FAILED;
874
- if (peg$silentFails === 0) {
875
- peg$fail(peg$e19);
876
- }
877
- }
878
- return s0;
879
- }
880
- function peg$parsenag() {
881
- var s0, s2, s3, s4, s5;
882
- peg$silentFails++;
883
- s0 = peg$currPos;
884
- peg$parse_();
885
- if (input.charCodeAt(peg$currPos) === 36) {
886
- s2 = peg$c8;
887
- peg$currPos++;
888
- } else {
889
- s2 = peg$FAILED;
890
- if (peg$silentFails === 0) {
891
- peg$fail(peg$e22);
892
- }
893
- }
894
- if (s2 !== peg$FAILED) {
895
- s3 = peg$currPos;
896
- s4 = [];
897
- s5 = input.charAt(peg$currPos);
898
- if (peg$r2.test(s5)) {
899
- peg$currPos++;
900
- } else {
901
- s5 = peg$FAILED;
902
- if (peg$silentFails === 0) {
903
- peg$fail(peg$e9);
904
- }
905
- }
906
- if (s5 !== peg$FAILED) {
907
- while (s5 !== peg$FAILED) {
908
- s4.push(s5);
909
- s5 = input.charAt(peg$currPos);
910
- if (peg$r2.test(s5)) {
911
- peg$currPos++;
912
- } else {
913
- s5 = peg$FAILED;
914
- if (peg$silentFails === 0) {
915
- peg$fail(peg$e9);
916
- }
917
- }
918
- }
919
- } else {
920
- s4 = peg$FAILED;
921
- }
922
- if (s4 !== peg$FAILED) {
923
- s3 = input.substring(s3, peg$currPos);
924
- } else {
925
- s3 = s4;
926
- }
927
- if (s3 !== peg$FAILED) {
928
- s0 = peg$f6(s3);
929
- } else {
930
- peg$currPos = s0;
931
- s0 = peg$FAILED;
932
- }
933
- } else {
934
- peg$currPos = s0;
935
- s0 = peg$FAILED;
936
- }
937
- peg$silentFails--;
938
- if (s0 === peg$FAILED) {
939
- if (peg$silentFails === 0) {
940
- peg$fail(peg$e21);
941
- }
942
- }
943
- return s0;
944
- }
945
- function peg$parsecomment() {
946
- var s0;
947
- s0 = peg$parsebraceComment();
948
- if (s0 === peg$FAILED) {
949
- s0 = peg$parserestOfLineComment();
950
- }
951
- return s0;
952
- }
953
- function peg$parsebraceComment() {
954
- var s0, s1, s2, s3, s4;
955
- peg$silentFails++;
956
- s0 = peg$currPos;
957
- if (input.charCodeAt(peg$currPos) === 123) {
958
- s1 = peg$c9;
959
- peg$currPos++;
960
- } else {
961
- s1 = peg$FAILED;
962
- if (peg$silentFails === 0) {
963
- peg$fail(peg$e24);
964
- }
965
- }
966
- if (s1 !== peg$FAILED) {
967
- s2 = peg$currPos;
968
- s3 = [];
969
- s4 = input.charAt(peg$currPos);
970
- if (peg$r7.test(s4)) {
971
- peg$currPos++;
972
- } else {
973
- s4 = peg$FAILED;
974
- if (peg$silentFails === 0) {
975
- peg$fail(peg$e25);
976
- }
977
- }
978
- while (s4 !== peg$FAILED) {
979
- s3.push(s4);
980
- s4 = input.charAt(peg$currPos);
981
- if (peg$r7.test(s4)) {
982
- peg$currPos++;
983
- } else {
984
- s4 = peg$FAILED;
985
- if (peg$silentFails === 0) {
986
- peg$fail(peg$e25);
987
- }
988
- }
989
- }
990
- s2 = input.substring(s2, peg$currPos);
991
- if (input.charCodeAt(peg$currPos) === 125) {
992
- s3 = peg$c10;
993
- peg$currPos++;
994
- } else {
995
- s3 = peg$FAILED;
996
- if (peg$silentFails === 0) {
997
- peg$fail(peg$e26);
998
- }
999
- }
1000
- if (s3 !== peg$FAILED) {
1001
- s0 = peg$f7(s2);
1002
- } else {
1003
- peg$currPos = s0;
1004
- s0 = peg$FAILED;
1005
- }
1006
- } else {
1007
- peg$currPos = s0;
1008
- s0 = peg$FAILED;
1009
- }
1010
- peg$silentFails--;
1011
- if (s0 === peg$FAILED) {
1012
- s1 = peg$FAILED;
1013
- if (peg$silentFails === 0) {
1014
- peg$fail(peg$e23);
1015
- }
1016
- }
1017
- return s0;
1018
- }
1019
- function peg$parserestOfLineComment() {
1020
- var s0, s1, s2, s3, s4;
1021
- peg$silentFails++;
1022
- s0 = peg$currPos;
1023
- if (input.charCodeAt(peg$currPos) === 59) {
1024
- s1 = peg$c11;
1025
- peg$currPos++;
1026
- } else {
1027
- s1 = peg$FAILED;
1028
- if (peg$silentFails === 0) {
1029
- peg$fail(peg$e28);
1030
- }
1031
- }
1032
- if (s1 !== peg$FAILED) {
1033
- s2 = peg$currPos;
1034
- s3 = [];
1035
- s4 = input.charAt(peg$currPos);
1036
- if (peg$r8.test(s4)) {
1037
- peg$currPos++;
1038
- } else {
1039
- s4 = peg$FAILED;
1040
- if (peg$silentFails === 0) {
1041
- peg$fail(peg$e29);
1042
- }
1043
- }
1044
- while (s4 !== peg$FAILED) {
1045
- s3.push(s4);
1046
- s4 = input.charAt(peg$currPos);
1047
- if (peg$r8.test(s4)) {
1048
- peg$currPos++;
1049
- } else {
1050
- s4 = peg$FAILED;
1051
- if (peg$silentFails === 0) {
1052
- peg$fail(peg$e29);
1053
- }
1054
- }
1055
- }
1056
- s2 = input.substring(s2, peg$currPos);
1057
- s0 = peg$f8(s2);
1058
- } else {
1059
- peg$currPos = s0;
1060
- s0 = peg$FAILED;
1061
- }
1062
- peg$silentFails--;
1063
- if (s0 === peg$FAILED) {
1064
- s1 = peg$FAILED;
1065
- if (peg$silentFails === 0) {
1066
- peg$fail(peg$e27);
1067
- }
1068
- }
1069
- return s0;
1070
- }
1071
- function peg$parsevariation() {
1072
- var s0, s2, s3, s5;
1073
- peg$silentFails++;
1074
- s0 = peg$currPos;
1075
- peg$parse_();
1076
- if (input.charCodeAt(peg$currPos) === 40) {
1077
- s2 = peg$c12;
1078
- peg$currPos++;
1079
- } else {
1080
- s2 = peg$FAILED;
1081
- if (peg$silentFails === 0) {
1082
- peg$fail(peg$e31);
1083
- }
1084
- }
1085
- if (s2 !== peg$FAILED) {
1086
- s3 = peg$parseline();
1087
- if (s3 !== peg$FAILED) {
1088
- peg$parse_();
1089
- if (input.charCodeAt(peg$currPos) === 41) {
1090
- s5 = peg$c13;
1091
- peg$currPos++;
1092
- } else {
1093
- s5 = peg$FAILED;
1094
- if (peg$silentFails === 0) {
1095
- peg$fail(peg$e32);
1096
- }
1097
- }
1098
- if (s5 !== peg$FAILED) {
1099
- s0 = peg$f9(s3);
1100
- } else {
1101
- peg$currPos = s0;
1102
- s0 = peg$FAILED;
1103
- }
1104
- } else {
1105
- peg$currPos = s0;
1106
- s0 = peg$FAILED;
1107
- }
1108
- } else {
1109
- peg$currPos = s0;
1110
- s0 = peg$FAILED;
1111
- }
1112
- peg$silentFails--;
1113
- if (s0 === peg$FAILED) {
1114
- if (peg$silentFails === 0) {
1115
- peg$fail(peg$e30);
1116
- }
1117
- }
1118
- return s0;
1119
- }
1120
- function peg$parsegameTerminationMarker() {
1121
- var s0, s1, s3;
1122
- peg$silentFails++;
1123
- s0 = peg$currPos;
1124
- if (input.substr(peg$currPos, 3) === peg$c14) {
1125
- s1 = peg$c14;
1126
- peg$currPos += 3;
1127
- } else {
1128
- s1 = peg$FAILED;
1129
- if (peg$silentFails === 0) {
1130
- peg$fail(peg$e34);
1131
- }
1132
- }
1133
- if (s1 === peg$FAILED) {
1134
- if (input.substr(peg$currPos, 3) === peg$c15) {
1135
- s1 = peg$c15;
1136
- peg$currPos += 3;
1137
- } else {
1138
- s1 = peg$FAILED;
1139
- if (peg$silentFails === 0) {
1140
- peg$fail(peg$e35);
1141
- }
1142
- }
1143
- if (s1 === peg$FAILED) {
1144
- if (input.substr(peg$currPos, 7) === peg$c16) {
1145
- s1 = peg$c16;
1146
- peg$currPos += 7;
1147
- } else {
1148
- s1 = peg$FAILED;
1149
- if (peg$silentFails === 0) {
1150
- peg$fail(peg$e36);
1151
- }
1152
- }
1153
- if (s1 === peg$FAILED) {
1154
- if (input.charCodeAt(peg$currPos) === 42) {
1155
- s1 = peg$c17;
1156
- peg$currPos++;
1157
- } else {
1158
- s1 = peg$FAILED;
1159
- if (peg$silentFails === 0) {
1160
- peg$fail(peg$e37);
1161
- }
1162
- }
1163
- }
1164
- }
1165
- }
1166
- if (s1 !== peg$FAILED) {
1167
- peg$parse_();
1168
- s3 = peg$parsecomment();
1169
- if (s3 === peg$FAILED) {
1170
- s3 = null;
1171
- }
1172
- s0 = peg$f10(s1, s3);
1173
- } else {
1174
- peg$currPos = s0;
1175
- s0 = peg$FAILED;
1176
- }
1177
- peg$silentFails--;
1178
- if (s0 === peg$FAILED) {
1179
- s1 = peg$FAILED;
1180
- if (peg$silentFails === 0) {
1181
- peg$fail(peg$e33);
1182
- }
1183
- }
1184
- return s0;
1185
- }
1186
- function peg$parse_() {
1187
- var s0, s1;
1188
- peg$silentFails++;
1189
- s0 = [];
1190
- s1 = input.charAt(peg$currPos);
1191
- if (peg$r9.test(s1)) {
1192
- peg$currPos++;
1193
- } else {
1194
- s1 = peg$FAILED;
1195
- if (peg$silentFails === 0) {
1196
- peg$fail(peg$e39);
1197
- }
1198
- }
1199
- while (s1 !== peg$FAILED) {
1200
- s0.push(s1);
1201
- s1 = input.charAt(peg$currPos);
1202
- if (peg$r9.test(s1)) {
1203
- peg$currPos++;
1204
- } else {
1205
- s1 = peg$FAILED;
1206
- if (peg$silentFails === 0) {
1207
- peg$fail(peg$e39);
1208
- }
1209
- }
1210
- }
1211
- peg$silentFails--;
1212
- s1 = peg$FAILED;
1213
- if (peg$silentFails === 0) {
1214
- peg$fail(peg$e38);
1215
- }
1216
- return s0;
1217
- }
1218
- peg$result = peg$startRuleFunction();
1219
- if (options.peg$library) {
1220
- return {
1221
- peg$result,
1222
- peg$currPos,
1223
- peg$FAILED,
1224
- peg$maxFailExpected,
1225
- peg$maxFailPos
1226
- };
1227
- }
1228
- if (peg$result !== peg$FAILED && peg$currPos === input.length) {
1229
- return peg$result;
1230
- } else {
1231
- if (peg$result !== peg$FAILED && peg$currPos < input.length) {
1232
- peg$fail(peg$endExpectation());
1233
- }
1234
- throw peg$buildStructuredError(peg$maxFailExpected, peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, peg$maxFailPos < input.length ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) : peg$computeLocation(peg$maxFailPos, peg$maxFailPos));
1235
- }
1236
- }
1237
- var MASK64 = 0xffffffffffffffffn;
1238
- function rotl(x, k) {
1239
- return (x << k | x >> 64n - k) & 0xffffffffffffffffn;
1240
- }
1241
- function wrappingMul(x, y) {
1242
- return x * y & MASK64;
1243
- }
1244
- function xoroshiro128(state) {
1245
- return function() {
1246
- let s0 = BigInt(state & MASK64);
1247
- let s1 = BigInt(state >> 64n & MASK64);
1248
- const result = wrappingMul(rotl(wrappingMul(s0, 5n), 7n), 9n);
1249
- s1 ^= s0;
1250
- s0 = (rotl(s0, 24n) ^ s1 ^ s1 << 16n) & MASK64;
1251
- s1 = rotl(s1, 37n);
1252
- state = s1 << 64n | s0;
1253
- return result;
1254
- };
1255
- }
1256
- var rand = xoroshiro128(0xa187eb39cdcaed8f31c4b365b102e01en);
1257
- var PIECE_KEYS = Array.from({ length: 2 }, () => Array.from({ length: 6 }, () => Array.from({ length: 128 }, () => rand())));
1258
- var EP_KEYS = Array.from({ length: 8 }, () => rand());
1259
- var CASTLING_KEYS = Array.from({ length: 16 }, () => rand());
1260
- var SIDE_KEY = rand();
1261
- var WHITE = "w";
1262
- var BLACK = "b";
1263
- var PAWN = "p";
1264
- var KNIGHT = "n";
1265
- var BISHOP = "b";
1266
- var ROOK = "r";
1267
- var QUEEN = "q";
1268
- var KING = "k";
1269
- var DEFAULT_POSITION = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1";
1270
-
1271
- class Move {
1272
- color;
1273
- from;
1274
- to;
1275
- piece;
1276
- captured;
1277
- promotion;
1278
- flags;
1279
- san;
1280
- lan;
1281
- before;
1282
- after;
1283
- constructor(chess, internal) {
1284
- const { color, piece, from, to, flags, captured, promotion } = internal;
1285
- const fromAlgebraic = algebraic(from);
1286
- const toAlgebraic = algebraic(to);
1287
- this.color = color;
1288
- this.piece = piece;
1289
- this.from = fromAlgebraic;
1290
- this.to = toAlgebraic;
1291
- this.san = chess["_moveToSan"](internal, chess["_moves"]({ legal: true }));
1292
- this.lan = fromAlgebraic + toAlgebraic;
1293
- this.before = chess.fen();
1294
- chess["_makeMove"](internal);
1295
- this.after = chess.fen();
1296
- chess["_undoMove"]();
1297
- this.flags = "";
1298
- for (const flag in BITS) {
1299
- if (BITS[flag] & flags) {
1300
- this.flags += FLAGS[flag];
1301
- }
1302
- }
1303
- if (captured) {
1304
- this.captured = captured;
1305
- }
1306
- if (promotion) {
1307
- this.promotion = promotion;
1308
- this.lan += promotion;
1309
- }
1310
- }
1311
- isCapture() {
1312
- return this.flags.indexOf(FLAGS["CAPTURE"]) > -1;
1313
- }
1314
- isPromotion() {
1315
- return this.flags.indexOf(FLAGS["PROMOTION"]) > -1;
1316
- }
1317
- isEnPassant() {
1318
- return this.flags.indexOf(FLAGS["EP_CAPTURE"]) > -1;
1319
- }
1320
- isKingsideCastle() {
1321
- return this.flags.indexOf(FLAGS["KSIDE_CASTLE"]) > -1;
1322
- }
1323
- isQueensideCastle() {
1324
- return this.flags.indexOf(FLAGS["QSIDE_CASTLE"]) > -1;
1325
- }
1326
- isBigPawn() {
1327
- return this.flags.indexOf(FLAGS["BIG_PAWN"]) > -1;
1328
- }
1329
- }
1330
- var EMPTY = -1;
1331
- var FLAGS = {
1332
- NORMAL: "n",
1333
- CAPTURE: "c",
1334
- BIG_PAWN: "b",
1335
- EP_CAPTURE: "e",
1336
- PROMOTION: "p",
1337
- KSIDE_CASTLE: "k",
1338
- QSIDE_CASTLE: "q",
1339
- NULL_MOVE: "-"
1340
- };
1341
- var BITS = {
1342
- NORMAL: 1,
1343
- CAPTURE: 2,
1344
- BIG_PAWN: 4,
1345
- EP_CAPTURE: 8,
1346
- PROMOTION: 16,
1347
- KSIDE_CASTLE: 32,
1348
- QSIDE_CASTLE: 64,
1349
- NULL_MOVE: 128
1350
- };
1351
- var SEVEN_TAG_ROSTER = {
1352
- Event: "?",
1353
- Site: "?",
1354
- Date: "????.??.??",
1355
- Round: "?",
1356
- White: "?",
1357
- Black: "?",
1358
- Result: "*"
1359
- };
1360
- var SUPLEMENTAL_TAGS = {
1361
- WhiteTitle: null,
1362
- BlackTitle: null,
1363
- WhiteElo: null,
1364
- BlackElo: null,
1365
- WhiteUSCF: null,
1366
- BlackUSCF: null,
1367
- WhiteNA: null,
1368
- BlackNA: null,
1369
- WhiteType: null,
1370
- BlackType: null,
1371
- EventDate: null,
1372
- EventSponsor: null,
1373
- Section: null,
1374
- Stage: null,
1375
- Board: null,
1376
- Opening: null,
1377
- Variation: null,
1378
- SubVariation: null,
1379
- ECO: null,
1380
- NIC: null,
1381
- Time: null,
1382
- UTCTime: null,
1383
- UTCDate: null,
1384
- TimeControl: null,
1385
- SetUp: null,
1386
- FEN: null,
1387
- Termination: null,
1388
- Annotator: null,
1389
- Mode: null,
1390
- PlyCount: null
1391
- };
1392
- var HEADER_TEMPLATE = {
1393
- ...SEVEN_TAG_ROSTER,
1394
- ...SUPLEMENTAL_TAGS
1395
- };
1396
- var Ox88 = {
1397
- a8: 0,
1398
- b8: 1,
1399
- c8: 2,
1400
- d8: 3,
1401
- e8: 4,
1402
- f8: 5,
1403
- g8: 6,
1404
- h8: 7,
1405
- a7: 16,
1406
- b7: 17,
1407
- c7: 18,
1408
- d7: 19,
1409
- e7: 20,
1410
- f7: 21,
1411
- g7: 22,
1412
- h7: 23,
1413
- a6: 32,
1414
- b6: 33,
1415
- c6: 34,
1416
- d6: 35,
1417
- e6: 36,
1418
- f6: 37,
1419
- g6: 38,
1420
- h6: 39,
1421
- a5: 48,
1422
- b5: 49,
1423
- c5: 50,
1424
- d5: 51,
1425
- e5: 52,
1426
- f5: 53,
1427
- g5: 54,
1428
- h5: 55,
1429
- a4: 64,
1430
- b4: 65,
1431
- c4: 66,
1432
- d4: 67,
1433
- e4: 68,
1434
- f4: 69,
1435
- g4: 70,
1436
- h4: 71,
1437
- a3: 80,
1438
- b3: 81,
1439
- c3: 82,
1440
- d3: 83,
1441
- e3: 84,
1442
- f3: 85,
1443
- g3: 86,
1444
- h3: 87,
1445
- a2: 96,
1446
- b2: 97,
1447
- c2: 98,
1448
- d2: 99,
1449
- e2: 100,
1450
- f2: 101,
1451
- g2: 102,
1452
- h2: 103,
1453
- a1: 112,
1454
- b1: 113,
1455
- c1: 114,
1456
- d1: 115,
1457
- e1: 116,
1458
- f1: 117,
1459
- g1: 118,
1460
- h1: 119
1461
- };
1462
- var PAWN_OFFSETS = {
1463
- b: [16, 32, 17, 15],
1464
- w: [-16, -32, -17, -15]
1465
- };
1466
- var PIECE_OFFSETS = {
1467
- n: [-18, -33, -31, -14, 18, 33, 31, 14],
1468
- b: [-17, -15, 17, 15],
1469
- r: [-16, 1, 16, -1],
1470
- q: [-17, -16, -15, 1, 17, 16, 15, -1],
1471
- k: [-17, -16, -15, 1, 17, 16, 15, -1]
1472
- };
1473
- var ATTACKS = [
1474
- 20,
1475
- 0,
1476
- 0,
1477
- 0,
1478
- 0,
1479
- 0,
1480
- 0,
1481
- 24,
1482
- 0,
1483
- 0,
1484
- 0,
1485
- 0,
1486
- 0,
1487
- 0,
1488
- 20,
1489
- 0,
1490
- 0,
1491
- 20,
1492
- 0,
1493
- 0,
1494
- 0,
1495
- 0,
1496
- 0,
1497
- 24,
1498
- 0,
1499
- 0,
1500
- 0,
1501
- 0,
1502
- 0,
1503
- 20,
1504
- 0,
1505
- 0,
1506
- 0,
1507
- 0,
1508
- 20,
1509
- 0,
1510
- 0,
1511
- 0,
1512
- 0,
1513
- 24,
1514
- 0,
1515
- 0,
1516
- 0,
1517
- 0,
1518
- 20,
1519
- 0,
1520
- 0,
1521
- 0,
1522
- 0,
1523
- 0,
1524
- 0,
1525
- 20,
1526
- 0,
1527
- 0,
1528
- 0,
1529
- 24,
1530
- 0,
1531
- 0,
1532
- 0,
1533
- 20,
1534
- 0,
1535
- 0,
1536
- 0,
1537
- 0,
1538
- 0,
1539
- 0,
1540
- 0,
1541
- 0,
1542
- 20,
1543
- 0,
1544
- 0,
1545
- 24,
1546
- 0,
1547
- 0,
1548
- 20,
1549
- 0,
1550
- 0,
1551
- 0,
1552
- 0,
1553
- 0,
1554
- 0,
1555
- 0,
1556
- 0,
1557
- 0,
1558
- 0,
1559
- 20,
1560
- 2,
1561
- 24,
1562
- 2,
1563
- 20,
1564
- 0,
1565
- 0,
1566
- 0,
1567
- 0,
1568
- 0,
1569
- 0,
1570
- 0,
1571
- 0,
1572
- 0,
1573
- 0,
1574
- 0,
1575
- 2,
1576
- 53,
1577
- 56,
1578
- 53,
1579
- 2,
1580
- 0,
1581
- 0,
1582
- 0,
1583
- 0,
1584
- 0,
1585
- 0,
1586
- 24,
1587
- 24,
1588
- 24,
1589
- 24,
1590
- 24,
1591
- 24,
1592
- 56,
1593
- 0,
1594
- 56,
1595
- 24,
1596
- 24,
1597
- 24,
1598
- 24,
1599
- 24,
1600
- 24,
1601
- 0,
1602
- 0,
1603
- 0,
1604
- 0,
1605
- 0,
1606
- 0,
1607
- 2,
1608
- 53,
1609
- 56,
1610
- 53,
1611
- 2,
1612
- 0,
1613
- 0,
1614
- 0,
1615
- 0,
1616
- 0,
1617
- 0,
1618
- 0,
1619
- 0,
1620
- 0,
1621
- 0,
1622
- 0,
1623
- 20,
1624
- 2,
1625
- 24,
1626
- 2,
1627
- 20,
1628
- 0,
1629
- 0,
1630
- 0,
1631
- 0,
1632
- 0,
1633
- 0,
1634
- 0,
1635
- 0,
1636
- 0,
1637
- 0,
1638
- 20,
1639
- 0,
1640
- 0,
1641
- 24,
1642
- 0,
1643
- 0,
1644
- 20,
1645
- 0,
1646
- 0,
1647
- 0,
1648
- 0,
1649
- 0,
1650
- 0,
1651
- 0,
1652
- 0,
1653
- 20,
1654
- 0,
1655
- 0,
1656
- 0,
1657
- 24,
1658
- 0,
1659
- 0,
1660
- 0,
1661
- 20,
1662
- 0,
1663
- 0,
1664
- 0,
1665
- 0,
1666
- 0,
1667
- 0,
1668
- 20,
1669
- 0,
1670
- 0,
1671
- 0,
1672
- 0,
1673
- 24,
1674
- 0,
1675
- 0,
1676
- 0,
1677
- 0,
1678
- 20,
1679
- 0,
1680
- 0,
1681
- 0,
1682
- 0,
1683
- 20,
1684
- 0,
1685
- 0,
1686
- 0,
1687
- 0,
1688
- 0,
1689
- 24,
1690
- 0,
1691
- 0,
1692
- 0,
1693
- 0,
1694
- 0,
1695
- 20,
1696
- 0,
1697
- 0,
1698
- 20,
1699
- 0,
1700
- 0,
1701
- 0,
1702
- 0,
1703
- 0,
1704
- 0,
1705
- 24,
1706
- 0,
1707
- 0,
1708
- 0,
1709
- 0,
1710
- 0,
1711
- 0,
1712
- 20
1713
- ];
1714
- var RAYS = [
1715
- 17,
1716
- 0,
1717
- 0,
1718
- 0,
1719
- 0,
1720
- 0,
1721
- 0,
1722
- 16,
1723
- 0,
1724
- 0,
1725
- 0,
1726
- 0,
1727
- 0,
1728
- 0,
1729
- 15,
1730
- 0,
1731
- 0,
1732
- 17,
1733
- 0,
1734
- 0,
1735
- 0,
1736
- 0,
1737
- 0,
1738
- 16,
1739
- 0,
1740
- 0,
1741
- 0,
1742
- 0,
1743
- 0,
1744
- 15,
1745
- 0,
1746
- 0,
1747
- 0,
1748
- 0,
1749
- 17,
1750
- 0,
1751
- 0,
1752
- 0,
1753
- 0,
1754
- 16,
1755
- 0,
1756
- 0,
1757
- 0,
1758
- 0,
1759
- 15,
1760
- 0,
1761
- 0,
1762
- 0,
1763
- 0,
1764
- 0,
1765
- 0,
1766
- 17,
1767
- 0,
1768
- 0,
1769
- 0,
1770
- 16,
1771
- 0,
1772
- 0,
1773
- 0,
1774
- 15,
1775
- 0,
1776
- 0,
1777
- 0,
1778
- 0,
1779
- 0,
1780
- 0,
1781
- 0,
1782
- 0,
1783
- 17,
1784
- 0,
1785
- 0,
1786
- 16,
1787
- 0,
1788
- 0,
1789
- 15,
1790
- 0,
1791
- 0,
1792
- 0,
1793
- 0,
1794
- 0,
1795
- 0,
1796
- 0,
1797
- 0,
1798
- 0,
1799
- 0,
1800
- 17,
1801
- 0,
1802
- 16,
1803
- 0,
1804
- 15,
1805
- 0,
1806
- 0,
1807
- 0,
1808
- 0,
1809
- 0,
1810
- 0,
1811
- 0,
1812
- 0,
1813
- 0,
1814
- 0,
1815
- 0,
1816
- 0,
1817
- 17,
1818
- 16,
1819
- 15,
1820
- 0,
1821
- 0,
1822
- 0,
1823
- 0,
1824
- 0,
1825
- 0,
1826
- 0,
1827
- 1,
1828
- 1,
1829
- 1,
1830
- 1,
1831
- 1,
1832
- 1,
1833
- 1,
1834
- 0,
1835
- -1,
1836
- -1,
1837
- -1,
1838
- -1,
1839
- -1,
1840
- -1,
1841
- -1,
1842
- 0,
1843
- 0,
1844
- 0,
1845
- 0,
1846
- 0,
1847
- 0,
1848
- 0,
1849
- -15,
1850
- -16,
1851
- -17,
1852
- 0,
1853
- 0,
1854
- 0,
1855
- 0,
1856
- 0,
1857
- 0,
1858
- 0,
1859
- 0,
1860
- 0,
1861
- 0,
1862
- 0,
1863
- 0,
1864
- -15,
1865
- 0,
1866
- -16,
1867
- 0,
1868
- -17,
1869
- 0,
1870
- 0,
1871
- 0,
1872
- 0,
1873
- 0,
1874
- 0,
1875
- 0,
1876
- 0,
1877
- 0,
1878
- 0,
1879
- -15,
1880
- 0,
1881
- 0,
1882
- -16,
1883
- 0,
1884
- 0,
1885
- -17,
1886
- 0,
1887
- 0,
1888
- 0,
1889
- 0,
1890
- 0,
1891
- 0,
1892
- 0,
1893
- 0,
1894
- -15,
1895
- 0,
1896
- 0,
1897
- 0,
1898
- -16,
1899
- 0,
1900
- 0,
1901
- 0,
1902
- -17,
1903
- 0,
1904
- 0,
1905
- 0,
1906
- 0,
1907
- 0,
1908
- 0,
1909
- -15,
1910
- 0,
1911
- 0,
1912
- 0,
1913
- 0,
1914
- -16,
1915
- 0,
1916
- 0,
1917
- 0,
1918
- 0,
1919
- -17,
1920
- 0,
1921
- 0,
1922
- 0,
1923
- 0,
1924
- -15,
1925
- 0,
1926
- 0,
1927
- 0,
1928
- 0,
1929
- 0,
1930
- -16,
1931
- 0,
1932
- 0,
1933
- 0,
1934
- 0,
1935
- 0,
1936
- -17,
1937
- 0,
1938
- 0,
1939
- -15,
1940
- 0,
1941
- 0,
1942
- 0,
1943
- 0,
1944
- 0,
1945
- 0,
1946
- -16,
1947
- 0,
1948
- 0,
1949
- 0,
1950
- 0,
1951
- 0,
1952
- 0,
1953
- -17
1954
- ];
1955
- var PIECE_MASKS = { p: 1, n: 2, b: 4, r: 8, q: 16, k: 32 };
1956
- var SYMBOLS = "pnbrqkPNBRQK";
1957
- var PROMOTIONS = [KNIGHT, BISHOP, ROOK, QUEEN];
1958
- var RANK_1 = 7;
1959
- var RANK_2 = 6;
1960
- var RANK_7 = 1;
1961
- var RANK_8 = 0;
1962
- var SIDES = {
1963
- [KING]: BITS.KSIDE_CASTLE,
1964
- [QUEEN]: BITS.QSIDE_CASTLE
1965
- };
1966
- var ROOKS = {
1967
- w: [
1968
- { square: Ox88.a1, flag: BITS.QSIDE_CASTLE },
1969
- { square: Ox88.h1, flag: BITS.KSIDE_CASTLE }
1970
- ],
1971
- b: [
1972
- { square: Ox88.a8, flag: BITS.QSIDE_CASTLE },
1973
- { square: Ox88.h8, flag: BITS.KSIDE_CASTLE }
1974
- ]
1975
- };
1976
- var SECOND_RANK = { b: RANK_7, w: RANK_2 };
1977
- var SAN_NULLMOVE = "--";
1978
- function rank(square) {
1979
- return square >> 4;
1980
- }
1981
- function file(square) {
1982
- return square & 15;
1983
- }
1984
- function isDigit(c) {
1985
- return "0123456789".indexOf(c) !== -1;
1986
- }
1987
- function algebraic(square) {
1988
- const f = file(square);
1989
- const r = rank(square);
1990
- return "abcdefgh".substring(f, f + 1) + "87654321".substring(r, r + 1);
1991
- }
1992
- function swapColor(color) {
1993
- return color === WHITE ? BLACK : WHITE;
1994
- }
1995
- function validateFen(fen) {
1996
- const tokens = fen.split(/\s+/);
1997
- if (tokens.length !== 6) {
1998
- return {
1999
- ok: false,
2000
- error: "Invalid FEN: must contain six space-delimited fields"
2001
- };
2002
- }
2003
- const moveNumber = parseInt(tokens[5], 10);
2004
- if (isNaN(moveNumber) || moveNumber <= 0) {
2005
- return {
2006
- ok: false,
2007
- error: "Invalid FEN: move number must be a positive integer"
2008
- };
2009
- }
2010
- const halfMoves = parseInt(tokens[4], 10);
2011
- if (isNaN(halfMoves) || halfMoves < 0) {
2012
- return {
2013
- ok: false,
2014
- error: "Invalid FEN: half move counter number must be a non-negative integer"
2015
- };
2016
- }
2017
- if (!/^(-|[abcdefgh][36])$/.test(tokens[3])) {
2018
- return { ok: false, error: "Invalid FEN: en-passant square is invalid" };
2019
- }
2020
- if (/[^kKqQ-]/.test(tokens[2])) {
2021
- return { ok: false, error: "Invalid FEN: castling availability is invalid" };
2022
- }
2023
- if (!/^(w|b)$/.test(tokens[1])) {
2024
- return { ok: false, error: "Invalid FEN: side-to-move is invalid" };
2025
- }
2026
- const rows = tokens[0].split("/");
2027
- if (rows.length !== 8) {
2028
- return {
2029
- ok: false,
2030
- error: "Invalid FEN: piece data does not contain 8 '/'-delimited rows"
2031
- };
2032
- }
2033
- for (let i = 0;i < rows.length; i++) {
2034
- let sumFields = 0;
2035
- let previousWasNumber = false;
2036
- for (let k = 0;k < rows[i].length; k++) {
2037
- if (isDigit(rows[i][k])) {
2038
- if (previousWasNumber) {
2039
- return {
2040
- ok: false,
2041
- error: "Invalid FEN: piece data is invalid (consecutive number)"
2042
- };
2043
- }
2044
- sumFields += parseInt(rows[i][k], 10);
2045
- previousWasNumber = true;
2046
- } else {
2047
- if (!/^[prnbqkPRNBQK]$/.test(rows[i][k])) {
2048
- return {
2049
- ok: false,
2050
- error: "Invalid FEN: piece data is invalid (invalid piece)"
2051
- };
2052
- }
2053
- sumFields += 1;
2054
- previousWasNumber = false;
2055
- }
2056
- }
2057
- if (sumFields !== 8) {
2058
- return {
2059
- ok: false,
2060
- error: "Invalid FEN: piece data is invalid (too many squares in rank)"
2061
- };
2062
- }
2063
- }
2064
- if (tokens[3][1] == "3" && tokens[1] == "w" || tokens[3][1] == "6" && tokens[1] == "b") {
2065
- return { ok: false, error: "Invalid FEN: illegal en-passant square" };
2066
- }
2067
- const kings = [
2068
- { color: "white", regex: /K/g },
2069
- { color: "black", regex: /k/g }
2070
- ];
2071
- for (const { color, regex } of kings) {
2072
- if (!regex.test(tokens[0])) {
2073
- return { ok: false, error: `Invalid FEN: missing ${color} king` };
2074
- }
2075
- if ((tokens[0].match(regex) || []).length > 1) {
2076
- return { ok: false, error: `Invalid FEN: too many ${color} kings` };
2077
- }
2078
- }
2079
- if (Array.from(rows[0] + rows[7]).some((char) => char.toUpperCase() === "P")) {
2080
- return {
2081
- ok: false,
2082
- error: "Invalid FEN: some pawns are on the edge rows"
2083
- };
2084
- }
2085
- return { ok: true };
2086
- }
2087
- function getDisambiguator(move, moves) {
2088
- const from = move.from;
2089
- const to = move.to;
2090
- const piece = move.piece;
2091
- let ambiguities = 0;
2092
- let sameRank = 0;
2093
- let sameFile = 0;
2094
- for (let i = 0, len = moves.length;i < len; i++) {
2095
- const ambigFrom = moves[i].from;
2096
- const ambigTo = moves[i].to;
2097
- const ambigPiece = moves[i].piece;
2098
- if (piece === ambigPiece && from !== ambigFrom && to === ambigTo) {
2099
- ambiguities++;
2100
- if (rank(from) === rank(ambigFrom)) {
2101
- sameRank++;
2102
- }
2103
- if (file(from) === file(ambigFrom)) {
2104
- sameFile++;
2105
- }
2106
- }
2107
- }
2108
- if (ambiguities > 0) {
2109
- if (sameRank > 0 && sameFile > 0) {
2110
- return algebraic(from);
2111
- } else if (sameFile > 0) {
2112
- return algebraic(from).charAt(1);
2113
- } else {
2114
- return algebraic(from).charAt(0);
2115
- }
2116
- }
2117
- return "";
2118
- }
2119
- function addMove(moves, color, from, to, piece, captured = undefined, flags = BITS.NORMAL) {
2120
- const r = rank(to);
2121
- if (piece === PAWN && (r === RANK_1 || r === RANK_8)) {
2122
- for (let i = 0;i < PROMOTIONS.length; i++) {
2123
- const promotion = PROMOTIONS[i];
2124
- moves.push({
2125
- color,
2126
- from,
2127
- to,
2128
- piece,
2129
- captured,
2130
- promotion,
2131
- flags: flags | BITS.PROMOTION
2132
- });
2133
- }
2134
- } else {
2135
- moves.push({
2136
- color,
2137
- from,
2138
- to,
2139
- piece,
2140
- captured,
2141
- flags
2142
- });
2143
- }
2144
- }
2145
- function inferPieceType(san) {
2146
- let pieceType = san.charAt(0);
2147
- if (pieceType >= "a" && pieceType <= "h") {
2148
- const matches = san.match(/[a-h]\d.*[a-h]\d/);
2149
- if (matches) {
2150
- return;
2151
- }
2152
- return PAWN;
2153
- }
2154
- pieceType = pieceType.toLowerCase();
2155
- if (pieceType === "o") {
2156
- return KING;
2157
- }
2158
- return pieceType;
2159
- }
2160
- function strippedSan(move) {
2161
- return move.replace(/=/, "").replace(/[+#]?[?!]*$/, "");
2162
- }
2163
-
2164
- class Chess {
2165
- _board = new Array(128);
2166
- _turn = WHITE;
2167
- _header = {};
2168
- _kings = { w: EMPTY, b: EMPTY };
2169
- _epSquare = -1;
2170
- _halfMoves = 0;
2171
- _moveNumber = 0;
2172
- _history = [];
2173
- _comments = {};
2174
- _castling = { w: 0, b: 0 };
2175
- _hash = 0n;
2176
- _positionCount = new Map;
2177
- constructor(fen = DEFAULT_POSITION, { skipValidation = false } = {}) {
2178
- this.load(fen, { skipValidation });
2179
- }
2180
- clear({ preserveHeaders = false } = {}) {
2181
- this._board = new Array(128);
2182
- this._kings = { w: EMPTY, b: EMPTY };
2183
- this._turn = WHITE;
2184
- this._castling = { w: 0, b: 0 };
2185
- this._epSquare = EMPTY;
2186
- this._halfMoves = 0;
2187
- this._moveNumber = 1;
2188
- this._history = [];
2189
- this._comments = {};
2190
- this._header = preserveHeaders ? this._header : { ...HEADER_TEMPLATE };
2191
- this._hash = this._computeHash();
2192
- this._positionCount = new Map;
2193
- this._header["SetUp"] = null;
2194
- this._header["FEN"] = null;
2195
- }
2196
- load(fen, { skipValidation = false, preserveHeaders = false } = {}) {
2197
- let tokens = fen.split(/\s+/);
2198
- if (tokens.length >= 2 && tokens.length < 6) {
2199
- const adjustments = ["-", "-", "0", "1"];
2200
- fen = tokens.concat(adjustments.slice(-(6 - tokens.length))).join(" ");
2201
- }
2202
- tokens = fen.split(/\s+/);
2203
- if (!skipValidation) {
2204
- const { ok, error } = validateFen(fen);
2205
- if (!ok) {
2206
- throw new Error(error);
2207
- }
2208
- }
2209
- const position = tokens[0];
2210
- let square = 0;
2211
- this.clear({ preserveHeaders });
2212
- for (let i = 0;i < position.length; i++) {
2213
- const piece = position.charAt(i);
2214
- if (piece === "/") {
2215
- square += 8;
2216
- } else if (isDigit(piece)) {
2217
- square += parseInt(piece, 10);
2218
- } else {
2219
- const color = piece < "a" ? WHITE : BLACK;
2220
- this._put({ type: piece.toLowerCase(), color }, algebraic(square));
2221
- square++;
2222
- }
2223
- }
2224
- this._turn = tokens[1];
2225
- if (tokens[2].indexOf("K") > -1) {
2226
- this._castling.w |= BITS.KSIDE_CASTLE;
2227
- }
2228
- if (tokens[2].indexOf("Q") > -1) {
2229
- this._castling.w |= BITS.QSIDE_CASTLE;
2230
- }
2231
- if (tokens[2].indexOf("k") > -1) {
2232
- this._castling.b |= BITS.KSIDE_CASTLE;
2233
- }
2234
- if (tokens[2].indexOf("q") > -1) {
2235
- this._castling.b |= BITS.QSIDE_CASTLE;
2236
- }
2237
- this._epSquare = tokens[3] === "-" ? EMPTY : Ox88[tokens[3]];
2238
- this._halfMoves = parseInt(tokens[4], 10);
2239
- this._moveNumber = parseInt(tokens[5], 10);
2240
- this._hash = this._computeHash();
2241
- this._updateSetup(fen);
2242
- this._incPositionCount();
2243
- }
2244
- fen({ forceEnpassantSquare = false } = {}) {
2245
- let empty = 0;
2246
- let fen = "";
2247
- for (let i = Ox88.a8;i <= Ox88.h1; i++) {
2248
- if (this._board[i]) {
2249
- if (empty > 0) {
2250
- fen += empty;
2251
- empty = 0;
2252
- }
2253
- const { color, type: piece } = this._board[i];
2254
- fen += color === WHITE ? piece.toUpperCase() : piece.toLowerCase();
2255
- } else {
2256
- empty++;
2257
- }
2258
- if (i + 1 & 136) {
2259
- if (empty > 0) {
2260
- fen += empty;
2261
- }
2262
- if (i !== Ox88.h1) {
2263
- fen += "/";
2264
- }
2265
- empty = 0;
2266
- i += 8;
2267
- }
2268
- }
2269
- let castling = "";
2270
- if (this._castling[WHITE] & BITS.KSIDE_CASTLE) {
2271
- castling += "K";
2272
- }
2273
- if (this._castling[WHITE] & BITS.QSIDE_CASTLE) {
2274
- castling += "Q";
2275
- }
2276
- if (this._castling[BLACK] & BITS.KSIDE_CASTLE) {
2277
- castling += "k";
2278
- }
2279
- if (this._castling[BLACK] & BITS.QSIDE_CASTLE) {
2280
- castling += "q";
2281
- }
2282
- castling = castling || "-";
2283
- let epSquare = "-";
2284
- if (this._epSquare !== EMPTY) {
2285
- if (forceEnpassantSquare) {
2286
- epSquare = algebraic(this._epSquare);
2287
- } else {
2288
- const bigPawnSquare = this._epSquare + (this._turn === WHITE ? 16 : -16);
2289
- const squares = [bigPawnSquare + 1, bigPawnSquare - 1];
2290
- for (const square of squares) {
2291
- if (square & 136) {
2292
- continue;
2293
- }
2294
- const color = this._turn;
2295
- if (this._board[square]?.color === color && this._board[square]?.type === PAWN) {
2296
- this._makeMove({
2297
- color,
2298
- from: square,
2299
- to: this._epSquare,
2300
- piece: PAWN,
2301
- captured: PAWN,
2302
- flags: BITS.EP_CAPTURE
2303
- });
2304
- const isLegal = !this._isKingAttacked(color);
2305
- this._undoMove();
2306
- if (isLegal) {
2307
- epSquare = algebraic(this._epSquare);
2308
- break;
2309
- }
2310
- }
2311
- }
2312
- }
2313
- }
2314
- return [
2315
- fen,
2316
- this._turn,
2317
- castling,
2318
- epSquare,
2319
- this._halfMoves,
2320
- this._moveNumber
2321
- ].join(" ");
2322
- }
2323
- _pieceKey(i) {
2324
- if (!this._board[i]) {
2325
- return 0n;
2326
- }
2327
- const { color, type } = this._board[i];
2328
- const colorIndex = {
2329
- w: 0,
2330
- b: 1
2331
- }[color];
2332
- const typeIndex = {
2333
- p: 0,
2334
- n: 1,
2335
- b: 2,
2336
- r: 3,
2337
- q: 4,
2338
- k: 5
2339
- }[type];
2340
- return PIECE_KEYS[colorIndex][typeIndex][i];
2341
- }
2342
- _epKey() {
2343
- return this._epSquare === EMPTY ? 0n : EP_KEYS[this._epSquare & 7];
2344
- }
2345
- _castlingKey() {
2346
- const index = this._castling.w >> 5 | this._castling.b >> 3;
2347
- return CASTLING_KEYS[index];
2348
- }
2349
- _computeHash() {
2350
- let hash = 0n;
2351
- for (let i = Ox88.a8;i <= Ox88.h1; i++) {
2352
- if (i & 136) {
2353
- i += 7;
2354
- continue;
2355
- }
2356
- if (this._board[i]) {
2357
- hash ^= this._pieceKey(i);
2358
- }
2359
- }
2360
- hash ^= this._epKey();
2361
- hash ^= this._castlingKey();
2362
- if (this._turn === "b") {
2363
- hash ^= SIDE_KEY;
2364
- }
2365
- return hash;
2366
- }
2367
- _updateSetup(fen) {
2368
- if (this._history.length > 0)
2369
- return;
2370
- if (fen !== DEFAULT_POSITION) {
2371
- this._header["SetUp"] = "1";
2372
- this._header["FEN"] = fen;
2373
- } else {
2374
- this._header["SetUp"] = null;
2375
- this._header["FEN"] = null;
2376
- }
2377
- }
2378
- reset() {
2379
- this.load(DEFAULT_POSITION);
2380
- }
2381
- get(square) {
2382
- return this._board[Ox88[square]];
2383
- }
2384
- findPiece(piece) {
2385
- const squares = [];
2386
- for (let i = Ox88.a8;i <= Ox88.h1; i++) {
2387
- if (i & 136) {
2388
- i += 7;
2389
- continue;
2390
- }
2391
- if (!this._board[i] || this._board[i]?.color !== piece.color) {
2392
- continue;
2393
- }
2394
- if (this._board[i].color === piece.color && this._board[i].type === piece.type) {
2395
- squares.push(algebraic(i));
2396
- }
2397
- }
2398
- return squares;
2399
- }
2400
- put({ type, color }, square) {
2401
- if (this._put({ type, color }, square)) {
2402
- this._updateCastlingRights();
2403
- this._updateEnPassantSquare();
2404
- this._updateSetup(this.fen());
2405
- return true;
2406
- }
2407
- return false;
2408
- }
2409
- _set(sq, piece) {
2410
- this._hash ^= this._pieceKey(sq);
2411
- this._board[sq] = piece;
2412
- this._hash ^= this._pieceKey(sq);
2413
- }
2414
- _put({ type, color }, square) {
2415
- if (SYMBOLS.indexOf(type.toLowerCase()) === -1) {
2416
- return false;
2417
- }
2418
- if (!(square in Ox88)) {
2419
- return false;
2420
- }
2421
- const sq = Ox88[square];
2422
- if (type == KING && !(this._kings[color] == EMPTY || this._kings[color] == sq)) {
2423
- return false;
2424
- }
2425
- const currentPieceOnSquare = this._board[sq];
2426
- if (currentPieceOnSquare && currentPieceOnSquare.type === KING) {
2427
- this._kings[currentPieceOnSquare.color] = EMPTY;
2428
- }
2429
- this._set(sq, { type, color });
2430
- if (type === KING) {
2431
- this._kings[color] = sq;
2432
- }
2433
- return true;
2434
- }
2435
- _clear(sq) {
2436
- this._hash ^= this._pieceKey(sq);
2437
- delete this._board[sq];
2438
- }
2439
- remove(square) {
2440
- const piece = this.get(square);
2441
- this._clear(Ox88[square]);
2442
- if (piece && piece.type === KING) {
2443
- this._kings[piece.color] = EMPTY;
2444
- }
2445
- this._updateCastlingRights();
2446
- this._updateEnPassantSquare();
2447
- this._updateSetup(this.fen());
2448
- return piece;
2449
- }
2450
- _updateCastlingRights() {
2451
- this._hash ^= this._castlingKey();
2452
- const whiteKingInPlace = this._board[Ox88.e1]?.type === KING && this._board[Ox88.e1]?.color === WHITE;
2453
- const blackKingInPlace = this._board[Ox88.e8]?.type === KING && this._board[Ox88.e8]?.color === BLACK;
2454
- if (!whiteKingInPlace || this._board[Ox88.a1]?.type !== ROOK || this._board[Ox88.a1]?.color !== WHITE) {
2455
- this._castling.w &= -65;
2456
- }
2457
- if (!whiteKingInPlace || this._board[Ox88.h1]?.type !== ROOK || this._board[Ox88.h1]?.color !== WHITE) {
2458
- this._castling.w &= -33;
2459
- }
2460
- if (!blackKingInPlace || this._board[Ox88.a8]?.type !== ROOK || this._board[Ox88.a8]?.color !== BLACK) {
2461
- this._castling.b &= -65;
2462
- }
2463
- if (!blackKingInPlace || this._board[Ox88.h8]?.type !== ROOK || this._board[Ox88.h8]?.color !== BLACK) {
2464
- this._castling.b &= -33;
2465
- }
2466
- this._hash ^= this._castlingKey();
2467
- }
2468
- _updateEnPassantSquare() {
2469
- if (this._epSquare === EMPTY) {
2470
- return;
2471
- }
2472
- const startSquare = this._epSquare + (this._turn === WHITE ? -16 : 16);
2473
- const currentSquare = this._epSquare + (this._turn === WHITE ? 16 : -16);
2474
- const attackers = [currentSquare + 1, currentSquare - 1];
2475
- if (this._board[startSquare] !== null || this._board[this._epSquare] !== null || this._board[currentSquare]?.color !== swapColor(this._turn) || this._board[currentSquare]?.type !== PAWN) {
2476
- this._hash ^= this._epKey();
2477
- this._epSquare = EMPTY;
2478
- return;
2479
- }
2480
- const canCapture = (square) => !(square & 136) && this._board[square]?.color === this._turn && this._board[square]?.type === PAWN;
2481
- if (!attackers.some(canCapture)) {
2482
- this._hash ^= this._epKey();
2483
- this._epSquare = EMPTY;
2484
- }
2485
- }
2486
- _attacked(color, square, verbose) {
2487
- const attackers = [];
2488
- for (let i = Ox88.a8;i <= Ox88.h1; i++) {
2489
- if (i & 136) {
2490
- i += 7;
2491
- continue;
2492
- }
2493
- if (this._board[i] === undefined || this._board[i].color !== color) {
2494
- continue;
2495
- }
2496
- const piece = this._board[i];
2497
- const difference = i - square;
2498
- if (difference === 0) {
2499
- continue;
2500
- }
2501
- const index = difference + 119;
2502
- if (ATTACKS[index] & PIECE_MASKS[piece.type]) {
2503
- if (piece.type === PAWN) {
2504
- if (difference > 0 && piece.color === WHITE || difference <= 0 && piece.color === BLACK) {
2505
- if (!verbose) {
2506
- return true;
2507
- } else {
2508
- attackers.push(algebraic(i));
2509
- }
2510
- }
2511
- continue;
2512
- }
2513
- if (piece.type === "n" || piece.type === "k") {
2514
- if (!verbose) {
2515
- return true;
2516
- } else {
2517
- attackers.push(algebraic(i));
2518
- continue;
2519
- }
2520
- }
2521
- const offset = RAYS[index];
2522
- let j = i + offset;
2523
- let blocked = false;
2524
- while (j !== square) {
2525
- if (this._board[j] != null) {
2526
- blocked = true;
2527
- break;
2528
- }
2529
- j += offset;
2530
- }
2531
- if (!blocked) {
2532
- if (!verbose) {
2533
- return true;
2534
- } else {
2535
- attackers.push(algebraic(i));
2536
- continue;
2537
- }
2538
- }
2539
- }
2540
- }
2541
- if (verbose) {
2542
- return attackers;
2543
- } else {
2544
- return false;
2545
- }
2546
- }
2547
- attackers(square, attackedBy) {
2548
- if (!attackedBy) {
2549
- return this._attacked(this._turn, Ox88[square], true);
2550
- } else {
2551
- return this._attacked(attackedBy, Ox88[square], true);
2552
- }
2553
- }
2554
- _isKingAttacked(color) {
2555
- const square = this._kings[color];
2556
- return square === -1 ? false : this._attacked(swapColor(color), square);
2557
- }
2558
- hash() {
2559
- return this._hash.toString(16);
2560
- }
2561
- isAttacked(square, attackedBy) {
2562
- return this._attacked(attackedBy, Ox88[square]);
2563
- }
2564
- isCheck() {
2565
- return this._isKingAttacked(this._turn);
2566
- }
2567
- inCheck() {
2568
- return this.isCheck();
2569
- }
2570
- isCheckmate() {
2571
- return this.isCheck() && this._moves().length === 0;
2572
- }
2573
- isStalemate() {
2574
- return !this.isCheck() && this._moves().length === 0;
2575
- }
2576
- isInsufficientMaterial() {
2577
- const pieces = {
2578
- b: 0,
2579
- n: 0,
2580
- r: 0,
2581
- q: 0,
2582
- k: 0,
2583
- p: 0
2584
- };
2585
- const bishops = [];
2586
- let numPieces = 0;
2587
- let squareColor = 0;
2588
- for (let i = Ox88.a8;i <= Ox88.h1; i++) {
2589
- squareColor = (squareColor + 1) % 2;
2590
- if (i & 136) {
2591
- i += 7;
2592
- continue;
2593
- }
2594
- const piece = this._board[i];
2595
- if (piece) {
2596
- pieces[piece.type] = piece.type in pieces ? pieces[piece.type] + 1 : 1;
2597
- if (piece.type === BISHOP) {
2598
- bishops.push(squareColor);
2599
- }
2600
- numPieces++;
2601
- }
2602
- }
2603
- if (numPieces === 2) {
2604
- return true;
2605
- } else if (numPieces === 3 && (pieces[BISHOP] === 1 || pieces[KNIGHT] === 1)) {
2606
- return true;
2607
- } else if (numPieces === pieces[BISHOP] + 2) {
2608
- let sum = 0;
2609
- const len = bishops.length;
2610
- for (let i = 0;i < len; i++) {
2611
- sum += bishops[i];
2612
- }
2613
- if (sum === 0 || sum === len) {
2614
- return true;
2615
- }
2616
- }
2617
- return false;
2618
- }
2619
- isThreefoldRepetition() {
2620
- return this._getPositionCount(this._hash) >= 3;
2621
- }
2622
- isDrawByFiftyMoves() {
2623
- return this._halfMoves >= 100;
2624
- }
2625
- isDraw() {
2626
- return this.isDrawByFiftyMoves() || this.isStalemate() || this.isInsufficientMaterial() || this.isThreefoldRepetition();
2627
- }
2628
- isGameOver() {
2629
- return this.isCheckmate() || this.isDraw();
2630
- }
2631
- moves({ verbose = false, square = undefined, piece = undefined } = {}) {
2632
- const moves = this._moves({ square, piece });
2633
- if (verbose) {
2634
- return moves.map((move) => new Move(this, move));
2635
- } else {
2636
- return moves.map((move) => this._moveToSan(move, moves));
2637
- }
2638
- }
2639
- _moves({ legal = true, piece = undefined, square = undefined } = {}) {
2640
- const forSquare = square ? square.toLowerCase() : undefined;
2641
- const forPiece = piece?.toLowerCase();
2642
- const moves = [];
2643
- const us = this._turn;
2644
- const them = swapColor(us);
2645
- let firstSquare = Ox88.a8;
2646
- let lastSquare = Ox88.h1;
2647
- let singleSquare = false;
2648
- if (forSquare) {
2649
- if (!(forSquare in Ox88)) {
2650
- return [];
2651
- } else {
2652
- firstSquare = lastSquare = Ox88[forSquare];
2653
- singleSquare = true;
2654
- }
2655
- }
2656
- for (let from = firstSquare;from <= lastSquare; from++) {
2657
- if (from & 136) {
2658
- from += 7;
2659
- continue;
2660
- }
2661
- if (!this._board[from] || this._board[from].color === them) {
2662
- continue;
2663
- }
2664
- const { type } = this._board[from];
2665
- let to;
2666
- if (type === PAWN) {
2667
- if (forPiece && forPiece !== type)
2668
- continue;
2669
- to = from + PAWN_OFFSETS[us][0];
2670
- if (!this._board[to]) {
2671
- addMove(moves, us, from, to, PAWN);
2672
- to = from + PAWN_OFFSETS[us][1];
2673
- if (SECOND_RANK[us] === rank(from) && !this._board[to]) {
2674
- addMove(moves, us, from, to, PAWN, undefined, BITS.BIG_PAWN);
2675
- }
2676
- }
2677
- for (let j = 2;j < 4; j++) {
2678
- to = from + PAWN_OFFSETS[us][j];
2679
- if (to & 136)
2680
- continue;
2681
- if (this._board[to]?.color === them) {
2682
- addMove(moves, us, from, to, PAWN, this._board[to].type, BITS.CAPTURE);
2683
- } else if (to === this._epSquare) {
2684
- addMove(moves, us, from, to, PAWN, PAWN, BITS.EP_CAPTURE);
2685
- }
2686
- }
2687
- } else {
2688
- if (forPiece && forPiece !== type)
2689
- continue;
2690
- for (let j = 0, len = PIECE_OFFSETS[type].length;j < len; j++) {
2691
- const offset = PIECE_OFFSETS[type][j];
2692
- to = from;
2693
- while (true) {
2694
- to += offset;
2695
- if (to & 136)
2696
- break;
2697
- if (!this._board[to]) {
2698
- addMove(moves, us, from, to, type);
2699
- } else {
2700
- if (this._board[to].color === us)
2701
- break;
2702
- addMove(moves, us, from, to, type, this._board[to].type, BITS.CAPTURE);
2703
- break;
2704
- }
2705
- if (type === KNIGHT || type === KING)
2706
- break;
2707
- }
2708
- }
2709
- }
2710
- }
2711
- if (forPiece === undefined || forPiece === KING) {
2712
- if (!singleSquare || lastSquare === this._kings[us]) {
2713
- if (this._castling[us] & BITS.KSIDE_CASTLE) {
2714
- const castlingFrom = this._kings[us];
2715
- const castlingTo = castlingFrom + 2;
2716
- if (!this._board[castlingFrom + 1] && !this._board[castlingTo] && !this._attacked(them, this._kings[us]) && !this._attacked(them, castlingFrom + 1) && !this._attacked(them, castlingTo)) {
2717
- addMove(moves, us, this._kings[us], castlingTo, KING, undefined, BITS.KSIDE_CASTLE);
2718
- }
2719
- }
2720
- if (this._castling[us] & BITS.QSIDE_CASTLE) {
2721
- const castlingFrom = this._kings[us];
2722
- const castlingTo = castlingFrom - 2;
2723
- if (!this._board[castlingFrom - 1] && !this._board[castlingFrom - 2] && !this._board[castlingFrom - 3] && !this._attacked(them, this._kings[us]) && !this._attacked(them, castlingFrom - 1) && !this._attacked(them, castlingTo)) {
2724
- addMove(moves, us, this._kings[us], castlingTo, KING, undefined, BITS.QSIDE_CASTLE);
2725
- }
2726
- }
2727
- }
2728
- }
2729
- if (!legal || this._kings[us] === -1) {
2730
- return moves;
2731
- }
2732
- const legalMoves = [];
2733
- for (let i = 0, len = moves.length;i < len; i++) {
2734
- this._makeMove(moves[i]);
2735
- if (!this._isKingAttacked(us)) {
2736
- legalMoves.push(moves[i]);
2737
- }
2738
- this._undoMove();
2739
- }
2740
- return legalMoves;
2741
- }
2742
- move(move, { strict = false } = {}) {
2743
- let moveObj = null;
2744
- if (typeof move === "string") {
2745
- moveObj = this._moveFromSan(move, strict);
2746
- } else if (move === null) {
2747
- moveObj = this._moveFromSan(SAN_NULLMOVE, strict);
2748
- } else if (typeof move === "object") {
2749
- const moves = this._moves();
2750
- for (let i = 0, len = moves.length;i < len; i++) {
2751
- if (move.from === algebraic(moves[i].from) && move.to === algebraic(moves[i].to) && (!("promotion" in moves[i]) || move.promotion === moves[i].promotion)) {
2752
- moveObj = moves[i];
2753
- break;
2754
- }
2755
- }
2756
- }
2757
- if (!moveObj) {
2758
- if (typeof move === "string") {
2759
- throw new Error(`Invalid move: ${move}`);
2760
- } else {
2761
- throw new Error(`Invalid move: ${JSON.stringify(move)}`);
2762
- }
2763
- }
2764
- if (this.isCheck() && moveObj.flags & BITS.NULL_MOVE) {
2765
- throw new Error("Null move not allowed when in check");
2766
- }
2767
- const prettyMove = new Move(this, moveObj);
2768
- this._makeMove(moveObj);
2769
- this._incPositionCount();
2770
- return prettyMove;
2771
- }
2772
- _push(move) {
2773
- this._history.push({
2774
- move,
2775
- kings: { b: this._kings.b, w: this._kings.w },
2776
- turn: this._turn,
2777
- castling: { b: this._castling.b, w: this._castling.w },
2778
- epSquare: this._epSquare,
2779
- halfMoves: this._halfMoves,
2780
- moveNumber: this._moveNumber
2781
- });
2782
- }
2783
- _movePiece(from, to) {
2784
- this._hash ^= this._pieceKey(from);
2785
- this._board[to] = this._board[from];
2786
- delete this._board[from];
2787
- this._hash ^= this._pieceKey(to);
2788
- }
2789
- _makeMove(move) {
2790
- const us = this._turn;
2791
- const them = swapColor(us);
2792
- this._push(move);
2793
- if (move.flags & BITS.NULL_MOVE) {
2794
- if (us === BLACK) {
2795
- this._moveNumber++;
2796
- }
2797
- this._halfMoves++;
2798
- this._turn = them;
2799
- this._epSquare = EMPTY;
2800
- return;
2801
- }
2802
- this._hash ^= this._epKey();
2803
- this._hash ^= this._castlingKey();
2804
- if (move.captured) {
2805
- this._hash ^= this._pieceKey(move.to);
2806
- }
2807
- this._movePiece(move.from, move.to);
2808
- if (move.flags & BITS.EP_CAPTURE) {
2809
- if (this._turn === BLACK) {
2810
- this._clear(move.to - 16);
2811
- } else {
2812
- this._clear(move.to + 16);
2813
- }
2814
- }
2815
- if (move.promotion) {
2816
- this._clear(move.to);
2817
- this._set(move.to, { type: move.promotion, color: us });
2818
- }
2819
- if (this._board[move.to].type === KING) {
2820
- this._kings[us] = move.to;
2821
- if (move.flags & BITS.KSIDE_CASTLE) {
2822
- const castlingTo = move.to - 1;
2823
- const castlingFrom = move.to + 1;
2824
- this._movePiece(castlingFrom, castlingTo);
2825
- } else if (move.flags & BITS.QSIDE_CASTLE) {
2826
- const castlingTo = move.to + 1;
2827
- const castlingFrom = move.to - 2;
2828
- this._movePiece(castlingFrom, castlingTo);
2829
- }
2830
- this._castling[us] = 0;
2831
- }
2832
- if (this._castling[us]) {
2833
- for (let i = 0, len = ROOKS[us].length;i < len; i++) {
2834
- if (move.from === ROOKS[us][i].square && this._castling[us] & ROOKS[us][i].flag) {
2835
- this._castling[us] ^= ROOKS[us][i].flag;
2836
- break;
2837
- }
2838
- }
2839
- }
2840
- if (this._castling[them]) {
2841
- for (let i = 0, len = ROOKS[them].length;i < len; i++) {
2842
- if (move.to === ROOKS[them][i].square && this._castling[them] & ROOKS[them][i].flag) {
2843
- this._castling[them] ^= ROOKS[them][i].flag;
2844
- break;
2845
- }
2846
- }
2847
- }
2848
- this._hash ^= this._castlingKey();
2849
- if (move.flags & BITS.BIG_PAWN) {
2850
- let epSquare;
2851
- if (us === BLACK) {
2852
- epSquare = move.to - 16;
2853
- } else {
2854
- epSquare = move.to + 16;
2855
- }
2856
- if (!(move.to - 1 & 136) && this._board[move.to - 1]?.type === PAWN && this._board[move.to - 1]?.color === them || !(move.to + 1 & 136) && this._board[move.to + 1]?.type === PAWN && this._board[move.to + 1]?.color === them) {
2857
- this._epSquare = epSquare;
2858
- this._hash ^= this._epKey();
2859
- } else {
2860
- this._epSquare = EMPTY;
2861
- }
2862
- } else {
2863
- this._epSquare = EMPTY;
2864
- }
2865
- if (move.piece === PAWN) {
2866
- this._halfMoves = 0;
2867
- } else if (move.flags & (BITS.CAPTURE | BITS.EP_CAPTURE)) {
2868
- this._halfMoves = 0;
2869
- } else {
2870
- this._halfMoves++;
2871
- }
2872
- if (us === BLACK) {
2873
- this._moveNumber++;
2874
- }
2875
- this._turn = them;
2876
- this._hash ^= SIDE_KEY;
2877
- }
2878
- undo() {
2879
- const hash = this._hash;
2880
- const move = this._undoMove();
2881
- if (move) {
2882
- const prettyMove = new Move(this, move);
2883
- this._decPositionCount(hash);
2884
- return prettyMove;
2885
- }
2886
- return null;
2887
- }
2888
- _undoMove() {
2889
- const old = this._history.pop();
2890
- if (old === undefined) {
2891
- return null;
2892
- }
2893
- this._hash ^= this._epKey();
2894
- this._hash ^= this._castlingKey();
2895
- const move = old.move;
2896
- this._kings = old.kings;
2897
- this._turn = old.turn;
2898
- this._castling = old.castling;
2899
- this._epSquare = old.epSquare;
2900
- this._halfMoves = old.halfMoves;
2901
- this._moveNumber = old.moveNumber;
2902
- this._hash ^= this._epKey();
2903
- this._hash ^= this._castlingKey();
2904
- this._hash ^= SIDE_KEY;
2905
- const us = this._turn;
2906
- const them = swapColor(us);
2907
- if (move.flags & BITS.NULL_MOVE) {
2908
- return move;
2909
- }
2910
- this._movePiece(move.to, move.from);
2911
- if (move.piece) {
2912
- this._clear(move.from);
2913
- this._set(move.from, { type: move.piece, color: us });
2914
- }
2915
- if (move.captured) {
2916
- if (move.flags & BITS.EP_CAPTURE) {
2917
- let index;
2918
- if (us === BLACK) {
2919
- index = move.to - 16;
2920
- } else {
2921
- index = move.to + 16;
2922
- }
2923
- this._set(index, { type: PAWN, color: them });
2924
- } else {
2925
- this._set(move.to, { type: move.captured, color: them });
2926
- }
2927
- }
2928
- if (move.flags & (BITS.KSIDE_CASTLE | BITS.QSIDE_CASTLE)) {
2929
- let castlingTo, castlingFrom;
2930
- if (move.flags & BITS.KSIDE_CASTLE) {
2931
- castlingTo = move.to + 1;
2932
- castlingFrom = move.to - 1;
2933
- } else {
2934
- castlingTo = move.to - 2;
2935
- castlingFrom = move.to + 1;
2936
- }
2937
- this._movePiece(castlingFrom, castlingTo);
2938
- }
2939
- return move;
2940
- }
2941
- pgn({ newline = `
2942
- `, maxWidth = 0 } = {}) {
2943
- const result = [];
2944
- let headerExists = false;
2945
- for (const i in this._header) {
2946
- const headerTag = this._header[i];
2947
- if (headerTag)
2948
- result.push(`[${i} "${this._header[i]}"]` + newline);
2949
- headerExists = true;
2950
- }
2951
- if (headerExists && this._history.length) {
2952
- result.push(newline);
2953
- }
2954
- const appendComment = (moveString) => {
2955
- const comment = this._comments[this.fen()];
2956
- if (typeof comment !== "undefined") {
2957
- const delimiter = moveString.length > 0 ? " " : "";
2958
- moveString = `${moveString}${delimiter}{${comment}}`;
2959
- }
2960
- return moveString;
2961
- };
2962
- const reversedHistory = [];
2963
- while (this._history.length > 0) {
2964
- reversedHistory.push(this._undoMove());
2965
- }
2966
- const moves = [];
2967
- let moveString = "";
2968
- if (reversedHistory.length === 0) {
2969
- moves.push(appendComment(""));
2970
- }
2971
- while (reversedHistory.length > 0) {
2972
- moveString = appendComment(moveString);
2973
- const move = reversedHistory.pop();
2974
- if (!move) {
2975
- break;
2976
- }
2977
- if (!this._history.length && move.color === "b") {
2978
- const prefix = `${this._moveNumber}. ...`;
2979
- moveString = moveString ? `${moveString} ${prefix}` : prefix;
2980
- } else if (move.color === "w") {
2981
- if (moveString.length) {
2982
- moves.push(moveString);
2983
- }
2984
- moveString = this._moveNumber + ".";
2985
- }
2986
- moveString = moveString + " " + this._moveToSan(move, this._moves({ legal: true }));
2987
- this._makeMove(move);
2988
- }
2989
- if (moveString.length) {
2990
- moves.push(appendComment(moveString));
2991
- }
2992
- moves.push(this._header.Result || "*");
2993
- if (maxWidth === 0) {
2994
- return result.join("") + moves.join(" ");
2995
- }
2996
- const strip = function() {
2997
- if (result.length > 0 && result[result.length - 1] === " ") {
2998
- result.pop();
2999
- return true;
3000
- }
3001
- return false;
3002
- };
3003
- const wrapComment = function(width, move) {
3004
- for (const token of move.split(" ")) {
3005
- if (!token) {
3006
- continue;
3007
- }
3008
- if (width + token.length > maxWidth) {
3009
- while (strip()) {
3010
- width--;
3011
- }
3012
- result.push(newline);
3013
- width = 0;
3014
- }
3015
- result.push(token);
3016
- width += token.length;
3017
- result.push(" ");
3018
- width++;
3019
- }
3020
- if (strip()) {
3021
- width--;
3022
- }
3023
- return width;
3024
- };
3025
- let currentWidth = 0;
3026
- for (let i = 0;i < moves.length; i++) {
3027
- if (currentWidth + moves[i].length > maxWidth) {
3028
- if (moves[i].includes("{")) {
3029
- currentWidth = wrapComment(currentWidth, moves[i]);
3030
- continue;
3031
- }
3032
- }
3033
- if (currentWidth + moves[i].length > maxWidth && i !== 0) {
3034
- if (result[result.length - 1] === " ") {
3035
- result.pop();
3036
- }
3037
- result.push(newline);
3038
- currentWidth = 0;
3039
- } else if (i !== 0) {
3040
- result.push(" ");
3041
- currentWidth++;
3042
- }
3043
- result.push(moves[i]);
3044
- currentWidth += moves[i].length;
3045
- }
3046
- return result.join("");
3047
- }
3048
- header(...args) {
3049
- for (let i = 0;i < args.length; i += 2) {
3050
- if (typeof args[i] === "string" && typeof args[i + 1] === "string") {
3051
- this._header[args[i]] = args[i + 1];
3052
- }
3053
- }
3054
- return this._header;
3055
- }
3056
- setHeader(key, value) {
3057
- this._header[key] = value ?? SEVEN_TAG_ROSTER[key] ?? null;
3058
- return this.getHeaders();
3059
- }
3060
- removeHeader(key) {
3061
- if (key in this._header) {
3062
- this._header[key] = SEVEN_TAG_ROSTER[key] || null;
3063
- return true;
3064
- }
3065
- return false;
3066
- }
3067
- getHeaders() {
3068
- const nonNullHeaders = {};
3069
- for (const [key, value] of Object.entries(this._header)) {
3070
- if (value !== null) {
3071
- nonNullHeaders[key] = value;
3072
- }
3073
- }
3074
- return nonNullHeaders;
3075
- }
3076
- loadPgn(pgn, { strict = false, newlineChar = `\r?
3077
- ` } = {}) {
3078
- if (newlineChar !== `\r?
3079
- `) {
3080
- pgn = pgn.replace(new RegExp(newlineChar, "g"), `
3081
- `);
3082
- }
3083
- const parsedPgn = peg$parse(pgn);
3084
- this.reset();
3085
- const headers = parsedPgn.headers;
3086
- let fen = "";
3087
- for (const key in headers) {
3088
- if (key.toLowerCase() === "fen") {
3089
- fen = headers[key];
3090
- }
3091
- this.header(key, headers[key]);
3092
- }
3093
- if (!strict) {
3094
- if (fen) {
3095
- this.load(fen, { preserveHeaders: true });
3096
- }
3097
- } else {
3098
- if (headers["SetUp"] === "1") {
3099
- if (!("FEN" in headers)) {
3100
- throw new Error("Invalid PGN: FEN tag must be supplied with SetUp tag");
3101
- }
3102
- this.load(headers["FEN"], { preserveHeaders: true });
3103
- }
3104
- }
3105
- let node = parsedPgn.root;
3106
- while (node) {
3107
- if (node.move) {
3108
- const move = this._moveFromSan(node.move, strict);
3109
- if (move == null) {
3110
- throw new Error(`Invalid move in PGN: ${node.move}`);
3111
- } else {
3112
- this._makeMove(move);
3113
- this._incPositionCount();
3114
- }
3115
- }
3116
- if (node.comment !== undefined) {
3117
- this._comments[this.fen()] = node.comment;
3118
- }
3119
- node = node.variations[0];
3120
- }
3121
- const result = parsedPgn.result;
3122
- if (result && Object.keys(this._header).length && this._header["Result"] !== result) {
3123
- this.setHeader("Result", result);
3124
- }
3125
- }
3126
- _moveToSan(move, moves) {
3127
- let output = "";
3128
- if (move.flags & BITS.KSIDE_CASTLE) {
3129
- output = "O-O";
3130
- } else if (move.flags & BITS.QSIDE_CASTLE) {
3131
- output = "O-O-O";
3132
- } else if (move.flags & BITS.NULL_MOVE) {
3133
- return SAN_NULLMOVE;
3134
- } else {
3135
- if (move.piece !== PAWN) {
3136
- const disambiguator = getDisambiguator(move, moves);
3137
- output += move.piece.toUpperCase() + disambiguator;
3138
- }
3139
- if (move.flags & (BITS.CAPTURE | BITS.EP_CAPTURE)) {
3140
- if (move.piece === PAWN) {
3141
- output += algebraic(move.from)[0];
3142
- }
3143
- output += "x";
3144
- }
3145
- output += algebraic(move.to);
3146
- if (move.promotion) {
3147
- output += "=" + move.promotion.toUpperCase();
3148
- }
3149
- }
3150
- this._makeMove(move);
3151
- if (this.isCheck()) {
3152
- if (this.isCheckmate()) {
3153
- output += "#";
3154
- } else {
3155
- output += "+";
3156
- }
3157
- }
3158
- this._undoMove();
3159
- return output;
3160
- }
3161
- _moveFromSan(move, strict = false) {
3162
- let cleanMove = strippedSan(move);
3163
- if (!strict) {
3164
- if (cleanMove === "0-0") {
3165
- cleanMove = "O-O";
3166
- } else if (cleanMove === "0-0-0") {
3167
- cleanMove = "O-O-O";
3168
- }
3169
- }
3170
- if (cleanMove == SAN_NULLMOVE) {
3171
- const res = {
3172
- color: this._turn,
3173
- from: 0,
3174
- to: 0,
3175
- piece: "k",
3176
- flags: BITS.NULL_MOVE
3177
- };
3178
- return res;
3179
- }
3180
- let pieceType = inferPieceType(cleanMove);
3181
- let moves = this._moves({ legal: true, piece: pieceType });
3182
- for (let i = 0, len = moves.length;i < len; i++) {
3183
- if (cleanMove === strippedSan(this._moveToSan(moves[i], moves))) {
3184
- return moves[i];
3185
- }
3186
- }
3187
- if (strict) {
3188
- return null;
3189
- }
3190
- let piece = undefined;
3191
- let matches = undefined;
3192
- let from = undefined;
3193
- let to = undefined;
3194
- let promotion = undefined;
3195
- let overlyDisambiguated = false;
3196
- matches = cleanMove.match(/([pnbrqkPNBRQK])?([a-h][1-8])x?-?([a-h][1-8])([qrbnQRBN])?/);
3197
- if (matches) {
3198
- piece = matches[1];
3199
- from = matches[2];
3200
- to = matches[3];
3201
- promotion = matches[4];
3202
- if (from.length == 1) {
3203
- overlyDisambiguated = true;
3204
- }
3205
- } else {
3206
- matches = cleanMove.match(/([pnbrqkPNBRQK])?([a-h]?[1-8]?)x?-?([a-h][1-8])([qrbnQRBN])?/);
3207
- if (matches) {
3208
- piece = matches[1];
3209
- from = matches[2];
3210
- to = matches[3];
3211
- promotion = matches[4];
3212
- if (from.length == 1) {
3213
- overlyDisambiguated = true;
3214
- }
3215
- }
3216
- }
3217
- pieceType = inferPieceType(cleanMove);
3218
- moves = this._moves({
3219
- legal: true,
3220
- piece: piece ? piece : pieceType
3221
- });
3222
- if (!to) {
3223
- return null;
3224
- }
3225
- for (let i = 0, len = moves.length;i < len; i++) {
3226
- if (!from) {
3227
- if (cleanMove === strippedSan(this._moveToSan(moves[i], moves)).replace("x", "")) {
3228
- return moves[i];
3229
- }
3230
- } else if ((!piece || piece.toLowerCase() == moves[i].piece) && Ox88[from] == moves[i].from && Ox88[to] == moves[i].to && (!promotion || promotion.toLowerCase() == moves[i].promotion)) {
3231
- return moves[i];
3232
- } else if (overlyDisambiguated) {
3233
- const square = algebraic(moves[i].from);
3234
- if ((!piece || piece.toLowerCase() == moves[i].piece) && Ox88[to] == moves[i].to && (from == square[0] || from == square[1]) && (!promotion || promotion.toLowerCase() == moves[i].promotion)) {
3235
- return moves[i];
3236
- }
3237
- }
3238
- }
3239
- return null;
3240
- }
3241
- ascii() {
3242
- let s = ` +------------------------+
3243
- `;
3244
- for (let i = Ox88.a8;i <= Ox88.h1; i++) {
3245
- if (file(i) === 0) {
3246
- s += " " + "87654321"[rank(i)] + " |";
3247
- }
3248
- if (this._board[i]) {
3249
- const piece = this._board[i].type;
3250
- const color = this._board[i].color;
3251
- const symbol = color === WHITE ? piece.toUpperCase() : piece.toLowerCase();
3252
- s += " " + symbol + " ";
3253
- } else {
3254
- s += " . ";
3255
- }
3256
- if (i + 1 & 136) {
3257
- s += `|
3258
- `;
3259
- i += 8;
3260
- }
3261
- }
3262
- s += ` +------------------------+
3263
- `;
3264
- s += " a b c d e f g h";
3265
- return s;
3266
- }
3267
- perft(depth) {
3268
- const moves = this._moves({ legal: false });
3269
- let nodes = 0;
3270
- const color = this._turn;
3271
- for (let i = 0, len = moves.length;i < len; i++) {
3272
- this._makeMove(moves[i]);
3273
- if (!this._isKingAttacked(color)) {
3274
- if (depth - 1 > 0) {
3275
- nodes += this.perft(depth - 1);
3276
- } else {
3277
- nodes++;
3278
- }
3279
- }
3280
- this._undoMove();
3281
- }
3282
- return nodes;
3283
- }
3284
- setTurn(color) {
3285
- if (this._turn == color) {
3286
- return false;
3287
- }
3288
- this.move("--");
3289
- return true;
3290
- }
3291
- turn() {
3292
- return this._turn;
3293
- }
3294
- board() {
3295
- const output = [];
3296
- let row = [];
3297
- for (let i = Ox88.a8;i <= Ox88.h1; i++) {
3298
- if (this._board[i] == null) {
3299
- row.push(null);
3300
- } else {
3301
- row.push({
3302
- square: algebraic(i),
3303
- type: this._board[i].type,
3304
- color: this._board[i].color
3305
- });
3306
- }
3307
- if (i + 1 & 136) {
3308
- output.push(row);
3309
- row = [];
3310
- i += 8;
3311
- }
3312
- }
3313
- return output;
3314
- }
3315
- squareColor(square) {
3316
- if (square in Ox88) {
3317
- const sq = Ox88[square];
3318
- return (rank(sq) + file(sq)) % 2 === 0 ? "light" : "dark";
3319
- }
3320
- return null;
3321
- }
3322
- history({ verbose = false } = {}) {
3323
- const reversedHistory = [];
3324
- const moveHistory = [];
3325
- while (this._history.length > 0) {
3326
- reversedHistory.push(this._undoMove());
3327
- }
3328
- while (true) {
3329
- const move = reversedHistory.pop();
3330
- if (!move) {
3331
- break;
3332
- }
3333
- if (verbose) {
3334
- moveHistory.push(new Move(this, move));
3335
- } else {
3336
- moveHistory.push(this._moveToSan(move, this._moves()));
3337
- }
3338
- this._makeMove(move);
3339
- }
3340
- return moveHistory;
3341
- }
3342
- _getPositionCount(hash) {
3343
- return this._positionCount.get(hash) ?? 0;
3344
- }
3345
- _incPositionCount() {
3346
- this._positionCount.set(this._hash, (this._positionCount.get(this._hash) ?? 0) + 1);
3347
- }
3348
- _decPositionCount(hash) {
3349
- const currentCount = this._positionCount.get(hash) ?? 0;
3350
- if (currentCount === 1) {
3351
- this._positionCount.delete(hash);
3352
- } else {
3353
- this._positionCount.set(hash, currentCount - 1);
3354
- }
3355
- }
3356
- _pruneComments() {
3357
- const reversedHistory = [];
3358
- const currentComments = {};
3359
- const copyComment = (fen) => {
3360
- if (fen in this._comments) {
3361
- currentComments[fen] = this._comments[fen];
3362
- }
3363
- };
3364
- while (this._history.length > 0) {
3365
- reversedHistory.push(this._undoMove());
3366
- }
3367
- copyComment(this.fen());
3368
- while (true) {
3369
- const move = reversedHistory.pop();
3370
- if (!move) {
3371
- break;
3372
- }
3373
- this._makeMove(move);
3374
- copyComment(this.fen());
3375
- }
3376
- this._comments = currentComments;
3377
- }
3378
- getComment() {
3379
- return this._comments[this.fen()];
3380
- }
3381
- setComment(comment) {
3382
- this._comments[this.fen()] = comment.replace("{", "[").replace("}", "]");
3383
- }
3384
- deleteComment() {
3385
- return this.removeComment();
3386
- }
3387
- removeComment() {
3388
- const comment = this._comments[this.fen()];
3389
- delete this._comments[this.fen()];
3390
- return comment;
3391
- }
3392
- getComments() {
3393
- this._pruneComments();
3394
- return Object.keys(this._comments).map((fen) => {
3395
- return { fen, comment: this._comments[fen] };
3396
- });
3397
- }
3398
- deleteComments() {
3399
- return this.removeComments();
3400
- }
3401
- removeComments() {
3402
- this._pruneComments();
3403
- return Object.keys(this._comments).map((fen) => {
3404
- const comment = this._comments[fen];
3405
- delete this._comments[fen];
3406
- return { fen, comment };
3407
- });
3408
- }
3409
- setCastlingRights(color, rights) {
3410
- for (const side of [KING, QUEEN]) {
3411
- if (rights[side] !== undefined) {
3412
- if (rights[side]) {
3413
- this._castling[color] |= SIDES[side];
3414
- } else {
3415
- this._castling[color] &= ~SIDES[side];
3416
- }
3417
- }
3418
- }
3419
- this._updateCastlingRights();
3420
- const result = this.getCastlingRights(color);
3421
- return (rights[KING] === undefined || rights[KING] === result[KING]) && (rights[QUEEN] === undefined || rights[QUEEN] === result[QUEEN]);
3422
- }
3423
- getCastlingRights(color) {
3424
- return {
3425
- [KING]: (this._castling[color] & SIDES[KING]) !== 0,
3426
- [QUEEN]: (this._castling[color] & SIDES[QUEEN]) !== 0
3427
- };
3428
- }
3429
- moveNumber() {
3430
- return this._moveNumber;
3431
- }
3432
- }
3433
-
3434
- // src/features/chess/utils/chessEngine.ts
3435
- function createChess(fen) {
3436
- try {
3437
- return new Chess(fen);
3438
- } catch {
3439
- return null;
3440
- }
3441
- }
3442
- function toPieceCode(piece) {
3443
- return piece.color === "w" ? piece.type.toUpperCase() : piece.type.toLowerCase();
3444
- }
3445
- function toPromotionPiece(piece) {
3446
- return piece === "q" || piece === "r" || piece === "b" || piece === "n" ? piece : undefined;
3447
- }
3448
- function toMoveResult(move, fen) {
3449
- return {
3450
- fen,
3451
- from: move.from,
3452
- lan: move.lan,
3453
- promotion: toPromotionPiece(move.promotion),
3454
- san: move.san,
3455
- to: move.to
3456
- };
3457
- }
3458
- function readChessPieces(fen) {
3459
- const chess = createChess(fen);
3460
- const pieces = new Map;
3461
- if (!chess)
3462
- return pieces;
3463
- for (const rank of chess.board()) {
3464
- for (const piece of rank) {
3465
- if (!piece)
3466
- continue;
3467
- pieces.set(piece.square, {
3468
- color: piece.color === "w" ? "white" : "black",
3469
- piece: toPieceCode(piece),
3470
- square: piece.square
3471
- });
3472
- }
3473
- }
3474
- return pieces;
3475
- }
3476
- function getLegalTargets(fen, from) {
3477
- const chess = createChess(fen);
3478
- return chess ? chess.moves({ square: from, verbose: true }).map((move) => move.to) : [];
3479
- }
3480
- function tryMove(fen, attempt) {
3481
- const chess = createChess(fen);
3482
- if (!chess)
3483
- return null;
3484
- try {
3485
- const move = chess.move({
3486
- from: attempt.from,
3487
- promotion: attempt.promotion,
3488
- to: attempt.to
3489
- });
3490
- return toMoveResult(move, chess.fen());
3491
- } catch {
3492
- return null;
3493
- }
3494
- }
3495
-
3496
- // src/features/chess/utils/createBoardSquares.ts
3497
- var files = ["a", "b", "c", "d", "e", "f", "g", "h"];
3498
- var ranks = ["1", "2", "3", "4", "5", "6", "7", "8"];
3499
- function createBoardSquares(orientation) {
3500
- const displayedRanks = orientation === "white" ? [...ranks].reverse() : [...ranks];
3501
- const displayedFiles = orientation === "white" ? [...files] : [...files].reverse();
3502
- return displayedRanks.flatMap((rank) => displayedFiles.map((file) => `${file}${rank}`));
3503
- }
3504
-
3505
- // src/features/chess/utils/createChessBoardColorScheme.ts
3506
- function createChessBoardColorScheme(theme, overrides) {
3507
- return {
3508
- border: theme.semantics.neutral.divider,
3509
- coordinateText: theme.semantics.content.muted,
3510
- darkPiece: theme.semantics.content.default,
3511
- darkSquare: theme.semantics.neutral.surfaceHover,
3512
- darkSquareText: theme.semantics.content.muted,
3513
- lastMoveFrom: theme.semantics.warning.softBg,
3514
- lastMoveTo: theme.semantics.warning.softBg,
3515
- legalTarget: theme.semantics.success.softBg,
3516
- lightPiece: theme.semantics.content.default,
3517
- lightSquare: theme.semantics.neutral.surface,
3518
- lightSquareText: theme.semantics.content.muted,
3519
- selectedSquare: theme.semantics.action.primary.softBg,
3520
- ...overrides
3521
- };
3522
- }
3523
-
3524
- // src/features/chess/utils/isLightSquare.ts
3525
- var files2 = "abcdefgh";
3526
- function isLightSquare(square) {
3527
- return (files2.indexOf(square[0] ?? "") + Number(square[1]) - 1) % 2 === 1;
3528
- }
3529
-
3530
- // src/features/chess/adapters/inbound/ChessBoard.tsx
3531
- import { jsx, jsxs } from "react/jsx-runtime";
3532
- var symbols = new Map([
3533
- ["white:p", "♙"],
3534
- ["white:n", "♘"],
3535
- ["white:b", "♗"],
3536
- ["white:r", "♖"],
3537
- ["white:q", "♕"],
3538
- ["white:k", "♔"],
3539
- ["black:p", "♟"],
3540
- ["black:n", "♞"],
3541
- ["black:b", "♝"],
3542
- ["black:r", "♜"],
3543
- ["black:q", "♛"],
3544
- ["black:k", "♚"]
3545
- ]);
3546
- var ChessBoard2 = withZoraThemeScope(ChessBoardInner);
3547
- function ChessBoardInner({
3548
- fen,
3549
- pieces,
3550
- orientation = "white",
3551
- selectedSquare = null,
3552
- legalTargets,
3553
- lastMove = null,
3554
- disabled = false,
3555
- showCoordinates = false,
3556
- validateMoves = true,
3557
- colorScheme,
3558
- onSquarePress,
3559
- onMoveAttempt,
3560
- onLegalMove,
3561
- onInvalidMove,
3562
- renderPiece,
3563
- interactionPolicy,
3564
- testID
3565
- }) {
3566
- const { theme } = useZoraTheme2();
3567
- const colors = createChessBoardColorScheme(theme, colorScheme);
3568
- const squares = createBoardSquares(orientation);
3569
- const piecesBySquare = pieces === undefined ? fen === undefined ? new Map : new Map(readChessPieces(fen)) : new Map(pieces.map((piece) => [piece.square, piece]));
3570
- const resolvedLegalTargets = legalTargets ?? (fen !== undefined && selectedSquare !== null ? getLegalTargets(fen, selectedSquare) : []);
3571
- const legalTargetSet = new Set(resolvedLegalTargets);
3572
- const pressSquare = (square) => {
3573
- if (disabled || interactionPolicy === "passive")
3574
- return;
3575
- onSquarePress?.(square);
3576
- if (selectedSquare === null || selectedSquare === square)
3577
- return;
3578
- const attempt = { from: selectedSquare, to: square };
3579
- onMoveAttempt?.(attempt);
3580
- if (!validateMoves || fen === undefined)
3581
- return;
3582
- const result = tryMove(fen, attempt);
3583
- if (result)
3584
- onLegalMove?.(result);
3585
- else
3586
- onInvalidMove?.(attempt);
3587
- };
3588
- return /* @__PURE__ */ jsx(import_react_native.View, {
3589
- accessibilityLabel: "Chess board",
3590
- style: [styles.board, { borderColor: colors.border, opacity: disabled ? 0.56 : 1 }],
3591
- testID,
3592
- children: squares.map((square) => {
3593
- const piece = piecesBySquare.get(square);
3594
- const light = isLightSquare(square);
3595
- const isTarget = legalTargetSet.has(square);
3596
- const backgroundColor = selectedSquare === square ? colors.selectedSquare : isTarget ? colors.legalTarget : lastMove?.from === square ? colors.lastMoveFrom : lastMove?.to === square ? colors.lastMoveTo : light ? colors.lightSquare : colors.darkSquare;
3597
- const pieceContent = piece === undefined ? null : renderPiece ? renderPiece({
3598
- color: piece.color === "white" ? colors.lightPiece : colors.darkPiece,
3599
- piece: piece.piece,
3600
- square
3601
- }) : symbols.get(`${piece.color}:${piece.piece.toLowerCase()}`) ?? piece.piece;
3602
- return /* @__PURE__ */ jsxs(import_react_native.Pressable, {
3603
- accessibilityLabel: square,
3604
- accessibilityRole: "button",
3605
- disabled: disabled || interactionPolicy === "passive",
3606
- onPress: () => pressSquare(square),
3607
- style: [styles.square, { backgroundColor }],
3608
- testID: testID ? `${testID}-square-${square}` : undefined,
3609
- children: [
3610
- showCoordinates ? /* @__PURE__ */ jsx(import_react_native.Text, {
3611
- style: [
3612
- styles.coordinate,
3613
- { color: light ? colors.lightSquareText : colors.darkSquareText }
3614
- ],
3615
- children: square
3616
- }) : null,
3617
- piece === undefined ? null : /* @__PURE__ */ jsx(import_react_native.View, {
3618
- pointerEvents: "none",
3619
- style: styles.pieceContainer,
3620
- children: renderPiece ? pieceContent : /* @__PURE__ */ jsx(import_react_native.Text, {
3621
- style: [
3622
- styles.piece,
3623
- { color: piece.color === "white" ? colors.lightPiece : colors.darkPiece }
3624
- ],
3625
- children: pieceContent
3626
- })
3627
- })
3628
- ]
3629
- }, square);
3630
- })
3631
- });
3632
- }
3633
- var styles = import_react_native.StyleSheet.create({
3634
- board: {
3635
- aspectRatio: 1,
3636
- borderRadius: 12,
3637
- borderWidth: import_react_native.StyleSheet.hairlineWidth,
3638
- flexDirection: "row",
3639
- flexWrap: "wrap",
3640
- overflow: "hidden",
3641
- width: "100%"
3642
- },
3643
- coordinate: {
3644
- fontSize: 9,
3645
- fontWeight: "600",
3646
- left: 3,
3647
- opacity: 0.72,
3648
- position: "absolute",
3649
- top: 2,
3650
- zIndex: 2
3651
- },
3652
- piece: { fontSize: 32, fontWeight: "600", lineHeight: 38 },
3653
- pieceContainer: {
3654
- alignItems: "center",
3655
- bottom: 0,
3656
- justifyContent: "center",
3657
- left: 0,
3658
- position: "absolute",
3659
- right: 0,
3660
- top: 0
3661
- },
3662
- square: {
3663
- alignItems: "center",
3664
- aspectRatio: 1,
3665
- width: "12.5%",
3666
- justifyContent: "center",
3667
- position: "relative"
3668
- }
3669
- });
3670
-
3671
- // src/features/chess/adapters/inbound/OpeningBook.tsx
3672
- var import_react_native2 = __toESM(require_cjs(), 1);
3673
-
3674
- // src/features/chess/utils/createOpeningBookColorScheme.ts
3675
- function createOpeningBookColorScheme(theme, overrides) {
3676
- return {
3677
- border: theme.semantics.neutral.divider,
3678
- metricSurface: theme.semantics.neutral.surface,
3679
- primaryText: theme.semantics.content.default,
3680
- secondaryText: theme.semantics.content.muted,
3681
- selectedSurface: theme.semantics.action.primary.softBg,
3682
- surface: theme.semantics.neutral.surface,
3683
- surfaceHover: theme.semantics.neutral.surfaceHover,
3684
- titleText: theme.semantics.content.default,
3685
- ...overrides
3686
- };
3687
- }
3688
-
3689
- // src/features/chess/adapters/inbound/OpeningBook.tsx
3690
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
3691
- var OpeningBook2 = withZoraThemeScope(OpeningBookInner);
3692
- function rate(label, value) {
3693
- if (value === undefined || !Number.isFinite(value))
3694
- return;
3695
- return `${label} ${Math.round(value <= 1 ? value * 100 : value)}%`;
3696
- }
3697
- function moveKey(move) {
3698
- return move.uci ?? move.fen ?? move.san;
3699
- }
3700
- function OpeningBookInner({
3701
- moves = [],
3702
- title = "Opening book",
3703
- loading = false,
3704
- errorText,
3705
- emptyText = "No book moves for this position.",
3706
- selectedMove = null,
3707
- colorScheme,
3708
- onMovePress,
3709
- interactionPolicy,
3710
- testID
3711
- }) {
3712
- const { theme } = useZoraTheme2();
3713
- const colors = createOpeningBookColorScheme(theme, colorScheme);
3714
- const stateText = loading ? "Loading opening moves…" : errorText ?? emptyText;
3715
- const showState = loading || errorText !== undefined || moves.length === 0;
3716
- return /* @__PURE__ */ jsxs2(import_react_native2.View, {
3717
- accessibilityLabel: title,
3718
- style: [
3719
- styles2.root,
3720
- {
3721
- borderColor: colors.border,
3722
- backgroundColor: colors.surface
3723
- }
3724
- ],
3725
- testID,
3726
- children: [
3727
- /* @__PURE__ */ jsx2(import_react_native2.Text, {
3728
- style: [styles2.title, { color: colors.titleText }],
3729
- children: title
3730
- }),
3731
- !showState ? /* @__PURE__ */ jsx2(import_react_native2.View, {
3732
- style: styles2.moves,
3733
- children: moves.map((move) => {
3734
- const selected = selectedMove !== null && (selectedMove === move.san || selectedMove === move.uci || selectedMove === move.fen);
3735
- const details = [
3736
- move.eco,
3737
- move.name,
3738
- move.games === undefined ? undefined : `${move.games} games`
3739
- ].filter((part) => typeof part === "string" && part.length > 0);
3740
- const stats = [
3741
- rate("W", move.whiteWinRate),
3742
- rate("D", move.drawRate),
3743
- rate("B", move.blackWinRate)
3744
- ].filter((part) => part !== undefined);
3745
- return /* @__PURE__ */ jsxs2(import_react_native2.Pressable, {
3746
- accessibilityRole: "button",
3747
- disabled: onMovePress === undefined || interactionPolicy === "passive",
3748
- onPress: () => {
3749
- if (interactionPolicy === "passive")
3750
- return;
3751
- onMovePress?.(move);
3752
- },
3753
- style: [
3754
- styles2.move,
3755
- {
3756
- backgroundColor: selected ? colors.selectedSurface : colors.surfaceHover,
3757
- borderColor: colors.border
3758
- }
3759
- ],
3760
- testID: testID ? `${testID}-move-${move.san}` : undefined,
3761
- children: [
3762
- /* @__PURE__ */ jsxs2(import_react_native2.View, {
3763
- style: styles2.moveMain,
3764
- children: [
3765
- /* @__PURE__ */ jsx2(import_react_native2.Text, {
3766
- style: [styles2.san, { color: colors.primaryText }],
3767
- children: move.san
3768
- }),
3769
- /* @__PURE__ */ jsx2(import_react_native2.Text, {
3770
- style: [styles2.meta, { color: colors.secondaryText }],
3771
- children: details.length > 0 ? details.join(" · ") : "Book move"
3772
- })
3773
- ]
3774
- }),
3775
- stats.length > 0 ? /* @__PURE__ */ jsx2(import_react_native2.View, {
3776
- style: [styles2.metric, { backgroundColor: colors.metricSurface }],
3777
- children: /* @__PURE__ */ jsx2(import_react_native2.Text, {
3778
- style: [styles2.metricText, { color: colors.secondaryText }],
3779
- children: stats.join(" ")
3780
- })
3781
- }) : null
3782
- ]
3783
- }, moveKey(move));
3784
- })
3785
- }) : /* @__PURE__ */ jsx2(import_react_native2.Text, {
3786
- style: [styles2.stateText, { color: colors.secondaryText }],
3787
- children: stateText
3788
- })
3789
- ]
3790
- });
3791
- }
3792
- var styles2 = import_react_native2.StyleSheet.create({
3793
- root: { borderRadius: 12, borderWidth: import_react_native2.StyleSheet.hairlineWidth, gap: 10, padding: 12 },
3794
- title: { fontSize: 15, fontWeight: "700", lineHeight: 20 },
3795
- stateText: { fontSize: 13, lineHeight: 18 },
3796
- moves: { gap: 8 },
3797
- move: {
3798
- alignItems: "center",
3799
- borderRadius: 10,
3800
- borderWidth: import_react_native2.StyleSheet.hairlineWidth,
3801
- flexDirection: "row",
3802
- gap: 10,
3803
- justifyContent: "space-between",
3804
- paddingHorizontal: 10,
3805
- paddingVertical: 8
3806
- },
3807
- moveMain: { flex: 1, gap: 2 },
3808
- san: { fontSize: 16, fontWeight: "700", lineHeight: 20 },
3809
- meta: { fontSize: 12, lineHeight: 16 },
3810
- metric: { borderRadius: 999, paddingHorizontal: 8, paddingVertical: 4 },
3811
- metricText: { fontSize: 11, fontWeight: "600" }
3812
- });
3813
- export { ChessBoard2, OpeningBook2 };