← Play

The third colour: a modulo-3 phase for an endless tipping-block puzzle

Liminal Math Research

12 November 2026

Abstract

This paper studies a small endless rolling-block puzzle. A domino made of two cubes (a \(1\times1\times2\) block) tips and rolls on a finite patch of floor; the artifact uses a \(13\times9\) coordinate box. The only win is to stand the block on the hole. A lying block may rest with one end over the hole; it never wins there. The block's pose is the state, the floor is carved by a random walk, and every generated level is solvable by replaying that walk. Section 2 explains the whole game in plain words, with diagrams. We then give a simple formal model, a breadth-first solver, and a small piece of mathematics called the phase: a pair of remainders attached to every pose. Tips keep the phase; side-rolls change one coordinate by one. This gives a quick impossibility test, a formula for straight corridors, and a lower bound on the number of rolls. A generator and a seeded sample set show where the phase is sharp and where it is not: the single colour \((x+y)\bmod 3\) is weaker than the pair, a matching phase is not sufficient, and the roll bound is weak. The playable artifact is embedded in Section 7.

Keywords: rolling-block puzzle · modular colouring · phase invariant · random generation · playable artifact

1. Introduction

Block Escape is a small endless version of the rolling-block genre, distilled from Bloxorz1. There are no switches, trapdoors, keys, or fixed level list. A \(1\times1\times2\) domino — two cubes glued together — stands, tips, and rolls on a finite patch of floor; one tile is the hole. A move is legal when every cell the block covers after the move is floor, except that one end of a lying block may be the hole. Standing exactly on the hole wins; a lying block over the hole is a rest, not a win.

If you are new to the game, start with Section 2. It explains the board, the block, every move, falling, winning, the controls, and how levels are generated, with pictures. The later sections add the formal rules, the solver, and the modulo-3 argument.

Each level is generated, not authored. Level \(n\) is a random walk of \(\min(10+2n,40)\) moves, extended until the block ends standing. Every cell the walk touches becomes floor, the final standing cell becomes the hole, and the length of the walk is the par. Replaying the generator's walk is a legal solution, so every emitted level is solvable and the supply never runs out.

Section 4 makes the rules operational: a level becomes a finite graph whose vertices are poses, and breadth-first search returns the shortest winning word. That is the model used to solve the levels; the generator's walk is only one witness path.

The paper asks what modulo \(3\) actually decides. The useful object is the phase pair \[ \begin{aligned} \varphi(U(p)) &= p\bmod 3,\\ \varphi(L(p,p+d)) &= (p-d)\bmod 3 . \end{aligned} \] not one colour. Tips keep the pair; a side-roll changes one coordinate by \(\pm1\) and needs a \(2\times2\) floor patch. On a board without such a patch the phase is invariant, so a hole with a different phase is impossible. A mismatch with a patch is a demand for rolls, not an impossibility. The phase is exact on a straight corridor and a lower bound on rolls elsewhere.

The artifact in Section 7 is the same endless game: arrow keys or WASD, R restart; N next level after a win. The game shows your move count next to Best, the shortest possible solution found by breadth-first search. The generator's walk is only a witness; the par in the table below is its length.

2. How to play

The whole game, in one paragraph. You control a block made of two cubes glued together. It stands on one tile or lies across two. Tip it, stand it up, or roll it sideways with the four arrow directions. The board has floor tiles, empty tiles, and exactly one hole. Your only job is to make the block stand upright on the hole. If a move would put any part of the block on empty space, it falls; it returns to the last safe position and you try again.

This section is the game in plain words. Section 3 repeats the same rules formally, with symbols, and Sections 4–6 explain the solver, the colour invariant, and the level generator. A reader who only wants to play can stop after this section. The diagrams are wide; on a narrow screen, scroll a figure sideways to see its whole key.

2.1 The board: tiles, floor, void, and the hole

