pokemon-player
Installation
SKILL.md
Pokémon Player Skill
Play Pokémon games autonomously via headless emulation. Uses the pokemon-agent
package to run a game server, then interacts via HTTP API.
Setup (First Time Only)
# Install the package + emulator + dashboard
pip install pokemon-agent[dashboard] pyboy
# User must provide their own ROM file
# The agent CANNOT download or distribute ROMs
Ask the user for the ROM file path if not provided. Common locations:
~/roms/pokemon_red.gb~/pokemon_red.gb
Starting a Game
# Start the game server as a background process
pokemon-agent serve --rom <ROM_PATH> --port 8765 &
# Verify it's running
curl -s http://localhost:8765/health
Tell the user: "Dashboard available at http://localhost:8765/dashboard"
Gameplay Loop
Each turn, follow this cycle:
1. Observe — Read Game State
curl -s http://localhost:8765/state | python3 -m json.tool
Parse the JSON to understand:
- Where am I? (map name, position)
- What's happening? (overworld, battle, dialog, menu)
- Party status? (HP, levels, any fainted?)
- Bag contents? (potions, pokeballs?)
- Badges earned?
2. Decide — What To Do
Priority order:
- If in dialog → press A to advance (
a_until_dialog_end) - If in battle → choose best move (see Battle Strategy)
- If party needs healing → navigate to Pokémon Center
- If ready for next gym → navigate toward it
- Otherwise → explore, train, catch Pokémon
Use Hermes memory to track:
- Current objective:
PKM:OBJECTIVE: Defeat Brock in Pewter City - Map knowledge:
PKM:MAP: Viridian Forest has bug catchers, exit north to Pewter - Strategy notes:
PKM:STRATEGY: Brock's Onix is weak to Water — use Bubble
3. Act — Send Commands
# Single action
curl -s -X POST http://localhost:8765/action \
-H "Content-Type: application/json" \
-d '{"actions": ["press_a"]}'
# Movement sequence
curl -s -X POST http://localhost:8765/action \
-H "Content-Type: application/json" \
-d '{"actions": ["walk_up", "walk_up", "walk_right", "press_a"]}'
# Advance dialog
curl -s -X POST http://localhost:8765/action \
-H "Content-Type: application/json" \
-d '{"actions": ["a_until_dialog_end"]}'
4. Verify — Check Result
After each action, the response includes state_after. Check:
- Did I move? (position changed)
- Did the dialog advance? (new text or cleared)
- Did the battle state change? (HP, turn)
If stuck (same state after 3+ actions), try:
- Press B to cancel menus
- Try different direction
- Load last save
Action Reference
| Action | What It Does |
|---|---|
press_a |
Press A (confirm, talk, interact) |
press_b |
Press B (cancel, run from battle) |
press_start |
Open menu |
press_select |
Select button |
walk_up/down/left/right |
Walk one tile |
wait_60 |
Wait ~1 second |
a_until_dialog_end |
Mash A until dialog finishes |
hold_a_30 |
Hold A for 30 frames |
Battle Strategy (Gen 1)
Type Effectiveness — Key Matchups
- Water beats: Fire, Ground, Rock
- Fire beats: Grass, Bug, Ice
- Grass beats: Water, Ground, Rock
- Electric beats: Water, Flying
- Ground beats: Fire, Electric, Rock, Poison
- Ice beats: Grass, Ground, Flying, Dragon
- Fighting beats: Normal, Rock, Ice
- Psychic beats: Fighting, Poison (VERY strong in Gen 1)
Decision Tree
- Can I one-shot? → Use strongest super-effective move
- Am I at type disadvantage? → Switch if possible, or use neutral STAB
- Is enemy HP high? → Consider stat moves first (Growl, Tail Whip)
- Should I catch? → Weaken to red HP, use Poké Ball
- Wild battle, don't need it? → Run (press_b or use "Run" option)
Gen 1 Quirks
- Special stat is BOTH Special Attack and Special Defense
- Psychic type has NO effective counters (Ghost moves bugged, Bug moves weak)
- Critical hit rate based on Speed stat
- Wrap/Bind/Fire Spin prevent the opponent from acting
Saving
# Save before important battles
curl -s -X POST http://localhost:8765/save \
-d '{"name": "before_brock"}'
# Load if things go wrong
curl -s -X POST http://localhost:8765/load \
-d '{"name": "before_brock"}'
# List available saves
curl -s http://localhost:8765/saves
Save before: Gym battles, catching rare Pokémon, entering dungeons.
Progression Milestones
Track these in memory as you complete them:
- ☐ Get starter Pokémon from Oak
- ☐ Deliver Oak's Parcel, get Pokédex
- ☐ Reach Pewter City through Viridian Forest
- ☐ Boulder Badge (Brock — Rock type, use Water/Grass)
- ☐ Reach Cerulean City via Mt. Moon
- ☐ Cascade Badge (Misty — Water type, use Grass/Electric)
- ☐ Board SS Anne, get HM01 Cut
- ☐ Thunder Badge (Lt. Surge — Electric, use Ground)
- ☐ Clear Rock Tunnel to Lavender Town
- ☐ Rainbow Badge (Erika — Grass, use Fire/Ice/Flying)
- ☐ Clear Team Rocket Hideout, get Silph Scope
- ☐ Soul Badge (Koga — Poison, use Ground/Psychic)
- ☐ Marsh Badge (Sabrina — Psychic, use Bug... but good luck in Gen 1)
- ☐ Volcano Badge (Blaine — Fire, use Water/Ground)
- ☐ Earth Badge (Giovanni — Ground, use Water/Grass/Ice)
- ☐ Victory Road
- ☐ Elite Four + Champion
Memory Conventions
Use these prefixes in Hermes memory for Pokémon-related entries:
PKM:OBJECTIVE:— Current goalPKM:MAP:— Map/navigation knowledgePKM:STRATEGY:— Battle/team strategy notesPKM:PROGRESS:— Milestone completionPKM:STUCK:— Notes about stuck situations and how they were resolved
Taking Screenshots
# Save screenshot for vision analysis
curl -s http://localhost:8765/screenshot -o /tmp/pokemon_screen.png
Use vision_analyze on the screenshot when:
- You're unsure what's on screen (menus, NPCs)
- You need to read in-game text that RAM doesn't capture well
- You want to verify your position visually
Stopping
When done playing:
- Save the game:
curl -X POST localhost:8765/save -d '{"name": "session_end"}' - Kill the background server process
- Save progress notes to memory