Source code for chessplotlib.base

import copy
from typing import Tuple

import chess
import matplotlib.pyplot as plt
import numpy as np

import matplotlib.patches as patches

SYMBOLS = {
    "K": "♔",
    "Q": "♕",
    "R": "♖",
    "B": "♗",
    "N": "♘",
    "P": "♙",
    "k": "♚",
    "q": "♛",
    "r": "♜",
    "b": "♝",
    "n": "♞",
    "p": "♟︎",
}


def plot_blank_board(ax: plt.Axes, checkers: bool = True):
    r"""
    Creates a blank board plot on the specified axis.

    Parameters
    ----------
    ax: plt.Axes
        Axes to apply the board to.
    checkers: bool, default=True
        Whether or not to apply a checker pattern to the background.

    Examples
    --------
    >>> from chessplotlib import plot_blank_board
    >>> import matplotlib.pyplot as plt
    >>> ax = plt.gca()
    >>> plot_blank_board(ax)
    >>> plt.show()

    .. image:: ../../examples/blank.png

    """
    ax.set_xlim([-0.5, 7.5])
    ax.set_ylim([7.5, -0.5])
    for i in range(8):
        ax.axhline(i - 0.5, 0, 8, color="black")
        ax.axvline(i - 0.5, 0, 8, color="black")

    ax.tick_params(labeltop=True, labelright=True, length=0)

    ax.set_yticks(list(reversed(list(range(8)))))
    ax.set_xticks(list(range(8)))

    ax.set_yticklabels(("1", "2", "3", "4", "5", "6", "7", "8"))
    ax.set_xticklabels(("a", "b", "c", "d", "e", "f", "g", "h"))

    if checkers:
        _make_checkers(ax)


