diff --git a/snakes/BestBattleSnake.py b/snakes/BestBattleSnake.py index 23d2e4e..359af61 100644 --- a/snakes/BestBattleSnake.py +++ b/snakes/BestBattleSnake.py @@ -348,6 +348,7 @@ class BestBattleSnake(TemplateSnake): enemy_head = (enemy["head"]["x"], enemy["head"]["y"]) enemy_len = enemy.get("length", len(enemy["body"])) encase_target_space = max(8, enemy_len * 2) + can_head_hunt = my_len > enemy_len and my_len >= 8 scores:dict[str, float] = {} move_safety:dict[str, dict[str, Any]] = {} @@ -421,10 +422,10 @@ class BestBattleSnake(TemplateSnake): score += max(0, 3 - enemy_options) * 95.0 if reachable_space > enemy_space: score += 120.0 - if direct_head_distance <= 2: + if direct_head_distance <= 2 and can_head_hunt: score += 40.0 - if my_len > enemy_len: + if can_head_hunt: if direct_head_distance == 1: score += 220.0 * duel_weights["head_pressure"] elif direct_head_distance == 2: @@ -432,6 +433,8 @@ class BestBattleSnake(TemplateSnake): else: if direct_head_distance <= 2: score -= 120.0 * duel_weights["distance_safety"] + if direct_head_distance == 1: + score -= 180.0 * duel_weights["distance_safety"] hunger_urgency = max(0.0, (65.0 - my_health) / 65.0) if nearest_food_dist is not None: @@ -918,7 +921,7 @@ class BestBattleSnake(TemplateSnake): def _distance_map(self, start:Point, blocked:set[Point], width:int, height:int) -> dict[Point, int]: """Build a BFS distance map from the given start cell.""" queue = deque([(start, 0)]) - distances = {start:0} + distances = {start: 0} while queue: point, distance = queue.popleft() diff --git a/tests/test_BestBattleSnake.py b/tests/test_BestBattleSnake.py index baa7d1e..f7c78c9 100644 --- a/tests/test_BestBattleSnake.py +++ b/tests/test_BestBattleSnake.py @@ -218,6 +218,146 @@ class TestBestBattleSnake(unittest.TestCase): move = make_board(game_state).snake_neat_make_a_move() self.assertNotEqual(move, "right") + def test_duel_small_length_lead_does_not_head_hunt(self): + game_state = { + "game": { + "id": "test-duel-small-no-head-hunt", + "ruleset": {"name": "standard", "version": "v1.0.0"}, + "source": "custom", + "map": "standard", + }, + "turn": 20, + "board": { + "height": 11, + "width": 11, + "food": [{"x": 1, "y": 1}], + "hazards": [], + "snakes": [ + { + "id": "me", + "name": "me", + "health": 90, + "length": 7, + "head": {"x": 5, "y": 5}, + "body": [ + {"x": 5, "y": 5}, + {"x": 5, "y": 4}, + {"x": 5, "y": 3}, + {"x": 4, "y": 3}, + {"x": 4, "y": 4}, + {"x": 4, "y": 5}, + {"x": 4, "y": 6}, + ], + }, + { + "id": "enemy", + "name": "enemy", + "health": 90, + "length": 6, + "head": {"x": 7, "y": 5}, + "body": [ + {"x": 7, "y": 5}, + {"x": 7, "y": 4}, + {"x": 7, "y": 3}, + {"x": 7, "y": 2}, + {"x": 7, "y": 1}, + {"x": 6, "y": 1}, + ], + }, + ], + }, + "you": { + "id": "me", + "name": "me", + "health": 90, + "length": 7, + "head": {"x": 5, "y": 5}, + "body": [ + {"x": 5, "y": 5}, + {"x": 5, "y": 4}, + {"x": 5, "y": 3}, + {"x": 4, "y": 3}, + {"x": 4, "y": 4}, + {"x": 4, "y": 5}, + {"x": 4, "y": 6}, + ], + }, + } + + move = make_board(game_state).snake_neat_make_a_move() + self.assertNotEqual(move, "right") + + def test_duel_big_length_lead_can_head_hunt(self): + game_state = { + "game": { + "id": "test-duel-big-head-hunt", + "ruleset": {"name": "standard", "version": "v1.0.0"}, + "source": "custom", + "map": "standard", + }, + "turn": 20, + "board": { + "height": 11, + "width": 11, + "food": [{"x": 1, "y": 1}], + "hazards": [], + "snakes": [ + { + "id": "me", + "name": "me", + "health": 90, + "length": 8, + "head": {"x": 5, "y": 5}, + "body": [ + {"x": 5, "y": 5}, + {"x": 5, "y": 4}, + {"x": 5, "y": 3}, + {"x": 4, "y": 3}, + {"x": 4, "y": 4}, + {"x": 4, "y": 5}, + {"x": 4, "y": 6}, + {"x": 5, "y": 6}, + ], + }, + { + "id": "enemy", + "name": "enemy", + "health": 90, + "length": 6, + "head": {"x": 7, "y": 5}, + "body": [ + {"x": 7, "y": 5}, + {"x": 7, "y": 4}, + {"x": 7, "y": 3}, + {"x": 7, "y": 2}, + {"x": 7, "y": 1}, + {"x": 6, "y": 1}, + ], + }, + ], + }, + "you": { + "id": "me", + "name": "me", + "health": 90, + "length": 8, + "head": {"x": 5, "y": 5}, + "body": [ + {"x": 5, "y": 5}, + {"x": 5, "y": 4}, + {"x": 5, "y": 3}, + {"x": 4, "y": 3}, + {"x": 4, "y": 4}, + {"x": 4, "y": 5}, + {"x": 4, "y": 6}, + {"x": 5, "y": 6}, + ], + }, + } + + move = make_board(game_state).snake_neat_make_a_move() + self.assertEqual(move, "right") + def test_does_not_step_into_stacked_tail(self): game_state = { "game": {