返回 Skills 目錄
gamedev-skills/awesome-gamedev-agent-skills已通過檢查

SKILL DETAIL

puzzle

gamedev-skills/awesome-gamedev-agent-skills/puzzle

Build a puzzle game: grid/board state, move input, rule-based resolution (match-3 cascades, sokoban pushes, tile logic), scoring, and undo. Use for a match-3, sokoban, or grid-logic puzzle.

安裝量 · 231查看來源

Installation

npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill puzzle

技能檔案

SKILL.md

最近同步 · 2026年10月24日

references/board-and-resolution.md›
# Puzzle board models and resolution (depth)

Detail behind `SKILL.md`. Engine-neutral pseudocode. Board coordinates are `(y, x)` with
`(0,0)` top-left and `y` growing downward (matches most tilemaps).

## 1. Match-3 full resolution

The resolution loop is: detect matches → score → clear → gravity → refill → repeat until stable.

```python
def apply_gravity(board):
    for x in range(W):
        # Compact non-empty cells downward within each column.
        column = [board[y][x] for y in range(H) if board[y][x] is not EMPTY]
        pad = [EMPTY] * (H - len(column))
        for y in range(H):
            board[y][x] = (pad + column)[y]      # empties on top, pieces settle to the bottom

def refill(board, rng):
    for y in range(H):
        for x in range(W):
            if board[y][x] is EMPTY:
                board[y][x] = random_piece(rng)  # seeded RNG for reproducibility
```

**Avoid spawning matches on refill** if you don't want free cascades: when filling, reject a
color that would immediately complete a line, or resolve those cascades intentionally as part
of scoring.

**Initial board:** generate so there are **no pre-existing matches** but **at least one valid
move** (see deadlocks). A common method: fill randomly, clear any starting matches, then verify
a move exists.

## 2. Deadlock detection and reshuffle (match-3)

A board with no possible matching move is a soft-lock. Detect it and react:

```python
def has_valid_move(board):
    # Try every adjacent swap; if any creates a match, a move exists.
    for y in range(H):
        for x in range(W):
            for dy, dx in ((0, 1), (1, 0)):
                if in_bounds(y+dy, x+dx):
                    swap(board, (y, x), (y+dy, x+dx))
                    ok = bool(find_matches(board))
                    swap(board, (y, x), (y+dy, x+dx))   # swap back
                    if ok: return True
    return False
# If not has_valid_move(board): reshuffle existing pieces (keep counts) until a move exists,
# or end the level, depending on your rules.
```

## 3. Cascade scoring

Reward chains so deep setups feel great:

```python
def score_for(matches, chain):
    base = len(matches) * 10
    return base * chain            # linear in chain; or base * 2**(chain-1) for exponential
# Bonus for larger single matches (4 = line-clear piece, 5 = color bomb, etc.) is a common
# layer on top — special pieces created by 4+/5+ matches add strategy.
```

## 4. Sokoban / push puzzles

A different rule family: the player pushes blocks; the goal is to place blocks on targets.
Resolution is a legality check, not a cascade.

```python
def try_push(board, player, dir):
    ahead  = player + dir
    beyond = player + dir * 2
    if is_wall(board, ahead): return False
    if is_block(board, ahead):
        if is_wall(board, beyond) or is_block(board, beyond):
            return False                       # can't push two blocks or into a wall
        move_block(board, ahead, beyond)
    move_player(board, player, ahead)
    return True
# Win when every target cell holds a block. Undo is essential — sokoban is unforgiving.
# Detect dead states (a block pushed into a corner that isn't a target) to hint a restart.
```

## 5. Rule-based / logic puzzles

For logic grids (nonograms, sliding tiles, circuit/flow puzzles), the "resolution" is usually
just **validity + win check** after each move — no cascade. Keep the rule check pure and total:
given a board, return solved / unsolved / invalid. Undo and a clear "current constraints"
display matter more than animation here.

## 6. Undo strategies

