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 # šŸŒ Game World Data 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.", "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.", "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.", "emoji": "šŸ‘‘", "type": "competition" } ] ACTIONS = [ { "id": "stealth", "name": "Use Stealth", "description": "Sneak past obstacles or enemies without being detected.", "emoji": "šŸ¤«", "type": "skill" }, { "id": "agility", "name": "Showcase Agility", "description": "Perform impressive acrobatic maneuvers to overcome challenges.", "emoji": "šŸƒ", "type": "physical" }, { "id": "charm", "name": "Charm Others", "description": "Use your cat's natural charisma to win over allies or distract foes.", "emoji": "šŸ˜»", "type": "social" }, { "id": "resourcefulness", "name": "Be Resourceful", "description": "Utilize the environment or items in creative ways to solve problems.", "emoji": "šŸ§ ", "type": "mental" } ] # šŸŽ² Game Mechanics def generate_situation(): return random.choice(SITUATIONS) def generate_actions(): return random.sample(ACTIONS, 3) 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: conclusions = [ f"Your {action['name']} was successful! You've overcome the challenges of {situation['name']}.", f"Through clever use of {action['name']}, you've triumphed in the {situation['name']}!", f"Your mastery of {action['name']} has led to a victorious outcome in the {situation['name']}!" ] else: conclusions = [ f"Despite your efforts with {action['name']}, you've failed to overcome the {situation['name']}.", f"Your attempt at {action['name']} wasn't enough to succeed in the {situation['name']}.", f"The challenges of {situation['name']} proved too great for your {action['name']} this time." ] return random.choice(conclusions) 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 # šŸŒ³ 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[row['situation_type']]) 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[row['action_type']]) 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 # šŸŽ® Main Game Application def main(): st.title("šŸ± Cat Rider šŸ‡") st.markdown(""" ## Welcome to Cat Rider! 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. """) # šŸ“œ Game Rules st.markdown(""" ### šŸ“œ Game Rules | šŸ›¤ļø Step | šŸ“ Description | |---------|----------------| | 1ļøāƒ£ | Choose your Cat Rider | | 2ļøāƒ£ | Select the 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': 5, 'rider_skill': 5, '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']) } # šŸ“Š Game Stats st.sidebar.markdown("## šŸ“Š Game Stats") st.sidebar.markdown(f"**Score:** {st.session_state.game_state['score']}") st.sidebar.markdown(f"**Gear Strength:** {st.session_state.game_state['gear_strength']:.2f}") st.sidebar.markdown(f"**Rider Skill:** {st.session_state.game_state['rider_skill']:.2f}") # šŸŽ­ Game Loop 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()