awacke1 commited on
Commit
4c4ec27
·
verified ·
1 Parent(s): be66a8a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +294 -59
app.py CHANGED
@@ -1,5 +1,3 @@
1
-
2
-
3
  import streamlit as st
4
  import pandas as pd
5
  import plotly.express as px
@@ -32,7 +30,6 @@ if useConfig:
32
  }
33
  )
34
 
35
-
36
  # 🐱 Cat Rider and Gear Data
37
  CAT_RIDERS = [
38
  {"name": "Whiskers", "type": "Speed", "emoji": "🐾", "strength": 3, "skill": 7},
@@ -82,9 +79,32 @@ ACTIONS = [
82
  {"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"}
83
  ]
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
- SUCCESS_CONCLUSIONS = ["Your swift paws led you to victory! 🎉"]
87
- FAILURE_CONCLUSIONS = ["You tried your best, but it just wasn’t enough. 😿"]
 
 
 
 
 
 
 
 
 
 
88
 
89
  # Function to save history to a markdown file
90
  def save_history_to_file(history_df, user_id):
@@ -100,50 +120,54 @@ def load_saved_histories():
100
  history_files = [f for f in os.listdir('.') if f.startswith('history_') and f.endswith('.md')]
101
  return history_files
102
 
103
- # Generate a random situation
104
  def generate_situation():
105
  return random.choice(SITUATIONS)
106
 
107
- # Generate random actions
108
  def generate_actions():
109
  return random.sample(ACTIONS, min(3, len(ACTIONS)))
110
 
111
- # Evaluate the chosen action
112
  def evaluate_action(situation, action, gear_strength, rider_skill, history):
 
113
  base_success_chance = 50
114
- stat_modifier = (gear_strength + rider_skill - 10) * 2
 
 
115
  success_chance = base_success_chance + stat_modifier
 
 
116
  if action['id'] == situation['preferred_action']:
117
  success_chance += 10
 
 
 
 
 
 
118
  success_chance = max(5, min(95, success_chance))
 
119
  outcome = random.randint(1, 100) <= success_chance
120
  return outcome, success_chance
121
 
122
- # Update character stats based on outcome
 
 
 
 
 
 
123
  def update_character_stats(game_state, outcome):
124
  if outcome:
 
125
  game_state['rider_skill'] += 0.5
126
  game_state['gear_strength'] += 0.2
127
  else:
 
128
  game_state['rider_skill'] = max(1, game_state['rider_skill'] - 0.3)
129
  game_state['gear_strength'] = max(1, game_state['gear_strength'] - 0.1)
130
  return game_state
131
 
132
- # Create markdown preview of history
133
- def create_markdown_preview(history_df):
134
- markdown = "## 🌳 Journey Preview\n\n"
135
- grouped = history_df.groupby(['situation_name'], sort=False)
136
- for situation_name, group in grouped:
137
- markdown += f"### {group.iloc[0]['situation_emoji']} **{situation_name}**\n"
138
- for _, row in group.iterrows():
139
- outcome_str = '✅ Success' if row['outcome'] else '❌ Failure'
140
- stars = '⭐' * int(row['score'])
141
- markdown += f"- Attempt {row['attempt']}: {row['action_emoji']} **{row['action_name']}**: {outcome_str} {stars}\n"
142
- markdown += f" - {row['conclusion']}\n"
143
- markdown += "\n"
144
- return markdown
145
-
146
- # Create knowledge graph with markdown support in nodes
147
  def create_knowledge_graph(history_df):
148
  nodes = []
149
  edges = []
@@ -152,38 +176,27 @@ def create_knowledge_graph(history_df):
152
  situation_node_id = f"situation_{row['situation_id']}"
153
  action_node_id = f"action_{index}"
154
 
155
- # Situation node with markdown content
156
  if situation_node_id not in node_ids:
157
  situation_node = StreamlitFlowNode(
158
- id=situation_node_id,
159
  pos=(0, 0),
160
- data={'content': f"### {row['situation_emoji']} {row['situation_name']}\n\n{row['description']}"},
161
  type='default',
162
- shape='ellipse',
163
- width=300
164
  )
165
  nodes.append(situation_node)
166
  node_ids[situation_node_id] = situation_node_id
167
 
168
- # Attempt node (action and outcome) with markdown content
169
- outcome_content = '✅ **Success**' if row['outcome'] else '❌ **Failure**'
170
  stars = '⭐' * int(row['score'])
171
- attempt_node_content = f"""
172
- #### {row['action_emoji']} {row['action_name']} ({outcome_content})
173
-
174
- **Conclusion:** {row['conclusion']}
175
-
176
- **Score:** {stars}
177
-
178
- **Gear Strength:** {row['gear_strength']:.2f} | **Rider Skill:** {row['rider_skill']:.2f}
179
- """
180
  attempt_node = StreamlitFlowNode(
181
- id=action_node_id,
182
  pos=(0, 0),
183
- data={'content': attempt_node_content},
184
  type='default',
185
- shape='rectangle',
186
- width=300
187
  )
188
  nodes.append(attempt_node)
189
 
@@ -197,11 +210,103 @@ def create_knowledge_graph(history_df):
197
 
198
  return nodes, edges
199
 
200
- # Main game application
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  def main():
202
  st.title("🐱 Cat Rider 🏇")
203
 
204
- # Initialize game state
 
 
 
 
 
 
 
 
 
 
 
 
205
  if 'game_state' not in st.session_state:
206
  st.session_state.game_state = {
207
  'user_id': str(uuid.uuid4()),
@@ -218,20 +323,150 @@ def main():
218
  'succeeded': False
219
  }
220
 
221
- # Game logic...
222
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  game_state = st.session_state.game_state
224
 
225
- # 🌳 Display Knowledge Journey Graph
226
- if not game_state['history_df'].empty:
227
- nodes, edges = create_knowledge_graph(game_state['history_df'])
228
- try:
229
- streamlit_flow('cat_rider_flow', nodes, edges, layout=TreeLayout(direction='down'), fit_view=True, height=600)
230
- except Exception as e:
231
- st.error(f"An error occurred while rendering the journey graph: {str(e)}")
232
- st.markdown("Please try refreshing the page if the graph doesn't appear.")
233
-
234
- # Rest of the game logic...
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
  if __name__ == "__main__":
237
  main()
 
 
 
1
  import streamlit as st
2
  import pandas as pd
3
  import plotly.express as px
 
30
  }
