New job: Word search (osmismerka)

This commit is contained in:
Dejvino 2025-12-23 23:17:27 +01:00
parent 0754f82ab6
commit 510ea220cc
3 changed files with 178 additions and 0 deletions

33
jobs/czech_words.py Normal file
View File

@ -0,0 +1,33 @@
CZECH_WORDS = [
"AUTO", "BABIČKA", "BANÁN", "BARVA", "BÁSNIČKA", "BATOH", "BAVLNA", "BAZÉN",
"BEDNA", "BERAN", "BLÁTO", "BLESK", "BLOUDIT", "BOBŘÍK", "BODLÁK", "BOTY",
"BOUDA", "BOUŘKA", "BRÁNA", "BRATR", "BROUK", "BRUSLE", "BUBEN", "BUNDA",
"CESTA", "CIHLA", "CIRKUS", "CITRON", "CUKR", "ČEPICE", "ČERVENÁ", "ČESNEK",
"ČÍSLO", "ČLOVĚK", "DÁREK", "DATEL", "DCERA", "DĚDEČEK", "DEŠTNÍK", "DIVADLO",
"DOKTOR", "DOMOV", "DOPIS", "DORT", "DRAK", "DUBEN", "DŮM", "DVEŘE",
"DŽBÁN", "FARA", "FIALA", "FILM", "FLÉTNA", "FOTBAL", "GUMA", "HAVRAN",
"HLAVA", "HLÍNA", "HNÍZDO", "HODINY", "HOLKA", "HOLUB", "HORA", "HOUSKA",
"HRAD", "HRÁBĚ", "HRANA", "HRAČKA", "HRNEK", "HRUŠKA", "HUDBA", "CHATA",
"CHLÉB", "CHLAP", "CHYBA", "JABLKO", "JAHODA", "JARO", "JAZYK", "JEHLA",
"JEZERO", "JÍDLO", "JITRO", "KABÁT", "KAČNA", "KAKAO", "KÁMEN", "KAPSÁŘ",
"KARTA", "KÁVA", "KILO", "KLADIVO", "KLÍČ", "KLOBOUK", "KLUK", "KNIHA",
"KOČKA", "KOLO", "KOMÁR", "KONEC", "KOPEC", "KOŘEN", "KOST", "KOŠILE",
"KOZA", "KRÁL", "KRÁVA", "KRESLIT", "KREV", "KRK", "KRUH", "KUCHYNĚ",
"KVĚTINA", "LÁSKA", "LAVICE", "LEDEN", "LES", "LÉTO", "LEV", "LÍSTEK",
"LOĎ", "LOUKA", "LŽÍCE", "MÁMA", "MAPA", "MASO", "MĚSTO", "METR",
"MLÉKO", "MLÝN", "MODRÁ", "MOŘE", "MOST", "MOTÝL", "MRAK", "MRKEV",
"MUŽ", "MYŠ", "NÁDRAŽÍ", "NOHA", "NOC", "NOS", "NOVINY", "NŮŽKY",
"OBCHOD", "OBĚD", "OBRAZ", "OCAS", "OKNO", "OKO", "OLEJ", "OPICE",
"OREL", "OVOCE", "PÁTEK", "PES", "PÍSEŇ", "PIVO", "PLÁČ", "PLOT",
"POLE", "POLÉVKA", "POMOC", "POSTEL", "POTOK", "PRÁCE", "PRAHA", "PRASE",
"PRST", "PTÁK", "RÁDIO", "RADOST", "RAKETA", "RÁNO", "RUKA", "RYBA",
"ŘEKA", "ŘEPA", "SÁŇKY", "SEDLO", "SESTRA", "SEŠIT", "SKLO", "SLON",
"SLUNCE", "SNÍH", "SOVA", "SRDCE", "STROM", "STŮL", "SVĚTLO", "ŠKOLA",
"ŠATY", "ŠNEK", "TÁTA", "TELEVIZE", "TETA", "TMA", "TRAVÁ", "TRH",
"TUŽKA", "UCHO", "ULICE", "ÚNOR", "ÚSTA", "VAJÍČKO", "VÁNOCE", "VČELA",
"VEČEŘE", "VEJCE", "VELRYBA", "VESNICE", "VĚTR", "VODA", "VOJÁK", "VOLANT",
"VRÁNA", "VRATA", "VLASY", "VLAK", "VLK", "ZÁHADA", "ZAHRADA", "ZÁMEK",
"ZIMA", "ZLATO", "ZUB", "ZVON", "ŽÁBA", "ŽÁROVKA", "ŽENA", "ŽIDLE", "ŽIVOT",
# special letters to make sure we have them covered:
"WEB", "PIXEL", "TEQUILA", "BRAWL", "BOX", "QÍK"
]

143
jobs/word_search.py Normal file
View File

