@@ -92,6 +92,8 @@ def _set_data(self, x, y, value):
92
92
self ._board_data [y * self .grid_width + x ] = value
93
93
94
94
def _get_data (self , x , y ):
95
+ if x < 0 or x >= self .grid_width or y < 0 or y >= self .grid_height :
96
+ return None # out of bounds, do nothing
95
97
return self ._board_data [y * self .grid_width + x ]
96
98
97
99
def _set_board (self , x , y , value ):
@@ -102,6 +104,8 @@ def _set_board(self, x, y, value):
102
104
def _get_board (self , x , y ):
103
105
if not isinstance (self .game_board , TileGrid ):
104
106
raise ValueError ("Game board not initialized" )
107
+ if x < 0 or x >= self .grid_width or y < 0 or y >= self .grid_height :
108
+ return None # out of bounds, do nothing
105
109
return self .game_board [x , y ] # pylint: disable=unsubscriptable-object
106
110
107
111
def _compute_counts (self ):
@@ -165,6 +169,77 @@ def square_flagged(self, coords):
165
169
break
166
170
return True
167
171
172
+ def square_chorded (self , coords ):
173
+ if self ._status in (STATUS_WON , STATUS_LOST ):
174
+ return False
175
+
176
+ x , y = coords
177
+ if x < 0 or x >= self .grid_width or y < 0 or y >= self .grid_height :
178
+ return True # out of bounds, do nothing
179
+
180
+ value = self ._get_board (x , y )
181
+
182
+ if value not in (OPEN1 , OPEN2 , OPEN3 , OPEN4 , OPEN5 , OPEN6 , OPEN7 , OPEN8 ):
183
+ return True # Nothing to do if not an open numbered square
184
+
185
+ # Pre-compute valid neighbors
186
+ neighbors = [
187
+ (nx , ny )
188
+ for nx in range (x - 1 , x + 2 )
189
+ for ny in range (y - 1 , y + 2 )
190
+ if (0 <= nx < self .grid_width
191
+ and 0 <= ny < self .grid_height
192
+ and not (nx == x and ny == y ))
193
+ ]
194
+
195
+ # Count flagged neighbors
196
+ flags = sum (1 for nx , ny in neighbors if self ._get_board (nx , ny ) == FLAG )
197
+
198
+ if flags != value :
199
+ return True # not enough flags, do nothing
200
+
201
+ # Uncover all non-flagged neighbors
202
+ for nx , ny in neighbors :
203
+ if self ._get_board (nx , ny ) != FLAG :
204
+ if not self .square_clicked ((nx , ny )):
205
+ return False # lost
206
+
207
+ return True
208
+
209
+ def square_chord_highlight (self , coords , highlight = True ):
210
+ if self ._status in (STATUS_WON , STATUS_LOST ):
211
+ return False
212
+
213
+ x , y = coords
214
+ if x < 0 or x >= self .grid_width or y < 0 or y >= self .grid_height :
215
+ return False # out of bounds, do nothing
216
+
217
+ value = self ._get_board (x , y )
218
+
219
+ if value not in (OPEN1 , OPEN2 , OPEN3 , OPEN4 , OPEN5 , OPEN6 , OPEN7 , OPEN8 ):
220
+ return False # Nothing to do if not an open numbered square
221
+
222
+ # Pre-compute valid neighbors
223
+ neighbors = [
224
+ (nx , ny )
225
+ for nx in range (x - 1 , x + 2 )
226
+ for ny in range (y - 1 , y + 2 )
227
+ if (0 <= nx < self .grid_width
228
+ and 0 <= ny < self .grid_height
229
+ and not (nx == x and ny == y ))
230
+ ]
231
+
232
+ # Highlight all non-flagged squares around here
233
+ for nx , ny in neighbors :
234
+ if highlight :
235
+ if self ._get_board (nx , ny ) == BLANK :
236
+ self ._set_board (nx , ny ,MINE_QUESTION_OPEN )
237
+ else :
238
+ if self ._get_board (nx , ny ) == MINE_QUESTION_OPEN :
239
+ self ._set_board (nx , ny , BLANK )
240
+
241
+ return True
242
+
168
243
def square_clicked (self , coords ):
169
244
x , y = coords
170
245
@@ -178,7 +253,7 @@ def square_clicked(self, coords):
178
253
if self ._start_time is None :
179
254
self ._start_time = ticks_ms ()
180
255
181
- if self ._get_board (x , y ) != FLAG :
256
+ if self ._get_board (x , y ) not in ( FLAG , None ) :
182
257
under_the_tile = self ._get_data (x , y )
183
258
if under_the_tile == MINE :
184
259
self ._set_data (x , y , MINE_CLICKED )
@@ -215,7 +290,9 @@ def check_for_win(self):
215
290
# first make sure everything has been explored and decided
216
291
for x in range (self .grid_width ):
217
292
for y in range (self .grid_height ):
218
- if self ._get_board (x , y ) == BLANK or self ._get_board (x , y ) == MINE_QUESTION :
293
+ if self ._get_board (x , y ) == BLANK or \
294
+ self ._get_board (x , y ) == MINE_QUESTION or \
295
+ self ._get_board (x , y ) == MINE_QUESTION_OPEN :
219
296
return None # still ignored or question squares
220
297
# then check for mistagged bombs
221
298
for x in range (self .grid_width ):
0 commit comments