update
Browse files- client/src/components/GameNavigation.jsx +7 -1
- client/src/components/StoryChoices.jsx +56 -7
- client/src/components/UniverseSlotMachine.jsx +1 -1
- client/src/layouts/config.js +1 -1
- server/core/generators/metadata_generator.py +3 -1
- server/core/generators/story_segment_generator.py +4 -13
- server/core/generators/universe_generator.py +1 -0
client/src/components/GameNavigation.jsx
CHANGED
@@ -16,10 +16,16 @@ export function GameNavigation() {
|
|
16 |
const { isSoundEnabled, setIsSoundEnabled, playSound } = useSoundSystem();
|
17 |
const { downloadStoryImage } = useStoryCapture();
|
18 |
const containerRef = useRef(null);
|
|
|
19 |
|
20 |
const handleBack = () => {
|
21 |
playSound("page");
|
22 |
-
|
|
|
|
|
|
|
|
|
|
|
23 |
};
|
24 |
|
25 |
const handleToggleSound = () => {
|
|
|
16 |
const { isSoundEnabled, setIsSoundEnabled, playSound } = useSoundSystem();
|
17 |
const { downloadStoryImage } = useStoryCapture();
|
18 |
const containerRef = useRef(null);
|
19 |
+
const location = window.location.pathname;
|
20 |
|
21 |
const handleBack = () => {
|
22 |
playSound("page");
|
23 |
+
if (location === "/game") {
|
24 |
+
navigate("/");
|
25 |
+
window.location.reload();
|
26 |
+
} else {
|
27 |
+
navigate("/");
|
28 |
+
}
|
29 |
};
|
30 |
|
31 |
const handleToggleSound = () => {
|
client/src/components/StoryChoices.jsx
CHANGED
@@ -38,6 +38,43 @@ const RANDOM_PLACEHOLDERS = [
|
|
38 |
"A portal opens, and out steps the hero's evil twin made entirely of cheese...",
|
39 |
"The moon starts beatboxing an ominous rhythm...",
|
40 |
"Every nearby plant suddenly develops a British accent and starts having tea...",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
];
|
42 |
|
43 |
// Function to convert text with ** to Chip elements
|
@@ -70,12 +107,15 @@ export function StoryChoices() {
|
|
70 |
const [sarahRecommendation, setSarahRecommendation] = useState(null);
|
71 |
const [showCustomDialog, setShowCustomDialog] = useState(false);
|
72 |
const [customChoice, setCustomChoice] = useState("");
|
73 |
-
const [
|
74 |
-
|
|
|
75 |
RANDOM_PLACEHOLDERS[
|
76 |
Math.floor(Math.random() * RANDOM_PLACEHOLDERS.length)
|
77 |
-
]
|
78 |
-
|
|
|
|
|
79 |
const {
|
80 |
choices,
|
81 |
onChoice,
|
@@ -113,9 +153,18 @@ export function StoryChoices() {
|
|
113 |
const storyText = lastSegment?.rawText || "";
|
114 |
|
115 |
const getRandomPlaceholder = () => {
|
116 |
-
|
117 |
-
|
118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
119 |
};
|
120 |
|
121 |
if (isGameOver()) {
|
|
|
38 |
"A portal opens, and out steps the hero's evil twin made entirely of cheese...",
|
39 |
"The moon starts beatboxing an ominous rhythm...",
|
40 |
"Every nearby plant suddenly develops a British accent and starts having tea...",
|
41 |
+
"A giant rubber duck floats down from the sky...",
|
42 |
+
"The hero's sword turns into a bouquet of flowers...",
|
43 |
+
"A mysterious fog rolls in, bringing with it the scent of fresh cookies...",
|
44 |
+
"The hero's shoes start tap dancing on their own...",
|
45 |
+
"A unicorn gallops by, leaving a trail of glitter...",
|
46 |
+
"The sky turns neon green and starts flashing like a disco...",
|
47 |
+
"A talking squirrel offers the hero some sage advice...",
|
48 |
+
"The hero's reflection in the water winks and waves...",
|
49 |
+
"A giant marshmallow bounces across the landscape...",
|
50 |
+
"The hero's cape transforms into a pair of wings...",
|
51 |
+
"A parade of tiny elephants marches through the scene...",
|
52 |
+
"The sun suddenly dons sunglasses and starts singing...",
|
53 |
+
"A mysterious door appears, leading to a candy world...",
|
54 |
+
"The hero's hat turns into a magical top hat...",
|
55 |
+
"A rainbow-colored river flows uphill...",
|
56 |
+
"The hero's backpack starts floating and glowing...",
|
57 |
+
"A group of fairies begins to dance around the hero...",
|
58 |
+
"The hero's footsteps echo with musical notes...",
|
59 |
+
"A giant book opens, revealing a new adventure...",
|
60 |
+
"The hero's pet dragon starts juggling fireballs...",
|
61 |
+
"A spaceship lands and out steps an alien with a top hat...",
|
62 |
+
"The hero's backpack starts singing show tunes...",
|
63 |
+
"A rainbow appears and a leprechaun slides down it...",
|
64 |
+
"The hero's pet suddenly starts speaking in riddles...",
|
65 |
+
"A gust of wind brings a shower of confetti...",
|
66 |
+
"The hero's map transforms into a treasure map...",
|
67 |
+
"A giant clock appears, ticking backwards...",
|
68 |
+
"The hero's footsteps leave a trail of glowing footprints...",
|
69 |
+
"A parade of penguins marches by, playing instruments...",
|
70 |
+
"The hero's hat flies off and starts floating in mid-air...",
|
71 |
+
"A mysterious voice narrates the hero's every move...",
|
72 |
+
"The hero's shadow starts mimicking their actions in exaggerated ways...",
|
73 |
+
"A pikachu appears, looking curious...",
|
74 |
+
"A bublizarre jumps out from the bushes...",
|
75 |
+
"A pikachu flies by, leaving a trail of sparkles...",
|
76 |
+
"A salameche suddenly joins the hero's journey...",
|
77 |
+
"A carapuce watches from a distance, intrigued...",
|
78 |
];
|
79 |
|
80 |
// Function to convert text with ** to Chip elements
|
|
|
107 |
const [sarahRecommendation, setSarahRecommendation] = useState(null);
|
108 |
const [showCustomDialog, setShowCustomDialog] = useState(false);
|
109 |
const [customChoice, setCustomChoice] = useState("");
|
110 |
+
const [lastUsedPlaceholder, setLastUsedPlaceholder] = useState("");
|
111 |
+
const [currentPlaceholder] = useState(() => {
|
112 |
+
const randomPlaceholder =
|
113 |
RANDOM_PLACEHOLDERS[
|
114 |
Math.floor(Math.random() * RANDOM_PLACEHOLDERS.length)
|
115 |
+
];
|
116 |
+
setLastUsedPlaceholder(randomPlaceholder);
|
117 |
+
return randomPlaceholder;
|
118 |
+
});
|
119 |
const {
|
120 |
choices,
|
121 |
onChoice,
|
|
|
153 |
const storyText = lastSegment?.rawText || "";
|
154 |
|
155 |
const getRandomPlaceholder = () => {
|
156 |
+
// Filter out the last used placeholder
|
157 |
+
const availablePlaceholders = RANDOM_PLACEHOLDERS.filter(
|
158 |
+
(p) => p !== lastUsedPlaceholder
|
159 |
+
);
|
160 |
+
// Get a random placeholder from the filtered list
|
161 |
+
const newPlaceholder =
|
162 |
+
availablePlaceholders[
|
163 |
+
Math.floor(Math.random() * availablePlaceholders.length)
|
164 |
+
];
|
165 |
+
// Update the last used placeholder
|
166 |
+
setLastUsedPlaceholder(newPlaceholder);
|
167 |
+
return newPlaceholder;
|
168 |
};
|
169 |
|
170 |
if (isGameOver()) {
|
client/src/components/UniverseSlotMachine.jsx
CHANGED
@@ -7,7 +7,7 @@ import { useSoundSystem } from "../contexts/SoundContext";
|
|
7 |
const SLOT_ANIMATION_DURATION = 2; // Duration of each slot animation
|
8 |
const SLOT_SPEED = 1; // Base speed of the slot animation (higher = faster)
|
9 |
const TOTAL_ANIMATION_DURATION = 1; // Total duration for each slot reel in seconds
|
10 |
-
const SLOT_START_DELAY =
|
11 |
|
12 |
// Random words for each category
|
13 |
const RANDOM_STYLES = [
|
|
|
7 |
const SLOT_ANIMATION_DURATION = 2; // Duration of each slot animation
|
8 |
const SLOT_SPEED = 1; // Base speed of the slot animation (higher = faster)
|
9 |
const TOTAL_ANIMATION_DURATION = 1; // Total duration for each slot reel in seconds
|
10 |
+
const SLOT_START_DELAY = 0.75; // Delay between each slot start in seconds
|
11 |
|
12 |
// Random words for each category
|
13 |
const RANDOM_STYLES = [
|
client/src/layouts/config.js
CHANGED
@@ -4,7 +4,7 @@ export const PANEL_SIZES = {
|
|
4 |
COLUMN: { width: 512, height: 1024 },
|
5 |
LANDSCAPE: { width: 768, height: 512 },
|
6 |
PANORAMIC: { width: 1024, height: 512 },
|
7 |
-
COVER_SIZE: { width: 512, height:
|
8 |
SQUARE: { width: 512, height: 512 },
|
9 |
};
|
10 |
|
|
|
4 |
COLUMN: { width: 512, height: 1024 },
|
5 |
LANDSCAPE: { width: 768, height: 512 },
|
6 |
PANORAMIC: { width: 1024, height: 512 },
|
7 |
+
COVER_SIZE: { width: 512, height: 1024 },
|
8 |
SQUARE: { width: 512, height: 512 },
|
9 |
};
|
10 |
|
server/core/generators/metadata_generator.py
CHANGED
@@ -69,7 +69,7 @@ Current story segment:
|
|
69 |
{is_end}
|
70 |
|
71 |
The choice not have to be the most obvious one. or even the most logical one.
|
72 |
-
It
|
73 |
|
74 |
- Each choice MUST be NO MORE than 6 words - this is a HARD limit
|
75 |
You must return a JSON object with the following format:
|
@@ -81,6 +81,8 @@ You must return a JSON object with the following format:
|
|
81 |
"choices": ["Choice 1", "Choice 2"] # ALWAYS exactly two choices, each max 6 words
|
82 |
}}}}
|
83 |
|
|
|
|
|
84 |
"""
|
85 |
|
86 |
|
|
|
69 |
{is_end}
|
70 |
|
71 |
The choice not have to be the most obvious one. or even the most logical one.
|
72 |
+
It must have a relation to the context of the story but it can be a choice that doesn't make sense.
|
73 |
|
74 |
- Each choice MUST be NO MORE than 6 words - this is a HARD limit
|
75 |
You must return a JSON object with the following format:
|
|
|
81 |
"choices": ["Choice 1", "Choice 2"] # ALWAYS exactly two choices, each max 6 words
|
82 |
}}}}
|
83 |
|
84 |
+
NEVER proposes a choice that is not a direct continuation of the story.
|
85 |
+
THE CHOICE HAVE TO REFERENCE THE CURRENT SEGMENT OF THE STORY.
|
86 |
"""
|
87 |
|
88 |
|
server/core/generators/story_segment_generator.py
CHANGED
@@ -78,8 +78,8 @@ Never describes game variables.
|
|
78 |
IT MUST BE THE DIRECT CONTINUATION OF THE CURRENT STORY.
|
79 |
You MUST mention the previous situation and what is happening now with the new choice.
|
80 |
Never propose choices or options. Never describe the game variables.
|
81 |
-
|
82 |
-
|
83 |
|
84 |
LIMIT: 15 words.
|
85 |
"""
|
@@ -163,17 +163,8 @@ LIMIT: 15 words.
|
|
163 |
|
164 |
# Si c'est un choix personnalisé, on l'utilise comme contexte pour générer la suite
|
165 |
if previous_choice and not previous_choice.startswith("Choice "):
|
166 |
-
what_to_represent = f"""
|
167 |
-
|
168 |
-
|
169 |
-
Write a story segment that:
|
170 |
-
1. Respects all previous rules about length and style
|
171 |
-
2. Ff you find a path to go in a special place, you have to travel there.
|
172 |
-
3. Directly follows and incorporates the player's choice
|
173 |
-
4. Maintains consistency with the universe and story
|
174 |
-
5. Naturally integrates the custom elements while staying true to the plot
|
175 |
-
|
176 |
-
MANDATORY : Start with a direct reaction to the player's choice, Show immediate consequences of their action. Then go forward in the story.
|
177 |
"""
|
178 |
|
179 |
# Créer les messages
|
|
|
78 |
IT MUST BE THE DIRECT CONTINUATION OF THE CURRENT STORY.
|
79 |
You MUST mention the previous situation and what is happening now with the new choice.
|
80 |
Never propose choices or options. Never describe the game variables.
|
81 |
+
|
82 |
+
{what_to_represent}
|
83 |
|
84 |
LIMIT: 15 words.
|
85 |
"""
|
|
|
163 |
|
164 |
# Si c'est un choix personnalisé, on l'utilise comme contexte pour générer la suite
|
165 |
if previous_choice and not previous_choice.startswith("Choice "):
|
166 |
+
what_to_represent = f"""Based on the player's custom choice: "{previous_choice}"
|
167 |
+
MANDATORY : Start with a direct reaction to the player's choice, Show immediate consequences of their action.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
"""
|
169 |
|
170 |
# Créer les messages
|
server/core/generators/universe_generator.py
CHANGED
@@ -25,6 +25,7 @@ class UniverseGenerator(BaseGenerator):
|
|
25 |
- Historical epoch: {epoch}
|
26 |
|
27 |
Describe the first segment of the story. in 30 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(
|
|
|
25 |
- Historical epoch: {epoch}
|
26 |
|
27 |
Describe the first segment of the story. in 30 words. Where is the main character, what is he doing? HE has to do something banal. You have to describe the first action.
|
28 |
+
Always write a direction to the story. (a small strange thing must happen, as a start of the story)
|
29 |
"""
|
30 |
|
31 |
return ChatPromptTemplate(
|