Source code for wordle.wordle

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Wordle for Python"""

import datetime
from collections import defaultdict

import numpy as np
from rich.console import Console
from rich.padding import Padding
from rich.panel import Panel

from .vocab import Vocabulary
from .defaults import MAXIMUM_ATTEMPTS

###############################################################################


[docs]class Wordle: def __init__( self, word: str = None, max_attempts: int = MAXIMUM_ATTEMPTS, seed: int = "today", display: bool = False ): self.vocabulary = Vocabulary() self.console = Console() self.display = display if word in self.vocabulary.vocab: self.word = word else: if seed == "today": today = datetime.date.today() seed = today.year * 10000 + today.month * 100 + today.day np.random.seed(seed) self.word = np.random.choice(list(self.vocabulary.vocab)) self.letter_position = defaultdict(set) for position, letter in enumerate(self.word): self.letter_position[letter].add(position) self.max_attempts = max_attempts self.num_attempts = 0 self.attempts = tuple([ [(" ", -1)] * self.vocabulary.word_length for _ in range(max_attempts) ]) self.alphabet = {chr(i): -1 for i in range(97, 123)} self.solved = False self.failed = False
[docs] def message(self, msg, style="bold yellow"): if self.display: self.console.print(Panel(msg), justify="center", style=style)
[docs] def guess(self, word): word = word.lower() result = [] if self.num_attempts == self.max_attempts: self.message("No more attempts left.", style="bold red") elif self.solved: self.message("Wordle is already solved!") elif not self.vocabulary.is_word(word): self.message(f"'{word}' is not a valid word.", style="bold red") else: total_score = 0 for position, letter in enumerate(word): score = sum([ letter in self.letter_position, position in self.letter_position.get(letter, set()) ]) result.append((letter, score)) self.alphabet[letter] = score total_score += score if total_score == 2 * len(word): self.solved = True self.message("Congratulations!", style="bold green") if result in self.attempts: self.message(f"Already attempted '{word}'.") else: self.attempts[self.num_attempts].clear() self.attempts[self.num_attempts].extend(result) self.num_attempts += 1 if self.num_attempts == self.max_attempts and not self.solved: self.failed = True self.message("Oops.. No more attempts left!", style="bold red") if self.display: self.show() return result
[docs] def show(self, style=None): if style is None: style = { -1: "bold white underline", 0: "bold black underline", 1: "bold yellow underline", 2: "bold green underline" } attempts_display = [] for attempt in list(self.attempts): attempts_display.append(" ".join([ f"[{style[score]}]{letter.upper()}[/{style[score]}]" for letter, score in attempt ])) alphabet_display = " ".join([ f"[{style[score]}]{letter.upper()}[/{style[score]}]" for letter, score in self.alphabet.items() ]) self.console.print( Panel( Padding("\n".join(attempts_display), (1, 3)), style="on black" ), "\n", Panel( Padding(alphabet_display, (0, 1)), style="on black" ), justify="center" )
###############################################################################