@ -0,0 +1,143 @@
import random
import time
import textwrap
from jobs.czech_words import CZECH_WORDS
class WordSearchJob:
def __init__(self):
self.width = 14
self.height = 14
self.hidden_phrase = "TAJENKA"
self.words_to_find = []
self.grid = []
def get_name(self):
return "Word Search (Osmismerka)"
def configure(self):
print("\n--- Configure Word Search ---")
phrase = input("Enter hidden phrase (default: TAJENKA): ").strip().upper()
if phrase:
self.hidden_phrase = "".join(c for c in phrase if c.isalnum())
else:
self.hidden_phrase = "TAJENKA"
self.width = len(self.hidden_phrase) + 2
self.height = len(self.hidden_phrase) + 2
size = int(input(f"Enter size (default: {self.width}): ").strip())
if size:
self.width = size
self.height = size
if self.width < 5:
self.width = 5
self.height = 5
if self.width > 40:
self.width = 40
self.height = 40
def run(self, printer):
# Directions: Right, Down, Diag-Down-Right
directions = [(0, 1), (1, 0), (1, 1)]
target_empty = len(self.hidden_phrase)
# Retry loop to ensure perfect fill (no leftover letters)
for attempt in range(20):
# Initialize grid
self.grid = [['' for _ in range(self.width)] for _ in range(self.height)]
used_mask = [[False for _ in range(self.width)] for _ in range(self.height)]
# Filter words that fit in the grid
available_words = [w for w in CZECH_WORDS if len(w) <= self.width and len(w) <= self.height]
random.shuffle(available_words)
self.words_to_find = []
total_cells = self.width * self.height
current_empty = total_cells
# Try to place words until we reach target_empty
for word in available_words:
if current_empty == target_empty:
break
placed = False
attempts = 0
while not placed and attempts < 50:
attempts += 1
direction = random.choice(directions)
dr, dc = direction
# Determine bounds
if dr == 0: # Horizontal
r = random.randint(0, self.height - 1)
c = random.randint(0, self.width - len(word))
elif dc == 0: # Vertical
r = random.randint(0, self.height - len(word))
c = random.randint(0, self.width - 1)
else: # Diagonal
r = random.randint(0, self.height - len(word))
c = random.randint(0, self.width - len(word))
# Check collision
fits = True
temp_new_cells = 0
for i, char in enumerate(word):
nr, nc = r + i*dr, c + i*dc
# Cell must be empty OR contain the same letter
if self.grid[nr][nc] != '' and self.grid[nr][nc] != char:
fits = False
break
if self.grid[nr][nc] == '':
temp_new_cells += 1
if fits:
# Check if this overfills
if current_empty - temp_new_cells < target_empty:
continue
# Place it
for i, char in enumerate(word):
nr, nc = r + i*dr, c + i*dc
if self.grid[nr][nc] == '':
current_empty -= 1
self.grid[nr][nc] = char
used_mask[nr][nc] = True
self.words_to_find.append(word)
placed = True
if current_empty == target_empty:
break
# Fill remaining spots with hidden phrase
empty_slots = []
for r in range(self.height):
for c in range(self.width):
if not used_mask[r][c]:
empty_slots.append((r, c))
phrase_idx = 0
for r, c in empty_slots:
if phrase_idx < len(self.hidden_phrase):
self.grid[r][c] = self.hidden_phrase[phrase_idx]
phrase_idx += 1
else:
# Fill with random letters if phrase is done (extra filler)
self.grid[r][c] = random.choice("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
# Print Header
printer.text("OSMISMĚRKA\n")
printer.text("Najdi slova a přečti tajenku!\n")
if current_empty != target_empty:
printer.text(f"Tajenka má {len(self.hidden_phrase)} písmen.\n")
printer.text("\n")
# Print Grid
for r in range(self.height):
line = " ".join(self.grid[r])
printer.text(line + "\n")
time.sleep(0.05)
printer.text("\nSlova k hledání:\n")
words_str = ", ".join(sorted(self.words_to_find))
printer.text(textwrap.fill(words_str, width=42) + "\n")
printer.text("\n\n")
printer.cut()

View File

@ -10,6 +10,7 @@ from jobs.decimal_division import DecimalDivisionJob
from jobs.joke import JokeJob from jobs.joke import JokeJob
from jobs.maze_multitarget import MazeMultitargetJob from jobs.maze_multitarget import MazeMultitargetJob
from jobs.flush import FlushJob from jobs.flush import FlushJob
from jobs.word_search import WordSearchJob
# ========================================== # ==========================================
# CONFIGURATION # CONFIGURATION
@ -64,6 +65,7 @@ JOBS = [
DecimalDivisionJob(), DecimalDivisionJob(),
JokeJob(), JokeJob(),
MazeMultitargetJob(), MazeMultitargetJob(),
WordSearchJob(),
# keep this last: # keep this last:
FlushJob() FlushJob()
] ]