Example #1
0
def _make_bot_move(game_mod, bot_object, board, move_list, token, state):
    bot_mod = loader.create_module_from_str("bot", bot_object.code)
    fn = bot_mod.get_next_move
    param_list = runner.get_param_list(fn)
    all_args = {
        "board": board,
        "move_list": [],
        "token": token,
        "state": state
    }
    args = {
        param: value
        for param, value in all_args.items() if param in param_list
    }
    rv = fn(**args)
    try:
        bot_move, state = rv
        print("Got a state")
    except TypeError:
        bot_move, state = rv, None
        print("Got no state")
    move_list.append(bot_move)
    boards = runner.rerun_game(game_mod, move_list)
    board = boards[-1]
    return (board, move_list, state)
Example #2
0
 def test_rerun_game(self):
     move_list = [0, 1, 2, 3, 4, 5, 6]
     boards = rerun_game(game, move_list)
     expected_boards = [
         [".", ".", ".", ".", ".", ".", ".", ".", "."],
         ["X", ".", ".", ".", ".", ".", ".", ".", "."],
         ["X", "O", ".", ".", ".", ".", ".", ".", "."],
         ["X", "O", "X", ".", ".", ".", ".", ".", "."],
         ["X", "O", "X", "O", ".", ".", ".", ".", "."],
         ["X", "O", "X", "O", "X", ".", ".", ".", "."],
         ["X", "O", "X", "O", "X", "O", ".", ".", "."],
         ["X", "O", "X", "O", "X", "O", "X", ".", "."],
     ]
     self.assertEqual(boards, expected_boards)
Example #3
0
def game(request, game_id):
    game = get_object_or_404(Game, id=game_id)

    game_mod = loader.load_module_from_dotted_path(settings.BOTANY_GAME_MODULE)
    boards = runner.rerun_game(game_mod, game.move_list())

    rendered_boards = [game_mod.render_html(board) for board in boards]

    ctx = {
        "game": game,
        "bot1": game.bot1,
        "bot2": game.bot2,
        "boards": rendered_boards,
        "styles": game_mod.html_styles,
    }
    return render(request, "botany/game.html", ctx)
Example #4
0
def play(request, bot1_id, bot2_id):
    if bot1_id == "human":
        assert bot2_id is not "human"
    else:
        bot = get_object_or_404(Bot, id=bot1_id)
        title = f"human vs {bot.name_and_version()}"

    if bot2_id == "human":
        assert bot1_id is not "human"
    else:
        bot = get_object_or_404(Bot, id=bot2_id)
        title = f"{bot.name_and_version()} vs human"

    game_mod = loader.load_module_from_dotted_path(settings.BOTANY_GAME_MODULE)

    if request.POST:
        moves = request.POST["moves"]
        move_list = [int(m) for m in moves]
        next_move = int(request.POST["next_move"])

        token = game_mod.TOKENS[len(moves) % 2]
        other_token = game_mod.TOKENS[(len(moves) + 1) % 2]

        boards = runner.rerun_game(game_mod, move_list)
        board = boards[-1]
        assert game_mod.is_valid_move(board, next_move)

        game_mod.make_move(board, next_move, token)
        move_list.append(next_move)
        state = None

        if not game_mod.check_winner(board):
            bot_mod = loader.create_module_from_str("bot", bot.code)
            fn = bot_mod.get_next_move
            param_list = runner.get_param_list(fn)
            if "state" in request.POST:
                state = json.loads(b64decode(request.POST["state"]))

            all_args = {
                "board": board,
                "move_list": move_list,
                "token": other_token,
                "state": state,
            }

            args = {
                param: value for param, value in all_args.items() if param in param_list
            }

            rv = fn(**args)
            try:
                next_next_move, state = rv
                print("Got a state")
            except TypeError:
                next_next_move, state = rv, None
                print("Got no state")
            move_list.append(next_next_move)

        moves = "".join(str(m) for m in move_list)

        qs_dict = {"moves": moves}
        if state is not None:
            qs_dict["state"] = b64encode(json.dumps(state).encode("utf8"))

        qs = urllib.parse.urlencode(qs_dict)
        return redirect(reverse("play", args=[bot1_id, bot2_id]) + f"?{qs}")

    if request.GET.get("moves"):
        moves = request.GET["moves"]
        state = request.GET.get("state")
        move_list = [int(m) for m in request.GET["moves"]]
        boards = runner.rerun_game(game_mod, move_list)
        board = boards[-1]

        if game_mod.check_winner(board):
            token = game_mod.TOKENS[(len(moves) + 1) % 2]
            result = f"{token} wins"
        elif len(game_mod.available_moves(board)) == 0:
            result = "draw"
        else:
            result = None
    else:
        moves = ""
        board = game_mod.new_board()
        state = None
        result = None

    ctx = {
        "title": title,
        "result": result,
        "moves": moves,
        "state": state,
        "board": game_mod.render_html(board),
        "styles": game_mod.html_styles,
    }

    return render(request, "botany/play.html", ctx)
