Update app.py
Browse files
app.py
CHANGED
@@ -9,6 +9,7 @@ import getpass
|
|
9 |
import re
|
10 |
import random
|
11 |
import time
|
|
|
12 |
|
13 |
# Set up OpenAI API key
|
14 |
if 'OPENAI_API_KEY' not in os.environ:
|
@@ -161,7 +162,7 @@ interactions = pxt.create_table(
|
|
161 |
'timestamp': pxt.Timestamp,
|
162 |
'player_stats': pxt.String,
|
163 |
'random_event': pxt.String,
|
164 |
-
'use_fallback': pxt.Bool,
|
165 |
'fallback_story': pxt.String,
|
166 |
'fallback_stats': pxt.String,
|
167 |
'fallback_options': pxt.String
|
@@ -196,12 +197,17 @@ class RPGGame:
|
|
196 |
self.current_session_id = None
|
197 |
self.turn_number = 0
|
198 |
self.current_stats = ""
|
|
|
|
|
199 |
|
200 |
def start_game(self, player_name: str, genre: str, scenario: str) -> tuple[str, str, list[str]]:
|
201 |
session_id = f"session_{datetime.now().strftime('%Y%m%d%H%M%S')}_{player_name}"
|
202 |
self.current_session_id = session_id
|
203 |
self.turn_number = 0
|
204 |
|
|
|
|
|
|
|
205 |
# Get initial stats as a string
|
206 |
initial_stats = initialize_stats(genre)
|
207 |
self.current_stats = initial_stats
|
@@ -238,14 +244,37 @@ class RPGGame:
|
|
238 |
(interactions.turn_number == 0)
|
239 |
).collect()
|
240 |
|
241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
242 |
except Exception as e:
|
|
|
243 |
# If OpenAI fails, use the fallback values
|
244 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
except Exception as e:
|
|
|
247 |
# If everything fails, return fallback
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
|
250 |
def process_action(self, action: str) -> tuple[str, str, list[str]]:
|
251 |
if not self.current_session_id:
|
@@ -280,8 +309,9 @@ class RPGGame:
|
|
280 |
]
|
281 |
random_event_val = random.choice(events)
|
282 |
|
|
|
283 |
if random_event_val:
|
284 |
-
|
285 |
|
286 |
# Create fallback content
|
287 |
fallback = create_fallback_response(action, self.turn_number)
|
@@ -292,7 +322,7 @@ class RPGGame:
|
|
292 |
'genre': prev_turn['genre'][0],
|
293 |
'initial_scenario': prev_turn['initial_scenario'][0],
|
294 |
'turn_number': self.turn_number,
|
295 |
-
'player_input':
|
296 |
'timestamp': datetime.now(),
|
297 |
'player_stats': self.current_stats,
|
298 |
'random_event': random_event_val,
|
@@ -313,17 +343,44 @@ class RPGGame:
|
|
313 |
).collect()
|
314 |
|
315 |
# Update stats for next turn
|
316 |
-
|
|
|
|
|
|
|
|
|
317 |
|
318 |
-
|
|
|
|
|
|
|
319 |
except Exception as e:
|
|
|
320 |
# If OpenAI fails, use the fallback values
|
321 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
322 |
|
323 |
except Exception as e:
|
|
|
324 |
# If everything fails, use fallback
|
325 |
fallback = create_fallback_response(action, self.turn_number)
|
326 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
|
328 |
def create_interface():
|
329 |
game = RPGGame()
|
@@ -482,12 +539,12 @@ def create_interface():
|
|
482 |
gr.Examples(
|
483 |
examples=[
|
484 |
["Admiral Yi", "π§ββοΈ Fantasy", "You wake up at the edge of a forgotten mystical forest. In the distance, you can see castle spires, and in your mind remains only the clue about ancient magic threatening the kingdom. Suddenly, you see a strange light coming from the forest..."],
|
485 |
-
["
|
486 |
["Elon Musk", "π€ Cyberpunk", "Seoul, 2077. You are the CEO of Neural Link Industries. Your latest brain-computer interface technology has started giving users an unexpected ability - they can communicate with their houseplants. As you prepare for a major investor presentation, your AI assistant reports that test participants are organizing a mysterious 'plant revolution'..."],
|
487 |
["Gordon Ramsay", "π Post-Apocalyptic", "You are the last master chef in New Seoul, running an underground restaurant in the ruins of an old luxury hotel. Your signature dish requires a rare mushroom that only grows in dangerous radioactive zones. While preparing for tonight's secret gathering, your scout returns with ominous news about rival chef gangs in the area..."],
|
488 |
-
["
|
489 |
-
["
|
490 |
-
["
|
491 |
],
|
492 |
inputs=[player_name, genre, scenario]
|
493 |
)
|
@@ -513,30 +570,15 @@ def create_interface():
|
|
513 |
try:
|
514 |
initial_story, initial_stats, initial_options = game.start_game(name, genre_choice, scenario_text)
|
515 |
|
516 |
-
#
|
517 |
-
|
518 |
-
history_df = interactions.select(
|
519 |
-
turn=interactions.turn_number,
|
520 |
-
action=interactions.player_input,
|
521 |
-
response=interactions.story_text
|
522 |
-
).where(
|
523 |
-
(interactions.session_id == game.current_session_id)
|
524 |
-
).order_by(
|
525 |
-
interactions.turn_number
|
526 |
-
).collect().to_pandas()
|
527 |
-
|
528 |
-
history_data = [
|
529 |
-
[str(row['turn']), row['action'], row['response']]
|
530 |
-
for _, row in history_df.iterrows()
|
531 |
-
]
|
532 |
-
except Exception as e:
|
533 |
-
history_data = [["0", "Game starts", initial_story]]
|
534 |
|
535 |
story_html = f"<div class='story-container'>{initial_story}</div>"
|
536 |
stats_html = f"<div class='stats-container'><h3>π Character Status</h3>{initial_stats}</div>"
|
537 |
|
538 |
return story_html, stats_html, gr.Radio(choices=initial_options, interactive=True), history_data
|
539 |
except Exception as e:
|
|
|
540 |
# Handle any other unexpected errors
|
541 |
fallback = create_fallback_response("Game starts", 0)
|
542 |
return (
|
@@ -558,31 +600,15 @@ def create_interface():
|
|
558 |
|
559 |
story, stats, options = game.process_action(action_choice)
|
560 |
|
561 |
-
#
|
562 |
-
|
563 |
-
history_df = interactions.select(
|
564 |
-
turn=interactions.turn_number,
|
565 |
-
action=interactions.player_input,
|
566 |
-
response=interactions.story_text
|
567 |
-
).where(
|
568 |
-
(interactions.session_id == game.current_session_id)
|
569 |
-
).order_by(
|
570 |
-
interactions.turn_number
|
571 |
-
).collect().to_pandas()
|
572 |
-
|
573 |
-
history_data = [
|
574 |
-
[str(row['turn']), row['action'], row['response']]
|
575 |
-
for _, row in history_df.iterrows()
|
576 |
-
]
|
577 |
-
except Exception as e:
|
578 |
-
# If history retrieval fails, create minimal history
|
579 |
-
history_data = [[str(game.turn_number), action_choice, story]]
|
580 |
|
581 |
story_html = f"<div class='story-container'>{story}</div>"
|
582 |
stats_html = f"<div class='stats-container'><h3>π Character Status</h3>{stats}</div>"
|
583 |
|
584 |
return story_html, stats_html, gr.Radio(choices=options, interactive=True), history_data
|
585 |
except Exception as e:
|
|
|
586 |
# Handle any other unexpected errors
|
587 |
fallback = create_fallback_response(action_choice, 1)
|
588 |
return (
|
|
|
9 |
import re
|
10 |
import random
|
11 |
import time
|
12 |
+
import pandas as pd
|
13 |
|
14 |
# Set up OpenAI API key
|
15 |
if 'OPENAI_API_KEY' not in os.environ:
|
|
|
162 |
'timestamp': pxt.Timestamp,
|
163 |
'player_stats': pxt.String,
|
164 |
'random_event': pxt.String,
|
165 |
+
'use_fallback': pxt.Bool,
|
166 |
'fallback_story': pxt.String,
|
167 |
'fallback_stats': pxt.String,
|
168 |
'fallback_options': pxt.String
|
|
|
197 |
self.current_session_id = None
|
198 |
self.turn_number = 0
|
199 |
self.current_stats = ""
|
200 |
+
# Add game_history to track history directly in memory
|
201 |
+
self.game_history = []
|
202 |
|
203 |
def start_game(self, player_name: str, genre: str, scenario: str) -> tuple[str, str, list[str]]:
|
204 |
session_id = f"session_{datetime.now().strftime('%Y%m%d%H%M%S')}_{player_name}"
|
205 |
self.current_session_id = session_id
|
206 |
self.turn_number = 0
|
207 |
|
208 |
+
# Reset history for new game
|
209 |
+
self.game_history = []
|
210 |
+
|
211 |
# Get initial stats as a string
|
212 |
initial_stats = initialize_stats(genre)
|
213 |
self.current_stats = initial_stats
|
|
|
244 |
(interactions.turn_number == 0)
|
245 |
).collect()
|
246 |
|
247 |
+
story = result['story_text'][0]
|
248 |
+
stats = result['stats_update'][0]
|
249 |
+
options = result['options'][0]
|
250 |
+
|
251 |
+
# Add to our internal history
|
252 |
+
self.game_history.append(["0", "Game starts", story])
|
253 |
+
|
254 |
+
return story, stats, options
|
255 |
except Exception as e:
|
256 |
+
print(f"Error getting initial response: {str(e)}")
|
257 |
# If OpenAI fails, use the fallback values
|
258 |
+
story = fallback["story"]
|
259 |
+
stats = fallback["stats"]
|
260 |
+
options = fallback["options"]
|
261 |
+
|
262 |
+
# Still add to history even if using fallback
|
263 |
+
self.game_history.append(["0", "Game starts", story])
|
264 |
+
|
265 |
+
return story, stats, options
|
266 |
|
267 |
except Exception as e:
|
268 |
+
print(f"Error inserting initial turn: {str(e)}")
|
269 |
# If everything fails, return fallback
|
270 |
+
story = fallback["story"]
|
271 |
+
stats = fallback["stats"]
|
272 |
+
options = fallback["options"]
|
273 |
+
|
274 |
+
# Still add to history even if using fallback
|
275 |
+
self.game_history.append(["0", "Game starts", story])
|
276 |
+
|
277 |
+
return story, stats, options
|
278 |
|
279 |
def process_action(self, action: str) -> tuple[str, str, list[str]]:
|
280 |
if not self.current_session_id:
|
|
|
309 |
]
|
310 |
random_event_val = random.choice(events)
|
311 |
|
312 |
+
modified_action = action
|
313 |
if random_event_val:
|
314 |
+
modified_action = f"{action} ({random_event_val})"
|
315 |
|
316 |
# Create fallback content
|
317 |
fallback = create_fallback_response(action, self.turn_number)
|
|
|
322 |
'genre': prev_turn['genre'][0],
|
323 |
'initial_scenario': prev_turn['initial_scenario'][0],
|
324 |
'turn_number': self.turn_number,
|
325 |
+
'player_input': modified_action,
|
326 |
'timestamp': datetime.now(),
|
327 |
'player_stats': self.current_stats,
|
328 |
'random_event': random_event_val,
|
|
|
343 |
).collect()
|
344 |
|
345 |
# Update stats for next turn
|
346 |
+
story = result['story_text'][0]
|
347 |
+
stats = result['stats_update'][0]
|
348 |
+
options = result['options'][0]
|
349 |
+
|
350 |
+
self.current_stats = stats
|
351 |
|
352 |
+
# Add to our internal history
|
353 |
+
self.game_history.append([str(self.turn_number), modified_action, story])
|
354 |
+
|
355 |
+
return story, stats, options
|
356 |
except Exception as e:
|
357 |
+
print(f"Error getting turn response: {str(e)}")
|
358 |
# If OpenAI fails, use the fallback values
|
359 |
+
story = fallback["story"]
|
360 |
+
stats = fallback["stats"]
|
361 |
+
options = fallback["options"]
|
362 |
+
|
363 |
+
# Add to our internal history even with fallback
|
364 |
+
self.game_history.append([str(self.turn_number), modified_action, story])
|
365 |
+
|
366 |
+
return story, stats, options
|
367 |
|
368 |
except Exception as e:
|
369 |
+
print(f"Error processing action: {str(e)}")
|
370 |
# If everything fails, use fallback
|
371 |
fallback = create_fallback_response(action, self.turn_number)
|
372 |
+
story = fallback["story"]
|
373 |
+
stats = fallback["stats"]
|
374 |
+
options = fallback["options"]
|
375 |
+
|
376 |
+
# Add to our internal history even with fallback
|
377 |
+
self.game_history.append([str(self.turn_number), action, story])
|
378 |
+
|
379 |
+
return story, stats, options
|
380 |
+
|
381 |
+
def get_history(self):
|
382 |
+
"""Return the game history from memory instead of querying the database"""
|
383 |
+
return self.game_history
|
384 |
|
385 |
def create_interface():
|
386 |
game = RPGGame()
|
|
|
539 |
gr.Examples(
|
540 |
examples=[
|
541 |
["Admiral Yi", "π§ββοΈ Fantasy", "You wake up at the edge of a forgotten mystical forest. In the distance, you can see castle spires, and in your mind remains only the clue about ancient magic threatening the kingdom. Suddenly, you see a strange light coming from the forest..."],
|
542 |
+
["Ji-Young Kim", "π Sci-Fi", "As the navigator of the starship 'Horizon', you wake up to an emergency alarm during the exploration of an unknown planet. Contact with the captain has been lost, and life support systems are gradually failing. You hear strange footsteps in the quiet ship..."],
|
543 |
["Elon Musk", "π€ Cyberpunk", "Seoul, 2077. You are the CEO of Neural Link Industries. Your latest brain-computer interface technology has started giving users an unexpected ability - they can communicate with their houseplants. As you prepare for a major investor presentation, your AI assistant reports that test participants are organizing a mysterious 'plant revolution'..."],
|
544 |
["Gordon Ramsay", "π Post-Apocalyptic", "You are the last master chef in New Seoul, running an underground restaurant in the ruins of an old luxury hotel. Your signature dish requires a rare mushroom that only grows in dangerous radioactive zones. While preparing for tonight's secret gathering, your scout returns with ominous news about rival chef gangs in the area..."],
|
545 |
+
["Jung-Ho Yoo", "π» Horror", "You came to a secluded cabin in the forest for the weekend at your friend's invitation. On the first night, you are drawn into the forest by a strange light visible through the window. As you try to find your way back, you can't see the cabin, and unfamiliar fog grows thicker. In the distance, you hear someoneβno, something calling you..."],
|
546 |
+
["Detective Park", "π Mystery", "As a rookie detective, your first case is the mysterious disappearance of the CEO of the city's top tech company. There's no blood in his office, and the only clues are an encrypted note on the desk and his powered-down cutting-edge AI assistant. As you begin your investigation, you hear about a secret project the CEO was working on..."],
|
547 |
+
["Min-Su Lee", "βοΈ Steampunk", "In New Joseon, filled with steam and gears, you are an innovative airship designer. During a demonstration of your latest invention, a government secret agent approaches with a secret mission for the imperial family in danger. Underground groups are threatening the throne, and your invention is the royal family's only hope..."]
|
548 |
],
|
549 |
inputs=[player_name, genre, scenario]
|
550 |
)
|
|
|
570 |
try:
|
571 |
initial_story, initial_stats, initial_options = game.start_game(name, genre_choice, scenario_text)
|
572 |
|
573 |
+
# Get history from our in-memory tracking
|
574 |
+
history_data = game.get_history()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
575 |
|
576 |
story_html = f"<div class='story-container'>{initial_story}</div>"
|
577 |
stats_html = f"<div class='stats-container'><h3>π Character Status</h3>{initial_stats}</div>"
|
578 |
|
579 |
return story_html, stats_html, gr.Radio(choices=initial_options, interactive=True), history_data
|
580 |
except Exception as e:
|
581 |
+
print(f"Error in start_new_game: {str(e)}")
|
582 |
# Handle any other unexpected errors
|
583 |
fallback = create_fallback_response("Game starts", 0)
|
584 |
return (
|
|
|
600 |
|
601 |
story, stats, options = game.process_action(action_choice)
|
602 |
|
603 |
+
# Get history from our in-memory tracking
|
604 |
+
history_data = game.get_history()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
605 |
|
606 |
story_html = f"<div class='story-container'>{story}</div>"
|
607 |
stats_html = f"<div class='stats-container'><h3>π Character Status</h3>{stats}</div>"
|
608 |
|
609 |
return story_html, stats_html, gr.Radio(choices=options, interactive=True), history_data
|
610 |
except Exception as e:
|
611 |
+
print(f"Error in process_player_action: {str(e)}")
|
612 |
# Handle any other unexpected errors
|
613 |
fallback = create_fallback_response(action_choice, 1)
|
614 |
return (
|