Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,712 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import plotly.express as px
|
4 |
+
import random
|
5 |
+
import uuid
|
6 |
+
from datetime import datetime
|
7 |
+
from streamlit_flow import streamlit_flow
|
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 (Expanded to 10 Situations)
|
27 |
+
SITUATIONS = [
|
28 |
+
{"id": "feline_escape", "name": "The Great Feline Escape", "description": "Your cat rider is trapped in an old mansion, which is about to be demolished. Using agility, wit, and bravery, orchestrate the perfect escape before the walls crumble! ๐๏ธ", "emoji": "๐ช", "type": "escape", "preferred_action": "agility"},
|
29 |
+
{"id": "lost_temple", "name": "The Treasure of the Lost Temple", "description": "On a quest to retrieve an ancient artifact, your cat rider must navigate through a labyrinth filled with traps and guardian spirits. Don't let the spooky ghosts get you! ๐ป", "emoji": "๐๏ธ", "type": "exploration", "preferred_action": "resourcefulness"},
|
30 |
+
{"id": "royal_tournament", "name": "The Royal Tournament", "description": "Compete in a grand tournament where the finest cat riders showcase their skills and bravery to earn the title of the Royal Rider. Prepare for a showdown with noble feline adversaries! ๐ฑ", "emoji": "๐", "type": "competition", "preferred_action": "bravery"},
|
31 |
+
{"id": "sky_race", "name": "The Sky Race", "description": "Compete in the annual Sky Race, where your cat rider flies across the skies on a magical broomstick! Watch out for lightning storms and mischievous crows! ๐ฉ๏ธ", "emoji": "โ๏ธ", "type": "competition", "preferred_action": "agility"},
|
32 |
+
{"id": "cheese_heist", "name": "The Great Cheese Heist", "description": "Your cat rider must sneak into the royal pantry to steal the legendary Cheese of Destiny. Beware โ the palace mice are guarding it! ๐ง", "emoji": "๐ง", "type": "heist", "preferred_action": "stealth"},
|
33 |
+
{"id": "pirate_cove", "name": "The Pirate Cove", "description": "Sail the high seas with your trusty crew of cats and uncover the secrets of Pirate Cove. Beware of the treacherous Sea Dogs! ๐ดโโ ๏ธ", "emoji": "๐ดโโ ๏ธ", "type": "exploration", "preferred_action": "bravery"},
|
34 |
+
{"id": "feline_moon_mission", "name": "The Feline Moon Mission", "description": "Blast off into space! Your mission is to plant the flag of Catopia on the moon. Pilot your rocket through an asteroid field! ๐", "emoji": "๐", "type": "exploration", "preferred_action": "resourcefulness"},
|
35 |
+
{"id": "purr_summit", "name": "The Purr Summit", "description": "Join a secret gathering of the most intellectual cats in the world. Engage in a battle of wits and wisdom to become the Grand Purr! ๐ง ", "emoji": "๐", "type": "debate", "preferred_action": "insight"},
|
36 |
+
{"id": "feline_invasion", "name": "The Feline Invasion", "description": "Aliens have invaded Earth and only your cat rider can save the planet! Use cunning strategies to repel the invaders! ๐ฝ", "emoji": "๐ฝ", "type": "battle", "preferred_action": "strategy"},
|
37 |
+
{"id": "eternal_catnap", "name": "The Eternal Catnap", "description": "You've entered a sacred temple where cats nap for centuries. Can you navigate the dream world and escape before you too are lulled into eternal slumber? ๐๏ธ", "emoji": "๐ค", "type": "exploration", "preferred_action": "stealth"}
|
38 |
+
]
|
39 |
+
|
40 |
+
# ๐ง Expanded Actions (10 Actions)
|
41 |
+
ACTIONS = [
|
42 |
+
{"id": "stealth", "name": "Use Stealth", "description": "Sneak past obstacles or enemies without being detected. You're like a ninja in the shadows! ๐พ", "emoji": "๐คซ", "type": "skill"},
|
43 |
+
{"id": "agility", "name": "Showcase Agility", "description": "Perform impressive acrobatic maneuvers to overcome challenges. Cats always land on their feet, right? ๐", "emoji": "๐", "type": "physical"},
|
44 |
+
{"id": "charm", "name": "Charm Others", "description": "Use your cat's natural charisma to win over allies or distract foes. Who could resist those cute eyes? ๐ป", "emoji": "๐ป", "type": "social"},
|
45 |
+
{"id": "resourcefulness", "name": "Be Resourceful", "description": "Utilize the environment or items in creative ways to solve problems. Think on your paws! ๐ง ", "emoji": "๐ง ", "type": "mental"},
|
46 |
+
{"id": "bravery", "name": "Show Bravery", "description": "Face dangers head-on with your feline courage. Not all heroes wear capes โ some wear fur! ๐ฆ", "emoji": "๐ฆ", "type": "physical"},
|
47 |
+
{"id": "strategy", "name": "Develop a Strategy", "description": "Use tactical thinking to outsmart opponents and gain the upper hand in battle. Brains over brawn! ๐ง ", "emoji": "๐ง ", "type": "mental"},
|
48 |
+
{"id": "speed", "name": "Sprint Away", "description": "Run faster than you've ever run before to escape danger. Like a cat fleeing a vacuum cleaner! ๐โโ๏ธ", "emoji": "๐โโ๏ธ", "type": "physical"},
|
49 |
+
{"id": "insight", "name": "Use Insight", "description": "Tap into ancient feline wisdom to solve puzzles and mysteries. A cat always knows! ๐ฎ", "emoji": "๐ฎ", "type": "mental"},
|
50 |
+
{"id": "distraction", "name": "Create a Distraction", "description": "Use cunning tricks and diversions to draw attention away from your real goal. Look over there! ๐ช", "emoji": "๐ช", "type": "mental"},
|
51 |
+
{"id": "negotiation", "name": "Negotiate", "description": "Use diplomacy and clever negotiation to get out of a tight spot. Every cat has their price! ๐ผ", "emoji": "๐ผ", "type": "social"}
|
52 |
+
]
|
53 |
+
|
54 |
+
|
55 |
+
# Expanded conclusions for outcomes - 10 items each for success and failure
|
56 |
+
SUCCESS_CONCLUSIONS = [
|
57 |
+
"Your swift paws led you to victory! ๐",
|
58 |
+
"You pounced at the perfect moment! ๐",
|
59 |
+
"The stars aligned for your cat rider! ๐",
|
60 |
+
"You navigated the challenge like a true feline champion! ๐ฑ",
|
61 |
+
"Victory is sweet, just like a bowl of fresh milk! ๐ฅ",
|
62 |
+
"Your opponents are left in awe of your skills! ๐บ",
|
63 |
+
"Youโve earned the title of Cat Commander! ๐
",
|
64 |
+
"All the other cats are jealous of your agility! ๐โโ๏ธ",
|
65 |
+
"Your strategy was flawless, and the victory is yours! ๐๏ธ",
|
66 |
+
"Your cat rider is now a legend in the feline world! ๐"
|
67 |
+
]
|
68 |
+
|
69 |
+
FAILURE_CONCLUSIONS = [
|
70 |
+
"You tried your best, but it just wasnโt enough. ๐ฟ",
|
71 |
+
"Maybe next time, kitty. Keep your tail up! ๐พ",
|
72 |
+
"That didnโt go as planned. Time for a catnap to recover! ๐ค",
|
73 |
+
"Even the best cats have their off days. ๐",
|
74 |
+
"The challenge was too great this time. Better luck next time! ๐",
|
75 |
+
"You might need more than nine lives to get through this. ๐",
|
76 |
+
"The enemy was too clever for your plan. ๐ง ",
|
77 |
+
"You tripped over your own paws! ๐พ",
|
78 |
+
"The cat gods were not in your favor today. ๐",
|
79 |
+
"Itโs okay, every cat has a learning curve. ๐"
|
80 |
+
]
|
81 |
+
|
82 |
+
# ๐ง Game Mechanics
|
83 |
+
def generate_situation():
|
84 |
+
return random.choice(SITUATIONS)
|
85 |
+
|
86 |
+
def generate_actions():
|
87 |
+
return random.sample(ACTIONS, min(3, len(ACTIONS)))
|
88 |
+
|
89 |
+
def evaluate_action(situation, action, gear_strength, rider_skill, history):
|
90 |
+
# Determine if the action is the preferred action
|
91 |
+
base_success_chance = (gear_strength + rider_skill) / 2
|
92 |
+
if action['id'] == situation['preferred_action']:
|
93 |
+
success_chance = base_success_chance + 30 # Boost success chance for preferred action
|
94 |
+
else:
|
95 |
+
success_chance = base_success_chance
|
96 |
+
|
97 |
+
if action['id'] in history:
|
98 |
+
success_chance += history[action['id']] * 2
|
99 |
+
|
100 |
+
outcome = random.randint(1, 100) <= success_chance
|
101 |
+
return outcome, success_chance
|
102 |
+
|
103 |
+
def generate_encounter_conclusion(situation, action, outcome):
|
104 |
+
if outcome:
|
105 |
+
return random.choice(SUCCESS_CONCLUSIONS)
|
106 |
+
else:
|
107 |
+
return random.choice(FAILURE_CONCLUSIONS)
|
108 |
+
|
109 |
+
# ๐ณ Journey Visualization
|
110 |
+
def create_heterogeneous_graph(history_df):
|
111 |
+
nodes = []
|
112 |
+
edges = []
|
113 |
+
for index, row in history_df.iterrows():
|
114 |
+
scenario_id = f"scenario-{row['situation_id']}"
|
115 |
+
action_id = f"action-{row['action_id']}-{index}"
|
116 |
+
conclusion_id = f"conclusion-{index}"
|
117 |
+
|
118 |
+
# Scenario node
|
119 |
+
scenario_node = StreamlitFlowNode(scenario_id, (0, 0), {'content': f"{row['situation_emoji']} {row['situation_name']}"}, 'output', 'bottom', 'top', shape='ellipse')
|
120 |
+
nodes.append(scenario_node)
|
121 |
+
|
122 |
+
# Action node
|
123 |
+
action_node = StreamlitFlowNode(action_id, (0, 0), {'content': f"{row['action_emoji']} {row['action_name']}"}, 'output', 'bottom', 'top', shape='ellipse')
|
124 |
+
nodes.append(action_node)
|
125 |
+
|
126 |
+
# Conclusion node
|
127 |
+
conclusion_node = StreamlitFlowNode(conclusion_id, (0, 0), {'content': f"{row['conclusion']}\n๐ช Gear: {row['gear_strength']:.2f}"}, 'output', 'bottom', 'top', shape='ellipse')
|
128 |
+
nodes.append(conclusion_node)
|
129 |
+
|
130 |
+
# Edges
|
131 |
+
edges.append(StreamlitFlowEdge(f"{scenario_id}-{action_id}", scenario_id, action_id, animated=True))
|
132 |
+
edges.append(StreamlitFlowEdge(f"{action_id}-{conclusion_id}", action_id, conclusion_id, animated=True))
|
133 |
+
|
134 |
+
# Link to previous scenario
|
135 |
+
if index > 0:
|
136 |
+
prev_conclusion_id = f"conclusion-{index-1}"
|
137 |
+
edges.append(StreamlitFlowEdge(f"{prev_conclusion_id}-{scenario_id}", prev_conclusion_id, scenario_id, animated=True, dashed=True))
|
138 |
+
|
139 |
+
return nodes, edges
|
140 |
+
|
141 |
+
# ๐ Markdown Preview with Single Scenario Entry and Attempts
|
142 |
+
def create_markdown_preview(history_df):
|
143 |
+
markdown = "## ๐ณ Journey Preview\n\n"
|
144 |
+
grouped_scenarios = history_df.groupby('situation_name')
|
145 |
+
|
146 |
+
for situation_name, group in grouped_scenarios:
|
147 |
+
markdown += f"๐ **{situation_name}**\n"
|
148 |
+
for _, row in group.iterrows():
|
149 |
+
markdown += f" โช {row['action_emoji']} {row['action_name']}: "
|
150 |
+
markdown += "โ
Success\n" if row['outcome'] else "โ Failure\n"
|
151 |
+
markdown += f" ๐ {row['conclusion']} ๐ช Gear: {row['gear_strength']:.2f} | ๐๏ธ Skill: {row['rider_skill']:.2f}\n"
|
152 |
+
markdown += "\n"
|
153 |
+
return markdown
|
154 |
+
|
155 |
+
# ๐ฎ Main Game Application
|
156 |
+
def main():
|
157 |
+
st.title("๐ฑ Cat Rider ๐")
|
158 |
+
|
159 |
+
# ๐ Game Rules
|
160 |
+
st.markdown("""
|
161 |
+
### ๐ Game Rules
|
162 |
+
| Step | Description |
|
163 |
+
|------|-------------|
|
164 |
+
| 1๏ธโฃ | Choose your Cat Rider |
|
165 |
+
| 2๏ธโฃ | Select your Riding Gear |
|
166 |
+
| 3๏ธโฃ | Set off on an Adventure |
|
167 |
+
| 4๏ธโฃ | Encounter Challenges and Make Decisions |
|
168 |
+
| 5๏ธโฃ | Complete the Quest and Grow Stronger |
|
169 |
+
""")
|
170 |
+
|
171 |
+
# ๐ Initialize game state
|
172 |
+
if 'game_state' not in st.session_state:
|
173 |
+
st.session_state.game_state = {
|
174 |
+
'user_id': str(uuid.uuid4()),
|
175 |
+
'score': 0,
|
176 |
+
'history': {},
|
177 |
+
'gear_strength': 0,
|
178 |
+
'rider_skill': 0,
|
179 |
+
'cat_rider': None,
|
180 |
+
'riding_gear': None,
|
181 |
+
'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'])
|
182 |
+
}
|
183 |
+
|
184 |
+
# ๐ฑ Cat Rider Selection
|
185 |
+
if st.session_state.game_state['cat_rider'] is None:
|
186 |
+
st.markdown("## Choose Your Cat Rider:")
|
187 |
+
cols = st.columns(len(CAT_RIDERS))
|
188 |
+
for i, rider in enumerate(CAT_RIDERS):
|
189 |
+
if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})"):
|
190 |
+
st.session_state.game_state['cat_rider'] = rider
|
191 |
+
st.session_state.game_state['rider_skill'] = rider['skill']
|
192 |
+
|
193 |
+
# ๐ Riding Gear Selection
|
194 |
+
if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None:
|
195 |
+
st.markdown("## Select Your Riding Gear:")
|
196 |
+
cols = st.columns(len(RIDING_GEAR))
|
197 |
+
for i, gear in enumerate(RIDING_GEAR):
|
198 |
+
if cols[i].button(f"{gear['name']} ({gear['type']})"):
|
199 |
+
st.session_state.game_state['riding_gear'] = gear
|
200 |
+
st.session_state.game_state['gear_strength'] = gear['strength']
|
201 |
+
|
202 |
+
# ๐ญ Game Loop
|
203 |
+
if st.session_state.game_state['cat_rider'] is not None and st.session_state.game_state['riding_gear'] is not None:
|
204 |
+
situation = generate_situation()
|
205 |
+
actions = generate_actions()
|
206 |
+
|
207 |
+
st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
|
208 |
+
st.markdown(situation['description'])
|
209 |
+
st.markdown("### ๐ญ Choose your action:")
|
210 |
+
|
211 |
+
cols = st.columns(3)
|
212 |
+
for i, action in enumerate(actions):
|
213 |
+
if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})"):
|
214 |
+
outcome, success_chance = evaluate_action(situation, action, st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill'], st.session_state.game_state['history'])
|
215 |
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
216 |
+
|
217 |
+
st.markdown(f"You decided to: **{action['name']}** ({action['type']})")
|
218 |
+
st.markdown(action['description'])
|
219 |
+
st.markdown(f"**Outcome:** {'โ
Success!' if outcome else 'โ Failure.'}")
|
220 |
+
st.markdown(f"**Success Chance:** {success_chance:.2f}%")
|
221 |
+
|
222 |
+
if outcome:
|
223 |
+
st.session_state.game_state['score'] += 1
|
224 |
+
|
225 |
+
# ๐ Update game state
|
226 |
+
st.session_state.game_state = update_game_state(
|
227 |
+
st.session_state.game_state,
|
228 |
+
situation,
|
229 |
+
action,
|
230 |
+
outcome,
|
231 |
+
timestamp
|
232 |
+
)
|
233 |
+
|
234 |
+
# Display conclusion
|
235 |
+
conclusion = st.session_state.game_state['history_df'].iloc[-1]['conclusion']
|
236 |
+
st.markdown(f"**Encounter Conclusion:** {conclusion}")
|
237 |
+
|
238 |
+
# Display updated stats
|
239 |
+
st.markdown(f"**Updated Stats:**")
|
240 |
+
st.markdown(f"๐ช Gear Strength: {st.session_state.game_state['gear_strength']:.2f}")
|
241 |
+
st.markdown(f"๐๏ธ Rider Skill: {st.session_state.game_state['rider_skill']:.2f}")
|
242 |
+
|
243 |
+
# ๐ Display Markdown Preview
|
244 |
+
if not st.session_state.game_state['history_df'].empty:
|
245 |
+
st.markdown(create_markdown_preview(st.session_state.game_state['history_df']))
|
246 |
+
|
247 |
+
# ๐ณ Display Heterogeneous Journey Graph
|
248 |
+
if not st.session_state.game_state['history_df'].empty:
|
249 |
+
st.markdown("## ๐ณ Your Journey (Heterogeneous Graph)")
|
250 |
+
nodes, edges = create_heterogeneous_graph(st.session_state.game_state['history_df'])
|
251 |
+
try:
|
252 |
+
streamlit_flow('cat_rider_flow',
|
253 |
+
nodes,
|
254 |
+
edges,
|
255 |
+
layout=TreeLayout(direction='down'),
|
256 |
+
fit_view=True,
|
257 |
+
height=600)
|
258 |
+
except Exception as e:
|
259 |
+
st.error(f"An error occurred while rendering the journey graph: {str(e)}")
|
260 |
+
st.markdown("Please try refreshing the page if the graph doesn't appear.")
|
261 |
+
|
262 |
+
# ๐ Character Stats Visualization
|
263 |
+
data = {"Stat": ["Gear Strength ๐ก๏ธ", "Rider Skill ๐"],
|
264 |
+
"Value": [st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill']]}
|
265 |
+
df = pd.DataFrame(data)
|
266 |
+
fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats ๐")
|
267 |
+
st.plotly_chart(fig)
|
268 |
+
|
269 |
+
if __name__ == "__main__":
|
270 |
+
main()
|
271 |
+
|
272 |
+
|
273 |
+
|
274 |
+
import streamlit as st
|
275 |
+
import pandas as pd
|
276 |
+
import plotly.express as px
|
277 |
+
import random
|
278 |
+
import uuid
|
279 |
+
from datetime import datetime
|
280 |
+
from streamlit_flow import streamlit_flow
|
281 |
+
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
|
282 |
+
from streamlit_flow.layouts import TreeLayout
|
283 |
+
|
284 |
+
# ๐ฑ Cat Rider and Gear Data
|
285 |
+
CAT_RIDERS = [
|
286 |
+
{"name": "Whiskers", "type": "Speed", "emoji": "๐พ", "strength": 3, "skill": 7},
|
287 |
+
{"name": "Fluffy", "type": "Bravery", "emoji": "๐ฆ", "strength": 5, "skill": 5},
|
288 |
+
{"name": "Midnight", "type": "Stealth", "emoji": "๐", "strength": 4, "skill": 6},
|
289 |
+
{"name": "Bella", "type": "Charm", "emoji": "๐บ", "strength": 2, "skill": 8}
|
290 |
+
]
|
291 |
+
|
292 |
+
RIDING_GEAR = [
|
293 |
+
{"name": "Feathered Boots", "type": "Agility", "strength": 2},
|
294 |
+
{"name": "Golden Armor", "type": "Defense", "strength": 4},
|
295 |
+
{"name": "Magic Whisker Wand", "type": "Magic", "strength": 3},
|
296 |
+
{"name": "Sleek Shadow Cape", "type": "Stealth", "strength": 1}
|
297 |
+
]
|
298 |
+
|
299 |
+
# ๐ Game World Data - SITUATIONS and ACTIONS expanded with humorous elements
|
300 |
+
SITUATIONS = [
|
301 |
+
{
|
302 |
+
"id": "feline_escape",
|
303 |
+
"name": "The Great Feline Escape",
|
304 |
+
"description": "Your cat rider is trapped in an old mansion, which is about to be demolished. Using agility, wit, and bravery, orchestrate the perfect escape before the walls crumble! ๐๏ธ",
|
305 |
+
"emoji": "๐ช",
|
306 |
+
"type": "escape"
|
307 |
+
},
|
308 |
+
{
|
309 |
+
"id": "lost_temple",
|
310 |
+
"name": "The Treasure of the Lost Temple",
|
311 |
+
"description": "On a quest to retrieve an ancient artifact, your cat rider must navigate through a labyrinth filled with traps and guardian spirits. Don't let the spooky ghosts get you! ๐ป",
|
312 |
+
"emoji": "๐๏ธ",
|
313 |
+
"type": "exploration"
|
314 |
+
},
|
315 |
+
{
|
316 |
+
"id": "royal_tournament",
|
317 |
+
"name": "The Royal Tournament",
|
318 |
+
"description": "Compete in a grand tournament where the finest cat riders showcase their skills and bravery to earn the title of the Royal Rider. Be prepared to face noble feline adversaries! ๐ฑ",
|
319 |
+
"emoji": "๐",
|
320 |
+
"type": "competition"
|
321 |
+
},
|
322 |
+
{
|
323 |
+
"id": "cheese_heist",
|
324 |
+
"name": "The Great Cheese Heist",
|
325 |
+
"description": "Your cat rider must sneak into the royal pantry to steal the legendary Cheese of Destiny. But beware โ the palace mice are guarding it! ๐ง",
|
326 |
+
"emoji": "๐ง",
|
327 |
+
"type": "heist"
|
328 |
+
},
|
329 |
+
{
|
330 |
+
"id": "sky_race",
|
331 |
+
"name": "The Sky Race",
|
332 |
+
"description": "Compete in the annual Sky Race where your cat rider flies across the skies on a magical broomstick! Watch out for lightning storms and mischievous crows! ๐ฉ๏ธ",
|
333 |
+
"emoji": "โ๏ธ",
|
334 |
+
"type": "competition"
|
335 |
+
},
|
336 |
+
{
|
337 |
+
"id": "purr_summit",
|
338 |
+
"name": "The Purr Summit",
|
339 |
+
"description": "Join a secret gathering of the most intellectual cats in the world. Engage in a battle of wits and wisdom to become the Grand Purr! ๐ง ",
|
340 |
+
"emoji": "๐",
|
341 |
+
"type": "debate"
|
342 |
+
},
|
343 |
+
{
|
344 |
+
"id": "cat_nap",
|
345 |
+
"name": "The Eternal Catnap",
|
346 |
+
"description": "You've entered a sacred temple where cats nap for centuries. Can you navigate the dream world and escape before you too are lulled into eternal slumber? ๐๏ธ",
|
347 |
+
"emoji": "๐ค",
|
348 |
+
"type": "exploration"
|
349 |
+
},
|
350 |
+
{
|
351 |
+
"id": "feline_moon_mission",
|
352 |
+
"name": "The Feline Moon Mission",
|
353 |
+
"description": "Blast off into space! Your mission is to plant the flag of Catopia on the moon. But first, you must pilot your rocket through an asteroid field. ๐",
|
354 |
+
"emoji": "๐",
|
355 |
+
"type": "exploration"
|
356 |
+
},
|
357 |
+
{
|
358 |
+
"id": "pirate_cove",
|
359 |
+
"name": "The Pirate Cove",
|
360 |
+
"description": "Sail the high seas with your trusty crew of cats and uncover the secrets of the Pirate Cove. But beware of the treacherous Sea Dogs! ๐ดโโ ๏ธ",
|
361 |
+
"emoji": "๐ดโโ ๏ธ",
|
362 |
+
"type": "exploration"
|
363 |
+
},
|
364 |
+
{
|
365 |
+
"id": "cat_casino",
|
366 |
+
"name": "The Cat Casino",
|
367 |
+
"description": "Test your luck in the glamorous Cat Casino! Bet your whiskers on the tables and try not to lose it all. Meow is the time! ๐ฒ",
|
368 |
+
"emoji": "๐ฐ",
|
369 |
+
"type": "competition"
|
370 |
+
}
|
371 |
+
]
|
372 |
+
|
373 |
+
ACTIONS = [
|
374 |
+
{
|
375 |
+
"id": "stealth",
|
376 |
+
"name": "Use Stealth",
|
377 |
+
"description": "Sneak past obstacles or enemies without being detected. You're like a ninja in the shadows! ๐พ",
|
378 |
+
"emoji": "๐คซ",
|
379 |
+
"type": "skill"
|
380 |
+
},
|
381 |
+
{
|
382 |
+
"id": "agility",
|
383 |
+
"name": "Showcase Agility",
|
384 |
+
"description": "Perform impressive acrobatic maneuvers to overcome challenges. Cats always land on their feet, right? ๐",
|
385 |
+
"emoji": "๐",
|
386 |
+
"type": "physical"
|
387 |
+
},
|
388 |
+
{
|
389 |
+
"id": "charm",
|
390 |
+
"name": "Charm Others",
|
391 |
+
"description": "Use your cat's natural charisma to win over allies or distract foes. Who could resist those cute eyes? ๐ป",
|
392 |
+
"emoji": "๐ป",
|
393 |
+
"type": "social"
|
394 |
+
},
|
395 |
+
{
|
396 |
+
"id": "resourcefulness",
|
397 |
+
"name": "Be Resourceful",
|
398 |
+
"description": "Utilize the environment or items in creative ways to solve problems. Think on your paws! ๐ง ",
|
399 |
+
"emoji": "๐ง ",
|
400 |
+
"type": "mental"
|
401 |
+
},
|
402 |
+
{
|
403 |
+
"id": "bravery",
|
404 |
+
"name": "Show Bravery",
|
405 |
+
"description": "Face dangers head-on with your feline courage. Not all heroes wear capes โ some wear fur! ๐ฆธโโ๏ธ",
|
406 |
+
"emoji": "๐ฆธโโ๏ธ",
|
407 |
+
"type": "physical"
|
408 |
+
},
|
409 |
+
{
|
410 |
+
"id": "negotiation",
|
411 |
+
"name": "Negotiate",
|
412 |
+
"description": "Use diplomacy and clever negotiation to get out of a tight spot. Every cat has their price! ๐ผ",
|
413 |
+
"emoji": "๐ผ",
|
414 |
+
"type": "social"
|
415 |
+
},
|
416 |
+
{
|
417 |
+
"id": "precision",
|
418 |
+
"name": "Precision Attack",
|
419 |
+
"description": "Execute a perfectly timed attack to disable traps or defeat enemies. Purrfection in motion! ๐ฏ",
|
420 |
+
"emoji": "๐ฏ",
|
421 |
+
"type": "skill"
|
422 |
+
},
|
423 |
+
{
|
424 |
+
"id": "distraction",
|
425 |
+
"name": "Create a Distraction",
|
426 |
+
"description": "Use cunning tricks and diversions to draw attention away from your real goal. Look over there! ๐ช",
|
427 |
+
"emoji": "๐ช",
|
428 |
+
"type": "mental"
|
429 |
+
},
|
430 |
+
{
|
431 |
+
"id": "speed",
|
432 |
+
"name": "Sprint Away",
|
433 |
+
"description": "Run faster than you've ever run before to escape danger. Just like a cat fleeing a vacuum cleaner! ๐โโ๏ธ",
|
434 |
+
"emoji": "๐โโ๏ธ",
|
435 |
+
"type": "physical"
|
436 |
+
},
|
437 |
+
{
|
438 |
+
"id": "insight",
|
439 |
+
"name": "Use Insight",
|
440 |
+
"description": "Tap into ancient feline wisdom to solve puzzles and mysteries. A cat always knows! ๐ฎ",
|
441 |
+
"emoji": "๐ฎ",
|
442 |
+
"type": "mental"
|
443 |
+
}
|
444 |
+
]
|
445 |
+
|
446 |
+
# Expanded conclusions for outcomes - 10 items each for success and failure
|
447 |
+
SUCCESS_CONCLUSIONS = [
|
448 |
+
"Your swift paws led you to victory! ๐",
|
449 |
+
"You pounced at the perfect moment! ๐",
|
450 |
+
"The stars aligned for your cat rider! ๐",
|
451 |
+
"You navigated the challenge like a true feline champion! ๐ฑ",
|
452 |
+
"Victory is sweet, just like a bowl of fresh milk! ๐ฅ",
|
453 |
+
"Your opponents are left in awe of your skills! ๐บ",
|
454 |
+
"Youโve earned the title of Cat Commander! ๐
",
|
455 |
+
"All the other cats are jealous of your agility! ๐โโ๏ธ",
|
456 |
+
"Your strategy was flawless, and the victory is yours! ๐๏ธ",
|
457 |
+
"Your cat rider is now a legend in the feline world! ๐"
|
458 |
+
]
|
459 |
+
|
460 |
+
FAILURE_CONCLUSIONS = [
|
461 |
+
"You tried your best, but it just wasnโt enough. ๐ฟ",
|
462 |
+
"Maybe next time, kitty. Keep your tail up! ๐พ",
|
463 |
+
"That didnโt go as planned. Time for a catnap to recover! ๐ค",
|
464 |
+
"Even the best cats have their off days. ๐",
|
465 |
+
"The challenge was too great this time. Better luck next time! ๐",
|
466 |
+
"You might need more than nine lives to get through this. ๐",
|
467 |
+
"The enemy was too clever for your plan. ๐ง ",
|
468 |
+
"You tripped over your own paws! ๐พ",
|
469 |
+
"The cat gods were not in your favor today. ๐",
|
470 |
+
"Itโs okay, every cat has a learning curve. ๐"
|
471 |
+
]
|
472 |
+
|
473 |
+
# ๐ง Game Mechanics
|
474 |
+
def generate_situation():
|
475 |
+
return random.choice(SITUATIONS)
|
476 |
+
|
477 |
+
def generate_actions():
|
478 |
+
return random.sample(ACTIONS, min(3, len(ACTIONS)))
|
479 |
+
|
480 |
+
def evaluate_action(action, gear_strength, rider_skill, history):
|
481 |
+
base_success_chance = (gear_strength + rider_skill) / 2
|
482 |
+
if action['id'] in history:
|
483 |
+
success_chance = base_success_chance + (history[action['id']] * 2)
|
484 |
+
else:
|
485 |
+
success_chance = base_success_chance
|
486 |
+
outcome = random.randint(1, 100) <= success_chance
|
487 |
+
return outcome, success_chance
|
488 |
+
|
489 |
+
def generate_encounter_conclusion(situation, action, outcome):
|
490 |
+
if outcome:
|
491 |
+
return random.choice(SUCCESS_CONCLUSIONS)
|
492 |
+
else:
|
493 |
+
return random.choice(FAILURE_CONCLUSIONS)
|
494 |
+
|
495 |
+
# ๐ณ Journey Visualization with Heterogeneous Graph Structure
|
496 |
+
def create_heterogeneous_graph(history_df):
|
497 |
+
nodes = []
|
498 |
+
edges = []
|
499 |
+
|
500 |
+
# Define node shapes based on situation and action types
|
501 |
+
situation_shapes = {
|
502 |
+
"escape": "diamond",
|
503 |
+
"exploration": "triangle",
|
504 |
+
"competition": "star"
|
505 |
+
}
|
506 |
+
action_shapes = {
|
507 |
+
"skill": "square",
|
508 |
+
"physical": "circle",
|
509 |
+
"social": "hexagon",
|
510 |
+
"mental": "octagon"
|
511 |
+
}
|
512 |
+
|
513 |
+
for index, row in history_df.iterrows():
|
514 |
+
situation_id = f"situation-{index}"
|
515 |
+
action_id = f"action-{index}"
|
516 |
+
conclusion_id = f"conclusion-{index}"
|
517 |
+
|
518 |
+
# Create situation node
|
519 |
+
situation_content = f"{row['situation_emoji']} {row['situation_name']}\n๐ {row['timestamp']}"
|
520 |
+
situation_node = StreamlitFlowNode(situation_id, (0, 0), {'content': situation_content}, 'output', 'bottom', 'top', shape=situation_shapes.get(row['situation_type'], 'ellipse'))
|
521 |
+
nodes.append(situation_node)
|
522 |
+
|
523 |
+
# Create action node
|
524 |
+
action_content = f"{row['action_emoji']} {row['action_name']}\nOutcome: {'โ
Success' if row['outcome'] else 'โ Failure'}"
|
525 |
+
action_node = StreamlitFlowNode(action_id, (0, 0), {'content': action_content}, 'output', 'bottom', 'top', shape=action_shapes.get(row['action_type'], 'ellipse'))
|
526 |
+
nodes.append(action_node)
|
527 |
+
|
528 |
+
# Create conclusion node
|
529 |
+
conclusion_content = f"๐ {row['conclusion']}\n๐ช Gear: {row['gear_strength']:.2f} | ๐๏ธ Skill: {row['rider_skill']:.2f}"
|
530 |
+
conclusion_node = StreamlitFlowNode(conclusion_id, (0, 0), {'content': conclusion_content}, 'output', 'bottom', 'top', shape='parallelogram')
|
531 |
+
nodes.append(conclusion_node)
|
532 |
+
|
533 |
+
# Create edges
|
534 |
+
edges.append(StreamlitFlowEdge(f"{situation_id}-{action_id}", situation_id, action_id, animated=True, dashed=False))
|
535 |
+
edges.append(StreamlitFlowEdge(f"{action_id}-{conclusion_id}", action_id, conclusion_id, animated=True, dashed=False))
|
536 |
+
|
537 |
+
# Create edge to previous conclusion if not the first node
|
538 |
+
if index > 0:
|
539 |
+
prev_conclusion_id = f"conclusion-{index-1}"
|
540 |
+
edges.append(StreamlitFlowEdge(f"{prev_conclusion_id}-{situation_id}", prev_conclusion_id, situation_id, animated=True, dashed=True))
|
541 |
+
|
542 |
+
return nodes, edges
|
543 |
+
|
544 |
+
# ๐ Markdown Preview
|
545 |
+
def create_markdown_preview(history_df):
|
546 |
+
markdown = "## ๐ณ Journey Preview\n\n"
|
547 |
+
for index, row in history_df.iterrows():
|
548 |
+
indent = " " * (index * 3)
|
549 |
+
markdown += f"{indent}๐ **{row['situation_name']}** ({row['situation_type']})\n"
|
550 |
+
markdown += f"{indent} โช {row['action_emoji']} {row['action_name']} ({row['action_type']}): "
|
551 |
+
markdown += "โ
Success\n" if row['outcome'] else "โ Failure\n"
|
552 |
+
markdown += f"{indent} ๐ {row['conclusion']}\n"
|
553 |
+
markdown += f"{indent} ๐ช Gear: {row['gear_strength']:.2f} | ๐๏ธ Skill: {row['rider_skill']:.2f}\n\n"
|
554 |
+
return markdown
|
555 |
+
|
556 |
+
# ๐ Game State Management
|
557 |
+
def update_game_state(game_state, situation, action, outcome, timestamp):
|
558 |
+
conclusion = generate_encounter_conclusion(situation, action, outcome)
|
559 |
+
game_state = update_character_stats(game_state, outcome)
|
560 |
+
|
561 |
+
new_record = pd.DataFrame({
|
562 |
+
'user_id': [game_state['user_id']],
|
563 |
+
'timestamp': [timestamp],
|
564 |
+
'situation_id': [situation['id']],
|
565 |
+
'situation_name': [situation['name']],
|
566 |
+
'situation_emoji': [situation['emoji']],
|
567 |
+
'situation_type': [situation['type']],
|
568 |
+
'action_id': [action['id']],
|
569 |
+
'action_name': [action['name']],
|
570 |
+
'action_emoji': [action['emoji']],
|
571 |
+
'action_type': [action['type']],
|
572 |
+
'outcome': [outcome],
|
573 |
+
'conclusion': [conclusion],
|
574 |
+
'gear_strength': [game_state['gear_strength']],
|
575 |
+
'rider_skill': [game_state['rider_skill']],
|
576 |
+
'score': [game_state['score']]
|
577 |
+
})
|
578 |
+
game_state['history_df'] = pd.concat([game_state['history_df'], new_record], ignore_index=True)
|
579 |
+
|
580 |
+
if action['id'] in game_state['history']:
|
581 |
+
game_state['history'][action['id']] += 1 if outcome else -1
|
582 |
+
else:
|
583 |
+
game_state['history'][action['id']] = 1 if outcome else -1
|
584 |
+
|
585 |
+
return game_state
|
586 |
+
|
587 |
+
# ๐ Update character stats based on the outcome
|
588 |
+
def update_character_stats(game_state, outcome):
|
589 |
+
if outcome:
|
590 |
+
game_state['gear_strength'] = min(10, game_state['gear_strength'] + random.uniform(0.1, 0.5))
|
591 |
+
game_state['rider_skill'] = min(10, game_state['rider_skill'] + random.uniform(0.1, 0.5))
|
592 |
+
return game_state
|
593 |
+
|
594 |
+
# ๐ฎ Main Game Application
|
595 |
+
def main():
|
596 |
+
st.title("๐ฑ Cat Rider ๐")
|
597 |
+
|
598 |
+
# ๐ Game Rules
|
599 |
+
st.markdown("""
|
600 |
+
### ๐ Game Rules
|
601 |
+
| Step | Description |
|
602 |
+
|------|-------------|
|
603 |
+
| 1๏ธโฃ | Choose your Cat Rider |
|
604 |
+
| 2๏ธโฃ | Select your Riding Gear |
|
605 |
+
| 3๏ธโฃ | Set off on an Adventure |
|
606 |
+
| 4๏ธโฃ | Encounter Challenges and Make Decisions |
|
607 |
+
| 5๏ธโฃ | Complete the Quest and Grow Stronger |
|
608 |
+
""")
|
609 |
+
|
610 |
+
# ๐ Initialize game state
|
611 |
+
if 'game_state' not in st.session_state:
|
612 |
+
st.session_state.game_state = {
|
613 |
+
'user_id': str(uuid.uuid4()),
|
614 |
+
'score': 0,
|
615 |
+
'history': {},
|
616 |
+
'gear_strength': 0,
|
617 |
+
'rider_skill': 0,
|
618 |
+
'cat_rider': None,
|
619 |
+
'riding_gear': None,
|
620 |
+
'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'])
|
621 |
+
}
|
622 |
+
|
623 |
+
# ๐ฑ Cat Rider Selection
|
624 |
+
if st.session_state.game_state['cat_rider'] is None:
|
625 |
+
st.markdown("## Choose Your Cat Rider:")
|
626 |
+
cols = st.columns(len(CAT_RIDERS))
|
627 |
+
for i, rider in enumerate(CAT_RIDERS):
|
628 |
+
if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})"):
|
629 |
+
st.session_state.game_state['cat_rider'] = rider
|
630 |
+
st.session_state.game_state['rider_skill'] = rider['skill']
|
631 |
+
|
632 |
+
# ๐ Riding Gear Selection
|
633 |
+
if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None:
|
634 |
+
st.markdown("## Select Your Riding Gear:")
|
635 |
+
cols = st.columns(len(RIDING_GEAR))
|
636 |
+
for i, gear in enumerate(RIDING_GEAR):
|
637 |
+
if cols[i].button(f"{gear['name']} ({gear['type']})"):
|
638 |
+
st.session_state.game_state['riding_gear'] = gear
|
639 |
+
st.session_state.game_state['gear_strength'] = gear['strength']
|
640 |
+
|
641 |
+
# ๐ญ Game Loop
|
642 |
+
if st.session_state.game_state['cat_rider'] is not None and st.session_state.game_state['riding_gear'] is not None:
|
643 |
+
situation = generate_situation()
|
644 |
+
actions = generate_actions()
|
645 |
+
|
646 |
+
st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
|
647 |
+
st.markdown(situation['description'])
|
648 |
+
st.markdown("### ๐ญ Choose your action:")
|
649 |
+
|
650 |
+
cols = st.columns(3)
|
651 |
+
for i, action in enumerate(actions):
|
652 |
+
if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})"):
|
653 |
+
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'])
|
654 |
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
655 |
+
|
656 |
+
st.markdown(f"You decided to: **{action['name']}** ({action['type']})")
|
657 |
+
st.markdown(action['description'])
|
658 |
+
st.markdown(f"**Outcome:** {'โ
Success!' if outcome else 'โ Failure.'}")
|
659 |
+
st.markdown(f"**Success Chance:** {success_chance:.2f}%")
|
660 |
+
|
661 |
+
if outcome:
|
662 |
+
st.session_state.game_state['score'] += 1
|
663 |
+
|
664 |
+
# ๐ Update game state
|
665 |
+
st.session_state.game_state = update_game_state(
|
666 |
+
st.session_state.game_state,
|
667 |
+
situation,
|
668 |
+
action,
|
669 |
+
outcome,
|
670 |
+
timestamp
|
671 |
+
)
|
672 |
+
|
673 |
+
# Display conclusion
|
674 |
+
conclusion = st.session_state.game_state['history_df'].iloc[-1]['conclusion']
|
675 |
+
st.markdown(f"**Encounter Conclusion:** {conclusion}")
|
676 |
+
|
677 |
+
# Display updated stats
|
678 |
+
st.markdown(f"**Updated Stats:**")
|
679 |
+
st.markdown(f"๐ช Gear Strength: {st.session_state.game_state['gear_strength']:.2f}")
|
680 |
+
st.markdown(f"๐๏ธ Rider Skill: {st.session_state.game_state['rider_skill']:.2f}")
|
681 |
+
|
682 |
+
# ๐ Display Markdown Preview
|
683 |
+
if not st.session_state.game_state['history_df'].empty:
|
684 |
+
st.markdown(create_markdown_preview(st.session_state.game_state['history_df']))
|
685 |
+
|
686 |
+
# ๐ณ Display Heterogeneous Journey Graph
|
687 |
+
if not st.session_state.game_state['history_df'].empty:
|
688 |
+
st.markdown("## ๐ณ Your Journey (Heterogeneous Graph)")
|
689 |
+
nodes, edges = create_heterogeneous_graph(st.session_state.game_state['history_df'])
|
690 |
+
try:
|
691 |
+
streamlit_flow('cat_rider_flow',
|
692 |
+
nodes,
|
693 |
+
edges,
|
694 |
+
layout=TreeLayout(direction='down'),
|
695 |
+
fit_view=True,
|
696 |
+
height=600)
|
697 |
+
except Exception as e:
|
698 |
+
st.error(f"An error occurred while rendering the journey graph: {str(e)}")
|
699 |
+
st.markdown("Please try refreshing the page if the graph doesn't appear.")
|
700 |
+
|
701 |
+
# ๐ Character Stats Visualization
|
702 |
+
data = {"Stat": ["Gear Strength ๐ก๏ธ", "Rider Skill ๐"],
|
703 |
+
"Value": [st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill']]}
|
704 |
+
df = pd.DataFrame(data)
|
705 |
+
fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats ๐")
|
706 |
+
st.plotly_chart(fig)
|
707 |
+
|
708 |
+
if __name__ == "__main__":
|
709 |
+
main()
|
710 |
+
|
711 |
+
|
712 |
+
|