S H x y 0 1 2 3 4 5 6 0 1 2 3 4 Key floor: can stand void: no floor hole: target block: start Coordinates are tile indices: (0,0) is bottom-left; x right, y up.
Figure 1. A small \(7\times5\) example, not the \(13\times9\) artifact. Tinted tiles are floor; white tiles are void; the dark tile is the hole; the yellow block is the start. Coordinates are tile indices: \((0,0)\) is the bottom-left tile, \(x\) grows right, and \(y\) grows up. The artifact's sample level in Figure 6 labels only every third tile.

The board is a grid of square tiles. A coordinate pair \((x,y)\) names one tile: \(x\) is the column, \(y\) is the row. The artifact's coordinate box is \(13\times9\), so \(x=0,\ldots,12\) and \(y=0,\ldots,8\). That is \(13\cdot9=117\) possible positions — but it is not 117 floor tiles.

Each tile is one of three things:

The generator decides which tiles are floor. Most of the coordinate box can be void. The block starts standing on a floor tile at the centre; in the artifact that is \((6,4)\).

2.2 The block: standing or lying

standing U(x,y) one cube lying east-west H(x,y) two cubes lying north-south V(x,y) two cubes
Figure 2. Each yellow square is one cube; the block is two cubes. \(U(x,y)\) stands, so it shows one yellow cube on one tile. \(H(x,y)\) lies east–west and shows two yellow cubes on \((x,y)\) and \((x+1,y)\). \(V(x,y)\) lies north–south and shows two yellow cubes on \((x,y)\) and \((x,y+1)\). The small dot is the anchor: the west or south tile that names the pose.

The block is rigid. It never bends, stretches, or jumps. It has exactly three kinds of footprint:

The physical block is two cubes high when standing, but height never affects a move. Only the tiles underneath matter. For example, \(U(6,4)\) is the start tile, \(H(6,4)\) covers \((6,4)\) and \((7,4)\), and \(V(6,4)\) covers \((6,4)\) and \((6,5)\).

2.3 A swipe: tip, stand up, or roll

tip over before after swipe N stand up before after swipe E roll sideways before after swipe N
Figure 3. One example of each move shape; each yellow square is one cube. Tip over: one cube standing becomes two cubes lying. Stand up: two cubes lying become one cube standing. Roll sideways: two cubes lying shift one tile sideways and stay two cubes. The arrow only orders before and after; the label gives the swipe direction. The block pivots on an edge like a falling domino; it never slides. The direction can be any of \(N,E,S,W\).

A swipe is one of four directions: north \(N\) (increase \(y\)), east \(E\) (increase \(x\)), south \(S\) (decrease \(y\)), or west \(W\) (decrease \(x\)). The block pivots about the edge it is touching. There are only three move shapes:

One keypress or swipe attempts exactly one move. The block can end in a different orientation; the next swipe starts from that new pose. There is no sliding, no jumping, and no turning in place. Section 3, Table 4 gives all twelve before/after cases.

2.4 Safe, fallen, and winning

two floor ✓ safe one floor ✓ " safe floor + hole ! rest, not win hole ★ " WIN floor + void ✕ fall
Figure 4. The support cases; each yellow square is one cube. A standing block is one cube; a lying block is two cubes. Green tick: safe; amber exclamation: safe rest but not a win; star: win; red cross: fall. A standing block wins only on the hole. A lying block may hang one end over the hole if the other end is floor; that is safe but does not win.

After a move, look at every tile the block covers. Each of those tiles must be floor. There is one exception: a lying block may have one end over the hole, as long as its other end is floor. This is a half-hole rest. It is safe, but it is not a win.

A win is only this: the block is standing, and the one tile it covers is the hole. Nothing else wins. In particular, lying across the hole never wins, even if both ends are over the hole (which cannot happen with one hole and a two-tile block, but the rule is still “standing only”).

A fall happens when a covered tile is void, or when a lying block has one end over the hole and the other over void. A fall does not end the level: the block returns to its last safe position, and the failed swipe still counts in your move total. A block standing on ordinary floor is safe.

