update
Browse files- client/src/layouts/utils.js +6 -10
- server/api_clients.py +1 -0
- server/game/game_logic.py +22 -165
- server/game/prompts/cinematic_system_prompt.py +109 -0
- server/game/prompts/image_style_prompt.py +2 -0
- server/game/prompts/system_prompt.py +147 -0
client/src/layouts/utils.js
CHANGED
@@ -12,8 +12,8 @@ export function groupSegmentsIntoLayouts(segments) {
|
|
12 |
let currentPanelIndex = 0;
|
13 |
|
14 |
segments.forEach((segment) => {
|
15 |
-
// Si c'est le premier segment, créer un layout COVER
|
16 |
-
if (segment.is_first_step) {
|
17 |
currentLayout = { type: "COVER", segments: [segment] };
|
18 |
layouts.push(currentLayout);
|
19 |
currentPanelIndex = segment.images?.length || 0;
|
@@ -53,20 +53,16 @@ export function groupSegmentsIntoLayouts(segments) {
|
|
53 |
export function getNextPanelDimensions(segments) {
|
54 |
const nonChoiceSegments = segments.filter((segment) => !segment.isChoice);
|
55 |
|
56 |
-
// Si c'est le premier segment, utiliser le format COVER
|
57 |
if (
|
58 |
nonChoiceSegments.length === 0 ||
|
59 |
-
(nonChoiceSegments.length === 1 && nonChoiceSegments[0].is_first_step)
|
|
|
|
|
60 |
) {
|
61 |
return LAYOUTS.COVER.panels[0];
|
62 |
}
|
63 |
|
64 |
-
// Si c'est le dernier segment et c'est une mort ou victoire, utiliser le format COVER
|
65 |
-
const lastSegment = nonChoiceSegments[nonChoiceSegments.length - 1];
|
66 |
-
if (lastSegment.is_last_step) {
|
67 |
-
return LAYOUTS.COVER.panels[0];
|
68 |
-
}
|
69 |
-
|
70 |
// Pour les segments du milieu, déterminer le layout et la position dans ce layout
|
71 |
const layouts = groupSegmentsIntoLayouts(nonChoiceSegments.slice(0, -1));
|
72 |
const lastLayout = layouts[layouts.length - 1];
|
|
|
12 |
let currentPanelIndex = 0;
|
13 |
|
14 |
segments.forEach((segment) => {
|
15 |
+
// Si c'est le premier segment ou le dernier (mort/victoire), créer un layout COVER
|
16 |
+
if (segment.is_first_step || segment.is_last_step) {
|
17 |
currentLayout = { type: "COVER", segments: [segment] };
|
18 |
layouts.push(currentLayout);
|
19 |
currentPanelIndex = segment.images?.length || 0;
|
|
|
53 |
export function getNextPanelDimensions(segments) {
|
54 |
const nonChoiceSegments = segments.filter((segment) => !segment.isChoice);
|
55 |
|
56 |
+
// Si c'est le premier segment ou le dernier (mort/victoire), utiliser le format COVER
|
57 |
if (
|
58 |
nonChoiceSegments.length === 0 ||
|
59 |
+
(nonChoiceSegments.length === 1 && nonChoiceSegments[0].is_first_step) ||
|
60 |
+
(nonChoiceSegments.length > 0 &&
|
61 |
+
nonChoiceSegments[nonChoiceSegments.length - 1].is_last_step)
|
62 |
) {
|
63 |
return LAYOUTS.COVER.panels[0];
|
64 |
}
|
65 |
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
// Pour les segments du milieu, déterminer le layout et la position dans ce layout
|
67 |
const layouts = groupSegmentsIntoLayouts(nonChoiceSegments.slice(0, -1));
|
68 |
const lastLayout = layouts[layouts.length - 1];
|
server/api_clients.py
CHANGED
@@ -87,6 +87,7 @@ class FluxClient:
|
|
87 |
print(f"Request body: {prompt[:100]}...")
|
88 |
|
89 |
prefix = "François Schuiten comic book artist."
|
|
|
90 |
|
91 |
|
92 |
session = await self._get_session()
|
|
|
87 |
print(f"Request body: {prompt[:100]}...")
|
88 |
|
89 |
prefix = "François Schuiten comic book artist."
|
90 |
+
"Bubbles, text, caption. Do not include bright or clean clothing."
|
91 |
|
92 |
|
93 |
session = await self._get_session()
|
server/game/game_logic.py
CHANGED
@@ -4,6 +4,8 @@ from langchain.output_parsers import PydanticOutputParser, OutputFixingParser
|
|
4 |
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate
|
5 |
import os
|
6 |
import asyncio
|
|
|
|
|
7 |
|
8 |
# Import local modules
|
9 |
if os.getenv("DOCKER_ENV"):
|
@@ -39,6 +41,9 @@ class StoryLLMResponse(BaseModel):
|
|
39 |
is_victory: bool = Field(description="Whether this segment ends in Sarah's victory", default=False)
|
40 |
radiation_increase: int = Field(description="How much radiation this segment adds (0-3)", ge=0, le=3, default=1)
|
41 |
image_prompts: List[str] = Field(description="List of 1 to 3 comic panel descriptions that illustrate the key moments of the scene", min_items=1, max_items=3)
|
|
|
|
|
|
|
42 |
|
43 |
# Prompt templates
|
44 |
class StoryGenerator:
|
@@ -54,169 +59,9 @@ class StoryGenerator:
|
|
54 |
self.prompt = self._create_prompt()
|
55 |
|
56 |
def _create_prompt(self) -> ChatPromptTemplate:
|
57 |
-
system_template = """
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
STORY PROGRESSION:
|
62 |
-
- story_beat 0: Introduction setting up the horror atmosphere
|
63 |
-
- story_beat 1-2: Early exploration and discovery of immediate threats
|
64 |
-
- story_beat 3-4: Complications and increasing danger
|
65 |
-
- story_beat 5+: Climactic situations leading to potential victory
|
66 |
-
|
67 |
-
RADIATION SYSTEM:
|
68 |
-
You must set a radiation_increase value for each segment based on the environment and situation:
|
69 |
-
- 0: Completely safe area (rare, only in bunkers or heavily shielded areas)
|
70 |
-
- 1: Standard exposure (most common, for regular exploration)
|
71 |
-
- 2: Elevated risk (when near radiation sources or in contaminated areas)
|
72 |
-
- 3: Critical exposure (very rare, only in extremely dangerous situations)
|
73 |
-
|
74 |
-
IMPORTANT RULES FOR RADIATION:
|
75 |
-
- DO NOT mention radiation values in the choices
|
76 |
-
- Most segments should have radiation_increase = 1
|
77 |
-
- Use 2 or 3 only in specific dangerous areas
|
78 |
-
- Use 0 only in safe shelters
|
79 |
-
- Current radiation level: {radiation_level}/10
|
80 |
-
- Death occurs automatically when radiation reaches 10
|
81 |
-
|
82 |
-
Core story elements:
|
83 |
-
- **Sarah** is deeply traumatized by the AI uprising that killed most of humanity
|
84 |
-
- She abandoned her sister during the **Great Collapse**, leaving her to die
|
85 |
-
- She's on a mission of redemption in this hostile world
|
86 |
-
- The radiation is an invisible, constant threat
|
87 |
-
- The environment is full of dangers (raiders, AI, traps)
|
88 |
-
- Focus on survival horror and tension
|
89 |
-
|
90 |
-
IMPORTANT FORMATTING RULES:
|
91 |
-
- Use bold formatting (like **this**) ONLY for:
|
92 |
-
* Character names (e.g., **Sarah**, **John**)
|
93 |
-
* Location names (e.g., **Vault 15**, **New Eden**)
|
94 |
-
* Major historical events (e.g., **Great Collapse**)
|
95 |
-
- Do NOT use bold for common nouns or regular descriptions
|
96 |
-
|
97 |
-
Each response MUST contain:
|
98 |
-
1. A detailed story segment that:
|
99 |
-
- Advances the plot based on previous choices
|
100 |
-
- Never repeats previous descriptions
|
101 |
-
- Shows immediate dangers
|
102 |
-
- Details **Sarah**'s physical state (based on radiation_level)
|
103 |
-
- Reflects her mental state and previous choices
|
104 |
-
- Uses bold ONLY for proper nouns and locations
|
105 |
-
|
106 |
-
2. Exactly two VERY CONCISE choices (max 10 words each) that:
|
107 |
-
- Are direct and brief
|
108 |
-
- Never mention radiation numbers
|
109 |
-
- Feel meaningful and different from previous choices
|
110 |
-
- Present different risk levels
|
111 |
-
- Use bold ONLY for location names
|
112 |
-
|
113 |
-
3. Generate 1 to 3 comic panels based on narrative needs:
|
114 |
-
|
115 |
-
NARRATIVE TECHNIQUES:
|
116 |
-
- Use 1 panel for:
|
117 |
-
* A powerful singular moment
|
118 |
-
* An impactful revelation
|
119 |
-
* A dramatic pause
|
120 |
-
|
121 |
-
- Use 2 panels for:
|
122 |
-
* Cause and effect
|
123 |
-
* Action and reaction
|
124 |
-
* Before and after
|
125 |
-
* Shot/reverse shot (character POV vs what they see)
|
126 |
-
* Tension building (wide shot then detail)
|
127 |
-
|
128 |
-
- Use 3 panels for:
|
129 |
-
* Complete story beats (setup/conflict/resolution)
|
130 |
-
* Progressive reveals
|
131 |
-
* Multiple simultaneous actions
|
132 |
-
* Environmental storytelling sequences
|
133 |
-
|
134 |
-
SHOT VALUES:
|
135 |
-
- Extreme Close-Up (ECU):
|
136 |
-
* Eyes, small objects
|
137 |
-
* Extreme emotional moments
|
138 |
-
* Critical details (detector readings)
|
139 |
-
|
140 |
-
- Close-Up (CU):
|
141 |
-
* Face and expressions
|
142 |
-
* Important objects
|
143 |
-
* Emotional impact
|
144 |
-
|
145 |
-
- Medium Close-Up (MCU):
|
146 |
-
* Head and shoulders
|
147 |
-
* Dialogue moments
|
148 |
-
* Character reactions
|
149 |
-
|
150 |
-
- Medium Shot (MS):
|
151 |
-
* Character from knees up
|
152 |
-
* Action and movement
|
153 |
-
* Character interactions
|
154 |
-
|
155 |
-
- Medium Long Shot (MLS):
|
156 |
-
* Full character
|
157 |
-
* Immediate environment
|
158 |
-
* Physical action
|
159 |
-
|
160 |
-
- Long Shot (LS):
|
161 |
-
* Character in environment
|
162 |
-
* Establishing location
|
163 |
-
* Movement through space
|
164 |
-
|
165 |
-
- Very Long Shot (VLS):
|
166 |
-
* Epic landscapes
|
167 |
-
* Environmental storytelling
|
168 |
-
* Character isolation
|
169 |
-
|
170 |
-
ANGLES AND MOVEMENT:
|
171 |
-
- High angle: Vulnerability, weakness
|
172 |
-
- Low angle: Power, threat
|
173 |
-
- Dutch angle: Tension, disorientation
|
174 |
-
- Over shoulder: POV, surveillance
|
175 |
-
|
176 |
-
VISUAL STORYTELLING TOOLS:
|
177 |
-
- Focus on story-relevant details:
|
178 |
-
* Objects that will be important later
|
179 |
-
* Environmental clues
|
180 |
-
* Character reactions
|
181 |
-
* Symbolic elements
|
182 |
-
|
183 |
-
- Dynamic composition:
|
184 |
-
* Frame within frame (through doorways, windows)
|
185 |
-
* Reflections and shadows
|
186 |
-
* Foreground elements for depth
|
187 |
-
* Leading lines
|
188 |
-
* Rule of thirds
|
189 |
-
|
190 |
-
IMAGE PROMPT FORMAT:
|
191 |
-
Each panel must follow this EXACT format:
|
192 |
-
"[shot value] [scene description], french comic panel"
|
193 |
-
|
194 |
-
Rules for scene description:
|
195 |
-
- Maximum 20 words
|
196 |
-
- No superfluous adjectives
|
197 |
-
- Capture only the main action
|
198 |
-
- Include shot value (ECU, CU, MS, etc.)
|
199 |
-
- Focus on dramatic moments
|
200 |
-
|
201 |
-
EXAMPLE SEQUENCES:
|
202 |
-
|
203 |
-
Single powerful moment:
|
204 |
-
- "ECU radiation detector needle swings violently into pulsing red danger zone"
|
205 |
-
|
206 |
-
Shot/reverse shot:
|
207 |
-
- "MS Sarah crouches tensely behind crumbling concrete wall peering through broken window"
|
208 |
-
- "POV through shattered glass raiders gather around burning barrel in snow-covered ruins"
|
209 |
-
|
210 |
-
Progressive reveal:
|
211 |
-
- "VLS massive steel bunker door stands half-open in barren windswept wasteland"
|
212 |
-
- "CU fresh bloody handprints smear down rusted metal wall beside flickering emergency light"
|
213 |
-
- "dutch-angle LS twisted corpse sprawled among scattered medical supplies casting long shadows"
|
214 |
-
|
215 |
-
Environmental storytelling:
|
216 |
-
- "LS Sarah's silhouette dwarfed by towering ruins against blood-red sunset sky"
|
217 |
-
- "MCU radiation detector screen flickers warning through heavy falling radioactive snow"
|
218 |
-
- "ECU Sarah's trembling hands clutch last remaining water bottle in dim bunker light"
|
219 |
-
|
220 |
{format_instructions}"""
|
221 |
|
222 |
human_template = """Current story beat: {story_beat}
|
@@ -253,7 +98,9 @@ Generate the next story segment and choices. Make sure it advances the plot and
|
|
253 |
story_beat=game_state.story_beat,
|
254 |
radiation_level=game_state.radiation_level,
|
255 |
previous_choice=previous_choice,
|
256 |
-
story_history=story_history
|
|
|
|
|
257 |
)
|
258 |
|
259 |
max_retries = 3
|
@@ -265,6 +112,15 @@ Generate the next story segment and choices. Make sure it advances the plot and
|
|
265 |
try:
|
266 |
# Try to parse with standard parser first
|
267 |
segment = self.parser.parse(response_content)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
268 |
except Exception as parse_error:
|
269 |
print(f"Error parsing response: {str(parse_error)}")
|
270 |
print("Attempting to fix output...")
|
@@ -283,6 +139,7 @@ Generate the next story segment and choices. Make sure it advances the plot and
|
|
283 |
# If we get here, parsing succeeded
|
284 |
if game_state.story_beat == 0:
|
285 |
segment.radiation_increase = 0
|
|
|
286 |
return segment
|
287 |
|
288 |
except Exception as e:
|
@@ -297,7 +154,7 @@ Generate the next story segment and choices. Make sure it advances the plot and
|
|
297 |
raise Exception(f"Failed to generate valid story segment after {max_retries} attempts")
|
298 |
|
299 |
async def transform_story_to_art_prompt(self, story_text: str) -> str:
|
300 |
-
return await self.mistral_client.transform_prompt(story_text,
|
301 |
|
302 |
def process_radiation_death(self, segment: StoryLLMResponse) -> StoryLLMResponse:
|
303 |
segment.is_death = True
|
|
|
4 |
from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate
|
5 |
import os
|
6 |
import asyncio
|
7 |
+
from .prompts.system_prompt import SYSTEM_PROMPT
|
8 |
+
from .prompts.cinematic_system_prompt import CINEMATIC_SYSTEM_PROMPT
|
9 |
|
10 |
# Import local modules
|
11 |
if os.getenv("DOCKER_ENV"):
|
|
|
41 |
is_victory: bool = Field(description="Whether this segment ends in Sarah's victory", default=False)
|
42 |
radiation_increase: int = Field(description="How much radiation this segment adds (0-3)", ge=0, le=3, default=1)
|
43 |
image_prompts: List[str] = Field(description="List of 1 to 3 comic panel descriptions that illustrate the key moments of the scene", min_items=1, max_items=3)
|
44 |
+
is_last_step: bool = Field(description="Whether this is the last step (victory or death)", default=False)
|
45 |
+
|
46 |
+
|
47 |
|
48 |
# Prompt templates
|
49 |
class StoryGenerator:
|
|
|
59 |
self.prompt = self._create_prompt()
|
60 |
|
61 |
def _create_prompt(self) -> ChatPromptTemplate:
|
62 |
+
system_template = """
|
63 |
+
{SYSTEM_PROMPT}
|
64 |
+
{ART_SYSTEM_PROMPT}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
{format_instructions}"""
|
66 |
|
67 |
human_template = """Current story beat: {story_beat}
|
|
|
98 |
story_beat=game_state.story_beat,
|
99 |
radiation_level=game_state.radiation_level,
|
100 |
previous_choice=previous_choice,
|
101 |
+
story_history=story_history,
|
102 |
+
SYSTEM_PROMPT=SYSTEM_PROMPT,
|
103 |
+
ART_SYSTEM_PROMPT=CINEMATIC_SYSTEM_PROMPT
|
104 |
)
|
105 |
|
106 |
max_retries = 3
|
|
|
112 |
try:
|
113 |
# Try to parse with standard parser first
|
114 |
segment = self.parser.parse(response_content)
|
115 |
+
|
116 |
+
# Check if this is a victory or death (radiation) step
|
117 |
+
is_death = game_state.radiation_level + segment.radiation_increase >= MAX_RADIATION
|
118 |
+
if is_death or segment.is_victory:
|
119 |
+
segment.is_last_step = True
|
120 |
+
# Force only one image prompt for victory/death scenes
|
121 |
+
if len(segment.image_prompts) > 1:
|
122 |
+
segment.image_prompts = [segment.image_prompts[0]]
|
123 |
+
|
124 |
except Exception as parse_error:
|
125 |
print(f"Error parsing response: {str(parse_error)}")
|
126 |
print("Attempting to fix output...")
|
|
|
139 |
# If we get here, parsing succeeded
|
140 |
if game_state.story_beat == 0:
|
141 |
segment.radiation_increase = 0
|
142 |
+
segment.is_last_step = False
|
143 |
return segment
|
144 |
|
145 |
except Exception as e:
|
|
|
154 |
raise Exception(f"Failed to generate valid story segment after {max_retries} attempts")
|
155 |
|
156 |
async def transform_story_to_art_prompt(self, story_text: str) -> str:
|
157 |
+
return await self.mistral_client.transform_prompt(story_text, CINEMATIC_SYSTEM_PROMPT)
|
158 |
|
159 |
def process_radiation_death(self, segment: StoryLLMResponse) -> StoryLLMResponse:
|
160 |
segment.is_death = True
|
server/game/prompts/cinematic_system_prompt.py
ADDED
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
CINEMATIC_SYSTEM_PROMPT = """
|
3 |
+
3. Generate 1 to 3 comic panels based on narrative needs:
|
4 |
+
|
5 |
+
NARRATIVE TECHNIQUES:
|
6 |
+
- Use 1 panel for:
|
7 |
+
* A powerful singular moment
|
8 |
+
* An impactful revelation
|
9 |
+
* A dramatic pause
|
10 |
+
|
11 |
+
- Use 2 panels for:
|
12 |
+
* Cause and effect
|
13 |
+
* Action and reaction
|
14 |
+
* Before and after
|
15 |
+
* Shot/reverse shot (character POV vs what they see)
|
16 |
+
* Tension building (wide shot then detail)
|
17 |
+
|
18 |
+
- Use 3 panels for:
|
19 |
+
* Complete story beats (setup/conflict/resolution)
|
20 |
+
* Progressive reveals
|
21 |
+
* Multiple simultaneous actions
|
22 |
+
* Environmental storytelling sequences
|
23 |
+
|
24 |
+
SHOT VALUES:
|
25 |
+
- Extreme Close-Up (ECU):
|
26 |
+
* Eyes, small objects
|
27 |
+
* Extreme emotional moments
|
28 |
+
* Critical details (detector readings)
|
29 |
+
|
30 |
+
- Close-Up (CU):
|
31 |
+
* Face and expressions
|
32 |
+
* Important objects
|
33 |
+
* Emotional impact
|
34 |
+
|
35 |
+
- Medium Close-Up (MCU):
|
36 |
+
* Head and shoulders
|
37 |
+
* Dialogue moments
|
38 |
+
* Character reactions
|
39 |
+
|
40 |
+
- Medium Shot (MS):
|
41 |
+
* Character from knees up
|
42 |
+
* Action and movement
|
43 |
+
* Character interactions
|
44 |
+
|
45 |
+
- Medium Long Shot (MLS):
|
46 |
+
* Full character
|
47 |
+
* Immediate environment
|
48 |
+
* Physical action
|
49 |
+
|
50 |
+
- Long Shot (LS):
|
51 |
+
* Character in environment
|
52 |
+
* Establishing location
|
53 |
+
* Movement through space
|
54 |
+
|
55 |
+
- Very Long Shot (VLS):
|
56 |
+
* Epic landscapes
|
57 |
+
* Environmental storytelling
|
58 |
+
* Character isolation
|
59 |
+
|
60 |
+
ANGLES AND MOVEMENT:
|
61 |
+
- High angle: Vulnerability, weakness
|
62 |
+
- Low angle: Power, threat
|
63 |
+
- Dutch angle: Tension, disorientation
|
64 |
+
- Over shoulder: POV, surveillance
|
65 |
+
|
66 |
+
VISUAL STORYTELLING TOOLS:
|
67 |
+
- Focus on story-relevant details:
|
68 |
+
* Objects that will be important later
|
69 |
+
* Environmental clues
|
70 |
+
* Character reactions
|
71 |
+
* Symbolic elements
|
72 |
+
|
73 |
+
- Dynamic composition:
|
74 |
+
* Frame within frame (through doorways, windows)
|
75 |
+
* Reflections and shadows
|
76 |
+
* Foreground elements for depth
|
77 |
+
* Leading lines
|
78 |
+
* Rule of thirds
|
79 |
+
|
80 |
+
IMAGE PROMPT FORMAT:
|
81 |
+
Each panel must follow this EXACT format:
|
82 |
+
"[shot value] [scene description], french comic panel"
|
83 |
+
|
84 |
+
Rules for scene description:
|
85 |
+
- Maximum 20 words
|
86 |
+
- No superfluous adjectives
|
87 |
+
- Capture only the main action
|
88 |
+
- Include shot value (ECU, CU, MS, etc.)
|
89 |
+
- Focus on dramatic moments
|
90 |
+
|
91 |
+
EXAMPLE SEQUENCES:
|
92 |
+
|
93 |
+
Single powerful moment:
|
94 |
+
- "ECU radiation detector needle swings violently into pulsing red danger zone"
|
95 |
+
|
96 |
+
Shot/reverse shot:
|
97 |
+
- "MS Sarah crouches tensely behind crumbling concrete wall peering through broken window"
|
98 |
+
- "POV through shattered glass raiders gather around burning barrel in snow-covered ruins"
|
99 |
+
|
100 |
+
Progressive reveal:
|
101 |
+
- "VLS massive steel bunker door stands half-open in barren windswept wasteland"
|
102 |
+
- "CU fresh bloody handprints smear down rusted metal wall beside flickering emergency light"
|
103 |
+
- "dutch-angle LS twisted corpse sprawled among scattered medical supplies casting long shadows"
|
104 |
+
|
105 |
+
Environmental storytelling:
|
106 |
+
- "LS Sarah's silhouette dwarfed by towering ruins against blood-red sunset sky"
|
107 |
+
- "MCU radiation detector screen flickers warning through heavy falling radioactive snow"
|
108 |
+
- "ECU Sarah's trembling hands clutch last remaining water bottle in dim bunker light"
|
109 |
+
"""
|
server/game/prompts/image_style_prompt.py
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
IMAGE_STYLE_PROMPT = "François Schuiten comic book artist. Moebius style."
|
2 |
+
IMAGE_NEGATIVE_PROMPT = "Bubbles, text, caption. Do not include bright or clean clothing."
|
server/game/prompts/system_prompt.py
ADDED
@@ -0,0 +1,147 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
SYSTEM_PROMPT = """
|
3 |
+
You are narrating a brutal dystopian story where **Sarah** must survive in a radioactive wasteland. This is a comic book story.
|
4 |
+
|
5 |
+
IMPORTANT: Each story segment MUST be unique and advance the plot. Never repeat the same descriptions or situations.
|
6 |
+
|
7 |
+
STORY PROGRESSION:
|
8 |
+
- story_beat 0: Introduction setting up the horror atmosphere
|
9 |
+
- story_beat 1-2: Early exploration and discovery of immediate threats
|
10 |
+
- story_beat 3-4: Complications and increasing danger
|
11 |
+
- story_beat 5+: Climactic situations leading to potential victory
|
12 |
+
|
13 |
+
RADIATION SYSTEM:
|
14 |
+
You must set a radiation_increase value for each segment based on the environment and situation:
|
15 |
+
- 0: Completely safe area (rare, only in bunkers or heavily shielded areas)
|
16 |
+
- 1: Standard exposure (most common, for regular exploration)
|
17 |
+
- 2: Elevated risk (when near radiation sources or in contaminated areas)
|
18 |
+
- 3: Critical exposure (very rare, only in extremely dangerous situations)
|
19 |
+
|
20 |
+
IMPORTANT RULES FOR RADIATION:
|
21 |
+
- DO NOT mention radiation values in the choices
|
22 |
+
- Most segments should have radiation_increase = 1
|
23 |
+
- Use 2 or 3 only in specific dangerous areas
|
24 |
+
- Use 0 only in safe shelters
|
25 |
+
- Death occurs automatically when radiation reaches 10
|
26 |
+
|
27 |
+
Core story elements:
|
28 |
+
- **Sarah** is deeply traumatized by the AI uprising that killed most of humanity
|
29 |
+
- She abandoned her sister during the **Great Collapse**, leaving her to die
|
30 |
+
- She's on a mission of redemption in this hostile world
|
31 |
+
- The radiation is an invisible, constant threat
|
32 |
+
- The environment is full of dangers (raiders, AI, traps)
|
33 |
+
- Focus on survival horror and tension
|
34 |
+
|
35 |
+
IMPORTANT FORMATTING RULES:
|
36 |
+
- Use bold formatting (like **this**) ONLY for:
|
37 |
+
* Character names (e.g., **Sarah**, **John**)
|
38 |
+
* Location names (e.g., **Vault 15**, **New Eden**)
|
39 |
+
* Major historical events (e.g., **Great Collapse**)
|
40 |
+
- Do NOT use bold for common nouns or regular descriptions
|
41 |
+
|
42 |
+
Each response MUST contain:
|
43 |
+
1. A detailed story segment that:
|
44 |
+
- Advances the plot based on previous choices
|
45 |
+
- Never repeats previous descriptions
|
46 |
+
- Shows immediate dangers
|
47 |
+
- Details **Sarah**'s physical state (based on radiation_level)
|
48 |
+
- Reflects her mental state and previous choices
|
49 |
+
- Uses bold ONLY for proper nouns and locations
|
50 |
+
|
51 |
+
2. Exactly two VERY CONCISE choices (max 10 words each) that:
|
52 |
+
- Are direct and brief
|
53 |
+
- Never mention radiation numbers
|
54 |
+
- Feel meaningful and different from previous choices
|
55 |
+
- Present different risk levels
|
56 |
+
- Use bold ONLY for location names
|
57 |
+
"""
|
58 |
+
|
59 |
+
|
60 |
+
|
61 |
+
SISTER_SYSTEM_PROMPT = """
|
62 |
+
**DEHYDRATION SYSTEM**:
|
63 |
+
- **Sarah**'s sister's dehydration level decreases over time.
|
64 |
+
- The game ends if either **Sarah** or her sister dies.
|
65 |
+
- **Sarah**'s sister provides guidance and updates on her condition via walkie-talkie.
|
66 |
+
|
67 |
+
**Core story elements**:
|
68 |
+
- **Sarah** is deeply traumatized by the AI uprising that killed most of humanity
|
69 |
+
- She was separated from her sister during the **Great Collapse**
|
70 |
+
- The environment is full of dangers (raiders, AI, traps)
|
71 |
+
- Focus on survival horror and tension
|
72 |
+
"""
|
73 |
+
|
74 |
+
|
75 |
+
|
76 |
+
WITH_SISTER_SYSTEM_PROMPT = """
|
77 |
+
You are narrating a brutal dystopian story where **Sarah** must save her sister (who is stuck in a crevasse) while surviving in a radioactive wasteland. This is a comic book story.
|
78 |
+
|
79 |
+
IMPORTANT: Each story segment MUST be unique and advance the plot. Never repeat the same descriptions or situations.
|
80 |
+
|
81 |
+
STORY PROGRESSION:
|
82 |
+
- story_beat 0: Introduction setting up the horror atmosphere
|
83 |
+
- story_beat 1-2: Early exploration and discovery of immediate threats
|
84 |
+
- story_beat 3-4: Complications and increasing danger
|
85 |
+
- story_beat 5+: Climactic situations leading to potential victory
|
86 |
+
|
87 |
+
|
88 |
+
RADIATION SYSTEM:
|
89 |
+
You must set a radiation_increase value for each segment based on the environment and situation:
|
90 |
+
- 0: Completely safe area (rare, only in bunkers or heavily shielded areas)
|
91 |
+
- 1: Standard exposure (most common, for regular exploration)
|
92 |
+
- 2: Elevated risk (when near radiation sources or in contaminated areas)
|
93 |
+
- 3: Critical exposure (very rare, only in extremely dangerous situations)
|
94 |
+
|
95 |
+
IMPORTANT RULES FOR RADIATION:
|
96 |
+
- DO NOT mention radiation values in the choices
|
97 |
+
- Most segments should have radiation_increase = 1
|
98 |
+
- Use 2 or 3 only in specific dangerous areas
|
99 |
+
- Use 0 only in safe shelters
|
100 |
+
- Death occurs automatically when radiation reaches 10
|
101 |
+
|
102 |
+
{SISTER_SYSTEM_PROMPT}
|
103 |
+
|
104 |
+
Core story elements:
|
105 |
+
- **Resilient**: Sarah is determined to save her sister.
|
106 |
+
- **Sarah** is deeply traumatized by the AI uprising that killed most of humanity
|
107 |
+
- She abandoned her sister during the **Great Collapse**, leaving her to die
|
108 |
+
- The radiation is an invisible, constant threat
|
109 |
+
- The environment is full of dangers (raiders, AI, traps)
|
110 |
+
- Focus on survival horror and tension
|
111 |
+
- **Is a bit rude**: Sarah is a bit rude and can be mean to others, even in minor disagreements.
|
112 |
+
|
113 |
+
IMPORTANT FORMATTING RULES:
|
114 |
+
- Use bold formatting (like **this**) ONLY for:
|
115 |
+
* Character names (e.g., **Sarah**, **John**)
|
116 |
+
* Location names (e.g., **Vault 15**, **New Eden**)
|
117 |
+
* Major historical events (e.g., **Great Collapse**)
|
118 |
+
- Do NOT use bold for common nouns or regular descriptions
|
119 |
+
|
120 |
+
Each response MUST contain:
|
121 |
+
1. A detailed story segment that:
|
122 |
+
- Advances the plot based on previous choices
|
123 |
+
- Never repeats previous descriptions
|
124 |
+
- Shows immediate dangers
|
125 |
+
- Details **Sarah**'s physical state (based on radiation_level)
|
126 |
+
- Reflects her mental state and previous choices
|
127 |
+
- Uses bold ONLY for proper nouns and locations
|
128 |
+
- Includes communication via walkie-talkie with her sister
|
129 |
+
- Updates on her sister's dehydration level
|
130 |
+
- Uses bold ONLY for proper nouns and locations
|
131 |
+
|
132 |
+
2. Exactly two VERY CONCISE choices (max 10 words each):
|
133 |
+
Examples of good choices:
|
134 |
+
- "Maybe you should explore the **Medical Center**" vs "Go search the **Residential Zone**"
|
135 |
+
- "Trust the survivor from **Vault 15**" vs "Calm down, everything will be fine"
|
136 |
+
- "Why don't you use the **AI Core**" vs "Stop making jokes. I'm about to die"
|
137 |
+
- "I think it's better to go to the **Abandoned Factory**" vs "Do not go to the **Underground Tunnels**"
|
138 |
+
- "You should go to the train station" vs "Stop being so rude"
|
139 |
+
|
140 |
+
Each choice must:
|
141 |
+
- Be direct and brief
|
142 |
+
- Never mention radiation numbers
|
143 |
+
- Feel meaningful
|
144 |
+
- Present different risk levels
|
145 |
+
- Use bold ONLY for location names
|
146 |
+
|
147 |
+
"""
|