Beispiel #1
0
def test_can_fill_whole_board_with_tokens():
    nc, nr = 3, 2
    token = 1
    game = GameBoard(nc, nr)
    for c in range(1, nc + 1):
        for r in range(1, nr + 1):
            assert game.drop_token(c, token)
Beispiel #2
0
def test_winning_condition_detected_for_full_column():
    nc, nr = 4, 4
    token = 1
    game = GameBoard(nc, nr)
    for r in range(1, nr + 1):
        game.drop_token(1, token)
    assert game.check_win(1, 4)
Beispiel #3
0
def test_winning_condition_detected_for_full_row_rfrom_middle():
    nc, nr = 4, 4
    token = 1
    game = GameBoard(nc, nr)
    for c in range(1, nr + 1):
        game.drop_token(c, token)
    assert game.check_win(2, 1)
Beispiel #4
0
def test_apply_all_moves_should_fail():
    nc, nr = 3, 2
    game = GameBoard(nc, nr)
    moves = [
        {
            'token': 1,
            'column': 4
        },
        {
            'token': 2,
            'column': 1
        },
    ]
    assert not game.apply_moves(moves)
Beispiel #5
0
def test_apply_all_moves_should_succeed():
    nc, nr = 4, 2
    game = GameBoard(nc, nr)
    moves = [{
        'token': 1,
        'column': 4
    }, {
        'token': 2,
        'column': 1
    }, {
        'token': 1,
        'column': 1
    }, {
        'token': 2,
        'column': 3
    }]
    expected_board = [[2, 1], [None, None], [2, None], [1, None]]
    assert game.apply_moves(moves)
    assert game.board == expected_board
Beispiel #6
0
def test_dropping_token_to_nonexisting_column_fails():
    nc, nr = 2, 2
    token = 1
    game = GameBoard(nc, nr)
    assert not game.drop_token(nc + 1, token)
Beispiel #7
0
def test_create_board_with_correct_num_cols():
    game = GameBoard(5, 4)
    assert len(game.board) == 5
Beispiel #8
0
def test_cannot_drop_token_into_nonexisting_column():
    nc, nr = 1, 3
    game = GameBoard(nc, nr)
    assert not game.can_drop(0)
Beispiel #9
0
def test_cannot_drop_token_into_full_column():
    nc, nr = 1, 3
    game = GameBoard(nc, nr)
    game.board[0] = [1, 1, 1]
    assert not game.can_drop(1)
Beispiel #10
0
def test_winning_condition_detected_for_main_diagonal_from_bottom():
    nc, nr = 4, 4
    game = GameBoard(nc, nr)
    game.board = [[2, 2, 2, 0], [1, 2, 0, 0], [1, 1, 2, 0], [1, 1, 1, 2]]
    assert game.check_win(1, 1)
Beispiel #11
0
def test_can_drop_token_into_empty_column():
    nc, nr = 1, 3
    game = GameBoard(nc, nr)
    assert game.can_drop(1)
Beispiel #12
0
def test_create_board_with_all_cells_set_to_none():
    nc, nr = 3, 2
    game = GameBoard(nc, nr)
    for c in range(nc):
        for r in range(nr):
            assert not game.board[c][r]
Beispiel #13
0
def test_no_win_detected():
    nc, nr = 4, 4
    game = GameBoard(nc, nr)
    game.board = [[2, 2, 2, 0], [2, 2, 1, 0], [2, 1, 1, 1], [1, 1, 1, 0]]
    assert not game.check_win(4, 3)
Beispiel #14
0
def test_winning_condition_detected_for_secondary_diagonal_from_mid():
    nc, nr = 4, 4
    game = GameBoard(nc, nr)
    game.board = [[2, 2, 2, 1], [2, 2, 1, 0], [2, 1, 1, 1], [1, 1, 0, 0]]
    assert game.check_win(2, 3)
Beispiel #15
0
def test_can_drop_token_into_almost_full_column():
    nc, nr = 1, 3
    game = GameBoard(nc, nr)
    game.board[0] = [1, 1, None]
    assert game.can_drop(1)
Beispiel #16
0
    def post(self, game_id, player_id):
        """
            Input:
                {
                "column" : 2
                }
            Output:
                {
                "move": "{gameId}/moves/{move_number}"
                }
            Status codes:
                • 200 - OK. On success
                • 400 - Malformed input. Illegal move
                • 404 - Game not found or player is not a part of it.
                • 409 - Player tried to post when it’s not their turn.
                • 410 - Game is already in DONE state. (additional requirement, noticed while testing)
        """
        args = moves_post_parser.parse_args()
        request_column = args['column']

        # get the game object
        try:
            g = GameModel.objects(id=game_id).get()
        except (DoesNotExist, ValidationError):
            abort(404, message=f"Game {game_id} not found.")

        # check if player is part of the game
        try:
            p = g.players.get(name=player_id)
        except DoesNotExist:
            abort(
                404,
                message=f"Player {player_id} does not belong to game {game_id}."
            )

        # check if game is already DONE
        if g.state == 'DONE':
            abort(410, message=f"The game is already DONE.")

        # check if it's player's turn
        if g.current_token != p.token:
            abort(
                409,
                message=
                f"Player {player_id} tried to post when it’s not their turn.")

        # build GameBoard
        gb = GameBoard(g.num_cols, g.num_rows)
        players_to_token_map = {p.name: p.token for p in g.players}
        moves = [{
            'token': players_to_token_map[m.player_name],
            'column': m.column
        } for m in g.moves if m.move_type == 'MOVE']
        gb.apply_moves(moves)

        # test if next move is legal
        if not gb.can_drop(request_column):
            abort(
                400,
                message=
                f"Illegal move. Unable to drop token in column {request_column}"
            )

        # apply move and check winning condition
        row = gb.drop_token(request_column, p.token)

        if gb.check_win(request_column, row):
            g.state = 'DONE'
            g.winner = p.name
        # can also be done if board is full
        elif g.moves.count() + 1 == g.num_cols * g.num_rows:
            g.state = 'DONE'
            g.winner = None

        move_number = len(moves) + 1
        g.moves.create(turn=move_number,
                       move_type='MOVE',
                       player_name=p.name,
                       column=request_column)

        token_list = list(players_to_token_map.values())
        g.current_token = get_next_token(token_list, p.token)

        # TODO: possibly use conditional save here, to make sure we're updating the latest tamestamp seen
        g.save()

        # success
        return {
            "move": f"{game_id}/moves/{move_number}"
        }  # TODO: use @marshal_with, fields.Url('endpoint_resource')
Beispiel #17
0
def test_create_board_with_correct_num_rows():
    game = GameBoard(5, 4)
    assert len(game.board[0]) == 4