ifoxhz/pigame

This is a Pi extension that uses an LLM to drive the game, starting with a simple 2D game.

4

stars

3

commits

TypeScript

primary language

Aug 21, 2026

updated

README

pigame

English | 中文

General game agent on Pi + LLM (e.g. DeepSeek).
Design codename: GameMind. First demo game: Neon Snake.

Remote: git@github.com:ifoxhz/pigame.git

Welcome. Contributions of any kind and any ideas are welcome — let’s make the Pi agent more fun.


Principle

Pi + LLM  = brain (strategy / when to stop)
pigame    = scaffolding only
  tools   = eyes / hands / feet
LayerRole
Pi + LLMDecide what to do; judge when the goal is done
game_observeEyes — see the screen → AgentState
game_move / game_waitHands & feet — act / wait
npm run smoke:* / /game eatTest scaffolding only — hardcoded loops for CI; not the agent path

There is no game_eat_food / game_survive tool. The model loops observe → move itself.


Requirements

ToolNotes
Node.js≥ 20 recommended (--experimental-strip-types)
npmComes with Node
Pi CLIRequired for the agent path (pi on PATH)
LLM in Pie.g. DeepSeek configured in your Pi settings
WSLg / displayOnly for visible Chromium (HEADED=1)

Setup

1. Clone pigame

git clone git@github.com:ifoxhz/pigame.git
cd pigame   # or your local folder name

2. Install pigame deps + Chromium

npm install --prefix pigame
npx --prefix pigame playwright install chromium

Default game (no extra clone): pigame/games/snake.html — a vendored Neon Snake with agent mode (see below).
Anyone who clones this repo gets the patched game automatically; Adapter loads it on /game connect.

3. Optional — upstream Mini Game Studio

Only if you want the original continuous-loop game for comparison:

git clone git@github.com:Digiman/mini-game-studio-ai-gen.git
# HTTPS: https://github.com/Digiman/mini-game-studio-ai-gen.git
SNAKE_HTML=./mini-game-studio-ai-gen/games/snake.html HEADED=1 pi -e ./.pi/extensions/pigame.ts

Live site (reference): https://digiman.github.io/mini-game-studio-ai-gen/

No separate compile step for smokes: Node strip-types runs TypeScript directly.
Root package.json only proxies scripts into pigame/.


Quick test (full run once)

A — One-time setup

git clone git@github.com:ifoxhz/pigame.git
cd pigame   # or your local folder name

npm install --prefix pigame
npx --prefix pigame playwright install chromium

B — Pi + LLM (primary path)

cd /path/to/pigame
HEADED=1 pi -e ./.pi/extensions/pigame.ts

In the Pi TUI (in order):

/game connect
/skill:eat-food

Or paste this prompt instead of the skill:

Use only game_observe, game_move, and optionally game_wait.
Prefer groundTruth grid coords. Eat one food: observe → move → repeat.
When score increases, stop and report before/after score.
Do not reverse 180°.

Watch the Playwright Chromium window (snake freezes between moves).
When done:

/game disconnect

After code changes in a live session: /reload, then /game disconnect/game connect again.

C — Optional: non-LLM smoke (scaffolding)

# Adapter + perception + I/O only (no Pi / no LLM)
npm run smoke:eat
npm run smoke:eat:headed

D — Pack as a Pi npm extension (for others)

npm run pack:pi

Produces:

  • dist/pi-pigame/ — installable directory
  • dist/pigame-0.1.0.tgz — npm tarball

Others install into Pi with:

pi install /path/to/pigame/dist/pi-pigame
# or
pi install /path/to/pigame/dist/pigame-0.1.0.tgz

# after you publish to npm:
# npm publish ./dist/pigame-0.1.0.tgz
# pi install npm:pigame

From a git clone (without packing), they can also:

pi install ./pigame

Then restart Pi or /reload. First time: npx playwright install chromium (from the installed package dir if needed).


Agent-mode Snake (for Pi + LLM latency)

Problem: Upstream Snake ticks on its own. While the LLM is in a long observe → think → move chain, the snake has already moved, so decisions are stale and play feels clumsy.

What we ship: pigame/games/snake.html (see pigame/games/README.md)

BehaviorMeaning
Auto gameLoopPaused after connect (setAgentMode(true))
game_observeWorld stays frozen (no time pass)
game_movesetDir + exactly 1 grid step (MOVE_STEPS to change)

No special startup flag is required for agent mode — connect uses the vendored file by default.

VariableDefaultMeaning
SNAKE_HTMLpigame/games/snake.htmlOverride HTML path
MOVE_STEPS1Grid steps per game_move
HEADEDunset1 → show Chromium

Pi-driven play (primary path)

This is the intended product flow: you open Pi; the LLM uses tools.

