def test_yield_resources_two_players_and_city(): board = Board() resource_freqdeck = starting_resource_bank() tile, edge1, edge2, red_node, blue_node = ( board.map.land_tiles[(0, 0, 0)], (2, 3), (3, 4), 4, 0, ) if tile.resource is None: # is desert tile, edge1, edge2, red_node, blue_node = ( board.map.land_tiles[(1, -1, 0)], (9, 2), (9, 8), 8, 6, ) # red has one settlements and one city on tile board.build_settlement(Color.RED, 2, initial_build_phase=True) board.build_road(Color.RED, edge1) board.build_road(Color.RED, edge2) board.build_settlement(Color.RED, red_node) board.build_city(Color.RED, red_node) # blue has a city in tile board.build_settlement(Color.BLUE, blue_node, initial_build_phase=True) board.build_city(Color.BLUE, blue_node) payout, depleted = yield_resources(board, resource_freqdeck, tile.number) assert len(depleted) == 0 assert freqdeck_count(payout[Color.RED], tile.resource) >= 3 # type: ignore assert freqdeck_count(payout[Color.BLUE], tile.resource) >= 2 # type: ignore
def test_must_build_distance_two(): board = Board() board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 2)) with pytest.raises(ValueError): # distance less than 2 board.build_settlement(Color.BLUE, 4, initial_build_phase=True) board.build_settlement(Color.BLUE, 1, initial_build_phase=True)
def test_initial_build_phase_bypasses_restrictions(): board = Board() with pytest.raises(ValueError): # not connected and not initial-placement board.build_settlement(Color.RED, 3) with pytest.raises(ValueError): # not connected to settlement board.build_road(Color.RED, (3, 2)) board.build_settlement(Color.RED, 3, initial_build_phase=True)
def test_enemy_edge_not_buildable(): board = Board() board.build_settlement(Color.BLUE, 0, initial_build_phase=True) board.build_road(Color.BLUE, (0, 1)) board.build_settlement(Color.RED, 2, initial_build_phase=True) board.build_road(Color.RED, (2, 1)) buildable_edges = board.buildable_edges(Color.RED) assert len(buildable_edges) == 3
def test_two_connected_components(): board = Board() board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 4)) components = board.find_connected_components(Color.RED) assert len(components) == 1 board.build_settlement(Color.RED, 1, initial_build_phase=True) board.build_road(Color.RED, (0, 1)) components = board.find_connected_components(Color.RED) assert len(components) == 2
def test_buildable_nodes_respects_distance_two(): board = Board() board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 4)) nodes = board.buildable_node_ids(Color.RED) assert len(nodes) == 0 board.build_road(Color.RED, (4, 5)) nodes = board.buildable_node_ids(Color.RED) assert len(nodes) == 1 assert nodes.pop() == 5
def test_building_road_to_enemy_works_well(): board = Board() board.build_settlement(Color.BLUE, 0, initial_build_phase=True) board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 2)) board.build_road(Color.RED, (2, 1)) board.build_road(Color.RED, (1, 0)) # Test building towards enemy works well. assert len(board.find_connected_components(Color.RED)) == 1 assert len(board.find_connected_components(Color.RED)[0]) == 3
def test_placements_must_be_connected(): board = Board() board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 2)) with pytest.raises(ValueError): # distance less than 2 (even if connected) board.build_settlement(Color.RED, 2) with pytest.raises(ValueError): # not connected board.build_settlement(Color.RED, 1) board.build_road(Color.RED, (2, 1)) board.build_settlement(Color.RED, 1)
def test_yield_resources_two_settlements(): board = Board() resource_freqdeck = starting_resource_bank() tile, edge2, node2 = board.map.land_tiles[(0, 0, 0)], (4, 5), 5 if tile.resource is None: # is desert tile, edge2, node2 = board.map.land_tiles[(-1, 0, 1)], (4, 15), 15 board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 4)) board.build_road(Color.RED, edge2) board.build_settlement(Color.RED, node2) payout, depleted = yield_resources(board, resource_freqdeck, tile.number) assert len(depleted) == 0 assert freqdeck_count(payout[Color.RED], tile.resource) >= 2 # type: ignore
def test_roads_must_always_be_connected(): board = Board() board.build_settlement(Color.RED, 3, initial_build_phase=True) with pytest.raises(ValueError): # not connected to settlement board.build_road(Color.RED, (2, 1)) board.build_road(Color.RED, (3, 2)) board.build_road(Color.RED, (2, 1)) board.build_road(Color.RED, (3, 4))
def test_building_into_enemy_doesnt_merge_components(): board = Board() board.build_settlement(Color.BLUE, 0, initial_build_phase=True) board.build_settlement(Color.RED, 16, initial_build_phase=True) board.build_settlement(Color.RED, 6, initial_build_phase=True) board.build_road(Color.RED, (16, 5)) board.build_road(Color.RED, (5, 0)) board.build_road(Color.RED, (6, 1)) board.build_road(Color.RED, (1, 0)) assert len(board.find_connected_components(Color.RED)) == 2
def test_cut_but_not_disconnected(): board = Board() board.build_settlement(Color.RED, 0, initial_build_phase=True) board.build_road(Color.RED, (0, 1)) board.build_road(Color.RED, (1, 2)) board.build_road(Color.RED, (2, 3)) board.build_road(Color.RED, (3, 4)) board.build_road(Color.RED, (4, 5)) board.build_road(Color.RED, (5, 0)) board.build_road(Color.RED, (3, 12)) assert (max( map(lambda path: len(path), board.continuous_roads_by_player(Color.RED))) == 7) assert len(board.find_connected_components(Color.RED)) == 1 board.build_settlement(Color.BLUE, 2, initial_build_phase=True) assert len(board.find_connected_components(Color.RED)) == 1 assert (max( map(lambda path: len(path), board.continuous_roads_by_player(Color.RED))) == 6)
def test_cant_use_enemy_roads_to_connect(): board = Board() board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 2)) board.build_settlement(Color.BLUE, 1, initial_build_phase=True) board.build_road(Color.BLUE, (1, 2)) board.build_road(Color.BLUE, (0, 1)) board.build_road(Color.BLUE, (0, 20)) # north out of center tile nodes = board.buildable_node_ids(Color.RED) assert len(nodes) == 0 nodes = board.buildable_node_ids(Color.BLUE) assert len(nodes) == 1
def test_triple_longest_road_tie(): board = Board() board.build_settlement(Color.RED, 3, True) board.build_road(Color.RED, (3, 2)) board.build_road(Color.RED, (2, 1)) board.build_road(Color.RED, (1, 0)) board.build_road(Color.RED, (0, 5)) board.build_road(Color.RED, (5, 4)) board.build_road(Color.RED, (3, 4)) board.build_settlement(Color.BLUE, 24, True) board.build_road(Color.BLUE, (24, 25)) board.build_road(Color.BLUE, (25, 26)) board.build_road(Color.BLUE, (26, 27)) board.build_road(Color.BLUE, (27, 8)) board.build_road(Color.BLUE, (8, 7)) board.build_road(Color.BLUE, (7, 24)) board.build_settlement(Color.WHITE, 17, True) board.build_road(Color.WHITE, (18, 17)) board.build_road(Color.WHITE, (17, 39)) board.build_road(Color.WHITE, (39, 41)) board.build_road(Color.WHITE, (41, 42)) board.build_road(Color.WHITE, (42, 40)) board.build_road(Color.WHITE, (40, 18)) assert board.road_color is Color.RED assert board.road_length == 6 assert board.road_lengths == {Color.RED: 6, Color.BLUE: 6, Color.WHITE: 6}
def test_many_buildings(): board = Board() board.build_settlement(Color.ORANGE, 7, True) board.build_settlement(Color.ORANGE, 12, True) board.build_road(Color.ORANGE, (6, 7)) board.build_road(Color.ORANGE, (7, 8)) board.build_road(Color.ORANGE, (8, 9)) board.build_road(Color.ORANGE, (8, 27)) board.build_road(Color.ORANGE, (26, 27)) board.build_road(Color.ORANGE, (9, 10)) board.build_road(Color.ORANGE, (10, 11)) board.build_road(Color.ORANGE, (11, 12)) board.build_road(Color.ORANGE, (12, 13)) board.build_road(Color.ORANGE, (13, 34)) assert len(board.find_connected_components(Color.ORANGE)) == 1 board.build_settlement(Color.WHITE, 30, True) board.build_road(Color.WHITE, (29, 30)) board.build_road(Color.WHITE, (10, 29)) board.build_road(Color.WHITE, (28, 29)) board.build_road(Color.WHITE, (27, 28)) board.build_settlement(Color.WHITE, 10) # cut board.build_road(Color.WHITE, (30, 31)) board.build_road(Color.WHITE, (31, 32)) board.build_settlement(Color.WHITE, 32) board.build_road(Color.WHITE, (11, 32)) board.build_road(Color.WHITE, (32, 33)) board.build_road(Color.WHITE, (33, 34)) board.build_settlement(Color.WHITE, 34) board.build_road(Color.WHITE, (34, 35)) board.build_road(Color.WHITE, (35, 36)) board.build_settlement(Color.WHITE, 41, True) board.build_city(Color.WHITE, 41) board.build_road(Color.WHITE, (41, 42)) board.build_road(Color.WHITE, (40, 42)) board.build_settlement(Color.WHITE, 27) # cut assert len(board.find_connected_components(Color.WHITE)) == 2 assert len(board.find_connected_components(Color.ORANGE)) == 3
def test_longest_road_simple(): board = Board() # Place initial settlements. board.build_settlement(Color.RED, 0, initial_build_phase=True) board.build_road(Color.RED, (0, 1)) board.build_settlement(Color.BLUE, 24, initial_build_phase=True) board.build_road(Color.BLUE, (24, 25)) board.build_settlement(Color.BLUE, 26, initial_build_phase=True) board.build_road(Color.BLUE, (25, 26)) board.build_settlement(Color.RED, 2, initial_build_phase=True) board.build_road(Color.RED, (1, 2)) assert board.road_color is None assert board.road_lengths == {Color.RED: 2, Color.BLUE: 2} board.build_road(Color.RED, (2, 3)) board.build_road(Color.RED, (3, 4)) board.build_road(Color.RED, (4, 5)) assert board.road_color is Color.RED assert board.road_length == 5 assert board.road_lengths == {Color.RED: 5, Color.BLUE: 2}
def test_longest_road_tie(): board = Board() # Place initial settlements. board.build_settlement(Color.RED, 0, initial_build_phase=True) board.build_road(Color.RED, (0, 1)) board.build_settlement(Color.BLUE, 24, initial_build_phase=True) board.build_road(Color.BLUE, (24, 25)) board.build_settlement(Color.BLUE, 26, initial_build_phase=True) board.build_road(Color.BLUE, (25, 26)) board.build_settlement(Color.RED, 2, initial_build_phase=True) board.build_road(Color.RED, (1, 2)) assert board.road_color is None assert board.road_lengths == {Color.RED: 2, Color.BLUE: 2} board.build_road(Color.RED, (2, 3)) board.build_road(Color.RED, (3, 4)) board.build_road(Color.RED, (4, 5)) board.build_road(Color.BLUE, (26, 27)) board.build_road(Color.BLUE, (27, 28)) board.build_road(Color.BLUE, (28, 29)) assert (board.road_color is Color.RED ) # even if blue also has 5-road. red had it first assert board.road_length == 5 assert board.road_lengths == {Color.RED: 5, Color.BLUE: 5} board.build_road(Color.BLUE, (29, 30)) assert board.road_color is Color.BLUE assert board.road_length == 6 assert board.road_lengths == {Color.RED: 5, Color.BLUE: 6}
def test_connected_components(): board = Board() assert board.find_connected_components(Color.RED) == [] # Simple test: roads stay at component, disconnected settlement creates new board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 2)) assert len(board.find_connected_components(Color.RED)) == 1 assert len(board.find_connected_components(Color.RED)[0]) == 2 # This is just to be realistic board.build_settlement(Color.BLUE, 13, initial_build_phase=True) board.build_road(Color.BLUE, (13, 14)) board.build_settlement(Color.BLUE, 37, initial_build_phase=True) board.build_road(Color.BLUE, (37, 14)) board.build_settlement(Color.RED, 0, initial_build_phase=True) board.build_road(Color.RED, (0, 1)) assert len(board.find_connected_components(Color.RED)) == 2 assert len(board.find_connected_components(Color.RED)[0]) == 2 assert len(board.find_connected_components(Color.RED)[1]) == 2 # Merging subcomponents board.build_road(Color.RED, (1, 2)) assert len(board.find_connected_components(Color.RED)) == 1 assert len(board.find_connected_components(Color.RED)[0]) == 4 board.build_road(Color.RED, (3, 4)) board.build_road(Color.RED, (4, 15)) board.build_road(Color.RED, (15, 17)) assert len(board.find_connected_components(Color.RED)) == 1 # Enemy cutoff board.build_road(Color.BLUE, (14, 15)) board.build_settlement(Color.BLUE, 15) assert len(board.find_connected_components(Color.RED)) == 2
def test_three_connected_components_bc_enemy_cut_road(): board = Board() # Initial Building Phase of 2 players: board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 4)) board.build_settlement(Color.BLUE, 15, initial_build_phase=True) board.build_road(Color.BLUE, (15, 4)) board.build_settlement(Color.BLUE, 34, initial_build_phase=True) board.build_road(Color.BLUE, (34, 13)) board.build_settlement(Color.RED, 1, initial_build_phase=True) board.build_road(Color.RED, (0, 1)) # Extend road in a risky way board.build_road(Color.RED, (5, 0)) board.build_road(Color.RED, (5, 16)) # Plow </3 board.build_road(Color.BLUE, (5, 4)) board.build_settlement(Color.BLUE, 5) components = board.find_connected_components(Color.RED) assert len(components) == 3
def test_complicated_road(): # classic 8-like roads board = Board() # Place initial settlements. board.build_settlement(Color.RED, 0, initial_build_phase=True) board.build_road(Color.RED, (0, 1)) board.build_settlement(Color.BLUE, 24, initial_build_phase=True) board.build_road(Color.BLUE, (24, 25)) board.build_settlement(Color.BLUE, 26, initial_build_phase=True) board.build_road(Color.BLUE, (25, 26)) board.build_settlement(Color.RED, 2, initial_build_phase=True) board.build_road(Color.RED, (1, 2)) board.build_road(Color.RED, (2, 3)) board.build_road(Color.RED, (3, 4)) board.build_road(Color.RED, (4, 5)) board.build_road(Color.RED, (0, 5)) board.build_road(Color.RED, (1, 6)) board.build_road(Color.RED, (6, 7)) board.build_road(Color.RED, (7, 8)) board.build_road(Color.RED, (8, 9)) board.build_road(Color.RED, (2, 9)) assert board.road_color is Color.RED assert board.road_length == 11 assert board.road_lengths == {Color.RED: 11, Color.BLUE: 2} board.build_road(Color.RED, (8, 27)) assert board.road_color is Color.RED assert board.road_length == 11 assert board.road_lengths == {Color.RED: 11, Color.BLUE: 2}
def test_buildable_edges(): board = Board() board.build_settlement(Color.RED, 3, initial_build_phase=True) board.build_road(Color.RED, (3, 4)) buildable = board.buildable_edges(Color.RED) assert len(buildable) == 4