AI Game Dev Search

Difficulty that grows with the player: measuring every room with simulated players

We asked Claude Code to check how hard each room is for new, average and skilled players and reshape the game into waves. See the measured curves before and after, and play the 15 rooms.

Tested with Phaser 3.80.1 · Claude Code 2.1.311

Before you start

  • The 12-room game from part 5 of this series, or any platformer that keeps its rooms as data.
  • Claude Code, started in the game's folder.
  • The skill at the end of this page, in the folder's .claude/skills/platformer-levels/. Then type the prompt below.
What we asked“Players get better as they go. Check how hard each room is for a new, an average and a skilled player, then adjust the rooms so the game gets harder in waves as the player improves. Don't change how the character moves.”

What happened

You
Players get better as they go. Check how hard each room is for a new, an average and a skilled player, then adjust the rooms so the game gets harder in waves as the player improves. Don't change how the character moves.
  • Used the platformer-levels skill
  • Read index.html and the skill's notes on progression, checking, room stories and teaching
Claude
Reading the game is done; now I'm building a headless test harness that plays each room with timing noise.
Claude
Measured jump: 107 px high (3.3 tiles), 208 px across (6.5 tiles), matching the constants. Now writing routes for each room and an auto-tuner to find the most forgiving timing for each.
  • Ran the whole game: the run hit the 10-minute limit
  • Traced the slowdown to Playwright's overhead of about 1 s per call
  • Moved each room's search and measurement into one call inside the page
Claude
Now about 30 s for the whole game. Some results look wrong: "Spike pits" fails 100% even for skilled players, which doesn't fit its easy gaps. Checking the harness before trusting anything.
Claude
Found it. A death schedules a room reload 250 ms later, and in the harness that timer fired inside the next trial and teleported the player. Clearing pending timers between trials.
  • Measured all 12 rooms of the old game
  • Split the game into three areas: jump, double jump, spring
  • Added a pit run, a double jump test and a calm last room
  • Tried several layouts for each spring room
Claude
Still tuning area 3. "Spring in the pit" now passes about 89% (61% for new players) with one spring and a farther, higher ledge.
Claude
Almost everything is on target. The one miss is "Pit run" at 88%, just under the 90% floor for area 1, so I'm easing it slightly.
Claude
Wider rests turned out harder: landing on a 3-tile step breaks the jump rhythm. I'm using three 4-tile pits with 2-tile steps, which passes 96%.
  • Ran every room's route on the finished file
  • Checked that the diff touches only room data
  • Loaded all 15 rooms in the real page: no errors
Claude
The game now gets harder in three waves, one per area. Each area starts easy, gets harder, and ends on its hardest room; the next area starts easy again. Only the room data in index.html changed; no movement constants were touched. All 15 rooms load in the real page with no errors, and every room's scripted route reaches the exit. A test harness in tools/ plays each room 100 times with random timing errors on every key press and release: new player ±0.10 s, average ±0.05 s, skilled ±0.02 s, and a player who improves steadily from new in room 1 to average in the last room. It assumes the player knows the best route and only gets the timing wrong. Before: the old game had two areas, and area 1 taught both the jump and the double jump. Area 2 was flat: every room was 93–100% for the player who'd reached it, and its "test" room was 100%. After: I split the game into three areas of 4, 4 and 7 rooms (jump, double jump, spring) and added three rooms: a pit run, a double-jump test and a calm final room before the flag. I also re-tuned most of the later rooms. The double jump test is 70% for the player who reaches it (43% for new players), the spring test 89% (46%), and skilled players pass 100% everywhere. In the rooms I changed, no jump needs more than 90% of the maximum. What falls short: area 3's test is too easy for an improving player, 89% against a target of 40–70%. Springs give the double jump back and let you bounce in place to wait, so they forgive timing errors. Every fair layout I tried came out at 89–100%, so area 2's test (70%) is the hardest point for an improving player, not the end of the game. "Spring" and "Spring jump" are both treated as introductions. The simulation only tests timing. It can't tell whether a room is confusing or fun. Please watch someone play area 1 and the two test rooms.

How hard a room feels depends on how good the player is by the time they get there. Room 12 is played by someone with eleven rooms of practice, so it can ask for more than room 1 and feel just as fair. The usual shape is a sawtooth: each area starts easy with its new idea, gets harder up to a test room, and the next area drops back down.

We asked Claude Code to measure part 5’s 12 rooms for new, average and skilled players and reshape them that way. It rebuilt the game as 15 rooms in three areas. Measured by us, the old game was flat at 99–100% for the player who has reached each room. The new one dips once in each area.

Real measurements from our own runs: every room of both versions played 200 times per skill level in the real game, with replays of the recorded attempts. The thick line is a player who starts in room 1 with ±0.10 s of timing error and improves steadily to ±0.05 s by the last room. Beat labels come from Claude's plan of the game. Switch between before and after, or drag the skill slider.

The waves are shallow in the first two areas. Area 1 bottoms out at 97% in its new pit run and area 2 at 91% in its double jump test. Area 3 goes lowest: 73% in Get it back, one room before its test (79%), then 100% in the last room.

Claude's 15 rooms. There is no way to skip ahead: our scripted run reaches area 3 after 21 seconds and finishes all 15 rooms in 41.5 seconds with no deaths. Spikes restart the room you're in. We only added the start screen and loaded Phaser from this site.

