diff --git a/README.md b/README.md index 79b349c..8d838ab 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,19 @@ Simple homework printer using a thermal printer. Practice makes perfect! pip install python-escpos[all] --user ``` +### Chess module + +``` +pip install chess +``` + +## Config + + +Consult python-escpos docs: +- [Usage](https://python-escpos.readthedocs.io/en/latest/user/usage.html) +- [Available profiles](https://python-escpos.readthedocs.io/en/latest/printer_profiles/available-profiles.html) + ## Run ```shell diff --git a/jobs/chess_puzzle.py b/jobs/chess_puzzle.py index 0ac1170..e4b56ec 100644 --- a/jobs/chess_puzzle.py +++ b/jobs/chess_puzzle.py @@ -1,4 +1,8 @@ import random +try: + import chess +except ImportError: + chess = None from .base import Job class ChessPuzzleJob(Job): @@ -6,32 +10,12 @@ class ChessPuzzleJob(Job): return "SACHOVE ULOHY" def print_body(self, p): - # (FEN, Instruction, Solution) - puzzles = [ - ("r1bqkb1r/pppp1ppp/2n2n2/4p2Q/2B1P3/8/PPPP1PPP/RNB1K1NR w KQkq - 4 4", "Bily na tahu. Mat 1. tahem.", "Qxf7# (Scholar's Mate)"), - ("rnb1kbnr/pppp1ppp/8/4p3/6Pq/5P2/PPPPP2P/RNBQKBNR b KQkq - 1 3", "Cerny na tahu. Mat 1. tahem.", "Qh4# (Fool's Mate)"), - ("6k1/5ppp/8/8/8/8/5PPP/4R1K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Re8# (Back Rank Mate)"), - ("3r2k1/p4ppp/1p6/8/8/8/P4PPP/3R2K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Rxd8#"), - ("6rk/5p1p/3N4/8/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Nf7# (Smothered Mate)"), - ("8/4N1pk/8/7R/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Rh5# (Anastasia's Mate)"), - ("7k/R7/5N2/8/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Rh7# (Arabian Mate)"), - ("2kr4/1pp5/B7/8/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Ba6# (Boden's Mate)"), - ("7k/6pp/6P1/7Q/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Qh7#"), - ("6k1/5p1p/5PpQ/8/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Qg7# (Lolli's Mate)"), - ("3k4/5ppp/8/6B1/8/8/5PPP/3R2K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Rd8# (Opera Mate)"), - ("6k1/5P2/8/8/8/8/5PPP/6KR w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Rh8# (Anderssen's Mate)"), - ("7k/5ppp/8/7Q/8/2B5/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Qxh7# (Damiano's Bishop Mate)"), - ("4k3/8/4K3/8/8/8/8/5Q2 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Qf7# (Dovetail Mate)"), - ("2rkr3/8/2Q5/8/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Qd7# (Swallow's Tail Mate)"), - ("3rkr2/8/4Q3/8/8/8/5PPP/6K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Qe6# (Epaulette Mate)"), - ("7k/6p1/8/8/2B5/8/5PPP/R5K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Rh1# (Greco's Mate)"), - ("6k1/5pP1/5N2/8/8/8/5PPP/3R2K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Rd8# (Hook Mate)"), - ("8/8/8/8/8/5K2/6Q1/7k w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Qg2#"), - ("k7/1R6/8/8/8/8/8/R5K1 w - - 0 1", "Bily na tahu. Mat 1. tahem.", "Ra8# (Ladder Mate)") - ] + if chess is None: + p.text("CHYBA: Neni nainstalovana knihovna 'chess'.\n") + p.text("Spust: pip install chess\n\n") + return - puzzle = random.choice(puzzles) - fen, instruction, solution = puzzle + fen, instruction, solution = self.generate_puzzle() p.text(f"{instruction}\n\n") self.print_board(p, fen) @@ -44,6 +28,38 @@ class ChessPuzzleJob(Job): p.text("Reseni (naskenuj):\n") p.qr(solution, size=6, native=True) + def generate_puzzle(self): + """ + Simulates a random game until a 'Mate in 1' situation arises. + """ + while True: + board = chess.Board() + # Play up to 120 ply (60 moves) + for _ in range(120): + if board.is_game_over(): + break + + legal_moves = list(board.legal_moves) + random.shuffle(legal_moves) + + # Check if any move leads to immediate checkmate + for move in legal_moves: + board.push(move) + if board.is_checkmate(): + # Found a puzzle! + board.pop() # Revert to state before mate + board.pop() + solution = board.san(move) + turn = "Bily" if board.turn == chess.WHITE else "Cerny" + return board.fen(), f"{turn} na tahu. Mat jednim tahem.", solution + board.pop() + + # No mate found, play a random move to progress the game + if legal_moves: + board.push(random.choice(legal_moves)) + else: + break + def print_board(self, p, fen): board_str = fen.split(' ')[0] rows = board_str.split('/')