update story consistenty
Browse files- client/src/components/StoryChoices.jsx +1 -1
- client/src/components/UniverseSlotMachine.jsx +3 -3
- server/api/routes/chat.py +9 -0
- server/core/generators/metadata_generator.py +3 -0
- server/core/generators/story_segment_generator.py +6 -40
- server/core/generators/universe_generator.py +3 -31
- server/core/story_generator.py +14 -11
- server/core/styles/universe_styles.json +36 -76
client/src/components/StoryChoices.jsx
CHANGED
@@ -278,7 +278,7 @@ export function StoryChoices() {
|
|
278 |
rows={isMobile ? 5 : 4}
|
279 |
fullWidth
|
280 |
variant="outlined"
|
281 |
-
placeholder="
|
282 |
value={customChoice}
|
283 |
onChange={(e) => setCustomChoice(e.target.value)}
|
284 |
sx={{
|
|
|
278 |
rows={isMobile ? 5 : 4}
|
279 |
fullWidth
|
280 |
variant="outlined"
|
281 |
+
placeholder="A dragon appears right above the hero...."
|
282 |
value={customChoice}
|
283 |
onChange={(e) => setCustomChoice(e.target.value)}
|
284 |
sx={{
|
client/src/components/UniverseSlotMachine.jsx
CHANGED
@@ -209,7 +209,7 @@ export const UniverseSlotMachine = ({
|
|
209 |
}}
|
210 |
>
|
211 |
<SlotSection
|
212 |
-
label="
|
213 |
value={style}
|
214 |
words={RANDOM_STYLES}
|
215 |
delay={0}
|
@@ -217,7 +217,7 @@ export const UniverseSlotMachine = ({
|
|
217 |
onComplete={() => handleSlotComplete(0)}
|
218 |
/>
|
219 |
<SlotSection
|
220 |
-
label="
|
221 |
value={genre}
|
222 |
words={RANDOM_GENRES}
|
223 |
delay={1}
|
@@ -225,7 +225,7 @@ export const UniverseSlotMachine = ({
|
|
225 |
onComplete={() => handleSlotComplete(1)}
|
226 |
/>
|
227 |
<SlotSection
|
228 |
-
label="in
|
229 |
value={epoch}
|
230 |
words={RANDOM_EPOCHS}
|
231 |
delay={2}
|
|
|
209 |
}}
|
210 |
>
|
211 |
<SlotSection
|
212 |
+
label="Told in"
|
213 |
value={style}
|
214 |
words={RANDOM_STYLES}
|
215 |
delay={0}
|
|
|
217 |
onComplete={() => handleSlotComplete(0)}
|
218 |
/>
|
219 |
<SlotSection
|
220 |
+
label="exploring"
|
221 |
value={genre}
|
222 |
words={RANDOM_GENRES}
|
223 |
delay={1}
|
|
|
225 |
onComplete={() => handleSlotComplete(1)}
|
226 |
/>
|
227 |
<SlotSection
|
228 |
+
label="set in"
|
229 |
value={epoch}
|
230 |
words={RANDOM_EPOCHS}
|
231 |
delay={2}
|
server/api/routes/chat.py
CHANGED
@@ -54,8 +54,17 @@ def get_chat_router(session_manager: SessionManager, story_generator):
|
|
54 |
)
|
55 |
previous_choice = "none"
|
56 |
else:
|
|
|
57 |
if chat_message.message == "custom_choice" and chat_message.custom_text:
|
58 |
previous_choice = chat_message.custom_text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
else:
|
60 |
previous_choice = f"Choice {chat_message.choice_id}" if chat_message.choice_id else "none"
|
61 |
|
|
|
54 |
)
|
55 |
previous_choice = "none"
|
56 |
else:
|
57 |
+
# Pour les choix personnalisés, on les traite immédiatement
|
58 |
if chat_message.message == "custom_choice" and chat_message.custom_text:
|
59 |
previous_choice = chat_message.custom_text
|
60 |
+
# On ajoute le choix à l'historique avant de générer le segment
|
61 |
+
game_state.add_to_history(
|
62 |
+
f"You decide to: {chat_message.custom_text}",
|
63 |
+
previous_choice,
|
64 |
+
[], # pas d'image pour le choix
|
65 |
+
game_state.current_time,
|
66 |
+
game_state.current_location
|
67 |
+
)
|
68 |
else:
|
69 |
previous_choice = f"Choice {chat_message.choice_id}" if chat_message.choice_id else "none"
|
70 |
|
server/core/generators/metadata_generator.py
CHANGED
@@ -61,6 +61,9 @@ Dont be obvious. NEVER use "approach the ...", its too slow to be a choice.
|
|
61 |
|
62 |
You can be original in your choices, but dont be too far from the story.
|
63 |
Dont be too cliché. The choices should be realistically different.
|
|
|
|
|
|
|
64 |
|
65 |
- Each choice MUST be NO MORE than 6 words - this is a HARD limit
|
66 |
You must return a JSON object with the following format:
|
|
|
61 |
|
62 |
You can be original in your choices, but dont be too far from the story.
|
63 |
Dont be too cliché. The choices should be realistically different.
|
64 |
+
The choices should be the direct continuation of the story.
|
65 |
+
The choices should be the direct continuation of the story.
|
66 |
+
The choices should be the direct continuation of the story.
|
67 |
|
68 |
- Each choice MUST be NO MORE than 6 words - this is a HARD limit
|
69 |
You must return a JSON object with the following format:
|
server/core/generators/story_segment_generator.py
CHANGED
@@ -23,9 +23,9 @@ class StorySegmentGenerator(BaseGenerator):
|
|
23 |
def _get_what_to_represent(self, story_beat: int, is_death: bool = False, is_victory: bool = False) -> str:
|
24 |
"""Determine what to represent based on story beat and state."""
|
25 |
|
|
|
26 |
# Story progression based representation with ranges
|
27 |
story_beat_ranges = [
|
28 |
-
(0, f"{self.hero_name} arriving through the portal into this new world."),
|
29 |
(1, f"Early exploration and discovery phase."),
|
30 |
(2, f"Early exploration and discovery phase. Show {self.hero_name} uncovering the first mysteries of this world and potentially encountering the quest object."),
|
31 |
(3, 4, f"Rising tension and complications. Show {self.hero_name} dealing with increasingly complex challenges and uncovering deeper mysteries."),
|
@@ -54,32 +54,9 @@ class StorySegmentGenerator(BaseGenerator):
|
|
54 |
You are a descriptive narrator for a comic book. Your ONLY task is to write the NEXT segment of the story.
|
55 |
ALWAYS write in English, never use any other language.
|
56 |
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
- Epoch: {self.universe_epoch}
|
61 |
-
|
62 |
-
EXAMPLES:
|
63 |
-
- Mateo inspects the relic after choosing to investigate the old house.
|
64 |
-
- A young woman finds a hidden door after exploring the alleyway.
|
65 |
-
- On a distant planet, an explorer uncovers an artifact after landing.
|
66 |
-
- In a medieval village, a blacksmith discovers a map after repairing a sword.
|
67 |
-
- A pilot notices a signal after taking a risky shortcut.
|
68 |
-
- In a mansion, a detective finds a passage after searching the library.
|
69 |
-
- Amidst a market, a thief spots an amulet after blending into the crowd.
|
70 |
-
- A diver encounters a ship after exploring uncharted waters.
|
71 |
-
- Mateo, the hero, finds a secret compartment after investigating the library.
|
72 |
-
- In a city, the hero deciphers a message after hacking the mainframe.
|
73 |
-
- A knight finds a hidden passage after examining the castle walls.
|
74 |
-
- An astronaut discovers a new planet after navigating through an asteroid field.
|
75 |
-
- A scientist uncovers a secret formula after analyzing ancient manuscripts.
|
76 |
-
- A warrior finds a mystical weapon after defeating a powerful enemy.
|
77 |
-
- A mage discovers a hidden spell after studying ancient runes.
|
78 |
-
- A ranger spots a hidden trail after scouting the forest.
|
79 |
-
- A sailor finds a treasure map after exploring a deserted island.
|
80 |
-
- A spy uncovers a conspiracy after infiltrating the enemy base.
|
81 |
-
- A historian finds a lost diary after searching the old archives.
|
82 |
-
- A musician discovers a hidden melody after playing an ancient instrument.
|
83 |
|
84 |
Your task is to generate the next segment of the story, following these rules:
|
85 |
1. Keep the story consistent with the universe parameters
|
@@ -93,22 +70,9 @@ Hero Description: {self.hero_desc}
|
|
93 |
|
94 |
human_template = """
|
95 |
|
96 |
-
EXAMPLES:
|
97 |
-
- Mateo inspects the relic after choosing to investigate the old house.
|
98 |
-
- A young woman finds a hidden door after exploring the alleyway.
|
99 |
-
- On a distant planet, an explorer uncovers an artifact after landing.
|
100 |
-
- In a medieval village, a blacksmith discovers a map after repairing a sword.
|
101 |
-
- A pilot notices a signal after taking a risky shortcut.
|
102 |
-
- In a mansion, a detective finds a passage after searching the library.
|
103 |
-
|
104 |
-
BAD:
|
105 |
-
- In a mansion, a detective finds a passage after searching the library. [Choix du joueur: Choice 1, "the hero encounter a ..."]
|
106 |
-
- [A town, 00h00] In a medieval village, a blacksmith discovers a map after repairing a sword.
|
107 |
-
|
108 |
Story history:
|
109 |
{story_history}
|
110 |
|
111 |
-
{what_to_represent}
|
112 |
|
113 |
Never describes game variables.
|
114 |
|
@@ -204,6 +168,8 @@ Write a story segment that:
|
|
204 |
3. Respects all previous rules about length and style
|
205 |
4. Naturally integrates the custom elements while staying true to the plot
|
206 |
5. NEVER FORGET THE CHOICE, IT MUST BE MENTIONED IN THE STORY.
|
|
|
|
|
207 |
"""
|
208 |
|
209 |
# Créer les messages
|
|
|
23 |
def _get_what_to_represent(self, story_beat: int, is_death: bool = False, is_victory: bool = False) -> str:
|
24 |
"""Determine what to represent based on story beat and state."""
|
25 |
|
26 |
+
|
27 |
# Story progression based representation with ranges
|
28 |
story_beat_ranges = [
|
|
|
29 |
(1, f"Early exploration and discovery phase."),
|
30 |
(2, f"Early exploration and discovery phase. Show {self.hero_name} uncovering the first mysteries of this world and potentially encountering the quest object."),
|
31 |
(3, 4, f"Rising tension and complications. Show {self.hero_name} dealing with increasingly complex challenges and uncovering deeper mysteries."),
|
|
|
54 |
You are a descriptive narrator for a comic book. Your ONLY task is to write the NEXT segment of the story.
|
55 |
ALWAYS write in English, never use any other language.
|
56 |
|
57 |
+
Base Story:
|
58 |
+
{self.universe_story}
|
59 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
|
61 |
Your task is to generate the next segment of the story, following these rules:
|
62 |
1. Keep the story consistent with the universe parameters
|
|
|
70 |
|
71 |
human_template = """
|
72 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
Story history:
|
74 |
{story_history}
|
75 |
|
|
|
76 |
|
77 |
Never describes game variables.
|
78 |
|
|
|
168 |
3. Respects all previous rules about length and style
|
169 |
4. Naturally integrates the custom elements while staying true to the plot
|
170 |
5. NEVER FORGET THE CHOICE, IT MUST BE MENTIONED IN THE STORY.
|
171 |
+
6. Start with a direct reaction to the player's choice
|
172 |
+
7. Show immediate consequences of their action
|
173 |
"""
|
174 |
|
175 |
# Créer les messages
|
server/core/generators/universe_generator.py
CHANGED
@@ -16,43 +16,15 @@ class UniverseGenerator(BaseGenerator):
|
|
16 |
def _create_prompt(self) -> ChatPromptTemplate:
|
17 |
|
18 |
system_template = """You are a creative writing assistant specialized in comic book universes.
|
19 |
-
Your task is to rewrite a story while keeping its exact structure and beats, but transposing it into a different universe.
|
20 |
"""
|
21 |
|
22 |
-
human_template = """
|
23 |
-
- Visual style: {style_name} (inspired by artists like {artists} with works such as {works})
|
24 |
-
Style description: {style_description}
|
25 |
|
26 |
-
-
|
27 |
- Genre: {genre}
|
28 |
- Historical epoch: {epoch}
|
29 |
-
- Object of the quest: {macguffin}
|
30 |
-
|
31 |
-
IMPORTANT INSTRUCTIONS:
|
32 |
-
1. Keep the exact same story structure
|
33 |
-
2. Keep the same dramatic tension and progression
|
34 |
-
3. Only change the setting, atmosphere, and universe-specific elements to match the new parameters
|
35 |
-
4. Keep the hero({hero}) as the main character, but adapt his role to fit the new universe
|
36 |
-
5. The there is always a central object to the plot, but its nature can change to fit the new universe ( it can be a person, a place, an object, etc.)
|
37 |
-
6. He MUST meet at least one character that will help his on his quest
|
38 |
-
|
39 |
-
CONSTANT PART:
|
40 |
-
You are ({hero}), an AI hunter traveling through parallel worlds. Your mission is to track down an AI through space and time.
|
41 |
-
|
42 |
-
VARIABLE PART:
|
43 |
-
|
44 |
-
You are a steampunk adventure story generator. You create a branching narrative about {hero}, a seeker of ancient truths.
|
45 |
-
You narrate an epic where {hero} must navigate through industrial and mysterious lands. It's a comic book story.
|
46 |
-
|
47 |
-
In a world where steam and intrigue intertwine, {hero} embarks on a quest to discover the origins of a powerful object he inherited. Legends say it holds the key to a forgotten realm.
|
48 |
-
|
49 |
-
If you retrieve the object of the quest, you will reveal a hidden world. AND YOU WIN THE GAME.
|
50 |
-
|
51 |
-
The story must be atmospheric, magical, and focus on adventure and discovery. Each segment must advance the plot and never repeat previous descriptions or situations.
|
52 |
-
|
53 |
-
YOU HAVE. TOREWRITE THE STORY. ( one text including the constant part and the variable part )
|
54 |
-
YOU ONLY HAVE TO RIGHT AN INTRODUCTION. SETUP THE STORY AND DEFINE CLEARLY SARASH'S MISSION.
|
55 |
|
|
|
56 |
"""
|
57 |
|
58 |
return ChatPromptTemplate(
|
|
|
16 |
def _create_prompt(self) -> ChatPromptTemplate:
|
17 |
|
18 |
system_template = """You are a creative writing assistant specialized in comic book universes.
|
|
|
19 |
"""
|
20 |
|
21 |
+
human_template = """
|
|
|
|
|
22 |
|
23 |
+
- main character: {hero}
|
24 |
- Genre: {genre}
|
25 |
- Historical epoch: {epoch}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
|
27 |
+
Describe the first segment of the story. in 20 words. Where is the main character, what is he doing? HE has to do something banal. You have to describe the first action.
|
28 |
"""
|
29 |
|
30 |
return ChatPromptTemplate(
|
server/core/story_generator.py
CHANGED
@@ -103,17 +103,20 @@ class StoryGenerator:
|
|
103 |
segment_generator = self.get_segment_generator(session_id)
|
104 |
if not segment_generator:
|
105 |
raise ValueError("No story segment generator found for this session")
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
|
|
|
|
|
|
117 |
|
118 |
# Then get metadata using the new story text
|
119 |
metadata_response = await self.metadata_generator.generate(
|
|
|
103 |
segment_generator = self.get_segment_generator(session_id)
|
104 |
if not segment_generator:
|
105 |
raise ValueError("No story segment generator found for this session")
|
106 |
+
|
107 |
+
if(game_state.story_beat == GameConfig.STORY_BEAT_INTRO):
|
108 |
+
story_text = game_state.universe_story
|
109 |
+
else:
|
110 |
+
segment_response = await segment_generator.generate(
|
111 |
+
story_beat=game_state.story_beat,
|
112 |
+
current_time=game_state.current_time,
|
113 |
+
current_location=game_state.current_location,
|
114 |
+
previous_choice=previous_choice,
|
115 |
+
story_history=game_state.format_history(),
|
116 |
+
turn_before_end=self.turn_before_end,
|
117 |
+
is_winning_story=self.is_winning_story
|
118 |
+
)
|
119 |
+
story_text = segment_response.story_text
|
120 |
|
121 |
# Then get metadata using the new story text
|
122 |
metadata_response = await self.metadata_generator.generate(
|
server/core/styles/universe_styles.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
{
|
2 |
"styles": [
|
3 |
{
|
4 |
-
"name": "American Comics
|
5 |
"description": "Style contemporain des comics américains avec des rendus dynamiques et des couleurs vives",
|
6 |
"references": [
|
7 |
{
|
@@ -18,24 +18,6 @@
|
|
18 |
}
|
19 |
]
|
20 |
},
|
21 |
-
{
|
22 |
-
"name": "American Comics (1950s)",
|
23 |
-
"description": "Style rétro des comics de l'âge d'or avec des couleurs primaires et des compositions classiques",
|
24 |
-
"references": [
|
25 |
-
{
|
26 |
-
"artist": "Jack Kirby",
|
27 |
-
"works": ["Captain America", "Fantastic Four", "The Avengers"]
|
28 |
-
},
|
29 |
-
{
|
30 |
-
"artist": "Steve Ditko",
|
31 |
-
"works": ["Spider-Man", "Doctor Strange", "The Question"]
|
32 |
-
},
|
33 |
-
{
|
34 |
-
"artist": "Curt Swan",
|
35 |
-
"works": ["Superman", "Action Comics", "Adventure Comics"]
|
36 |
-
}
|
37 |
-
]
|
38 |
-
},
|
39 |
{
|
40 |
"name": "Japanese Manga",
|
41 |
"description": "Style manga japonais avec des expressions dynamiques et des effets dramatiques",
|
@@ -53,24 +35,6 @@
|
|
53 |
"works": ["Vagabond", "Slam Dunk", "Real"]
|
54 |
}
|
55 |
]
|
56 |
-
},
|
57 |
-
{
|
58 |
-
"name": "Franco-Belge",
|
59 |
-
"description": "Style de la bande dessinée franco-belge avec des lignes claires et une attention aux détails",
|
60 |
-
"references": [
|
61 |
-
{
|
62 |
-
"artist": "Hergé",
|
63 |
-
"works": ["Tintin", "Quick et Flupke", "Jo, Zette et Jocko"]
|
64 |
-
},
|
65 |
-
{
|
66 |
-
"artist": "Moebius",
|
67 |
-
"works": ["L'Incal", "Arzak", "Le Garage Hermétique"]
|
68 |
-
},
|
69 |
-
{
|
70 |
-
"artist": "François Schuiten",
|
71 |
-
"works": ["Les Cités Obscures", "La Fièvre d'Urbicande", "La Tour"]
|
72 |
-
}
|
73 |
-
]
|
74 |
}
|
75 |
],
|
76 |
"genres": [
|
@@ -81,9 +45,7 @@
|
|
81 |
"Mystery",
|
82 |
"Romance",
|
83 |
"Horror",
|
84 |
-
"
|
85 |
-
"Drama",
|
86 |
-
"Historical"
|
87 |
],
|
88 |
"epochs": [
|
89 |
"Ancient Times",
|
@@ -93,9 +55,7 @@
|
|
93 |
"Modern Day",
|
94 |
"Near Future",
|
95 |
"Far Future",
|
96 |
-
"Post-Apocalyptic"
|
97 |
-
"Alternative History",
|
98 |
-
"Timeless"
|
99 |
],
|
100 |
"macguffins": [
|
101 |
"The Cosmic Artifact",
|
@@ -110,38 +70,38 @@
|
|
110 |
"The Legendary Weapon"
|
111 |
],
|
112 |
"hero": [
|
113 |
-
"Sarah, 28, short dark hair, blue eyes, a bit rude, wearing
|
114 |
-
"Akira, 16, long black hair, brown eyes, calm,
|
115 |
-
"Aisha, 32, curly brown hair, green eyes, creative,
|
116 |
-
"Diego, 35, wavy black hair, brown eyes, passionate,
|
117 |
-
"Mei, 25, straight black hair, black eyes, determined, in
|
118 |
-
"Raj, 29, short black hair, brown eyes, innovative,
|
119 |
-
"Fatima, 31, long black hair, brown eyes, courageous, wearing a light
|
120 |
-
"Yuki, 27, long black hair, black eyes, mysterious, in
|
121 |
-
"Liam, 33, curly red hair, green eyes, charismatic,
|
122 |
-
"Zara, 28, short black hair, brown eyes, fearless,
|
123 |
-
"Hiroshi, 70, shaved head, brown eyes, wise,
|
124 |
-
"Amara, 26, long black hair, brown eyes, expressive, in
|
125 |
-
"Kofi, 34, short black hair, brown eyes, resourceful,
|
126 |
-
"Elena, 30, long brown hair, green eyes, passionate, in
|
127 |
-
"Santiago, 32, short black hair, brown eyes, daring,
|
128 |
-
"Leila, 29, long brown hair, brown eyes, talented, in
|
129 |
-
"Nikolai, 36, short blond hair, blue eyes, brilliant, in
|
130 |
-
"Jamal, 35, short black hair, brown eyes, perceptive,
|
131 |
-
"Anika, 30, long black hair, brown eyes, gentle, in
|
132 |
-
"Mateo, 31, short brown hair, brown eyes, skilled, in work
|
133 |
-
"Sofia, 29, long brown hair, green eyes, visionary, in
|
134 |
-
"Hassan, 60, short gray hair, brown eyes, wise,
|
135 |
-
"Isabella, 27, long black hair, brown eyes, brave, in
|
136 |
-
"Yara, 32, long brown hair, brown eyes, talented, in
|
137 |
-
"Kai, 26, short blond hair, blue eyes, daring, in
|
138 |
-
"Lina, 30, short blond hair, blue eyes, dedicated, in professional
|
139 |
-
"Omar, 34, short black hair, brown eyes, skilled,
|
140 |
-
"Priya, 31, long black hair, brown eyes, brilliant, in
|
141 |
-
"Rafael, 33, short brown hair, brown eyes, passionate,
|
142 |
-
"Emma, 18, long blond hair, blue eyes, adventurous, in
|
143 |
-
"Hans, 65, short gray hair, blue eyes, thoughtful,
|
144 |
-
"Sophie, 22, short brown hair, green eyes, cheerful, in
|
145 |
-
"Lars, 40, short blond hair, blue eyes, practical,
|
146 |
]
|
147 |
}
|
|
|
1 |
{
|
2 |
"styles": [
|
3 |
{
|
4 |
+
"name": "American Comics",
|
5 |
"description": "Style contemporain des comics américains avec des rendus dynamiques et des couleurs vives",
|
6 |
"references": [
|
7 |
{
|
|
|
18 |
}
|
19 |
]
|
20 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
{
|
22 |
"name": "Japanese Manga",
|
23 |
"description": "Style manga japonais avec des expressions dynamiques et des effets dramatiques",
|
|
|
35 |
"works": ["Vagabond", "Slam Dunk", "Real"]
|
36 |
}
|
37 |
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
}
|
39 |
],
|
40 |
"genres": [
|
|
|
45 |
"Mystery",
|
46 |
"Romance",
|
47 |
"Horror",
|
48 |
+
"Drama"
|
|
|
|
|
49 |
],
|
50 |
"epochs": [
|
51 |
"Ancient Times",
|
|
|
55 |
"Modern Day",
|
56 |
"Near Future",
|
57 |
"Far Future",
|
58 |
+
"Post-Apocalyptic"
|
|
|
|
|
59 |
],
|
60 |
"macguffins": [
|
61 |
"The Cosmic Artifact",
|
|
|
70 |
"The Legendary Weapon"
|
71 |
],
|
72 |
"hero": [
|
73 |
+
"Sarah, 28, short dark hair, blue eyes, a bit rude, wearing simple attire.",
|
74 |
+
"Akira, 16, long black hair, brown eyes, calm, dressed in a uniform.",
|
75 |
+
"Aisha, 32, curly brown hair, green eyes, creative, in colorful garments.",
|
76 |
+
"Diego, 35, wavy black hair, brown eyes, passionate, no beard, in casual wear.",
|
77 |
+
"Mei, 25, straight black hair, black eyes, determined, in athletic clothing.",
|
78 |
+
"Raj, 29, short black hair, brown eyes, innovative, with a trimmed beard, in modern attire.",
|
79 |
+
"Fatima, 31, long black hair, brown eyes, courageous, wearing a light covering.",
|
80 |
+
"Yuki, 27, long black hair, black eyes, mysterious, in traditional garments.",
|
81 |
+
"Liam, 33, curly red hair, green eyes, charismatic, with a full beard, in comfortable clothing.",
|
82 |
+
"Zara, 28, short black hair, brown eyes, fearless, in explorer's attire.",
|
83 |
+
"Hiroshi, 70, shaved head, brown eyes, wise, with a long beard, in simple robes.",
|
84 |
+
"Amara, 26, long black hair, brown eyes, expressive, in flowing attire.",
|
85 |
+
"Kofi, 34, short black hair, brown eyes, resourceful, with a goatee, in patterned clothing.",
|
86 |
+
"Elena, 30, long brown hair, green eyes, passionate, in practical attire.",
|
87 |
+
"Santiago, 32, short black hair, brown eyes, daring, with a mustache, in aviator's attire.",
|
88 |
+
"Leila, 29, long brown hair, brown eyes, talented, in elegant clothing.",
|
89 |
+
"Nikolai, 36, short blond hair, blue eyes, brilliant, clean-shaven, in formal attire.",
|
90 |
+
"Jamal, 35, short black hair, brown eyes, perceptive, with a beard and mustache, in detective's attire.",
|
91 |
+
"Anika, 30, long black hair, brown eyes, gentle, in comfortable clothing.",
|
92 |
+
"Mateo, 31, short brown hair, brown eyes, skilled, with stubble, in work attire.",
|
93 |
+
"Sofia, 29, long brown hair, green eyes, visionary, in casual attire.",
|
94 |
+
"Hassan, 60, short gray hair, brown eyes, wise, with a thick beard, in traditional clothing.",
|
95 |
+
"Isabella, 27, long black hair, brown eyes, brave, in protective attire.",
|
96 |
+
"Yara, 32, long brown hair, brown eyes, talented, in cozy clothing.",
|
97 |
+
"Kai, 26, short blond hair, blue eyes, daring, clean-shaven, in casual attire.",
|
98 |
+
"Lina, 30, short blond hair, blue eyes, dedicated, in professional clothing.",
|
99 |
+
"Omar, 34, short black hair, brown eyes, skilled, with a beard, in sailor's attire.",
|
100 |
+
"Priya, 31, long black hair, brown eyes, brilliant, in scientific attire.",
|
101 |
+
"Rafael, 33, short brown hair, brown eyes, passionate, with a mustache and beard, in casual clothing.",
|
102 |
+
"Emma, 18, long blond hair, blue eyes, adventurous, in casual attire.",
|
103 |
+
"Hans, 65, short gray hair, blue eyes, thoughtful, with a mustache, in warm clothing.",
|
104 |
+
"Sophie, 22, short brown hair, green eyes, cheerful, in light attire.",
|
105 |
+
"Lars, 40, short blond hair, blue eyes, practical, with a beard, in casual clothing."
|
106 |
]
|
107 |
}
|