@cubingcenter/scrambler 0.6.0 → 0.6.2

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 (50) hide show
  1. package/dist/core/types.d.ts +1 -1
  2. package/dist/core/types.d.ts.map +1 -1
  3. package/dist/puzzles/cube3/solver/browser-loader.d.ts.map +1 -1
  4. package/dist/puzzles/cube3/solver/browser-loader.js +26 -1
  5. package/dist/puzzles/cube3/solver/generated/manifest.json +14 -0
  6. package/dist/puzzles/cube3/solver/generated/phase1-udco.bin +1 -0
  7. package/dist/puzzles/cube3/solver/generated/phase1-udeo.bin +1 -0
  8. package/dist/puzzles/cube3/solver/generated-assets.d.ts.map +1 -1
  9. package/dist/puzzles/cube3/solver/generated-assets.js +2 -1
  10. package/dist/puzzles/cube3/solver/node-loader.d.ts.map +1 -1
  11. package/dist/puzzles/cube3/solver/node-loader.js +22 -0
  12. package/dist/puzzles/cube3/solver/pair-browser-loader.d.ts +11 -0
  13. package/dist/puzzles/cube3/solver/pair-browser-loader.d.ts.map +1 -0
  14. package/dist/puzzles/cube3/solver/pair-browser-loader.js +93 -0
  15. package/dist/puzzles/cube3/solver/pair-node-loader.d.ts +6 -0
  16. package/dist/puzzles/cube3/solver/pair-node-loader.d.ts.map +1 -0
  17. package/dist/puzzles/cube3/solver/pair-node-loader.js +79 -0
  18. package/dist/puzzles/cube3/solver/pair-tables-types.d.ts +37 -0
  19. package/dist/puzzles/cube3/solver/pair-tables-types.d.ts.map +1 -0
  20. package/dist/puzzles/cube3/solver/pair-tables-types.js +29 -0
  21. package/dist/puzzles/cube3/solver/pair-tables.d.ts +29 -0
  22. package/dist/puzzles/cube3/solver/pair-tables.d.ts.map +1 -0
  23. package/dist/puzzles/cube3/solver/pair-tables.js +69 -0
  24. package/dist/puzzles/cube3/solver/phase1.d.ts +3 -1
  25. package/dist/puzzles/cube3/solver/phase1.d.ts.map +1 -1
  26. package/dist/puzzles/cube3/solver/phase1.js +32 -2
  27. package/dist/puzzles/cube3/solver/phase2.d.ts +3 -0
  28. package/dist/puzzles/cube3/solver/phase2.d.ts.map +1 -1
  29. package/dist/puzzles/cube3/solver/phase2.js +63 -5
  30. package/dist/puzzles/cube3/solver/tables.d.ts +16 -0
  31. package/dist/puzzles/cube3/solver/tables.d.ts.map +1 -1
  32. package/dist/puzzles/cube3/solver/tables.js +4 -2
  33. package/dist/puzzles/cube4/scrambler.d.ts +4 -1
  34. package/dist/puzzles/cube4/scrambler.d.ts.map +1 -1
  35. package/dist/puzzles/cube4/scrambler.js +101 -14
  36. package/dist-cjs/puzzles/cube3/solver/browser-loader.js +26 -1
  37. package/dist-cjs/puzzles/cube3/solver/generated/manifest.json +14 -0
  38. package/dist-cjs/puzzles/cube3/solver/generated/phase1-udco.bin +1 -0
  39. package/dist-cjs/puzzles/cube3/solver/generated/phase1-udeo.bin +1 -0
  40. package/dist-cjs/puzzles/cube3/solver/generated-assets.js +2 -1
  41. package/dist-cjs/puzzles/cube3/solver/node-loader.js +22 -0
  42. package/dist-cjs/puzzles/cube3/solver/pair-browser-loader.js +96 -0
  43. package/dist-cjs/puzzles/cube3/solver/pair-node-loader.js +85 -0
  44. package/dist-cjs/puzzles/cube3/solver/pair-tables-types.js +33 -0
  45. package/dist-cjs/puzzles/cube3/solver/pair-tables.js +107 -0
  46. package/dist-cjs/puzzles/cube3/solver/phase1.js +32 -2
  47. package/dist-cjs/puzzles/cube3/solver/phase2.js +63 -5
  48. package/dist-cjs/puzzles/cube3/solver/tables.js +4 -2
  49. package/dist-cjs/puzzles/cube4/scrambler.js +101 -15
  50. package/package.json +4 -1
