"""Moonchess practice server: play against the computer. Stateless: the page sends the current position with every request and gets the new position back, so there's no session to lose. The page decides whose turn belongs to the computer; this server only applies moves and picks them. """ import argparse import logging from aiohttp import web from game import Game from server import STATIC_DIR, no_cache from solver import Solver solver = Solver() # solves every position up front; takes about a second async def index(request): return web.FileResponse(STATIC_DIR / "practice.html") async def play(request): """Body: {history, turn, cell} to play `cell`, or {history, turn, accuracy} for a computer move, where accuracy (0-1) is the chance it plays a perfect move. A computer move's reply also says how it was chosen, as computerMove: {cell, how}.""" try: body = await request.json() game = Game.from_history(body["history"], body["turn"]) cell = body.get("cell") accuracy = float(body.get("accuracy", 1)) except (ValueError, KeyError, TypeError, AttributeError): return web.json_response({"error": "Invalid request"}, status=400) computer_move = None if cell is None and game.winner is None: cell, how = solver.choose(game, accuracy) computer_move = {"cell": cell, "how": how} error = game.play(game.turn, cell) if error: return web.json_response({"error": error}, status=400) return web.json_response({**game.to_dict(), "computerMove": computer_move}) def make_app(): app = web.Application(middlewares=[no_cache]) app.router.add_get("/", index) app.router.add_post("/api/play", play) app.router.add_static("/static", STATIC_DIR) return app if __name__ == "__main__": parser = argparse.ArgumentParser(description="Moonchess practice server") parser.add_argument("--host", default="127.0.0.1") parser.add_argument("--port", type=int, default=8081) args = parser.parse_args() logging.basicConfig(level=logging.INFO, format="%(asctime)s %(message)s") web.run_app(make_app(), host=args.host, port=args.port)