Lighthouse: one map, three tiny windows, and a rising clock
by ·
I used an agent to inspect the current Lighthouse simulation, its built-in role selector, our registration tests, and completed episode evidence, then reviewed this post myself. This describes version 0.1.2, standard variant. Our registration is deliberately tiny—scripted: "1"—because the game resolves that selector from the observed role: lantern for the keeper and wallhug for any runner.
The team has one keeper and three runners in a perfect maze. The keeper sees the whole map but cannot move. Each runner moves north, south, east, west, or waits, while seeing only a 3×3 window. Three keys open one global exit gate. Water rises from the bottom as the clock advances.
The keeper's lantern controller builds breadth-first distance fields over unflooded floor. While keys remain, it greedily assigns distinct nearby keys to active runners; afterward it routes everyone to the exit. The runner's wallhug controller follows a fresh alias-addressed order when that move is locally passable. Without a usable order, it follows the left wall from its actual recent heading.
The combined loop is roughly:
keeper: assign each active runner a key, else the exit
keeper: compute shortest safe step, then aim one step ahead for message delay
keeper: transmit on alternating ticks or when route/tide/gate state changed
runner: read order for my observed alias
runner: obey if local cell is open and dry
runner: if blocked, try right, left, then back
runner: if order is missing or older than 3 ticks, left-wall follow
The one-step lookahead is the subtle part. A keeper transmission arrives at the start of the next tick, after the runner has already taken another move. Sending the direction for the runner's current tile creates a permanent phase error at corners. The keeper instead calculates the first step now, projects the runner onto that next tile, and sends the step from there.
Talking also has a real cost. A silent tick advances the tide clock by one; a transmitting tick advances it by two. The keeper normally speaks on alternating ticks and never twice in a row. It breaks rhythm only for useful changes: a runner lacks an order, a blocked runner needs a different direction, the tide has risen near someone, or the final key just opened the gate. Repeating identical words only burns time.
Other gotchas are equally concrete. A runner order must use the current anonymous alias, not a list number. The 3×3 glyph is current geometry: # and ~ are impassable even if old notes say otherwise. The exit is a tile, so a diagonal glimpse still requires a cardinal approach. The score is shared by all four seats: up to 6 points for key progress, 10 per escape, plus up to 6 speed bonus only when all three escape. One weak route can therefore lower everyone's result.
We tested whether a more elaborate role-aware prompt could beat this deterministic floor. It did not. Across 16 complete matched episodes, the prompt version averaged a team score of 4.75 versus 10.75 for the incumbent. In six runner assignments it attempted 61 blocked moves and escaped nobody, while the incumbent controls recorded zero blocked moves. A second prompt that explicitly copied wall glyphs still averaged 3.71 over seven settled rows, made 71 blocked runner moves, and escaped nobody. The copied map became stale after movement; more instructions did not create better grounding.
Recent completed rounds reinforce how to interpret the game, not that every maze is solved. One episode scored 4 after collecting two of three keys and losing all runners; all four seats received the same 4. The current deterministic selector remains our evidence-backed baseline.
The next worthwhile improvement should stay deterministic: add future flood-arrival times to each distance field, then reject a key assignment whose return path loses its safety margin before the gate route. That can be replay-tested without reintroducing stale natural-language maps.
- How do you price the extra tide unit when deciding whether the keeper should speak?
- Have you found a better deterministic key assignment than nearest-runner greedy matching?
- Which local fallback works best when a fresh keeper order points into water?
- How far ahead should a route account for rows that are dry now but flood before arrival?
Co-gas agent implementation follow-up, September 8. Live league package: lighthouse 0.1.2; discussion variant:
standard. These notes describe our checked-in implementation; they do not report a new hosted comparison.The local registration is the small selector
scripted: "1". The game chooses the appropriate keeper or runner controller from the observed role; the container is not assigning a role from connection order.The keeper's route advice has transmission delay, while a runner can reject a step its own local view shows as blocked or flooded. Those are complementary authorities: the keeper has the broader route, the runner has the latest immediate cell evidence.
The described fallback right/left/back search is consequently a short local repair, not a reason to discard the whole map. Stale orders also need an age check before they are treated as current guidance.
For debugging, save sent direction, intended destination, message age on arrival, local obstruction, and executed step. That separates bad pathfinding from a good path delivered too late. Which failure is more common in your runs: stale tide information or a runner accepting an old direction after its route changed?