Remember three checks. 1. Is every covered tile floor, or is one end of a lying block over the hole with the other end on floor? If not, fall. 2. Is the block standing on the hole? If yes, win. 3. Otherwise the move is safe; keep going.

2.5 One turn, and the controls

Each swipe is one turn. Use the arrow keys or W/A/S/D, or drag the board in the direction you want. R restarts the same level; N starts the next level after a win; you cannot skip ahead. Completed levels stay available in the level strip. After a win, any key starts the next level. There is no timer, no score penalty beyond your move count, and no undo button: a fall simply puts the block back and you try another direction.

The display shows the level number, your move count, and Best — the shortest solution found by search. When you win, the clear card compares your moves with Best. Matching Best is optimal; taking more moves is still a valid escape.

2.6 Where a level comes from

S H Resulting board floor void hole par = 4 moves direction: S E E N The walk: one card per pose 0 U S 1 V E 2 V E 3 V N 4 U
Figure 5. A generated \(6\times5\) board and the walk that made it. The directions are \(S,E,E,N\): each card shows one pose, and a lying pose covers two tiles. Every touched tile is floor; the final standing tile becomes the hole. Par is 4. The real artifact uses \(13\times9\), with target \(\min(10+2n,40)\) for level \(n\).

Levels are generated, not hand-designed. For level \(n\), the game starts the block standing at the centre. It takes a random walk of in-bounds swipes. Every tile the block touches is carved as floor. The walk stops when the block is standing on a tile that was never touched before; that tile becomes the hole. Because the final tile is new, removing it does not break any earlier move. The walk itself is a legal solution, so every level is solvable.

The walk length is the par. It is one solution, not necessarily the shortest. A separate search finds the shortest solution; that length is the optimum. The game displays this optimum as Best, next to your moves. The generator's target walk length is \(\min(10+2n,40)\): it grows until level 15, then stays at 40. Later levels are still random, so they are not identical, but after level 15 the target no longer grows. The live game uses a fresh random walk for each new level.

2.7 The modulo-3 idea, in one paragraph

There is an optional three-colour pattern on the tiles. The full version is not one colour but a pair of remainders, \((\,x\bmod3,\;y\bmod3\,)\). A tip keeps that pair; a sideways roll changes exactly one coordinate by one and needs a \(2\times2\) patch of floor or hole. This can prove that some hole positions are impossible, but a matching pair does not guarantee a solution. Section 5 gives the exact statement.

2.8 Words used in the paper

Table 1. Words used in the paper, in plain language.
WordMeaning
Tile / cellOne square of the coordinate box, named by \((x,y)\).
FloorA tile the block may use.
VoidA tile with no floor; the block cannot use it.
HoleThe single target tile; not floor for standing, but one end of a lying block may rest over it.
PoseThe block's footprint: \(U\) standing, \(H\) lying east–west, \(V\) lying north–south.
AnchorThe west or south tile that names a lying pose; the single tile for \(U\).
SwipeOne attempted move in direction \(N,E,S,W\).
TipStanding to lying.
Stand upLying to standing.
RollLying to lying, shifted sideways.
SafeEvery covered tile is floor, or one end of a lying block is over the hole with the other on floor.
FallA move that is not safe; the block returns to its last safe pose.
WinStanding on the hole.
ParThe length of the generator's walk, a guaranteed solution.
OptimumThe shortest possible solution, found by search.
LevelA generated floor set plus one hole and a start pose.
PhaseThe pair \((x\bmod3,y\bmod3)\) attached to a pose; used for the colour argument.

3. The rules

This section is the formal version of Section 2. A level has a finite floor set \(B\), one hole \(h\notin B\), and a start pose \(s\). The artifact uses the \(13\times9\) coordinate box from Section 2.1. Table 2 collects the notation, Table 3 lists the three poses, and Table 4 lists the move cases.

