import streamlit as st import pandas as pd import plotly.express as px import random import uuid from datetime import datetime from streamlit_flow import streamlit_flow from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge from streamlit_flow.layouts import TreeLayout # 🐱 Cat Rider and Gear Data CAT_RIDERS = [ {"name": "Whiskers", "type": "Speed", "emoji": "🐾", "strength": 3, "skill": 7}, {"name": "Fluffy", "type": "Bravery", "emoji": "🦁", "strength": 5, "skill": 5}, {"name": "Midnight", "type": "Stealth", "emoji": "🌑", "strength": 4, "skill": 6}, {"name": "Bella", "type": "Charm", "emoji": "😺", "strength": 2, "skill": 8} ] RIDING_GEAR = [ {"name": "Feathered Boots", "type": "Agility", "strength": 2}, {"name": "Golden Armor", "type": "Defense", "strength": 4}, {"name": "Magic Whisker Wand", "type": "Magic", "strength": 3}, {"name": "Sleek Shadow Cape", "type": "Stealth", "strength": 1} ] # 🌍 Game World Data - SITUATIONS and ACTIONS expanded with humorous elements SITUATIONS = [ { "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" }, { "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" }, { "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. Be prepared to face noble feline adversaries! 🐱", "emoji": "👑", "type": "competition" }, { "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. But beware – the palace mice are guarding it! 🧀", "emoji": "🧀", "type": "heist" }, { "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" }, { "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" }, { "id": "cat_nap", "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" }, { "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. But first, you must pilot your rocket through an asteroid field. 🚀", "emoji": "🌕", "type": "exploration" }, { "id": "pirate_cove", "name": "The Pirate Cove", "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! 🏴‍☠️", "emoji": "🏴‍☠️", "type": "exploration" }, { "id": "cat_casino", "name": "The Cat Casino", "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! 🎲", "emoji": "🎰", "type": "competition" } ] ACTIONS = [ { "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" }, { "id": "agility", "name": "Showcase Agility", "description": "Perform impressive acrobatic maneuvers to overcome challenges. Cats always land on their feet, right? 🏃", "emoji": "🏃", "type": "physical" }, { "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" }, { "id": "resourcefulness", "name": "Be Resourceful", "description": "Utilize the environment or items in creative ways to solve problems. Think on your paws! 🧠", "emoji": "🧠", "type": "mental" }, { "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" }, { "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" }, { "id": "precision", "name": "Precision Attack", "description": "Execute a perfectly timed attack to disable traps or defeat enemies. Purrfection in motion! 🎯", "emoji": "🎯", "type": "skill" }, { "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" }, { "id": "speed", "name": "Sprint Away", "description": "Run faster than you've ever run before to escape danger. Just like a cat fleeing a vacuum cleaner! 🏃‍♀️", "emoji": "🏃‍♀️", "type": "physical" }, { "id": "insight", "name": "Use Insight", "description": "Tap into ancient feline wisdom to solve puzzles and mysteries. A cat always knows! 🔮", "emoji": "🔮", "type": "mental" } ] # Expanded conclusions for outcomes - 10 items each for success and failure SUCCESS_CONCLUSIONS = [ "Your swift paws led you to victory! 🎉", "You pounced at the perfect moment! 🏆", "The stars aligned for your cat rider! 🌟", "You navigated the challenge like a true feline champion! 🐱", "Victory is sweet, just like a bowl of fresh milk! 🥛", "Your opponents are left in awe of your skills! 😺", "You’ve earned the title of Cat Commander! 🏅", "All the other cats are jealous of your agility! 🏃‍♂️", "Your strategy was flawless, and the victory is yours! 🎖️", "Your cat rider is now a legend in the feline world! 👑" ] FAILURE_CONCLUSIONS = [ "You tried your best, but it just wasn’t enough. 😿", "Maybe next time, kitty. Keep your tail up! 🐾", "That didn’t go as planned. Time for a catnap to recover! 💤", "Even the best cats have their off days. 😔", "The challenge was too great this time. Better luck next time! 🍀", "You might need more than nine lives to get through this. 🐈", "The enemy was too clever for your plan. 🧠", "You tripped over your own paws! 🐾", "The cat gods were not in your favor today. 🙀", "It’s okay, every cat has a learning curve. 📚" ] # 🧠 Game Mechanics def generate_situation(): return random.choice(SITUATIONS) def generate_actions(): return random.sample(ACTIONS, min(3, len(ACTIONS))) def evaluate_action(action, gear_strength, rider_skill, history): base_success_chance = (gear_strength + rider_skill) / 2 if action['id'] in history: success_chance = base_success_chance + (history[action['id']] * 2) else: success_chance = base_success_chance outcome = random.randint(1, 100) <= success_chance return outcome, success_chance def generate_encounter_conclusion(situation, action, outcome): if outcome: return random.choice(SUCCESS_CONCLUSIONS) else: return random.choice(FAILURE_CONCLUSIONS) # 🌳 Journey Visualization with Heterogeneous Graph Structure def create_heterogeneous_graph(history_df): nodes = [] edges = [] # Define node shapes based on situation and action types situation_shapes = { "escape": "diamond", "exploration": "triangle", "competition": "star" } action_shapes = { "skill": "square", "physical": "circle", "social": "hexagon", "mental": "octagon" } for index, row in history_df.iterrows(): situation_id = f"situation-{index}" action_id = f"action-{index}" conclusion_id = f"conclusion-{index}" # Create situation node situation_content = f"{row['situation_emoji']} {row['situation_name']}\n🕒 {row['timestamp']}" situation_node = StreamlitFlowNode(situation_id, (0, 0), {'content': situation_content}, 'output', 'bottom', 'top', shape=situation_shapes.get(row['situation_type'], 'ellipse')) nodes.append(situation_node) # Create action node action_content = f"{row['action_emoji']} {row['action_name']}\nOutcome: {'✅ Success' if row['outcome'] else '❌ Failure'}" action_node = StreamlitFlowNode(action_id, (0, 0), {'content': action_content}, 'output', 'bottom', 'top', shape=action_shapes.get(row['action_type'], 'ellipse')) nodes.append(action_node) # Create conclusion node conclusion_content = f"📜 {row['conclusion']}\n💪 Gear: {row['gear_strength']:.2f} | 🏋️ Skill: {row['rider_skill']:.2f}" conclusion_node = StreamlitFlowNode(conclusion_id, (0, 0), {'content': conclusion_content}, 'output', 'bottom', 'top', shape='parallelogram') nodes.append(conclusion_node) # Create edges edges.append(StreamlitFlowEdge(f"{situation_id}-{action_id}", situation_id, action_id, animated=True, dashed=False)) edges.append(StreamlitFlowEdge(f"{action_id}-{conclusion_id}", action_id, conclusion_id, animated=True, dashed=False)) # Create edge to previous conclusion if not the first node if index > 0: prev_conclusion_id = f"conclusion-{index-1}" edges.append(StreamlitFlowEdge(f"{prev_conclusion_id}-{situation_id}", prev_conclusion_id, situation_id, animated=True, dashed=True)) return nodes, edges # 📝 Markdown Preview def create_markdown_preview(history_df): markdown = "## 🌳 Journey Preview\n\n" for index, row in history_df.iterrows(): indent = " " * (index * 3) markdown += f"{indent}🌟 **{row['situation_name']}** ({row['situation_type']})\n" markdown += f"{indent} ↪ {row['action_emoji']} {row['action_name']} ({row['action_type']}): " markdown += "✅ Success\n" if row['outcome'] else "❌ Failure\n" markdown += f"{indent} 📜 {row['conclusion']}\n" markdown += f"{indent} 💪 Gear: {row['gear_strength']:.2f} | 🏋️ Skill: {row['rider_skill']:.2f}\n\n" return markdown # 🔄 Game State Management def update_game_state(game_state, situation, action, outcome, timestamp): conclusion = generate_encounter_conclusion(situation, action, outcome) game_state = update_character_stats(game_state, outcome) new_record = pd.DataFrame({ 'user_id': [game_state['user_id']], 'timestamp': [timestamp], 'situation_id': [situation['id']], 'situation_name': [situation['name']], 'situation_emoji': [situation['emoji']], 'situation_type': [situation['type']], 'action_id': [action['id']], 'action_name': [action['name']], 'action_emoji': [action['emoji']], 'action_type': [action['type']], 'outcome': [outcome], 'conclusion': [conclusion], 'gear_strength': [game_state['gear_strength']], 'rider_skill': [game_state['rider_skill']], 'score': [game_state['score']] }) game_state['history_df'] = pd.concat([game_state['history_df'], new_record], ignore_index=True) if action['id'] in game_state['history']: game_state['history'][action['id']] += 1 if outcome else -1 else: game_state['history'][action['id']] = 1 if outcome else -1 return game_state # 🔄 Update character stats based on the outcome def update_character_stats(game_state, outcome): if outcome: game_state['gear_strength'] = min(10, game_state['gear_strength'] + random.uniform(0.1, 0.5)) game_state['rider_skill'] = min(10, game_state['rider_skill'] + random.uniform(0.1, 0.5)) return game_state # 🎮 Main Game Application def main(): st.title("🐱 Cat Rider 🏇") # 📜 Game Rules st.markdown(""" ### 📜 Game Rules | Step | Description | |------|-------------| | 1️⃣ | Choose your Cat Rider | | 2️⃣ | Select your Riding Gear | | 3️⃣ | Set off on an Adventure | | 4️⃣ | Encounter Challenges and Make Decisions | | 5️⃣ | Complete the Quest and Grow Stronger | """) # 🏁 Initialize game state if 'game_state' not in st.session_state: st.session_state.game_state = { 'user_id': str(uuid.uuid4()), 'score': 0, 'history': {}, 'gear_strength': 0, 'rider_skill': 0, 'cat_rider': None, 'riding_gear': None, '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']) } # 🐱 Cat Rider Selection if st.session_state.game_state['cat_rider'] is None: st.markdown("## Choose Your Cat Rider:") cols = st.columns(len(CAT_RIDERS)) for i, rider in enumerate(CAT_RIDERS): if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})"): st.session_state.game_state['cat_rider'] = rider st.session_state.game_state['rider_skill'] = rider['skill'] # 🏇 Riding Gear Selection if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None: st.markdown("## Select Your Riding Gear:") cols = st.columns(len(RIDING_GEAR)) for i, gear in enumerate(RIDING_GEAR): if cols[i].button(f"{gear['name']} ({gear['type']})"): st.session_state.game_state['riding_gear'] = gear st.session_state.game_state['gear_strength'] = gear['strength'] # 🎭 Game Loop if st.session_state.game_state['cat_rider'] is not None and st.session_state.game_state['riding_gear'] is not None: situation = generate_situation() actions = generate_actions() st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})") st.markdown(situation['description']) st.markdown("### 🎭 Choose your action:") cols = st.columns(3) for i, action in enumerate(actions): if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})"): 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']) timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") st.markdown(f"You decided to: **{action['name']}** ({action['type']})") st.markdown(action['description']) st.markdown(f"**Outcome:** {'✅ Success!' if outcome else '❌ Failure.'}") st.markdown(f"**Success Chance:** {success_chance:.2f}%") if outcome: st.session_state.game_state['score'] += 1 # 🔄 Update game state st.session_state.game_state = update_game_state( st.session_state.game_state, situation, action, outcome, timestamp ) # Display conclusion conclusion = st.session_state.game_state['history_df'].iloc[-1]['conclusion'] st.markdown(f"**Encounter Conclusion:** {conclusion}") # Display updated stats st.markdown(f"**Updated Stats:**") st.markdown(f"💪 Gear Strength: {st.session_state.game_state['gear_strength']:.2f}") st.markdown(f"🏋️ Rider Skill: {st.session_state.game_state['rider_skill']:.2f}") # 📝 Display Markdown Preview if not st.session_state.game_state['history_df'].empty: st.markdown(create_markdown_preview(st.session_state.game_state['history_df'])) # 🌳 Display Heterogeneous Journey Graph if not st.session_state.game_state['history_df'].empty: st.markdown("## 🌳 Your Journey (Heterogeneous Graph)") nodes, edges = create_heterogeneous_graph(st.session_state.game_state['history_df']) try: streamlit_flow('cat_rider_flow', nodes, edges, layout=TreeLayout(direction='down'), fit_view=True, height=600) except Exception as e: st.error(f"An error occurred while rendering the journey graph: {str(e)}") st.markdown("Please try refreshing the page if the graph doesn't appear.") # 📊 Character Stats Visualization data = {"Stat": ["Gear Strength 🛡️", "Rider Skill 🏇"], "Value": [st.session_state.game_state['gear_strength'], st.session_state.game_state['rider_skill']]} df = pd.DataFrame(data) fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats 📊") st.plotly_chart(fig) if __name__ == "__main__": main()