implement royale game mode and tighten spaces in duel mode
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
import time
|
||||
|
||||
from server.GameBoard import GameBoard
|
||||
from snakes.BestBattleSnake import BestBattleSnake
|
||||
|
||||
def build_game_state() -> dict:
|
||||
return {
|
||||
"game": {
|
||||
"id": "bench-best-snake",
|
||||
"ruleset": {
|
||||
"name": "standard",
|
||||
"version": "v1.0.0",
|
||||
"settings": {"hazardDamagePerTurn": 14},
|
||||
},
|
||||
"source": "custom",
|
||||
"map": "standard",
|
||||
},
|
||||
"turn": 42,
|
||||
"board": {
|
||||
"height": 11,
|
||||
"width": 11,
|
||||
"food": [{"x": 1, "y": 9}, {"x": 9, "y": 1}],
|
||||
"hazards": [],
|
||||
"snakes": [
|
||||
{
|
||||
"id": "me",
|
||||
"name": "me",
|
||||
"health": 74,
|
||||
"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": 3, "y": 3},
|
||||
{"x": 3, "y": 4},
|
||||
{"x": 3, "y": 5},
|
||||
{"x": 4, "y": 5},
|
||||
],
|
||||
},
|
||||
{
|
||||
"id": "enemy",
|
||||
"name": "enemy",
|
||||
"health": 70,
|
||||
"length": 8,
|
||||
"head": {"x": 7, "y": 7},
|
||||
"body": [
|
||||
{"x": 7, "y": 7},
|
||||
{"x": 7, "y": 6},
|
||||
{"x": 7, "y": 5},
|
||||
{"x": 8, "y": 5},
|
||||
{"x": 9, "y": 5},
|
||||
{"x": 9, "y": 6},
|
||||
{"x": 9, "y": 7},
|
||||
{"x": 8, "y": 7},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"you": {
|
||||
"id": "me",
|
||||
"name": "me",
|
||||
"health": 74,
|
||||
"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": 3, "y": 3},
|
||||
{"x": 3, "y": 4},
|
||||
{"x": 3, "y": 5},
|
||||
{"x": 4, "y": 5},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--iterations", type=int, default=1000)
|
||||
args = parser.parse_args()
|
||||
|
||||
game_state = build_game_state()
|
||||
board = GameBoard(
|
||||
game_id=game_state["game"]["id"],
|
||||
width=game_state["board"]["width"],
|
||||
height=game_state["board"]["height"],
|
||||
ruleset=game_state["game"]["ruleset"],
|
||||
source=game_state["game"]["source"],
|
||||
map=game_state["game"]["map"],
|
||||
snake_class=BestBattleSnake(),
|
||||
)
|
||||
|
||||
start = time.perf_counter()
|
||||
for i in range(args.iterations):
|
||||
game_state["turn"] = i + 1
|
||||
board.read_game_data(game_state)
|
||||
board.snake_neat_make_a_move()
|
||||
elapsed = time.perf_counter() - start
|
||||
|
||||
avg_ms = (elapsed / max(1, args.iterations)) * 1000.0
|
||||
print(f"BestBattleSnake benchmark: {args.iterations} moves in {elapsed:.4f}s ({avg_ms:.3f} ms/move)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -328,6 +328,84 @@ class TestBestBattleSnake(unittest.TestCase):
|
||||
move = make_board(game_state).snake_neat_make_a_move()
|
||||
self.assertNotEqual(move, "up")
|
||||
|
||||
def test_royale_uses_ruleset_hazard_damage_setting(self):
|
||||
game_state = {
|
||||
"game": {
|
||||
"id": "test-royale-hazard-setting",
|
||||
"ruleset": {
|
||||
"name": "standard",
|
||||
"version": "v1.0.0",
|
||||
"settings": {"hazardDamagePerTurn": 22},
|
||||
},
|
||||
"source": "custom",
|
||||
"map": "royale",
|
||||
},
|
||||
"turn": 5,
|
||||
"board": {
|
||||
"height": 11,
|
||||
"width": 11,
|
||||
"food": [],
|
||||
"hazards": [],
|
||||
"snakes": [
|
||||
{
|
||||
"id": "me",
|
||||
"name": "me",
|
||||
"health": 80,
|
||||
"length": 3,
|
||||
"head": {"x": 5, "y": 5},
|
||||
"body": [
|
||||
{"x": 5, "y": 5},
|
||||
{"x": 5, "y": 4},
|
||||
{"x": 5, "y": 3},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
"you": {
|
||||
"id": "me",
|
||||
"name": "me",
|
||||
"health": 80,
|
||||
"length": 3,
|
||||
"head": {"x": 5, "y": 5},
|
||||
"body": [
|
||||
{"x": 5, "y": 5},
|
||||
{"x": 5, "y": 4},
|
||||
{"x": 5, "y": 3},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
board = make_board(game_state)
|
||||
snake = board.snake_class
|
||||
self.assertEqual(snake._hazard_damage_per_turn(board), 22)
|
||||
|
||||
def test_royale_new_hazard_has_spawn_grace(self):
|
||||
snake = BestBattleSnake()
|
||||
point = (4, 4)
|
||||
hazard_set = {point}
|
||||
|
||||
self.assertFalse(
|
||||
snake._hazard_is_active(
|
||||
point, ate_food=False, hazard_set=hazard_set, previous_hazard_set=set()
|
||||
)
|
||||
)
|
||||
self.assertTrue(
|
||||
snake._hazard_is_active(
|
||||
point,
|
||||
ate_food=False,
|
||||
hazard_set=hazard_set,
|
||||
previous_hazard_set=hazard_set,
|
||||
)
|
||||
)
|
||||
self.assertFalse(
|
||||
snake._hazard_is_active(
|
||||
point,
|
||||
ate_food=True,
|
||||
hazard_set=hazard_set,
|
||||
previous_hazard_set=hazard_set,
|
||||
)
|
||||
)
|
||||
|
||||
def test_constrictor_avoids_growth_dead_end(self):
|
||||
game_state = {
|
||||
"game": {
|
||||
@@ -393,6 +471,75 @@ class TestBestBattleSnake(unittest.TestCase):
|
||||
move = make_board(game_state).snake_neat_make_a_move()
|
||||
self.assertEqual(move, "up")
|
||||
|
||||
def test_duel_tightens_space_when_enemy_is_encased(self):
|
||||
game_state = {
|
||||
"game": {
|
||||
"id": "test-encase-tighten",
|
||||
"ruleset": {"name": "standard", "version": "v1.0.0"},
|
||||
"source": "custom",
|
||||
"map": "standard",
|
||||
},
|
||||
"turn": 40,
|
||||
"board": {
|
||||
"height": 7,
|
||||
"width": 7,
|
||||
"food": [{"x": 0, "y": 0}],
|
||||
"hazards": [],
|
||||
"snakes": [
|
||||
{
|
||||
"id": "me",
|
||||
"name": "me",
|
||||
"health": 92,
|
||||
"length": 8,
|
||||
"head": {"x": 2, "y": 3},
|
||||
"body": [
|
||||
{"x": 2, "y": 3},
|
||||
{"x": 2, "y": 2},
|
||||
{"x": 1, "y": 2},
|
||||
{"x": 1, "y": 3},
|
||||
{"x": 1, "y": 4},
|
||||
{"x": 2, "y": 4},
|
||||
{"x": 3, "y": 4},
|
||||
{"x": 3, "y": 5},
|
||||
],
|
||||
},
|
||||
{
|
||||
"id": "enemy",
|
||||
"name": "enemy",
|
||||
"health": 88,
|
||||
"length": 5,
|
||||
"head": {"x": 4, "y": 3},
|
||||
"body": [
|
||||
{"x": 4, "y": 3},
|
||||
{"x": 5, "y": 3},
|
||||
{"x": 5, "y": 2},
|
||||
{"x": 4, "y": 2},
|
||||
{"x": 4, "y": 1},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
"you": {
|
||||
"id": "me",
|
||||
"name": "me",
|
||||
"health": 92,
|
||||
"length": 8,
|
||||
"head": {"x": 2, "y": 3},
|
||||
"body": [
|
||||
{"x": 2, "y": 3},
|
||||
{"x": 2, "y": 2},
|
||||
{"x": 1, "y": 2},
|
||||
{"x": 1, "y": 3},
|
||||
{"x": 1, "y": 4},
|
||||
{"x": 2, "y": 4},
|
||||
{"x": 3, "y": 4},
|
||||
{"x": 3, "y": 5},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
move = make_board(game_state).snake_neat_make_a_move()
|
||||
self.assertEqual(move, "right")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user