Step A — Start Pi with the extension

cd /path/to/pigame
HEADED=1 pi -e ./.pi/extensions/pigame.ts
# or: pi   (auto-loads .pi/extensions/pigame.ts if the project is trusted)

After code changes: /reload.

You should see something like: GameMind ready — LLM tools: game_observe, game_move, game_wait.

Step B — Connect the game (human / slash command)

In Pi:

/game connect

Playwright opens Chromium and loads pigame/games/snake.html (agent-mode), then Start.
World is frozen until each game_move.
Do not open snake.html in your own browser — only the Playwright window is controlled.

Optional: /game observe to sanity-check AgentState.

Step C — Let the LLM drive (prompt)

Example (DeepSeek / any model in Pi):

Use only game_observe, game_move, and optionally game_wait.
Eat one food: observe → choose a direction → move → repeat.
When score increases, stop and report before/after score.
Do not reverse 180° from the previous move.

Or load the skill: /skill:eat-food.

Step D — What the model should do

game_observe  →  read player / food / score
game_move     →  one step toward food
game_observe  →  …
… until the model decides the goal is done …

Slash commands (session scaffolding — not LLM tools)

CommandAction
/gameStatus + help
/game connectStart Playwright Neon Snake
/game observeCompact AgentState (manual check)
/game stateFull AgentState JSON
/game resetRestart round
/game disconnectClose browser
/game mockSwitch to mock adapter
/game eatTest scaffolding — scripted auto-eat
/game surviveTest scaffolding — scripted play until death

LLM tools

ToolRole
game_observeEyes
game_moveHands / feet (up / down / left / right)
game_waitWait

Test scaffolding (npm run smoke:*)

These commands do not use Pi or an LLM. They run fixed policies (eatFoodLoop / surviveUntilEnd) to verify Adapter + Perception + I/O. Use them for CI and debugging — not as the agent design.

# Eat one food (score 0 → 10), headless
npm run smoke:eat

# Same with visible Chromium (WSLg)
npm run smoke:eat:headed

# Long run until death (or stop at a score)
npm run smoke:survive:headed
MAX_SCORE=50 npm run smoke:survive:headed
CommandWhat it checks (scaffolding)
npm run smokeMock adapter / AgentState pipeline
npm run smoke:snakePlaywright open + Start + key + screenshot
npm run smoke:perceptionCV fixture + live perception
npm run smoke:eatScripted steer until score↑
npm run smoke:surviveScripted loop until game over (or MAX_SCORE)
npm run smoke:*:headedSame with HEADED=1

Environment variables (smoke / headed)

VariableDefaultMeaning
HEADEDunset1 / true → show Chromium
SNAKE_HTMLvendored agent snakePath override
MOVE_STEPS1Steps per move (agent mode)
MAX_SCOREnoneSurvive stops when score ≥ value
MAX_STEPS50000Survive step cap
STEP_MS200Visual delay between smoke moves
HOLD_MS50008000Keep window open after headed runs

Neon Snake has no clear — only death; MAX_SCORE is an artificial stop for tests.


Layout

.
├── README.md / README.zh-CN.md
├── package.json                 # script proxies
├── docs/                        # design & schema
├── pigame/                      # main package
│   ├── games/snake.html         # DEFAULT agent-mode Neon Snake (vendored)
│   ├── games/README.md
│   ├── extensions/pigame.ts
│   ├── skills/
│   ├── scripts/                 # smoke:* (test scaffolding)
│   └── src/
├── .pi/extensions/pigame.ts     # Pi entry
└── mini-game-studio-ai-gen/     # optional upstream clone (SNAKE_HTML=…)

Design docs: docs/README.md.


Troubleshooting

IssueFix
Missing pigame/games/snake.htmlPull latest pigame — file is in-repo
Want upstream continuous loopSNAKE_HTML=./mini-game-studio-ai-gen/games/snake.html (clone Digiman first)
Snake runs by itself while LLM thinksYou are not on agent-mode HTML; check default path / SNAKE_HTML
ENOENT package.json at rootUse root scripts or cd pigame
No Chromium windowHEADED=1 or *:headed; check WSLg / echo $DISPLAY
Opened Snake yourself, nothing happensOnly Playwright’s window is controlled
Pi extension not loadedpi -e ./.pi/extensions/pigame.ts then /reload

Acknowledgments

Thanks to Mini Game Studio (Digiman/mini-game-studio-ai-gen) for the original Neon Snake and HTML game collection.
We vendor a patched copy under pigame/games/ for Pi + LLM agent-mode testing (paused auto loop + single-step moves).


License / status

Work in progress (MVP: Pi + LLM drives Snake via observe / move).
Phase notes: docs/implementation.md.

Contributors

ifoxhz

3 commits

ifoxhz/pigame