31
  )
32
 
 
33
  # 🐱 Cat Rider and Gear Data
34
  CAT_RIDERS = [
35
  {"name": "Whiskers", "type": "Speed", "emoji": "🐾", "strength": 3, "skill": 7},
 
79
  {"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"}
80
  ]
81
 
82
+ # Expanded conclusions for outcomes - 10 items each for success and failure
83
+ SUCCESS_CONCLUSIONS = [
84
+ "Your swift paws led you to victory! 🎉",
85
+ "You pounced at the perfect moment! 🏆",
86
+ "The stars aligned for your cat rider! 🌟",
87
+ "You navigated the challenge like a true feline champion! 🐱",
88
+ "Victory is sweet, just like a bowl of fresh milk! 🥛",
89
+ "Your opponents are left in awe of your skills! 😺",
90
+ "You’ve earned the title of Cat Commander! 🏅",
91
+ "All the other cats are jealous of your agility! 🏃‍♂️",
92
+ "Your strategy was flawless, and the victory is yours! 🎖️",
93
+ "Your cat rider is now a legend in the feline world! 👑"
94
+ ]
95
 
96
+ FAILURE_CONCLUSIONS = [
97
+ "You tried your best, but it just wasn’t enough. 😿",
98
+ "Maybe next time, kitty. Keep your tail up! 🐾",
99
+ "That didn’t go as planned. Time for a catnap to recover! 💤",
100
+ "Even the best cats have their off days. 😔",
101
+ "The challenge was too great this time. Better luck next time! 🍀",
102
+ "You might need more than nine lives to get through this. 🐈",
103
+ "The enemy was too clever for your plan. 🧠",
104
+ "You tripped over your own paws! 🐾",
105
+ "The cat gods were not in your favor today. 🙀",
106
+ "It’s okay, every cat has a learning curve. 📚"
107
+ ]
108
 
