@cubingcenter/scrambler 0.6.3 → 0.8.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/README.md +17 -4
- package/dist/core/api.d.ts.map +1 -1
- package/dist/core/api.js +10 -2
- package/dist/puzzles/cube2/solver/browser-loader.d.ts +4 -7
- package/dist/puzzles/cube2/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/browser-loader.js +42 -14
- package/dist/puzzles/cube2/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/generated-assets.js +8 -3
- package/dist/puzzles/cube2/solver/search.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/search.js +3 -3
- package/dist/puzzles/cube2/solver/tables.d.ts +6 -0
- package/dist/puzzles/cube2/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/cube2/solver/tables.js +16 -2
- package/dist/puzzles/cube3/index.d.ts +1 -0
- package/dist/puzzles/cube3/index.d.ts.map +1 -1
- package/dist/puzzles/cube3/moves.d.ts.map +1 -1
- package/dist/puzzles/cube3/moves.js +104 -18
- package/dist/puzzles/cube3/scrambler.d.ts +16 -1
- package/dist/puzzles/cube3/scrambler.d.ts.map +1 -1
- package/dist/puzzles/cube3/scrambler.js +1 -1
- package/dist/puzzles/cube3/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/browser-loader.js +48 -22
- package/dist/puzzles/cube3/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/generated-assets.js +9 -3
- package/dist/puzzles/cube3/solver/index.d.ts +5 -3
- package/dist/puzzles/cube3/solver/index.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/index.js +2 -1
- package/dist/puzzles/cube3/solver/node-loader.js +9 -2
- package/dist/puzzles/cube3/solver/phase1.d.ts +37 -0
- package/dist/puzzles/cube3/solver/phase1.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/phase1.js +156 -15
- package/dist/puzzles/cube3/solver/phase2.d.ts +75 -0
- package/dist/puzzles/cube3/solver/phase2.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/phase2.js +279 -68
- package/dist/puzzles/cube3/solver/search-utils.d.ts +1 -1
- package/dist/puzzles/cube3/solver/search-utils.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/symmetry.d.ts +24 -0
- package/dist/puzzles/cube3/solver/symmetry.d.ts.map +1 -0
- package/dist/puzzles/cube3/solver/symmetry.js +74 -0
- package/dist/puzzles/cube3/solver/tables.d.ts +6 -1
- package/dist/puzzles/cube3/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/cube3/solver/tables.js +14 -12
- package/dist/puzzles/cube3/validation.d.ts.map +1 -1
- package/dist/puzzles/cube3/validation.js +15 -7
- package/dist/puzzles/cube4/browser-worker-pool.d.ts +82 -0
- package/dist/puzzles/cube4/browser-worker-pool.d.ts.map +1 -0
- package/dist/puzzles/cube4/browser-worker-pool.js +205 -0
- package/dist/puzzles/cube4/browser-worker.d.ts +2 -0
- package/dist/puzzles/cube4/browser-worker.d.ts.map +1 -0
- package/dist/puzzles/cube4/browser-worker.js +31 -0
- package/dist/puzzles/cube4/index.d.ts +10 -2
- package/dist/puzzles/cube4/index.d.ts.map +1 -1
- package/dist/puzzles/cube4/index.js +6 -2
- package/dist/puzzles/cube4/moves.d.ts +5 -0
- package/dist/puzzles/cube4/moves.d.ts.map +1 -1
- package/dist/puzzles/cube4/moves.js +212 -11
- package/dist/puzzles/cube4/reduction/browser-loader.d.ts +29 -1
- package/dist/puzzles/cube4/reduction/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/browser-loader.js +227 -32
- package/dist/puzzles/cube4/reduction/center2.d.ts +44 -3
- package/dist/puzzles/cube4/reduction/center2.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/center2.js +152 -10
- package/dist/puzzles/cube4/reduction/edge3.d.ts +4 -0
- package/dist/puzzles/cube4/reduction/edge3.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/edge3.js +23 -3
- package/dist/puzzles/cube4/reduction/finish3.d.ts +53 -0
- package/dist/puzzles/cube4/reduction/finish3.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/finish3.js +393 -0
- package/dist/puzzles/cube4/reduction/generated/c3_pair_dist.bin +1 -0
- package/dist/puzzles/cube4/reduction/generated/center2-manifest.json +36 -0
- package/dist/puzzles/cube4/reduction/generated/center2-pruning-wide.bin +1 -0
- package/dist/puzzles/cube4/reduction/generated/hc-distances.bin +1 -0
- package/dist/puzzles/cube4/reduction/generated/hc-manifest.json +44 -0
- package/dist/puzzles/cube4/reduction/generated/hc-move.bin +0 -0
- package/dist/puzzles/cube4/reduction/hc-pdb.d.ts +52 -0
- package/dist/puzzles/cube4/reduction/hc-pdb.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/hc-pdb.js +220 -0
- package/dist/puzzles/cube4/reduction/node-loader.d.ts +15 -1
- package/dist/puzzles/cube4/reduction/node-loader.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/node-loader.js +199 -25
- package/dist/puzzles/cube4/reduction/pair-transversal.d.ts +28 -0
- package/dist/puzzles/cube4/reduction/pair-transversal.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/pair-transversal.js +107 -0
- package/dist/puzzles/cube4/reduction/pairing-coordinate.js +5 -5
- package/dist/puzzles/cube4/reduction/phase3-search.d.ts +116 -7
- package/dist/puzzles/cube4/reduction/phase3-search.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/phase3-search.js +458 -32
- package/dist/puzzles/cube4/reduction/rotation-fix.d.ts +28 -0
- package/dist/puzzles/cube4/reduction/rotation-fix.d.ts.map +1 -0
- package/dist/puzzles/cube4/reduction/rotation-fix.js +212 -0
- package/dist/puzzles/cube4/reduction/solve.d.ts +172 -2
- package/dist/puzzles/cube4/reduction/solve.d.ts.map +1 -1
- package/dist/puzzles/cube4/reduction/solve.js +1201 -180
- package/dist/puzzles/cube4/scramble-cache.d.ts +93 -0
- package/dist/puzzles/cube4/scramble-cache.d.ts.map +1 -0
- package/dist/puzzles/cube4/scramble-cache.js +150 -0
- package/dist/puzzles/cube4/scrambler.d.ts +201 -6
- package/dist/puzzles/cube4/scrambler.d.ts.map +1 -1
- package/dist/puzzles/cube4/scrambler.js +414 -176
- package/dist/puzzles/cube4/state.d.ts.map +1 -1
- package/dist/puzzles/cube4/state.js +4 -1
- package/dist/puzzles/cube4/worker-pool.d.ts +139 -0
- package/dist/puzzles/cube4/worker-pool.d.ts.map +1 -0
- package/dist/puzzles/cube4/worker-pool.js +405 -0
- package/dist/puzzles/cube4/worker-protocol.d.ts +58 -0
- package/dist/puzzles/cube4/worker-protocol.d.ts.map +1 -0
- package/dist/puzzles/cube4/worker-protocol.js +58 -0
- package/dist/puzzles/cube4/worker.d.ts +26 -0
- package/dist/puzzles/cube4/worker.d.ts.map +1 -0
- package/dist/puzzles/cube4/worker.js +49 -0
- package/dist/puzzles/pyraminx/solver/browser-loader.d.ts +4 -8
- package/dist/puzzles/pyraminx/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/browser-loader.js +44 -15
- package/dist/puzzles/pyraminx/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/generated-assets.js +8 -3
- package/dist/puzzles/pyraminx/solver/search.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/search.js +3 -6
- package/dist/puzzles/pyraminx/solver/tables.d.ts +6 -0
- package/dist/puzzles/pyraminx/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/pyraminx/solver/tables.js +17 -0
- package/dist/puzzles/shared/compressed-fetch.d.ts +37 -1
- package/dist/puzzles/shared/compressed-fetch.d.ts.map +1 -1
- package/dist/puzzles/shared/compressed-fetch.js +226 -31
- package/dist/puzzles/shared/load-once.d.ts +16 -0
- package/dist/puzzles/shared/load-once.d.ts.map +1 -0
- package/dist/puzzles/shared/load-once.js +11 -0
- package/dist/puzzles/skewb/solver/browser-loader.d.ts +4 -11
- package/dist/puzzles/skewb/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/skewb/solver/browser-loader.js +44 -16
- package/dist/puzzles/skewb/solver/generated-assets.d.ts.map +1 -1
- package/dist/puzzles/skewb/solver/generated-assets.js +8 -3
- package/dist/puzzles/skewb/solver/search.js +3 -3
- package/dist/puzzles/skewb/solver/tables.d.ts +6 -0
- package/dist/puzzles/skewb/solver/tables.d.ts.map +1 -1
- package/dist/puzzles/skewb/solver/tables.js +17 -0
- package/dist/puzzles/sq1/solver/browser-loader.d.ts.map +1 -1
- package/dist/puzzles/sq1/solver/browser-loader.js +58 -26
- package/dist-cjs/core/api.js +10 -2
- package/dist-cjs/puzzles/cube2/solver/browser-loader.js +42 -14
- package/dist-cjs/puzzles/cube2/solver/generated-assets.js +8 -3
- package/dist-cjs/puzzles/cube2/solver/search.js +2 -2
- package/dist-cjs/puzzles/cube2/solver/tables.js +17 -3
- package/dist-cjs/puzzles/cube3/moves.js +104 -18
- package/dist-cjs/puzzles/cube3/scrambler.js +1 -1
- package/dist-cjs/puzzles/cube3/solver/browser-loader.js +48 -22
- package/dist-cjs/puzzles/cube3/solver/generated-assets.js +9 -3
- package/dist-cjs/puzzles/cube3/solver/index.js +8 -1
- package/dist-cjs/puzzles/cube3/solver/node-loader.js +9 -2
- package/dist-cjs/puzzles/cube3/solver/phase1.js +157 -15
- package/dist-cjs/puzzles/cube3/solver/phase2.js +276 -65
- package/dist-cjs/puzzles/cube3/solver/symmetry.js +80 -0
- package/dist-cjs/puzzles/cube3/solver/tables.js +14 -12
- package/dist-cjs/puzzles/cube3/validation.js +15 -7
- package/dist-cjs/puzzles/cube4/browser-worker-pool.js +211 -0
- package/dist-cjs/puzzles/cube4/index.js +23 -1
- package/dist-cjs/puzzles/cube4/moves.js +213 -11
- package/dist-cjs/puzzles/cube4/reduction/browser-loader.js +227 -32
- package/dist-cjs/puzzles/cube4/reduction/center2.js +155 -10
- package/dist-cjs/puzzles/cube4/reduction/edge3.js +24 -3
- package/dist-cjs/puzzles/cube4/reduction/finish3.js +398 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/c3_pair_dist.bin +1 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/center2-manifest.json +36 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/center2-pruning-wide.bin +1 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/hc-distances.bin +1 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/hc-manifest.json +44 -0
- package/dist-cjs/puzzles/cube4/reduction/generated/hc-move.bin +0 -0
- package/dist-cjs/puzzles/cube4/reduction/hc-pdb.js +232 -0
- package/dist-cjs/puzzles/cube4/reduction/node-loader.js +200 -25
- package/dist-cjs/puzzles/cube4/reduction/pair-transversal.js +112 -0
- package/dist-cjs/puzzles/cube4/reduction/pairing-coordinate.js +5 -5
- package/dist-cjs/puzzles/cube4/reduction/phase3-search.js +460 -33
- package/dist-cjs/puzzles/cube4/reduction/rotation-fix.js +216 -0
- package/dist-cjs/puzzles/cube4/reduction/solve.js +1203 -172
- package/dist-cjs/puzzles/cube4/scramble-cache.js +156 -0
- package/dist-cjs/puzzles/cube4/scrambler.js +416 -174
- package/dist-cjs/puzzles/cube4/state.js +4 -1
- package/dist-cjs/puzzles/cube4/worker-pool.js +447 -0
- package/dist-cjs/puzzles/cube4/worker-protocol.js +62 -0
- package/dist-cjs/puzzles/pyraminx/solver/browser-loader.js +44 -15
- package/dist-cjs/puzzles/pyraminx/solver/generated-assets.js +8 -3
- package/dist-cjs/puzzles/pyraminx/solver/search.js +2 -5
- package/dist-cjs/puzzles/pyraminx/solver/tables.js +18 -1
- package/dist-cjs/puzzles/shared/compressed-fetch.js +229 -31
- package/dist-cjs/puzzles/shared/load-once.js +14 -0
- package/dist-cjs/puzzles/skewb/solver/browser-loader.js +44 -16
- package/dist-cjs/puzzles/skewb/solver/generated-assets.js +8 -3
- package/dist-cjs/puzzles/skewb/solver/search.js +2 -2
- package/dist-cjs/puzzles/skewb/solver/tables.js +18 -1
- package/dist-cjs/puzzles/sq1/solver/browser-loader.js +58 -26
- package/docs/development.md +19 -7
- package/package.json +17 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.lookupCube3MoveTable = exports.loadCube3SolverTables = exports.loadCube3Phase2Tables = exports.loadCube3Phase1Tables = exports.generateCube3SolverTables = exports.generateCube3PruningTable = exports.generateCube3MoveTable = exports.generateCube3Phase2Tables = exports.generateCube3Phase1Tables = exports.checksum = exports.CUBE3_PHASE2_MOVES = exports.CUBE3_PHASE1_MOVES = exports.CUBE3_SOLVER_TABLE_METADATA = exports.moveCoordinate = exports.encodeUdSlice = exports.encodeUdEdgePermutation = exports.encodeSlicePermutation = exports.encodePermutation = exports.encodeEdgeOrientation = exports.encodeCube3Coordinates = exports.encodeCornerOrientation = exports.encodeCube3Coordinate = exports.decodeUdSlice = exports.decodeUdEdgePermutation = exports.decodeSlicePermutation = exports.decodePermutation = exports.decodeEdgeOrientation = exports.decodeCornerOrientation = exports.createRepresentativeStateForCoordinate = exports.CUBE3_COORDINATE_RANGES = exports.Cube3Phase1SearchError = exports.solveCube3Phase1 = exports.isCube3Phase1Solved = exports.encodeCube3Phase1Coordinates = exports.applyCube3Phase1Moves = exports.Cube3Phase2SearchError = exports.solveCube3State = exports.solveCube3Phase2 = exports.isCube3Phase2Solved = exports.encodeCube3Phase2Coordinates = exports.applyCube3Phase2Moves = void 0;
|
|
3
|
+
exports.lookupCube3MoveTable = exports.loadCube3SolverTables = exports.loadCube3Phase2Tables = exports.loadCube3Phase1Tables = exports.generateCube3SolverTables = exports.generateCube3PruningTable = exports.generateCube3MoveTable = exports.generateCube3Phase2Tables = exports.generateCube3Phase1Tables = exports.checksum = exports.CUBE3_PHASE2_MOVES = exports.CUBE3_PHASE1_MOVES = exports.CUBE3_SOLVER_TABLE_METADATA = exports.moveCoordinate = exports.encodeUdSlice = exports.encodeUdEdgePermutation = exports.encodeSlicePermutation = exports.encodePermutation = exports.encodeEdgeOrientation = exports.encodeCube3Coordinates = exports.encodeCornerOrientation = exports.encodeCube3Coordinate = exports.decodeUdSlice = exports.decodeUdEdgePermutation = exports.decodeSlicePermutation = exports.decodePermutation = exports.decodeEdgeOrientation = exports.decodeCornerOrientation = exports.createRepresentativeStateForCoordinate = exports.CUBE3_COORDINATE_RANGES = exports.rotateCube3AlgorithmBySequence = exports.rotateCube3Algorithm = exports.invertCube3RotationSequence = exports.CUBE3_ROTATION_INVERSE = exports.CUBE3_ORIENTATIONS_24 = exports.Cube3Phase1SearchError = exports.solveCube3Phase1 = exports.isCube3Phase1Solved = exports.encodeCube3Phase1Coordinates = exports.collectCube3Phase1Solutions = exports.applyCube3Phase1Moves = exports.Cube3Phase2SearchError = exports.solveCube3State = exports.solveCube3Phase2 = exports.isCube3Phase2Solved = exports.encodeCube3Phase2Coordinates = exports.applyCube3Phase2Moves = void 0;
|
|
4
4
|
var phase2_js_1 = require("./phase2.js");
|
|
5
5
|
Object.defineProperty(exports, "applyCube3Phase2Moves", { enumerable: true, get: function () { return phase2_js_1.applyCube3Phase2Moves; } });
|
|
6
6
|
Object.defineProperty(exports, "encodeCube3Phase2Coordinates", { enumerable: true, get: function () { return phase2_js_1.encodeCube3Phase2Coordinates; } });
|
|
@@ -10,10 +10,17 @@ Object.defineProperty(exports, "solveCube3State", { enumerable: true, get: funct
|
|
|
10
10
|
Object.defineProperty(exports, "Cube3Phase2SearchError", { enumerable: true, get: function () { return phase2_js_1.Cube3Phase2SearchError; } });
|
|
11
11
|
var phase1_js_1 = require("./phase1.js");
|
|
12
12
|
Object.defineProperty(exports, "applyCube3Phase1Moves", { enumerable: true, get: function () { return phase1_js_1.applyCube3Phase1Moves; } });
|
|
13
|
+
Object.defineProperty(exports, "collectCube3Phase1Solutions", { enumerable: true, get: function () { return phase1_js_1.collectCube3Phase1Solutions; } });
|
|
13
14
|
Object.defineProperty(exports, "encodeCube3Phase1Coordinates", { enumerable: true, get: function () { return phase1_js_1.encodeCube3Phase1Coordinates; } });
|
|
14
15
|
Object.defineProperty(exports, "isCube3Phase1Solved", { enumerable: true, get: function () { return phase1_js_1.isCube3Phase1Solved; } });
|
|
15
16
|
Object.defineProperty(exports, "solveCube3Phase1", { enumerable: true, get: function () { return phase1_js_1.solveCube3Phase1; } });
|
|
16
17
|
Object.defineProperty(exports, "Cube3Phase1SearchError", { enumerable: true, get: function () { return phase1_js_1.Cube3Phase1SearchError; } });
|
|
18
|
+
var symmetry_js_1 = require("./symmetry.js");
|
|
19
|
+
Object.defineProperty(exports, "CUBE3_ORIENTATIONS_24", { enumerable: true, get: function () { return symmetry_js_1.CUBE3_ORIENTATIONS_24; } });
|
|
20
|
+
Object.defineProperty(exports, "CUBE3_ROTATION_INVERSE", { enumerable: true, get: function () { return symmetry_js_1.CUBE3_ROTATION_INVERSE; } });
|
|
21
|
+
Object.defineProperty(exports, "invertCube3RotationSequence", { enumerable: true, get: function () { return symmetry_js_1.invertCube3RotationSequence; } });
|
|
22
|
+
Object.defineProperty(exports, "rotateCube3Algorithm", { enumerable: true, get: function () { return symmetry_js_1.rotateCube3Algorithm; } });
|
|
23
|
+
Object.defineProperty(exports, "rotateCube3AlgorithmBySequence", { enumerable: true, get: function () { return symmetry_js_1.rotateCube3AlgorithmBySequence; } });
|
|
17
24
|
var coordinates_js_1 = require("./coordinates.js");
|
|
18
25
|
Object.defineProperty(exports, "CUBE3_COORDINATE_RANGES", { enumerable: true, get: function () { return coordinates_js_1.CUBE3_COORDINATE_RANGES; } });
|
|
19
26
|
Object.defineProperty(exports, "createRepresentativeStateForCoordinate", { enumerable: true, get: function () { return coordinates_js_1.createRepresentativeStateForCoordinate; } });
|
|
@@ -71,9 +71,16 @@ function readMoveTable(assetDirectory, entry) {
|
|
|
71
71
|
if (buffer.length !== expectedBytes) {
|
|
72
72
|
throw new Error(`Invalid byte size for ${entry.coordinate} move table.`);
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
// Every coordinate fits in 16 bits (max range 40320): store half the
|
|
75
|
+
// bytes the int32 wire format uses. Checksums are order-sensitive FNV
|
|
76
|
+
// over the same numeric sequence, so they still match the manifest.
|
|
77
|
+
const values = new Uint16Array(entry.range * entry.moves.length);
|
|
75
78
|
for (let index = 0; index < values.length; index += 1) {
|
|
76
|
-
|
|
79
|
+
const value = buffer.readInt32LE(index * 4);
|
|
80
|
+
if (value < 0 || value > 0xffff) {
|
|
81
|
+
throw new Error(`Move table value out of range for ${entry.coordinate}: ${value}.`);
|
|
82
|
+
}
|
|
83
|
+
values[index] = value;
|
|
77
84
|
}
|
|
78
85
|
const table = {
|
|
79
86
|
coordinate: entry.coordinate,
|
|
@@ -5,6 +5,7 @@ exports.solveCube3Phase1 = solveCube3Phase1;
|
|
|
5
5
|
exports.encodeCube3Phase1Coordinates = encodeCube3Phase1Coordinates;
|
|
6
6
|
exports.isCube3Phase1Solved = isCube3Phase1Solved;
|
|
7
7
|
exports.applyCube3Phase1Moves = applyCube3Phase1Moves;
|
|
8
|
+
exports.collectCube3Phase1Solutions = collectCube3Phase1Solutions;
|
|
8
9
|
const moves_js_1 = require("../moves.js");
|
|
9
10
|
const coordinates_js_1 = require("./coordinates.js");
|
|
10
11
|
const tables_js_1 = require("./tables.js");
|
|
@@ -36,14 +37,7 @@ async function solveCube3Phase1(state, options = {}) {
|
|
|
36
37
|
const maxDepth = options.maxDepth ?? 12;
|
|
37
38
|
const start = encodeCube3Phase1Coordinates(state);
|
|
38
39
|
const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
|
|
39
|
-
const context =
|
|
40
|
-
tables,
|
|
41
|
-
jointTables,
|
|
42
|
-
maxDepth,
|
|
43
|
-
deadline,
|
|
44
|
-
visitedNodes: 0,
|
|
45
|
-
timedOut: false
|
|
46
|
-
};
|
|
40
|
+
const context = createPhase1SearchContext(tables, jointTables, maxDepth, deadline, options.maxNodes);
|
|
47
41
|
if (await isCube3Phase1Solved(start, tables)) {
|
|
48
42
|
return {
|
|
49
43
|
moves: [],
|
|
@@ -85,6 +79,9 @@ async function solveCube3Phase1(state, options = {}) {
|
|
|
85
79
|
visitedNodes: context.visitedNodes
|
|
86
80
|
};
|
|
87
81
|
}
|
|
82
|
+
if (context.nodesExceeded) {
|
|
83
|
+
throw new Cube3Phase1SearchError(`3x3 Phase 1 node budget exceeded (${options.maxNodes} nodes).`, context.visitedNodes);
|
|
84
|
+
}
|
|
88
85
|
if (context.timedOut) {
|
|
89
86
|
throw new Cube3Phase1SearchError(`3x3 Phase 1 search timed out after ${options.timeoutMs}ms.`, context.visitedNodes);
|
|
90
87
|
}
|
|
@@ -115,8 +112,17 @@ const PHASE1_MOVE_FACES = tables_js_1.CUBE3_PHASE1_MOVES.map((move) => {
|
|
|
115
112
|
});
|
|
116
113
|
function searchPhase1(cornerOrientation, edgeOrientation, udSlice, previousFace, previousPreviousFace, remainingDepth, path, context) {
|
|
117
114
|
context.visitedNodes += 1;
|
|
118
|
-
if (context.
|
|
115
|
+
if (context.nodeCap !== undefined &&
|
|
116
|
+
context.visitedNodes > context.nodeCap) {
|
|
117
|
+
context.nodesExceeded = true;
|
|
118
|
+
}
|
|
119
|
+
if (!context.nodesExceeded &&
|
|
120
|
+
context.deadline !== undefined &&
|
|
121
|
+
(context.visitedNodes & 1023) === 0 &&
|
|
122
|
+
performance.now() > context.deadline) {
|
|
119
123
|
context.timedOut = true;
|
|
124
|
+
}
|
|
125
|
+
if (context.timedOut || context.nodesExceeded) {
|
|
120
126
|
return false;
|
|
121
127
|
}
|
|
122
128
|
if (remainingDepth === 0) {
|
|
@@ -124,6 +130,68 @@ function searchPhase1(cornerOrientation, edgeOrientation, udSlice, previousFace,
|
|
|
124
130
|
edgeOrientation === 0 &&
|
|
125
131
|
udSlice === context.tables.moveTables.udSlice.solvedCoordinate;
|
|
126
132
|
}
|
|
133
|
+
const moveCount = context.tables.phase1Moves.length;
|
|
134
|
+
const childCount = collectPhase1Children(cornerOrientation, edgeOrientation, udSlice, previousFace, previousPreviousFace, remainingDepth, context);
|
|
135
|
+
const slot = remainingDepth * moveCount;
|
|
136
|
+
const scratchMove = context.scratchMove;
|
|
137
|
+
const scratchCo = context.scratchCo;
|
|
138
|
+
const scratchEo = context.scratchEo;
|
|
139
|
+
const scratchUd = context.scratchUd;
|
|
140
|
+
for (let i = 0; i < childCount; i += 1) {
|
|
141
|
+
const moveIndex = scratchMove[slot + i];
|
|
142
|
+
const face = PHASE1_MOVE_FACES[moveIndex];
|
|
143
|
+
path.push(context.tables.phase1Moves[moveIndex]);
|
|
144
|
+
if (searchPhase1(scratchCo[slot + i], scratchEo[slot + i], scratchUd[slot + i], face, previousFace, remainingDepth - 1, path, context)) {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
path.pop();
|
|
148
|
+
if (context.timedOut || context.nodesExceeded) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Enumerates up to `limit` phase-1 solutions of exactly `depth` moves for
|
|
156
|
+
* the given state, most promising first (same ordered DFS as the search).
|
|
157
|
+
* Used to try several G1 landing states and keep the best phase-1+phase-2
|
|
158
|
+
* total — a slightly longer phase 1 often collapses phase 2.
|
|
159
|
+
*/
|
|
160
|
+
async function collectCube3Phase1Solutions(state, depth, options = {}) {
|
|
161
|
+
const tables = options.tables ?? await (0, tables_js_1.loadCube3Phase1Tables)();
|
|
162
|
+
const jointTables = options.jointTables ?? tables.jointTables;
|
|
163
|
+
const limit = options.limit ?? 32;
|
|
164
|
+
const deadline = options.timeoutMs === undefined ? undefined : performance.now() + options.timeoutMs;
|
|
165
|
+
const context = createPhase1SearchContext(tables, jointTables, depth, deadline, options.maxNodes);
|
|
166
|
+
const start = encodeCube3Phase1Coordinates(state);
|
|
167
|
+
const solutions = [];
|
|
168
|
+
searchPhase1Collect(start.cornerOrientation, start.edgeOrientation, start.udSlice, -1, -1, depth, [], solutions, limit, context);
|
|
169
|
+
return { solutions, visitedNodes: context.visitedNodes };
|
|
170
|
+
}
|
|
171
|
+
function createPhase1SearchContext(tables, jointTables, maxDepth, deadline, nodeCap) {
|
|
172
|
+
const scratchLevels = maxDepth + 1;
|
|
173
|
+
const scratchSize = scratchLevels * tables_js_1.CUBE3_PHASE1_MOVES.length;
|
|
174
|
+
return {
|
|
175
|
+
tables,
|
|
176
|
+
jointTables,
|
|
177
|
+
maxDepth,
|
|
178
|
+
deadline,
|
|
179
|
+
nodeCap,
|
|
180
|
+
visitedNodes: 0,
|
|
181
|
+
timedOut: false,
|
|
182
|
+
nodesExceeded: false,
|
|
183
|
+
scratchMove: new Int32Array(scratchSize),
|
|
184
|
+
scratchBound: new Int32Array(scratchSize),
|
|
185
|
+
scratchCo: new Int32Array(scratchSize),
|
|
186
|
+
scratchEo: new Int32Array(scratchSize),
|
|
187
|
+
scratchUd: new Int32Array(scratchSize)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Fills the scratch slot for `remainingDepth` with the surviving children
|
|
192
|
+
* in ascending lower-bound order (stable). Returns the child count.
|
|
193
|
+
*/
|
|
194
|
+
function collectPhase1Children(cornerOrientation, edgeOrientation, udSlice, previousFace, previousPreviousFace, remainingDepth, context) {
|
|
127
195
|
const moveCount = context.tables.phase1Moves.length;
|
|
128
196
|
const validMoves = PHASE1_VALID_MOVES[previousFace + 1][previousPreviousFace + 1];
|
|
129
197
|
const coTable = context.tables.moveTables.cornerOrientation.values;
|
|
@@ -131,9 +199,17 @@ function searchPhase1(cornerOrientation, edgeOrientation, udSlice, previousFace,
|
|
|
131
199
|
const udTable = context.tables.moveTables.udSlice.values;
|
|
132
200
|
const coeoTable = context.tables.pruningTables.cornerOrientationEdgeOrientation.values;
|
|
133
201
|
const udPruningTable = context.tables.pruningTables.udSlice.values;
|
|
202
|
+
const jointTables = context.jointTables;
|
|
134
203
|
const coOffset = cornerOrientation * moveCount;
|
|
135
204
|
const eoOffset = edgeOrientation * moveCount;
|
|
136
205
|
const udOffset = udSlice * moveCount;
|
|
206
|
+
const slot = remainingDepth * moveCount;
|
|
207
|
+
const scratchMove = context.scratchMove;
|
|
208
|
+
const scratchBound = context.scratchBound;
|
|
209
|
+
const scratchCo = context.scratchCo;
|
|
210
|
+
const scratchEo = context.scratchEo;
|
|
211
|
+
const scratchUd = context.scratchUd;
|
|
212
|
+
let childCount = 0;
|
|
137
213
|
for (let i = 0; i < validMoves.length; i += 1) {
|
|
138
214
|
const moveIndex = validMoves[i];
|
|
139
215
|
const nextCornerOrientation = coTable[coOffset + moveIndex];
|
|
@@ -146,7 +222,6 @@ function searchPhase1(cornerOrientation, edgeOrientation, udSlice, previousFace,
|
|
|
146
222
|
if (nextLowerBound > remainingDepth - 1) {
|
|
147
223
|
continue;
|
|
148
224
|
}
|
|
149
|
-
const jointTables = context.jointTables;
|
|
150
225
|
if (jointTables) {
|
|
151
226
|
const udCoIndex = nextUdSlice * 2187 + nextCornerOrientation;
|
|
152
227
|
const jc = (jointTables.jointUdCo[udCoIndex >> 1] >> ((udCoIndex & 1) << 2)) & 0x0f;
|
|
@@ -162,14 +237,81 @@ function searchPhase1(cornerOrientation, edgeOrientation, udSlice, previousFace,
|
|
|
162
237
|
continue;
|
|
163
238
|
}
|
|
164
239
|
}
|
|
240
|
+
scratchMove[slot + childCount] = moveIndex;
|
|
241
|
+
scratchBound[slot + childCount] = nextLowerBound;
|
|
242
|
+
scratchCo[slot + childCount] = nextCornerOrientation;
|
|
243
|
+
scratchEo[slot + childCount] = nextEdgeOrientation;
|
|
244
|
+
scratchUd[slot + childCount] = nextUdSlice;
|
|
245
|
+
childCount += 1;
|
|
246
|
+
}
|
|
247
|
+
// Stable insertion sort by bound (n <= 18; ties keep reference order).
|
|
248
|
+
for (let i = 1; i < childCount; i += 1) {
|
|
249
|
+
const move = scratchMove[slot + i];
|
|
250
|
+
const bound = scratchBound[slot + i];
|
|
251
|
+
const co = scratchCo[slot + i];
|
|
252
|
+
const eo = scratchEo[slot + i];
|
|
253
|
+
const ud = scratchUd[slot + i];
|
|
254
|
+
let j = i - 1;
|
|
255
|
+
while (j >= 0 && scratchBound[slot + j] > bound) {
|
|
256
|
+
scratchMove[slot + j + 1] = scratchMove[slot + j];
|
|
257
|
+
scratchBound[slot + j + 1] = scratchBound[slot + j];
|
|
258
|
+
scratchCo[slot + j + 1] = scratchCo[slot + j];
|
|
259
|
+
scratchEo[slot + j + 1] = scratchEo[slot + j];
|
|
260
|
+
scratchUd[slot + j + 1] = scratchUd[slot + j];
|
|
261
|
+
j -= 1;
|
|
262
|
+
}
|
|
263
|
+
scratchMove[slot + j + 1] = move;
|
|
264
|
+
scratchBound[slot + j + 1] = bound;
|
|
265
|
+
scratchCo[slot + j + 1] = co;
|
|
266
|
+
scratchEo[slot + j + 1] = eo;
|
|
267
|
+
scratchUd[slot + j + 1] = ud;
|
|
268
|
+
}
|
|
269
|
+
return childCount;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Ordered exact-depth DFS that collects solutions instead of stopping at
|
|
273
|
+
* the first one. Returns true when collection should stop (limit reached
|
|
274
|
+
* or timed out).
|
|
275
|
+
*/
|
|
276
|
+
function searchPhase1Collect(cornerOrientation, edgeOrientation, udSlice, previousFace, previousPreviousFace, remainingDepth, path, solutions, limit, context) {
|
|
277
|
+
context.visitedNodes += 1;
|
|
278
|
+
if (context.nodeCap !== undefined &&
|
|
279
|
+
context.visitedNodes > context.nodeCap) {
|
|
280
|
+
context.nodesExceeded = true;
|
|
281
|
+
}
|
|
282
|
+
if (!context.nodesExceeded &&
|
|
283
|
+
context.deadline !== undefined &&
|
|
284
|
+
(context.visitedNodes & 1023) === 0 &&
|
|
285
|
+
performance.now() > context.deadline) {
|
|
286
|
+
context.timedOut = true;
|
|
287
|
+
}
|
|
288
|
+
if (context.timedOut || context.nodesExceeded) {
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
if (remainingDepth === 0) {
|
|
292
|
+
if (cornerOrientation === 0 &&
|
|
293
|
+
edgeOrientation === 0 &&
|
|
294
|
+
udSlice === context.tables.moveTables.udSlice.solvedCoordinate) {
|
|
295
|
+
solutions.push([...path]);
|
|
296
|
+
return solutions.length >= limit;
|
|
297
|
+
}
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
const moveCount = context.tables.phase1Moves.length;
|
|
301
|
+
const childCount = collectPhase1Children(cornerOrientation, edgeOrientation, udSlice, previousFace, previousPreviousFace, remainingDepth, context);
|
|
302
|
+
const slot = remainingDepth * moveCount;
|
|
303
|
+
const scratchMove = context.scratchMove;
|
|
304
|
+
const scratchCo = context.scratchCo;
|
|
305
|
+
const scratchEo = context.scratchEo;
|
|
306
|
+
const scratchUd = context.scratchUd;
|
|
307
|
+
for (let i = 0; i < childCount; i += 1) {
|
|
308
|
+
const moveIndex = scratchMove[slot + i];
|
|
165
309
|
const face = PHASE1_MOVE_FACES[moveIndex];
|
|
166
310
|
path.push(context.tables.phase1Moves[moveIndex]);
|
|
167
|
-
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
311
|
+
const stop = searchPhase1Collect(scratchCo[slot + i], scratchEo[slot + i], scratchUd[slot + i], face, previousFace, remainingDepth - 1, path, solutions, limit, context);
|
|
170
312
|
path.pop();
|
|
171
|
-
if (
|
|
172
|
-
return
|
|
313
|
+
if (stop) {
|
|
314
|
+
return true;
|
|
173
315
|
}
|
|
174
316
|
}
|
|
175
317
|
return false;
|