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')