I love the Huggingface Editor - One of the Most Satisfying experiences is commit and run to see the new wonders at record time.

#1
by awacke1 - opened

image.png

import streamlit as st
import pandas as pd
import plotly.express as px
import random
import uuid
import os
from datetime import datetime
from streamlit_flow import streamlit_flow
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge
from streamlit_flow.layouts import TreeLayout

Set page configuration to wide mode

Site_Name = '๐ŸฆCatRider๐Ÿˆ'
title="๐ŸฆCatRider๐Ÿˆby๐Ÿ‘คAaron Wacker"
helpURL='https://huggingface.co./awacke1'
bugURL='https://huggingface.co./spaces/awacke1'
icons='๐Ÿฆ'

useConfig=True
if useConfig:
st.set_page_config(
page_title=title,
page_icon=icons,
layout="wide",
initial_sidebar_state="auto",
menu_items={
'Get Help': helpURL,
'Report a bug': bugURL,
'About': title
}
)

๐Ÿฑ 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},
{"name": "Shadow", "type": "Mystery", "emoji": "๐Ÿ‘ค", "strength": 4, "skill": 6},
{"name": "Simba", "type": "Royalty", "emoji": "๐Ÿฆ", "strength": 5, "skill": 7},
{"name": "Luna", "type": "Magic", "emoji": "๐ŸŒ™", "strength": 3, "skill": 8},
{"name": "Leo", "type": "Courage", "emoji": "๐Ÿฏ", "strength": 6, "skill": 5},
{"name": "Milo", "type": "Playful", "emoji": "๐Ÿ˜ผ", "strength": 4, "skill": 7},
{"name": "Nala", "type": "Grace", "emoji": "๐Ÿˆ", "strength": 5, "skill": 6}
]

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 (Expanded to 10 Situations)

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", "preferred_action": "agility"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"},
{"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"}
]

๐Ÿง  Expanded Actions (10 Actions)

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": "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"},
{"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"},
{"id": "insight", "name": "Use Insight", "description": "Tap into ancient feline wisdom to solve puzzles and mysteries. A cat always knows! ๐Ÿ”ฎ", "emoji": "๐Ÿ”ฎ", "type": "mental"},
{"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": "negotiation", "name": "Negotiate", "description": "Use diplomacy and clever negotiation to get out of a tight spot. Every cat has their price! ๐Ÿ’ผ", "emoji": "๐Ÿ’ผ", "type": "social"}
]

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. ๐Ÿ“š"
]

Function to save history to a markdown file

def save_history_to_file(history_df, user_id):
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = f"history_{user_id}_{timestamp}.md"
markdown = create_markdown_preview(history_df)
with open(filename, 'w', encoding='utf-8') as f:
f.write(markdown)
return filename

Function to load saved histories

def load_saved_histories():
history_files = [f for f in os.listdir('.') if f.startswith('history_') and f.endswith('.md')]
return history_files

๐Ÿง  Game Mechanics

def generate_situation():
return random.choice(SITUATIONS)

def generate_actions():
return random.sample(ACTIONS, min(3, len(ACTIONS)))

def evaluate_action(situation, action, gear_strength, rider_skill, history):
# Adjusted base success chance to around 50%
base_success_chance = 50

# Adjust success chance based on gear strength and rider skill
stat_modifier = (gear_strength + rider_skill - 10) * 2  # Assuming average stats sum to 10
success_chance = base_success_chance + stat_modifier

# Boost success chance for preferred action
if action['id'] == situation['preferred_action']:
    success_chance += 10

# Adjust based on action history
if action['id'] in history:
    success_chance += history[action['id']] * 2

