File size: 3,536 Bytes
fcaa899 24bdd7c 5db3b83 fcaa899 f370e63 fcaa899 24bdd7c f370e63 24bdd7c 5db3b83 fcaa899 24bdd7c fcaa899 24bdd7c fcaa899 5db3b83 24bdd7c 5db3b83 77af7b8 5db3b83 fcaa899 24bdd7c 77af7b8 fcaa899 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 24bdd7c 5db3b83 fcaa899 5db3b83 fcaa899 24bdd7c f370e63 24bdd7c fcaa899 f370e63 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
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
import os
from dotenv import load_dotenv
# Choose import based on environment
if os.getenv("DOCKER_ENV"):
from server.game.game_logic import GameState, StoryGenerator, MAX_RADIATION
else:
from game.game_logic import GameState, StoryGenerator, MAX_RADIATION
# Load environment variables
load_dotenv()
# API configuration
API_HOST = os.getenv("API_HOST", "0.0.0.0")
API_PORT = int(os.getenv("API_PORT", "8000"))
STATIC_FILES_DIR = os.getenv("STATIC_FILES_DIR", "../client/dist")
app = FastAPI(title="Echoes of Influence")
# Configure CORS
app.add_middleware(
CORSMiddleware,
allow_origins=[
"http://localhost:5173", # Vite dev server
f"http://localhost:{API_PORT}", # API port
"https://huggingface.co", # HF main domain
"https://*.hf.space", # HF Spaces domains
],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Initialize game components
game_state = GameState()
story_generator = StoryGenerator(api_key=os.getenv("MISTRAL_API_KEY"))
class Choice(BaseModel):
id: int
text: str
class StoryResponse(BaseModel):
story_text: str
choices: List[Choice]
is_death: bool = False
radiation_level: int
class ChatMessage(BaseModel):
message: str
choice_id: Optional[int] = None
@app.get("/api/health")
async def health_check():
"""Health check endpoint"""
return {
"status": "healthy",
"game_state": {
"story_beat": game_state.story_beat,
"radiation_level": game_state.radiation_level
}
}
@app.post("/api/chat", response_model=StoryResponse)
async def chat_endpoint(chat_message: ChatMessage):
try:
# Handle restart
if chat_message.message.lower() == "restart":
game_state.reset()
previous_choice = "none"
else:
previous_choice = f"Choice {chat_message.choice_id}" if chat_message.choice_id else "none"
# Generate story segment
story_segment = story_generator.generate_story_segment(game_state, previous_choice)
# Update radiation level
game_state.radiation_level += story_segment.radiation_increase
# Check for radiation death
if game_state.radiation_level >= MAX_RADIATION:
story_segment = story_generator.process_radiation_death(story_segment)
# Only increment story beat if not dead
if not story_segment.is_death:
game_state.story_beat += 1
# Convert to response format
choices = [] if story_segment.is_death else [
Choice(id=i, text=choice.strip())
for i, choice in enumerate(story_segment.choices, 1)
]
return StoryResponse(
story_text=story_segment.story_text,
choices=choices,
is_death=story_segment.is_death,
radiation_level=game_state.radiation_level
)
except Exception as e:
print(f"Error: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
# Mount static files (this should be after all API routes)
app.mount("/", StaticFiles(directory=STATIC_FILES_DIR, html=True), name="static")
if __name__ == "__main__":
import uvicorn
uvicorn.run("server.server:app", host=API_HOST, port=API_PORT, reload=True) |