Phaser AE

Slide-merge puzzles

Pro packv3.0.0-32DGrid

The rules of the slide-and-merge number puzzle: every tile shifts as far as it can in one direction and matching neighbours combine on the way. Each move returns a per-tile script for your game to animate, and a hint plays well without ever changing what the game would have done.

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

Slide-merge 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

slide

function slide(): Pack<{ slide: SlideApi }>

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

Helpers

config2048

function config2048(over: Partial<SlideConfig> = {}): SlideConfig

2048: slide all the way, equal tiles sum, spawn 2 (90%) / 4 (10%) anywhere.

configThrees

function configThrees(over: Partial<SlideConfig> = {}): SlideConfig

Threes: one-step slide, 1+2=3 then equal-doubles, spawn on the swiped-from edge.

createSlide

function createSlide(cfg: SlideConfig): Slide

Creates a slide-merge board with its start tiles spawned.

Classes

Slide

class Slide

A directional-slide merge board (2048, Threes). Get one from createSlide with config2048 or configThrees.

  • readonly cols: number — The number of columns in the board.
  • readonly rows: number — The number of rows in the board.
  • score: number — The score. Each merge adds the merged value.
  • moveCount: number — The number of valid moves made so far.
  • won: boolean — True after a tile reaches the win value. Play continues.
  • constructor(cfg: SlideConfig)
  • tile(x: number, y: number): Tile | null — Returns the tile at (x, y), or null when the cell is empty.
  • tiles(): Tile[] — All live tiles.
  • peek(): number | null — The previewed next value (Threes), or null.
  • move(dir: Dir): SlideResult — Slides all tiles in one direction, merges, and spawns. Returns the per-tile records for the presenter.
  • legalMoves(): Dir[] — Directions that would change the board.
  • suggest(opts: SuggestOptions = {}): Dir | null — The move to play, or null when the board is stuck. Makes no move and consumes no randomness: the game after asking is byte-identical to the game before. For a hint button, an attract mode, a tutorial's pointing finger, or a test that needs a board played competently rather than merely played.
  • autoplay(maxMoves = 2000, opts: SuggestOptions & { policy?: 'suggest' | 'simple' } = {}): SlideResult[] — Play the game out, for tests and for checking a config. By default it plays the way suggest plays; pass policy: 'simple' for the old fixed preference (left, down, right, up), which is much weaker and useful mainly for producing a losing board quickly.
  • debugGrid(): string — Returns the board as tab-separated text, one row per line, for debug output.

Types

Dir

type Dir = 'up' | 'down' | 'left' | 'right'

One of the four slide directions.

SlideApi

type SlideApi = typeof kit

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

SlideConfig

interface SlideConfig

Configures a slide-merge board for createSlide. config2048 and configThrees build one.

  • cols: number — The number of columns in the board.
  • rows: number — The number of rows in the board.
  • seed?: number — The seed for the random generator. Default 1.
  • step: 'full' | 'one' — full slides tiles as far as possible (2048); one moves one cell (Threes).
  • canMerge?: (a: number, b: number) => number | null — Merge predicate → the resulting value, or null for no merge. Default: equal→sum.
  • spawn: SpawnPolicy — Where and how a new tile spawns after each valid move.
  • startTiles?: number — Tiles spawned at game start. Default 2.
  • winValue?: number — Reaching this value flags won (play continues). Default 2048; 0 disables.

SlideCorner

type SlideCorner = 'topLeft' | 'topRight' | 'bottomLeft' | 'bottomRight'

The corner a hint stacks the big tiles into.

SlideResult

interface SlideResult

What one move did — the presenter's slide-then-pop script. Returned by Slide.move.

  • valid: boolean — True when the move changed the board. An invalid move spawns nothing.
  • moves: TileMove[] — Each tile slide this move, with start and end cells.
  • merges: TileMerge[] — Each merge this move.
  • spawn: { id: number; value: number; at: XY } | null — The tile spawned after the move, or null when no cell was free.
  • gained: number — The score gained this move: the sum of the merged values.
  • gameOver: boolean — True when no move can change the board.
  • won: boolean — True when a tile has reached the win value.

SpawnPolicy

interface SpawnPolicy

Configures where and with which values new tiles spawn. Set on SlideConfig.spawn.

  • where: 'anyEmpty' | 'oppositeEdge' — anyEmpty (2048) or oppositeEdge (Threes — only lanes that shifted).
  • table: 'weighted' | 'bag' — weighted (value→weight table) or bag (shuffled multiset, refilled).
  • values: [number, number][] | number[] — For weighted: [value, weight] pairs. For bag: the multiset values.
  • preview?: boolean — Show the next tile before it spawns (Threes).

SuggestOptions

interface SuggestOptions

How suggest should think.

  • depth?: number — How many of the player's moves to look ahead, 1 or more. Default 2. 1 is greedy: it picks the move whose resulting board scores best. 2 and above also ask what the WORST spawn could do to that board and what the player could do next, which is what stops a hint from walking into a full board it could have seen coming. Each extra ply multiplies the work by roughly the number of empty cells times four, so 3 is the practical ceiling on a full board.
  • corner?: SlideCorner — Which corner to stack the big tiles into. Default 'topLeft'. Every strong policy for this family keeps the largest tile pinned in one corner with a descending run along the edge beside it, because that is what lets a big tile ever find a partner. Which corner is arbitrary — but it must be the SAME one every move, so it is chosen here rather than drifting.

Tile

interface Tile

A live tile. value is the number shown; id is stable for animation.

  • id: number — A stable id for animation. Ids increase from 1.
  • value: number — The number the tile shows.
  • x: number — The column index of the tile.
  • y: number — The row index of the tile.

TileMerge

interface TileMerge

A merge that happened this move. into survives; gone is removed after sliding.

  • intoId: number — The id of the tile that survives the merge.
  • goneId: number — The id of the tile removed after it slides in.
  • at: XY — The cell where the merge happens.
  • value: number — The value of the merged tile.

TileMove

interface TileMove

Per-move tile movement (for the presenter).

  • id: number — The id of the tile that moved.
  • from: XY — The cell the tile left.
  • to: XY — The cell the tile ends in.

XY

interface XY

A grid position: x is the column index and y is the row index, 0 at the top left.

  • x: number — The column index, 0 at the left.
  • y: number — The row index, 0 at the top.