Files

201 lines
5.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sys
import os
from pathlib import Path
project_root = Path(__file__).resolve().parent.parent
if str(project_root) not in sys.path:
sys.path.insert(0, str(project_root))
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from pydantic import BaseModel
from typing import List, Optional, Dict, Any
from shortdeck_server.persistence import append_game_history
from shortdeck_server.arena_adapter import ArenaGame
app = FastAPI(title="ShortDeck Poker Server", version="1.0.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
GAME = ArenaGame()
client_path = project_root / "client"
if client_path.exists():
app.mount("/client", StaticFiles(directory=str(client_path)), name="client")
class JoinRequest(BaseModel):
name: str
class JoinResponse(BaseModel):
player_id: int
name: str
class ActionRequest(BaseModel):
player_id: int
action: str # "fold", "call", "raise", "check", "bet"
amount: Optional[int] = None
class ApiResponse(BaseModel):
success: bool = True
message: Optional[str] = None
data: Optional[Dict[str, Any]] = None
error: Optional[str] = None
class GameInfo(BaseModel):
game_id: str
players: List[str]
dealer_index: int
current_turn: int
stage: str
total_pot: int
side_pots: List[Dict[str, Any]]
player_cards: List[str]
board_cards: List[str]
stacks: List[int]
player_states: List[str]
current_pot: List[int]
actions: Dict[str, Any]
class HandStrength(BaseModel):
hand_type: str
description: str
strength: float
cards: List[str]
class Game1v1Response(BaseModel):
success: bool
message: str
human_player_id: Optional[int] = None
ai_player_id: Optional[int] = None
game_id: Optional[str] = None
@app.post("/reset_game")
def reset_game():
global GAME
try:
GAME = ArenaGame()
return {"success": True, "message": "游戏已重置"}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@app.post("/join", response_model=JoinResponse)
def join(req: JoinRequest):
try:
print(f"收到加入请求: {req.name}")
player_id = GAME.join_game(req.name)
print(f"玩家 {req.name} 成功加入ID: {player_id}")
return JoinResponse(player_id=player_id, name=req.name)
except ValueError as e:
print(f"加入游戏失败 - ValueError: {e}")
raise HTTPException(status_code=400, detail=str(e)) from e
except Exception as e:
print(f"加入游戏失败 - Exception: {e}")
import traceback
traceback.print_exc()
raise HTTPException(status_code=500, detail=str(e)) from e
@app.get("/get_game_state")
def get_game_state(player_id):
try:
state = GAME.info(player_id)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
return state
@app.get("/info/{player_id}", response_model=Dict[str, Any])
def get_info(player_id: int):
try:
state = GAME.info(player_id)
return state
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@app.post("/apply_action", response_model=Dict[str, Any])
def apply_action(req: ActionRequest):
try:
result = GAME.apply_action(req.player_id, req.action, req.amount)
append_game_history(GAME.game_id, {"history": GAME.history})
return result
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e)) from e
@app.get("/valid_actions/{player_id}")
def get_valid_actions(player_id: int):
try:
actions = GAME.get_valid_actions(player_id)
return {"valid_actions": actions}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@app.get("/hand_strength/{player_id}")
def get_hand_strength(player_id: int):
try:
strength = GAME.get_hand_strength(player_id)
return strength
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@app.get("/winners")
def get_winners():
try:
winners = GAME.get_winners()
return winners
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@app.post("/reset")
def reset_game(request: dict = None):
try:
global GAME
keep_chips = False
if request and isinstance(request, dict):
keep_chips = request.get("keep_chips", False)
if keep_chips and GAME and len(GAME.agents) >= 2:
GAME.reset_hand_keep_chips()
message = "游戏重置,筹码保持"
else:
GAME = ArenaGame()
message = "游戏完全重置"
return {"ok": True, "message": message}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
@app.get("/hand_complete")
def check_hand_complete():
try:
is_complete = GAME.check_hand_complete()
return {"hand_complete": is_complete}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e
if __name__ == "__main__":
import uvicorn
print(" Starting ShortDeck Poker Server...")
print(" Server will run on http://localhost:8001")
print(" API docs available at http://localhost:8001/docs")
uvicorn.run(
app,
host="127.0.0.1",
port=8001,
reload=False
)