@mirasen/chessboard 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +96 -0
- package/assets/pieces/chessnut/ATTRIBUTION.md +13 -0
- package/assets/pieces/chessnut/LICENSE.txt +202 -0
- package/assets/pieces/chessnut/bB.svg +58 -0
- package/assets/pieces/chessnut/bK.svg +51 -0
- package/assets/pieces/chessnut/bN.svg +19 -0
- package/assets/pieces/chessnut/bP.svg +17 -0
- package/assets/pieces/chessnut/bQ.svg +97 -0
- package/assets/pieces/chessnut/bR.svg +34 -0
- package/assets/pieces/chessnut/wB.svg +61 -0
- package/assets/pieces/chessnut/wK.svg +71 -0
- package/assets/pieces/chessnut/wN.svg +19 -0
- package/assets/pieces/chessnut/wP.svg +17 -0
- package/assets/pieces/chessnut/wQ.svg +40 -0
- package/assets/pieces/chessnut/wR.svg +38 -0
- package/dist/animation/planner.d.ts +6 -0
- package/dist/animation/planner.js +128 -0
- package/dist/animation/render/fade.d.ts +7 -0
- package/dist/animation/render/fade.js +24 -0
- package/dist/animation/render/move.d.ts +7 -0
- package/dist/animation/render/move.js +28 -0
- package/dist/animation/render/plan.d.ts +14 -0
- package/dist/animation/render/plan.js +69 -0
- package/dist/animation/render/static.d.ts +7 -0
- package/dist/animation/render/static.js +21 -0
- package/dist/animation/render/types.d.ts +21 -0
- package/dist/animation/render/types.js +1 -0
- package/dist/animation/types.d.ts +46 -0
- package/dist/animation/types.js +6 -0
- package/dist/extensions/animation/factory.d.ts +3 -0
- package/dist/extensions/animation/factory.js +88 -0
- package/dist/extensions/animation/types.d.ts +11 -0
- package/dist/extensions/animation/types.js +1 -0
- package/dist/extensions/factory/main.d.ts +2 -0
- package/dist/extensions/factory/main.js +101 -0
- package/dist/extensions/factory/runtime.d.ts +5 -0
- package/dist/extensions/factory/runtime.js +43 -0
- package/dist/extensions/first-party/active-target/factory.d.ts +2 -0
- package/dist/extensions/first-party/active-target/factory.js +109 -0
- package/dist/extensions/first-party/active-target/types.d.ts +25 -0
- package/dist/extensions/first-party/active-target/types.js +15 -0
- package/dist/extensions/first-party/board-events/factory.d.ts +2 -0
- package/dist/extensions/first-party/board-events/factory.js +65 -0
- package/dist/extensions/first-party/board-events/types.d.ts +27 -0
- package/dist/extensions/first-party/board-events/types.js +2 -0
- package/dist/extensions/first-party/common/helpers.d.ts +8 -0
- package/dist/extensions/first-party/common/helpers.js +33 -0
- package/dist/extensions/first-party/common/types.d.ts +10 -0
- package/dist/extensions/first-party/common/types.js +1 -0
- package/dist/extensions/first-party/last-move/factory.d.ts +2 -0
- package/dist/extensions/first-party/last-move/factory.js +106 -0
- package/dist/extensions/first-party/last-move/types.d.ts +19 -0
- package/dist/extensions/first-party/last-move/types.js +6 -0
- package/dist/extensions/first-party/legal-moves/factory.d.ts +2 -0
- package/dist/extensions/first-party/legal-moves/factory.js +101 -0
- package/dist/extensions/first-party/legal-moves/types.d.ts +29 -0
- package/dist/extensions/first-party/legal-moves/types.js +19 -0
- package/dist/extensions/first-party/main-renderer/animation/factory.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/animation/factory.js +35 -0
- package/dist/extensions/first-party/main-renderer/animation/render.d.ts +7 -0
- package/dist/extensions/first-party/main-renderer/animation/render.js +46 -0
- package/dist/extensions/first-party/main-renderer/animation/types.d.ts +24 -0
- package/dist/extensions/first-party/main-renderer/animation/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/animation/update.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/animation/update.js +40 -0
- package/dist/extensions/first-party/main-renderer/board/factory.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/board/factory.js +16 -0
- package/dist/extensions/first-party/main-renderer/board/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/board/render.js +24 -0
- package/dist/extensions/first-party/main-renderer/board/types.d.ts +10 -0
- package/dist/extensions/first-party/main-renderer/board/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/board/update.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/board/update.js +27 -0
- package/dist/extensions/first-party/main-renderer/coordinates/factory.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/coordinates/factory.js +9 -0
- package/dist/extensions/first-party/main-renderer/coordinates/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/coordinates/render.js +60 -0
- package/dist/extensions/first-party/main-renderer/coordinates/types.d.ts +8 -0
- package/dist/extensions/first-party/main-renderer/coordinates/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/drag/factory.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/drag/factory.js +23 -0
- package/dist/extensions/first-party/main-renderer/drag/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/drag/render.js +27 -0
- package/dist/extensions/first-party/main-renderer/drag/types.d.ts +16 -0
- package/dist/extensions/first-party/main-renderer/drag/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/drag/update.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/drag/update.js +23 -0
- package/dist/extensions/first-party/main-renderer/factory.d.ts +2 -0
- package/dist/extensions/first-party/main-renderer/factory.js +95 -0
- package/dist/extensions/first-party/main-renderer/normalize.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/normalize.js +27 -0
- package/dist/extensions/first-party/main-renderer/pieces/factory.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/pieces/factory.js +27 -0
- package/dist/extensions/first-party/main-renderer/pieces/render.d.ts +3 -0
- package/dist/extensions/first-party/main-renderer/pieces/render.js +45 -0
- package/dist/extensions/first-party/main-renderer/pieces/suppress.d.ts +5 -0
- package/dist/extensions/first-party/main-renderer/pieces/suppress.js +9 -0
- package/dist/extensions/first-party/main-renderer/pieces/types.d.ts +20 -0
- package/dist/extensions/first-party/main-renderer/pieces/types.js +1 -0
- package/dist/extensions/first-party/main-renderer/pieces/update.d.ts +6 -0
- package/dist/extensions/first-party/main-renderer/pieces/update.js +31 -0
- package/dist/extensions/first-party/main-renderer/types/extension.d.ts +15 -0
- package/dist/extensions/first-party/main-renderer/types/extension.js +10 -0
- package/dist/extensions/first-party/main-renderer/types/input.d.ts +4 -0
- package/dist/extensions/first-party/main-renderer/types/input.js +1 -0
- package/dist/extensions/first-party/main-renderer/types/instance.d.ts +16 -0
- package/dist/extensions/first-party/main-renderer/types/instance.js +1 -0
- package/dist/extensions/first-party/main-renderer/types/internal.d.ts +17 -0
- package/dist/extensions/first-party/main-renderer/types/internal.js +30 -0
- package/dist/extensions/first-party/main-renderer/types/template.d.ts +5 -0
- package/dist/extensions/first-party/main-renderer/types/template.js +1 -0
- package/dist/extensions/first-party/selected-square/factory.d.ts +2 -0
- package/dist/extensions/first-party/selected-square/factory.js +88 -0
- package/dist/extensions/first-party/selected-square/types.d.ts +18 -0
- package/dist/extensions/first-party/selected-square/types.js +6 -0
- package/dist/extensions/index.d.ts +8 -0
- package/dist/extensions/index.js +6 -0
- package/dist/extensions/invalidation/factory.d.ts +2 -0
- package/dist/extensions/invalidation/factory.js +22 -0
- package/dist/extensions/invalidation/types.d.ts +11 -0
- package/dist/extensions/invalidation/types.js +1 -0
- package/dist/extensions/types/basic/animation.d.ts +28 -0
- package/dist/extensions/types/basic/animation.js +6 -0
- package/dist/extensions/types/basic/events.d.ts +34 -0
- package/dist/extensions/types/basic/events.js +7 -0
- package/dist/extensions/types/basic/mount.d.ts +7 -0
- package/dist/extensions/types/basic/mount.js +14 -0
- package/dist/extensions/types/basic/render.d.ts +9 -0
- package/dist/extensions/types/basic/render.js +1 -0
- package/dist/extensions/types/basic/transient-visuals.d.ts +10 -0
- package/dist/extensions/types/basic/transient-visuals.js +1 -0
- package/dist/extensions/types/basic/update.d.ts +16 -0
- package/dist/extensions/types/basic/update.js +11 -0
- package/dist/extensions/types/context/animation.d.ts +31 -0
- package/dist/extensions/types/context/animation.js +9 -0
- package/dist/extensions/types/context/render.d.ts +6 -0
- package/dist/extensions/types/context/render.js +1 -0
- package/dist/extensions/types/context/transient-visuals.d.ts +7 -0
- package/dist/extensions/types/context/transient-visuals.js +1 -0
- package/dist/extensions/types/context/ui-move.d.ts +16 -0
- package/dist/extensions/types/context/ui-move.js +1 -0
- package/dist/extensions/types/context/update.d.ts +25 -0
- package/dist/extensions/types/context/update.js +10 -0
- package/dist/extensions/types/extension.d.ts +40 -0
- package/dist/extensions/types/extension.js +1 -0
- package/dist/extensions/types/main.d.ts +44 -0
- package/dist/extensions/types/main.js +1 -0
- package/dist/extensions/types/surface/commands.d.ts +26 -0
- package/dist/extensions/types/surface/commands.js +1 -0
- package/dist/extensions/types/surface/events.d.ts +5 -0
- package/dist/extensions/types/surface/events.js +1 -0
- package/dist/extensions/types/surface/main.d.ts +10 -0
- package/dist/extensions/types/surface/main.js +1 -0
- package/dist/extensions/types/surface/transient-visuals.d.ts +4 -0
- package/dist/extensions/types/surface/transient-visuals.js +1 -0
- package/dist/extensions/types/wrapper.d.ts +26 -0
- package/dist/extensions/types/wrapper.js +11 -0
- package/dist/extensions/update.d.ts +4 -0
- package/dist/extensions/update.js +29 -0
- package/dist/helpers/util.d.ts +1 -0
- package/dist/helpers/util.js +9 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -0
- package/dist/layout/factory.d.ts +2 -0
- package/dist/layout/factory.js +33 -0
- package/dist/layout/geometry/factory.d.ts +12 -0
- package/dist/layout/geometry/factory.js +33 -0
- package/dist/layout/geometry/types.d.ts +20 -0
- package/dist/layout/geometry/types.js +1 -0
- package/dist/layout/helpers.d.ts +4 -0
- package/dist/layout/helpers.js +6 -0
- package/dist/layout/mutation.d.ts +6 -0
- package/dist/layout/mutation.js +1 -0
- package/dist/layout/reducers.d.ts +2 -0
- package/dist/layout/reducers.js +30 -0
- package/dist/layout/types.d.ts +23 -0
- package/dist/layout/types.js +1 -0
- package/dist/mutation/pipeline.d.ts +2 -0
- package/dist/mutation/pipeline.js +36 -0
- package/dist/mutation/session.d.ts +3 -0
- package/dist/mutation/session.js +66 -0
- package/dist/mutation/types.d.ts +26 -0
- package/dist/mutation/types.js +1 -0
- package/dist/render/factory.d.ts +2 -0
- package/dist/render/factory.js +117 -0
- package/dist/render/mount.d.ts +3 -0
- package/dist/render/mount.js +28 -0
- package/dist/render/rendering/animation.d.ts +13 -0
- package/dist/render/rendering/animation.js +92 -0
- package/dist/render/rendering/helpers.d.ts +3 -0
- package/dist/render/rendering/helpers.js +10 -0
- package/dist/render/rendering/state.d.ts +4 -0
- package/dist/render/rendering/state.js +48 -0
- package/dist/render/rendering/visuals.d.ts +3 -0
- package/dist/render/rendering/visuals.js +21 -0
- package/dist/render/scheduler/scheduler.d.ts +2 -0
- package/dist/render/scheduler/scheduler.js +53 -0
- package/dist/render/scheduler/types.d.ts +12 -0
- package/dist/render/scheduler/types.js +1 -0
- package/dist/render/svg/factory.d.ts +4 -0
- package/dist/render/svg/factory.js +38 -0
- package/dist/render/svg/helpers.d.ts +18 -0
- package/dist/render/svg/helpers.js +34 -0
- package/dist/render/types.d.ts +42 -0
- package/dist/render/types.js +1 -0
- package/dist/runtime/factory/helpers.d.ts +6 -0
- package/dist/runtime/factory/helpers.js +42 -0
- package/dist/runtime/factory/input.d.ts +3 -0
- package/dist/runtime/factory/input.js +98 -0
- package/dist/runtime/factory/main.d.ts +2 -0
- package/dist/runtime/factory/main.js +182 -0
- package/dist/runtime/factory/ui-move.d.ts +4 -0
- package/dist/runtime/factory/ui-move.js +84 -0
- package/dist/runtime/input/adapter/factory.d.ts +2 -0
- package/dist/runtime/input/adapter/factory.js +55 -0
- package/dist/runtime/input/adapter/helpers.d.ts +5 -0
- package/dist/runtime/input/adapter/helpers.js +23 -0
- package/dist/runtime/input/adapter/pointer.d.ts +13 -0
- package/dist/runtime/input/adapter/pointer.js +97 -0
- package/dist/runtime/input/adapter/types.d.ts +16 -0
- package/dist/runtime/input/adapter/types.js +1 -0
- package/dist/runtime/input/controller/factory.d.ts +2 -0
- package/dist/runtime/input/controller/factory.js +32 -0
- package/dist/runtime/input/controller/helpers.d.ts +3 -0
- package/dist/runtime/input/controller/helpers.js +12 -0
- package/dist/runtime/input/controller/pointer.d.ts +7 -0
- package/dist/runtime/input/controller/pointer.js +104 -0
- package/dist/runtime/input/controller/transient-visuals.d.ts +3 -0
- package/dist/runtime/input/controller/transient-visuals.js +12 -0
- package/dist/runtime/input/controller/types.d.ts +25 -0
- package/dist/runtime/input/controller/types.js +1 -0
- package/dist/runtime/layout.d.ts +2 -0
- package/dist/runtime/layout.js +10 -0
- package/dist/runtime/lifecycle.d.ts +12 -0
- package/dist/runtime/lifecycle.js +49 -0
- package/dist/runtime/mutation/extension-update.d.ts +2 -0
- package/dist/runtime/mutation/extension-update.js +26 -0
- package/dist/runtime/mutation/factory.d.ts +2 -0
- package/dist/runtime/mutation/factory.js +47 -0
- package/dist/runtime/mutation/interaction.d.ts +2 -0
- package/dist/runtime/mutation/interaction.js +34 -0
- package/dist/runtime/mutation/invalidation.d.ts +0 -0
- package/dist/runtime/mutation/invalidation.js +2 -0
- package/dist/runtime/mutation/last-move.d.ts +3 -0
- package/dist/runtime/mutation/last-move.js +19 -0
- package/dist/runtime/mutation/layout.d.ts +2 -0
- package/dist/runtime/mutation/layout.js +8 -0
- package/dist/runtime/mutation/pipeline.d.ts +22 -0
- package/dist/runtime/mutation/pipeline.js +1 -0
- package/dist/runtime/mutation/request-render.d.ts +2 -0
- package/dist/runtime/mutation/request-render.js +29 -0
- package/dist/runtime/mutation/run.d.ts +2 -0
- package/dist/runtime/mutation/run.js +3 -0
- package/dist/runtime/mutation/types.d.ts +14 -0
- package/dist/runtime/mutation/types.js +1 -0
- package/dist/runtime/types/main.d.ts +36 -0
- package/dist/runtime/types/main.js +1 -0
- package/dist/runtime/types/ui-move.d.ts +9 -0
- package/dist/runtime/types/ui-move.js +1 -0
- package/dist/state/board/check.d.ts +27 -0
- package/dist/state/board/check.js +148 -0
- package/dist/state/board/coords.d.ts +4 -0
- package/dist/state/board/coords.js +9 -0
- package/dist/state/board/denormalize.d.ts +11 -0
- package/dist/state/board/denormalize.js +77 -0
- package/dist/state/board/factory.d.ts +3 -0
- package/dist/state/board/factory.js +46 -0
- package/dist/state/board/mutation.d.ts +9 -0
- package/dist/state/board/mutation.js +1 -0
- package/dist/state/board/normalize.d.ts +8 -0
- package/dist/state/board/normalize.js +76 -0
- package/dist/state/board/piece.d.ts +3 -0
- package/dist/state/board/piece.js +11 -0
- package/dist/state/board/position.d.ts +4 -0
- package/dist/state/board/position.js +94 -0
- package/dist/state/board/reducers.d.ts +8 -0
- package/dist/state/board/reducers.js +80 -0
- package/dist/state/board/types/input.d.ts +35 -0
- package/dist/state/board/types/input.js +1 -0
- package/dist/state/board/types/internal.d.ts +54 -0
- package/dist/state/board/types/internal.js +17 -0
- package/dist/state/board/types/main.d.ts +18 -0
- package/dist/state/board/types/main.js +1 -0
- package/dist/state/board/types/output.d.ts +5 -0
- package/dist/state/board/types/output.js +1 -0
- package/dist/state/board/types/template.d.ts +23 -0
- package/dist/state/board/types/template.js +1 -0
- package/dist/state/change/factory.d.ts +2 -0
- package/dist/state/change/factory.js +28 -0
- package/dist/state/change/helpers.d.ts +8 -0
- package/dist/state/change/helpers.js +86 -0
- package/dist/state/change/mutation.d.ts +6 -0
- package/dist/state/change/mutation.js +1 -0
- package/dist/state/change/reducers.d.ts +5 -0
- package/dist/state/change/reducers.js +16 -0
- package/dist/state/change/types.d.ts +17 -0
- package/dist/state/change/types.js +1 -0
- package/dist/state/factory.d.ts +2 -0
- package/dist/state/factory.js +24 -0
- package/dist/state/interaction/factory.d.ts +2 -0
- package/dist/state/interaction/factory.js +83 -0
- package/dist/state/interaction/helpers.d.ts +4 -0
- package/dist/state/interaction/helpers.js +16 -0
- package/dist/state/interaction/movability.d.ts +5 -0
- package/dist/state/interaction/movability.js +87 -0
- package/dist/state/interaction/mutation.d.ts +11 -0
- package/dist/state/interaction/mutation.js +1 -0
- package/dist/state/interaction/normalize.d.ts +5 -0
- package/dist/state/interaction/normalize.js +50 -0
- package/dist/state/interaction/reducers.d.ts +11 -0
- package/dist/state/interaction/reducers.js +81 -0
- package/dist/state/interaction/types/input.d.ts +18 -0
- package/dist/state/interaction/types/input.js +1 -0
- package/dist/state/interaction/types/internal.d.ts +35 -0
- package/dist/state/interaction/types/internal.js +1 -0
- package/dist/state/interaction/types/main.d.ts +33 -0
- package/dist/state/interaction/types/main.js +1 -0
- package/dist/state/types.d.ts +30 -0
- package/dist/state/types.js +1 -0
- package/dist/state/view/factory.d.ts +2 -0
- package/dist/state/view/factory.js +24 -0
- package/dist/state/view/mutation.d.ts +5 -0
- package/dist/state/view/mutation.js +1 -0
- package/dist/state/view/reducers.d.ts +3 -0
- package/dist/state/view/reducers.js +6 -0
- package/dist/state/view/types/internal.d.ts +6 -0
- package/dist/state/view/types/internal.js +1 -0
- package/dist/state/view/types/main.d.ts +12 -0
- package/dist/state/view/types/main.js +1 -0
- package/dist/wrapper/factory.d.ts +3 -0
- package/dist/wrapper/factory.js +61 -0
- package/dist/wrapper/types.d.ts +56 -0
- package/dist/wrapper/types.js +1 -0
- package/package.json +98 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { isPieceString, isRolePromotionCode, isValidSquare } from './check';
|
|
2
|
+
import { FILE_START, RANK_START } from './types/internal';
|
|
3
|
+
export function normalizeColor(input) {
|
|
4
|
+
switch (input) {
|
|
5
|
+
case 'white':
|
|
6
|
+
case 'w':
|
|
7
|
+
return 0 /* ColorCode.White */;
|
|
8
|
+
case 'black':
|
|
9
|
+
case 'b':
|
|
10
|
+
return 8 /* ColorCode.Black */;
|
|
11
|
+
default:
|
|
12
|
+
throw new RangeError(`Invalid color input: ${input}`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function normalizeRole(input) {
|
|
16
|
+
switch (input) {
|
|
17
|
+
case 'P':
|
|
18
|
+
case 'pawn':
|
|
19
|
+
return 1 /* RoleCode.Pawn */;
|
|
20
|
+
case 'N':
|
|
21
|
+
case 'knight':
|
|
22
|
+
return 2 /* RoleCode.Knight */;
|
|
23
|
+
case 'B':
|
|
24
|
+
case 'bishop':
|
|
25
|
+
return 3 /* RoleCode.Bishop */;
|
|
26
|
+
case 'R':
|
|
27
|
+
case 'rook':
|
|
28
|
+
return 4 /* RoleCode.Rook */;
|
|
29
|
+
case 'Q':
|
|
30
|
+
case 'queen':
|
|
31
|
+
return 5 /* RoleCode.Queen */;
|
|
32
|
+
case 'K':
|
|
33
|
+
case 'king':
|
|
34
|
+
return 6 /* RoleCode.King */;
|
|
35
|
+
default:
|
|
36
|
+
throw new RangeError(`Invalid role input: ${input}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function normalizePiece(input) {
|
|
40
|
+
const [color, role] = isPieceString(input)
|
|
41
|
+
? [input[0], input[1]]
|
|
42
|
+
: [input.color, input.role];
|
|
43
|
+
const colorCode = normalizeColor(color);
|
|
44
|
+
const roleCode = normalizeRole(role);
|
|
45
|
+
return colorCode + roleCode;
|
|
46
|
+
}
|
|
47
|
+
export function normalizeRolePromotion(input) {
|
|
48
|
+
const role = normalizeRole(input);
|
|
49
|
+
if (!isRolePromotionCode(role)) {
|
|
50
|
+
throw new RangeError(`Invalid role promotion input (cannot promote to ${role}): ${input}`);
|
|
51
|
+
}
|
|
52
|
+
return role;
|
|
53
|
+
}
|
|
54
|
+
export function normalizeSquare(s) {
|
|
55
|
+
const file = Math.trunc(s.charCodeAt(0) - FILE_START);
|
|
56
|
+
const rank = Math.trunc(s.charCodeAt(1) - RANK_START);
|
|
57
|
+
const sq = Math.trunc(rank * 8 + file);
|
|
58
|
+
if (!isValidSquare(sq)) {
|
|
59
|
+
throw new TypeError(`Invalid algebraic square: ${s}`);
|
|
60
|
+
}
|
|
61
|
+
return sq;
|
|
62
|
+
}
|
|
63
|
+
export function normalizeMoveRequest(move) {
|
|
64
|
+
return {
|
|
65
|
+
from: normalizeSquare(move.from),
|
|
66
|
+
to: normalizeSquare(move.to),
|
|
67
|
+
...(move.capturedSquare && { capturedSquare: normalizeSquare(move.capturedSquare) }),
|
|
68
|
+
...(move.promotedTo && { promotedTo: normalizeRolePromotion(move.promotedTo) }),
|
|
69
|
+
...(move.secondary && {
|
|
70
|
+
secondary: {
|
|
71
|
+
from: normalizeSquare(move.secondary.from),
|
|
72
|
+
to: normalizeSquare(move.secondary.to)
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function toPieceCode(role, color) {
|
|
2
|
+
return color + role;
|
|
3
|
+
}
|
|
4
|
+
export function fromPieceCode(code) {
|
|
5
|
+
if (code <= 0 /* PieceCode.Empty */) {
|
|
6
|
+
throw new RangeError(`Invalid piece code: ${code}`);
|
|
7
|
+
}
|
|
8
|
+
const color = code >= 8 /* ColorCode.Black */ ? 8 /* ColorCode.Black */ : 0 /* ColorCode.White */;
|
|
9
|
+
const role = color === 8 /* ColorCode.Black */ ? code - 8 /* ColorCode.Black */ : code;
|
|
10
|
+
return { role: role, color };
|
|
11
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { PiecePositionInput, PositionInput } from './types/input';
|
|
2
|
+
import { ParsedPosition } from './types/internal';
|
|
3
|
+
export declare function boardParsePiecePositionInput(input: PiecePositionInput): Uint8Array;
|
|
4
|
+
export declare function boardParsePosition(input: PositionInput): ParsedPosition;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { parse } from '@echecs/fen';
|
|
2
|
+
import { normalizeColor, normalizePiece, normalizeSquare } from './normalize';
|
|
3
|
+
import { SQUARE_COUNT } from './types/internal';
|
|
4
|
+
const START_POSITION_RECORD_STRING = {
|
|
5
|
+
a1: 'wR',
|
|
6
|
+
b1: 'wN',
|
|
7
|
+
c1: 'wB',
|
|
8
|
+
d1: 'wQ',
|
|
9
|
+
e1: 'wK',
|
|
10
|
+
f1: 'wB',
|
|
11
|
+
g1: 'wN',
|
|
12
|
+
h1: 'wR',
|
|
13
|
+
a2: 'wP',
|
|
14
|
+
b2: 'wP',
|
|
15
|
+
c2: 'wP',
|
|
16
|
+
d2: 'wP',
|
|
17
|
+
e2: 'wP',
|
|
18
|
+
f2: 'wP',
|
|
19
|
+
g2: 'wP',
|
|
20
|
+
h2: 'wP',
|
|
21
|
+
a8: 'bR',
|
|
22
|
+
b8: 'bN',
|
|
23
|
+
c8: 'bB',
|
|
24
|
+
d8: 'bQ',
|
|
25
|
+
e8: 'bK',
|
|
26
|
+
f8: 'bB',
|
|
27
|
+
g8: 'bN',
|
|
28
|
+
h8: 'bR',
|
|
29
|
+
a7: 'bP',
|
|
30
|
+
b7: 'bP',
|
|
31
|
+
c7: 'bP',
|
|
32
|
+
d7: 'bP',
|
|
33
|
+
e7: 'bP',
|
|
34
|
+
f7: 'bP',
|
|
35
|
+
g7: 'bP',
|
|
36
|
+
h7: 'bP'
|
|
37
|
+
// All other squares are implicitly empty (undefined)
|
|
38
|
+
};
|
|
39
|
+
function boardParsePositionInputRecord(input) {
|
|
40
|
+
const out = new Uint8Array(SQUARE_COUNT);
|
|
41
|
+
for (const [sq, piece] of Object.entries(input)) {
|
|
42
|
+
const square = normalizeSquare(sq);
|
|
43
|
+
const pieceCode = normalizePiece(piece);
|
|
44
|
+
out[square] = pieceCode;
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
const START_POSITION_ARRAY = boardParsePositionInputRecord(START_POSITION_RECORD_STRING);
|
|
49
|
+
export function boardParsePiecePositionInput(input) {
|
|
50
|
+
const out = new Uint8Array(SQUARE_COUNT);
|
|
51
|
+
if (input === 'start') {
|
|
52
|
+
out.set(START_POSITION_ARRAY);
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
for (const [sq, piece] of Object.entries(input)) {
|
|
56
|
+
const square = normalizeSquare(sq);
|
|
57
|
+
const pieceCode = normalizePiece(piece);
|
|
58
|
+
out[square] = pieceCode;
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
function isPositionInputObject(input) {
|
|
63
|
+
return typeof input === 'object' && input !== null && !Array.isArray(input);
|
|
64
|
+
}
|
|
65
|
+
function boardParsePositionInputFen(input) {
|
|
66
|
+
const position = parse(input);
|
|
67
|
+
if (!position) {
|
|
68
|
+
throw new Error('Failed to parse FEN string');
|
|
69
|
+
}
|
|
70
|
+
const piecePositionRecord = {};
|
|
71
|
+
for (const [square, piece] of position.board) {
|
|
72
|
+
piecePositionRecord[square] = { role: piece.type, color: piece.color };
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
pieces: boardParsePositionInputRecord(piecePositionRecord),
|
|
76
|
+
turn: normalizeColor(position.turn)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
export function boardParsePosition(input) {
|
|
80
|
+
if (input === 'start') {
|
|
81
|
+
return {
|
|
82
|
+
pieces: START_POSITION_ARRAY,
|
|
83
|
+
turn: 0 /* ColorCode.White */
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (isPositionInputObject(input)) {
|
|
87
|
+
return {
|
|
88
|
+
pieces: boardParsePiecePositionInput(input.pieces ?? 'start'),
|
|
89
|
+
turn: normalizeColor(input.turn ?? 'white')
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// So this one is FEN string left
|
|
93
|
+
return boardParsePositionInputFen(input);
|
|
94
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ColorCode, Move, MoveRequest } from './types/internal';
|
|
2
|
+
import { BoardStateInternal } from './types/main';
|
|
3
|
+
export declare function boardSetPosition(state: BoardStateInternal, pieces: Uint8Array): boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Set active color turn.
|
|
6
|
+
*/
|
|
7
|
+
export declare function boardSetTurn(state: BoardStateInternal, turn: ColorCode): boolean;
|
|
8
|
+
export declare function boardMove(state: BoardStateInternal, request: MoveRequest): Move;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { isEmptyPieceCode } from './check';
|
|
2
|
+
import { denormalizeSquare } from './denormalize';
|
|
3
|
+
import { fromPieceCode, toPieceCode } from './piece';
|
|
4
|
+
export function boardSetPosition(state, pieces) {
|
|
5
|
+
state.pieces = new Uint8Array(pieces);
|
|
6
|
+
// Increment position epoch to prevent false animation across position resets
|
|
7
|
+
state.positionEpoch++;
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Set active color turn.
|
|
12
|
+
*/
|
|
13
|
+
export function boardSetTurn(state, turn) {
|
|
14
|
+
if (state.turn === turn)
|
|
15
|
+
return false; // no-op
|
|
16
|
+
state.turn = turn;
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
function buildMoveBase(state, request) {
|
|
20
|
+
const from = request.from;
|
|
21
|
+
const to = request.to;
|
|
22
|
+
if (from === to) {
|
|
23
|
+
throw new RangeError(`Source and destination squares are the same: ${from}`);
|
|
24
|
+
}
|
|
25
|
+
const moved = state.pieces[from];
|
|
26
|
+
if (isEmptyPieceCode(moved)) {
|
|
27
|
+
throw new RangeError(`Cannot move from empty square: ${from}`);
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
from,
|
|
31
|
+
to,
|
|
32
|
+
piece: moved
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function buildMove(state, request) {
|
|
36
|
+
const base = buildMoveBase(state, request);
|
|
37
|
+
let captured;
|
|
38
|
+
const captureSq = request.capturedSquare ?? request.to;
|
|
39
|
+
const codeAtCapture = state.pieces[captureSq];
|
|
40
|
+
if (!isEmptyPieceCode(codeAtCapture)) {
|
|
41
|
+
captured = { piece: codeAtCapture, square: captureSq };
|
|
42
|
+
}
|
|
43
|
+
let secondary;
|
|
44
|
+
if (request.secondary) {
|
|
45
|
+
secondary = buildMoveBase(state, request.secondary);
|
|
46
|
+
if (secondary.from === base.to ||
|
|
47
|
+
secondary.to === base.to ||
|
|
48
|
+
secondary.from === base.from ||
|
|
49
|
+
secondary.to === base.from) {
|
|
50
|
+
throw new RangeError(`Secondary move squares cannot overlap with primary move squares: ${denormalizeSquare(secondary.from)}, ${denormalizeSquare(secondary.to)} vs ${denormalizeSquare(base.from)}, ${denormalizeSquare(base.to)}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
...base,
|
|
55
|
+
...(captured && { captured }),
|
|
56
|
+
...(request.promotedTo && { promotedTo: request.promotedTo }),
|
|
57
|
+
...(secondary && { secondary })
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export function boardMove(state, request) {
|
|
61
|
+
const move = buildMove(state, request);
|
|
62
|
+
const moved = fromPieceCode(move.piece);
|
|
63
|
+
const newPieceCode = move.promotedTo
|
|
64
|
+
? toPieceCode(move.promotedTo, moved.color)
|
|
65
|
+
: move.piece;
|
|
66
|
+
state.pieces[move.to] = newPieceCode;
|
|
67
|
+
state.pieces[move.from] = 0 /* PieceCode.Empty */;
|
|
68
|
+
if (move.captured && move.captured.square !== move.to) {
|
|
69
|
+
state.pieces[move.captured.square] = 0 /* PieceCode.Empty */;
|
|
70
|
+
}
|
|
71
|
+
if (move.secondary) {
|
|
72
|
+
state.pieces[move.secondary.to] = move.secondary.piece;
|
|
73
|
+
state.pieces[move.secondary.from] = 0 /* PieceCode.Empty */;
|
|
74
|
+
}
|
|
75
|
+
// Toggle turn
|
|
76
|
+
state.turn = state.turn === 0 /* ColorCode.White */ ? 8 /* ColorCode.Black */ : 0 /* ColorCode.White */;
|
|
77
|
+
// Increment position epoch
|
|
78
|
+
state.positionEpoch++;
|
|
79
|
+
return move;
|
|
80
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { TMoveRequest } from './template';
|
|
2
|
+
export type Color = 'white' | 'black';
|
|
3
|
+
export type ColorShort = 'w' | 'b';
|
|
4
|
+
export type ColorInput = Color | ColorShort;
|
|
5
|
+
export type Role = 'pawn' | 'knight' | 'bishop' | 'rook' | 'queen' | 'king';
|
|
6
|
+
export type RoleShort = 'P' | 'N' | 'B' | 'R' | 'Q' | 'K';
|
|
7
|
+
export type RoleInput = Role | RoleShort;
|
|
8
|
+
export type RolePromotion = Exclude<Role, 'king' | 'pawn'>;
|
|
9
|
+
export type RolePromotionShort = Exclude<RoleShort, 'P' | 'K'>;
|
|
10
|
+
export type RolePromotionInput = RolePromotion | RolePromotionShort;
|
|
11
|
+
export type FileChar = 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h';
|
|
12
|
+
export type RankChar = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8';
|
|
13
|
+
export type SquareString = `${FileChar}${RankChar}`;
|
|
14
|
+
export interface Piece {
|
|
15
|
+
color: Color;
|
|
16
|
+
role: Role;
|
|
17
|
+
}
|
|
18
|
+
export interface PieceShort {
|
|
19
|
+
color: ColorShort;
|
|
20
|
+
role: RoleShort;
|
|
21
|
+
}
|
|
22
|
+
export type PieceString = `${ColorShort}${RoleShort}`;
|
|
23
|
+
export type PieceInput = Piece | PieceShort | PieceString;
|
|
24
|
+
export type PiecePositionRecord = Partial<Record<SquareString, Piece>>;
|
|
25
|
+
export type PiecePositionRecordShort = Partial<Record<SquareString, PieceShort>>;
|
|
26
|
+
export type PiecePositionRecordString = Partial<Record<SquareString, PieceString>>;
|
|
27
|
+
export type PiecePositionInputRecord = PiecePositionRecord | PiecePositionRecordShort | PiecePositionRecordString;
|
|
28
|
+
export type PiecePositionInput = 'start' | PiecePositionInputRecord;
|
|
29
|
+
export type PositionInputObject = {
|
|
30
|
+
pieces?: PiecePositionInput;
|
|
31
|
+
turn?: ColorInput;
|
|
32
|
+
};
|
|
33
|
+
export type FenString = string;
|
|
34
|
+
export type PositionInput = 'start' | PositionInputObject | FenString;
|
|
35
|
+
export type MoveRequestInput = TMoveRequest<SquareString, RolePromotionInput>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
2
|
+
import { TMove, TMoveBase, TMoveCaptured, TMoveRequest, TMoveRequestBase } from './template';
|
|
3
|
+
export type Square = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63;
|
|
4
|
+
export declare const SQUARE_COUNT = 64;
|
|
5
|
+
export type SquareFile = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
|
6
|
+
export type SquareRank = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7;
|
|
7
|
+
export declare const enum RoleCode {
|
|
8
|
+
Pawn = 1,
|
|
9
|
+
Knight = 2,
|
|
10
|
+
Bishop = 3,
|
|
11
|
+
Rook = 4,
|
|
12
|
+
Queen = 5,
|
|
13
|
+
King = 6
|
|
14
|
+
}
|
|
15
|
+
export type RolePromotionCode = Exclude<RoleCode, RoleCode.King | RoleCode.Pawn>;
|
|
16
|
+
export declare const enum ColorCode {
|
|
17
|
+
White = 0,
|
|
18
|
+
Black = 8
|
|
19
|
+
}
|
|
20
|
+
export declare const enum PieceCode {
|
|
21
|
+
Empty = 0,
|
|
22
|
+
WhitePawn = 1,
|
|
23
|
+
WhiteKnight = 2,
|
|
24
|
+
WhiteBishop = 3,
|
|
25
|
+
WhiteRook = 4,
|
|
26
|
+
WhiteQueen = 5,
|
|
27
|
+
WhiteKing = 6,
|
|
28
|
+
BlackPawn = 9,
|
|
29
|
+
BlackKnight = 10,
|
|
30
|
+
BlackBishop = 11,
|
|
31
|
+
BlackRook = 12,
|
|
32
|
+
BlackQueen = 13,
|
|
33
|
+
BlackKing = 14
|
|
34
|
+
}
|
|
35
|
+
export type EmptyPieceCode = Extract<PieceCode, PieceCode.Empty>;
|
|
36
|
+
export type NonEmptyPieceCode = Exclude<PieceCode, PieceCode.Empty>;
|
|
37
|
+
export declare const ALL_NON_EMPTY_PIECE_CODES: NonEmptyPieceCode[];
|
|
38
|
+
export interface PieceCoded {
|
|
39
|
+
role: RoleCode;
|
|
40
|
+
color: ColorCode;
|
|
41
|
+
}
|
|
42
|
+
export type MoveRequestBase = TMoveRequestBase<Square>;
|
|
43
|
+
export type MoveRequest = TMoveRequest<Square, RolePromotionCode>;
|
|
44
|
+
export type MoveBase = TMoveBase<Square, NonEmptyPieceCode>;
|
|
45
|
+
export type Move = TMove<Square, NonEmptyPieceCode, RolePromotionCode>;
|
|
46
|
+
export type MoveCaptured = TMoveCaptured<Square, NonEmptyPieceCode>;
|
|
47
|
+
export type MoveBaseSnapshot = ReadonlyDeep<MoveBase>;
|
|
48
|
+
export type MoveSnapshot = ReadonlyDeep<Move>;
|
|
49
|
+
export declare const FILE_START: number;
|
|
50
|
+
export declare const RANK_START: number;
|
|
51
|
+
export type ParsedPosition = {
|
|
52
|
+
pieces: Uint8Array;
|
|
53
|
+
turn: ColorCode;
|
|
54
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const SQUARE_COUNT = 64;
|
|
2
|
+
export const ALL_NON_EMPTY_PIECE_CODES = [
|
|
3
|
+
1 /* PieceCode.WhitePawn */,
|
|
4
|
+
2 /* PieceCode.WhiteKnight */,
|
|
5
|
+
3 /* PieceCode.WhiteBishop */,
|
|
6
|
+
4 /* PieceCode.WhiteRook */,
|
|
7
|
+
5 /* PieceCode.WhiteQueen */,
|
|
8
|
+
6 /* PieceCode.WhiteKing */,
|
|
9
|
+
9 /* PieceCode.BlackPawn */,
|
|
10
|
+
10 /* PieceCode.BlackKnight */,
|
|
11
|
+
11 /* PieceCode.BlackBishop */,
|
|
12
|
+
12 /* PieceCode.BlackRook */,
|
|
13
|
+
13 /* PieceCode.BlackQueen */,
|
|
14
|
+
14 /* PieceCode.BlackKing */
|
|
15
|
+
];
|
|
16
|
+
export const FILE_START = 'a'.charCodeAt(0);
|
|
17
|
+
export const RANK_START = '1'.charCodeAt(0);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ReadonlyDeep } from 'type-fest';
|
|
2
|
+
import { BoardStateMutationSession } from '../mutation';
|
|
3
|
+
import { ColorInput, MoveRequestInput, PiecePositionInput, PositionInput } from './input';
|
|
4
|
+
import { ColorCode, Move, MoveRequest, PieceCode, Square } from './internal';
|
|
5
|
+
export interface BoardStateInternal {
|
|
6
|
+
pieces: Uint8Array;
|
|
7
|
+
turn: ColorCode;
|
|
8
|
+
positionEpoch: number;
|
|
9
|
+
}
|
|
10
|
+
export type BoardStateSnapshot = ReadonlyDeep<BoardStateInternal>;
|
|
11
|
+
export interface BoardState {
|
|
12
|
+
setPosition(input: PositionInput, mutationSession: BoardStateMutationSession): boolean;
|
|
13
|
+
setPiecePosition(input: PiecePositionInput, mutationSession: BoardStateMutationSession): boolean;
|
|
14
|
+
setTurn(turn: ColorInput, mutationSession: BoardStateMutationSession): boolean;
|
|
15
|
+
move(request: MoveRequestInput | MoveRequest, mutationSession: BoardStateMutationSession): Move;
|
|
16
|
+
getPieceCodeAt(square: Square): PieceCode;
|
|
17
|
+
getSnapshot(): BoardStateSnapshot;
|
|
18
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { PieceString, RolePromotionShort, SquareString } from './input';
|
|
2
|
+
import { TMove, TMoveBase, TMoveCaptured } from './template';
|
|
3
|
+
export type MoveBaseOutput = TMoveBase<SquareString, PieceString>;
|
|
4
|
+
export type MoveCapturedOutput = TMoveCaptured<SquareString, PieceString>;
|
|
5
|
+
export type MoveOutput = TMove<SquareString, PieceString, RolePromotionShort>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface TMoveRequestBase<TSquare> {
|
|
2
|
+
from: TSquare;
|
|
3
|
+
to: TSquare;
|
|
4
|
+
}
|
|
5
|
+
export interface TMoveRequest<TSquare, TPromotion> extends TMoveRequestBase<TSquare> {
|
|
6
|
+
capturedSquare?: TSquare;
|
|
7
|
+
promotedTo?: TPromotion;
|
|
8
|
+
secondary?: TMoveRequestBase<TSquare>;
|
|
9
|
+
}
|
|
10
|
+
export interface TMoveCaptured<TSquare, TPiece> {
|
|
11
|
+
square: TSquare;
|
|
12
|
+
piece: TPiece;
|
|
13
|
+
}
|
|
14
|
+
export interface TMoveBase<TSquare, TPiece> {
|
|
15
|
+
from: TSquare;
|
|
16
|
+
to: TSquare;
|
|
17
|
+
piece: TPiece;
|
|
18
|
+
}
|
|
19
|
+
export interface TMove<TSquare, TPiece, TPromotion> extends TMoveBase<TSquare, TPiece> {
|
|
20
|
+
captured?: TMoveCaptured<TSquare, TPiece>;
|
|
21
|
+
promotedTo?: TPromotion;
|
|
22
|
+
secondary?: TMoveBase<TSquare, TPiece>;
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cloneDeep } from 'es-toolkit/object';
|
|
2
|
+
import { changeStateSetDeferredUIMoveRequestContext, changeStateSetLastMove } from './reducers';
|
|
3
|
+
function createChangeStateInternal() {
|
|
4
|
+
return {
|
|
5
|
+
lastMove: null,
|
|
6
|
+
deferredUIMoveRequestContext: null
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function createChangeState() {
|
|
10
|
+
const internalState = createChangeStateInternal();
|
|
11
|
+
return {
|
|
12
|
+
get lastMove() {
|
|
13
|
+
return cloneDeep(internalState.lastMove);
|
|
14
|
+
},
|
|
15
|
+
setLastMove(move, mutationSession) {
|
|
16
|
+
return mutationSession.addMutation('state.change.setLastMove', changeStateSetLastMove(internalState, move));
|
|
17
|
+
},
|
|
18
|
+
getSnapshot() {
|
|
19
|
+
return {
|
|
20
|
+
...cloneDeep(internalState),
|
|
21
|
+
deferredUIMoveRequestContext: internalState.deferredUIMoveRequestContext?.getSnapshot() ?? null
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
setDeferredUIMoveRequestContext(context, mutationSession) {
|
|
25
|
+
return mutationSession.addMutation('state.change.setDeferredUIMoveRequestContext', changeStateSetDeferredUIMoveRequestContext(internalState, context));
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ExtensionUIMoveRequestContextSnapshot } from '../../extensions/types/context/ui-move';
|
|
2
|
+
import type { MoveRequest, MoveRequestBase, MoveSnapshot } from '../board/types/internal';
|
|
3
|
+
import { MoveDestinationSnapshot } from '../interaction/types/internal';
|
|
4
|
+
export declare function movesEqual(moveA: MoveSnapshot | null, moveB: MoveSnapshot | null): boolean;
|
|
5
|
+
export declare function moveRequestBasesEqual(requestA: MoveRequestBase | null, requestB: MoveRequestBase | null): boolean;
|
|
6
|
+
export declare function moveRequestsEqual(requestA: MoveRequest | null, requestB: MoveRequest | null): boolean;
|
|
7
|
+
export declare function moveDestinationsEqual(destA: MoveDestinationSnapshot | null, destB: MoveDestinationSnapshot | null): boolean;
|
|
8
|
+
export declare function uiMoveRequestContextsEqual(contextA: ExtensionUIMoveRequestContextSnapshot | null, contextB: ExtensionUIMoveRequestContextSnapshot | null): boolean;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { setsEqual } from '../../helpers/util';
|
|
2
|
+
function baseMovesEqual(moveA, moveB) {
|
|
3
|
+
const diffs = [
|
|
4
|
+
moveA.from !== moveB.from,
|
|
5
|
+
moveA.to !== moveB.to,
|
|
6
|
+
moveA.piece !== moveB.piece
|
|
7
|
+
];
|
|
8
|
+
return !diffs.some(Boolean);
|
|
9
|
+
}
|
|
10
|
+
export function movesEqual(moveA, moveB) {
|
|
11
|
+
if (moveA === null && moveB === null) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
if (moveA === null || moveB === null) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
if (!baseMovesEqual(moveA, moveB)) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const diffs = [
|
|
21
|
+
moveA.promotedTo !== moveB.promotedTo,
|
|
22
|
+
moveA.captured?.piece !== moveB.captured?.piece,
|
|
23
|
+
moveA.captured?.square !== moveB.captured?.square
|
|
24
|
+
];
|
|
25
|
+
if (diffs.some(Boolean)) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
// Now check secondary moves
|
|
29
|
+
if (moveA.secondary === undefined && moveB.secondary === undefined) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
if (moveA.secondary === undefined || moveB.secondary === undefined) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
return movesEqual(moveA.secondary, moveB.secondary);
|
|
36
|
+
}
|
|
37
|
+
export function moveRequestBasesEqual(requestA, requestB) {
|
|
38
|
+
if (requestA === null && requestB === null) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
if (requestA === null || requestB === null) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return requestA.from === requestB.from && requestA.to === requestB.to;
|
|
45
|
+
}
|
|
46
|
+
export function moveRequestsEqual(requestA, requestB) {
|
|
47
|
+
if (requestA === null && requestB === null) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
if (requestA === null || requestB === null) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
// Compare relevant properties of MoveRequest here
|
|
54
|
+
// Assuming MoveRequest has properties 'from' and 'to' for example
|
|
55
|
+
return (moveRequestBasesEqual(requestA, requestB) &&
|
|
56
|
+
requestA.capturedSquare === requestB.capturedSquare &&
|
|
57
|
+
requestA.promotedTo === requestB.promotedTo &&
|
|
58
|
+
moveRequestBasesEqual(requestA.secondary ?? null, requestB.secondary ?? null));
|
|
59
|
+
}
|
|
60
|
+
export function moveDestinationsEqual(destA, destB) {
|
|
61
|
+
if (destA === null && destB === null) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
if (destA === null || destB === null) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
return (destA.to === destB.to &&
|
|
68
|
+
destA.capturedSquare === destB.capturedSquare &&
|
|
69
|
+
setsEqual(new Set(destA.promotedTo ?? []), new Set(destB.promotedTo ?? [])) &&
|
|
70
|
+
moveRequestBasesEqual(destA.secondary ?? null, destB.secondary ?? null));
|
|
71
|
+
}
|
|
72
|
+
export function uiMoveRequestContextsEqual(contextA, contextB) {
|
|
73
|
+
if (contextA === null && contextB === null) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
if (contextA === null || contextB === null) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
// Compare relevant properties of UIMoveRequestContext here
|
|
80
|
+
// Assuming UIMoveRequestContext has properties 'from' and 'to' for example
|
|
81
|
+
return (contextA.status === contextB.status &&
|
|
82
|
+
contextA.sourceSquare === contextB.sourceSquare &&
|
|
83
|
+
moveDestinationsEqual(contextA.destination, contextB.destination) &&
|
|
84
|
+
contextA.canBeAutoResolved === contextB.canBeAutoResolved &&
|
|
85
|
+
moveRequestsEqual(contextA.resolvedMoveRequest, contextB.resolvedMoveRequest));
|
|
86
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { MutationSession } from '../../mutation/types';
|
|
2
|
+
export type ChangeStateMutationPayloadByCause = {
|
|
3
|
+
'state.change.setLastMove': undefined;
|
|
4
|
+
'state.change.setDeferredUIMoveRequestContext': undefined;
|
|
5
|
+
};
|
|
6
|
+
export type ChangeStateMutationSession = MutationSession<ChangeStateMutationPayloadByCause>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { ExtensionUIMoveRequestContext } from '../../extensions/types/context/ui-move';
|
|
2
|
+
import type { MoveSnapshot } from '../board/types/internal';
|
|
3
|
+
import type { ChangeStateInternal } from './types';
|
|
4
|
+
export declare function changeStateSetLastMove(state: ChangeStateInternal, move: MoveSnapshot | null): boolean;
|
|
5
|
+
export declare function changeStateSetDeferredUIMoveRequestContext(state: ChangeStateInternal, context: ExtensionUIMoveRequestContext): boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { cloneDeep } from 'es-toolkit/object';
|
|
2
|
+
import { movesEqual, uiMoveRequestContextsEqual } from './helpers';
|
|
3
|
+
export function changeStateSetLastMove(state, move) {
|
|
4
|
+
if (movesEqual(state.lastMove, move)) {
|
|
5
|
+
return false; // No change
|
|
6
|
+
}
|
|
7
|
+
state.lastMove = cloneDeep(move);
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
export function changeStateSetDeferredUIMoveRequestContext(state, context) {
|
|
11
|
+
if (uiMoveRequestContextsEqual(state.deferredUIMoveRequestContext, context)) {
|
|
12
|
+
return false; // No change
|
|
13
|
+
}
|
|
14
|
+
state.deferredUIMoveRequestContext = context;
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ReadonlyDeep } from 'type-fest';
|
|
2
|
+
import { ExtensionUIMoveRequestContext, ExtensionUIMoveRequestContextSnapshot } from '../../extensions/types/context/ui-move';
|
|
3
|
+
import type { MoveSnapshot } from '../board/types/internal';
|
|
4
|
+
import type { ChangeStateMutationSession } from './mutation';
|
|
5
|
+
export interface ChangeStateInternal {
|
|
6
|
+
lastMove: MoveSnapshot | null;
|
|
7
|
+
deferredUIMoveRequestContext: ExtensionUIMoveRequestContext | null;
|
|
8
|
+
}
|
|
9
|
+
export type ChangeStateSnapshot = ReadonlyDeep<Omit<ChangeStateInternal, 'deferredUIMoveRequestContext'>> & {
|
|
10
|
+
deferredUIMoveRequestContext: ExtensionUIMoveRequestContextSnapshot | null;
|
|
11
|
+
};
|
|
12
|
+
export interface ChangeState {
|
|
13
|
+
readonly lastMove: MoveSnapshot | null;
|
|
14
|
+
setLastMove(move: MoveSnapshot | null, mutationSession: ChangeStateMutationSession): boolean;
|
|
15
|
+
setDeferredUIMoveRequestContext(context: ExtensionUIMoveRequestContext, mutationSession: ChangeStateMutationSession): boolean;
|
|
16
|
+
getSnapshot(): ChangeStateSnapshot;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|