@@ -92,6 +92,8 @@ def _set_data(self, x, y, value):
9292 self ._board_data [y * self .grid_width + x ] = value
9393
9494 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
9597 return self ._board_data [y * self .grid_width + x ]
9698
9799 def _set_board (self , x , y , value ):
@@ -102,6 +104,8 @@ def _set_board(self, x, y, value):
102104 def _get_board (self , x , y ):
103105 if not isinstance (self .game_board , TileGrid ):
104106 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
105109 return self .game_board [x , y ] # pylint: disable=unsubscriptable-object
106110
107111 def _compute_counts (self ):
@@ -165,6 +169,77 @@ def square_flagged(self, coords):
165169 break
166170 return True
167171
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+
168243 def square_clicked (self , coords ):
169244 x , y = coords
170245
@@ -178,7 +253,7 @@ def square_clicked(self, coords):
178253 if self ._start_time is None :
179254 self ._start_time = ticks_ms ()
180255
181- if self ._get_board (x , y ) != FLAG :
256+ if self ._get_board (x , y ) not in ( FLAG , None ) :
182257 under_the_tile = self ._get_data (x , y )
183258 if under_the_tile == MINE :
184259 self ._set_data (x , y , MINE_CLICKED )
@@ -215,7 +290,9 @@ def check_for_win(self):
215290 # first make sure everything has been explored and decided
216291 for x in range (self .grid_width ):
217292 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 :
219296 return None # still ignored or question squares
220297 # then check for mistagged bombs
221298 for x in range (self .grid_width ):
0 commit comments