@@ -3,6 +3,10 @@
3
3
  * The 4x4 scramble generator: sample a uniform random state, solve it with
4
4
  * the reduction solver (phases 1-4), and invert the solution. The scramble
5
5
  * always reproduces the sampled target state and facelets exactly.
6
+ *
7
+ * If the solver fails after 5 attempts it falls back to cubing.js
8
+ * `randomScrambleForEvent("444")` (also random-state). If that also fails,
9
+ * a WCA-compatible random-moves sequence (40 moves) is returned.
6
10
  */
7
11
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
12
  if (k2 === undefined) k2 = k;
@@ -39,7 +43,6 @@ var __importStar = (this && this.__importStar) || (function () {
39
43
  })();
40
44
  Object.defineProperty(exports, "__esModule", { value: true });
41
45
  exports.cube4ScrambleGenerator = void 0;
42
- exports.isCube4TablesLoaded = isCube4TablesLoaded;
43
46
  exports.generateCube4Scramble = generateCube4Scramble;
44
47
  const moves_js_1 = require("./moves.js");
45
48
  const random_state_js_1 = require("./random-state.js");
@@ -47,6 +50,95 @@ const state_js_1 = require("./state.js");
47
50
  const facelets_js_1 = require("./facelets.js");
48
51
  const solve_js_1 = require("./reduction/solve.js");
49
52
  const index_js_1 = require("../cube3/solver/index.js");
