Example #1
0
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)
Example #2
0
def view_game(request):
    """ Returns the game. """
    game = get_game_or_none(request)
    if game is None:
        return HTTPNotFound('No such game.')

    # Get the MineMap
    mine_map = DBSession.query(models.MineMap).get(game.mine_map)
    number_of_mines = DBSession.query(models.MineMapData).filter_by(
        mine_map_id=mine_map.id).count()

    # If the game is over, just send over the full map
    if game.state is const.GameState.IN_PROGRESS:
        grid = derive_grid(mine_map, game.id)
    else:
        grid = mine_map.to_matrix()

    response = {
        'game': True,
        'height': mine_map.height,
        'width': mine_map.width,
        'mines': number_of_mines,
        'state': game.state,
        'grid': grid,
    }
    return response
Example #3
0
def main(argv=sys.argv):
    if len(argv) < 2:
        usage(argv)
    config_uri = argv[1]
    setup_logging(config_uri)
    settings = get_appsettings(config_uri)
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    ModelBase.metadata.create_all(engine)
Example #4
0
def main(global_config, **settings):
    # Set up database stuff
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    ModelBase.metadata.bind = engine

    # Configure
    config = Configurator(settings=settings)
    config.include('pyramid_mako')
    for route in routes:
        config.add_route(route.name, route.url)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.scan()
    return config.make_wsgi_app()
Example #5
0
def derive_grid(mine_map, game_id):
    """ Returns the derived grid (mine matrix * click matrix) """
    mine_matrix = mine_map.to_matrix()
    click_map = DBSession.query(models.PlayerMap).filter_by(
        game_id=game_id, map_type=const.PlayerMapType.CLICK).first()
    click_matrix = click_map.to_matrix()  # Acts as a mask
    return multiply(mine_matrix, click_matrix)
Example #6
0
def get_flags(request):
    game = get_game_or_none(request)
    if game is None:
        return HTTPNotFound('No such game.')

    # Get the FlagMap
    flag_map = DBSession.query(models.PlayerMap).filter_by(
        game_id=game.id, map_type=const.PlayerMapType.FLAG).first()
    # Each entry is either a flag, or a question
    flag_entries = DBSession.query(models.PlayerMapData).filter_by(
        player_map_id=flag_map.id, value=const.PlayerMapDataValue.FLAG).all()
    unsure_entries = DBSession.query(models.PlayerMapData).filter_by(
        player_map_id=flag_map.id, value=const.PlayerMapDataValue.UNSURE).all()

    flags = [[flag.row_num, flag.col_num] for flag in flag_entries]
    unsures = [[unsure.row_num, unsure.col_num] for unsure in unsure_entries]
    return {'flags': flags, 'unsures': unsures}
Example #7
0
 def to_matrix(self):
     from minesweeper.grids.matrices import Matrix
     mine_map = DBSession.query(MineMap).join(Game).filter_by(
         id=self.game_id).first()
     matrix = Matrix(mine_map.height, mine_map.width)
     for entry in self.map_data:
         # Each entry has a value that needs to be inserted into the matrix
         matrix[entry.row_num][entry.col_num] = entry.value
     return matrix
Example #8
0
def update_cell(request):
    """ Executes the provided action upon the cell, returns the state. """
    game = get_game_or_none(request)
    if game is None:
        return HTTPNotFound('No such game.')

    # If the game is not in progress (won or lost) then no action is allowed
    if game.state != const.GameState.IN_PROGRESS:
        return HTTPForbidden('The game is over.')

    try:
        x = int(request.matchdict['x'])
        y = int(request.matchdict['y'])
    except ValueError:
        return HTTPBadRequest('Cell parameters must be integers')

    # If there's a ClickMapData entry, the cell has already been clicked
    # It cannot be updated, so no further action is allowed
    click_map = DBSession.query(models.PlayerMap).filter_by(
        game_id=game.id, map_type=const.PlayerMapType.CLICK).first()
    click_data = DBSession.query(models.PlayerMapData).filter_by(
        player_map_id=click_map.id, row_num=x, col_num=y).first()
    if click_data:
        return HTTPForbidden('The cell has alread been revealed.')

    # Validate action
    try:
        action = int(request.POST.get('action'))
    except ValueError:
        return HTTPBadRequest('Action must be an integer')
    if action not in const.Action.choices():
        return HTTPBadRequest('That action is incorrect.')

    value = None
    reveal = []
    if action is const.Action.LEFT_CLICK:
        value, reveal, game = left_click(x, y, click_map, game)
    elif action is const.Action.RIGHT_CLICK:
        value, game = right_click(x, y, game)

    return {'state': game.state, 'value': value, 'reveal': reveal}
Example #9
0
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
Example #10
0
    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))
Example #11
0
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)
Example #12
0
def get_cell_mine_map_value(x, y, game):
    mine_map = DBSession.query(models.MineMap).get(game.mine_map)
    mine_matrix = mine_map.to_matrix()
    return mine_matrix[x][y]
Example #13
0
def derive_win_matrix(game):
    mine_map = DBSession.query(models.MineMap).get(game.mine_map)
    mine_matrix = mine_map.to_matrix()
    mask = Matrix(mine_matrix.height, width=mine_matrix.width, init_value=0.1)
    return bit_flip(multiply(mine_matrix, mask))
Example #14
0
def get_game_or_none(request):
    game_id = int(request.matchdict['game_id'])
    game = DBSession.query(models.Game).get(game_id)
    return game