import gradio as gr
from src.game_logic import RPGGame
from src.database import interactions
def create_interface():
game = RPGGame()
with gr.Blocks(theme=gr.themes.Base()) as demo:
# Header with title and description
gr.Markdown(
"""
🎲 AI RPG Adventure
An interactive RPG experience from Pixeltable and powered by OpenAI! Get started with an example below.
"""
)
# Side-by-side accordions
with gr.Row():
with gr.Column():
with gr.Accordion("🎯 What does it do?", open=False):
gr.Markdown("""
This AI RPG Adventure demonstrates Pixeltable's capabilities:
- 🎮 Creates dynamic, AI-driven interactive stories
- 🔄 Maintains game state and history using Pixeltable tables
- 💭 Generates contextual options based on player actions
- 📝 Processes natural language inputs for custom actions
- 🤖 Uses LLMs to create engaging narratives
- 📊 Tracks and displays game progression
Perfect for understanding how Pixeltable can manage complex,
stateful applications with AI integration! ✨
""")
with gr.Column():
with gr.Accordion("🛠️ How does it work?", open=False):
gr.Markdown("""
The app leverages several Pixeltable features:
1. 📦 **Data Management**: Uses Pixeltable tables to store game state,
player actions, and AI responses
2. 🤖 **AI Integration**: Seamlessly connects with language models
for story generation and response processing
3. 🔄 **State Tracking**: Maintains session history and player
choices using Pixeltable's computed columns
4. ⚙️ **Custom Processing**: Uses Pixeltable UDFs to handle game
logic and AI prompt generation
5. 🎯 **Interactive Flow**: Processes player inputs and generates
contextual responses in real-time
""")
with gr.Row():
# Setup column
with gr.Column():
player_name = gr.Textbox(
label="👤 Your Character's Name",
placeholder="Enter your character's name..."
)
genre = gr.Dropdown(
choices=[
"🧙♂️ Fantasy",
"🚀 Sci-Fi",
"👻 Horror",
"🔍 Mystery",
"🌋 Post-Apocalyptic",
"🤖 Cyberpunk",
"⚙️ Steampunk"
],
label="🎭 Choose Your Genre"
)
scenario = gr.Textbox(
label="📖 Starting Scenario",
lines=3,
placeholder="Describe the initial setting and situation..."
)
start_button = gr.Button("🎮 Begin Adventure", variant="primary")
# Game interaction column
with gr.Column():
story_display = gr.Textbox(
label="📜 Story",
lines=8,
interactive=False
)
gr.Markdown("### 🎯 Choose Your Action")
with gr.Row():
with gr.Column():
action_input = gr.Radio(
choices=[],
label="🎲 Select an action or write your own below:",
interactive=True
)
custom_action = gr.Textbox(
label="✨ Custom Action",
placeholder="Write your own action here...",
lines=2
)
submit_action = gr.Button("⚡ Take Action", variant="secondary")
# History display
history_df = gr.Dataframe(
headers=["📅 Turn", "🎯 Player Action", "💬 Game Response"],
label="📚 Adventure History",
wrap=True,
row_count=5,
col_count=(3, "fixed")
)
def start_new_game(name, genre_choice, scenario_text):
if not name or not genre_choice or not scenario_text:
return "Please fill in all fields before starting.", [], "", []
try:
_, initial_response = game.start_game(name, genre_choice, scenario_text)
# Get options from the initial response
options = interactions.select(interactions.options).where(
(interactions.session_id == game.current_session_id) &
(interactions.turn_number == 0)
).collect()['options'][0]
# Get initial history
history_df = interactions.select(
turn=interactions.turn_number,
action=interactions.player_input,
response=interactions.story_text
).where(
interactions.session_id == game.current_session_id
).order_by(
interactions.turn_number
).collect().to_pandas()
history_data = [
[str(row['turn']), row['action'], row['response']]
for _, row in history_df.iterrows()
]
return initial_response, gr.Radio(choices=options, interactive=True), "", history_data
except Exception as e:
return f"Error starting game: {str(e)}", [], "", []
def process_player_action(action_choice, custom_action):
try:
# Use custom action if provided, otherwise use selected choice
action = custom_action if custom_action else action_choice
if not action:
return "Please either select an action or write your own.", [], "", []
response = game.process_action(action)
# Get new options
options = interactions.select(interactions.options).where(
(interactions.session_id == game.current_session_id) &
(interactions.turn_number == game.turn_number)
).collect()['options'][0]
# Get updated history
history_df = interactions.select(
turn=interactions.turn_number,
action=interactions.player_input,
response=interactions.story_text
).where(
interactions.session_id == game.current_session_id
).order_by(
interactions.turn_number
).collect().to_pandas()
history_data = [
[str(row['turn']), row['action'], row['response']]
for _, row in history_df.iterrows()
]
return response, gr.Radio(choices=options, interactive=True), "", history_data
except Exception as e:
return f"Error: {str(e)}", [], "", []
# Connect the start button
start_button.click(
start_new_game,
inputs=[player_name, genre, scenario],
outputs=[story_display, action_input, custom_action, history_df]
)
# Single action submit button
submit_action.click(
process_player_action,
inputs=[action_input, custom_action],
outputs=[story_display, action_input, custom_action, history_df]
)
# Example scenarios
gr.Markdown("### 💫 Example Adventures")
gr.Examples(
examples=[
["Eldric", "🧙♂️ Fantasy", "You find yourself in an ancient forest clearing, standing before a mysterious glowing portal. Your journey begins..."],
["Commander Nova", "🚀 Sci-Fi", "Aboard the starship Nebula, alarms blare as unknown entities approach. The fate of the crew rests in your hands..."],
["Detective Blake", "🔍 Mystery", "In the fog-shrouded streets of Victorian London, a peculiar letter arrives at your doorstep..."],
],
inputs=[player_name, genre, scenario]
)
# Footer with links
gr.HTML(
"""
🚀 Built with Pixeltable
AI Data infrastructure providing a declarative, incremental approach for multimodal workloads.
✨ © 2024 Pixeltable. This demo is open source and available on
Hugging Face Spaces 🚀
"""
)
return demo