53
+ const index_js_2 = require("../../random/index.js");
54
+ // ────────────────────────────────────────────────────────────
55
+ // cubing.js fallback (random-state, WCA-compliant)
56
+ // ────────────────────────────────────────────────────────────
57
+ /**
58
+ * Try to generate a 4x4 scramble using cubing.js `randomScrambleForEvent`.
59
+ * Uses a dynamic import so browser bundles can tree-shake it when unused.
60
+ * Returns null if cubing.js is unavailable.
61
+ */
62
+ async function generateCube4WithCubingJs() {
63
+ try {
64
+ const { randomScrambleForEvent } = await Promise.resolve().then(() => __importStar(require(
65
+ /* webpackIgnore: true */
66
+ /* @vite-ignore */
67
+ "cubing/scramble")));
68
+ const alg = await randomScrambleForEvent("444");
69
+ const scramble = alg.toString();
70
+ const moves = scramble.trim().split(/\s+/);
71
+ return {
72
+ eventId: "444",
73
+ scramble,
74
+ moves,
75
+ quality: "random-state",
76
+ generator: "cubing-js",
77
+ metadata: {
78
+ generator: "cubing-js",
79
+ distribution: "random-state",
80
+ note: "Generated by cubing.js randomScrambleForEvent as fallback."
81
+ }
82
+ };
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ // ────────────────────────────────────────────────────────────
89
+ // Last-resort: random-moves (no external dep, always works)
90
+ // ────────────────────────────────────────────────────────────
91
+ const CUBE4_FACES = ["U", "R", "F", "D", "L", "B"];
92
+ // Opposite face indices (U↔D, R↔L, F↔B)
93
+ const CUBE4_OPPOSITE = { U: "D", D: "U", R: "L", L: "R", F: "B", B: "F" };
94
+ const CUBE4_SUFFIXES = ["", "2", "'"];
95
+ const CUBE4_WIDE_FACES = ["Uw", "Rw", "Fw", "Dw", "Lw", "Bw"];
96
+ // Opposite wide-move faces
97
+ const CUBE4_WIDE_OPPOSITE = {
98
+ Uw: "Dw", Dw: "Uw", Rw: "Lw", Lw: "Rw", Fw: "Bw", Bw: "Fw"
99
+ };
100
+ // All available move bases (outer + wide). Outer and wide turns are treated
101
+ // independently for the same-face/opposite-face check using their base letter.
102
+ const ALL_MOVE_BASES = [...CUBE4_FACES, ...CUBE4_WIDE_FACES];
103
+ function generateCube4RandomMoves(options = {}) {
104
+ const rng = (0, index_js_2.createRandomSource)(options.seed);
105
+ const moveCount = 40;
106
+ const moves = [];
107
+ let lastFace = null;
108
+ let secondLastFace = null;
109
+ const getBaseLetter = (face) => face.length > 1 ? face[0] : face;
110
+ for (let i = 0; i < moveCount; i++) {
111
+ let face;
112
+ // Reject same face as last or opposite face when the last two moves
113
+ // share the same axis (to avoid redundant move pairs like R L R).
114
+ do {
115
+ face = ALL_MOVE_BASES[rng.nextInt(ALL_MOVE_BASES.length)];
116
+ } while (face === lastFace ||
117
+ (lastFace !== null &&
118
+ (CUBE4_OPPOSITE[face] === lastFace || CUBE4_WIDE_OPPOSITE[face] === lastFace) &&
119
+ secondLastFace !== null &&
120
+ getBaseLetter(secondLastFace) === getBaseLetter(face)));
121
+ const suffix = CUBE4_SUFFIXES[rng.nextInt(3)];
122
+ moves.push(`${face}${suffix}`);
123
+ secondLastFace = lastFace;
124
+ lastFace = face;
125
+ }
126
+ const scramble = moves.join(" ");
127
+ return {
128
+ eventId: "444",
129
+ scramble,
130
+ moves,
131
+ quality: "random-moves",
132
+ generator: "cube4-random-moves-fallback",
133
+ metadata: {
134
+ generator: "cube4-random-moves-fallback",
135
+ distribution: "random-moves",
136
+ note: "Reduction solver and cubing.js both failed; using random-moves.",
137
+ ...options.metadata
138
+ }
139
+ };
140
+ }
141
+ // ────────────────────────────────────────────────────────────
50
142
  let cachedTables;
51
143
  async function loadCube4Tables(baseUrl) {
52
144
  if (cachedTables)
@@ -78,18 +170,6 @@ async function loadCube4Tables(baseUrl) {
78
170
  cachedTables = tables;
79
171
  return tables;
80
172
  }
81
- function isCube4TablesLoaded() {
82
- // For the scrambler retry logic, we need to know if tables are already
83
- // loaded to avoid re-loading on every attempt.
84
- try {
85
- // @ts-ignore
86
- const loader = globalThis;
87
- return false;
88
- }
89
- catch {
90
- return false;
91
- }
92
- }
93
173
  exports.cube4ScrambleGenerator = {
94
174
  info: {
95
175
  eventId: "444",
@@ -97,7 +177,7 @@ exports.cube4ScrambleGenerator = {
97
177
  puzzle: "cube-4x4",
98
178
  quality: "random-state",
99
179
  generator: "cube4-reduction",
100
- description: "Random-state 4x4 scramble via the reduction solver (centers + pairing + 3x3 finish)."
180
+ description: "Random-state 4x4 scramble via the reduction solver (centers + pairing + 3x3 finish). Falls back to random-moves if the solver fails."
101
181
  },
102
182
  generate(options = {}) {
103
183
  return generateCube4Scramble(options);
@@ -174,5 +254,11 @@ async function generateCube4Scramble(options = {}) {
174
254
  throw error;
175
255
  }
176
256
  }
177
- throw lastError;
257
+ // All solver attempts exhausted — try cubing.js first, then random-moves.
258
+ console.warn("[cube4-scrambler] Reduction solver failed after 5 attempts; trying cubing.js fallback.", lastError);
259
+ const cubingJsResult = await generateCube4WithCubingJs();
260
+ if (cubingJsResult)
261
+ return cubingJsResult;
262
+ console.warn("[cube4-scrambler] cubing.js fallback also failed; using random-moves.");
263
+ return generateCube4RandomMoves(options);
178
264
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cubingcenter/scrambler",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Extensible scramble generation toolkit for CubingCenter projects.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -57,6 +57,9 @@
57
57
  "tsx": "^4.20.0",
58
58
  "typescript": "^5.9.0"
59
59
  },
60
+ "dependencies": {
61
+ "cubing": "^0.63.4"
62
+ },
60
63
  "scripts": {
61
64
  "build": "node scripts/clean.cjs && tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node scripts/write-cjs-package.cjs && node scripts/copy-assets.cjs",
62
65
  "test": "node --test --import tsx test/*.test.ts",