[docs]def plot_board(ax: plt.Axes, board: chess.Board, checkers: bool = True): r""" Plots the board position defined in the board object on the given axis. Parameters ---------- ax: plt.Axes Axes to apply the board to. board: chess.Board Board object to plot. checkers: bool, default=True Whether or not to apply a checker pattern to the background. Examples -------- >>> import chess >>> from chessplotlib import plot_board >>> import matplotlib.pyplot as plt >>> board = chess.Board() >>> ax = plt.gca() >>> plot_board(ax, board) >>> plt.show() .. image:: ../../examples/starting_board.png """ plot_blank_board(ax) X, Y = np.meshgrid(np.arange(8), np.arange(8)) locs = np.stack([X.flatten(), Y.flatten()], axis=1) for square in chess.SQUARES_180: piece = board.piece_at(square) if piece: add_piece(ax, chess.SQUARE_NAMES[square], piece.symbol())
[docs]def plot_move( ax: plt.Axes, board: chess.Board, move: chess.Move, alpha: float = 1.0, color: str = "red", piece_alpha: float = 1.0, piece_color: str = "black", ): r""" Visualizes a move on top of a plotted board. Parameters ---------- ax: plt.Axes Axes containing the state of the board in which the move with take place move: chess.Move Potential move represented with a chess.Move object alpha: float, default=1.0 Alpha value for move visual color: str, default=black Color for move visual Examples -------- >>> import chess >>> from chessplotlib import plot_board, plot_move >>> import matplotlib.pyplot as plt >>> board = chess.Board() >>> move = chess.Move.from_uci("e2e4") >>> ax = plt.gca() >>> plot_board(ax, board) >>> plot_move(ax, board, move) >>> plt.show() .. image:: ../../examples/opening_move.png """ from_square = _from_square(move) to_square, promotion = _to_square(move) square = chess.SQUARE_NAMES.index(from_square) from_piece = board.piece_at(square) if promotion == "": to_piece = from_piece else: to_piece = chess.Piece.from_symbol(promotion) add_arrow(ax, from_square, to_square, alpha=alpha, color=color) add_piece(ax, to_square, to_piece.symbol(), alpha=piece_alpha, color=piece_color)
[docs]def mark_square(ax: plt.Axes, square: str): r""" Highlights a square in a red outline. Parameters ---------- ax: plt.Axes Axes containing the state of the board square: str String name for square, (i.e. e1) Examples -------- >>> import chess >>> from chessplotlib import plot_board, mark_square >>> import matplotlib.pyplot as plt >>> board = chess.Board() >>> ax = plt.gca() >>> plot_board(ax, board) >>> mark_square(ax, "e2") >>> plt.show() .. image:: ../../examples/starting_board_marked.png """ row, col = _square_to_grid(square) rect = patches.Rectangle( (row - 0.5, col - 0.5), 1.0, 1.0, linewidth=2, edgecolor="r", facecolor="none", zorder=3, ) # Add the patch to the Axes ax.add_patch(rect)
[docs]def color_square(ax: plt.Axes, square: str, color: str, alpha: float = 1.0): r""" Fills in a square with a particular color Parameters ---------- ax: plt.Axes Axes containing the state of the board square: str String name for square, (i.e. e1) Examples -------- >>> import chess >>> from chessplotlib import plot_board, color_square >>> import matplotlib.pyplot as plt >>> board = chess.Board() >>> plot_board(ax, board) >>> color_square(ax, "e4", "blue") >>> color_square(ax, "a1", "green") >>> color_square(ax, "f8", "red") >>> plt.show() .. image:: ../../examples/colored_squares.png """ row, col = _square_to_grid(square) rect = patches.Rectangle( (row - 0.5, col - 0.5), 1.0, 1.0, linewidth=2, facecolor=color, zorder=0, ) # Add the patch to the Axes ax.add_patch(rect)
[docs]def mark_move(ax: plt.Axes, move: chess.Move): r""" Marks the two squares used in a move. Parameters ---------- ax: plt.Axes Axes containing the state of the board move: chess.Move Move to visualize Examples -------- >>> import chess >>> from chessplotlib import plot_board, mark_square >>> import matplotlib.pyplot as plt >>> board = chess.Board() >>> move = chess.Move.from_uci("e2e4") >>> ax = plt.gca() >>> plot_board(ax, board) >>> mark_move(ax, move) >>> plt.show() .. image:: ../../examples/starting_board_move_marked.png """ from_square = _from_square(move) to_square, _ = _to_square(move) mark_square(ax, from_square) mark_square(ax, to_square)
[docs]def add_piece( ax: plt.Axes, square: str, piece: str, alpha: float = 1.0, color: str = "black" ): r""" Adds a piece to the board. Adds the piece, `piece`, at location square on axes ax. Parameters ---------- ax: plt.Axes Axes containing board square: str String representing the square (i.e. "e1") piece: str String symbol for the piece (i.e. "P") alpha: float Alpha for the piece, controls piece visibility color: str black or white, controls the color of the piece Examples -------- >>> from chessplotlib import plot_blank_board, add_piece >>> import matplotlib.pyplot as plt >>> ax = plt.gca() >>> plot_blank_board(ax) >>> add_piece(ax, 'e4', 'K') >>> add_piece(ax, 'g5', 'q', color='red', alpha=0.25) >>> plt.show() .. image:: ../../examples/blank_added_pieces.png """ x, y = _square_to_grid(square) ax.text( x, y + 0.05, SYMBOLS[piece], fontsize=32, ha="center", va="center", alpha=alpha, color=color, )
[docs]def add_arrow( ax: plt.Axes, from_square: str, to_square: str, alpha=1.0, color="black", ): r""" Adds an arrow from one square to the next Draws an arrow connecting two squares together. Can be used to represent moves. Parameters ---------- ax: plt.Axes Axes containing board. from_square: str String representing the square to start the arrow (i.e. "e1"). to_square: str String representing the square to finish the arrow (i.e. "e4"). alpha: float Alpha for the piece, controls piece visibility. color: str Controls the color of the piece, typically black or white. Examples -------- >>> from chessplotlib import plot_blank_board, add_arrow >>> import matplotlib.pyplot as plt >>> ax = plt.gca() >>> plot_blank_board(ax) >>> add_arrow(ax, 'e4', 'g5', color='blue') >>> plt.show() .. image:: ../../examples/blank_with_line.png """ from_x, from_y = _square_to_grid(from_square) to_x, to_y = _square_to_grid(to_square) # Not sure why this delta is need, but the arrows appear clearly off-center # otherwise. from_x += 0.02 to_x += 0.02 ax.arrow( from_x, from_y, to_x - from_x, to_y - from_y, alpha=alpha, color=color, zorder=4, head_width=0.15, length_includes_head=True, )
def _make_checkers(ax: plt.Axes): """ Adds checkers to the board to make it look more natural """ X, Y = np.meshgrid(np.arange(8), np.arange(8)) checker = (((X + Y) % 2) + 0.3) / 2 ax.imshow(checker, cmap="Greys", vmax=1.0, vmin=0.0) def _from_square(move: chess.Move) -> str: """ Converts a move into the from location """ return chess.SQUARE_NAMES[move.from_square] def _to_square(move: chess.Move) -> Tuple[str, str]: """ Converts a move into the to location and promotion """ promotion = "" if move.promotion is not None: promotion = chess.PIECE_SYMBOLS[move.promotion] return (chess.SQUARE_NAMES[move.to_square], promotion) def _square_to_grid(square: str) -> Tuple[int, int]: """ Converts the string name of the square into the grid location """ row_val = square[0] col_val = square[1] col = ["8", "7", "6", "5", "4", "3", "2", "1"].index(col_val) row = ["a", "b", "c", "d", "e", "f", "g", "h"].index(row_val) return row, col