@connectorvol/chessops 0.16.0 → 2.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 (93) hide show
  1. package/dist/{esm/attacks.js → attacks.js} +2 -3
  2. package/dist/{esm/board.js → board.js} +25 -9
  3. package/dist/{esm/chess.js → chess.js} +24 -18
  4. package/dist/{esm/compat.js → compat.js} +1 -2
  5. package/dist/{esm/debug.js → debug.js} +0 -1
  6. package/dist/{esm/fen.js → fen.js} +1 -2
  7. package/dist/{types/index.d.ts → index.d.ts} +6 -3
  8. package/dist/{esm/index.js → index.js} +1 -2
  9. package/dist/{esm/pgn.js → pgn.js} +54 -34
  10. package/dist/pgnOps.svelte.d.ts +31 -0
  11. package/dist/pgnOps.svelte.js +122 -0
  12. package/dist/{esm/san.js → san.js} +2 -5
  13. package/dist/{esm/setup.js → setup.js} +29 -26
  14. package/dist/{esm/squareSet.js → squareSet.js} +17 -16
  15. package/dist/{esm/transform.js → transform.js} +10 -14
  16. package/dist/{esm/types.js → types.js} +0 -1
  17. package/dist/{esm/util.js → util.js} +0 -1
  18. package/dist/{types/variant.d.ts → variant.d.ts} +2 -1
  19. package/dist/{esm/variant.js → variant.js} +21 -26
  20. package/package.json +31 -59
  21. package/dist/cjs/attacks.js +0 -152
  22. package/dist/cjs/attacks.js.map +0 -1
  23. package/dist/cjs/board.js +0 -143
  24. package/dist/cjs/board.js.map +0 -1
  25. package/dist/cjs/chess.js +0 -638
  26. package/dist/cjs/chess.js.map +0 -1
  27. package/dist/cjs/compat.js +0 -89
  28. package/dist/cjs/compat.js.map +0 -1
  29. package/dist/cjs/debug.js +0 -103
  30. package/dist/cjs/debug.js.map +0 -1
  31. package/dist/cjs/fen.js +0 -325
  32. package/dist/cjs/fen.js.map +0 -1
  33. package/dist/cjs/index.js +0 -94
  34. package/dist/cjs/index.js.map +0 -1
  35. package/dist/cjs/pgn.js +0 -796
  36. package/dist/cjs/pgn.js.map +0 -1
  37. package/dist/cjs/san.js +0 -174
  38. package/dist/cjs/san.js.map +0 -1
  39. package/dist/cjs/setup.js +0 -167
  40. package/dist/cjs/setup.js.map +0 -1
  41. package/dist/cjs/squareSet.js +0 -206
  42. package/dist/cjs/squareSet.js.map +0 -1
  43. package/dist/cjs/transform.js +0 -57
  44. package/dist/cjs/transform.js.map +0 -1
  45. package/dist/cjs/types.js +0 -24
  46. package/dist/cjs/types.js.map +0 -1
  47. package/dist/cjs/util.js +0 -104
  48. package/dist/cjs/util.js.map +0 -1
  49. package/dist/cjs/variant.js +0 -833
  50. package/dist/cjs/variant.js.map +0 -1
  51. package/dist/esm/attacks.js.map +0 -1
  52. package/dist/esm/board.js.map +0 -1
  53. package/dist/esm/chess.js.map +0 -1
  54. package/dist/esm/compat.js.map +0 -1
  55. package/dist/esm/debug.js.map +0 -1
  56. package/dist/esm/fen.js.map +0 -1
  57. package/dist/esm/index.js.map +0 -1
  58. package/dist/esm/pgn.js.map +0 -1
  59. package/dist/esm/san.js.map +0 -1
  60. package/dist/esm/setup.js.map +0 -1
  61. package/dist/esm/squareSet.js.map +0 -1
  62. package/dist/esm/transform.js.map +0 -1
  63. package/dist/esm/types.js.map +0 -1
  64. package/dist/esm/util.js.map +0 -1
  65. package/dist/esm/variant.js.map +0 -1
  66. package/src/attacks.ts +0 -160
  67. package/src/board.ts +0 -168
  68. package/src/chess.ts +0 -687
  69. package/src/compat.ts +0 -120
  70. package/src/debug.ts +0 -100
  71. package/src/fen.ts +0 -328
  72. package/src/index.ts +0 -85
  73. package/src/pgn.ts +0 -876
  74. package/src/san.ts +0 -190
  75. package/src/setup.ts +0 -203
  76. package/src/squareSet.ts +0 -243
  77. package/src/transform.ts +0 -49
  78. package/src/types.ts +0 -93
  79. package/src/util.ts +0 -116
  80. package/src/variant.ts +0 -939
  81. /package/dist/{types/attacks.d.ts → attacks.d.ts} +0 -0
  82. /package/dist/{types/board.d.ts → board.d.ts} +0 -0
  83. /package/dist/{types/chess.d.ts → chess.d.ts} +0 -0
  84. /package/dist/{types/compat.d.ts → compat.d.ts} +0 -0
  85. /package/dist/{types/debug.d.ts → debug.d.ts} +0 -0
  86. /package/dist/{types/fen.d.ts → fen.d.ts} +0 -0
  87. /package/dist/{types/pgn.d.ts → pgn.d.ts} +0 -0
  88. /package/dist/{types/san.d.ts → san.d.ts} +0 -0
  89. /package/dist/{types/setup.d.ts → setup.d.ts} +0 -0
  90. /package/dist/{types/squareSet.d.ts → squareSet.d.ts} +0 -0
  91. /package/dist/{types/transform.d.ts → transform.d.ts} +0 -0
  92. /package/dist/{types/types.d.ts → types.d.ts} +0 -0
  93. /package/dist/{types/util.d.ts → util.d.ts} +0 -0
