infra(player-api): 🧱 Enhance player API server startup script and debugging tools with improved error handling and logging

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-06-03 04:06:43 -07:00
parent f2494b6f6f
commit b651937b9b
2 changed files with 4 additions and 82 deletions

View file

@ -49,7 +49,8 @@ source "${SCRIPT_DIR}/run/heavy-prefix.sh"
# works directly. Env-var passthrough is automatic for the native path.
export CP_SEED CP_PLAYERS CP_PLAYER_SLOT CP_MAP_SIZE CP_MAP_TYPE \
CP_OMNISCIENT CP_TIMEOUT_SEC CP_LOG_FILE CP_VICTORY_MODE \
CP_PLAYER_CONTROLLERS CP_PLAYER_SLOTS
CP_PLAYER_CONTROLLERS CP_PLAYER_SLOTS \
MC_DATA_ROOT MC_LEARNED_POLICY_PATH
case "$(uname -s)" in
Darwin)
@ -78,6 +79,8 @@ case "$(uname -s)" in
--env=CP_VICTORY_MODE="${CP_VICTORY_MODE:-}" \
--env=CP_PLAYER_CONTROLLERS="${CP_PLAYER_CONTROLLERS:-}" \
--env=CP_PLAYER_SLOTS="${CP_PLAYER_SLOTS:-}" \
--env=MC_DATA_ROOT="${MC_DATA_ROOT:-}" \
--env=MC_LEARNED_POLICY_PATH="${MC_LEARNED_POLICY_PATH:-}" \
org.godotengine.Godot \
--path "$PROJECT_DIR/src/game" \
--headless \

View file

@ -1,81 +0,0 @@
import sys, json
sys.path.insert(0, '.')
from tooling.rl_self_play.harness_client import HarnessClient, HarnessConfig
from tooling.rl_self_play.encoders import encode_legal_actions
from tooling.rl_self_play.record_expert import _DropStats, _resolve
def adv(c, slot):
for a in c.suggest(slot=slot):
v = c.view(slot=slot)
_, i2a = encode_legal_actions(v)
idx = _resolve(a, v, i2a, _DropStats())
if idx is None:
continue
r = i2a[idx]
try:
if r.get('type') == 'end_turn':
c.end_turn(slot=slot)
else:
c.act(r, slot=slot)
except Exception:
break
try:
c.end_turn(slot=slot)
except Exception:
pass
c.drain_notifications()
def ents(v, slot, key):
return [x for x in v.get(key, []) if int(x.get('owner', -1)) == slot]
def pos(x):
p = x.get('position', [-99, -99])
return (float(p[0]), float(p[1]))
def wrapdist(a, b, w=40, h=24):
dx = abs(a[0] - b[0]); dx = min(dx, w - dx)
dy = abs(a[1] - b[1]); dy = min(dy, h - dy)
return (dx * dx + dy * dy) ** 0.5
def min_interplayer_dist(v):
p0 = [pos(x) for x in ents(v, 0, 'units')] + [pos(x) for x in ents(v, 0, 'cities')]
p1 = [pos(x) for x in ents(v, 1, 'units')] + [pos(x) for x in ents(v, 1, 'cities')]
if not p0 or not p1:
return -1
return min(wrapdist(a, b) for a in p0 for b in p1)
for seed in (1, 6):
c = HarnessClient(HarnessConfig(seed=seed, players=2, player_slots=(0, 1),
map_size='duel', map_type='pangaea',
victory_mode='domination', timeout_sec=110))
v = c.view(1)
cap0 = [pos(x) for x in ents(v, 0, 'cities')]
cap1 = [pos(x) for x in ents(v, 1, 'cities')]
print('seed%d t0: P0cap=%s P1cap=%s capdist=%.1f' % (
seed, cap0, cap1, wrapdist(cap0[0], cap1[0]) if cap0 and cap1 else -1))
prev0 = prev1 = 0
combat_seen = False
mindist_ever = 999
for rnd in range(58):
v = c.view(1)
n0 = len(ents(v, 0, 'units')); n1 = len(ents(v, 1, 'units'))
# mil drop relative to prior peak observed = combat loss signal
if rnd > 0 and (n0 < prev0 or n1 < prev1):
combat_seen = True
prev0, prev1 = max(prev0, n0), max(prev1, n1)
d = min_interplayer_dist(v)
if d >= 0:
mindist_ever = min(mindist_ever, d)
if rnd % 15 == 0:
print(' t%d: P0u=%d P1u=%d mindist=%.1f' % (
int(v.get('turn', 0)), n0, n1, d))
adv(c, 0); adv(c, 1)
print(' seed%d SUMMARY: combat_seen(mil_drop)=%s min_interplayer_dist_ever=%.1f' % (
seed, combat_seen, mindist_ever))
c.shutdown()