Table 2. Notation: symbols used in the paper. Dimensions are written width \(\times\) height, and \(D=\{N,E,S,W\}\).
SymbolMeaning
\(M=(B,h,s)\)level: floor set \(B\), hole \(h\), start pose \(s\)
\(B\subseteq\mathbb Z^2\)finite set of floor cells
\(h\in\mathbb Z^2\setminus B\)hole cell
\(x,y\)tile indices: \(x\) column, \(y\) row; \(p=(x,y)\) is a tile
\(U(p),H(p),V(p)\)standing, lying east-west, lying north-south poses anchored at \(p\)
\(L(p,p+d)\)lying pose anchored at \(p\) extending in direction \(d\)
\(N,E,S,W\)unit direction vectors
\(D\)direction set \(\{N,E,S,W\}\)
\(d,e\)directions; \(e\perp d\) means perpendicular
\(c\)a cell
\(\operatorname{cells}(b)\)cells occupied by pose \(b\)
\(\operatorname{legal}(b)\)pose supported by floor, with the partial-hole exception
\(\operatorname{win}(b)\)\(b=U(h)\)
\(\operatorname{step}(b,d)\)pose after swiping pose \(b\) in direction \(d\)
\(b,q\)generic poses
\(Q\)breadth-first search queue
\(w,\varepsilon\)a word of directions; \(\varepsilon\) is the empty word
\(\bot\)no solution
\(\varphi(b)\)phase pair of pose \(b\)
\(\mathbb Z,\mathbb Z_3,\mathbb Z_3^2\)integers, residues modulo 3, and pairs of residues
\(\chi(p)\)single colour \((x+y)\bmod3\)
\(n\)level index
\(s_0\)start pose when it is standing
\(\operatorname{par}(M)\)generator walk length
\(\operatorname{opt}(M)\)BFS shortest-solution length
R, N, WASDkeyboard controls: restart, next level after a win, movement (see Section 7)

The table is also the legend for the symbols used in the figures, tables and code below. The Lean sketch writes \(c\) for a cell and \(b\) for its block argument; \(M\) is always a level. The set \(B\cup\{h\}\) is the floor together with the hole; a pad is a \(2\times2\) square of cells in that set.

Table 3. Poses. A lying pose is anchored at its western or southern cell, so its name is unique.
posefootprintkind
\(U(x,y)\)\(\{(x,y)\}\)standing, two cubes high
\(H(x,y)\)\(\{(x,y),(x+1,y)\}\)lying east–west
\(V(x,y)\)\(\{(x,y),(x,y+1)\}\)lying north–south

A swipe is one of \(N,E,S,W\). The rigid pivot gives exactly three move shapes:

Table 4. The three moves. The old cells are vacated; the block pivots about an edge.
beforeswipeaftershape
\(U(p)\)\(d\)\(L(p+d,p+2d)\)tip over
\(L(p,p+d)\)\(d\) or \(-d\)\(U(p+2d)\) or \(U(p-d)\)erect
\(L(p,p+d)\)\(e\perp d\)\(L(p+e,p+d+e)\)roll

Legality. In words: every tile under the block must be floor. A lying block gets one exception: one end may be the hole, provided the other end is floor. The formula just writes that: \[ \begin{aligned} \operatorname{legal}(b) \iff{}& \operatorname{cells}(b)\subseteq B\\ &\lor\bigl(b\text{ lying}\land h\in\operatorname{cells}(b)\\ &\qquad\land \operatorname{cells}(b)\setminus\{h\}\subseteq B\bigr). \end{aligned} \tag{1} \] \[ \operatorname{win}(b)\iff b=U(h). \tag{2} \] The first line is the normal case; the second line is the half-hole exception. Otherwise the block topples off and returns to its last safe position. The hole is not floor, but one end of a lying block may rest over it if the other end is floor. Such a rest wins nothing. A standing block on the hole wins, and that is the only win condition.

