|
import streamlit as st |
|
import pandas as pd |
|
import plotly.express as px |
|
import random |
|
import json |
|
from streamlit_flow import streamlit_flow |
|
from streamlit_flow.elements import StreamlitFlowNode, StreamlitFlowEdge |
|
from streamlit_flow.layouts import TreeLayout |
|
|
|
def generate_situation(): |
|
situations = [ |
|
"The Village in Peril", |
|
"The Cursed Artifact", |
|
"The Sacred Pact", |
|
"The Shapeshifter's Challenge", |
|
"The Fox Fire Trial" |
|
] |
|
return random.choice(situations) |
|
|
|
def generate_actions(): |
|
actions = [ |
|
("Use Fox Fire", "π₯"), |
|
("Shapeshift", "π¦"), |
|
("Possess an Object", "π»"), |
|
("Call Upon Ancient Spirits", "π"), |
|
("Use Mystical Artifact", "π‘οΈ") |
|
] |
|
return random.sample(actions, 3) |
|
|
|
def evaluate_action(action, power_level, mystical_energy, history): |
|
base_success_chance = (power_level + mystical_energy) / 2 |
|
|
|
|
|
if action in history: |
|
success_chance = base_success_chance + (history[action] * 2) |
|
else: |
|
success_chance = base_success_chance |
|
|
|
outcome = random.randint(1, 100) <= success_chance |
|
return outcome, success_chance |
|
|
|
def update_graph(nodes, edges, situation, action, outcome): |
|
new_node_id = f"{len(nodes)}-{situation}-{action}" |
|
new_node = StreamlitFlowNode(new_node_id, (0, 0), {'content': f"{situation}\n{action}\nOutcome: {'Success' if outcome else 'Failure'}"}, 'output', 'bottom', 'top') |
|
nodes.append(new_node) |
|
|
|
if len(nodes) > 1: |
|
new_edge = StreamlitFlowEdge(f"{nodes[-2].id}-{new_node.id}", nodes[-2].id, new_node.id, animated=True) |
|
edges.append(new_edge) |
|
|
|
return nodes, edges |
|
|
|
def save_game_state(state): |
|
return json.dumps(state) |
|
|
|
def load_game_state(state_json): |
|
return json.loads(state_json) |
|
|
|
def app(): |
|
st.markdown("# Kitsune - The Mystical Shape-Shifter Game π¦") |
|
|
|
if 'game_state' not in st.session_state: |
|
st.session_state.game_state = { |
|
'nodes': [], |
|
'edges': [], |
|
'score': 0, |
|
'history': {}, |
|
'power_level': 50, |
|
'mystical_energy': 75 |
|
} |
|
|
|
|
|
st.sidebar.markdown("## Game Stats") |
|
st.sidebar.markdown(f"Score: {st.session_state.game_state['score']}") |
|
|
|
|
|
power_level = st.sidebar.slider('Power Level β‘', 0, 100, st.session_state.game_state['power_level']) |
|
mystical_energy = st.sidebar.slider('Mystical Energy β¨', 0, 100, st.session_state.game_state['mystical_energy']) |
|
|
|
|
|
situation = generate_situation() |
|
actions = generate_actions() |
|
|
|
st.markdown(f"## Current Situation: {situation}") |
|
st.markdown("Choose your action:") |
|
|
|
cols = st.columns(3) |
|
for i, (action, emoji) in enumerate(actions): |
|
if cols[i].button(f"{emoji} {action}"): |
|
outcome, success_chance = evaluate_action(action, power_level, mystical_energy, st.session_state.game_state['history']) |
|
|
|
st.markdown(f"You decided to: {action}") |
|
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 |
|
|
|
|
|
if action in st.session_state.game_state['history']: |
|
st.session_state.game_state['history'][action] += 1 if outcome else -1 |
|
else: |
|
st.session_state.game_state['history'][action] = 1 if outcome else -1 |
|
|
|
st.session_state.game_state['nodes'], st.session_state.game_state['edges'] = update_graph( |
|
st.session_state.game_state['nodes'], |
|
st.session_state.game_state['edges'], |
|
situation, |
|
action, |
|
outcome |
|
) |
|
|
|
|
|
if st.session_state.game_state['nodes']: |
|
streamlit_flow('kitsune_game_flow', |
|
st.session_state.game_state['nodes'], |
|
st.session_state.game_state['edges'], |
|
layout=TreeLayout(direction='TB'), |
|
fit_view=True, |
|
height=600) |
|
|
|
|
|
data = {"Stat": ["Power Level", "Mystical Energy"], |
|
"Value": [power_level, mystical_energy]} |
|
df = pd.DataFrame(data) |
|
fig = px.bar(df, x='Stat', y='Value', title="Kitsune Stats π") |
|
st.plotly_chart(fig) |
|
|
|
|
|
st.markdown("## Save/Load Game") |
|
if st.button("Save Game"): |
|
game_state_json = save_game_state(st.session_state.game_state) |
|
st.download_button( |
|
label="Download Game State", |
|
data=game_state_json, |
|
file_name="kitsune_game_state.json", |
|
mime="application/json" |
|
) |
|
|
|
uploaded_file = st.file_uploader("Load Game State", type="json") |
|
if uploaded_file is not None: |
|
game_state_json = uploaded_file.getvalue().decode("utf-8") |
|
st.session_state.game_state = load_game_state(game_state_json) |
|
st.success("Game state loaded successfully!") |
|
|
|
if __name__ == "__main__": |
|
app() |