109
  # Function to save history to a markdown file
110
  def save_history_to_file(history_df, user_id):
 
120
  history_files = [f for f in os.listdir('.') if f.startswith('history_') and f.endswith('.md')]
121
  return history_files
122
 
123
+ # 🧠 Game Mechanics
124
  def generate_situation():
125
  return random.choice(SITUATIONS)
126
 
 
127
  def generate_actions():
128
  return random.sample(ACTIONS, min(3, len(ACTIONS)))
129
 
 
130
  def evaluate_action(situation, action, gear_strength, rider_skill, history):
131
+ # Adjusted base success chance to around 50%
132
  base_success_chance = 50
133
+
134
+ # Adjust success chance based on gear strength and rider skill
135
+ stat_modifier = (gear_strength + rider_skill - 10) * 2 # Assuming average stats sum to 10
136
  success_chance = base_success_chance + stat_modifier
137
+
138
+ # Boost success chance for preferred action
139
  if action['id'] == situation['preferred_action']:
140
  success_chance += 10
141
+
142
+ # Adjust based on action history
143
+ if action['id'] in history:
144
+ success_chance += history[action['id']] * 2
145
+
146
+ # Clamp success chance between 5% and 95%
147
  success_chance = max(5, min(95, success_chance))
148
+
149
  outcome = random.randint(1, 100) <= success_chance
150
  return outcome, success_chance
151
 
152
+ def generate_encounter_conclusion(situation, action, outcome):
153
+ if outcome:
154
+ return random.choice(SUCCESS_CONCLUSIONS)
155
+ else:
156
+ return random.choice(FAILURE_CONCLUSIONS)
157
+
158
+ # 🔄 Update character stats based on outcome
159
  def update_character_stats(game_state, outcome):
160
  if outcome:
161
+ # Increase stats on success
162
  game_state['rider_skill'] += 0.5
163
  game_state['gear_strength'] += 0.2
164
  else:
165
+ # Decrease stats on failure, but not below 1
166
  game_state['rider_skill'] = max(1, game_state['rider_skill'] - 0.3)
167
  game_state['gear_strength'] = max(1, game_state['gear_strength'] - 0.1)
168
  return game_state
169
 
170
+ # 🌳 Journey Visualization
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  def create_knowledge_graph(history_df):
172
  nodes = []
173
  edges = []
 
176
  situation_node_id = f"situation_{row['situation_id']}"
177
  action_node_id = f"action_{index}"
178
 
179
+ # Situation node
180
  if situation_node_id not in node_ids:
181
  situation_node = StreamlitFlowNode(
182
+ situation_node_id,
183
  pos=(0, 0),
184
+ data={'content': f"{row['situation_emoji']} {row['situation_name']}"},
185
  type='default',
186
+ shape='ellipse'
 
187
  )
188
  nodes.append(situation_node)
189
  node_ids[situation_node_id] = situation_node_id
190
 
191
+ # Attempt node (action and outcome)
192
+ outcome_content = '✅ Success' if row['outcome'] else '❌ Failure'
193
  stars = '⭐' * int(row['score'])
 
 
 
 
 
 
 
 
 
194
  attempt_node = StreamlitFlowNode(
195
+ action_node_id,
196
  pos=(0, 0),
197
+ data={'content': f"{row['action_emoji']} {row['action_name']} ({outcome_content})\n{row['conclusion']}\n{stars}"},
198
  type='default',
199
+ shape='rectangle'
 
200
  )
