Joffrey Thomas
add chess
bea46e9
import os
import uuid
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from .chess_server import start_game as m_start_game, player_move as m_player_move, ai_move as m_ai_move, board as m_board, legal_moves as m_legal_moves, status as m_status, pgn as m_pgn
BASE_DIR = os.path.dirname(__file__)
TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")
STATIC_DIR = os.path.join(BASE_DIR, "static")
app = FastAPI()
app.mount("/static", StaticFiles(directory=STATIC_DIR), name="static")
templates = Jinja2Templates(directory=TEMPLATES_DIR)
# Simple room registry for UI convenience (MCP state keyed by room_id in chess_server)
rooms = {}
def generate_room_id() -> str:
return uuid.uuid4().hex[:8]
@app.get("/", response_class=HTMLResponse)
def home(request: Request):
base_path = request.scope.get('root_path', '')
return templates.TemplateResponse("index.html", {"request": request, "rooms": rooms, "base_path": base_path})
@app.post("/create_room")
def create_room(request: Request):
# Choose a new room id and redirect to room page; player picks color there
room_id = generate_room_id()
rooms[room_id] = {"id": room_id}
return RedirectResponse(url=f"{request.scope.get('root_path', '')}/room/{room_id}", status_code=303)
@app.get("/room/{room_id}", response_class=HTMLResponse)
def room_page(room_id: str, request: Request):
base_path = request.scope.get('root_path', '')
# Fetch board (this also ensures MCP game exists lazily)
state = m_board(session_id=room_id)
if room_id not in rooms:
rooms[room_id] = {"id": room_id}
return templates.TemplateResponse("room.html", {"request": request, "room_id": room_id, "state": state, "base_path": base_path})
# --- API: Map to MCP tools ---
@app.post("/room/{room_id}/start")
def api_start(room_id: str, payload: dict | None = None):
player_color = (payload or {}).get("player_color", "white")
state = m_start_game(session_id=room_id, player_color=player_color)
return JSONResponse(state)
@app.post("/room/{room_id}/player_move")
def api_player_move(room_id: str, payload: dict):
if not payload or "move" not in payload:
raise HTTPException(status_code=400, detail="Missing 'move' in body")
result = m_player_move(move=payload["move"], session_id=room_id)
if "error" in result:
raise HTTPException(status_code=400, detail=result["error"])
return JSONResponse(result)
@app.post("/room/{room_id}/ai_move")
def api_ai_move(room_id: str):
result = m_ai_move(session_id=room_id)
return JSONResponse(result)
@app.get("/room/{room_id}/board")
def api_board(room_id: str):
return JSONResponse(m_board(session_id=room_id))
@app.get("/room/{room_id}/legal_moves")
def api_legal_moves(room_id: str):
return JSONResponse(m_legal_moves(session_id=room_id))
@app.get("/room/{room_id}/status")
def api_status(room_id: str):
return JSONResponse(m_status(session_id=room_id))
@app.get("/room/{room_id}/pgn")
def api_pgn(room_id: str):
return JSONResponse({"pgn": m_pgn(session_id=room_id)})