feat(snake): optimize duels and persist customizations
Build and Push Docker Container / build-and-push (push) Successful in 7m29s

- Add deadline-aware iterative duel search with bitboards and tuple bodies.

- Reuse transposition bounds and move-order hints across search depths.

- Persist snake colors, heads, and tails in SQLite and PostgreSQL.

- Restore customization metadata when hydrating dashboard replays.

- Cover duel deadlines, cache reuse, schema storage, and replay output.
This commit is contained in:
2026-08-01 17:19:35 +02:00
parent 65c97b219b
commit 4f022d3d01
7 changed files with 449 additions and 11 deletions
@@ -1,9 +1,11 @@
import unittest
from time import perf_counter
from snakes import SnakeBuilder, get_snake_version
from snakes.ApexBattleSnake import ApexBattleSnake
from snakes.PrismBattleSnake_GPT_5_6_Sol import PrismBattleSnake_GPT_5_6_Sol
from snakes.bitboard import BitBoard
from snakes.bitboard_duel_search import BitboardDuelSearch
class TestBitBoard(unittest.TestCase):
@@ -64,5 +66,51 @@ class TestPrismBattleSnake_GPT_5_6_Sol(unittest.TestCase):
self.assertEqual(open_count, 9)
self.assertEqual(trapped_count, 1)
def test_bitboard_duel_search_values_length_advantage(self):
snake = PrismBattleSnake_GPT_5_6_Sol()
my_body = [{"x": 1, "y": 0}, {"x": 0, "y": 0}, {"x": 0, "y": 1}]
enemy_body = [{"x": 1, "y": 2}, {"x": 0, "y": 2}]
value = snake._minimax_sim(
my_body=my_body, enemy_body=enemy_body,
food_set=set(), hazard_set=set(),
my_health=100, enemy_health=100,
hazard_damage=15, hazard_count={},
width=3, height=3, depth=2,
alpha=-1e9, beta=1e9, deadline=None,
)
self.assertGreater(value, 0)
def test_bitboard_duel_search_reuses_transpositions(self):
board = BitBoard(5, 5)
search = BitboardDuelSearch(
board=board, food=set(), hazards=set(), hazard_count={},
hazard_damage=15, deadline=perf_counter() + 1.0,
)
my_body = [{"x": 1, "y": 1}, {"x": 1, "y": 0}, {"x": 0, "y": 0}]
enemy_body = [{"x": 3, "y": 3}, {"x": 3, "y": 4}, {"x": 4, "y": 4}]
search.search_depth(my_body, enemy_body, 100, 100, 3, set())
hits_before = search.cache_hits
search.search_depth(my_body, enemy_body, 100, 100, 3, set())
self.assertGreater(search.cache_hits, hits_before)
def test_bitboard_duel_search_respects_deadline(self):
board = BitBoard(11, 11)
search = BitboardDuelSearch(
board=board, food=set(), hazards=set(), hazard_count={},
hazard_damage=15, deadline=perf_counter() - 0.001,
)
my_body = [{"x": 2, "y": 2}, {"x": 2, "y": 1}, {"x": 2, "y": 0}]
enemy_body = [{"x": 8, "y": 8}, {"x": 8, "y": 9}, {"x": 8, "y": 10}]
started = perf_counter()
_, depth = search.search(my_body, enemy_body, 100, 100, 6, set())
self.assertEqual(depth, 0)
self.assertLess(perf_counter() - started, 0.05)
if __name__ == "__main__":
unittest.main()