def right_click(x, y, game): """ Set/increment/clear the flag in this cell. """ flag_map = DBSession.query(models.PlayerMap).filter_by( game_id=game.id, map_type=const.PlayerMapType.FLAG).first() # Get the FlagMapData, if it exists flag_data = DBSession.query(models.PlayerMapData).filter_by( player_map_id=flag_map.id, row_num=x, col_num=y).first() if flag_data is None: # UNCLICKED --> FLAG recorded_flag = models.PlayerMapData( player_map_id=flag_map.id, row_num=x, col_num=y, value=const.PlayerMapDataValue.FLAG) DBSession.add(recorded_flag) value = const.PlayerMapDataValue.FLAG else: if flag_data.value == const.PlayerMapDataValue.FLAG: # FLAG --> UNSURE value = const.PlayerMapDataValue.UNSURE flag_data.value = value DBSession.add(flag_data) else: # UNSURE --> UNCLICKED value = const.CellStates.UNCLICKED DBSession.delete(flag_data) DBSession.flush() return (value, game)
def post(self): """ Creates a new Game, MineMap, and PlayerMaps. """ # Create a MineMap mine_matrix = MineMatrix(const.DEFAULT_HEIGHT, width=const.DEFAULT_WIDTH, mine_number=const.DEFAULT_MINES) mine_map = mine_matrix.to_model() DBSession.add(mine_map) DBSession.flush() # Create a Game and PlayerMaps for it game = models.Game(mine_map=mine_map.id) game.player_maps = [ models.PlayerMap(map_type=const.PlayerMapType.CLICK), models.PlayerMap(map_type=const.PlayerMapType.FLAG), ] DBSession.add(game) DBSession.flush() return HTTPFound(location=self.request.route_url('view_game', game_id=game.id))
def cascade_reveal(start_x, start_y, mine_matrix, click_map_id): """ Returns the list of dicts, representing the values to reveal. """ # Where the revealed values go. The position records the x, y coordinates # Faster lookup than using the reveal list of dicts placeholder = Matrix(mine_matrix.height, width=mine_matrix.width, init_value=None) blank_spaces = [(start_x, start_y)] # queue of spaces to explore reveal = [] # Look around each blank space while(blank_spaces): (focus_x, focus_y) = blank_spaces.pop() for x in Matrix._adjacent_indices(focus_x, placeholder.height-1): for y in Matrix._adjacent_indices(focus_y, placeholder.width-1): # Have we already seen this entry? if (x, y) == (focus_x, focus_y) or placeholder[x][y] is not None: continue # skip this entry value = mine_matrix[x][y] # We haven't come across this entry yet, but it still may # already be clicked placeholder[x][y] = value # Check if there's a ClickMap entry for this datapoint click = DBSession.query(models.PlayerMapData).filter_by( player_map_id=click_map_id, row_num=x, col_num=y).first() if click is None: # Save a ClickMap entry for this cell recorded_click = models.PlayerMapData( player_map_id=click_map_id, row_num=x, col_num=y, value=const.PlayerMapDataValue.CLICKED) DBSession.add(recorded_click) reveal.append({'x': x, 'y': y, 'value': value}) # If the value is another blank space, save to look later if value is const.CellStates.CLUE[0]: blank_spaces.append((x, y)) return reveal
def left_click(x, y, click_map, game): reveal = [] # Record a successful click on the Click Map recorded_click = models.PlayerMapData( player_map_id=click_map.id, row_num=x, col_num=y, value=const.PlayerMapDataValue.CLICKED) DBSession.add(recorded_click) mine_map = DBSession.query(models.MineMap).get(game.mine_map) mine_matrix = mine_map.to_matrix() value = mine_matrix[x][y] # If the cell contains a mine, game over if value is const.MineMapDataValue.MINE: # Update game state game.state = const.GameState.LOSE DBSession.add(game) DBSession.flush() return (value, reveal, game) # If a blank space got revealed, time for a cascade reveal if value is const.MineMapDataValue.CLUE[0]: reveal = cascade_reveal(x, y, mine_matrix, click_map.id) DBSession.flush() # Compare the Click matrix to the Win matrix. If the same, the game is won click_map = DBSession.query(models.PlayerMap).filter_by( game_id=game.id, map_type=const.PlayerMapType.CLICK).first() click_matrix = click_map.to_matrix() win_matrix = derive_win_matrix(game) if click_matrix == win_matrix: # Update game state game.state = const.GameState.WIN DBSession.add(game) DBSession.flush() return (value, reveal, game)