discordbot/cogs/games/basic_games.py
Slipstream 8a0232b842
Feat: Update word list to words_alpha.txt
Changed the default word list file from `words.txt` to `words_alpha.txt` for both Wordle and Hangman games. This ensures a more comprehensive and accurate word source for these games.
2025-05-28 12:36:03 -06:00

115 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import discord
import random
import asyncio
from typing import List
# Simple utility functions for basic games
def roll_dice() -> int:
"""Roll a dice and return a number between 1 and 6."""
return random.randint(1, 6)
def flip_coin() -> str:
"""Flip a coin and return 'Heads' or 'Tails'."""
return random.choice(["Heads", "Tails"])
def magic8ball_response() -> str:
"""Return a random Magic 8 Ball response."""
responses = [
"It is certain.", "It is decidedly so.", "Without a doubt.", "Yes definitely.", "You may rely on it.",
"As I see it, yes.", "Most likely.", "Outlook good.", "Yes.", "Signs point to yes.",
"Reply hazy, try again.", "Ask again later.", "Better not tell you now.", "Cannot predict now.", "Concentrate and ask again.",
"Don't count on it.", "My reply is no.", "My sources say no.", "Outlook not so good.", "Very doubtful."
]
return random.choice(responses)
async def play_hangman(bot, channel, user, words_file_path: str = "words_alpha.txt") -> None:
"""
Play a game of Hangman in the specified channel.
Args:
bot: The Discord bot instance
channel: The channel to play in
user: The user who initiated the game
words_file_path: Path to the file containing words for the game
"""
try:
with open(words_file_path, "r") as file:
words = [line.strip().lower() for line in file if line.strip() and len(line.strip()) > 3]
if not words:
await channel.send("Word list is empty or not found.")
return
word = random.choice(words)
except FileNotFoundError:
await channel.send(f"`{words_file_path}` not found. Cannot start Hangman.")
return
guessed = ["_"] * len(word)
attempts = 6
guessed_letters = set()
def format_hangman_message(attempts_left, current_guessed, letters_tried):
stages = [ # Hangman stages (simple text version)
"```\n +---+\n | |\n O |\n/|\\ |\n/ \\ |\n |\n=======\n```", # 0 attempts left
"```\n +---+\n | |\n O |\n/|\\ |\n/ |\n |\n=======\n```", # 1 attempt left
"```\n +---+\n | |\n O |\n/|\\ |\n |\n |\n=======\n```", # 2 attempts left
"```\n +---+\n | |\n O |\n/| |\n |\n |\n=======\n```", # 3 attempts left
"```\n +---+\n | |\n O |\n | |\n |\n |\n=======\n```", # 4 attempts left
"```\n +---+\n | |\n O |\n |\n |\n |\n=======\n```", # 5 attempts left
"```\n +---+\n | |\n |\n |\n |\n |\n=======\n```" # 6 attempts left
]
stage_index = max(0, min(attempts_left, 6)) # Clamp index
guessed_str = ' '.join(current_guessed)
tried_str = ', '.join(sorted(list(letters_tried))) if letters_tried else "None"
return f"{stages[stage_index]}\nWord: `{guessed_str}`\nAttempts left: {attempts_left}\nGuessed letters: {tried_str}\n\nGuess a letter!"
initial_msg_content = format_hangman_message(attempts, guessed, guessed_letters)
game_message = await channel.send(initial_msg_content)
def check(m):
# Check if message is from the original user, in the same channel, and is a single letter
return m.author == user and m.channel == channel and len(m.content) == 1 and m.content.isalpha()
while attempts > 0 and "_" in guessed:
try:
msg = await bot.wait_for("message", check=check, timeout=120.0) # 2 min timeout per guess
guess = msg.content.lower()
# Delete the user's guess message for cleaner chat
try:
await msg.delete()
except (discord.Forbidden, discord.NotFound):
pass # Ignore if delete fails
if guess in guessed_letters:
feedback = "You already guessed that letter!"
else:
guessed_letters.add(guess)
if guess in word:
feedback = "✅ Correct!"
for i, letter in enumerate(word):
if letter == guess:
guessed[i] = guess
else:
attempts -= 1
feedback = f"❌ Wrong!"
# Check for win/loss after processing guess
if "_" not in guessed:
final_message = f"🎉 You guessed the word: **{word}**!"
await game_message.edit(content=final_message)
return # End game on win
elif attempts == 0:
final_message = f"💀 You ran out of attempts! The word was **{word}**."
await game_message.edit(content=format_hangman_message(0, guessed, guessed_letters) + "\n" + final_message)
return # End game on loss
# Update the game message with new state and feedback
updated_content = format_hangman_message(attempts, guessed, guessed_letters) + f"\n({feedback})"
await game_message.edit(content=updated_content)
except asyncio.TimeoutError:
timeout_message = f"⏰ Time's up! The word was **{word}**."
await game_message.edit(content=format_hangman_message(attempts, guessed, guessed_letters) + "\n" + timeout_message)
return # End game on timeout