-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmove_checker.py
241 lines (199 loc) · 7.78 KB
/
move_checker.py
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
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/python
# -*- coding: utf-8 -*-
import numpy as np
import tile
import pieces
from settings import PIECE_WHITE, PIECE_BLACK
def is_valid_move(state, old_tile, new_tile):
base_move_check = new_tile is not None and new_tile.coords \
!= old_tile.coords and (not new_tile.has_pieces()
or type(state.moving_piece)
is pieces.Beetle)
full_move_check = base_move_check \
and new_tile.is_hive_adjacent(state) \
and move_does_not_break_hive(state, old_tile) \
and (placement_is_allowed(state, old_tile, new_tile)
or state.moving_piece.move_is_valid(state, old_tile,
new_tile))
if state.turn == 1:
if base_move_check and type(new_tile) is tile.Start_Tile:
return True
elif state.turn == 2:
if base_move_check and new_tile.is_hive_adjacent(state):
return True
elif state.turn <= 6 and state.turn >= 3:
if full_move_check and queen_is_on_board(state, old_tile):
return True
elif state.turn == 7 or state.turn == 8:
if full_move_check and move_obeys_queen_by_4(state):
return True
else:
if full_move_check:
return True
return False
def move_does_not_break_hive(state, old_tile):
temp_piece = old_tile.pieces[-1]
old_tile.remove_piece()
tile_list = state.get_tiles_with_pieces()
visited = []
queue = []
visited.append(tile_list[0])
queue.append(tile_list[0])
while queue:
current_tile = queue.pop(0)
for neighbor_tile in [x for x in current_tile.adjacent_tiles
if x.has_pieces()]:
if neighbor_tile not in visited:
visited.append(neighbor_tile)
queue.append(neighbor_tile)
if len(visited) != len(tile_list):
old_tile.add_piece(temp_piece)
return False
else:
old_tile.add_piece(temp_piece)
return True
def queen_is_on_board(state, old_tile):
if old_tile.axial_coords == (99, 99): # placements are ok
return True
else:
# allow move if queen is down for that color
if state.turn % 2 == 1:
color = PIECE_WHITE
else:
color = PIECE_BLACK
for tile in state.get_tiles_with_pieces():
for piece in tile.pieces:
if type(piece) is pieces.Queen and piece.color == color:
return True
return False
def move_obeys_queen_by_4(state):
queens_on_board = []
for tile in state.get_tiles_with_pieces():
for piece in tile.pieces:
if type(piece) is pieces.Queen:
queens_on_board.append(piece)
if len(queens_on_board) == 2:
return True
elif len(queens_on_board) == 0:
if state.turn == 7 and type(state.moving_piece) is pieces.Queen \
and state.moving_piece.color == PIECE_WHITE:
return True
elif state.turn == 8 and type(state.moving_piece) \
is pieces.Queen and state.moving_piece.color == PIECE_BLACK:
return True
elif len(queens_on_board) > 0:
if queens_on_board[0].color == PIECE_WHITE and state.turn == 7:
return True
elif queens_on_board[0].color == PIECE_BLACK and state.turn \
== 7 and type(state.moving_piece) is pieces.Queen:
return True
elif queens_on_board[0].color == PIECE_BLACK and state.turn \
== 8:
return True
elif queens_on_board[0].color == PIECE_WHITE and state.turn \
== 8 and type(state.moving_piece) is pieces.Queen:
return True
return False
def game_is_over(state):
white_surrounded = False
black_surrounded = False
for tile in state.get_tiles_with_pieces():
for piece in tile.pieces:
if type(piece) is pieces.Queen:
adjacent_tiles_with_pieces = [x for x in
tile.adjacent_tiles if x.has_pieces()]
if len(adjacent_tiles_with_pieces) == 6:
if piece.color == PIECE_WHITE:
white_surrounded = True
elif piece.color == PIECE_BLACK:
black_surrounded = True
break
if white_surrounded and black_surrounded:
return True
elif white_surrounded:
state.winner = PIECE_BLACK
return True
elif black_surrounded:
state.winner = PIECE_WHITE
return True
else:
return False
def placement_is_allowed(state, old_tile, new_tile):
if old_tile.axial_coords == (99, 99):
new_tile_adjacents_with_pieces = [x for x in
new_tile.adjacent_tiles if x.has_pieces()]
for tile in new_tile_adjacents_with_pieces:
# placed pieces cannot touch other player's pieces to start
if tile.pieces[-1].color != state.moving_piece.color:
return False
return True
return False
def axial_distance(one, two):
(q1, r1) = one
(q2, r2) = two
return np.sqrt((q1 - q2) * (q1 - q2) + (r1 - r2) * (r1 - r2) + (q1
- q2) * (r1 - r2))
def move_is_not_blocked_or_jump(state, old_tile, new_tile): # check for each pathfinding move
dist = axial_distance(old_tile.axial_coords, new_tile.axial_coords)
old_adjacents_with_pieces = [x for x in old_tile.adjacent_tiles
if x.has_pieces()]
new_adjacents_with_pieces = [x for x in new_tile.adjacent_tiles
if x.has_pieces()]
overlap_tiles = [x for x in new_adjacents_with_pieces if x
in old_adjacents_with_pieces]
if dist == 1 and len(overlap_tiles) == 0: # restrict jumps
return False
elif dist == 1 and len(overlap_tiles) == 2:
return False
else:
return True
def path_exists(state, old_tile, new_tile, spider=False):
temp_piece = old_tile.pieces[-1]
old_tile.remove_piece()
queue = []
queue.append([old_tile])
while queue:
path = queue.pop(0)
current_tile = path[-1]
if spider:
if current_tile == new_tile and len(path) - 1 == 3:
old_tile.add_piece(temp_piece)
return True
elif current_tile == new_tile:
old_tile.add_piece(temp_piece)
return True
for neighbor_tile in [x for x in current_tile.adjacent_tiles
if x.is_hive_adjacent(state)
and not x.has_pieces()]:
if neighbor_tile not in path \
and move_is_not_blocked_or_jump(state, current_tile,
neighbor_tile):
new_path = list(path)
new_path.append(neighbor_tile)
queue.append(new_path)
old_tile.add_piece(temp_piece)
return False
def is_straight_line(old_coords, new_coords):
(q1, r1) = old_coords
(q2, r2) = new_coords
return q1 == q2 or r1 == r2 or -q1 - r1 == -q2 - r2
def player_has_no_moves(state):
if state.turn % 2 == 1:
color = PIECE_WHITE
elif state.turn % 2 == 0:
color = PIECE_BLACK
hive_tiles = state.get_tiles_with_pieces(include_inventory=True)
player_piece_tiles = [tile for tile in hive_tiles
if tile.pieces[-1].color == color]
open_adjacent_tiles = []
for tile in hive_tiles:
hive_adjacent_tiles = tile.adjacent_tiles
for HA_tile in hive_adjacent_tiles:
if HA_tile not in open_adjacent_tiles \
and not HA_tile.has_pieces():
open_adjacent_tiles.append(HA_tile)
for old_tile in player_piece_tiles:
for new_tile in open_adjacent_tiles:
if is_valid_move(state, old_tile, new_tile):
return False
return True