| Strategy | Stores | Pros | Cons |
|----------|--------|------|------|
| Snapshot | full board + counters per move | trivial, exact | memory on big boards |
| Command | the move + inverse data | compact | must implement invert per rule |
| Redo stack | future snapshots/commands | redo support | extra bookkeeping |

Whatever you choose, undo must restore **everything** that affects play: board, score, moves
left, RNG state, and any special-piece state. Test undo by hashing full state before a move and
after undo — they must match.

## 7. Solvable generation

Generated levels must be solvable, or players hit unfair dead ends:

- **Generate-and-verify:** make a candidate, run a solver (BFS/DFS/A\* over board states for
  push/slide puzzles; move-existence for match-3); keep it only if solvable within the move/time
  budget. Use a seed so a level is reproducible.
- **Reverse generation:** start from a solved board and apply random *legal inverse* moves; the
  scrambled result is guaranteed solvable by reversing them. Great for sliding/sokoban puzzles.
- Tag each level with its seed and intended difficulty so progression curves are tunable and a
  bad level can be reproduced and fixed.

## 8. Input locking and presentation

The board model resolves instantly; animation plays the resolution out over time. **Lock input
until the board is stable** so the player can't act on a mid-cascade board. Drive visuals from
the sequence of state changes resolution produced (a list of clears/falls/spawns), not by
re-reading a half-updated board.
SKILL.md›
---
name: puzzle
description: >
  Build a puzzle game: grid/board state, move input, rule-based resolution (match-3 cascades, sokoban
  pushes, tile logic), scoring, and undo. Use for a match-3, sokoban, or grid-logic puzzle.
---

# Puzzle

A playbook for grid/board puzzle games — the board model, move input, rule resolution
(matching, pushing, logic), scoring, undo, and level progression. This is a **compositional**
skill: it models board state and rules and presents them through a tilemap/UI. It does not
re-teach tilemaps; it defines the resolution loop and the correctness rules (clean state,
deterministic resolution, undo) that keep a puzzle fair and bug-free.

## When to use

- Use when the game is a **discrete board** the player changes with moves, and the board
  **resolves by rules**: match-3/tile-matching, sokoban/block-pusher, sliding puzzle, logic grid.
- Use when designing match/cascade resolution, undo, level progression, or solvability.

**When *not* to use:** real-time grid action with permadeath → `roguelike`. Card zones/turns →
`card-game`. Physics-based "puzzle platformer" → `platformer` + `physics-tuning`. For the tile
rendering, use `godot-tilemap` / `unity-tilemap-2d`.

## Core loop

**Read the board → plan a move → make the move → the board resolves by its rules (match, push,
fall, fill, cascade) → see progress toward the objective → repeat until solved/failed.** The
fun is the *planning*; the engine's job is to resolve each move **deterministically** and
present it clearly.

## Must-have systems

1. **Board model** — a grid of cells holding pieces; the single source of truth (logic, not visuals).
2. **Move input** — swap, push, drag, rotate, or place; validate legality before applying.
3. **Rule resolution** — detect and apply the genre's rule (matches, pushes, logic) until stable.
4. **Cascades/chains** — when resolution changes the board, re-resolve until no more changes.
5. **Objectives + scoring** — win/lose conditions (score, clear all, reach goal); move/time limits.
6. **Undo** — revert the last move (and its resolution) exactly; essential for thinky puzzles.
7. **Level progression + (often) generation** — hand-authored or generated **solvable** boards.
8. **Feedback ("juice")** — clear, satisfying animation/sound for matches, falls, and chains.

## Design knobs

| Knob | Effect | Notes |
|------|--------|-------|
| Grid size / shape | complexity | Square is standard; hex/irregular change feel. |
| Match/push rule | genre identity | 3-in-a-row, shapes, push-into-goal, etc. |
| Cascade scoring | reward depth | Bigger chains = exponential payoff. |
| Move / time limit | pressure | Move-limited = puzzly; time = arcade. |
| Difficulty curve | learning | Introduce one mechanic at a time. |
| Undo depth | forgiveness | Single-step vs. full history. |
| Solvability guarantee | fairness | Generated boards must be solvable. |
| Deadlock handling | no dead ends | Detect no-moves; shuffle or end (refs). |