201
  nodes.append(attempt_node)
202
 
 
210
 
211
  return nodes, edges
212
 
213
+ # 📝 Markdown Preview with Subpoints for Each Action
214
+ def create_markdown_preview(history_df):
215
+ markdown = "## 🌳 Journey Preview\n\n"
216
+ grouped = history_df.groupby(['situation_name'], sort=False)
217
+
218
+ for situation_name, group in grouped:
219
+ markdown += f"### {group.iloc[0]['situation_emoji']} **{situation_name}**\n"
220
+ for _, row in group.iterrows():
221
+ outcome_str = '✅ Success' if row['outcome'] else '❌ Failure'
222
+ stars = '⭐' * int(row['score'])
223
+ markdown += f"- Attempt {row['attempt']}: {row['action_emoji']} **{row['action_name']}**: {outcome_str} {stars}\n"
224
+ markdown += f" - {row['conclusion']}\n"
225
+ markdown += "\n"
226
+ return markdown
227
+
228
+ # 🔄 Update game state with the result of the action
229
+ def update_game_state(game_state, situation, action, outcome, timestamp):
230
+ # Generate the encounter conclusion (success or failure)
231
+ conclusion = generate_encounter_conclusion(situation, action, outcome)
232
+
233
+ # Update stats based on the outcome
234
+ game_state = update_character_stats(game_state, outcome)
235
+
236
+ # Update attempt count
237
+ attempt = game_state['current_attempt']
238
+
239
+ # Create a new record for the history
240
+ new_record = pd.DataFrame({
241
+ 'user_id': [game_state['user_id']],
242
+ 'timestamp': [timestamp],
243
+ 'situation_id': [situation['id']],
244
+ 'situation_name': [situation['name']],
245
+ 'situation_emoji': [situation['emoji']],
246
+ 'situation_type': [situation['type']],
247
+ 'attempt': [attempt],
248
+ 'action_id': [action['id']],
249
+ 'action_name': [action['name']],
250
+ 'action_emoji': [action['emoji']],
251
+ 'action_type': [action['type']],
252
+ 'outcome': [outcome],
253
+ 'conclusion': [conclusion],
254
+ 'gear_strength': [game_state['gear_strength']],
255
+ 'rider_skill': [game_state['rider_skill']],
256
+ 'score': [game_state['score']]
257
+ })
258
+
259
+ # Add the new record to the game history DataFrame
260
+ game_state['history_df'] = pd.concat([game_state['history_df'], new_record], ignore_index=True)
261
+
262
+ # Update the history of actions (tracking how many times each action was used)
263
+ if action['id'] in game_state['history']:
264
+ game_state['history'][action['id']] += 1 if outcome else -1
265
+ else:
266
+ game_state['history'][action['id']] = 1 if outcome else -1
267
+
268
+ return game_state
269
+
270
+ # 🏅 Display Scoreboard with Star Emojis and Buckyball Outline
271
+ def display_scoreboard(game_state):
272
+ # Calculate number of star emojis based on score
273
+ score = game_state['score']
274
+ stars = '⭐' * int(score)
275
+
276
+ # Create buckyball style outline (simplified)
277
+ outline = ''
278
+ if score > 0:
279
+ outline = '''
280
+ ⬡ ⬡ ⬡ ⬡ ⬡
281
+ ⬡ ⬡ ⬡ ⬡
282
+ ⬡ ⬡ ⬡ ⬡ ⬡
283
+ ⬡ ⬡ ⬡ ⬡
284
+ ⬡ ⬡ ⬡ ⬡ ⬡
285
+ '''
286
+ else:
287
+ outline = 'No successes yet.'
288
+
289
+ st.markdown("## 🏅 Scoreboard")
290
+ st.markdown(f"**Score:** {stars} ({score})")
291
+ st.markdown(outline)
292
+
293
+ # 🎮 Main Game Application
294
  def main():
295
  st.title("🐱 Cat Rider 🏇")
