File size: 2,401 Bytes
d8e2b36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""Pydantic models representing game state and LLM outputs."""

from typing import Dict, List, Optional, Set

from pydantic import BaseModel, Field


class Milestone(BaseModel):
    """Milestone that can be achieved during the story."""

    id: str
    description: str


class Ending(BaseModel):
    """Possible game ending."""

    id: str
    type: str  # "good" or "bad"
    condition: str
    description: Optional[str] = None


class StoryFrame(BaseModel):
    """Overall plot information generated by the LLM."""

    lore: str
    goal: str
    milestones: List[Milestone]
    endings: List[Ending]
    setting: str
    character: Dict[str, str]
    genre: str


class StoryFrameLLM(BaseModel):
    """Structure returned by the LLM for story frame generation."""

    lore: str
    goal: str
    milestones: List[Milestone]
    endings: List[Ending]


class SceneChoice(BaseModel):
    """User choice leading to another scene."""

    text: str
    next_scene_short_desc: str


class PlayerOption(BaseModel):
    """Option presented to the player in a scene."""

    option_description: str = Field(
        description=(
            "Description of the option, e.g. '[Say] Hello!' or "
            "'Go to the forest'"
        )
    )


class Scene(BaseModel):
    """Game scene with choices and optional assets."""

    scene_id: str
    description: str
    choices: List[SceneChoice]
    image: Optional[str] = None
    music: Optional[str] = None


class SceneLLM(BaseModel):
    """Structure expected from the LLM when generating a scene."""

    description: str
    choices: List[SceneChoice]


class EndingCheckResult(BaseModel):
    """Result returned from the LLM when checking for an ending."""

    ending_reached: bool = Field(default=False)
    ending: Optional[Ending] = None


class UserChoice(BaseModel):
    """Single player choice recorded in the history."""

    scene_id: str
    choice_text: str
    timestamp: Optional[str] = None


class UserState(BaseModel):
    """State stored for each user."""

    story_frame: Optional[StoryFrame] = None
    current_scene_id: Optional[str] = None
    scenes: Dict[str, Scene] = Field(default_factory=dict)
    milestones_achieved: Set[str] = Field(default_factory=set)
    user_choices: List[UserChoice] = Field(default_factory=list)
    ending: Optional[Ending] = None
    assets: Dict[str, str] = Field(default_factory=dict)