Guide
Game block-pushing and Sokoban puzzle systems explained
Harbor Quarry’s warehouse wing looked like a fair spatial puzzle: push crates onto pressure pads to open the exit. Telemetry told a harsher story — 62% of players who entered created an unwinnable block layout within their first three pushes, and only 18% reached the exit without reloading a save. The culprit was not difficulty; it was silent deadlocks from corner traps and a missing undo stack. After a layout pass that eliminated corner-deadlock tiles, adding ice-floor telegraphs, and shipping unlimited undo with move-count scoring, room completion rose to 69% while average solve time dropped 40%.
Block-pushing puzzles (Sokoban and its variants) ask players to rearrange discrete objects on a grid under strict movement rules. Unlike pressure-plate signal graphs where state propagates through wires, push puzzles make the player avatar the actuator — every move is irreversible unless you implement undo. This guide covers grid representation, canonical push rules, goal detection, ice and multi-push variants, deadlock theory, solvability validation, undo design, the Harbor Quarry refactor, a technique decision table versus other puzzle families, pitfalls, and a production checklist.
Canonical Sokoban rules
Classic Sokoban (warehouse keeper) defines a small rule set that players learn once and apply everywhere:
- The player moves on a grid one tile at a time (four directions).
- The player can push one adjacent crate; cannot pull.
- A crate moves into the next tile only if that tile is empty (or a goal).
- Crates cannot pass through walls or other crates.
- The puzzle is solved when every crate rests on a goal tile (exact count match).
These rules create monotonic difficulty: each push reduces future flexibility. That is the genre’s signature tension — and why deadlocks feel so punishing when the game does not telegraph them.
Grid layer model
Implement puzzles as layered tile data, not a single enum per cell:
floor[x,y] = empty | wall | goal | ice
entity[x,y] = none | player | crate | crate_on_goal
meta[x,y] = hole | conveyor | color_tag (optional)
Separating terrain from occupants lets goals persist under crates, ice modify movement without duplicating crate state, and validators run reachability on floor alone.
Push resolution algorithm
On player input direction d, compute target cell
t = player_pos + d:
- If
floor[t]is wall, reject move. - If
entity[t]is empty, move player tot. - If
entity[t]is crate, letu = t + d. - If
floor[u]is wall orentity[u]is occupied, reject. - Move crate to
u, player tot; update goal-on-goal flags.
Run push resolution before animation so simulation stays
authoritative; tween sprites toward grid targets afterward. For networked or
replay systems, log (tick, direction) pairs — the grid state is
fully determined by the move sequence.
Ice and slide variants
Ice floors continue movement in the input direction until the actor hits a wall, crate, or non-ice tile. Apply ice to the player, crates, or both independently. Chained ice slides compound errors — telegraph ice with distinct palette and SFX before the first slide puzzle.
Multi-crate push (non-canonical) allows pushing a line of crates if all cells in the line are free. Use sparingly; it changes deadlock math and confuses players trained on classic rules.
Deadlocks: why players quit
A deadlock is a board state from which no sequence of legal pushes reaches a solution. Players experience this as “I broke the puzzle” even when they followed reasonable instincts.
Simple deadlock patterns
- Corner deadlock — crate pushed into a floor corner (two adjacent walls); can never leave.
- Wall deadlock — crate against a wall segment with no goal on that line and no room to maneuver around.
- Pair deadlock — two crates blocking each other in a two-tile alcove.
- Goal starvation — a goal tile permanently blocked by a crate that does not belong there.
Detect corner deadlocks at push time with a cheap predicate:
fn is_corner_deadlock(pos, floor):
wall_N = floor[pos + up] == wall
wall_E = floor[pos + right] == wall
wall_S = floor[pos + down] == wall
wall_W = floor[pos + left] == wall
return (wall_N and wall_W) or (wall_N and wall_E)
or (wall_S and wall_W) or (wall_S and wall_E)
If a push would place a non-goal crate into a corner deadlock, warn in tutorial levels; in hard levels, either forbid the push (controversial) or accept it as player error with generous undo.
Full solvability checking
For level authoring, run reverse BFS from the goal configuration: start with all crates on goals, pull crates backward (inverse pushes) until no new states appear. If the level’s start state is unreachable, the level is unsolvable. Tools like Sokoban level editors embed this check — run it in CI for every hand-authored room.
Undo, reset, and move economy
Push puzzles are mistake-prone by design. Production UX almost always includes:
- Undo stack — snapshot grid state per move; pop on undo. Memory cost is tiny for typical room sizes (under 20×20).
- Room reset — one button to restore initial layout; essential on console without quick-save.
- Move counter — par moves for star ratings; separate from undo (undo does not increment; or use “effective pushes” only).
Harbor Quarry originally charged stamina per undo — players avoided exploration and rage-quit after one bad push. Removing undo friction mattered more than lowering crate count.
Hint ladders
Tier hints without spoiling: (1) highlight crates not on goals, (2) show next optimal push direction from a solver, (3) replay a full solution path. Pair with puzzle design hint philosophy so hints escalate only after sustained failure.
Variants beyond classic Sokoban
| Variant | Rule change | Design note |
|---|---|---|
| Colored crates and goals | Crate color must match goal color | Increases planning depth; document color rules in first room |
| Holes and pits | Crate falls in and is destroyed or respawns | Irreversible loss — pair with reset or limited crate supply |
| Linked crates | Two crates move together | Harder deadlock analysis; use in late-game only |
| Rotating blocks | Push changes block orientation for laser puzzles | Hybrid with beam routing |
| Realtime pressure | Conveyor belts move crates while player acts | Shifts genre toward action; see conveyor systems guides |
Embedding push puzzles in larger games
Pure Sokoban games live or die on level packs. In action-adventure or RPG contexts, push rooms should be short (one to three crates for optional loot, five to eight for dedicated puzzle wings). Gate difficulty with count and topology, not realtime threats — combat while pushing crates feels fiddly unless your core loop already supports it.
Couple push outcomes to pressure plates when crates should hold doors open: the crate becomes a persistent world object, not a goal-tile victory. Document whether leaving the room resets crates; inconsistent reset rules cause backtracking bugs familiar from key-door design.
Harbor Quarry refactor walkthrough
Harbor Quarry (fictional composite) is a puzzle-adventure with warehouse set-pieces. Before refactor, Room 7 (“Slipway Storage”):
- Completion rate: 18% (first attempt, no guide)
- Median moves before quit: 9 (puzzle solvable in 24 optimal)
- Deadlock rate: 62% of sessions created corner deadlock within 3 pushes
- Undo usage: 0.4 per player (stamina cost discouraged use)
Root causes from replay review:
- Corner trap layout — three crates started two pushes from irrecoverable corners.
- Ice without tutorial — first ice tile slid a crate into a wall deadlock before players understood slide rules.
- Ambiguous goals — floor marks looked decorative; players parked crates on wrong pads.
- Punishing undo — stamina cost made experimentation expensive.
Interventions:
- Authoring CI — reverse BFS solvability check; reject levels with start states within two pushes of corner deadlock unless flagged hard.
- Layout pass — widened south alcove by one tile; moved one goal off a choke point.
- Ice intro room — single-crate slide tutorial before Room 7.
- Goal clarity — pulsing outline on goals when crate is adjacent; distinct palette for “crate correctly placed.”
- Free undo + par display — unlimited undo; star rating on push count only.
Outcome: completion 18% → 69%, median moves before quit 9 → 28 (players persisted longer), undo usage 0.4 → 6.2 per session. Optional loot uptake rose without lowering combat difficulty elsewhere.
Technique decision table
| Design goal | Prefer block-pushing | Prefer alternative |
|---|---|---|
| Spatial planning with irreversible moves | Sokoban grid with undo safety net | Pressure plates (state reversible by stepping off) |
| Permission gating across rooms | Crate holds door open permanently | Key-door inventory graph |
| Optical routing puzzles | Rotating crate mirrors (hybrid) | Fixed mirror beam puzzles |
| Teaching careful movement | Small crate count, wide corridors | Precision platforming gauntlets |
| Speedrun / par competition | Move-count stars, leaderboards | Realtime physics stacking |
| Procedural endless mode | Generator with solvability oracle | Hand-authored curated packs only |
Common pitfalls
- Unsolvable layouts shipped — no reverse BFS in authoring pipeline.
- Corner traps near start — players deadlock before understanding rules.
- Missing undo — one mistake equals reload; mobile players churn.
- Ice without telegraph — sudden slides into deadlocks feel unfair.
- Decorative floor art — players cannot distinguish goals from noise.
- Too many crates — search space explodes; optimal play becomes tedious.
- Mixing push and combat — unless core loop supports it, friction not fun.
- Inconsistent room reset — crates reset but door state persists, softlocking.
Production checklist
- Layer floor, entity, and meta grids; keep goals as floor data under crates.
- Implement authoritative push resolution before animation tweens.
- Run reverse BFS solvability on every level at build time.
- Flag corner-deadlock pushes in tutorial; consider layout fixes over hard blocks.
- Ship unlimited undo or cheap reset; score on push count, not mistakes.
- Telegraph ice, holes, and colored-goal rules in isolated intro rooms.
- Use distinct VFX/SFX when crate enters goal state.
- Cap optional-room crate count (1–3 casual, 5–8 dedicated wing).
- Log push sequences in playtests to find early deadlock clusters.
- Document room reset behavior for crates, doors, and plates.
- Provide tiered hints tied to time-on-puzzle or failed push count.
- Playtest with gamepad and keyboard; grid games need responsive single-tap input.
Key takeaways
- Sokoban rules are simple; deadlocks are not. Validate levels with reverse BFS, not guesswork.
- Undo is part of the puzzle. Punishing experimentation kills completion more than difficulty.
- Harbor Quarry rose from 18% to 69% completion after layout, ice tutorial, and free undo.
- Corner deadlocks are detectable with cheap geometry checks at authoring time.
- Push puzzles pair well with plates and doors when crate state persists as world input.
Related reading
- Pressure plate and switch puzzle systems — signal graphs when crates should trigger doors
- Door, key and lock puzzle systems — permission gating and backtracking graphs
- Puzzle platformer design — embedding spatial puzzles in traversal levels
- Game puzzle design — fair constraints, hint ladders and the eureka moment