Example #5
0
def play(request, bot1_id, bot2_id):
    if bot1_id == "human":
        assert bot2_id is not "human"
    else:
        bot = get_object_or_404(Bot, id=bot1_id)
        title = f"human vs {bot.name_and_version()}"

    if bot2_id == "human":
        assert bot1_id is not "human"
    else:
        bot = get_object_or_404(Bot, id=bot2_id)
        title = f"{bot.name_and_version()} vs human"

    game_mod = loader.load_module_from_dotted_path(settings.BOTANY_GAME_MODULE)

    # POST request means human made a move, then bot plays.
    if request.POST:
        moves = request.POST["moves"]
        move_list = [int(m) for m in moves]
        next_move = int(request.POST["next_move"])

        token = game_mod.TOKENS[len(moves) % 2]
        other_token = game_mod.TOKENS[(len(moves) + 1) % 2]

        boards = runner.rerun_game(game_mod, move_list)
        board = boards[-1]
        assert game_mod.is_valid_move(board, next_move)

        game_mod.make_move(board, next_move, token)
        move_list.append(next_move)
        state = None

        # If the human move was not a winning move, it is time for the bot to play.
        if not game_mod.check_winner(board):
            if "state" in request.POST:
                state = json.loads(b64decode(request.POST["state"]))
            board, move_list, state = _make_bot_move(game_mod, bot, board,
                                                     move_list, other_token,
                                                     state)

        moves = "".join(str(m) for m in move_list)

        qs_dict = {"moves": moves}
        if state is not None:
            qs_dict["state"] = b64encode(json.dumps(state).encode("utf8"))

        qs = urllib.parse.urlencode(qs_dict)
        return redirect(reverse("play", args=[bot1_id, bot2_id]) + f"?{qs}")

    # GET request containing moves creating a game based on the moves in the request
    if request.GET.get("moves"):
        moves = request.GET["moves"]
        state = request.GET.get("state")
        move_list = [int(m) for m in request.GET["moves"]]
        boards = runner.rerun_game(game_mod, move_list)
        board = boards[-1]

        if game_mod.check_winner(board):
            token = game_mod.TOKENS[(len(moves) + 1) % 2]
            result = f"{token} wins"
        elif len(game_mod.available_moves(board)) == 0:
            result = "draw"
        else:
            result = None
    # If not a POST of a GET containing moves, this is a new game:
    #  - need to create the board and other variables
    #  - have the bot make his first move (if he was the first player)
    else:
        moves = ""
        board = game_mod.new_board()
        state = None
        result = None
        if bot1_id != "human":
            board, move_list, state = _make_bot_move(game_mod, bot, board, [],
                                                     "X", state)
            moves = "".join(str(m) for m in move_list)

    ctx = {
        "title": title,
        "result": result,
        "moves": moves,
        "state": state,
        "board": game_mod.render_html(board),
        "styles": game_mod.html_styles,
    }

    return render(request, "botany/play.html", ctx)