# Clamp success chance between 5% and 95%
success_chance = max(5, min(95, 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)

๐Ÿ”„ Update character stats based on outcome

def update_character_stats(game_state, outcome):
if outcome:
# Increase stats on success
game_state['rider_skill'] += 0.5
game_state['gear_strength'] += 0.2
else:
# Decrease stats on failure, but not below 1
game_state['rider_skill'] = max(1, game_state['rider_skill'] - 0.3)
game_state['gear_strength'] = max(1, game_state['gear_strength'] - 0.1)
return game_state

๐ŸŒณ Journey Visualization

def create_knowledge_graph(history_df):
nodes = []
edges = []
node_ids = {}
for index, row in history_df.iterrows():
situation_node_id = f"situation_{row['situation_id']}"
action_node_id = f"action_{index}"

    # Situation node
    if situation_node_id not in node_ids:
        situation_node = StreamlitFlowNode(
            situation_node_id,
            pos=(0, 0),
            data={'content': f"{row['situation_emoji']} {row['situation_name']}"},
            type='default',
            shape='ellipse'
        )
        nodes.append(situation_node)
        node_ids[situation_node_id] = situation_node_id

    # Attempt node (action and outcome)
    outcome_content = 'โœ… Success' if row['outcome'] else 'โŒ Failure'
    stars = 'โญ' * int(row['score'])
    attempt_node = StreamlitFlowNode(
        action_node_id,
        pos=(0, 0),
        data={'content': f"{row['action_emoji']} {row['action_name']} ({outcome_content})\n{row['conclusion']}\n{stars}"},
        type='default',
        shape='rectangle'
    )
    nodes.append(attempt_node)

    # Edge from situation to attempt
    edges.append(StreamlitFlowEdge(
        id=f"edge_{situation_node_id}_{action_node_id}",
        source=situation_node_id,
        target=action_node_id,
        animated=True
    ))

return nodes, edges

๐Ÿ“ Markdown Preview with Subpoints for Each Action

def create_markdown_preview(history_df):
markdown = "## ๐ŸŒณ Journey Preview\n\n"
grouped = history_df.groupby(['situation_name'], sort=False)

for situation_name, group in grouped:
    markdown += f"### {group.iloc[0]['situation_emoji']} **{situation_name}**\n"
    for _, row in group.iterrows():
        outcome_str = 'โœ… Success' if row['outcome'] else 'โŒ Failure'
        stars = 'โญ' * int(row['score'])
        markdown += f"- Attempt {row['attempt']}: {row['action_emoji']} **{row['action_name']}**: {outcome_str} {stars}\n"
        markdown += f"  - {row['conclusion']}\n"
    markdown += "\n"
return markdown

๐Ÿ”„ Update game state with the result of the action

def update_game_state(game_state, situation, action, outcome, timestamp):
# Generate the encounter conclusion (success or failure)
conclusion = generate_encounter_conclusion(situation, action, outcome)

# Update stats based on the outcome
game_state = update_character_stats(game_state, outcome)

# Update attempt count
attempt = game_state['current_attempt']

# Create a new record for the history
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']],
    'attempt': [attempt],
    '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']]
})

# Add the new record to the game history DataFrame
game_state['history_df'] = pd.concat([game_state['history_df'], new_record], ignore_index=True)

# Update the history of actions (tracking how many times each action was used)
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

๐Ÿ… Display Scoreboard with Star Emojis and Buckyball Outline

def display_scoreboard(game_state):
# Calculate number of star emojis based on score
score = game_state['score']
stars = 'โญ' * int(score)

# Create buckyball style outline (simplified)
outline = ''
if score > 0:
    outline = '''
    โฌก โฌก โฌก โฌก โฌก
     โฌก โฌก โฌก โฌก
    โฌก โฌก โฌก โฌก โฌก
     โฌก โฌก โฌก โฌก
    โฌก โฌก โฌก โฌก โฌก
    '''
else:
    outline = 'No successes yet.'

st.markdown("## ๐Ÿ… Scoreboard")
st.markdown(f"**Score:** {stars} ({score})")
st.markdown(outline)

๐ŸŽฎ 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', 'attempt', 'action_id', 'action_name', 'action_emoji', 'action_type', 'outcome', 'conclusion', 'gear_strength', 'rider_skill', 'score']),
        'current_situation': None,
        'current_attempt': 1,
        'actions': [],
        'succeeded': False
    }

