cube-state-engine 1.6.0 → 1.7.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.
@@ -3,7 +3,12 @@
3
3
  "allow": [
4
4
  "Bash(npm run *)",
5
5
  "Bash(node -e \"const m=require\\('./dist/index.js'\\); console.log\\(Object.keys\\(m\\).filter\\(k=>/analyze|invert|MovePerm/.test\\(k\\)\\)\\)\")",
6
- "Bash(npm test *)"
6
+ "Bash(npm test *)",
7
+ "Read(//mnt/d/workspace/**)",
8
+ "Bash(node -e ' *)",
9
+ "Bash(node *)",
10
+ "Bash(cd /tmp)",
11
+ "Bash(sed -i 's/console.log\\(`\\\\\\\\nsideA.*cmll\\)}`\\);/console.log\\(\"\\\\\\\\nsideA=\"+sideA+\" up=\"+up+\": aFirst=\"+firstTrue\\(aDone\\)+\" aLast=\"+aDone[n-1]+\" bFirst=\"+firstTrue\\(bDone\\)+\" bLast=\"+bDone[n-1]+\" cmllFirst=\"+firstTrue\\(cmll\\)\\);/' trace.mjs)"
7
12
  ]
8
13
  }
9
14
  }
package/dist/index.d.mts CHANGED
@@ -328,14 +328,27 @@ function rouxBlockPieces(geo, sideFace, upFace) {
328
328
  }
329
329
 
330
330
  // A Roux block is done when its three edges and two corners are all placed.
331
- function rouxBlockDone(st, centers, geo, sideFace, upFace) {
331
+ // As with CMLL, the block stays intact while the slice between the two blocks is
332
+ // unaligned, but the block's down/front/back facelets are compared against the
333
+ // floating centers -- which the slice displaces. So we accept the block if ANY
334
+ // of the four slice rotations makes its pieces match the centers: the slice
335
+ // moves neither the blocks nor their corners/edges (none sit on the slice), it
336
+ // only re-aligns the floating centers. Without this, a perfectly built block
337
+ // reads as broken for most of a Roux solve, because the slice is scrambled until
338
+ // LSE. `slicePerm` is the slice perpendicular to the block axis.
339
+ function rouxBlockDone(st, geo, sideFace, upFace, slicePerm) {
332
340
  const { edges, corners } = rouxBlockPieces(geo, sideFace, upFace);
333
341
  if (edges.length !== 3 || corners.length !== 2) return false;
334
- for (const e of edges)
335
- if (!slotCorrect(st, centers, e.indices, geo.per)) return false;
336
- for (const c of corners)
337
- if (!slotCorrect(st, centers, c.indices, geo.per)) return false;
338
- return true;
342
+ let cur = st;
343
+ for (let m = 0; m < 4; m++) {
344
+ if (m > 0) cur = applyPerm(cur, slicePerm);
345
+ const centers = centersOf(cur, geo);
346
+ const ok =
347
+ edges.every((e) => slotCorrect(cur, centers, e.indices, geo.per)) &&
348
+ corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per));
349
+ if (ok) return true;
350
+ }
351
+ return false;
339
352
  }
340
353
 
341
354
  // Applies a permutation (out[i] = st[perm[i]]) to a flat sticker array.
@@ -346,15 +359,17 @@ function applyPerm(st, perm) {
346
359
  }
347
360
 
348
361
  // CMLL is done when the four corners touching the up face are solved, allowing