This is a Pi extension that uses an LLM to drive the game, starting with a simple 2D game.

4

stars

3

commits

TypeScript

primary language

Aug 21, 2026

updated

README

pigame

English | 中文

General game agent on Pi + LLM (e.g. DeepSeek).
Design codename: GameMind. First demo game: Neon Snake.

Remote: git@github.com:ifoxhz/pigame.git

Welcome. Contributions of any kind and any ideas are welcome — let’s make the Pi agent more fun.


Principle

Pi + LLM  = brain (strategy / when to stop)
pigame    = scaffolding only
  tools   = eyes / hands / feet
LayerRole
Pi + LLMDecide what to do; judge when the goal is done
game_observeEyes — see the screen → AgentState
game_move / game_waitHands & feet — act / wait
npm run smoke:* / /game eatTest scaffolding only — hardcoded loops for CI; not the agent path

There is no game_eat_food / game_survive tool. The model loops observe → move itself.


Requirements

ToolNotes
Node.js≥ 20 recommended (--experimental-strip-types)
npmComes with Node
Pi CLIRequired for the agent path (pi on PATH)
LLM in Pie.g. DeepSeek configured in your Pi settings
WSLg / displayOnly for visible Chromium (HEADED=1)

Setup

1. Clone pigame

git clone git@github.com:ifoxhz/pigame.git
cd pigame   # or your local folder name

2. Install pigame deps + Chromium

npm install --prefix pigame
npx --prefix pigame playwright install chromium

Default game (no extra clone): pigame/games/snake.html — a vendored Neon Snake with agent mode (see below).
Anyone who clones this repo gets the patched game automatically; Adapter loads it on /game connect.

3. Optional — upstream Mini Game Studio

Only if you want the original continuous-loop game for comparison:

git clone git@github.com:Digiman/mini-game-studio-ai-gen.git
# HTTPS: https://github.com/Digiman/mini-game-studio-ai-gen.git
SNAKE_HTML=./mini-game-studio-ai-gen/games/snake.html HEADED=1 pi -e ./.pi/extensions/pigame.ts

Live site (reference): https://digiman.github.io/mini-game-studio-ai-gen/

No separate compile step for smokes: Node strip-types runs TypeScript directly.
Root package.json only proxies scripts into pigame/.


Quick test (full run once)

A — One-time setup

git clone git@github.com:ifoxhz/pigame.git
cd pigame   # or your local folder name

npm install --prefix pigame
npx --prefix pigame playwright install chromium

B — Pi + LLM (primary path)

cd /path/to/pigame
HEADED=1 pi -e ./.pi/extensions/pigame.ts

In the Pi TUI (in order):

/game connect
/skill:eat-food

Or paste this prompt instead of the skill:

Use only game_observe, game_move, and optionally game_wait.
Prefer groundTruth grid coords. Eat one food: observe → move → repeat.
When score increases, stop and report before/after score.
Do not reverse 180°.

Watch the Playwright Chromium window (snake freezes between moves).
When done:

/game disconnect

After code changes in a live session: /reload, then /game disconnect/game connect again.

C — Optional: non-LLM smoke (scaffolding)

# Adapter + perception + I/O only (no Pi / no LLM)
npm run smoke:eat
npm run smoke:eat:headed

D — Pack as a Pi npm extension (for others)

npm run pack:pi

Produces:

  • dist/pi-pigame/ — installable directory
  • dist/pigame-0.1.0.tgz — npm tarball

Others install into Pi with:

pi install /path/to/pigame/dist/pi-pigame
# or
pi install /path/to/pigame/dist/pigame-0.1.0.tgz

# after you publish to npm:
# npm publish ./dist/pigame-0.1.0.tgz
# pi install npm:pigame

From a git clone (without packing), they can also:

pi install ./pigame

Then restart Pi or /reload. First time: npx playwright install chromium (from the installed package dir if needed).


Agent-mode Snake (for Pi + LLM latency)

Problem: Upstream Snake ticks on its own. While the LLM is in a long observe → think → move chain, the snake has already moved, so decisions are stale and play feels clumsy.

What we ship: pigame/games/snake.html (see pigame/games/README.md)

BehaviorMeaning
Auto gameLoopPaused after connect (setAgentMode(true))
game_observeWorld stays frozen (no time pass)
game_movesetDir + exactly 1 grid step (MOVE_STEPS to change)

No special startup flag is required for agent mode — connect uses the vendored file by default.

VariableDefaultMeaning
SNAKE_HTMLpigame/games/snake.htmlOverride HTML path
MOVE_STEPS1Grid steps per game_move
HEADEDunset1 → show Chromium

Pi-driven play (primary path)

This is the intended product flow: you open Pi; the LLM uses tools.

Step A — Start Pi with the extension