296
 
297
+ # 📜 Game Rules
298
+ st.markdown("""
299
+ ### 📜 Game Rules
300
+ | Step | Description |
301
+ |------|-------------|
302
+ | 1️⃣ | Choose your Cat Rider |
303
+ | 2️⃣ | Select your Riding Gear |
304
+ | 3️⃣ | Set off on an Adventure |
305
+ | 4️⃣ | Encounter Challenges and Make Decisions |
306
+ | 5️⃣ | Complete the Quest and Grow Stronger |
307
+ """)
308
+
309
+ # 🏁 Initialize game state
310
  if 'game_state' not in st.session_state:
311
  st.session_state.game_state = {
312
  'user_id': str(uuid.uuid4()),
 
323
  'succeeded': False
324
  }
325
 
326
+ # Sidebar functionality
327
+ st.sidebar.header("📂 Saved Histories")
328
+ history_files = load_saved_histories()
329
+ if history_files:
330
+ selected_history = st.sidebar.selectbox("Select a history to load:", history_files)
331
+ if st.sidebar.button("Load Selected History"):
332
+ with open(selected_history, 'r', encoding='utf-8') as f:
333
+ st.session_state.game_state['loaded_history'] = f.read()
334
+ st.sidebar.success(f"Loaded {selected_history}")
335
+
336
+ # 🐱 Cat Rider Selection
337
+ if st.session_state.game_state['cat_rider'] is None:
338
+ st.markdown("## Choose Your Cat Rider:")
339
+ cols = st.columns(len(CAT_RIDERS))
340
+ for i, rider in enumerate(CAT_RIDERS):
341
+ if cols[i].button(f"{rider['emoji']} {rider['name']} ({rider['type']})", key=f"rider_{i}"):
342
+ st.session_state.game_state['cat_rider'] = rider
343
+ st.session_state.game_state['rider_skill'] = rider['skill']
344
+ st.session_state.game_state['user_id'] = rider['name'] # Use rider name as user ID
345
+
346
+ # 🏇 Riding Gear Selection
347
+ if st.session_state.game_state['riding_gear'] is None and st.session_state.game_state['cat_rider'] is not None:
348
+ st.markdown("## Select Your Riding Gear:")
349
+ cols = st.columns(len(RIDING_GEAR))
350
+ for i, gear in enumerate(RIDING_GEAR):
351
+ if cols[i].button(f"{gear['name']} ({gear['type']})", key=f"gear_{i}"):
352
+ st.session_state.game_state['riding_gear'] = gear
353
+ st.session_state.game_state['gear_strength'] = gear['strength']
354
+
355
+ # 🎭 Game Loop
356
  game_state = st.session_state.game_state
357
 