@@ -51,12 +51,12 @@ export const pawnAttacks = (color, square) => PAWN_ATTACKS[color][square];
51
51
  const FILE_RANGE = tabulate((sq) => SquareSet.fromFile(squareFile(sq)).without(sq));
52
52
  const RANK_RANGE = tabulate((sq) => SquareSet.fromRank(squareRank(sq)).without(sq));
53
53
  const DIAG_RANGE = tabulate((sq) => {
54
- const diag = new SquareSet(134480385, 2151686160);
54
+ const diag = new SquareSet(0x0804_0201, 0x8040_2010);
55
55
  const shift = 8 * (squareRank(sq) - squareFile(sq));
56
56
  return (shift >= 0 ? diag.shl64(shift) : diag.shr64(-shift)).without(sq);
57
57
  });
58
58
  const ANTI_DIAG_RANGE = tabulate((sq) => {
59
- const diag = new SquareSet(270549120, 16909320);
59
+ const diag = new SquareSet(0x1020_4080, 0x0102_0408);
60
60
  const shift = 8 * (squareRank(sq) + squareFile(sq) - 7);
61
61
  return (shift >= 0 ? diag.shl64(shift) : diag.shr64(-shift)).without(sq);
62
62
  });
@@ -137,4 +137,3 @@ export const ray = (a, b) => {
137
137
  export const between = (a, b) => ray(a, b)
138
138
  .intersect(SquareSet.full().shl64(a).xor(SquareSet.full().shl64(b)))
139
139
  .withoutFirst();
140
- //# sourceMappingURL=attacks.js.map
@@ -9,6 +9,23 @@ import { COLORS, ROLES } from "./types.js";
9
9
  * care to keep them consistent.
10
10
  */
11
11
  export class Board {
12
+ /**
13
+ * All occupied squares.
14
+ */
15
+ occupied;
16
+ /**
17
+ * All squares occupied by pieces known to be promoted. This information is
18
+ * relevant in chess variants like Crazyhouse.
19
+ */
20
+ promoted;
21
+ white;
22
+ black;
23
+ pawn;
24
+ knight;
25
+ bishop;
26
+ rook;
27
+ queen;
28
+ king;
12
29
  constructor() { }
13
30
  static default() {
14
31
  const board = new Board();
@@ -19,16 +36,16 @@ export class Board {
19
36
  * Resets all pieces to the default starting position for standard chess.
20
37
  */
21
38
  reset() {
22
- this.occupied = new SquareSet(0xffff, 4294901760);
39
+ this.occupied = new SquareSet(0xffff, 0xffff_0000);
23
40
  this.promoted = SquareSet.empty();
24
41
  this.white = new SquareSet(0xffff, 0);
25
- this.black = new SquareSet(0, 4294901760);
26
- this.pawn = new SquareSet(0xff00, 16711680);
27
- this.knight = new SquareSet(0x42, 1107296256);
28
- this.bishop = new SquareSet(0x24, 603979776);
29
- this.rook = new SquareSet(0x81, 2164260864);
30
- this.queen = new SquareSet(0x8, 134217728);
31
- this.king = new SquareSet(0x10, 268435456);
42
+ this.black = new SquareSet(0, 0xffff_0000);
43
+ this.pawn = new SquareSet(0xff00, 0x00ff_0000);
44
+ this.knight = new SquareSet(0x42, 0x4200_0000);
45
+ this.bishop = new SquareSet(0x24, 0x2400_0000);
46
+ this.rook = new SquareSet(0x81, 0x8100_0000);
47
+ this.queen = new SquareSet(0x8, 0x0800_0000);
48
+ this.king = new SquareSet(0x10, 0x1000_0000);
32
49
  }
33
50
  static empty() {
34
51
  const board = new Board();
@@ -135,4 +152,3 @@ export class Board {
135
152
  export const boardEquals = (left, right) => left.white.equals(right.white) &&
136
153
  left.promoted.equals(right.promoted) &&
137
154
  ROLES.every((role) => left[role].equals(right[role]));
138
- //# sourceMappingURL=board.js.map
@@ -21,6 +21,9 @@ const attacksTo = (square, attacker, board, occupied) => board[attacker].interse
21
21
  .union(kingAttacks(square).intersect(board.king))
22
22
  .union(pawnAttacks(opposite(attacker), square).intersect(board.pawn)));
23
23
  export class Castles {
24
+ castlingRights;
25
+ rook;
26
+ path;
24
27
  constructor() { }
25
28
  static default() {
26
29
  const castles = new Castles();
@@ -108,6 +111,15 @@ export class Castles {
108
111
  }
109
112
  }
110
113
  export class Position {
114
+ rules;
115
+ board;
116
+ pockets;
117
+ turn;
118
+ castles;
119
+ epSquare;
120
+ remainingChecks;
121
+ halfmoves;
122
+ fullmoves;
111
123
  constructor(rules) {
112
124
  this.rules = rules;
113
125
  }
@@ -185,14 +197,13 @@ export class Position {
185
197
  };
186
198
  }
187
199
  clone() {
188
- var _a, _b;
189
200
  const pos = new this.constructor();
190
201
  pos.board = this.board.clone();
191
- pos.pockets = (_a = this.pockets) === null || _a === void 0 ? void 0 : _a.clone();
202
+ pos.pockets = this.pockets?.clone();
192
203
  pos.turn = this.turn;
193
204
  pos.castles = this.castles.clone();
194
205
  pos.epSquare = this.epSquare;
195
- pos.remainingChecks = (_b = this.remainingChecks) === null || _b === void 0 ? void 0 : _b.clone();
206
+ pos.remainingChecks = this.remainingChecks?.clone();
196
207
  pos.halfmoves = this.halfmoves;
197
208
  pos.fullmoves = this.fullmoves;
198
209
  return pos;
@@ -297,14 +308,13 @@ export class Position {
297
308
  }
298
309
  // The following should be identical in all subclasses
299
310
  toSetup() {
300
- var _a, _b;
301
311
  return {
302
312
  board: this.board.clone(),
303
- pockets: (_a = this.pockets) === null || _a === void 0 ? void 0 : _a.clone(),
313
+ pockets: this.pockets?.clone(),
304
314
  turn: this.turn,
305
315
  castlingRights: this.castles.castlingRights,
306
316
  epSquare: legalEpSquare(this),
307
- remainingChecks: (_b = this.remainingChecks) === null || _b === void 0 ? void 0 : _b.clone(),
317
+ remainingChecks: this.remainingChecks?.clone(),
308
318
  halfmoves: Math.min(this.halfmoves, 150),
309
319
  fullmoves: Math.min(Math.max(this.fullmoves, 1), 9999),
310
320
  };
@@ -551,17 +561,14 @@ export const pseudoDests = (pos, square, ctx) => {
551
561
  else
552
562
  return pseudo;
553
563
  };
554
- export const equalsIgnoreMoves = (left, right) => {
555
- var _a, _b;
556
- return left.rules === right.rules &&
557
- boardEquals(left.board, right.board) &&
558
- ((right.pockets && ((_a = left.pockets) === null || _a === void 0 ? void 0 : _a.equals(right.pockets))) || (!left.pockets && !right.pockets)) &&
559
- left.turn === right.turn &&
560
- left.castles.castlingRights.equals(right.castles.castlingRights) &&
561
- legalEpSquare(left) === legalEpSquare(right) &&
562
- ((right.remainingChecks && ((_b = left.remainingChecks) === null || _b === void 0 ? void 0 : _b.equals(right.remainingChecks))) ||
563
- (!left.remainingChecks && !right.remainingChecks));
564
- };
564
+ export const equalsIgnoreMoves = (left, right) => left.rules === right.rules &&
565
+ boardEquals(left.board, right.board) &&
566
+ ((right.pockets && left.pockets?.equals(right.pockets)) || (!left.pockets && !right.pockets)) &&
567
+ left.turn === right.turn &&
568
+ left.castles.castlingRights.equals(right.castles.castlingRights) &&
569
+ legalEpSquare(left) === legalEpSquare(right) &&
570
+ ((right.remainingChecks && left.remainingChecks?.equals(right.remainingChecks)) ||
571
+ (!left.remainingChecks && !right.remainingChecks));
565
572
  export const castlingSide = (pos, move) => {
566
573
  if (isDrop(move))
567
574
  return;
@@ -621,4 +628,3 @@ export const isImpossibleCheck = (pos) => {
621
628
  checkers.intersect(pos.board.steppers()).moreThanOne());
622
629
  }
623
630
  };
624
- //# sourceMappingURL=chess.js.map
@@ -22,7 +22,7 @@ export const chessgroundDests = (pos, opts) => {
22
22
  for (const [from, squares] of pos.allDests(ctx)) {
23
23
  if (squares.nonEmpty()) {
24
24
  const d = Array.from(squares, makeSquare);
25
- if (!(opts === null || opts === void 0 ? void 0 : opts.chess960) && from === ctx.king && squareFile(from) === 4) {
25
+ if (!opts?.chess960 && from === ctx.king && squareFile(from) === 4) {
26
26
  // Chessground needs both types of castling dests and filters based on
27
27
  // a rookCastles setting.
28
28
  if (squares.has(0))
@@ -78,4 +78,3 @@ export const lichessVariant = (rules) => {
78
78
  return rules;
79
79
  }
80
80
  };
81
- //# sourceMappingURL=compat.js.map
@@ -91,4 +91,3 @@ export const perft = (pos, depth, log = false) => {
91
91
  return nodes;
92
92
  }
93
93
  };
94
- //# sourceMappingURL=debug.js.map
@@ -298,11 +298,10 @@ export const makeFen = (setup, opts) => [
298
298
  makeCastlingFen(setup.board, setup.castlingRights),
299
299
  defined(setup.epSquare) ? makeSquare(setup.epSquare) : "-",
300
300
  ...(setup.remainingChecks ? [makeRemainingChecks(setup.remainingChecks)] : []),
301
- ...((opts === null || opts === void 0 ? void 0 : opts.epd)
301
+ ...(opts?.epd
302
302
  ? []
303
303
  : [
304
304
  Math.max(0, Math.min(setup.halfmoves, 9999)),
305
305
  Math.max(1, Math.min(setup.fullmoves, 9999)),
306
306
  ]),
307
307
  ].join(" ");
308
- //# sourceMappingURL=fen.js.map
@@ -1,10 +1,13 @@
1
- export { ByCastlingSide, ByColor, ByRole, BySquare, CASTLING_SIDES, CastlingSide, Color, COLORS, DropMove, FILE_NAMES, FileName, isDrop, isNormal, Move, NormalMove, Outcome, Piece, RANK_NAMES, RankName, Role, ROLE_CHARS, RoleChar, ROLES, Rules, Square, SquareName, } from "./types.js";
1
+ export type { ByCastlingSide, ByColor, ByRole, BySquare, CastlingSide, Color, DropMove, FileName, Move, NormalMove, Outcome, Piece, RankName, Role, RoleChar, Rules, Square, SquareName, } from "./types.js";
2
+ export { CASTLING_SIDES, COLORS, FILE_NAMES, isDrop, isNormal, RANK_NAMES, ROLE_CHARS, ROLES, RULES, } from "./types.js";
2
3
  export { charToRole, defined, kingCastlesTo, makeSquare, makeUci, opposite, parseSquare, parseUci, roleToChar, squareFile, squareRank, } from "./util.js";
3
4
  export { SquareSet } from "./squareSet.js";
4
5
  export { attacks, between, bishopAttacks, kingAttacks, knightAttacks, pawnAttacks, queenAttacks, ray, rookAttacks, } from "./attacks.js";
5
6
  export { Board, boardEquals } from "./board.js";
6
- export { defaultSetup, emptySetup, Material, MaterialSide, RemainingChecks, Setup, setupClone, setupEquals, } from "./setup.js";
7
- export { Castles, Chess, Context, IllegalSetup, Position, PositionError } from "./chess.js";
7
+ export type { Setup } from "./setup.js";
8
+ export { defaultSetup, emptySetup, Material, MaterialSide, RemainingChecks, setupClone, setupEquals, } from "./setup.js";
9
+ export type { Context } from "./chess.js";
10
+ export { Castles, Chess, IllegalSetup, Position, PositionError } from "./chess.js";
8
11
  export * as compat from "./compat.js";
9
12
  export * as debug from "./debug.js";
10
13
  export * as fen from "./fen.js";
@@ -1,4 +1,4 @@
1
- export { CASTLING_SIDES, COLORS, FILE_NAMES, isDrop, isNormal, RANK_NAMES, ROLE_CHARS, ROLES, } from "./types.js";
1
+ export { CASTLING_SIDES, COLORS, FILE_NAMES, isDrop, isNormal, RANK_NAMES, ROLE_CHARS, ROLES, RULES, } from "./types.js";
2
2
  export { charToRole, defined, kingCastlesTo, makeSquare, makeUci, opposite, parseSquare, parseUci, roleToChar, squareFile, squareRank, } from "./util.js";
3
3
  export { SquareSet } from "./squareSet.js";
4
4
  export { attacks, between, bishopAttacks, kingAttacks, knightAttacks, pawnAttacks, queenAttacks, ray, rookAttacks, } from "./attacks.js";
@@ -12,4 +12,3 @@ export * as san from "./san.js";
12
12
  export * as transform from "./transform.js";
13
13
  export * as variant from "./variant.js";
14
14
  export * as pgn from "./pgn.js";
15
- //# sourceMappingURL=index.js.map
@@ -110,9 +110,7 @@ export const defaultGame = (initHeaders = defaultHeaders) => ({
110
110
  moves: new Node(),
111
111
  });
112
112
  export class Node {
113
- constructor() {
114
- this.children = [];
115
- }
113
+ children = [];
116
114
  *mainlineNodes() {
117
115
  // eslint-disable-next-line @typescript-eslint/no-this-alias
118
116
  let node = this;
@@ -135,6 +133,7 @@ export class Node {
135
133
  }
136
134
  }
137
135
  export class ChildNode extends Node {
136
+ data;
138
137
  constructor(data) {
139
138
  super();
140
139
  this.data = data;
@@ -150,6 +149,7 @@ export const extend = (node, data) => {
150
149
  return node;
151
150
  };
152
151
  export class Box {
152
+ value;
153
153
  constructor(value) {
154
154
  this.value = value;
155
155
  }
@@ -219,6 +219,12 @@ export const parseOutcome = (s) => {
219
219
  };
220
220
  const escapeHeader = (value) => value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
221
221
  const safeComment = (comment) => comment.replace(/\}/g, "");
222
+ var MakePgnState;
223
+ (function (MakePgnState) {
224
+ MakePgnState[MakePgnState["Pre"] = 0] = "Pre";
225
+ MakePgnState[MakePgnState["Sidelines"] = 1] = "Sidelines";
226
+ MakePgnState[MakePgnState["End"] = 2] = "End";
227
+ })(MakePgnState || (MakePgnState = {}));
222
228
  export const makePgn = (game) => {
223
229
  const builder = [], tokens = [];
224
230
  if (game.headers.size) {
@@ -238,7 +244,7 @@ export const makePgn = (game) => {
238
244
  const firstVariation = variations.next();
239
245
  if (!firstVariation.done) {
240
246
  stack.push({
241
- state: 0 /* MakePgnState.Pre */,
247
+ state: MakePgnState.Pre,
242
248
  ply: initialPly,
243
249
  node: firstVariation.value,
244
250
  sidelines: variations,
@@ -255,7 +261,7 @@ export const makePgn = (game) => {
255
261
  forceMoveNumber = true;
256
262
  }
257
263
  switch (frame.state) {
258
- case 0 /* MakePgnState.Pre */:
264
+ case MakePgnState.Pre:
259
265
  for (const comment of frame.node.data.startingComments || []) {
260
266
  tokens.push("{", safeComment(comment), "}");
261
267
  forceMoveNumber = true;
@@ -272,15 +278,15 @@ export const makePgn = (game) => {
272
278
  for (const comment of frame.node.data.comments || []) {
273
279
  tokens.push("{", safeComment(comment), "}");
274
280
  }
275
- frame.state = 1 /* MakePgnState.Sidelines */; // fall through
276
- case 1 /* MakePgnState.Sidelines */: {
281
+ frame.state = MakePgnState.Sidelines; // fall through
282
+ case MakePgnState.Sidelines: {
277
283
  const child = frame.sidelines.next();
278
284
  if (child.done) {
279
285
  const variations = frame.node.children[Symbol.iterator]();
280
286
  const firstVariation = variations.next();
281
287
  if (!firstVariation.done) {
282
288
  stack.push({
283
- state: 0 /* MakePgnState.Pre */,
289
+ state: MakePgnState.Pre,
284
290
  ply: frame.ply + 1,
285
291
  node: firstVariation.value,
286
292
  sidelines: variations,
@@ -288,13 +294,13 @@ export const makePgn = (game) => {
288
294
  inVariation: false,
289
295
  });
290
296
  }
291
- frame.state = 2 /* MakePgnState.End */;
297
+ frame.state = MakePgnState.End;
292
298
  }
293
299
  else {
294
300
  tokens.push("(");
295
301
  forceMoveNumber = true;
296
302
  stack.push({
297
- state: 0 /* MakePgnState.Pre */,
303
+ state: MakePgnState.Pre,
298
304
  ply: frame.ply,
299
305
  node: child.value,
300
306
  sidelines: [][Symbol.iterator](),
@@ -305,7 +311,7 @@ export const makePgn = (game) => {
305
311
  }
306
312
  break;
307
313
  }
308
- case 2 /* MakePgnState.End */:
314
+ case MakePgnState.End:
309
315
  stack.pop();
310
316
  }
311
317
  }
@@ -326,21 +332,38 @@ export const emptyHeaders = () => new Map();
326
332
  const BOM = "\ufeff";
327
333
  const isWhitespace = (line) => /^\s*$/.test(line);
328
334
  const isCommentLine = (line) => line.startsWith("%");
335
+ var ParserState;
336
+ (function (ParserState) {
337
+ ParserState[ParserState["Bom"] = 0] = "Bom";
338
+ ParserState[ParserState["Pre"] = 1] = "Pre";
339
+ ParserState[ParserState["Headers"] = 2] = "Headers";
340
+ ParserState[ParserState["Moves"] = 3] = "Moves";
341
+ ParserState[ParserState["Comment"] = 4] = "Comment";
342
+ })(ParserState || (ParserState = {}));
329
343
  export class PgnError extends Error {
330
344
  }
331
345
  export class PgnParser {
332
- constructor(emitGame, initHeaders = defaultHeaders, maxBudget = 1000000) {
346
+ emitGame;
347
+ initHeaders;
348
+ maxBudget;
349
+ lineBuf = [];
350
+ budget;
351
+ found;
352
+ state;
353
+ game;
354
+ stack;
355
+ commentBuf;
356
+ constructor(emitGame, initHeaders = defaultHeaders, maxBudget = 1_000_000) {
333
357
  this.emitGame = emitGame;
334
358
  this.initHeaders = initHeaders;
335
359
  this.maxBudget = maxBudget;
336
- this.lineBuf = [];
337
360
  this.resetGame();
338
- this.state = 0 /* ParserState.Bom */;
361
+ this.state = ParserState.Bom;
339
362
  }
340
363
  resetGame() {
341
364
  this.budget = this.maxBudget;
342
365
  this.found = false;
343
- this.state = 1 /* ParserState.Pre */;
366
+ this.state = ParserState.Pre;
344
367
  this.game = defaultGame(this.initHeaders);
345
368
  this.stack = [{ parent: this.game.moves, root: true }];
346
369
  this.commentBuf = [];
@@ -368,7 +391,7 @@ export class PgnParser {
368
391
  }
369
392
  this.consumeBudget(data.length - idx);
370
393
  this.lineBuf.push(data.slice(idx));
371
- if (!(options === null || options === void 0 ? void 0 : options.stream)) {
394
+ if (!options?.stream) {
372
395
  this.handleLine();
373
396
  this.emit(undefined);
374
397
  }
@@ -383,16 +406,16 @@ export class PgnParser {
383
406
  this.lineBuf = [];
384
407
  continuedLine: for (;;) {
385
408
  switch (this.state) {
386
- case 0 /* ParserState.Bom */:
409
+ case ParserState.Bom:
387
410
  if (line.startsWith(BOM))
388
411
  line = line.slice(BOM.length);
389
- this.state = 1 /* ParserState.Pre */; // fall through
390
- case 1 /* ParserState.Pre */:
412
+ this.state = ParserState.Pre; // fall through
413
+ case ParserState.Pre:
391
414
  if (isWhitespace(line) || isCommentLine(line))
392
415
  return;
393
416
  this.found = true;
394
- this.state = 2 /* ParserState.Headers */; // fall through
395
- case 2 /* ParserState.Headers */: {
417
+ this.state = ParserState.Headers; // fall through
418
+ case ParserState.Headers: {
396
419
  if (isCommentLine(line))
397
420
  return;
398
421
  let moreHeaders = true;
@@ -408,9 +431,9 @@ export class PgnParser {
408
431
  }
409
432
  if (isWhitespace(line))
410
433
  return;
411
- this.state = 3 /* ParserState.Moves */; // fall through
434
+ this.state = ParserState.Moves; // fall through
412
435
  }
413
- case 3 /* ParserState.Moves */: {
436
+ case ParserState.Moves: {
414
437
  if (freshLine) {
415
438
  if (isCommentLine(line))
416
439
  return;
@@ -463,7 +486,7 @@ export class PgnParser {
463
486
  const openIndex = tokenRegex.lastIndex;
464
487
  const beginIndex = line[openIndex] === " " ? openIndex + 1 : openIndex;
465
488
  line = line.slice(beginIndex);
466
- this.state = 4 /* ParserState.Comment */;
489
+ this.state = ParserState.Comment;
467
490
  continue continuedLine;
468
491
  }
469
492
  else {
@@ -486,7 +509,7 @@ export class PgnParser {
486
509
  }
487
510
  return;
488
511
  }
489
- case 4 /* ParserState.Comment */: {
512
+ case ParserState.Comment: {
490
513
  const closeIndex = line.indexOf("}");
491
514
  if (closeIndex === -1) {
492
515
  this.commentBuf.push(line);
@@ -497,7 +520,7 @@ export class PgnParser {
497
520
  this.commentBuf.push(line.slice(0, endIndex));
498
521
  this.handleComment();
499
522
  line = line.slice(closeIndex);
500
- this.state = 3 /* ParserState.Moves */;
523
+ this.state = ParserState.Moves;
501
524
  freshLine = false;
502
525
  }
503
526
  }
@@ -508,35 +531,33 @@ export class PgnParser {
508
531
  this.game.headers.set(name, name === "Result" ? makeOutcome(parseOutcome(value)) : value);
509
532
  }
510
533
  handleNag(nag) {
511
- var _a;
512
534
  this.consumeBudget(50);
513
535
  const frame = this.stack[this.stack.length - 1];
514
536
  if (frame.node) {
515
- (_a = frame.node.data).nags || (_a.nags = []);
537
+ frame.node.data.nags ||= [];
516
538
  frame.node.data.nags.push(nag);
517
539
  }
518
540
  }
519
541
  handleComment() {
520
- var _a, _b;
521
542
  this.consumeBudget(100);
522
543
  const frame = this.stack[this.stack.length - 1];
523
544
  const comment = this.commentBuf.join("\n");
524
545
  this.commentBuf = [];
525
546
  if (frame.node) {
526
- (_a = frame.node.data).comments || (_a.comments = []);
547
+ frame.node.data.comments ||= [];
527
548
  frame.node.data.comments.push(comment);
528
549
  }
529
550
  else if (frame.root) {
530
- (_b = this.game).comments || (_b.comments = []);
551
+ this.game.comments ||= [];
531
552
  this.game.comments.push(comment);
532
553
  }
533
554
  else {
534
- frame.startingComments || (frame.startingComments = []);
555
+ frame.startingComments ||= [];
535
556
  frame.startingComments.push(comment);
536
557
  }
537
558
  }
538
559
  emit(err) {
539
- if (this.state === 4 /* ParserState.Comment */)
560
+ if (this.state === ParserState.Comment)
540
561
  this.handleComment();
541
562
  if (err)
542
563
  return this.emitGame(this.game, err);
@@ -766,4 +787,3 @@ export const parseComment = (comment) => {
766
787
  evaluation,
767
788
  };
768
789
  };
769
- //# sourceMappingURL=pgn.js.map
@@ -0,0 +1,31 @@
1
+ import type { Color, Square, PieceType, Move } from "@connectorvol/shared";
2
+ import type { Rules } from "./types.js";
3
+ import { type Position } from "./variant.js";
4
+ /** Представляет обёртку над позицией chessops с реактивным состоянием, SAN и удобными операциями для UI. */
5
+ export declare class PgnOps {
6
+ pos: Position;
7
+ rule: Rules;
8
+ constructor(fen: string, rule: Rules);
9
+ turn(): Color;
10
+ getAllPossibleMoves(): string[];
11
+ moves(square: Square): ("a1" | "a2" | "a3" | "a4" | "a5" | "a6" | "a7" | "a8" | "b1" | "b2" | "b3" | "b4" | "b5" | "b6" | "b7" | "b8" | "c1" | "c2" | "c3" | "c4" | "c5" | "c6" | "c7" | "c8" | "d1" | "d2" | "d3" | "d4" | "d5" | "d6" | "d7" | "d8" | "e1" | "e2" | "e3" | "e4" | "e5" | "e6" | "e7" | "e8" | "f1" | "f2" | "f3" | "f4" | "f5" | "f6" | "f7" | "f8" | "g1" | "g2" | "g3" | "g4" | "g5" | "g6" | "g7" | "g8" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "h7" | "h8")[];
12
+ /** Представляет получение SAN-нотации для хода без его выполнения. */
13
+ getSanForMove(move: Pick<Move, "from" | "to" | "promotion">): string;
14
+ makeMove(move: Pick<Move, "from" | "to" | "promotion" | "flags">): {
15
+ ply: number;
16
+ fullMoves: number;
17
+ san: string;
18
+ move: {
19
+ from: string;
20
+ to: string;
21
+ promotion: PieceType | undefined;
22
+ flags: string;
23
+ };
24
+ };
25
+ makeSanMove(move: string): Move;
26
+ fen(): string;
27
+ /** Представляет установку FEN; при передаче rule обновляет и запомненный вариант. */
28
+ setFen(fen: string, rule?: Rules): void;
29
+ /** Представляет сброс позиции на стартовую для текущего варианта. */
30
+ reset(): void;
31
+ }
@@ -0,0 +1,122 @@
1
+ import { calculatePly } from "@connectorvol/shared";
2
+ import { chessgroundDests } from "./compat.js";
3
+ import { INITIAL_FEN, makeFen, parseFen } from "./fen.js";
4
+ import { makeSan, parseSan } from "./san.js";
5
+ import { makeSquare, parseSquare } from "./util.js";
6
+ import { Antichess, Atomic, castlingSide, Chess, Crazyhouse, Horde, KingOfTheHill, RacingKings, ThreeCheck, } from "./variant.js";
7
+ /** Представляет обёртку над позицией chessops с реактивным состоянием, SAN и удобными операциями для UI. */
8
+ export class PgnOps {
9
+ pos;
10
+ rule;
11
+ constructor(fen, rule) {
12
+ this.rule = $state(rule);
13
+ this.pos = $derived(setPosition(fen, rule));
14
+ }
15
+ turn() {
16
+ return this.pos.turn === "white" ? "w" : "b";
17
+ }
18
+ getAllPossibleMoves() {
19
+ const dests = chessgroundDests(this.pos);
20
+ const result = [];
21
+ for (const [from, tos] of dests) {
22
+ for (const to of tos) {
23
+ result.push(makeSan(this.pos, { from: parseSquare(from), to: parseSquare(to) }));
24
+ }
25
+ }
26
+ return result;
27
+ }
28
+ moves(square) {
29
+ const dests = chessgroundDests(this.pos).get(square) ?? [];
30
+ return dests;
31
+ }
32
+ /** Представляет получение SAN-нотации для хода без его выполнения. */
33
+ getSanForMove(move) {
34
+ const mov = {
35
+ from: parseSquare(move.from) ?? 0,
36
+ to: parseSquare(move.to) ?? 0,
37
+ promotion: move.promotion ? promotionMap[move.promotion] : undefined,
38
+ };
39
+ return makeSan(this.pos, mov);
40
+ }
41
+ makeMove(move) {
42
+ const mov = {
43
+ from: parseSquare(move.from) ?? 0,
44
+ to: parseSquare(move.to) ?? 0,
45
+ promotion: move.promotion ? promotionMap[move.promotion] : undefined,
46
+ };
47
+ let flags = move.flags ?? "";
48
+ const castling = castlingSide(this.pos, mov);
49
+ if (castling) {
50
+ flags = castling === "a" ? "q" : "k";
51
+ }
52
+ const san = makeSan(this.pos, mov);
53
+ this.pos.play(mov);
54
+ const fen = makeFen(this.pos.toSetup());
55
+ const { halfMoves, fullMoves } = calculatePly(fen);
56
+ const moveRecord = {
57
+ from: move.from,
58
+ to: move.to,
59
+ promotion: move.promotion,
60
+ flags,
61
+ };
62
+ return { ply: halfMoves, fullMoves, san, move: moveRecord };
63
+ }
64
+ makeSanMove(move) {
65
+ const mov = parseSan(this.pos, move);
66
+ if (mov) {
67
+ this.pos.play(mov);
68
+ if ("from" in mov) {
69
+ return {
70
+ from: makeSquare(mov.from),
71
+ to: makeSquare(mov.to),
72
+ };
73
+ }
74
+ }
75
+ throw new Error("Invalid move");
76
+ }
77
+ fen() {
78
+ return makeFen(this.pos.toSetup());
79
+ }
80
+ /** Представляет установку FEN; при передаче rule обновляет и запомненный вариант. */
81
+ setFen(fen, rule) {
82
+ if (rule !== undefined) {
83
+ this.rule = rule;
84
+ }
85
+ this.pos = setPosition(fen, this.rule);
86
+ }
87
+ /** Представляет сброс позиции на стартовую для текущего варианта. */
88
+ reset() {
89
+ this.pos = setPosition(INITIAL_FEN, this.rule);
90
+ }
91
+ }
92
+ function setPosition(fen, rule) {
93
+ const setup = parseFen(fen).unwrap();
94
+ switch (rule) {
95
+ case "kingofthehill":
96
+ return KingOfTheHill.fromSetup(setup).unwrap();
97
+ case "chess":
98
+ return Chess.fromSetup(setup).unwrap();
99
+ case "antichess":
100
+ return Antichess.fromSetup(setup).unwrap();
101
+ case "3check":
102
+ return ThreeCheck.fromSetup(setup).unwrap();
103
+ case "atomic":
104
+ return Atomic.fromSetup(setup).unwrap();
105
+ case "horde":
106
+ return Horde.fromSetup(setup).unwrap();
107
+ case "racingkings":
108
+ return RacingKings.fromSetup(setup).unwrap();
109
+ case "crazyhouse":
110
+ return Crazyhouse.fromSetup(setup).unwrap();
111
+ default:
112
+ return Chess.fromSetup(setup).unwrap();
113
+ }
114
+ }
115
+ const promotionMap = {
116
+ q: "queen",
117
+ r: "rook",
118
+ b: "bishop",
119
+ n: "knight",
120
+ p: "pawn",
121
+ k: "king",
122
+ };