Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -8,6 +8,21 @@ from streamlit_flow import streamlit_flow
|
|
8 |
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
|
9 |
from streamlit_flow.layouts import TreeLayout
|
10 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11 |
# ๐ Game World Data - SITUATIONS and ACTIONS expanded with humorous elements
|
12 |
SITUATIONS = [
|
13 |
{
|
@@ -182,40 +197,141 @@ FAILURE_CONCLUSIONS = [
|
|
182 |
"Itโs okay, every cat has a learning curve. ๐"
|
183 |
]
|
184 |
|
185 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
186 |
def generate_encounter_conclusion(situation, action, outcome):
|
187 |
if outcome:
|
188 |
return random.choice(SUCCESS_CONCLUSIONS)
|
189 |
else:
|
190 |
return random.choice(FAILURE_CONCLUSIONS)
|
191 |
|
192 |
-
#
|
193 |
-
def
|
194 |
-
|
|
|
195 |
|
196 |
-
#
|
197 |
-
|
198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
|
200 |
-
# The rest of the code remains mostly the same
|
201 |
# ๐ฎ Main Game Application
|
202 |
def main():
|
203 |
st.title("๐ฑ Cat Rider ๐")
|
204 |
-
st.markdown("""
|
205 |
-
## Welcome to Cat Rider!
|
206 |
-
In this immersive adventure, you will explore the thrilling world of feline riders. This game sets the stage for dramatic situations and guided storytelling with engaging interactive elements.
|
207 |
-
""")
|
208 |
|
209 |
-
# ๐ Game Rules
|
210 |
st.markdown("""
|
211 |
### ๐ Game Rules
|
212 |
-
|
|
213 |
-
|
214 |
-
| 1๏ธโฃ
|
215 |
-
| 2๏ธโฃ
|
216 |
-
| 3๏ธโฃ
|
217 |
-
| 4๏ธโฃ
|
218 |
-
| 5๏ธโฃ
|
219 |
""")
|
220 |
|
221 |
# ๐ Initialize game state
|
@@ -224,77 +340,100 @@ def main():
|
|
224 |
'user_id': str(uuid.uuid4()),
|
225 |
'score': 0,
|
226 |
'history': {},
|
227 |
-
'gear_strength':
|
228 |
-
'rider_skill':
|
|
|
|
|
229 |
'history_df': pd.DataFrame(columns=['user_id', 'timestamp', 'situation_id', 'situation_name', 'situation_emoji', 'situation_type', 'action_id', 'action_name', 'action_emoji', 'action_type', 'outcome', 'conclusion', 'gear_strength', 'rider_skill', 'score'])
|
230 |
}
|
231 |
|
232 |
-
#
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
|
299 |
if __name__ == "__main__":
|
300 |
main()
|
|
|
|
|
|
|
|
8 |
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
|
9 |
from streamlit_flow.layouts import TreeLayout
|
10 |
|
11 |
+
# ๐ฑ Cat Rider and Gear Data
|
12 |
+
CAT_RIDERS = [
|
13 |
+
{"name": "Whiskers", "type": "Speed", "emoji": "๐พ", "strength": 3, "skill": 7},
|
14 |
+
{"name": "Fluffy", "type": "Bravery", "emoji": "๐ฆ", "strength": 5, "skill": 5},
|
15 |
+
{"name": "Midnight", "type": "Stealth", "emoji": "๐", "strength": 4, "skill": 6},
|
16 |
+
{"name": "Bella", "type": "Charm", "emoji": "๐บ", "strength": 2, "skill": 8}
|
17 |
+
]
|
18 |
+
|
19 |
+
RIDING_GEAR = [
|
20 |
+
{"name": "Feathered Boots", "type": "Agility", "strength": 2},
|
21 |
+
{"name": "Golden Armor", "type": "Defense", "strength": 4},
|
22 |
+
{"name": "Magic Whisker Wand", "type": "Magic", "strength": 3},
|
23 |
+
{"name": "Sleek Shadow Cape", "type": "Stealth", "strength": 1}
|
24 |
+
]
|
25 |
+
|
26 |
# ๐ Game World Data - SITUATIONS and ACTIONS expanded with humorous elements
|
27 |
SITUATIONS = [
|
28 |
{
|
|
|
197 |
"Itโs okay, every cat has a learning curve. ๐"
|
198 |
]
|
199 |
|
200 |
+
# ๐ง Game Mechanics
|
201 |
+
def generate_situation():
|
202 |
+
return random.choice(SITUATIONS)
|
203 |
+
|
204 |
+
def generate_actions():
|
205 |
+
return random.sample(ACTIONS, min(3, len(ACTIONS)))
|
206 |
+
|
207 |
+
def evaluate_action(action, gear_strength, rider_skill, history):
|
208 |
+
base_success_chance = (gear_strength + rider_skill) / 2
|
209 |
+
if action['id'] in history:
|
210 |
+
success_chance = base_success_chance + (history[action['id']] * 2)
|
211 |
+
else:
|
212 |
+
success_chance = base_success_chance
|
213 |
+
outcome = random.randint(1, 100) <= success_chance
|
214 |
+
return outcome, success_chance
|
215 |
+
|
216 |
def generate_encounter_conclusion(situation, action, outcome):
|
217 |
if outcome:
|
218 |
return random.choice(SUCCESS_CONCLUSIONS)
|
219 |
else:
|
220 |
return random.choice(FAILURE_CONCLUSIONS)
|
221 |
|
222 |
+
# ๐ณ Journey Visualization with Heterogeneous Graph Structure
|
223 |
+
def create_heterogeneous_graph(history_df):
|
224 |
+
nodes = []
|
225 |
+
edges = []
|
226 |
|
227 |
+
# Define node shapes based on situation and action types
|
228 |
+
situation_shapes = {
|
229 |
+
"escape": "diamond",
|
230 |
+
"exploration": "triangle",
|
231 |
+
"competition": "star"
|
232 |
+
}
|
233 |
+
action_shapes = {
|
234 |
+
"skill": "square",
|
235 |
+
"physical": "circle",
|
236 |
+
"social": "hexagon",
|
237 |
+
"mental": "octagon"
|
238 |
+
}
|
239 |
+
|
240 |
+
for index, row in history_df.iterrows():
|
241 |
+
situation_id = f"situation-{index}"
|
242 |
+
action_id = f"action-{index}"
|
243 |
+
conclusion_id = f"conclusion-{index}"
|
244 |
+
|
245 |
+
# Create situation node
|
246 |
+
situation_content = f"{row['situation_emoji']} {row['situation_name']}\n๐ {row['timestamp']}"
|
247 |
+
situation_node = StreamlitFlowNode(situation_id, (0, 0), {'content': situation_content}, 'output', 'bottom', 'top', shape=situation_shapes.get(row['situation_type'], 'ellipse'))
|
248 |
+
nodes.append(situation_node)
|
249 |
+
|
250 |
+
# Create action node
|
251 |
+
action_content = f"{row['action_emoji']} {row['action_name']}\nOutcome: {'โ
Success' if row['outcome'] else 'โ Failure'}"
|
252 |
+
action_node = StreamlitFlowNode(action_id, (0, 0), {'content': action_content}, 'output', 'bottom', 'top', shape=action_shapes.get(row['action_type'], 'ellipse'))
|
253 |
+
nodes.append(action_node)
|
254 |
+
|
255 |
+
# Create conclusion node
|
256 |
+
conclusion_content = f"๐ {row['conclusion']}\n๐ช Gear: {row['gear_strength']:.2f} | ๐๏ธ Skill: {row['rider_skill']:.2f}"
|
257 |
+
conclusion_node = StreamlitFlowNode(conclusion_id, (0, 0), {'content': conclusion_content}, 'output', 'bottom', 'top', shape='parallelogram')
|
258 |
+
nodes.append(conclusion_node)
|
259 |
+
|
260 |
+
# Create edges
|
261 |
+
edges.append(StreamlitFlowEdge(f"{situation_id}-{action_id}", situation_id, action_id, animated=True, dashed=False))
|
262 |
+
edges.append(StreamlitFlowEdge(f"{action_id}-{conclusion_id}", action_id, conclusion_id, animated=True, dashed=False))
|
263 |
+
|
264 |
+
# Create edge to previous conclusion if not the first node
|
265 |
+
if index > 0:
|
266 |
+
prev_conclusion_id = f"conclusion-{index-1}"
|
267 |
+
edges.append(StreamlitFlowEdge(f"{prev_conclusion_id}-{situation_id}", prev_conclusion_id, situation_id, animated=True, dashed=True))
|
268 |
+
|
269 |
+
return nodes, edges
|
270 |
+
|
271 |
+
# ๐ Markdown Preview
|
272 |
+
def create_markdown_preview(history_df):
|
273 |
+
markdown = "## ๐ณ Journey Preview\n\n"
|
274 |
+
for index, row in history_df.iterrows():
|
275 |
+
indent = " " * (index * 3)
|
276 |
+
markdown += f"{indent}๐ **{row['situation_name']}** ({row['situation_type']})\n"
|
277 |
+
markdown += f"{indent} โช {row['action_emoji']} {row['action_name']} ({row['action_type']}): "
|
278 |
+
markdown += "โ
Success\n" if row['outcome'] else "โ Failure\n"
|
279 |
+
markdown += f"{indent} ๐ {row['conclusion']}\n"
|
280 |
+
markdown += f"{indent} ๐ช Gear: {row['gear_strength']:.2f} | ๐๏ธ Skill: {row['rider_skill']:.2f}\n\n"
|
281 |
+
return markdown
|
282 |
+
|
283 |
+
# ๐ Game State Management
|
284 |
+
def update_game_state(game_state, situation, action, outcome, timestamp):
|
285 |
+
conclusion = generate_encounter_conclusion(situation, action, outcome)
|
286 |
+
game_state = update_character_stats(game_state, outcome)
|
287 |
+
|
288 |
+
new_record = pd.DataFrame({
|
289 |
+
'user_id': [game_state['user_id']],
|
290 |
+
'timestamp': [timestamp],
|
291 |
+
'situation_id': [situation['id']],
|
292 |
+
'situation_name': [situation['name']],
|
293 |
+
'situation_emoji': [situation['emoji']],
|
294 |
+
'situation_type': [situation['type']],
|
295 |
+
'action_id': [action['id']],
|
296 |
+
'action_name': [action['name']],
|
297 |
+
'action_emoji': [action['emoji']],
|
298 |
+
'action_type': [action['type']],
|
299 |
+
'outcome': [outcome],
|
300 |
+
'conclusion': [conclusion],
|
301 |
+
'gear_strength': [game_state['gear_strength']],
|
302 |
+
'rider_skill': [game_state['rider_skill']],
|
303 |
+
'score': [game_state['score']]
|
304 |
+
})
|
305 |
+
game_state['history_df'] = pd.concat([game_state['history_df'], new_record], ignore_index=True)
|
306 |
+
|
307 |
+
if action['id'] in game_state['history']:
|
308 |
+
game_state['history'][action['id']] += 1 if outcome else -1
|
309 |
+
else:
|
310 |
+
game_state['history'][action['id']] = 1 if outcome else -1
|
311 |
+
|
312 |
+
return game_state
|
313 |
+
|
314 |
+
# ๐ Update character stats based on the outcome
|
315 |
+
def update_character_stats(game_state, outcome):
|
316 |
+
if outcome:
|
317 |
+
game_state['gear_strength'] = min(10, game_state['gear_strength'] + random.uniform(0.1, 0.5))
|
318 |
+
game_state['rider_skill'] = min(10, game_state['rider_skill'] + random.uniform(0.1, 0.5))
|
319 |
+
return game_state
|
320 |
|
|
|
321 |
# ๐ฎ Main Game Application
|
322 |
def main():
|
323 |
st.title("๐ฑ Cat Rider ๐")
|
|
|
|
|
|
|
|
|
324 |
|
325 |
+
# ๐ Game Rules
|
326 |
st.markdown("""
|
327 |
### ๐ Game Rules
|
328 |
+
| Step | Description |
|
329 |
+
|------|-------------|
|
330 |
+
| 1๏ธโฃ | Choose your Cat Rider |
|
331 |
+
| 2๏ธโฃ | Select your Riding Gear |
|
332 |
+
| 3๏ธโฃ | Set off on an Adventure |
|
333 |
+
| 4๏ธโฃ | Encounter Challenges and Make Decisions |
|
334 |
+
| 5๏ธโฃ | Complete the Quest and Grow Stronger |
|
335 |
""")
|
336 |
|
337 |
# ๐ Initialize game state
|
|
|
340 |
'user_id': str(uuid.uuid4()),
|
341 |
'score': 0,
|
342 |
'history': {},
|
343 |
+
'gear_strength': 0,
|
344 |
+
'rider_skill': 0,
|
345 |
+
'cat_rider': None,
|
346 |
+
'riding_gear': None,
|
347 |
'history_df': pd.DataFrame(columns=['user_id', 'timestamp', 'situation_id', 'situation_name', 'situation_emoji', 'situation_type', 'action_id', 'action_name', 'action_emoji', 'action_type', 'outcome', 'conclusion', 'gear_strength', 'rider_skill', 'score'])
|
348 |
}
|
349 |
|
350 |
+
# ๐ฑ Cat Rider Selection
|
351 |
+
if st.session_state.game_state['cat_rider'] is None:
|
352 |
+
st.markdown("## Choose Your Cat Rider:")
|
353 |
+
cols = st.columns(len(CAT_RIDERS))
|
354 |
+
for i, rider in enumerate(CAT_RIDERS):
|
355 |
+
if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})"):
|
356 |
+
st.session_state.game_state['cat_rider'] = rider
|
357 |
+
st.session_state.game_state['rider_skill'] = rider['skill']
|
358 |
+
|
359 |
+
# ๐ Riding Gear Selection
|
360 |
+
if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None:
|
361 |
+
st.markdown("## Select Your Riding Gear:")
|
362 |
+
cols = st.columns(len(RIDING_GEAR))
|
363 |
+
for i, gear in enumerate(RIDING_GEAR):
|
364 |
+
if cols[i].button(f"{gear['name']} ({gear['type']})"):
|
365 |
+
st.session_state.game_state['riding_gear'] = gear
|
366 |
+
st.session_state.game_state['gear_strength'] = gear['strength']
|
367 |
+
|
368 |
+
# ๐ญ Game Loop
|
369 |
+
if st.session_state.game_state['cat_rider'] is not None and st.session_state.game_state['riding_gear'] is not None:
|
370 |
+
situation = generate_situation()
|
371 |
+
actions = generate_actions()
|
372 |
+
|
373 |
+
st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
|
374 |
+
st.markdown(situation['description'])
|
375 |
+
st.markdown("### ๐ญ Choose your action:")
|
376 |
+
|
377 |
+
cols = st.columns(3)
|
378 |
+
for i, action in enumerate(actions):
|
379 |
+
if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})"):
|
380 |
+
outcome, success_chance = evaluate_action(action, st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill'], st.session_state.game_state['history'])
|
381 |
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
382 |
+
|
383 |
+
st.markdown(f"You decided to: **{action['name']}** ({action['type']})")
|
384 |
+
st.markdown(action['description'])
|
385 |
+
st.markdown(f"**Outcome:** {'โ
Success!' if outcome else 'โ Failure.'}")
|
386 |
+
st.markdown(f"**Success Chance:** {success_chance:.2f}%")
|
387 |
+
|
388 |
+
if outcome:
|
389 |
+
st.session_state.game_state['score'] += 1
|
390 |
+
|
391 |
+
# ๐ Update game state
|
392 |
+
st.session_state.game_state = update_game_state(
|
393 |
+
st.session_state.game_state,
|
394 |
+
situation,
|
395 |
+
action,
|
396 |
+
outcome,
|
397 |
+
timestamp
|
398 |
+
)
|
399 |
+
|
400 |
+
# Display conclusion
|
401 |
+
conclusion = st.session_state.game_state['history_df'].iloc[-1]['conclusion']
|
402 |
+
st.markdown(f"**Encounter Conclusion:** {conclusion}")
|
403 |
+
|
404 |
+
# Display updated stats
|
405 |
+
st.markdown(f"**Updated Stats:**")
|
406 |
+
st.markdown(f"๐ช Gear Strength: {st.session_state.game_state['gear_strength']:.2f}")
|
407 |
+
st.markdown(f"๐๏ธ Rider Skill: {st.session_state.game_state['rider_skill']:.2f}")
|
408 |
+
|
409 |
+
# ๐ Display Markdown Preview
|
410 |
+
if not st.session_state.game_state['history_df'].empty:
|
411 |
+
st.markdown(create_markdown_preview(st.session_state.game_state['history_df']))
|
412 |
+
|
413 |
+
# ๐ณ Display Heterogeneous Journey Graph
|
414 |
+
if not st.session_state.game_state['history_df'].empty:
|
415 |
+
st.markdown("## ๐ณ Your Journey (Heterogeneous Graph)")
|
416 |
+
nodes, edges = create_heterogeneous_graph(st.session_state.game_state['history_df'])
|
417 |
+
try:
|
418 |
+
streamlit_flow('cat_rider_flow',
|
419 |
+
nodes,
|
420 |
+
edges,
|
421 |
+
layout=TreeLayout(direction='down'),
|
422 |
+
fit_view=True,
|
423 |
+
height=600)
|
424 |
+
except Exception as e:
|
425 |
+
st.error(f"An error occurred while rendering the journey graph: {str(e)}")
|
426 |
+
st.markdown("Please try refreshing the page if the graph doesn't appear.")
|
427 |
+
|
428 |
+
# ๐ Character Stats Visualization
|
429 |
+
data = {"Stat": ["Gear Strength ๐ก๏ธ", "Rider Skill ๐"],
|
430 |
+
"Value": [st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill']]}
|
431 |
+
df = pd.DataFrame(data)
|
432 |
+
fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats ๐")
|
433 |
+
st.plotly_chart(fig)
|
434 |
|
435 |
if __name__ == "__main__":
|
436 |
main()
|
437 |
+
|
438 |
+
|
439 |
+
|