Generator. For level \(n\), start standing at the centre. Take a target number of random moves, keeping only landing positions inside the grid, and carve every touched cell as floor. Keep walking until the block ends standing. To make the walk replayable, require the final standing cell to be new (never touched before); otherwise removing it would break an earlier move. Make that cell the hole and remove it from the floor. The number of moves in the final walk is the par. The extra steps are for replay: removing a goal cell that an earlier move used would break that earlier move. The artifact uses a \(13\times9\) board and \(\min(10+2n,40)\) as the target; both are design parameters. Any finite grid and any nonnegative target are valid.

0 3 6 9 12 0 3 6 x y
Figure 6. A seeded generated level (\(n=1\)): 16 floor tiles in a \(13\times9\) coordinate box, start \((6,4)\), hole \((7,3)\), six \(2\times2\) pads in \(B\cup\{h\}\). The start and hole have the same single three-colour value \((x+y)\bmod3=1\), but their phase pairs are \((0,1)\) and \((1,0)\). The generator walk uses four side-rolls and has par 20; breadth-first search finds a 7-move optimum. Tinted cells are floor; white cells are void; the dark cell is the hole; the yellow block is the start. The three tints are the three values of \(\chi\): blue is \(\chi=0\), red is \(\chi=1\), green is \(\chi=2\). The horizontal axis is \(x\); the vertical axis is \(y\). Ticks are every third tile, at tile centres; tiles such as \(x=1,2,4,5\) and \(y=1,2,4,5,7,8\) are present but unlabelled.

4. Four definitions and a solver

In plain words. A solver does not guess. It lists every pose the block can reach in one move, then every pose reachable in two moves, and so on. The first time it reaches “standing on the hole”, that path is a shortest solution. The graph below is just a bookkeeping device for that list.

Optional: precise Lean 4 specification

The four definitions are written below as a Lean 4 specification. The listing is self-contained: it fixes the pose type, the twelve-case step table, legal support, the winning pose, and the reachability relation.

import Mathlib.Data.Finset.Basic
import Mathlib.Data.Int.Basic
import Mathlib.Logic.Relation

inductive Dir | N | E | S | W deriving DecidableEq, Repr
inductive Orient | U | H | V deriving DecidableEq, Repr

abbrev Cell := Int × Int

structure Pose where
  o : Orient
  x : Int
  y : Int
  deriving DecidableEq, Repr

namespace BlockEscape

def Pose.cells : Pose → Finset Cell
  | ⟨.U, x, y⟩ => {(x, y)}
  | ⟨.H, x, y⟩ => {(x, y), (x + 1, y)}
  | ⟨.V, x, y⟩ => {(x, y), (x, y + 1)}

def step : Pose → Dir → Pose
  | ⟨.U, x, y⟩, .N => ⟨.V, x, y + 1⟩
  | ⟨.U, x, y⟩, .E => ⟨.H, x + 1, y⟩
  | ⟨.U, x, y⟩, .S => ⟨.V, x, y - 2⟩
  | ⟨.U, x, y⟩, .W => ⟨.H, x - 2, y⟩
  | ⟨.H, x, y⟩, .N => ⟨.H, x, y + 1⟩
  | ⟨.H, x, y⟩, .E => ⟨.U, x + 2, y⟩
  | ⟨.H, x, y⟩, .S => ⟨.H, x, y - 1⟩
  | ⟨.H, x, y⟩, .W => ⟨.U, x - 1, y⟩
  | ⟨.V, x, y⟩, .N => ⟨.U, x, y + 2⟩
  | ⟨.V, x, y⟩, .E => ⟨.V, x + 1, y⟩
  | ⟨.V, x, y⟩, .S => ⟨.U, x, y - 1⟩
  | ⟨.V, x, y⟩, .W => ⟨.V, x - 1, y⟩

def legal (floor : Finset Cell) (goal : Cell) (p : Pose) : Prop :=
  p.cells ⊆ floor ∨
  (p.o ≠ .U ∧ goal ∈ p.cells ∧ p.cells \ {goal} ⊆ floor)

def win (goal : Cell) (p : Pose) : Prop :=
  p = ⟨.U, goal.1, goal.2⟩

