cube-state-engine

A Rubik's cube, held in memory.

Feed it moves and it tells you what the cube looks like, which stages are solved, and how a recorded solve was actually put together.

0 runtime dependencies 3x3 and 2x2 CJS + ESM + types MIT

npm install cube-state-engine

Watch it solve

The page replays real recorded solves at their recorded speed. The 3D view, the flat net, the stage checklist and the predicate checks below all read from one CubeEngine instance — every tick is the engine reporting what it sees, move by move. Take over whenever you like: press a key, or scramble it.

3D view cubing.js
state() 3 x 3
Replay loading…
    Readout
    isSolved() true
    Moves recorded 0
    simplifyMoves() 0

    Predicates live
      Controls

      Keyboard

      Break a solve into stages

      Hand analyzeSolution() a timed move list and it replays the solve, works out which method was used, and reports when each stage finished. This is the same solve playing above, as data.

      test/cfop-1.json analyzing…

      The API

      Everything is a named export. Predicates accept a CubeEngine, a state() object, or a flat sticker array.

      Engine

      • new CubeEngine(scramble?, { size }) Size 2 or 3. The scramble is applied but not recorded.
      • applyMoves(seq, { record }) U D L R F B, wide Uw Dw Lw Rw Fw, slices M E S, rotations x y z, with ' and 2.
      • state()Six faces as color matrices.
      • isSolved()Every face a single color.
      • getMoves(asString?)Move history.
      • reset()Back to solved, history cleared.
      • rotateU / D / L / R / F / B Plus Uw Dw Lw Rw Fw, M E S, and X Y Z. Each takes a clockwise flag.

      Predicates

      • isCubeSolved(cube)
      • isCrossComplete(cube, { color })
      • isF2LComplete(cube, { cross })
      • isLastLayerOriented(cube, { face })
      • areLastLayerCornersSolved(cube, { face })
      • matchesGoal(cube, goal) full · cross · f2l · oll · oll+cp, or your own function.
      • getCubeGeometry(size) Derived edges, corners, neighbors and opposites.

      Analysis

      • analyzeSolution(moves, { size }) Detects CFOP and Roux. Reports per-stage timing and TPS.
      • simplifyMoves(moves) Joins identical quarter turns into doubles. Never cancels.
      • invertSequence(tokens) Reverses and inverts a move list.
      • getMovePermutations(size) The cached permutation tables the engine runs on.
      // How this page is wired
      import { CubeEngine, matchesGoal, simplifyMoves } from "cube-state-engine";
      
      const cube = new CubeEngine();
      
      function onKey(move) {
        cube.applyMoves(move, { record: true });
      
        paintNet(cube.state());
        player.alg = cube.getMoves();
        solvedEl.textContent = cube.isSolved();
        crossLamp.dataset.on = matchesGoal(cube, "cross");
        countEl.textContent = simplifyMoves(cube.getMoves(false)).length;
      }