mirror of
https://github.com/TheCommsChannel/TC2-BBS-mesh.git
synced 2025-08-06 05:34:26 -04:00
Fixed an issue with Game Over states not being correctly detected/handled.
This commit is contained in:
parent
34704013bd
commit
dfeea2d36f
3 changed files with 53 additions and 51 deletions
|
@ -701,40 +701,34 @@ def get_games_available(game_files):
|
||||||
|
|
||||||
def handle_games_command(sender_id, interface):
|
def handle_games_command(sender_id, interface):
|
||||||
"""Handles the Games Menu and lists available text-based games."""
|
"""Handles the Games Menu and lists available text-based games."""
|
||||||
|
|
||||||
# Find files in ./games that:
|
|
||||||
# - Have a .txt or .csv extension
|
|
||||||
# - OR have no extension
|
|
||||||
game_files = [
|
game_files = [
|
||||||
f for f in os.listdir('./games')
|
f for f in os.listdir('./games')
|
||||||
if os.path.isfile(os.path.join('./games', f)) and (f.endswith('.txt') or f.endswith('.csv') or '.' not in f)
|
if os.path.isfile(os.path.join('./games', f)) and (f.endswith('.txt') or f.endswith('.csv') or '.' not in f)
|
||||||
]
|
]
|
||||||
|
|
||||||
games_available = get_games_available(game_files)
|
games_available = get_games_available(game_files)
|
||||||
|
|
||||||
if not games_available:
|
if not games_available:
|
||||||
send_message("No games available yet. Come back soon.", sender_id, interface)
|
send_message("No games available yet. Come back soon.", sender_id, interface)
|
||||||
update_user_state(sender_id, {'command': 'UTILITIES', 'step': 1})
|
update_user_state(sender_id, {'command': 'UTILITIES', 'step': 1})
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Store game filenames in state to avoid title-related issues
|
|
||||||
game_titles = list(games_available.keys()) # Display titles
|
game_titles = list(games_available.keys()) # Display titles
|
||||||
game_filenames = list(games_available.values()) # Actual filenames
|
game_filenames = list(games_available.values()) # Actual filenames
|
||||||
|
|
||||||
# Include exit option
|
|
||||||
numbered_games = "\n".join(f"{i+1}. {title}" for i, title in enumerate(game_titles))
|
numbered_games = "\n".join(f"{i+1}. {title}" for i, title in enumerate(game_titles))
|
||||||
numbered_games += "\n[X] Exit"
|
numbered_games += "\n[X] Exit"
|
||||||
|
|
||||||
response = f"🎮 Games Menu 🎮\nWhich game would you like to play?\n{numbered_games}"
|
response = f"🎮 Games Menu 🎮\nWhich game would you like to play?\n{numbered_games}"
|
||||||
send_message(response, sender_id, interface)
|
send_message(response, sender_id, interface)
|
||||||
|
|
||||||
|
# ✅ Ensure `games` state is always reset when displaying the menu
|
||||||
update_user_state(sender_id, {'command': 'GAMES', 'step': 1, 'games': game_filenames, 'titles': game_titles})
|
update_user_state(sender_id, {'command': 'GAMES', 'step': 1, 'games': game_filenames, 'titles': game_titles})
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def handle_game_menu_selection(sender_id, message, step, interface, state):
|
def handle_game_menu_selection(sender_id, message, step, interface, state):
|
||||||
"""Handles the user's selection of a game from the Games Menu, allowing exit with 'X' and starting immediately."""
|
"""Handles the user's selection of a game from the Games Menu, allowing exit with 'X' and starting immediately."""
|
||||||
|
|
||||||
|
@ -750,6 +744,9 @@ def handle_game_menu_selection(sender_id, message, step, interface, state):
|
||||||
if 0 <= game_index < len(games_available):
|
if 0 <= game_index < len(games_available):
|
||||||
selected_game = games_available[game_index]
|
selected_game = games_available[game_index]
|
||||||
|
|
||||||
|
# Reset user state to ensure a clean start
|
||||||
|
update_user_state(sender_id, None)
|
||||||
|
|
||||||
# Update state to indicate the user is now in-game
|
# Update state to indicate the user is now in-game
|
||||||
update_user_state(sender_id, {'command': 'IN_GAME', 'step': 3, 'game': selected_game})
|
update_user_state(sender_id, {'command': 'IN_GAME', 'step': 3, 'game': selected_game})
|
||||||
|
|
||||||
|
@ -761,6 +758,7 @@ def handle_game_menu_selection(sender_id, message, step, interface, state):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
send_message("Invalid input. Please enter a number corresponding to a game or 'X' to exit.", sender_id, interface)
|
send_message("Invalid input. Please enter a number corresponding to a game or 'X' to exit.", sender_id, interface)
|
||||||
|
|
||||||
|
|
||||||
def start_selected_game(sender_id, interface, state):
|
def start_selected_game(sender_id, interface, state):
|
||||||
"""Starts the game selected by the user and ensures title detection."""
|
"""Starts the game selected by the user and ensures title detection."""
|
||||||
|
|
||||||
|
@ -844,24 +842,37 @@ def load_game_map(file_path):
|
||||||
print(f"❌ ERROR inside load_game_map(): {e}")
|
print(f"❌ ERROR inside load_game_map(): {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def present_story_segment(sender_id, interface, state):
|
def present_story_segment(sender_id, interface, state):
|
||||||
"""Presents the current segment of the game and available choices."""
|
"""Presents the current segment of the game and available choices."""
|
||||||
|
|
||||||
game_name = state.get('game')
|
game_name = state.get('game')
|
||||||
game_title = state.get('game_title', "Unknown Game") # ✅ Prevent KeyError
|
game_title = state.get('game_title', "Unknown Game")
|
||||||
game_map = state.get('game_map', {})
|
game_map = state.get('game_map', {})
|
||||||
game_position = state.get('game_position', 1)
|
game_position = state.get('game_position', 1)
|
||||||
|
|
||||||
if game_position not in game_map:
|
if game_position not in game_map:
|
||||||
send_message("Error: Invalid game state.", sender_id, interface)
|
send_message("Error: Invalid game state.", sender_id, interface)
|
||||||
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
||||||
|
handle_games_command(sender_id, interface)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Retrieve the current story segment
|
# Retrieve the current story segment
|
||||||
segment = game_map[game_position]
|
segment = game_map[game_position]
|
||||||
storyline = segment[0]
|
storyline = segment[0]
|
||||||
choices = segment[1:]
|
choices = segment[1:] # Extract choices
|
||||||
|
|
||||||
|
# 🛠️ **Check if this is a game-over state (no choices)**
|
||||||
|
if not choices:
|
||||||
|
send_message(f"🎮 {game_title} 🎮\n\n{storyline}\n\n💀 GAME OVER! Returning to the game menu...", sender_id, interface)
|
||||||
|
|
||||||
|
# Reset user state before returning to menu
|
||||||
|
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
||||||
|
|
||||||
|
import time
|
||||||
|
time.sleep(1) # Ensure the message is processed before switching menus
|
||||||
|
|
||||||
|
handle_games_command(sender_id, interface)
|
||||||
|
return
|
||||||
|
|
||||||
# Build response message
|
# Build response message
|
||||||
response = f"🎮 {game_title} 🎮\n\n{storyline}\n\n"
|
response = f"🎮 {game_title} 🎮\n\n{storyline}\n\n"
|
||||||
|
@ -872,16 +883,17 @@ def present_story_segment(sender_id, interface, state):
|
||||||
|
|
||||||
send_message(response, sender_id, interface)
|
send_message(response, sender_id, interface)
|
||||||
|
|
||||||
# Update user state to track the current game progress
|
# Ensure user state is properly tracked
|
||||||
update_user_state(sender_id, {
|
update_user_state(sender_id, {
|
||||||
'command': 'IN_GAME',
|
'command': 'IN_GAME',
|
||||||
'step': 3,
|
'step': 3,
|
||||||
'game': game_name,
|
'game': game_name,
|
||||||
'game_title': game_title, # ✅ Ensure it stays in state
|
'game_title': game_title,
|
||||||
'game_map': game_map,
|
'game_map': game_map,
|
||||||
'game_position': game_position
|
'game_position': game_position
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def process_game_choice(sender_id, message, interface, state):
|
def process_game_choice(sender_id, message, interface, state):
|
||||||
"""Processes the player's choice and advances the game."""
|
"""Processes the player's choice and advances the game."""
|
||||||
|
|
||||||
|
@ -891,65 +903,50 @@ def process_game_choice(sender_id, message, interface, state):
|
||||||
if game_position not in game_map:
|
if game_position not in game_map:
|
||||||
send_message("Error: Invalid game state.", sender_id, interface)
|
send_message("Error: Invalid game state.", sender_id, interface)
|
||||||
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
||||||
|
handle_games_command(sender_id, interface)
|
||||||
return
|
return
|
||||||
|
|
||||||
segment = game_map[game_position]
|
segment = game_map[game_position]
|
||||||
|
|
||||||
# Extract the storyline and choices
|
# Extract the storyline and choices
|
||||||
storyline = segment[0] # First element is the story text
|
storyline = segment[0]
|
||||||
choices = segment[1:] # Remaining elements are choices
|
choices = segment[1:]
|
||||||
|
|
||||||
# Ensure choices are properly formatted (must be in pairs)
|
# Ensure choices are properly formatted
|
||||||
if len(choices) % 2 != 0:
|
if len(choices) % 2 != 0:
|
||||||
send_message("Error: Game data is corrupted.", sender_id, interface)
|
send_message("Error: Game data is corrupted.", sender_id, interface)
|
||||||
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
||||||
|
handle_games_command(sender_id, interface)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle Exit
|
# Handle Exit
|
||||||
if message.lower() == "x":
|
if message.lower() == "x":
|
||||||
send_message(f"Exiting '{state['game_title']}'... Returning to Games Menu.", sender_id, interface)
|
send_message(f"Exiting '{state['game_title']}'... Returning to Games Menu.", sender_id, interface)
|
||||||
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
||||||
handle_games_command(sender_id, interface) # Immediately display the game menu
|
handle_games_command(sender_id, interface)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Convert user input to index (1-based to 0-based)
|
|
||||||
choice_index = int(message) - 1
|
choice_index = int(message) - 1
|
||||||
|
|
||||||
# Validate choice selection
|
|
||||||
if choice_index < 0 or choice_index * 2 + 1 >= len(choices):
|
if choice_index < 0 or choice_index * 2 + 1 >= len(choices):
|
||||||
send_message("Invalid selection. Please enter a valid number.", sender_id, interface)
|
send_message("Invalid selection. Please enter a valid number.", sender_id, interface)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Retrieve the target position for the chosen option
|
|
||||||
target_position = int(choices[choice_index * 2 + 1])
|
target_position = int(choices[choice_index * 2 + 1])
|
||||||
|
|
||||||
# Check if the target position exists
|
|
||||||
if target_position not in game_map:
|
if target_position not in game_map:
|
||||||
send_message("💀 Game Over! You fell into an abyss. 💀", sender_id, interface)
|
send_message("💀 GAME OVER! No further choices available. 💀 Returning to the game menu...", sender_id, interface)
|
||||||
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
update_user_state(sender_id, {'command': 'GAMES', 'step': 1})
|
||||||
handle_games_command(sender_id, interface) # Return to game menu
|
handle_games_command(sender_id, interface)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Update state with the new game position
|
# ✅ FIX: Pass `state` instead of `update_user_state`
|
||||||
update_user_state(sender_id, {
|
state['game_position'] = target_position
|
||||||
'command': 'IN_GAME',
|
update_user_state(sender_id, state)
|
||||||
'step': 3,
|
|
||||||
'game': state['game'],
|
|
||||||
'game_title': state['game_title'],
|
|
||||||
'game_map': game_map,
|
|
||||||
'game_position': target_position
|
|
||||||
})
|
|
||||||
|
|
||||||
# Present the new story segment
|
# ✅ FIX: Pass the correct `state` variable, NOT `update_user_state`
|
||||||
present_story_segment(sender_id, interface, {
|
present_story_segment(sender_id, interface, state)
|
||||||
'command': 'IN_GAME',
|
|
||||||
'step': 3,
|
|
||||||
'game': state['game'],
|
|
||||||
'game_title': state['game_title'],
|
|
||||||
'game_map': game_map,
|
|
||||||
'game_position': target_position
|
|
||||||
})
|
|
||||||
|
|
||||||
except (ValueError, IndexError):
|
except ValueError:
|
||||||
send_message("Invalid selection. Please enter a valid number.", sender_id, interface)
|
send_message("Invalid input. Please enter a valid number.", sender_id, interface)
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
What is your first choice?, East, 2, West, 3, North, 4, South, 5
|
|
||||||
You chose East. A dense forest appears., Run forward, 6, Look around, 7
|
|
||||||
You chose West. A river blocks your path., Try to swim, 8, Walk along the bank, 9
|
|
||||||
You chose North. The path is blocked by rocks.
|
|
||||||
You chose South. A cave entrance looms ahead., Enter the cave, 10, Turn back, 11
|
|
||||||
You went East and chose to run. The ground gives way and you fall. GAME OVER.
|
|
||||||
You went East and looked around. You see a hidden path., Follow it, 12, Stay put, 13
|
|
12
games/the_shortest_game.csv
Normal file
12
games/the_shortest_game.csv
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
title="The Shortest Game"
|
||||||
|
You awaken at a crossroads. Which way will you go?, North, 2, East, 3, South, 4, West, 5
|
||||||
|
You chose north. There was a cottage. Will you:, Explore it, 6, Keep going, 7
|
||||||
|
You chose East. The way is dark. What will you do?, Keep going, 8, Light a fire, 9
|
||||||
|
You chose South. You walked for a mile and found nothing.
|
||||||
|
You chose West. There is a man on the path., Ignore him, 10, Talk to him, 11
|
||||||
|
You fell through the floor of the cottage.
|
||||||
|
Just beyond the cottage you see a village full of people. They seem to recognize you. You make this your new home.
|
||||||
|
You are brave. After a short walk through the dark forest you find a clearing you recognize. You know the way home.
|
||||||
|
Marauders spot your fire in the night. You don't wake again.
|
||||||
|
The man snickers as you pass. Later down the trail you are robbed.
|
||||||
|
The man tells you where you are and how to get back home.
|
Can't render this file because it contains an unexpected character in line 1 and column 7.
|
Loading…
Add table
Add a link
Reference in a new issue