# Written for Meshtastic mesh-bot by ZR1RF Johannes le Roux 2025 from modules.log import logger, getPrettyTime import os import json import random 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()