Files
meshing-around/modules/games/hangman.py
2025-12-27 19:39:34 -08:00

227 lines
12 KiB
Python

# Written for Meshtastic mesh-bot by ZR1RF Johannes le Roux 2025
from modules.log import logger, getPrettyTime
import os
import json
import random
from modules.settings import hangmanTracker
class Hangman:
WORDS = [
"ability","able","about","above","accept","according","account","across",
"act","action","activity","actually","add","address","administration","admit",
"adult","affect","after","again","against","age","agency","agent","ago",
"agree","agreement","ahead","air","all","allow","almost","alone","along",
"already","also","although","always","American","among","amount","analysis",
"and","animal","another","answer","any","anyone","anything","appear","apply",
"approach","area","argue","arm","around","arrive","art","article","artist",
"as","ask","assume","at","attack","attention","attorney","audience","author",
"authority","available","avoid","away","baby","back","bad","bag","ball",
"bank","bar","base","be","beat","beautiful","because","become","bed","before",
"begin","behavior","behind","believe","benefit","best","better","between",
"beyond","big","bill","billion","bit","black","blood","blue","board","body",
"book","born","both","box","boy","break","bring","brother","budget","build",
"building","business","but","buy","by","call","camera","campaign","can",
"cancer","candidate","capital","car","card","care","career","carry","case",
"catch","cause","cell","center","central","century","certain","certainly",
"chair","challenge","chance","change","character","charge","check","child",
"choice","choose","church","citizen","city","civil","claim","class","clear",
"clearly","close","coach","cold","collection","college","color","come",
"commercial","common","community","company","compare","computer","concern",
"condition","conference","Congress","consider","consumer","contain","continue",
"control","cost","could","country","couple","course","court","cover","create",
"crime","cultural","culture","cup","current","customer","cut","dark","data",
"daughter","day","dead","deal","death","debate","decade","decide","decision",
"deep","defense","degree","democrat","democratic","describe","design",
"despite","detail","determine","develop","development","die","difference",
"different","difficult","dinner","direction","director","discover","discuss",
"discussion","disease","do","doctor","dog","door","down","draw","dream","drive",
"drop","drug","during","each","early","east","easy","eat","economic","economy",
"edge","education","effect","effort","eight","either","election","else",
"employee","end","energy","enjoy","enough","enter","entire","environment",
"environmental","especially","establish","even","evening","event","ever",
"every","everybody","everyone","everything","evidence","exactly","example",
"executive","exist","expect","experience","expert","explain","eye","face",
"fact","factor","fail","fall","family","far","fast","father","fear","federal",
"feel","feeling","few","field","fight","figure","fill","film","final","finally",
"financial","find","fine","finger","finish","fire","firm","first","fish","five",
"floor","fly","focus","follow","food","foot","for","force","foreign","forget",
"form","former","forward","four","free","friend","from","front","full","fund",
"future","game","garden","gas","general","generation","get","girl","give",
"glass","go","goal","good","government","great","green","ground","group","grow",
"growth","guess","gun","guy","hair","half","hand","hang","happen","happy",
"hard","have","he","head","health","hear","heart","heat","heavy","help","her",
"here","herself","high","him","himself","his","history","hit","hold","home",
"hope","hospital","hot","hotel","hour","house","how","however","huge","human",
"hundred","husband","I","idea","identify","if","image","imagine","impact",
"important","improve","in","include","including","increase","indeed","indicate",
"individual","industry","information","inside","instead","institution","interest",
"interesting","international","interview","into","investment","involve","issue",
"it","item","its","itself","job","join","just","keep","key","kid","kill","kind",
"kitchen","know","knowledge","land","language","large","last","late","later",
"laugh","law","lawyer","lay","lead","leader","learn","least","leave","left",
"leg","legal","less","let","letter","level","lie","life","light","like","likely",
"line","list","listen","little","live","local","long","look","lose","loss",
"lot","love","low","machine","magazine","main","maintain","major","majority",
"make","man","manage","management","manager","many","market","marriage",
"material","matter","may","maybe","me","mean","measure","media","medical","meet",
"meeting","member","memory","mention","message","method","middle","might",
"military","million","mind","minute","miss","mission","model","modern","moment",
"money","month","more","morning","most","mother","mouth","move","movement",
"movie","Mr","Mrs","much","music","must","my","myself","name","nation",
"national","natural","nature","near","nearly","necessary","need","network",
"never","new","news","newspaper","next","nice","night","no","none","nor",
"north","not","note","nothing","notice","now","number","occur","of","off",
"offer","office","officer","official","often","oh","oil","ok","old","on",
"once","one","only","onto","open","operation","opportunity","option","or",
"order","organization","other","others","our","out","outside","over","own",
"owner","page","pain","painting","paper","parent","part","participant",
"particular","particularly","partner","party","pass","past","patient","pattern",
"pay","peace","people","per","perform","performance","perhaps","period",
"person","personal","phone","physical","pick","picture","piece","place","plan",
"plant","play","player","point","police","policy","political","politics",
"poor","popular","population","position","positive","possible","power",
"practice","prepare","present","president","pressure","pretty","prevent","price",
"private","probably","problem","process","produce","product","production",
"professional","professor","program","project","property","protect","prove",
"provide","public","pull","purpose","push","put","quality","question","quickly",
"quite","race","radio","raise","range","rate","rather","reach","read","ready",
"real","reality","realize","really","reason","receive","recent","recently",
"recognize","record","red","reduce","reflect","region","relate","relationship",
"religious","remain","remember","remove","report","represent","republican",
"require","research","resource","respond","response","responsibility","rest",
"result","return","reveal","rich","right","rise","risk","road","rock","role",
"room","rule","run","safe","same","save","say","scene","school","science",
"scientist","score","sea","season","seat","second","section","security","see",
"seek","seem","sell","send","senior","sense","series","serious","serve",
"service","set","seven","several","shake","share","she","shoot","short","shot",
"should","shoulder","show","side","sign","significant","similar","simple",
"simply","since","sing","single","sister","sit","site","situation","six","size",
"skill","skin","small","smile","so","social","society","soldier","some",
"somebody","someone","something","sometimes","son","song","soon","sort","sound",
"source","south","southern","space","speak","special","specific","speech",
"spend","sport","spring","staff","stage","stand","standard","star","start",
"state","statement","station","stay","step","still","stock","stop","store",
"story","strategy","street","strong","structure","student","study","stuff",
"style","subject","success","successful","such","suddenly","suffer","suggest",
"summer","support","sure","surface","system","table","take","talk","task","tax",
"teach","teacher","team","technology","television","tell","ten","tend","term",
"test","than","thank","that","the","their","them","themselves","then","theory",
"there","these","they","thing","think","third","this","those","though","thought",
"thousand","threat","three","through","throughout","throw","thus","time","to",
"today","together","tonight","too","top","total","tough","toward","town","trade",
"traditional","training","travel","treat","treatment","tree","trial","trip",
"trouble","true","truth","try","turn","TV","two","type","under","understand",
"unit","until","up","upon","us","use","usually","value","various","very",
"victim","view","violence","visit","voice","vote","wait","walk","wall","want",
"war","watch","water","way","we","weapon","wear","week","weight","well","west",
"western","what","whatever","when","where","whether","which","while","white",
"who","whole","whom","whose","why","wide","wife","will","win","wind","window",
"wish","with","within","without","woman","wonder","word","work","worker","world",
"worry","would","write","writer","wrong","yard","yeah","year","yes","yet","you",
"young","your","yourself","meshtastic","node","lora","mesh"]
def __init__(self):
self.game = {}
self.DEFAULT_WORDS = self.WORDS
# Try to load hangman.json if it exists
hangman_json_path = os.path.join('data', 'hangman.json')
if os.path.exists(hangman_json_path):
try:
with open(hangman_json_path, 'r') as f:
words = json.load(f)
# Ensure it's a list of strings
if isinstance(words, list) and all(isinstance(w, str) for w in words):
self.WORDS = words
else:
self.WORDS = self.DEFAULT_WORDS
except (FileNotFoundError, json.JSONDecodeError):
logger.warning("Failed to load hangman.json, using default words. example JSON: [\"apple\",\"banana\",\"cherry\"]")
self.WORDS = self.DEFAULT_WORDS
else:
self.WORDS = self.DEFAULT_WORDS
def new_game(self, id):
games = won = 0
ret = ""
if id in self.game:
games = self.game[id]["games"]
won = self.game[id]["won"]
ret += f"Total Games: {games}, Won: {won}\n"
self.game[id] = {
"word": self.random_word(),
"guesses": [],
"games": games+1,
"won": won
}
ret += self.game_continue(id)
return ret
def guess(self, id, input):
g = self.game[id]
if not input:
return
letter = input[0].lower()
if letter.isalpha() and letter not in g["guesses"]:
g["guesses"].append(letter)
def wrong_guesses(self, id):
g = self.game[id]
wrong = 0
for letter in g["guesses"]:
if letter not in g["word"]:
wrong += 1
return wrong
def won(self, id):
g = self.game[id]
for letter in g["word"]:
if letter not in g["guesses"]:
return False
return True
def mask(self, id):
g = self.game[id]
return " ".join([a if a in g["guesses"] else "_" for a in g["word"]])
def game_board(self, id):
g = self.game[id]
emotions = "😀🙂😐😑😕😔💀"
wrong = self.wrong_guesses(id)
ret = ""
if self.won(id):
ret += "🥳" + "\n"
g["won"] += 1
else:
ret += emotions[wrong] + "\n"
ret += hangman.mask(id) + "\n"
if g["guesses"]:
ret += ",".join(g["guesses"]) + "\n"
return ret
def game_continue(self, id):
return self.game_board(id) + "Guess a letter"
def game_over(self, id):
return self.game_board(id) + "Game over, the word was " + self.game[id]["word"]
def play(self, id, input):
if id not in self.game:
return self.new_game(id)
self.guess(id, input)
wrong = self.wrong_guesses(id)
if wrong >= 6 or self.won(id):
return self.game_over(id) + "\n" + self.new_game(id)
return self.game_continue(id)
def end(self, id):
del self.game[id]
def random_word(self):
return random.choice(self.WORDS)
hangmanTracker = []
hangman = Hangman()