349
- // the M slice to be unaligned: we accept the state if ANY of the four M-slice
350
- // rotations makes those corners correct. M moves neither the corners nor the
351
- // L/R blocks, only the U/F/D/B centers (and M-slice edges), so this captures
352
- // exactly "last-layer corners solved, M not necessarily aligned yet".
353
- function cmllDone(st, geo, upFace, mPerm) {
362
+ // the slice between the two blocks to be unaligned: we accept the state if ANY
363
+ // of the four slice rotations makes those corners correct. The slice moves
364
+ // neither the corners nor the two blocks, only the four floating centers (and
365
+ // slice edges) around the block axis, so this captures exactly "last-layer
366
+ // corners solved, slice not necessarily aligned yet". `slicePerm` must be the
367
+ // slice perpendicular to the block axis (M for L/R blocks, E for U/D, S for F/B).
368
+ function cmllDone(st, geo, upFace, slicePerm) {
354
369
  let cur = st;
355
370
  const corners = geo.cornersByFace(upFace);
356
371
  for (let m = 0; m < 4; m++) {
357
- if (m > 0) cur = applyPerm(cur, mPerm);
372
+ if (m > 0) cur = applyPerm(cur, slicePerm);
358
373
  const centers = centersOf(cur, geo);
359
374
  if (corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per)))
360
375
  return true;
@@ -434,16 +449,15 @@ function isCFOP(build) {
434
449
  // while the first block holds, CMLL only once both blocks hold, and LSE is the
435
450
  // fully solved cube. The first block is whichever of the two opposite side faces
436
451
  // finishes its block earliest; the other side is the second block.
437
- function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
452
+ function buildForRoux(snapshots, geo, sideA, upFace, slicePerm) {
438
453
  snapshots.length;
439
454
  const sideB = geo.opposite[sideA];
440
455
 
441
- const centersAt = snapshots.map((st) => centersOf(st, geo));
442
- const aDone = snapshots.map((st, i) =>
443
- rouxBlockDone(st, centersAt[i], geo, sideA, upFace)
456
+ const aDone = snapshots.map((st) =>
457
+ rouxBlockDone(st, geo, sideA, upFace, slicePerm)
444
458
  );
445
- const bDone = snapshots.map((st, i) =>
446
- rouxBlockDone(st, centersAt[i], geo, sideB, upFace)
459
+ const bDone = snapshots.map((st) =>
460
+ rouxBlockDone(st, geo, sideB, upFace, slicePerm)
447
461
  );
448
462
  const aIdx = completionIndex(aDone);
449
463
  const bIdx = completionIndex(bDone);
@@ -467,7 +481,7 @@ function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
467
481
 
468
482
  const cmllIdx = completionIndex(
469
483
  snapshots.map(
470
- (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, mPerm)
484
+ (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, slicePerm)
471
485
  )
472
486
  );
473
487
  const lseIdx = completionIndex(snapshots.map((st) => isSolvedFlat(st, geo.per)));
@@ -611,12 +625,19 @@ function analyzeSolution(moves, options = {}) {
611
625
  // Stage the solve as Roux (1st block -> 2nd block -> CMLL -> LSE) on every
612
626
  // orientation. Each candidate fixes a side face and a perpendicular up face;
613
627
  // buildForRoux assigns first/second block by which side finishes earliest.
628
+ // The "floating" slice that block/CMLL detection lets drift is the one
629
+ // perpendicular to the block axis: M for L/R blocks, E for U/D, S for F/B.
614
630
  // Pick the valid candidate whose first block completes earliest.
615
- const mPerm = getMovePermutations(size)["M"].cw;
631
+ const perms = getMovePermutations(size);
632
+ const axisSlicePerm = (face) => {
633
+ if (face === 1 || face === 3) return perms["M"].cw; // L/R axis
634
+ if (face === 0 || face === 5) return perms["E"].cw; // U/D axis
635
+ return perms["S"].cw; // F/B axis
636
+ };
616
637
  const rouxCandidates = [];
617
638
  for (let s = 0; s < 6; s++) {
618
639
  for (const u of geo.neighbors[s]) {
619
- rouxCandidates.push(buildForRoux(snapshots, geo, s, u, mPerm));
640
+ rouxCandidates.push(buildForRoux(snapshots, geo, s, u, axisSlicePerm(s)));
620
641
  }
621
642
  }
622
643
  const rouxBuild =
package/dist/index.d.ts CHANGED
@@ -328,14 +328,27 @@ function rouxBlockPieces(geo, sideFace, upFace) {
328
328
  }
329
329
 
330
330
  // A Roux block is done when its three edges and two corners are all placed.
331
- function rouxBlockDone(st, centers, geo, sideFace, upFace) {
331
+ // As with CMLL, the block stays intact while the slice between the two blocks is
332
+ // unaligned, but the block's down/front/back facelets are compared against the
333
+ // floating centers -- which the slice displaces. So we accept the block if ANY
334
+ // of the four slice rotations makes its pieces match the centers: the slice
335
+ // moves neither the blocks nor their corners/edges (none sit on the slice), it
336
+ // only re-aligns the floating centers. Without this, a perfectly built block
337
+ // reads as broken for most of a Roux solve, because the slice is scrambled until
338
+ // LSE. `slicePerm` is the slice perpendicular to the block axis.
339
+ function rouxBlockDone(st, geo, sideFace, upFace, slicePerm) {
332
340
  const { edges, corners } = rouxBlockPieces(geo, sideFace, upFace);
333
341
  if (edges.length !== 3 || corners.length !== 2) return false;
334
- for (const e of edges)
335
- if (!slotCorrect(st, centers, e.indices, geo.per)) return false;
336
- for (const c of corners)
337
- if (!slotCorrect(st, centers, c.indices, geo.per)) return false;
338
- return true;
342
+ let cur = st;
343
+ for (let m = 0; m < 4; m++) {
344
+ if (m > 0) cur = applyPerm(cur, slicePerm);
345
+ const centers = centersOf(cur, geo);
346
+ const ok =
347
+ edges.every((e) => slotCorrect(cur, centers, e.indices, geo.per)) &&
348
+ corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per));
349
+ if (ok) return true;
350
+ }
351
+ return false;
339
352
  }
340
353
 
341
354
  // Applies a permutation (out[i] = st[perm[i]]) to a flat sticker array.
@@ -346,15 +359,17 @@ function applyPerm(st, perm) {
346
359
  }
347
360
 
348
361
  // CMLL is done when the four corners touching the up face are solved, allowing
349
- // the M slice to be unaligned: we accept the state if ANY of the four M-slice
350
- // rotations makes those corners correct. M moves neither the corners nor the
351
- // L/R blocks, only the U/F/D/B centers (and M-slice edges), so this captures
352
- // exactly "last-layer corners solved, M not necessarily aligned yet".
353
- function cmllDone(st, geo, upFace, mPerm) {
362
+ // the slice between the two blocks to be unaligned: we accept the state if ANY
363
+ // of the four slice rotations makes those corners correct. The slice moves
364
+ // neither the corners nor the two blocks, only the four floating centers (and
365
+ // slice edges) around the block axis, so this captures exactly "last-layer
366
+ // corners solved, slice not necessarily aligned yet". `slicePerm` must be the
367
+ // slice perpendicular to the block axis (M for L/R blocks, E for U/D, S for F/B).
368
+ function cmllDone(st, geo, upFace, slicePerm) {
354
369
  let cur = st;
355
370
  const corners = geo.cornersByFace(upFace);
356
371
  for (let m = 0; m < 4; m++) {
357
- if (m > 0) cur = applyPerm(cur, mPerm);
372
+ if (m > 0) cur = applyPerm(cur, slicePerm);
358
373
  const centers = centersOf(cur, geo);
359
374
  if (corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per)))
360
375
  return true;
@@ -434,16 +449,15 @@ function isCFOP(build) {
434
449
  // while the first block holds, CMLL only once both blocks hold, and LSE is the
435
450
  // fully solved cube. The first block is whichever of the two opposite side faces
436
451
  // finishes its block earliest; the other side is the second block.
437
- function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
452
+ function buildForRoux(snapshots, geo, sideA, upFace, slicePerm) {
438
453
  snapshots.length;
439
454
  const sideB = geo.opposite[sideA];
440
455
 
441
- const centersAt = snapshots.map((st) => centersOf(st, geo));
442
- const aDone = snapshots.map((st, i) =>
443
- rouxBlockDone(st, centersAt[i], geo, sideA, upFace)
456
+ const aDone = snapshots.map((st) =>
457
+ rouxBlockDone(st, geo, sideA, upFace, slicePerm)
444
458
  );
445
- const bDone = snapshots.map((st, i) =>
446
- rouxBlockDone(st, centersAt[i], geo, sideB, upFace)
459
+ const bDone = snapshots.map((st) =>
460
+ rouxBlockDone(st, geo, sideB, upFace, slicePerm)
447
461
  );
448
462
  const aIdx = completionIndex(aDone);
449
463
  const bIdx = completionIndex(bDone);
@@ -467,7 +481,7 @@ function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
467
481
 
468
482
  const cmllIdx = completionIndex(
469
483
  snapshots.map(
470
- (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, mPerm)
484
+ (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, slicePerm)
471
485
  )
472
486
  );
473
487
  const lseIdx = completionIndex(snapshots.map((st) => isSolvedFlat(st, geo.per)));
@@ -611,12 +625,19 @@ function analyzeSolution(moves, options = {}) {
611
625
  // Stage the solve as Roux (1st block -> 2nd block -> CMLL -> LSE) on every
612
626
  // orientation. Each candidate fixes a side face and a perpendicular up face;
613
627
  // buildForRoux assigns first/second block by which side finishes earliest.
628
+ // The "floating" slice that block/CMLL detection lets drift is the one
629
+ // perpendicular to the block axis: M for L/R blocks, E for U/D, S for F/B.
614
630
  // Pick the valid candidate whose first block completes earliest.
615
- const mPerm = getMovePermutations(size)["M"].cw;
631
+ const perms = getMovePermutations(size);
632
+ const axisSlicePerm = (face) => {
633
+ if (face === 1 || face === 3) return perms["M"].cw; // L/R axis
634
+ if (face === 0 || face === 5) return perms["E"].cw; // U/D axis
635
+ return perms["S"].cw; // F/B axis
636
+ };
616
637
  const rouxCandidates = [];
617
638
  for (let s = 0; s < 6; s++) {
618
639
  for (const u of geo.neighbors[s]) {
619
- rouxCandidates.push(buildForRoux(snapshots, geo, s, u, mPerm));
640
+ rouxCandidates.push(buildForRoux(snapshots, geo, s, u, axisSlicePerm(s)));
620
641
  }
621
642
  }
622
643
  const rouxBuild =
package/dist/index.js CHANGED
@@ -276,25 +276,28 @@ function rouxBlockPieces(geo, sideFace, upFace) {
276
276
  const corners = geo.cornersByFace(sideFace).filter((c) => c.faces.includes(downFace));
277
277
  return { edges, corners };
278
278
  }
279
- function rouxBlockDone(st, centers, geo, sideFace, upFace) {
279
+ function rouxBlockDone(st, geo, sideFace, upFace, slicePerm) {
280
280
  const { edges, corners } = rouxBlockPieces(geo, sideFace, upFace);
281
281
  if (edges.length !== 3 || corners.length !== 2) return false;
282
- for (const e of edges)
283
- if (!slotCorrect(st, centers, e.indices, geo.per)) return false;
284
- for (const c of corners)
285
- if (!slotCorrect(st, centers, c.indices, geo.per)) return false;
286
- return true;
282
+ let cur = st;
283
+ for (let m = 0; m < 4; m++) {
284
+ if (m > 0) cur = applyPerm(cur, slicePerm);
285
+ const centers = centersOf(cur, geo);
286
+ const ok = edges.every((e) => slotCorrect(cur, centers, e.indices, geo.per)) && corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per));
287
+ if (ok) return true;
288
+ }
289
+ return false;
287
290
  }
288
291
  function applyPerm(st, perm) {
289
292
  const out = new Array(st.length);
290
293
  for (let i = 0; i < st.length; i++) out[i] = st[perm[i]];
291
294
  return out;
292
295
  }
293
- function cmllDone(st, geo, upFace, mPerm) {
296
+ function cmllDone(st, geo, upFace, slicePerm) {
294
297
  let cur = st;
295
298
  const corners = geo.cornersByFace(upFace);
296
299
  for (let m = 0; m < 4; m++) {
297
- if (m > 0) cur = applyPerm(cur, mPerm);
300
+ if (m > 0) cur = applyPerm(cur, slicePerm);
298
301
  const centers = centersOf(cur, geo);
299
302
  if (corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per)))
300
303
  return true;
@@ -346,15 +349,14 @@ function isCFOP(build) {
346
349
  const lastF2L = f2lSlots[3].idx;
347
350
  return ollIdx >= lastF2L && pllIdx >= ollIdx;
348
351
  }
349
- function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
352
+ function buildForRoux(snapshots, geo, sideA, upFace, slicePerm) {
350
353
  const n = snapshots.length;
351
354
  const sideB = geo.opposite[sideA];
352
- const centersAt = snapshots.map((st) => centersOf(st, geo));
353
355
  const aDone = snapshots.map(
354
- (st, i) => rouxBlockDone(st, centersAt[i], geo, sideA, upFace)
356
+ (st) => rouxBlockDone(st, geo, sideA, upFace, slicePerm)
355
357
  );
356
358
  const bDone = snapshots.map(
357
- (st, i) => rouxBlockDone(st, centersAt[i], geo, sideB, upFace)
359
+ (st) => rouxBlockDone(st, geo, sideB, upFace, slicePerm)
358
360
  );
359
361
  const aIdx = completionIndex(aDone);
360
362
  const bIdx = completionIndex(bDone);
@@ -373,7 +375,7 @@ function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
373
375
  const sbIdx = completionIndex(secondBlockBools);
374
376
  const cmllIdx = completionIndex(
375
377
  snapshots.map(
376
- (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, mPerm)
378
+ (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, slicePerm)
377
379
  )
378
380
  );
379
381
  const lseIdx = completionIndex(snapshots.map((st) => isSolvedFlat(st, geo.per)));
@@ -469,11 +471,16 @@ function analyzeSolution(moves, options = {}) {
469
471
  });
470
472
  const cfopChosen = (_a = ordered.find((c) => isCFOP(c.build))) != null ? _a : ordered[0];
471
473
  const cfopValid = !!cfopChosen && isCFOP(cfopChosen.build);
472
- const mPerm = getMovePermutations(size)["M"].cw;
474
+ const perms = getMovePermutations(size);
475
+ const axisSlicePerm = (face) => {
476
+ if (face === 1 || face === 3) return perms["M"].cw;
477
+ if (face === 0 || face === 5) return perms["E"].cw;
478
+ return perms["S"].cw;
479
+ };
473
480
  const rouxCandidates = [];
474
481
  for (let s = 0; s < 6; s++) {
475
482
  for (const u of geo.neighbors[s]) {
476
- rouxCandidates.push(buildForRoux(snapshots, geo, s, u, mPerm));
483
+ rouxCandidates.push(buildForRoux(snapshots, geo, s, u, axisSlicePerm(s)));
477
484
  }
478
485
  }
479
486
  const rouxBuild = (_b = rouxCandidates.filter((b) => isRoux(b)).sort((a, b) => a.fbIdx - b.fbIdx)[0]) != null ? _b : null;
package/dist/index.mjs CHANGED
@@ -248,25 +248,28 @@ function rouxBlockPieces(geo, sideFace, upFace) {
248
248
  const corners = geo.cornersByFace(sideFace).filter((c) => c.faces.includes(downFace));
249
249
  return { edges, corners };
250
250
  }
251
- function rouxBlockDone(st, centers, geo, sideFace, upFace) {
251
+ function rouxBlockDone(st, geo, sideFace, upFace, slicePerm) {
252
252
  const { edges, corners } = rouxBlockPieces(geo, sideFace, upFace);
253
253
  if (edges.length !== 3 || corners.length !== 2) return false;
254
- for (const e of edges)
255
- if (!slotCorrect(st, centers, e.indices, geo.per)) return false;
256
- for (const c of corners)
257
- if (!slotCorrect(st, centers, c.indices, geo.per)) return false;
258
- return true;
254
+ let cur = st;
255
+ for (let m = 0; m < 4; m++) {
256
+ if (m > 0) cur = applyPerm(cur, slicePerm);
257
+ const centers = centersOf(cur, geo);
258
+ const ok = edges.every((e) => slotCorrect(cur, centers, e.indices, geo.per)) && corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per));
259
+ if (ok) return true;
260
+ }
261
+ return false;
259
262
  }
260
263
  function applyPerm(st, perm) {
261
264
  const out = new Array(st.length);
262
265
  for (let i = 0; i < st.length; i++) out[i] = st[perm[i]];
263
266
  return out;
264
267
  }
265
- function cmllDone(st, geo, upFace, mPerm) {
268
+ function cmllDone(st, geo, upFace, slicePerm) {
266
269
  let cur = st;
267
270
  const corners = geo.cornersByFace(upFace);
268
271
  for (let m = 0; m < 4; m++) {
269
- if (m > 0) cur = applyPerm(cur, mPerm);
272
+ if (m > 0) cur = applyPerm(cur, slicePerm);
270
273
  const centers = centersOf(cur, geo);
271
274
  if (corners.every((c) => slotCorrect(cur, centers, c.indices, geo.per)))
272
275
  return true;
@@ -318,15 +321,14 @@ function isCFOP(build) {
318
321
  const lastF2L = f2lSlots[3].idx;
319
322
  return ollIdx >= lastF2L && pllIdx >= ollIdx;
320
323
  }
321
- function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
324
+ function buildForRoux(snapshots, geo, sideA, upFace, slicePerm) {
322
325
  const n = snapshots.length;
323
326
  const sideB = geo.opposite[sideA];
324
- const centersAt = snapshots.map((st) => centersOf(st, geo));
325
327
  const aDone = snapshots.map(
326
- (st, i) => rouxBlockDone(st, centersAt[i], geo, sideA, upFace)
328
+ (st) => rouxBlockDone(st, geo, sideA, upFace, slicePerm)
327
329
  );
328
330
  const bDone = snapshots.map(
329
- (st, i) => rouxBlockDone(st, centersAt[i], geo, sideB, upFace)
331
+ (st) => rouxBlockDone(st, geo, sideB, upFace, slicePerm)
330
332
  );
331
333
  const aIdx = completionIndex(aDone);
332
334
  const bIdx = completionIndex(bDone);
@@ -345,7 +347,7 @@ function buildForRoux(snapshots, geo, sideA, upFace, mPerm) {
345
347
  const sbIdx = completionIndex(secondBlockBools);
346
348
  const cmllIdx = completionIndex(
347
349
  snapshots.map(
348
- (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, mPerm)
350
+ (st, i) => secondBlockBools[i] && cmllDone(st, geo, upFace, slicePerm)
349
351
  )
350
352
  );
351
353
  const lseIdx = completionIndex(snapshots.map((st) => isSolvedFlat(st, geo.per)));
@@ -441,11 +443,16 @@ function analyzeSolution(moves, options = {}) {
441
443
  });
442
444
  const cfopChosen = (_a = ordered.find((c) => isCFOP(c.build))) != null ? _a : ordered[0];
443
445
  const cfopValid = !!cfopChosen && isCFOP(cfopChosen.build);
444
- const mPerm = getMovePermutations(size)["M"].cw;
446
+ const perms = getMovePermutations(size);
447
+ const axisSlicePerm = (face) => {
448
+ if (face === 1 || face === 3) return perms["M"].cw;
449
+ if (face === 0 || face === 5) return perms["E"].cw;
450
+ return perms["S"].cw;
451
+ };
445
452
  const rouxCandidates = [];
446
453
  for (let s = 0; s < 6; s++) {
447
454
  for (const u of geo.neighbors[s]) {
448
- rouxCandidates.push(buildForRoux(snapshots, geo, s, u, mPerm));
455
+ rouxCandidates.push(buildForRoux(snapshots, geo, s, u, axisSlicePerm(s)));
449
456
  }
450
457
  }
451
458
  const rouxBuild = (_b = rouxCandidates.filter((b) => isRoux(b)).sort((a, b) => a.fbIdx - b.fbIdx)[0]) != null ? _b : null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cube-state-engine",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "An efficient representation in memory for tracking the Rubik's cube state on each movement.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",