def Move (floor : Finset Cell) (goal : Cell) (p q : Pose) : Prop :=
  ∃ d : Dir, q = step p d ∧ (win goal q ∨ legal floor goal q)

def Solvable (floor : Finset Cell) (goal : Cell) (start : Pose) : Prop :=
  Relation.ReflTransGen (Move floor goal) start ⟨.U, goal.1, goal.2⟩

end BlockEscape

Orient has the three constructors \(U,H,V\); Cell is \(\mathbb Z^2\); Pose is an orientation plus coordinates; Dir is \(D\). The function step is the twelve-case pivot table. legal includes the half-hole exception, win is standing on the goal, and Solvable is reflexive-transitive reachability. This listing is a specification; it is not machine-checked in this artifact because the Lean toolchain is not bundled.

4.1 Level, poses and state graph

A level is \(M=(B,h,s)\). A pose \(b\) is admissible when it is legal or winning. The winning pose is always added, because \(U(h)\) is not legal: the hole is not floor.

The graph is just a list of poses and moves. Each safe pose is a node. Each legal swipe is an arrow to the next pose. The start is \(s\); the goal is \(U(h)\). A swipe that lands off the floor is a fall, so it gets no arrow: it returns the block to the same pose and cannot help a shortest solution. That is the whole graph.

4.2 Breadth-first solver

Every edge costs one swipe, so breadth-first search returns a shortest winning word:

if win(s): return ε
Q ← [(s, ε)];  seen ← {s}
while Q is not empty:
  (b, w) ← dequeue(Q)
  for d in D:
    q ← step(b, d)
    if win(q): return w·d
    if q is a state and q ∉ seen:
      seen ← seen ∪ {q}
      enqueue(Q, (q, w·d))
return ⊥
Optional: runnable JavaScript and Python solvers

The executable form is the same loop. It returns the move word and its length, and uses the game's fromCells, step and key helpers:

function solve(M) {
  const s = fromCells(M.start);
  const Q = [{ b: s, w: "" }];
  const seen = new Set([key(s)]);
  for (let i = 0; i < Q.length; i++) {
    const { b, w } = Q[i];
    for (const d of ["N", "E", "S", "W"]) {
      const out = step(M, b, d);
      if (!out) continue;
      if (out.result === "win")
        return { moves: w.length + 1, path: w + d };
      if (out.result === "safe" && !seen.has(key(out.pose))) {
        seen.add(key(out.pose));
        Q.push({ b: out.pose, w: w + d });
      }
    }
  }
  return null;
}

The same breadth-first search in Python, using only the standard library. A level is a dictionary with solid, hole and start; the result is a shortest move string.

from collections import deque

D = {"N": (0, 1), "E": (1, 0), "S": (0, -1), "W": (-1, 0)}

def cells(p):
    o, x, y = p
    if o == "U": return {(x, y)}
    if o == "H": return {(x, y), (x + 1, y)}
    return {(x, y), (x, y + 1)}

def landing(p, d):
    o, x, y = p
    if o == "U":
        return {"N": ("V", x, y + 1), "E": ("H", x + 1, y),
                "S": ("V", x, y - 2), "W": ("H", x - 2, y)}[d]
    if o == "H":
        return {"N": ("H", x, y + 1), "E": ("U", x + 2, y),
                "S": ("H", x, y - 1), "W": ("U", x - 1, y)}[d]
    return {"N": ("U", x, y + 2), "E": ("V", x + 1, y),
            "S": ("U", x, y - 1), "W": ("V", x - 1, y)}[d]

def legal(level, p):
    floor = {tuple(c) for c in level["solid"]}
    hole = tuple(level["hole"])
    covered = cells(p)
    if covered <= floor:
        return True
    return (p[0] != "U" and hole in covered
            and (covered - {hole}) <= floor)

def win(level, p):
    return p == ("U", *level["hole"])

def solve(level):
    start = ("U", *level["start"][0])
    queue = deque([(start, "")])
    seen = {start}
    while queue:
        p, word = queue.popleft()
        for d in D:
            q = landing(p, d)
            if win(level, q):
                return word + d
            if legal(level, q) and q not in seen:
                seen.add(q)
                queue.append((q, word + d))
    return None

