fix: resolve duel roots and recover legacy snake data

- Resolve selected moves and enemy replies on the same simulated turn.
- Add an Apex candidate hook and bump the Prism snake to version 1.1.0.
- Rebuild benchmark states from normalized turn data when snapshots are empty.
- Synthesize missing game snake identities during legacy database migration.
- Add regression coverage for duel timing and partial legacy schemas.
This commit is contained in:
2026-08-01 19:11:32 +02:00
parent c646392b84
commit 6643eb35af
8 changed files with 329 additions and 39 deletions
+23 -15
View File
@@ -143,6 +143,12 @@ def copy_game_snakes(source:sqlite3.Connection, destination:sqlite3.Connection,
has_game_snakes = source.execute("""
SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'game_snakes'
""").fetchone() is not None
sql = """
INSERT OR IGNORE INTO game_snakes (
game_id, snake_id, snake_name, is_you, customizations_json
) VALUES (?, ?, ?, ?, ?)
"""
count = 0
if has_game_snakes:
columns = object_columns(source, "game_snakes")
customizations = (
@@ -153,24 +159,26 @@ def copy_game_snakes(source:sqlite3.Connection, destination:sqlite3.Connection,
SELECT game_id, snake_id, snake_name, is_you, {customizations}
FROM game_snakes ORDER BY game_id, snake_id
""")
else:
cursor = source.execute("""
SELECT game_id, snake_id, MAX(snake_name), MAX(is_you),
'{}' AS customizations_json
FROM snake_turns
GROUP BY game_id, snake_id
ORDER BY game_id, snake_id
""")
sql = """
INSERT INTO game_snakes (
game_id, snake_id, snake_name, is_you, customizations_json
) VALUES (?, ?, ?, ?, ?)
"""
count = 0
while rows := cursor.fetchmany(batch_size):
retained_rows = [tuple(row) for row in rows if row[0] in retained_ids]
before = destination.total_changes
destination.executemany(sql, retained_rows)
count += destination.total_changes - before
# Older databases can contain an empty or only partially populated
# game_snakes table. Always synthesize missing identities from snake_turns.
cursor = source.execute("""
SELECT game_id, snake_id, MAX(snake_name), MAX(is_you),
'{}' AS customizations_json
FROM snake_turns
GROUP BY game_id, snake_id
ORDER BY game_id, snake_id
""")
while rows := cursor.fetchmany(batch_size):
retained_rows = [tuple(row) for row in rows if row[0] in retained_ids]
before = destination.total_changes
destination.executemany(sql, retained_rows)
count += len(retained_rows)
count += destination.total_changes - before
return count
def decode_json(value:str|None, fallback):