field-orders-ai-lab / scripts /lib /commander_demonstrations.py
orcnd's picture
Add reproducible game AI SDK review release v0.3.0
d533fd9 verified
Raw History Blame Contribute Delete
1.77 kB
"""Validate exported human macro demonstrations without inventing labels."""
import json
import math
from pathlib import Path
def load_demonstrations(filename):
payload = json.loads(Path(filename).read_text(encoding='utf-8-sig'))
if isinstance(payload, dict):
records = payload.get('commanderDemonstrations', payload.get('stats', {}).get('commanderDemonstrations', []))
else:
records = payload
if not isinstance(records, list):
raise ValueError('Expected commanderDemonstrations array')
rows, labels = [], []
for record in records:
if not record.get('trainable'):
continue
row, action = record.get('observation'), record.get('action', {})
if not isinstance(row, list) or len(row) != 116 or not all(isinstance(v, (int, float)) and math.isfinite(v) and -1 <= v <= 1 for v in row):
raise ValueError('Invalid 116-feature demonstration observation')
categories = [action.get(k) for k in ['command', 'formation', 'strategy', 'group', 'task']]
if not all(type(v) is int and 0 <= v < width for v, width in zip(categories, [11, 4, 7, 9, 5])):
raise ValueError('Invalid macro demonstration category')
if action.get('ttl') not in [2.5, 5, 10] or not all(isinstance(action.get(k), (int, float)) and math.isfinite(action[k]) for k in ['x', 'y']):
raise ValueError('Invalid macro demonstration position/TTL')
xy = [max(-.98, min(.98, (action['x'] - 30) / 520 - 1)), max(-.98, min(.98, (action['y'] - 47) / 285.5 - 1))]
rows.append(row)
labels.append(categories + [[2.5, 5, 10].index(action['ttl'])] + xy)
return rows, labels, {'records': len(records), 'accepted': len(rows), 'skipped': len(records) - len(rows)}