# Sidebar functionality
st.sidebar.header("๐Ÿ“‚ Saved Histories")
history_files = load_saved_histories()
if history_files:
    selected_history = st.sidebar.selectbox("Select a history to load:", history_files)
    if st.sidebar.button("Load Selected History"):
        with open(selected_history, 'r', encoding='utf-8') as f:
            st.session_state.game_state['loaded_history'] = f.read()
        st.sidebar.success(f"Loaded {selected_history}")

# ๐Ÿฑ 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']})", key=f"rider_{i}"):
            st.session_state.game_state['cat_rider'] = rider
            st.session_state.game_state['rider_skill'] = rider['skill']
            st.session_state.game_state['user_id'] = rider['name']  # Use rider name as user ID

# ๐Ÿ‡ 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']})", key=f"gear_{i}"):
            st.session_state.game_state['riding_gear'] = gear
            st.session_state.game_state['gear_strength'] = gear['strength']

# ๐ŸŽญ Game Loop
game_state = st.session_state.game_state

if game_state['cat_rider'] is not None and game_state['riding_gear'] is not None:
    # Check if current_situation is None or if the player succeeded in the previous situation
    if game_state['current_situation'] is None or game_state['succeeded']:
        # Generate a new situation
        game_state['current_situation'] = generate_situation()
        game_state['current_attempt'] = 1
        game_state['succeeded'] = False
        # Clear actions for new situation
        game_state['actions'] = []

    situation = game_state['current_situation']
    st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
    st.markdown(situation['description'])
    st.markdown("### ๐ŸŽญ Choose your action:")

    # Generate actions if not already generated
    if not game_state['actions']:
        game_state['actions'] = generate_actions()

    cols = st.columns(3)
    action_chosen = False
    for i, action in enumerate(game_state['actions']):
        if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})", key=f"action_{i}_{game_state['current_attempt']}"):
            outcome, success_chance = evaluate_action(situation, action, game_state['gear_strength'], game_state['rider_skill'], 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:
                game_state['score'] += 1
                game_state['succeeded'] = True
                # Clear actions for next situation
                game_state['actions'] = []
            else:
                game_state['current_attempt'] += 1
                # Generate new actions for retry
                game_state['actions'] = generate_actions()

            # ๐Ÿ”„ Update game state
            game_state = update_game_state(
                game_state,
                situation,
                action,
                outcome,
                timestamp
            )

            # Display conclusion
            conclusion = 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: {game_state['gear_strength']:.2f}")
            st.markdown(f"๐Ÿ‹๏ธ Rider Skill: {game_state['rider_skill']:.2f}")

            # ๐Ÿ… Display Scoreboard
            display_scoreboard(game_state)

            action_chosen = True
            break  # Exit the loop after action is taken

    # If no action was chosen, show a message
    if not action_chosen:
        st.markdown("Please choose an action to proceed.")

    # Integration point for both functions
    if not game_state['history_df'].empty:
        # ๐Ÿ“ Display Markdown Preview
        st.markdown(create_markdown_preview(game_state['history_df']))

        # ๐ŸŒณ Display Knowledge Journey Graph
        st.markdown("## ๐ŸŒณ Your Journey (Knowledge Graph)")
        nodes, edges = create_knowledge_graph(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": [game_state['gear_strength'], game_state['rider_skill']]}
        df = pd.DataFrame(data)
        fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats ๐Ÿ“Š")
        st.plotly_chart(fig)

        # Save history to file
        if st.button("๐Ÿ’พ Save Game History"):
            filename = save_history_to_file(game_state['history_df'], game_state['user_id'])
            st.success(f"History saved to {filename}")
            # Update history files list
            history_files = load_saved_histories()

        # Provide download buttons for saved histories
        st.sidebar.markdown("### ๐Ÿ“ฅ Download Histories")
        for history_file in history_files:
            with open(history_file, 'r', encoding='utf-8') as f:
                st.sidebar.download_button(
                    label=f"Download {history_file}",
                    data=f.read(),
                    file_name=history_file,
                    mime='text/markdown'
                )

if name == "main":
main()

Sign up or log in to comment