#!/usr/bin/env -S uv run --script # # Generates the blind_chess.apkg Anki Deck # # /// script # requires-python = ">=3.13" # dependencies = [ # "genanki", # "python-chess", # ] # /// import random import genanki import chess import chess.svg deck = genanki.Deck(2059400110, 'Blind Chess') model = genanki.Model(1120858226, 'Chess Model', fields=[ {'name': 'guid'}, {'name': 'Question'}, {'name': 'Answer'}, {'name': 'Board'}, ], templates=[ { 'name': 'Base Card with SVG board in answer', 'qfmt': '{{Question}}', 'afmt': '{{FrontSide}}
{{Answer}} {{Board}}', }, ] ) class ChessNote(genanki.Note): @property def guid(self): return genanki.guid_for(self.fields[0]) def square_color(sq_name): sq_id = chess.parse_square(sq_name) sq_file = chess.square_file(sq_id) sq_rank = chess.square_rank(sq_id) guid = f'{sq_name}-color' question = f'What is the color of square {sq_name}?' answer = 'black' if (sq_file+sq_rank) % 2 == 0 else 'white' board_svg = chess.svg.board(None, squares=sq_id) return ChessNote(model, [guid, question, answer, board_svg]) def knight_moves(sq_name): board = chess.Board().empty() sq_id = chess.parse_square(sq_name) board.set_piece_at(sq_id, chess.Piece(chess.KNIGHT, chess.WHITE)) attacks = board.attacks(sq_id) guid = f'{sq_name}-knight-moves' question = f'Where can the knight move from square {sq_name}?' answer = ', '.join(chess.SQUARE_NAMES[sq] for sq in list(attacks)) board_svg = chess.svg.board(board, fill=dict.fromkeys(attacks, "#cc0000cc")) return ChessNote(model, [guid, question, answer, board_svg]) def notes(): for sq_name in chess.SQUARE_NAMES: yield square_color(sq_name) yield knight_moves(sq_name) # randomize the order of the notes for note in random.shuffle(list(notes())) deck.add_note(note) out = 'blind_chess.apkg' genanki.Package(deck).write_to_file(out) print(f'Created deck {out} with {len(deck.notes)} notes')