Skip to content

Commit

Permalink
Remove mini map support (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
tonypr authored Jun 30, 2024
1 parent 5edcb6c commit 655b0c4
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 152 deletions.
2 changes: 0 additions & 2 deletions catanatron_core/catanatron/models/board.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from catanatron.models.player import Color
from catanatron.models.map import (
BASE_MAP_TEMPLATE,
MINI_MAP_TEMPLATE,
NUM_NODES,
CatanMap,
NodeId,
Expand All @@ -19,7 +18,6 @@

# Used to find relationships between nodes and edges
base_map = CatanMap.from_template(BASE_MAP_TEMPLATE)
mini_map = CatanMap.from_template(MINI_MAP_TEMPLATE)
STATIC_GRAPH = nx.Graph()
for tile in base_map.tiles.values():
STATIC_GRAPH.add_nodes_from(tile.nodes.values())
Expand Down
35 changes: 1 addition & 34 deletions catanatron_core/catanatron/models/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,37 +105,6 @@ class MapTemplate:
]


# Small 7-tile map, no ports.
MINI_MAP_TEMPLATE = MapTemplate(
[3, 4, 5, 6, 8, 9, 10],
[],
[WOOD, None, BRICK, SHEEP, WHEAT, WHEAT, ORE],
{
# center
(0, 0, 0): LandTile,
# first layer
(1, -1, 0): LandTile,
(0, -1, 1): LandTile,
(-1, 0, 1): LandTile,
(-1, 1, 0): LandTile,
(0, 1, -1): LandTile,
(1, 0, -1): LandTile,
# second layer
(2, -2, 0): Water,
(1, -2, 1): Water,
(0, -2, 2): Water,
(-1, -1, 2): Water,
(-2, 0, 2): Water,
(-2, 1, 1): Water,
(-2, 2, 0): Water,
(-1, 2, -1): Water,
(0, 2, -2): Water,
(1, 1, -2): Water,
(2, 0, -2): Water,
(2, -1, -1): Water,
},
)

"""Standard 4-player map"""
BASE_MAP_TEMPLATE = MapTemplate(
[2, 3, 3, 4, 4, 5, 5, 6, 6, 8, 8, 9, 9, 10, 10, 11, 11, 12],
Expand Down Expand Up @@ -553,10 +522,8 @@ def get_edge_nodes(edge_ref):
TOURNAMENT_MAP = CatanMap.from_tiles(TOURNAMENT_MAP_TILES)


def build_map(map_type: Literal["BASE", "TOURNAMENT", "MINI"]):
def build_map(map_type: Literal["BASE", "TOURNAMENT"]):
if map_type == "TOURNAMENT":
return TOURNAMENT_MAP # this assumes map is read-only data struct
elif map_type == "MINI":
return CatanMap.from_template(MINI_MAP_TEMPLATE)
else:
return CatanMap.from_template(BASE_MAP_TEMPLATE)
9 changes: 8 additions & 1 deletion tests/integration_tests/test_speed.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
from catanatron.models.player import Color, SimplePlayer, RandomPlayer
from catanatron.players.weighted_random import WeightedRandomPlayer
from catanatron_gym.features import create_sample
from catanatron_experimental.machine_learning.players.minimax import AlphaBetaPlayer, SameTurnAlphaBetaPlayer
from catanatron_experimental.machine_learning.players.minimax import (
AlphaBetaPlayer,
SameTurnAlphaBetaPlayer,
)

RANDOM_SEED = 0

Expand Down Expand Up @@ -62,6 +65,7 @@ def test_simpleplayer_speed(benchmark):
SimplePlayer(Color.ORANGE),
]
game = Game(players, seed=RANDOM_SEED)

def _play_game(game):
for _ in range(100):
game.play_tick()
Expand All @@ -78,6 +82,7 @@ def test_weightedrandom_speed(benchmark):
WeightedRandomPlayer(Color.ORANGE),
]
game = Game(players, seed=RANDOM_SEED)