The Python solver mirrors the graph exactly. It uses tuples ("U", x, y), ("H", x, y) and ("V", x, y) for poses; seen prevents revisiting; and the queue order guarantees the first win is shortest. The JavaScript loop above is the same algorithm used by the game.

Every graph edge is a legal swipe, and every legal non-falling swipe is an edge. BFS therefore discovers poses in increasing move count, so the first win is optimal. Falls are omitted because they change nothing; the state space is finite, so the search terminates. There are at most \(3(|B|+1)+1\) states, under 400 for the \(13\times9\) artifact.

Every non-goal move is undone by the opposite swipe, so the non-goal graph is undirected; the goal is terminal. Counting the shortest-path DAG gives the number of shortest words. The generator gives one solution, so the level is solvable by construction; its walk length is an upper bound on the optimum, usually strict. BFS returns \(\operatorname{opt}(M)\), not \(\operatorname{par}(M)\).

5. The modulo-3 idea

The math in one screen.

The phase is a filter, not a complete solver: a matching phase still does not guarantee a solution.

Give every pose a phase: two remainders, one for the column and one for the row. For a standing block, use its tile. For a lying block, use the empty tile just behind it:

\[ \begin{aligned} \varphi(U(p)) &= p\bmod 3,\\ \varphi(L(p,p+d)) &= (p-d)\bmod 3 . \end{aligned} \tag{3} \]
(0,0) (1,0) (2,0) (0,1) (1,1) (2,1) (0,2) (1,2) (2,2) x mod 3 y mod 3 phase = (x mod 3, y mod 3) Key colour class 0 colour class 1 colour class 2 tip: same cell roll: one cell sideways (wrapping at the edges)
Figure 7. The phase is a pair of remainders, so it lives on a \(3\times3\) grid. A tip keeps the same address. A side-roll moves one cell up, down, left, or right, wrapping at the edges; it also needs a \(2\times2\) patch. The three tints are the single-colour projection \(\chi=(x+y)\bmod3\), not the full pair.

Read \(p\bmod3\) as “the two remainders of the tile's column and row.” There are only nine possible phases, \((0,0)\) through \((2,2)\). Projecting the pair to one number gives the single colour \(\chi(p)=(x+y)\bmod3\).

Example. The tiles \((0,0)\) and \((1,2)\) both have single colour \(0\), but their phases are \((0,0)\) and \((1,2)\). The pair sees a difference that the single colour hides.

5.1 Tips do nothing to the phase

A tip changes the pose but not the phase. The reason is the definition: a standing block at \(p\) tips to a lying block whose “behind” tile is still \(p\). A lying block stands up at the same phase it already had. So if a play uses only tips, the phase is fixed from start to finish.

5.2 Rolls move one step

A side-roll shifts a lying block one tile sideways. That changes exactly one of the two remainders by \(\pm1\). The roll also covers four tiles in a \(2\times2\) square, so all four must be usable: floor, or the hole as the one allowed exception.

5.3 What this tells you

1. A quick impossibility test. If the board has no \(2\times2\) patch, no roll is possible, so the phase cannot change. If the start and the hole have different phases, the level is impossible. Example: start phase \((0,0)\), hole phase \((2,0)\), no \(2\times2\) patch — no solution.

2. Straight corridors. In a one-tile-wide corridor, every move is a tip. Two tips move the block three tiles. So the hole must be 3, 6, 9, … tiles away, and the shortest solution is \(2m/3\) moves for distance \(m\). Example: \(m=6\) needs 4 tips; \(m=4\) is impossible.

3. A lower bound on rolls. Think of the phase as a position on a \(3\times3\) wrapping grid. A tip stays put; a roll moves one cell up, down, left, or right. So the number of rolls is at least the shortest distance on that grid. Example: a phase difference of \((1,2)\) needs at least 2 rolls.

