feat: add Zenith strategy and move latency tracing
Build and Push Docker Container / build-and-push (push) Successful in 2m18s

- Register Zenith 1.1 with balanced duel verdicts and forced-outcome overrides.
- Prioritize permanent-trail space in Constrictor and health-aware hazard routes.
- Deduct executor queue delays and return fallback directions on move timeouts.
- Correlate response headers, replay timings, and sampled structured trace logs.
- Move shared metrics publication off the response path without losing local counts.
- Allow configurable tournament opponents and add a psql helper recipe.
- Preserve empty latency values through compact replay encoding and migration.
- Update Arena game links and use default assets for missing customizations.
- Cover strategy, HTTP lifecycle, tracing, replay codecs, and dashboard behavior.
- Validate with 260 passing Python tests, 4 skips, and 2 passing JavaScript tests.
This commit is contained in:
2026-11-05 01:11:31 +01:00
parent 39a7a53873
commit a2414f0b3d
26 changed files with 758 additions and 45 deletions
@@ -0,0 +1,84 @@
import unittest
from time import perf_counter
from snakes import SnakeBuilder, get_snake_version
from snakes.strategies.prism import PrismBattleSnake_GPT_5_6_Sol
from snakes.strategies.zenith import ZenithBattleSnake_ClaudeOpus5_5
LOSS = -100_000.0
WIN = 100_000.0
class TestZenithRegistration(unittest.TestCase):
def test_api_name_and_version_are_exposed(self):
snake = ZenithBattleSnake_ClaudeOpus5_5()
self.assertEqual(snake.name, "ZenithBattleSnake")
self.assertEqual(snake.version, "1.1.0")
self.assertEqual(get_snake_version("ZenithBattleSnake_ClaudeOpus5_5"), "1.1.0")
self.assertIsInstance(snake, PrismBattleSnake_GPT_5_6_Sol)
self.assertIsInstance(
SnakeBuilder.build("ZenithBattleSnake_ClaudeOpus5_5"),
ZenithBattleSnake_ClaudeOpus5_5,
)
class TestZenithVerdicts(unittest.TestCase):
def test_proven_loss_is_vetoed_for_best_surviving_heuristic(self):
scores = {"up": 300.0, "left": 120.0, "right": 90.0}
verdicts = {"up": (LOSS, 3), "left": (-40.0, 3), "right": (25.0, 3)}
self.assertEqual(ZenithBattleSnake_ClaudeOpus5_5._apply_verdicts("up", scores, verdicts), "left")
def test_proven_win_overrides_heuristic(self):
scores = {"up": 300.0, "left": 120.0}
verdicts = {"up": (15.0, 2), "left": (WIN, 2)}
self.assertEqual(ZenithBattleSnake_ClaudeOpus5_5._apply_verdicts("up", scores, verdicts), "left")
def test_keeps_choice_when_every_move_loses(self):
scores = {"up": 300.0, "left": 120.0}
verdicts = {"up": (LOSS, 2), "left": (LOSS - 1, 2)}
self.assertEqual(ZenithBattleSnake_ClaudeOpus5_5._apply_verdicts("up", scores, verdicts), "up")
def test_keeps_choice_without_verdict(self):
scores = {"up": 300.0, "left": 120.0}
self.assertEqual(ZenithBattleSnake_ClaudeOpus5_5._apply_verdicts("up", scores, {}), "up")
def test_verdict_search_resolves_every_candidate(self):
snake = ZenithBattleSnake_ClaudeOpus5_5()
# Longer enemy can also reach (2, 5): stepping there loses the head-to-head.
my_body = [{"x": 1, "y": 5}, {"x": 0, "y": 5}]
enemy = {"body": [{"x": 3, "y": 5}, {"x": 4, "y": 5}, {"x": 5, "y": 5}], "health": 100}
safe_moves = {"up": {"x": 1, "y": 6}, "right": {"x": 2, "y": 5}}
verdicts = snake._duel_verdicts(
safe_moves=safe_moves, my_body=my_body, enemy=enemy, my_health=100,
food_set=set(), hazard_set=set(), hazard_damage=15, hazard_count={},
previous_hazard_set=set(), width=11, height=11,
deadline=perf_counter() + 1.0,
)
self.assertEqual(set(verdicts), {"up", "right"})
self.assertLessEqual(verdicts["right"][0], LOSS / 2)
self.assertGreater(verdicts["up"][0], LOSS / 2)
self.assertEqual(
snake._apply_verdicts("right", {"right": 50.0, "up": 10.0}, verdicts), "up",
)
def test_verdict_search_stops_when_out_of_time(self):
snake = ZenithBattleSnake_ClaudeOpus5_5()
verdicts = snake._duel_verdicts(
safe_moves={"up": {"x": 0, "y": 2}}, my_body=[{"x": 0, "y": 1}],
enemy={"body": [{"x": 4, "y": 4}]}, my_health=100,
food_set=set(), hazard_set=set(), hazard_damage=15, hazard_count={},
previous_hazard_set=set(), width=5, height=5,
deadline=perf_counter() - 0.001,
)
self.assertEqual(verdicts, {})
if __name__ == "__main__":
unittest.main()
+44
View File
@@ -0,0 +1,44 @@
import unittest
from time import perf_counter
from snakes.engine.health_routes import health_route_cost
from snakes.engine.bitboard import BitBoard
from snakes.engine.survival_search import CompactSurvivalSearch
from server.services.move_safety import fallback_move, run_budgeted_move
from unittest.mock import Mock
class TestSurvivalCorrections(unittest.TestCase):
def test_food_resets_health_before_elimination(self):
self.assertEqual(health_route_cost((0, 0), {(1, 0)}, {(1, 0)}, {}, 14, set(), 2, 1), 0)
def test_food_does_not_make_body_passable(self):
self.assertIsNone(health_route_cost((0, 0), {(1, 0)}, set(), {}, 14, {(1, 0)}, 2, 1))
def test_hazard_escape_charges_every_step(self):
self.assertEqual(health_route_cost((0, 0), set(), {(0, 0), (1, 0)}, {}, 14, set(), 3, 1, refuge=True), 16)
def test_long_constrictor_can_survive_in_small_free_region(self):
bb = BitBoard(5, 2)
body = (0, 5, 6, 7, 8, 9)
search = CompactSurvivalSearch(bb, set(), True, None, 2)
self.assertGreater(search._evaluate(body, ()), search.DEATH)
standard = CompactSurvivalSearch(bb, set(), False, None, 2)
self.assertEqual(standard._evaluate(body, ()), standard.DEATH)
def test_expired_queued_job_never_starts_strategy(self):
board = Mock(timeout=500)
self.assertEqual(run_budgeted_move(board, perf_counter()-1, 'left'), 'left')
board.snake_neat_make_a_move.assert_not_called()
def test_worker_deducts_queue_time_and_restores_timeout(self):
board = Mock(timeout=500)
observed = []
board.snake_neat_make_a_move.side_effect = lambda: observed.append(board.timeout) or 'right'
self.assertEqual(run_budgeted_move(board, perf_counter()+0.2, 'left'), 'right')
self.assertLessEqual(observed[0], 200)
self.assertEqual(board.timeout, 500)
def test_fallback_avoids_body_and_wall(self):
mine = {'id':'me','head':{'x':0,'y':0},'body':[{'x':0,'y':0},{'x':1,'y':0}]}
state = {'you':mine,'board':{'width':3,'height':3,'snakes':[mine]}}
self.assertEqual(fallback_move(state), 'up')