| 61 | |
| 62 | |
| 63 | class Halite2Replayer(ReplayRenderer): |
| 64 | arena = "Halite2" |
| 65 | sim_glob = "*.hlt" |
| 66 | DRAW_JS = DRAW_JS |
| 67 | |
| 68 | def parse(self, raw: bytes, players=None) -> ReplayData: |
| 69 | import zstandard as zstd |
| 70 | |
| 71 | d = json.loads(zstd.ZstdDecompressor().decompress(raw)) |
| 72 | w, h = d["width"], d["height"] |
| 73 | num_players = d.get("num_players", 2) |
| 74 | engine_names = d.get("player_names", []) |
| 75 | |
| 76 | def name_for(owner: int) -> str: |
| 77 | if players and len(players) > owner: |
| 78 | return players[owner]["name"] |
| 79 | if len(engine_names) > owner: |
| 80 | return engine_names[owner] |
| 81 | return f"Player {owner}" |
| 82 | |
| 83 | static_planets = [ |
| 84 | {"id": p["id"], "x": round(p["x"], 2), "y": round(p["y"], 2), "r": round(p["r"], 2)} |
| 85 | for p in d.get("planets", []) |
| 86 | ] |
| 87 | colors = {o: PALETTE[o % len(PALETTE)] for o in range(num_players)} # owner is 0-based here |
| 88 | names = {o: name_for(o) for o in range(num_players)} |
| 89 | |
| 90 | frames = [] |
| 91 | for i, f in enumerate(d["frames"]): |
| 92 | ships = [ |
| 93 | {"o": int(owner), "x": round(s["x"], 2), "y": round(s["y"], 2), "hp": s.get("health", 0)} |
| 94 | for owner, fleet in f.get("ships", {}).items() |
| 95 | for s in fleet.values() |
| 96 | ] |
| 97 | planet_owner = {pid: pl.get("owner") for pid, pl in f.get("planets", {}).items()} |
| 98 | frames.append({"turn": i, "ships": ships, "planets": planet_owner}) |
| 99 | |
| 100 | # Winner = most ships alive in the final frame (Halite II is elimination/dominance). |
| 101 | last = d["frames"][-1] |
| 102 | counts = {int(o): len(fleet) for o, fleet in last.get("ships", {}).items()} |
| 103 | ranked = sorted(counts.items(), key=lambda kv: kv[1], reverse=True) |
| 104 | if not ranked or (len(ranked) > 1 and ranked[0][1] == ranked[1][1]): |
| 105 | winner, draw = None, True |
| 106 | else: |
| 107 | winner, draw = name_for(ranked[0][0]), False |
| 108 | |
| 109 | return ReplayData( |
| 110 | w=w, |
| 111 | h=h, |
| 112 | frames=frames, |
| 113 | winner=winner, |
| 114 | draw=draw, |
| 115 | extra={"planets": static_planets, "colors": colors, "names": names, "maxhp": 255}, |
| 116 | ) |