def _play_game(game):
for _ in range(100):
game.play_tick()
Expand All @@ -94,6 +99,7 @@ def test_alphabeta_speed(benchmark):
AlphaBetaPlayer(Color.ORANGE),
]
game = Game(players, seed=RANDOM_SEED)

def _play_game(game):
for _ in range(100):
game.play_tick()
Expand All @@ -110,6 +116,7 @@ def test_same_turn_alphabeta_speed(benchmark):
SameTurnAlphaBetaPlayer(Color.ORANGE),
]
game = Game(players, seed=RANDOM_SEED)

def _play_game(game):
for _ in range(100):
game.play_tick()
Expand Down
17 changes: 1 addition & 16 deletions tests/models/test_board.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from catanatron.models.map import MINI_MAP_TEMPLATE, CatanMap
from catanatron.models.map import CatanMap
from catanatron.models.enums import RESOURCES
from catanatron.models.board import Board, get_node_distances
from catanatron.models.player import Color
Expand Down Expand Up @@ -97,14 +97,6 @@ def test_buildable_nodes():
assert len(nodes) == 54


def test_buildable_nodes_in_mini_map():
board = Board(catan_map=CatanMap.from_template(MINI_MAP_TEMPLATE))
nodes = board.buildable_node_ids(Color.RED)
assert len(nodes) == 0
nodes = board.buildable_node_ids(Color.RED, initial_build_phase=True)
assert len(nodes) == 24


def test_placing_settlement_removes_four_buildable_nodes():
board = Board()
board.build_settlement(Color.RED, 3, initial_build_phase=True)
Expand Down Expand Up @@ -155,13 +147,6 @@ def test_buildable_edges_simple():
assert len(buildable) == 3


def test_buildable_edges_in_mini():
board = Board(catan_map=CatanMap.from_template(MINI_MAP_TEMPLATE))
board.build_settlement(Color.RED, 19, initial_build_phase=True)
buildable = board.buildable_edges(Color.RED)
assert len(buildable) == 2