#RoomBeatBeforeAfter
1Runintroduce100%100%
2Jumpintroduce100%100%
3Spike pitsdevelop100%100%
4Pit run (new)test–97%
5Double jumpintroduce100%100%
6Long jumpdevelop100%98%
7Pillar (was Goal)twist99%95%
8Double jump test (new)test–91%
9Springintroduce100%100%
10Spring jumpintroduce100%100%
11Bounce and double jumpdevelop100%81%
12Get it backdevelop100%73%
13Spring in the pittwist100%97%
14Spring testtest100%79%
15Home (new)rest–100%

Before and After are pass rates for the player who has reached the room. Beats are from Claude’s plan; it relabelled four old rooms, for example Goal (a test) became Pillar (a twist) now that a new room ends area 2. Skilled players (±0.02 s) pass every room at least 98% of the time. New players drop to 39% in Get it back and 45% in the spring test.

What Claude changed

Area 1 used to teach the jump and the double jump. Claude split it in two, so the game now has three areas of 4, 4 and 7 rooms: jump, double jump, spring. Each area ends on a test room. Two of them are new: a run over three spike pits with only two-tile steps between them, and a room where you hop onto a two-tile pillar without running off it, then jump and double jump across a wide pit. A third new room, Home, comes after the spring test: one bounce on safe ground and a walk to the flag.

It changed six old rooms. Long jump’s ledge is a tile higher and its pit a tile wider. The old Goal room became Pillar, with a second pit three tiles wider. Bounce and double jump has a ledge three tiles higher. Get it back has one spring instead of two and a ledge two tiles higher, and now comes before Spring in the pit, which also lost a spring and got a farther, higher ledge. The spring test was rebuilt as a long double jump onto a one-tile spring pillar, a bounce across to a second one, and a bounce and double jump up to the door. We compared the files: only the room data changed (grids, names and areas), and every movement setting is the same.

How we measured, and why Claude’s numbers differ

We used our own harness, not Claude’s. It runs the game in headless Chrome at a fixed 60 frames a second and plays each room’s route 200 times per skill level, with a random timing error on every press and release. Unchanged rooms kept exactly the routes we used before. For the nine rooms that are new or changed (Pit run, Long jump, Pillar, Double jump test, Bounce and double jump, Get it back, Spring in the pit, Spring test, Home) we wrote new routes and searched for the most forgiving timing, the way a player settles on the easiest way through.

Claude’s report gives different numbers: 70% at the double jump test, where we measured 91%, and 89% at the spring test, where we measured 79%. It concludes that area 3’s test is too easy. Part of the difference is how the two harnesses model a new player. In Claude’s harness, ±0.10 s is an even spread that never goes past 0.10 s. In ours, 0.10 s is the typical error of a bell curve, so about a third of our presses miss by more than that. The routes differ too. Both are simulations, and the two harnesses agree on the old game: flat, with nothing below 93%.

The session took 1 hour 16 minutes and cost $4.52. The first 45 minutes went into Claude’s harness: making it fast enough, and fixing a bug it found itself, where the room reload after a death fired in the middle of the next trial. The rooms took the other half hour.

A simulated player only measures timing. It can’t tell whether a room is confusing, whether anyone notices that the spring gives the double jump back, or whether the game is fun. Claude’s report says the same and asks for a real person to play area 1 and the two test rooms. We haven’t done that yet.

Update: the measuring now comes with the skill

Since Claude spent most of this session building its own harness, we put ours into the skill. Claude now adds a small hook to the game and writes a route for each room, and the skill’s script does the rest. It runs the simulated players, prints the table above and writes a chart you can open in a browser. Every run measures the same way, with a bell curve of timing errors, so numbers from different sessions can be compared. The skill now models the player improving with each room played (quickly at first, then levelling out near average) rather than by how far through the game a room is, so numbers from the current skill differ slightly from the chart above.

We ran this same prompt again in a clean session with the new skill, on the game before the reshape. Claude used the bundled script instead of writing its own, had its first full table after about two and a half minutes, and finished in 27 minutes for $2.89 (here: 1 hour 16 minutes, $4.52). Its reshaped spring area landed inside every target band by its own table, and our re-run with a different random seed agreed within a few points.

You need Node and Playwright for the script. If they are missing, the script prints the install commands.

Get the skill. The level rules work for any engine. The measuring script runs browser games, such as Phaser or plain canvas. You can also install all seven skills as a Claude Code plugin or replay this part from its starting files.

Recorded with a clean Claude Code: no personal skills, plugins or MCP servers. The session had platformer-levels and our earlier platformer-feel skill installed.

The skill that made it work

It makes Claude plan the game in areas, measure every room with simulated new, average and skilled players, and shape the difficulty so it rises in waves as the player improves.

platformer-levels
  1. Keep levels as data: each room in a small grid or list (tiles, hazards, pickups, start, exit), separate from the game code.
  2. Write each room's one-line story first: one sentence about the single thing the room asks of the player. Build only what serves it.
  3. Teach in order, without text: each new move or object is shown safely, then used, combined and tested.
  4. Check every room with the jump numbers: work out from the game's constants how far and how high the player can jump, check every required jump and every tempting wrong jump, then play each room with a scripted route.
  5. Plan the whole game, not just a room: bring in one new element per area through introduce, develop, twist and test, and measure every room with simulated players of different skill so the difficulty rises in waves.
  6. Report like a level designer: for each room, its story, what it teaches, its hardest jump as a share of the maximum, and whether the scripted route finished.

Save it as .claude/skills/platformer-levels/SKILL.md in your project.

Was this useful?

Part 6 of Make a complete platformer with AI

Next in Make a complete platformer with AIA full chapter with Claude Code: 34 rooms, two new mechanics and how they combine
Open →