{"spec_id":"chessboard-pieces","library":"makie","language":"julia","code":"# anyplot.ai\n# chessboard-pieces: Chess Board with Pieces for Position Diagrams\n# Library: makie 0.21.9 | Julia 1.11.9\n# Quality: 90/100 | Created: 2026-09-01\n\nusing CairoMakie\nusing Colors\n\n# --- Theme tokens ------------------------------------------------------------\nconst THEME       = get(ENV, \"ANYPLOT_THEME\", \"light\")\nconst PAGE_BG     = THEME == \"light\" ? colorant\"#FAF8F1\" : colorant\"#1A1A17\"\nconst INK         = THEME == \"light\" ? colorant\"#1A1A17\" : colorant\"#F0EFE8\"\nconst INK_SOFT    = THEME == \"light\" ? colorant\"#4A4A44\" : colorant\"#B8B7B0\"\nconst BRAND       = colorant\"#009E73\"  # Imprint palette position 1 — brand green\n\n# Board squares blended from approved tokens (page background + brand green)\n# so the checkerboard reads as a felt/wood board without an invented hue.\nconst LIGHT_SQUARE = weighted_color_mean(0.6, PAGE_BG, colorant\"#FFFDF6\")\nconst DARK_SQUARE  = weighted_color_mean(0.65, PAGE_BG, BRAND)\n\n# Piece identity (white vs. black) is the data here, so — like the Imprint\n# categorical colors — it stays fixed across themes; only the board and\n# chrome adapt. Each fill gets an opposite-polarity stroke so a piece reads\n# against either square shade.\nconst PIECE_LIGHT = colorant\"#FFFDF6\"\nconst PIECE_DARK  = colorant\"#1A1A17\"\n\nconst PIECE_GLYPHS = Dict(\n    'K' => \"♔\", 'Q' => \"♕\", 'R' => \"♖\", 'B' => \"♗\", 'N' => \"♘\", 'P' => \"♙\",\n    'k' => \"♚\", 'q' => \"♛\", 'r' => \"♜\", 'b' => \"♝\", 'n' => \"♞\", 'p' => \"♟\",\n)\n\n# --- Data ---------------------------------------------------------------------\n# Scholar's Mate, final position: 1. e4 e5  2. Bc4 Nc6  3. Qh5 Nf6??  4. Qxf7#\nconst pieces = Dict(\n    \"a1\" => 'R', \"b1\" => 'N', \"c1\" => 'B', \"e1\" => 'K', \"c4\" => 'B',\n    \"g1\" => 'N', \"h1\" => 'R', \"f7\" => 'Q',\n    \"a2\" => 'P', \"b2\" => 'P', \"c2\" => 'P', \"d2\" => 'P', \"e4\" => 'P',\n    \"f2\" => 'P', \"g2\" => 'P', \"h2\" => 'P',\n    \"a8\" => 'r', \"c6\" => 'n', \"c8\" => 'b', \"d8\" => 'q', \"e8\" => 'k',\n    \"f8\" => 'b', \"f6\" => 'n', \"h8\" => 'r',\n    \"a7\" => 'p', \"b7\" => 'p', \"c7\" => 'p', \"d7\" => 'p', \"e5\" => 'p',\n    \"g7\" => 'p', \"h7\" => 'p',\n)\n\n# 8x8 checkerboard matrix: a1 is dark, h1 is light (standard orientation)\nsquare_shade = [isodd(col + row) ? 1.0 : 0.0 for row in 1:8, col in 1:8]\n\n# --- Plot -----------------------------------------------------------------\nfig = Figure(\n    resolution      = (1200, 1200),\n    backgroundcolor = PAGE_BG,\n    figure_padding  = (24, 24, 12, 24),\n)\n\ntitle = \"chessboard-pieces · julia · makie · anyplot.ai\"\nn = length(title)\nratio = n > 67 ? 67 / n : 1.0\n\nax = Axis(\n    fig[1, 1];\n    title           = title,\n    titlesize       = round(Int, 24 * ratio),\n    titlecolor      = INK,\n    aspect          = DataAspect(),\n    backgroundcolor = PAGE_BG,\n    xticks          = (0.5:1:7.5, [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"]),\n    yticks          = (0.5:1:7.5, string.(1:8)),\n    xticklabelsize  = 20,\n    yticklabelsize  = 20,\n    xticklabelcolor = INK_SOFT,\n    yticklabelcolor = INK_SOFT,\n    xticksvisible     = false,\n    yticksvisible     = false,\n    xgridvisible      = false,\n    ygridvisible      = false,\n    topspinevisible   = false,\n    rightspinevisible = false,\n    leftspinevisible  = false,\n    bottomspinevisible = false,\n)\nxlims!(ax, 0, 8)\nylims!(ax, 0, 8)\n\nheatmap!(ax, 0.5:1:7.5, 0.5:1:7.5, square_shade';\n    colormap = [DARK_SQUARE, LIGHT_SQUARE])\nlines!(ax, [0, 8, 8, 0, 0], [0, 0, 8, 8, 0]; color = INK_SOFT, linewidth = 2)\n\nfor square in sort(collect(keys(pieces)))\n    piece = pieces[square]\n    col = Int(square[1]) - Int('a') + 1\n    row = parse(Int, square[2])\n    is_white = isuppercase(piece)\n    text!(ax, col - 0.5, row - 0.5;\n        text        = PIECE_GLYPHS[piece],\n        fontsize    = 76,\n        font        = \"DejaVu Sans\",\n        color       = is_white ? PIECE_LIGHT : PIECE_DARK,\n        strokecolor = is_white ? PIECE_DARK : PIECE_LIGHT,\n        strokewidth = 2.5,\n        align       = (:center, :center))\nend\n\n# --- Save -------------------------------------------------------------------\nsave(\"plot-$(THEME).png\", fig; px_per_unit = 2)\n"}