Phaser AE

Shape-placing puzzles

Pro packv3.0.0-32DGrid

The block-placing puzzle: a tray of fixed shapes, a grid with no gravity, and full lines that clear. The one rule the genre turns on, that the game ends only when nothing in the hand fits anywhere, is checked properly here.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 14, 2026 · updated October 20, 2026

Shape-placing puzzles: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

The pack

placer

function placer(): Pack<{ placer: PlacerApi }>

The placer pack. Pure logic, so it needs no backend and runs headless.

Helpers

createPlacer

function createPlacer(cfg: PlacerConfig): Placer

Creates a Placer board from the given configuration. Throws when cols or rows is not an integer of at least 2, or when a region has a cell off the board.

PIECES_1010

const PIECES_1010: PieceDef[]

The canonical 1010! piece set: lines 1–5, squares, L/T/S shapes.

PIECES_BLOCKS

const PIECES_BLOCKS: PieceDef[]

Tetromino set (Block Blast leans on these), no rotation in tray games.

sudokuBoxes

function sudokuBoxes(cols = 9, rows = 9, box = 3): RegionDef[]

The sudoku-box regions that tile a cols × rows board (default 9 × 9) with box × box squares (default 3), left to right and top to bottom: Woodoku's nine 3×3 boxes of a 9×9 board by default, or sudokuBoxes(8, 8, 4) for four 4×4 boxes of an 8×8. Ids are box<bx><by> by box column and row (box00 at the top left), with a hyphen between the two (box10-3) once a side has more than ten boxes. Throws when any argument is not a positive integer, or box does not divide both cols and rows: a box that ran off the board could never fill.

Classes

Placer

class Placer

A drag-piece puzzle board (1010!/Woodoku style). Create one with createPlacer.

  • readonly cols: number — The number of columns on the board.
  • readonly rows: number — The number of rows on the board.
  • tray: Piece[] — The pieces the player can place now. Refilled when empty.
  • score: number — The score gained from placements and clears so far.
  • placements: number — The number of pieces placed so far.
  • gameOver: boolean — True when no tray piece fits on the board — the game is over.
  • streak: number — Current clearing streak (consecutive placements that cleared ≥1 region).
  • constructor(cfg: PlacerConfig)
  • cell(x: number, y: number): PlacedCell | null — The placed cell at (x,y), or null.
  • canPlace(pieceId: number, at: XY): boolean — Can pieceId be placed with its origin at at?
  • rotatePiece(pieceId: number, dir: 1 | -1 = 1): void — Rotate a tray piece 90° in place (dir 1 = CW, -1 = CCW). No-op unless rotate is configured. Cells are re-normalised to a (0,0) origin.
  • place(pieceId: number, at: XY): PlaceResult — Place a tray piece; commit, clear completed regions, refill when empty.
  • findPlacements(pieceId?: number): Placement[] — Every legal placement of every tray piece (or one piece), scored, best first.
  • autoplay(maxPlacements = 500): PlaceResult[] — Auto-play by a policy until game over; returns each result.
  • debugGrid(): string — Rows of #/. — handy in tests.

Types

Piece

interface Piece

A live tray piece.

  • id: number — The unique instance id of the piece.
  • cells: XY[] — The cells of the piece, relative to its (0,0) origin.
  • tag?: string — The label carried over from the piece definition, if it had one.

PieceDef

interface PieceDef

A tray piece shape: cells relative to (0,0), plus a deal weight.

  • cells: XY[] — The cells of the shape, relative to its (0,0) origin.
  • weight?: number — Relative deal frequency. Default 1.
  • tag?: string — Optional label carried onto placed cells and journal events.

PlacedCell

interface PlacedCell

One placed board cell.

  • fill: number — Piece-instance id that filled it (for colour/theming).
  • tag?: string — The label carried over from the piece definition, if it had one.

Placement

interface Placement

A legal placement found by findPlacements.

  • pieceId: number — The id of the tray piece to place.
  • at: XY — The board cell for the piece origin (its 0,0 cell).
  • clears: number — Regions this placement would complete.
  • value: number — Heuristic value, higher = better.

PlacerApi

type PlacerApi = typeof kit

game.placer — every function and type this pack carries, as one namespace.

PlacerConfig

interface PlacerConfig

Configures createPlacer. cols and rows must be integers of at least 2.

  • cols: number — The number of columns on the board. Must be an integer of at least 2.
  • rows: number — The number of rows on the board. Must be an integer of at least 2.
  • seed?: number — The seed for the deterministic tray deals. Default 1.
  • regions?: RegionDef[] — Extra clearable regions beyond the default rows+columns (e.g. sudoku boxes). Every cell must be on the board; the constructor throws on one that is not.
  • pieces?: PieceDef[] — The deal pool. Default: the 1010! set.
  • traySize?: number — Pieces per tray. Default 3.
  • rotate?: boolean — Allow rotating tray pieces 90° (board.rotatePiece). Off in the classic games (1010!/Block Blast/Woodoku place pieces as dealt); opt in for a variant.
  • pieceFilter?: (fillRatio: number, pool: PieceDef[]) => PieceDef[] — Adaptive/weighted piece generation hook (Block Blast style). Given board fill ratio 0..1, return the pool to draw from. Default: the static pool.
  • scorer?: (ev: { cellsPlaced: number; regions: number; streak: number }) => number — Score a placement; called for every one, with regions 0 when nothing clears and streak the run before it. Default: the cells placed, plus a Block-Blast-like steep multi-region curve when it clears.

PlaceResult

interface PlaceResult

The outcome of one Placer.place call.

  • valid: boolean — True when the piece fit and was placed. False leaves the board unchanged.
  • steps: PlacerStep[] — The ordered event journal for this placement — present the steps in order.
  • combo: number — Regions cleared this placement (combo size).
  • streak: number — Consecutive clearing placements including this one (0 if this cleared nothing).
  • gained: number — The score gained by this placement.
  • gameOver: boolean — True when no remaining tray piece fits on the board.

PlacerStep

type PlacerStep = | { type: 'place'; pieceId: number; cells: XY[]; fill: number } | { type: 'regionClear'; regions: string[]; cells: XY[] } | { type: 'trayRefill'; pieces: { id: number; cells: XY[] }[] } | { type: 'gameOver' }

One event in a placement journal: a place, a region clear, a tray refill, or game over.

RegionDef

interface RegionDef

A clearable region: a named set of cells that vanishes when all are filled.

  • id: string — The unique name of the region, reported in regionClear steps.
  • cells: XY[] — The cells that make up the region.

XY

interface XY

A board cell position.

  • x: number — The column of the cell.
  • y: number — The row of the cell.