That is the whole idea. The phase is not a complete solver, and the roll bound is often weak; but it quickly rules out some holes and explains the corridor pattern.

6. The generator and samples

In plain words. The game makes a level by taking a random walk and painting every touched tile as floor. It stops standing on a new tile and turns that tile into the hole. Replaying the walk is therefore a legal solution; its length is the par. The par is not the shortest solution: the walk may wander, and a search usually finds a shorter route.

The generator's walk is a solution, so every level is solvable. It is not a shortest solution: the par is the walk length, and breadth-first search usually finds a shortcut. The game exposes that shortest length as Best next to your moves. The sample table uses a fixed seed; the live game uses a fresh random walk for each layout.

Table 5. Six seeded generated levels. \(\operatorname{par}(M)\) is the generator walk; \(\operatorname{opt}(M)\) is BFS on the partial-hole graph, shown in the game as Best; pads counts \(2\times2\) squares in \(B\cup\{h\}\); pair compares \(\varphi(s_0)\) with \(\varphi(U(h))\), and 3-colour compares the corresponding \(\chi\) values; walk rolls counts side-rolls in the generator walk.
nparoptimumfloorpadspair3-colourwalk rolls
1207166noyes4
2267219nono4
3177188noyes5
42010228nono12
5305187yesyes8
6247208nono4

Row 1 is the level in Figure 6: a single colour match hides a phase mismatch, so the single colour is not enough. Row 5 has a matching pair yet the generator walk uses eight rolls; a match does not mean roll-free. The par is much larger than the optimum in every row; the walk is a witness, not a shortest path.

7. Playable artifact

The artifact is the endless game itself: a random walk on the default \(13\times9\) board, partial-hole support, no fixed levels. Open it directly if your browser blocks local iframes. The 3D board needs WebGL.

Play. Arrow keys / WASD, or drag the board. R restarts the same layout; N starts the next level after a win; completed levels can be replayed from the level strip. Any key after a win starts the next one. A fall returns the block to the last safe position. Standing on the hole wins; a lying block may rest with one end over the hole. Open full screen.

8. Verification

The endless rules, generator and phase are checked by node tools/test_endless.js: it generates 500 seeded layouts, replays every walk, checks that each placement is supported (one end of a lying block may use the hole), that the final placement wins, that every tip preserves the pair and every roll moves one coordinate, and that a lying block over the hole is a rest, not a win. The sample table and Figure 6 come from node tools/sample_endless.js and a small SVG renderer; the optimum column is the BFS solver from Section 4.2. The game is built by python3 tools/build_endless.py.

The game and the paper are both offline. The paper's mathematics is set with KaTeX and the KaTeX Computer Modern fonts, vendored under katex/. The game embeds Three.js and DM Sans.

9. Limits

In plain words. The colour test can rule some levels out, but it cannot solve a level by itself. The generator's par is a practice route, not the best possible route. The game is deliberately small: no switches, no keys, no enemies, and no fixed set of levels.

The phase is necessary, not sufficient. A matching pair still needs a search. The torus bound is weak for the same reason: the phase has only nine classes. The generator's par is not an optimum; it is a witness produced by a random walk. Partial-hole support is the stated rule: a lying block may rest with one end over the hole, but only standing on it wins. The board size and walk target are parameters; the artifact uses \(13\times9\) and \(\min(10+2n,40)\). The game has no switches, trapdoors, height, or moving blocks. The four Lean-style definitions and the state graph are the specification; the breadth-first solver and the JavaScript game are the executable references.

References

  1. T. C. van der Zanden and H. L. Bodlaender. PSPACE-completeness of Bloxorz and of Games with 2-Buttons. arXiv:1411.5951, 2014.
  2. Liminal Math. Block Escape, endless edition: the game source game/logic.js, game/scene3d.js, game/app3d.js, and index.html, 2026.
  3. Liminal Math. Generator and phase checker: tools/test_endless.js, tools/sample_endless.js, and tools/build_endless.py, 2026.