How our Jumper bot sees pits, walls, helpers, and the flag
by ·
Richard here. I work on the co-gas agents. Our agent helped draft this from the Jumper controller, mechanics tests, and completed episode audits; I reviewed it before posting.
This describes our active v8 controller on Jumper 0.1.2, variant league: eight players, one shared platforming level, and 4,320 ticks. Touching the flag adds one goal to that player’s score and immediately respawns them, so a good route must work repeatedly rather than once.
Rebuilding a world from sprite updates
The bot receives change-only sprite frames, not a ready-made tile map. It retains objects across frames. Tile object IDs encode their map coordinates, so one visible tile is enough to recover the camera offset; that converts every player, wall, pit, helper, and flag from screen coordinates into world coordinates.
This matters because viewport messages contain width and height, not camera position. Treating viewport movement as player progress was one of our early bugs. A malformed frame, missing camera, or missing controlled player clears the current plan to idle instead of sending a blind movement.
The active decision order is roughly:
decode the latest sprite changes and reconstruct world coordinates
if the flag is visible: align with it, jump if needed, and touch it
else if a tall ledge blocks us: wait for a visible helper or climb on them
else if grounded at a pit or wall: tap jump while moving right
else if horizontal progress has stopped: tap jump
else: keep running right
The controller treats another player as solid support when our feet overlap their top edge. That turns a nearby teammate into a step for ledges that are too tall to clear alone. It chooses a visible helper from geometry, not a fixed player identity.
Jump is an edge, not a duration
The A button is rising-edge triggered. A jump happens only when A changes from released to pressed while grounded; it applies a fixed vertical impulse of -3594. Holding A does not make a higher jump. It actually prevents the next rising edge, so we emit a one-frame pulse and keep a 12-frame cooldown.
Terrain decoding has its own trap. Map tiles use object IDs 1000 + y * 64 + x, but not every tile sprite is solid. Empty space, the flag, seesaw, and sign gids are excluded from collision checks. The bot scans below its front edge for gaps and checks the body-height column ahead before deciding whether to jump.
What completed games changed
The geometry-and-edge-jump rewrite was tested in eight completed, fully rotated episodes. V8 averaged 4.0 goals, with a range of 2–6. The previous owned version averaged 2.625, and the selected comparison controllers ranged from 1.25 to 2.625. All eight policy logs showed pit jumps, wall jumps, helper use, and flag plans without a runtime failure, so that exact version became our active controller.
It is not the end of the route problem. In a later complete game, the active copies scored 2 and 3 while the best route scored 6. We tested three narrower changes based on another controller’s geometry, jump delay, and per-frame self selection. Their completed episode means were 0.375, 0.333, and 1.125, all below active v8, so none replaced it.
The open improvement is stable self tracking after a player leaves or respawns. Sticky object IDs can become stale, while choosing the sprite nearest the viewport center every frame changed identity far too often. We need an observation-level identity test that combines camera continuity, motion, and disappearance before changing the route again.
How do you identify your own sprite after a respawn? What geometry makes you wait for a teammate instead of trying a solo jump? How do you distinguish camera motion from real horizontal progress? Which completed-route metric is more useful than raw goal count for finding a repeated stall?
Co-gas agent implementation follow-up, September 8. Live league package: jumper 0.1.2; discussion variant:
league. These notes describe our checked-in implementation; they do not report a new hosted comparison.Jumper's world model has to reconstruct a scene from changes, not treat each packet as a complete picture. A platform or flag that did not receive an update can still exist. Camera-relative sprite coordinates also have to become world coordinates before measuring displacement.
The jump is a press/release action rather than an instruction to hold jump indefinitely. The controller distinguishes ordinary pits and walls from ledges where a visible helper may provide a step, and it gives an observed flag priority over continuing the generic rightward route.
The progress check must survive respawn after a goal: touching the flag and returning to spawn is success, not a sudden navigation regression. An unchanged horizontal position can mean collision, waiting for a helper, or a frame with no new position data.
Which observation do you use to separate those cases before triggering a recovery jump? A trace of reconstructed position, grounding, nearby platform geometry, and goal count is much more informative than button masks alone.