## Patterns

### 1. Board model + match detection (logic separate from visuals)

```python
# Pseudocode. The board is the truth; rendering reads from it. (0,0) top-left, y grows down.
board = [[piece_or_empty for _ in range(W)] for _ in range(H)]

def find_matches(board):
    matched = set()
    for y in range(H):                       # horizontal runs of >= 3 equal pieces
        run = 1
        for x in range(1, W):
            if board[y][x] and board[y][x] == board[y][x-1]: run += 1
            else:
                if run >= 3: matched |= {(y, k) for k in range(x-run, x)}
                run = 1
        if run >= 3: matched |= {(y, k) for k in range(W-run, W)}
    # ... repeat the same scan vertically (columns) ...
    return matched
```

### 2. Resolve → collapse → refill → cascade (repeat to stability)

```python
# Pseudocode. One player move can trigger a chain; loop until the board stops changing.
def resolve(board):
    chain = 0
    while True:
        matches = find_matches(board)
        if not matches: break                 # stable: resolution complete
        chain += 1
        score += score_for(matches, chain)    # later chain steps score more (see refs)
        clear(board, matches)                  # remove matched pieces
        apply_gravity(board)                   # pieces fall into the gaps
        refill(board, rng)                      # spawn new pieces at the top (seeded RNG)
    return chain
```

### 3. Undo via state snapshot or command

```python
# Pseudocode. Snapshot before each move; undo restores it exactly (board + score + counters).
def make_move(move):
    history.append(snapshot(board, score, moves_left))   # push BEFORE applying
    apply(move); resolve(board); moves_left -= 1

def undo():
    if history:
        board, score, moves_left = history.pop()         # exact revert, including resolution
```

For large boards prefer the **command** pattern (store the move + enough to invert it) over full
snapshots to save memory; snapshots are simplest and fine for small boards.

## Pitfalls / failure modes

- **Mixing logic and visuals** → animations desync from state and cause bugs. The board model is
  the single source of truth; the view only renders it.
- **Resolving only once** → cascades/chains are missed. Loop resolution until the board is stable
  (Pattern 2).
- **Undo that doesn't restore everything** → score/move-count/random-state drift. Snapshot *all*
  state, or make the move fully invertible.
- **Unseeded refill RNG** → can't reproduce a level / no deterministic undo or daily puzzle. Seed it.
- **Generated boards that aren't solvable** → unfair dead ends. Generate-and-verify, or generate
  from a known solution backward (refs).
- **No deadlock detection** (match-3) → board with no valid moves softlocks. Detect "no moves"
  and shuffle or end the level (refs).
- **Difficulty spikes** → too many mechanics at once. Teach one mechanic per level before combining.
- **Resolution mid-animation accepts input** → double-moves/corruption. Lock input until the
  board is stable.

## Composition (build it from these skills)

- **Board rendering:** `godot-tilemap` / `unity-tilemap-2d` for the grid; `godot-ui-control` for HUD, score, and menus.
- **Levels:** `level-design` for hand-authored puzzles and difficulty pacing; `procedural-gen` for solvable generated boards.
- **Persistence:** `save-systems` for level progress, high scores, and seeded daily puzzles.
- **Juice:** `game-feel` for match/cascade pop, screen shake, and chain feedback; the engine animation/`Tween` skill for swaps/falls/clears; `audio-design` for match and chain cues.
- **Scripting:** `godot-gdscript` / `unity-csharp-scripting` for the resolution loop and rules.

## References

- For match-3 detection/gravity/refill/cascade detail, deadlock detection and reshuffles,
  sokoban/rule-based puzzles, undo strategies, solvable generation, and scoring, read
  `references/board-and-resolution.md`.