File size: 8,785 Bytes
69373e6
 
 
 
 
c903325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
from .board import Board
from .tile import Tile
from .point import Point
from .tile_type import TileType
from .harbor import Harbor, HarborType

import math
import random

# The default, tileagonal board filled with random tiles and tokens
class DefaultBoard(Board):

    def __init__(self, game):
        super(DefaultBoard, self).__init__(game)

        # Set tiles
        tile_deck = Board.get_shuffled_tile_deck()
        token_deck = Board.get_shuffled_tile_nums()
        temp_tiles = []
        for r in range(5):
            temp_tiles.append([])
            for i in range([3, 4, 5, 4, 3][r]):
                # Add a tile
                new_tile = Tile(type=tile_deck.pop(), token_num=None, position=[r, i], points=[])
                temp_tiles[-1].append(new_tile)
                # Remove the token if it is the desert
                if new_tile.type == TileType.Desert:
                    self.robber = [r, i]
                else:
                    new_tile.token_num = token_deck.pop()

        self.tiles = tuple(map(lambda x: tuple(x), temp_tiles))

        # Add points
        temp_points = []
        for r in range(6):
            temp_points.append([])
            for i in range([7, 9, 11, 11, 9, 7][r]):
                point = Point(tiles=[], position=[r, i])
                temp_points[-1].append(point)
                # Set point/tile relations
                for pos in DefaultBoard.get_tile_indexes_for_point(r, i):
                    point.tiles.append(self.tiles[pos[0]][pos[1]])
                    self.tiles[pos[0]][pos[1]].points.append(point)


        self.points = tuple(map(lambda x: tuple(x), temp_points))
        # Set the connected points for each point
        # Must be done after initializing each point so that the point object exists
        for r in self.points:
            for p in r:
                p.connected_points = self.get_connected_points(p.position[0], p.position[1])
        # adds a harbor for each points in the pattern 2 3 2 2 3 2 etc
        outside_points = DefaultBoard.get_outside_points()
        # the pattern of spaces between harbors
        pattern = [1, 2, 1]
        # the current index of pattern
        index = 0
        # the different types of harbors
        harbor_types = [
            HarborType.Wood,
            HarborType.Brick,
            HarborType.Ore,
            HarborType.Wheat,
            HarborType.Sheep,
            HarborType.Any,
            HarborType.Any,
            HarborType.Any,
            HarborType.Any
        ]
        # Shuffles the harbors
        random.shuffle(harbor_types)
        # Run loop until harbor_types is empty
        while harbor_types:
            # Create a new harbor
            p_one = outside_points.pop()
            p_two = outside_points.pop()
            harbor = Harbor(
                point_one = self.points[p_one[0]][p_one[1]],
                point_two = self.points[p_two[0]][p_two[1]],
                type = harbor_types.pop())
            # Add it to harbors
            self.harbors.append(harbor)
            # Remove the unused points from outside_points
            for _ in range(pattern[index % len(pattern)]):
                outside_points.pop()
            # Use next pattern value for number of points inbetween next time
            index += 1

        # puts the robber on the desert tile to start
        for r in range(len(temp_tiles)):
            # checks if this row has the desert
            if temp_tiles[r].count(TileType.Desert) > 0:
                # places the robber
                self.robber = [r, temp_tiles[r].index(TileType.Desert)]

    # Returns the indexes of the tiles connected to a certain points
    # on the default, tileagonal Catan board
    @staticmethod
    def get_tile_indexes_for_point(r, i):
        # the indexes of the tiles
        tile_indexes = []
        # Points on a tileagonal board
        points = [
            [None] * 7,
            [None] * 9,
            [None] * 11,
            [None] * 11,
            [None] * 9,
            [None] * 7
        ]
        # gets the adjacent tiles differently depending on whether the point is in the top or the bottom
        if r < len(points) / 2:
            # gets the tiles below the point ------------------

            # adds the tiles to the right
            if i < len(points[r]) - 1:
                tile_indexes.append([r, math.floor(i / 2)])

            # if the index is even, the number is between two tiles
            if i % 2 == 0 and i > 0:
                tile_indexes.append([r, math.floor(i / 2) - 1])

            # gets the tiles above the point ------------------

            if r > 0:
                # gets the tile to the right
                if i > 0 and i < len(points[r]) - 2:
                    tile_indexes.append([r - 1, math.floor((i - 1) / 2)])

                # gets the tile to the left
                if i % 2 == 1 and i < len(points[r]) - 1 and i > 1:
                    tile_indexes.append([r - 1, math.floor((i - 1) / 2) - 1])

        else:

            # adds the below -------------

            if r < len(points) - 1:
                # gets the tile to the right or directly below
                if i < len(points[r]) - 2 and i > 0:
                    tile_indexes.append([r, math.floor((i - 1) / 2)])

                # gets the tile to the left
                if i % 2 == 1 and i > 1 and i < len(points[r]):
                    tile_indexes.append([r, math.floor((i - 1) / 2 - 1)])

            # gets the tiles above ------------

            # gets the tile above and to the right or directly above
            if i < len(points[r]) - 1:
                tile_indexes.append([r - 1, math.floor(i / 2)])

            # gets the tile to the left
            if i > 1 and i % 2 == 0:
                tile_indexes.append([r - 1, math.floor((i - 1) / 2)])

        return tile_indexes

    # gets the points that are connected to the point given
    def get_connected_points(self, r, i):
        to_return = []
        # Get the point to the left and the right
        if i > 0:
            to_return.append(self.points[r][i - 1])

        if i < len(self.points[r]) - 1:
            to_return.append(self.points[r][i + 1])

        # Get the point above and below
        # First, if the point is in the center two rows, the connected point
        # is either directly above/below this point
        if r == 2 and i % 2 == 0:
            to_return.append(self.points[r + 1][i])
        elif r == 3 and i % 2 == 0:
            to_return.append(self.points[r - 1][i])
        # If the point is not in the 2 center rows, the point will have an offset
        elif r < len(self.points) / 2:
            if i % 2 == 0:
                to_return.append(self.points[r + 1][i + 1])
            elif r > 0 and i > 0:
                to_return.append(self.points[r - 1][i - 1])
        else:
            if i % 2 == 0:
                to_return.append(self.points[r - 1][i + 1])
            elif r < len(self.points) - 1 and i > 0:
                to_return.append(self.points[r + 1][i - 1])
        return to_return

    # Get the points along the outside of the board, in clockwise order
    @staticmethod
    def get_outside_points():
        # The lengths of each row of points on the board
        row_lengths = [
            7,
            9,
            11,
            11,
            9,
            7
        ]
        # The points on the bottom
        bottom = list(map(lambda x: [len(row_lengths) - 1, x], range(row_lengths[-1])))
        # The points on the top
        top = list(map(lambda x: [0, x], range(row_lengths[0])))
        # adds all the points on the right and left
        right = []
        left = []
        for r in range(1, len(row_lengths) - 1):
            # Get the last two and first two points on this row
            last_two = list(map(lambda x: [r, x], range(row_lengths[r])[-2:]))
            first_two = list(map(lambda x: [r, x], reversed(range(2))))
            # If the points are one the bottom half of the board, reverse them
            if r > (len(row_lengths) - 1) / 2:
                last_two = list(reversed(last_two))
                first_two = list(reversed(first_two))
            # Add points to right and left
            right.extend(last_two)
            left.extend(first_two)

        # Put different sides of points in order
        # bottom and left are reversed since we want to count those points in reverse order
        # to make sure we go in clockwise order
        outside_points = []
        outside_points.extend(top)
        outside_points.extend(right)
        outside_points.extend(reversed(bottom))
        outside_points.extend(reversed(left))
        # Return them
        return outside_points