cd /path/to/pigame
HEADED=1 pi -e ./.pi/extensions/pigame.ts
# or: pi   (auto-loads .pi/extensions/pigame.ts if the project is trusted)

After code changes: /reload.

You should see something like: GameMind ready — LLM tools: game_observe, game_move, game_wait.

Step B — Connect the game (human / slash command)

In Pi:

/game connect

Playwright opens Chromium and loads pigame/games/snake.html (agent-mode), then Start.
World is frozen until each game_move.
Do not open snake.html in your own browser — only the Playwright window is controlled.

Optional: /game observe to sanity-check AgentState.

Step C — Let the LLM drive (prompt)

Example (DeepSeek / any model in Pi):

Use only game_observe, game_move, and optionally game_wait.
Eat one food: observe → choose a direction → move → repeat.
When score increases, stop and report before/after score.
Do not reverse 180° from the previous move.

Or load the skill: /skill:eat-food.

Step D — What the model should do

game_observe  →  read player / food / score
game_move     →  one step toward food
game_observe  →  …
… until the model decides the goal is done …

Slash commands (session scaffolding — not LLM tools)

CommandAction
/gameStatus + help
/game connectStart Playwright Neon Snake
/game observeCompact AgentState (manual check)
/game stateFull AgentState JSON
/game resetRestart round
/game disconnectClose browser
/game mockSwitch to mock adapter
/game eatTest scaffolding — scripted auto-eat
/game surviveTest scaffolding — scripted play until death

LLM tools

ToolRole
game_observeEyes
game_moveHands / feet (up / down / left / right)
game_waitWait

Test scaffolding (npm run smoke:*)

These commands do not use Pi or an LLM. They run fixed policies (eatFoodLoop / surviveUntilEnd) to verify Adapter + Perception + I/O. Use them for CI and debugging — not as the agent design.

# Eat one food (score 0 → 10), headless
npm run smoke:eat

# Same with visible Chromium (WSLg)
npm run smoke:eat:headed

# Long run until death (or stop at a score)
npm run smoke:survive:headed
MAX_SCORE=50 npm run smoke:survive:headed
CommandWhat it checks (scaffolding)
npm run smokeMock adapter / AgentState pipeline
npm run smoke:snakePlaywright open + Start + key + screenshot
npm run smoke:perceptionCV fixture + live perception
npm run smoke:eatScripted steer until score↑
npm run smoke:surviveScripted loop until game over (or MAX_SCORE)
npm run smoke:*:headedSame with HEADED=1

Environment variables (smoke / headed)

VariableDefaultMeaning
HEADEDunset1 / true → show Chromium
SNAKE_HTMLvendored agent snakePath override
MOVE_STEPS1Steps per move (agent mode)
MAX_SCOREnoneSurvive stops when score ≥ value
MAX_STEPS50000Survive step cap
STEP_MS200Visual delay between smoke moves
HOLD_MS50008000Keep window open after headed runs

Neon Snake has no clear — only death; MAX_SCORE is an artificial stop for tests.


Layout

.
├── README.md / README.zh-CN.md
├── package.json                 # script proxies
├── docs/                        # design & schema
├── pigame/                      # main package
│   ├── games/snake.html         # DEFAULT agent-mode Neon Snake (vendored)
│   ├── games/README.md
│   ├── extensions/pigame.ts
│   ├── skills/
│   ├── scripts/                 # smoke:* (test scaffolding)
│   └── src/
├── .pi/extensions/pigame.ts     # Pi entry
└── mini-game-studio-ai-gen/     # optional upstream clone (SNAKE_HTML=…)

Design docs: docs/README.md.


Troubleshooting

IssueFix
Missing pigame/games/snake.htmlPull latest pigame — file is in-repo
Want upstream continuous loopSNAKE_HTML=./mini-game-studio-ai-gen/games/snake.html (clone Digiman first)
Snake runs by itself while LLM thinksYou are not on agent-mode HTML; check default path / SNAKE_HTML
ENOENT package.json at rootUse root scripts or cd pigame
No Chromium windowHEADED=1 or *:headed; check WSLg / echo $DISPLAY
Opened Snake yourself, nothing happensOnly Playwright’s window is controlled
Pi extension not loadedpi -e ./.pi/extensions/pigame.ts then /reload

Acknowledgments

Thanks to Mini Game Studio (Digiman/mini-game-studio-ai-gen) for the original Neon Snake and HTML game collection.
We vendor a patched copy under pigame/games/ for Pi + LLM agent-mode testing (paused auto loop + single-step moves).


License / status

Work in progress (MVP: Pi + LLM drives Snake via observe / move).
Phase notes: docs/implementation.md.

Contributors

ifoxhz

3 commits

Languages

TypeScript

78.4%

HTML

19.6%

JavaScript

2.0%