ProjectsSuper Hexagon RL
The agent steering through the walls of a Super Hexagon level

Reinforcement learning

Super Hexagon RL

An agent that plays every level of the real game live

GitHubWatch it play
120/120real runs survived 10 minutes, paused per decision
1.86Msimulator steps a second
15 hoursof play without a death, in 30 runs of 30 minutes

Super Hexagon RL is a self learning agent for Terry Cavanagh's Super Hexagon, the real game running on Linux. With the real game paused after each decision until the agent answers, it survives the full 10 minutes in all 120 of its runs. It also plays all six levels live, on the game's own clock with key presses sent to the game's window, in a 7 minute video that isn't edited. It isn't affiliated with Terry Cavanagh and doesn't include the game or its code.

How it works

The game runs in fixed 1/60 second steps, so training doesn't need to draw anything. A small library loaded in front of the game takes over its clock, its random numbers, and the Steam calls, then pauses the game after every decision until the agent answers. The game binary is never patched, and the launcher checks its hash before it starts.

Real game steps are still slow, so the agent trains against a simulator instead. I decompiled the game's logic in Ghidra and turned it into C, which a script compares against the real game at every decision. With 256 simulators on 8 threads it runs 1.86 million agent steps a second. The agent learns by playing, using a standard method called PPO that nudges its choices towards what scored well.

Six Super Hexagon windows open side by side, each in a different level and colors, all being played at once
Six games played live at once, one window per level.

Playing live is a different problem from training, since the game runs on its own clock and the agent has to keep up. It reads the game's memory, sends keys straight to the game's window, and checks that its keys land on the very next tick. 31,774 of 31,777 key changes did.

How much survival does smoother play cost? The model that taps about six times a second never dies in 120 runs of the real game, with the game paused at each decision. The one I'd call best holds keys the way a person would, at 1.19 presses a second with a 340 ms average hold. It reaches the cap in 116 of 120 runs, so smoother play costs four runs.

Highlights

  1. The game stays untouchedA preloaded library takes over the game's clock and input, so training runs the real game one step at a time without patching its binary.
  2. A simulator that matched the gameThe game's own logic, compiled from its decompiled code, matched the real game on every check over about 69 minutes of play. That includes the 247 KB game object, apart from the colors, music and sound data, clock readings, and the pointers the simulator replaces.
  3. A bug found by replayLive runs were dying early because the game dropped held keys when a window changed focus. Replaying live games in the simulator found it, and the fix took a stress test from 0 of 20 runs surviving to 19 of 20.
A chart of seven models, with the share of runs reaching 600 seconds against key presses a second, where smoother play gives up a few runs
Seven models on 360 seeded simulator runs each. The model that holds keys like a person, at 1.19 presses a second, reaches the cap in 349 of 360 runs.

Built with

  • Python
  • PyTorch
  • C
  • Ghidra
  • SDL2
  • X11

Details

Started
Status
Done
License
MIT
Source
Public