358
+ if game_state['cat_rider'] is not None and game_state['riding_gear'] is not None:
359
+ # Check if current_situation is None or if the player succeeded in the previous situation
360
+ if game_state['current_situation'] is None or game_state['succeeded']:
361
+ # Generate a new situation
362
+ game_state['current_situation'] = generate_situation()
363
+ game_state['current_attempt'] = 1
364
+ game_state['succeeded'] = False
365
+ # Clear actions for new situation
366
+ game_state['actions'] = []
367
+
368
+ situation = game_state['current_situation']
369
+ st.markdown(f"## {situation['emoji']} Current Situation: {situation['name']} ({situation['type']})")
370
+ st.markdown(situation['description'])
371
+ st.markdown("### 🎭 Choose your action:")
372
+
373
+ # Generate actions if not already generated
374
+ if not game_state['actions']:
375
+ game_state['actions'] = generate_actions()
376
+
377
+ cols = st.columns(3)
378
+ action_chosen = False
379
+ for i, action in enumerate(game_state['actions']):
380
+ if cols[i].button(f"{action['emoji']} {action['name']} ({action['type']})", key=f"action_{i}_{game_state['current_attempt']}"):
381
+ outcome, success_chance = evaluate_action(situation, action, game_state['gear_strength'], game_state['rider_skill'], game_state['history'])
382
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
383
+
384
+ st.markdown(f"You decided to: **{action['name']}** ({action['type']})")
385
+ st.markdown(action['description'])
386
+ st.markdown(f"**Outcome:** {'✅ Success!' if outcome else '❌ Failure.'}")
387
+ st.markdown(f"**Success Chance:** {success_chance:.2f}%")
388
+
389
+ if outcome:
390
+ game_state['score'] += 1
391
+ game_state['succeeded'] = True
392
+ # Clear actions for next situation
393
+ game_state['actions'] = []
394
+ else:
395
+ game_state['current_attempt'] += 1
396
+ # Generate new actions for retry
397
+ game_state['actions'] = generate_actions()
398
+
399
+ # 🔄 Update game state
400
+ game_state = update_game_state(
401
+ game_state,
402
+ situation,
403
+ action,
404
+ outcome,
405
+ timestamp
406
+ )
407
+
408
+ # Display conclusion
409
+ conclusion = game_state['history_df'].iloc[-1]['conclusion']
410
+ st.markdown(f"**Encounter Conclusion:** {conclusion}")
411
+
412
+ # Display updated stats
413
+ st.markdown(f"**Updated Stats:**")
414
+ st.markdown(f"💪 Gear Strength: {game_state['gear_strength']:.2f}")
415
+ st.markdown(f"🏋️ Rider Skill: {game_state['rider_skill']:.2f}")
416
+
417
+ # 🏅 Display Scoreboard
418
+ display_scoreboard(game_state)
419
+
420
+ action_chosen = True
421
+ break # Exit the loop after action is taken
422
+
423
+ # If no action was chosen, show a message
424
+ if not action_chosen:
425
+ st.markdown("Please choose an action to proceed.")
426
+
427
+ # Integration point for both functions
428
+ if not game_state['history_df'].empty:
429
+ # 📝 Display Markdown Preview
430
+ st.markdown(create_markdown_preview(game_state['history_df']))
431
+
432
+ # 🌳 Display Knowledge Journey Graph
433
+ st.markdown("## 🌳 Your Journey (Knowledge Graph)")
434
+ nodes, edges = create_knowledge_graph(game_state['history_df'])
435
+ try:
436
+ streamlit_flow('cat_rider_flow',
437
+ nodes,
438
+ edges,
439
+ layout=TreeLayout(direction='down'),
440
+ fit_view=True,
441
+ height=600)
442
+ except Exception as e:
443
+ st.error(f"An error occurred while rendering the journey graph: {str(e)}")
444
+ st.markdown("Please try refreshing the page if the graph doesn't appear.")
445
+
446
+ # 📊 Character Stats Visualization
447
+ data = {"Stat": ["Gear Strength 🛡️", "Rider Skill 🏇"],
448
+ "Value": [game_state['gear_strength'], game_state['rider_skill']]}
449
+ df = pd.DataFrame(data)
450
+ fig = px.bar(df, x='Stat', y='Value', title="Cat Rider Stats 📊")
451
+ st.plotly_chart(fig)
452
+
453
+ # Save history to file
454
+ if st.button("💾 Save Game History"):
455
+ filename = save_history_to_file(game_state['history_df'], game_state['user_id'])
456
+ st.success(f"History saved to {filename}")
457
+ # Update history files list
458
+ history_files = load_saved_histories()
459
+
460
+ # Provide download buttons for saved histories
461
+ st.sidebar.markdown("### 📥 Download Histories")
462
+ for history_file in history_files:
463
+ with open(history_file, 'r', encoding='utf-8') as f:
464
+ st.sidebar.download_button(
465
+ label=f"Download {history_file}",
466
+ data=f.read(),
467
+ file_name=history_file,
468
+ mime='text/markdown'
469
+ )
470
 
471
  if __name__ == "__main__":
472
  main()