Download scripts/build_superbeam_page_data.py from StarAtNyte1/beam-boot: direct link, hf CLI and curl.
- Browser
- Download file 11.4 kB
-
https://huggingface.co/StarAtNyte1/beam-boot/resolve/main/scripts/build_superbeam_page_data.py
- Command line
-
hf download hf://StarAtNyte1/beam-boot/scripts/build_superbeam_page_data.py
-
curl -L -o build_superbeam_page_data.py https://huggingface.co/StarAtNyte1/beam-boot/resolve/main/scripts/build_superbeam_page_data.py
11.4 kB
| #!/usr/bin/env python3 | |
| """Build static-space/superbeam-data.js (window.SB) for index.html. Re-runnable. | |
| Sources (priority order for the player replay): | |
| 1. results/beam_live_weights_run.json: Beam played LIVE against the in-weights computer. Its | |
| best attempt's key_schedule is replayed on the current emulator; if every frame equals | |
| weights.frame_rows the run is for the current ROM -> live.status = "live". A partial prefix | |
| -> "partial"; no match (file missing / old ROM) -> "pending". | |
| 2. otherwise the best run in results/levels/beam_level<seed>_run.json (held-out test level, | |
| emulator backend): shown as a replay, in-weights frames = 0. | |
| Leaderboard: every results/levels/beam_level*_run.json; baselines: results/gym_baselines_levels.json. | |
| """ | |
| import glob | |
| import json | |
| import re | |
| import sys | |
| from pathlib import Path | |
| ROOT = Path(__file__).resolve().parent.parent | |
| sys.path.insert(0, str(ROOT)) | |
| from beamboot.superbeam_gym import (SuperBeamEnv, FLAGCOL, START_X, WIN_X, # noqa: E402 | |
| frames_from_events) | |
| OUT = ROOT / "static-space" / "superbeam-data.js" | |
| def load(path): | |
| p = ROOT / path | |
| return json.load(open(p)) if p.exists() else None | |
| def replay(events, n, level="classic"): | |
| """Emulator replay of a key schedule. Returns per-frame display rows, state | |
| [keys mask (1 left, 2 jump, 4 right), VA x, VB y, VD camera], walkers [[alive, col, off], x2], | |
| coins, plus the initial level bytes, level changes [[frame, col, byte]] and walkers.""" | |
| env = SuperBeamEnv(backend="emulator", level=level) | |
| env.reset() | |
| m = env.backend.m | |
| et = env.sym["ETAB"] | |
| lv0 = list(env.level_cols) # TMAP in RAM is only filled once the ROM has started | |
| cur = list(lv0) | |
| rows, state, walk, coins, changes = [], [], [], [], [] | |
| for f, keys in enumerate(frames_from_events(events, n)): | |
| env.backend.advance(keys) | |
| rows.append(m.display_rows()) | |
| mask = (1 if 4 in keys else 0) | (2 if 5 in keys else 0) | (4 if 6 in keys else 0) | |
| state.append([mask, m.v[0xA], m.v[0xB], m.v[0xD]]) | |
| walk.append([[m.mem[et + 4 * e + i] for i in range(3)] for e in range(2)]) | |
| coins.append(env.coins()) | |
| lv = env.live_level() | |
| for c in range(len(lv)): | |
| if lv[c] != cur[c]: | |
| changes.append([f, c, lv[c]]) | |
| cur = lv | |
| return {"rows": rows, "state": state, "walkers": walk, "coins": coins, "level0": lv0, | |
| "changes": changes, "level_cols": list(env.level_cols), "level_seed": env.level_seed, | |
| "start_walkers": [list(w) for w in env.walkers]} | |
| def play_data(level): | |
| """What the page's in-browser player needs: the exact ROM of the shown level (the same bytes the | |
| in-weights model runs), the RAM addresses it reads and the tile-code -> level-byte table.""" | |
| import base64 | |
| from beamboot import superbeam_levels as L | |
| if level == "classic": | |
| rom = (ROOT / "roms" / "superbeam.ch8").read_bytes() | |
| else: | |
| env = SuperBeamEnv(backend="emulator", level=level) | |
| env.reset() | |
| rom = bytes(env.backend.rom) | |
| _, sym = L._symbols() | |
| return {"rom_b64": base64.b64encode(rom).decode(), "ipf": 300, | |
| "sym": {k: sym[k] for k in ("TMAP", "WIN", "DEATHS", "COINS", "ETAB")}, | |
| "level_len": L.LEVEL_LEN, "code_of_tile": {str(k): v for k, v in L.CODE_OF_TILE.items()}, | |
| "keys": {"left": 4, "jump": 5, "right": 6}} | |
| def excerpt(text, limit=200): | |
| text = " ".join((text or "").split()) | |
| if not text: | |
| return "" | |
| sents = [s.strip() for s in re.split(r"(?<=[.!?])\s+", text) if s.strip()] | |
| pick = sents[-1] if sents else text | |
| i = len(sents) - 1 | |
| while i > 0 and len(sents) - i < 3 and len(sents[i - 1]) + 1 + len(pick) <= limit: | |
| i -= 1 | |
| pick = sents[i] + " " + pick | |
| if len(pick) > limit: | |
| pick = pick[: limit - 1].rstrip() + "…" | |
| return pick | |
| def reasoning(req): | |
| try: | |
| msg = req["response"]["choices"][0]["message"] | |
| except (KeyError, IndexError, TypeError): | |
| return "" | |
| return msg.get("reasoning_content") or msg.get("reasoning") or msg.get("content") or "" | |
| def attempts_summary(run): | |
| return [{"attempt": a["attempt"], "status": a["status"], "won": a["won"], | |
| "progress": round(a["progress"], 4), "frames": a["frames"], | |
| "requests": a["requests_used"]} for a in run["attempts"]] | |
| def best_attempt(run): | |
| return run["attempts"][run["best_attempt"] - 1] | |
| def actions_of(run, att): | |
| out = [] | |
| for r in att["requests"]: | |
| end = r["frames"] | |
| out.append({"request": r["request"], "action": r["action"], | |
| "frame_start": max(0, end - run["frame_skip"]), "frame_end": end - 1, | |
| "progress": round(r["progress"], 4), "excerpt": excerpt(reasoning(r))}) | |
| return out | |
| def main(): | |
| notes = [] | |
| live_run = load("results/beam_live_weights_run.json") | |
| live = {"status": "pending", "reason": "no live run file", "frames_equal": 0, "attempts": []} | |
| player = None # (run, attempt, level, weights dict or None) | |
| if live_run: | |
| att = best_attempt(live_run) | |
| lvl = live_run.get("level", "classic") | |
| w = att.get("weights") or {} | |
| n = att["frames"] | |
| rep = replay(att["key_schedule"], n, lvl) | |
| fr = w.get("frame_rows", []) | |
| k = 0 | |
| while k < len(fr) and k < n and fr[k] == rep["rows"][k]: | |
| k += 1 | |
| status = "live" if (k == n and len(fr) == n) else ("partial" if k > 0 else "pending") | |
| live = {"status": status, "frames_equal": k, "frames_model": len(fr), "attempts": attempts_summary(live_run), | |
| "reason": "" if status == "live" else | |
| ("model frames equal the emulator for the first %d of %d frames only" % (k, n) if status == "partial" else | |
| "live run's model frames do not reproduce on the current ROM (run is for an older game version)")} | |
| if status != "pending": | |
| player = (live_run, att, lvl, w) | |
| player_rep = rep | |
| else: | |
| notes.append("live run file is for an older ROM; not rendered") | |
| if player is None: | |
| cands = [] | |
| for p in sorted(glob.glob(str(ROOT / "results/levels/beam_level*_run.json"))): | |
| r = json.load(open(p)) | |
| if r.get("attempts"): | |
| cands.append(r) | |
| wins = [r for r in cands if best_attempt(r)["won"]] | |
| pick = wins[0] if wins else (cands[0] if cands else None) | |
| if pick is None: | |
| sys.exit("no usable player run (live run stale and no results/levels runs)") | |
| att = best_attempt(pick) | |
| player = (pick, att, pick["level"], None) | |
| player_rep = replay(att["key_schedule"], att["frames"], pick["level"]) | |
| run, att, lvl, w = player | |
| n = att["frames"] | |
| rep = player_rep | |
| # in-weights info | |
| inw = {"n": 0, "verified": False} | |
| model = {"cls": "BeamForCausalLM", "layers": 7, "hidden": 640, "dtype": "float32", | |
| "tok_per_s": None, "frames_all_draft_accepted": None, "compute_seconds": None} | |
| if w and live["status"] in ("live", "partial"): | |
| pf = w.get("per_frame", []) | |
| toks, secs = sum(p["tokens"] for p in pf), sum(p["s"] for p in pf) | |
| inw = {"n": live["frames_equal"], "verified": live["status"] == "live"} | |
| model.update(tok_per_s=round(toks / secs, 1) if secs else None, n_tokens=toks, | |
| frames_all_draft_accepted=w.get("frames_all_draft_accepted"), | |
| compute_seconds=w.get("compute_seconds"), | |
| s_per_frame=round(secs / len(pf), 2) if pf else None) | |
| # leaderboard: Beam on held-out test levels | |
| board = [] | |
| for p in sorted(glob.glob(str(ROOT / "results/levels/beam_level*_run.json"))): | |
| r = json.load(open(p)) | |
| if not r.get("attempts"): | |
| continue | |
| a = best_attempt(r) | |
| rr = replay(a["key_schedule"], a["frames"], r["level"]) | |
| board.append({"seed": r["level"], "won": bool(a["won"]), "progress": round(a["progress"], 4), | |
| "coins": rr["coins"][-1], "coins_total": sum(1 for b in rr["level_cols"] if b & 0x0C), | |
| "requests": r["total_requests"], "attempts": len(r["attempts"]), | |
| "frames": a["frames"], "model": r["model"]}) | |
| base = load("results/gym_baselines_levels.json") | |
| baselines = [] | |
| if base: | |
| baselines = [{"agent": b["agent"], "levels": b["episodes"], "levels_won": b["levels_won"], | |
| "mean_progress": round(b["mean_progress"], 3), "mean_coins": round(b["mean_coins"], 2)} | |
| for b in base["results"]] | |
| bw = load("results/beam_weights.json") # network whose weights Beam wrote (scripts/beam_weights.py) | |
| if bw and bw.get("test"): | |
| t = bw["test"] | |
| baselines.insert(0, {"agent": "beam_weights", "levels": t["levels"], "levels_won": t["won"], | |
| "mean_progress": t["mean_progress"], | |
| "mean_coins": round(sum(r["coins"] for r in t["detail"]) / t["levels"], 2), | |
| "rounds": bw.get("best_round")}) | |
| beam_row = None | |
| if board: | |
| beam_row = {"model": board[0]["model"], "levels": len(board), | |
| "levels_won": sum(b["won"] for b in board), | |
| "mean_progress": round(sum(b["progress"] for b in board) / len(board), 3), | |
| "mean_coins": round(sum(b["coins"] for b in board) / len(board), 2)} | |
| data = {"n_frames": n, "frames": rep["rows"], "state": rep["state"], "walkers": rep["walkers"], | |
| "coins": rep["coins"], "level": rep["level0"], "level_changes": rep["changes"], | |
| "level_seed": rep["level_seed"], "level_kind": "classic" if lvl == "classic" else "test seed", | |
| "start_walkers": rep["start_walkers"], | |
| "flag_col": FLAGCOL, "start_x": START_X, "win_x": WIN_X, | |
| "actions": actions_of(run, att), "inweights": inw, "live": live, "model": model, | |
| "player": {"model": run["model"], "backend": att.get("backend"), "won": att["won"], | |
| "attempt": att["attempt"], "attempts": attempts_summary(run), | |
| "requests": run["total_requests"], "frames": n, | |
| "progress": round(att["progress"], 4), "coins": rep["coins"][-1], | |
| "coins_total": sum(1 for b in rep["level_cols"] if b & 0x0C), | |
| "frame_skip": run["frame_skip"], "ipf": run["ipf"], | |
| "source": "live in-weights run" if live["status"] in ("live", "partial") | |
| else "held-out level run (emulator backend)"}, | |
| "leaderboard": {"beam": beam_row, "beam_levels": board, "baselines": baselines, | |
| "baseline_levels": (base or {}).get("levels"), | |
| "difficulty": (base or {}).get("difficulty")}, | |
| "notes": notes, | |
| "play": play_data(lvl)} | |
| OUT.write_text("window.SB = " + json.dumps(data, separators=(",", ":")) + ";\n") | |
| print("wrote %s: %d frames, %d actions, live=%s (equal %d), player=%s, board=%d levels" | |
| % (OUT, n, len(data["actions"]), live["status"], live["frames_equal"], data["player"]["source"], len(board))) | |
| if __name__ == "__main__": | |
| main() | |