def test_buildable_edges():
board = Board()
board.build_settlement(Color.RED, 3, initial_build_phase=True)
Expand Down
16 changes: 0 additions & 16 deletions tests/models/test_map.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from catanatron import WOOD, BRICK
from catanatron.models.map import (
BASE_MAP_TEMPLATE,
MINI_MAP_TEMPLATE,
CatanMap,
LandTile,
get_nodes_and_edges,
Expand All @@ -23,21 +22,6 @@ def test_node_production_of_same_resource_adjacent_tile():
assert result["WOOD"] == DICE_PROBAS[12] + DICE_PROBAS[6] + DICE_PROBAS[8]


def test_mini_map_can_be_created():
mini = CatanMap.from_template(MINI_MAP_TEMPLATE)
assert len(mini.land_tiles) == 7
assert len(mini.land_nodes) == 24
assert len(mini.tiles_by_id) == 7
assert len(mini.ports_by_id) == 0
assert len(mini.port_nodes) == 0
assert len(mini.adjacent_tiles) == 24
assert len(mini.node_production) == 24

resources = [i.resource for i in mini.land_tiles.values()]
assert any(isinstance(i, str) for i in resources)
assert any(i is None for i in resources) # theres one desert


def test_base_map_can_be_created():
catan_map = CatanMap.from_template(BASE_MAP_TEMPLATE)
assert len(catan_map.land_tiles) == 19
Expand Down
48 changes: 23 additions & 25 deletions tests/test_game.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
player_num_resource_cards,
)
from catanatron.state_functions import player_key
from catanatron.models.actions import (
generate_playable_actions
)
from catanatron.models.actions import generate_playable_actions
from catanatron.models.enums import (
BRICK,
ORE,
Expand Down Expand Up @@ -358,8 +356,8 @@ def test_longest_road_steal():
board.build_road(p0.color, (7, 8))
board.build_road(p0.color, (8, 9))
board.build_road(p0.color, (9, 10))
game.state.player_state[f'{p0_key}_VICTORY_POINTS'] = 1
game.state.player_state[f'{p0_key}_ACTUAL_VICTORY_POINTS'] = 1
game.state.player_state[f"{p0_key}_VICTORY_POINTS"] = 1
game.state.player_state[f"{p0_key}_ACTUAL_VICTORY_POINTS"] = 1

# p1 has longest road of lenght 5
board.build_settlement(p1.color, 28, True)
Expand All @@ -368,14 +366,14 @@ def test_longest_road_steal():
board.build_road(p1.color, (29, 30))
board.build_road(p1.color, (30, 31))
board.build_road(p1.color, (31, 32))
game.state.player_state[f'{p1_key}_VICTORY_POINTS'] = 3
game.state.player_state[f'{p1_key}_ACTUAL_VICTORY_POINTS'] = 3
game.state.player_state[f'{p1_key}_HAS_ROAD'] = True
game.state.player_state[f"{p1_key}_VICTORY_POINTS"] = 3
game.state.player_state[f"{p1_key}_ACTUAL_VICTORY_POINTS"] = 3
game.state.player_state[f"{p1_key}_HAS_ROAD"] = True

# Required to be able to apply actions other than rolling or initial build phase.
game.state.current_prompt = ActionPrompt.PLAY_TURN
game.state.is_initial_build_phase = False
game.state.player_state[f'{p0_key}_HAS_ROLLED'] = True
game.state.player_state[f"{p0_key}_HAS_ROLLED"] = True
game.state.playable_actions = generate_playable_actions(game.state)

# Set up player0 to build two roads and steal longest road.
Expand All @@ -386,25 +384,25 @@ def test_longest_road_steal():

# Matching length of longest road does not steal longest road.
apply_action(game.state, Action(p0.color, ActionType.BUILD_ROAD, road1))
assert game.state.player_state[f'{p0_key}_LONGEST_ROAD_LENGTH'] == 5
assert game.state.player_state[f'{p0_key}_HAS_ROAD'] == False
assert game.state.player_state[f'{p0_key}_VICTORY_POINTS'] == 1
assert game.state.player_state[f'{p0_key}_ACTUAL_VICTORY_POINTS'] == 1
assert game.state.player_state[f'{p1_key}_LONGEST_ROAD_LENGTH'] == 5
assert game.state.player_state[f'{p1_key}_HAS_ROAD'] == True
assert game.state.player_state[f'{p1_key}_VICTORY_POINTS'] == 3
assert game.state.player_state[f'{p1_key}_ACTUAL_VICTORY_POINTS'] == 3
assert game.state.player_state[f"{p0_key}_LONGEST_ROAD_LENGTH"] == 5
assert game.state.player_state[f"{p0_key}_HAS_ROAD"] == False
assert game.state.player_state[f"{p0_key}_VICTORY_POINTS"] == 1
assert game.state.player_state[f"{p0_key}_ACTUAL_VICTORY_POINTS"] == 1
assert game.state.player_state[f"{p1_key}_LONGEST_ROAD_LENGTH"] == 5
assert game.state.player_state[f"{p1_key}_HAS_ROAD"] == True
assert game.state.player_state[f"{p1_key}_VICTORY_POINTS"] == 3
assert game.state.player_state[f"{p1_key}_ACTUAL_VICTORY_POINTS"] == 3

# Surpassing length of longest road steals longest road and VPs.
apply_action(game.state, Action(p0.color, ActionType.BUILD_ROAD, road2))
assert game.state.player_state[f'{p0_key}_LONGEST_ROAD_LENGTH'] == 6
assert game.state.player_state[f'{p0_key}_HAS_ROAD'] == True
assert game.state.player_state[f'{p0_key}_VICTORY_POINTS'] == 3
assert game.state.player_state[f'{p0_key}_ACTUAL_VICTORY_POINTS'] == 3
assert game.state.player_state[f'{p1_key}_LONGEST_ROAD_LENGTH'] == 5
assert game.state.player_state[f'{p1_key}_HAS_ROAD'] == False
assert game.state.player_state[f'{p1_key}_VICTORY_POINTS'] == 1
assert game.state.player_state[f'{p1_key}_ACTUAL_VICTORY_POINTS'] == 1
assert game.state.player_state[f"{p0_key}_LONGEST_ROAD_LENGTH"] == 6
assert game.state.player_state[f"{p0_key}_HAS_ROAD"] == True
assert game.state.player_state[f"{p0_key}_VICTORY_POINTS"] == 3
assert game.state.player_state[f"{p0_key}_ACTUAL_VICTORY_POINTS"] == 3
assert game.state.player_state[f"{p1_key}_LONGEST_ROAD_LENGTH"] == 5
assert game.state.player_state[f"{p1_key}_HAS_ROAD"] == False
assert game.state.player_state[f"{p1_key}_VICTORY_POINTS"] == 1
assert game.state.player_state[f"{p1_key}_ACTUAL_VICTORY_POINTS"] == 1


def test_second_placement_takes_cards_from_bank():
Expand Down
8 changes: 0 additions & 8 deletions tests/test_gym.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,6 @@ def custom_reward(game, p0_color):
assert reward == 123


def test_custom_map():
env = gym.make("catanatron_gym:catanatron-v1", config={"map_type": "MINI"})
observation, info = env.reset()
assert len(env.get_valid_actions()) < 50 # type: ignore
assert len(observation) < 614
# assert env.action_space.n == 260


def test_enemies():
env = gym.make(
"catanatron_gym:catanatron-v1",
Expand Down
50 changes: 0 additions & 50 deletions tests/test_machine_learning.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from catanatron.models.board import Board, get_edges
from catanatron.models.map import (
BASE_MAP_TEMPLATE,
MINI_MAP_TEMPLATE,
NUM_EDGES,
NUM_NODES,
CatanMap,
Expand Down Expand Up @@ -192,29 +191,6 @@ def test_tile_features():
assert features[f"TILE0_PROBA"] == proba


def test_tile_features_in_mini():
players = [
SimplePlayer(Color.RED),
SimplePlayer(Color.BLUE),
]
game = Game(players, catan_map=CatanMap.from_template(MINI_MAP_TEMPLATE))

features = tile_features(game, players[0].color)
haystack = "".join(features.keys())
assert "TILE7" not in haystack


def test_port_features_in_mini():
players = [
SimplePlayer(Color.RED),
SimplePlayer(Color.BLUE),
]
game = Game(players, catan_map=CatanMap.from_template(MINI_MAP_TEMPLATE))

features = port_features(game, players[0].color)
assert len(features) == 0


def test_graph_features():
players = [
SimplePlayer(Color.RED),
Expand Down Expand Up @@ -242,32 +218,6 @@ def test_graph_features():
assert ("NODE" + str(node)) in haystack


def test_graph_features_in_mini():
players = [
SimplePlayer(Color.RED),
SimplePlayer(Color.BLUE),
]
game = Game(players, catan_map=CatanMap.from_template(MINI_MAP_TEMPLATE))
p0_color = game.state.colors[0]
game.execute(Action(p0_color, ActionType.BUILD_SETTLEMENT, 3))
game.execute(Action(p0_color, ActionType.BUILD_ROAD, (2, 3)))

features = graph_features(game, p0_color)
assert features[f"NODE3_P0_SETTLEMENT"]
assert features[f"EDGE(2, 3)_P0_ROAD"]
assert not features[f"NODE3_P1_SETTLEMENT"]
assert not features[f"NODE0_P1_SETTLEMENT"]
# todo: CHANGE NUM_EDGES
assert len(features) == 24 * len(players) * 2 + 30 * len(players)
assert sum(features.values()) == 2

haystack = "".join(features.keys())
for edge in get_edges(game.state.board.map.land_nodes):
assert str(edge) in haystack
for node in range(24):
assert ("NODE" + str(node)) in haystack


def test_init_board_tensor_map():
node_map, edge_map = init_board_tensor_map()
assert node_map[82] == (0, 0)
Expand Down

0 comments on commit 655b0c4

Please sign in to comment.