Printing Colored, CLId Unicode Chess Board - follow-up Follow up to: Printing Command Line Unicode Chess Board


A couple people from the previous question mentioned looking into coloring the command line with ANSI escape sequences. In Python, colorama seems to handle this quite nicely. Below is my attempt at using it for printing out a chess board.

from enum import Enum
from enum import auto
from colorama import init, Fore, Back, Style


class Color(Enum):
    WHITE = 0
    BLACK = 1


class Piece(Enum):
    EMPTY = auto()
    PAWN = auto()
    ROOK = auto()
    KNIGHT = auto()
    BISHOP = auto()
    KING = auto()
    QUEEN = auto()


ELEMENTS = {
    (Color.WHITE, Piece.EMPTY): Back.WHITE,
    (Color.WHITE, Piece.KING): f'{Fore.LIGHTWHITE_EX}\u265A',
    (Color.WHITE, Piece.QUEEN): f'{Fore.LIGHTWHITE_EX}\u265B',
    (Color.WHITE, Piece.ROOK): f'{Fore.LIGHTWHITE_EX}\u265C',
    (Color.WHITE, Piece.BISHOP): f'{Fore.LIGHTWHITE_EX}\u265D',
    (Color.WHITE, Piece.KNIGHT): f'{Fore.LIGHTWHITE_EX}\u265E',
    (Color.WHITE, Piece.PAWN): f'{Fore.LIGHTWHITE_EX}\u265F',
    (Color.BLACK, Piece.EMPTY): Back.LIGHTBLACK_EX,
    (Color.BLACK, Piece.KING): f'{Fore.BLACK}\u265A',
    (Color.BLACK, Piece.QUEEN): f'{Fore.BLACK}\u265B',
    (Color.BLACK, Piece.ROOK): f'{Fore.BLACK}\u265C',
    (Color.BLACK, Piece.BISHOP): f'{Fore.BLACK}\u265D',
    (Color.BLACK, Piece.KNIGHT): f'{Fore.BLACK}\u265E',
    (Color.BLACK, Piece.PAWN): f'{Fore.BLACK}\u265F'
}


def init_tiles():
    row = [ELEMENTS[(Color(i % 2), Piece.EMPTY)] for i in range(8)]
    return [row if i % 2 == 0 else row[::-1] for i in range(8)]


def init_board():

    def get_army(color):
        return [
            (color, Piece.ROOK),
            (color, Piece.KNIGHT),
            (color, Piece.BISHOP),
            (color, Piece.QUEEN),
            (color, Piece.KING),
            (color, Piece.BISHOP),
            (color, Piece.KNIGHT),
            (color, Piece.ROOK)
        ]

    return (
        [
            get_army(Color.BLACK),
            [(Color.BLACK, Piece.PAWN) for _ in range(8)],
            *[[None] * 8 for _ in range(4)],
            [(Color.WHITE, Piece.PAWN) for _ in range(8)],
            get_army(Color.WHITE)
        ]
    )


def print_board(board, flip=False):

    def flip_board(board):
        return [row[::-1] for row in reversed(board)]

    for i, row in enumerate(board if not flip else flip_board(board)):
        for j, piece in enumerate(row):
            piece = ELEMENTS.get(piece)
            print(f"{tiles[i][j]}{piece if piece else ' '}",
                  Style.RESET_ALL, end='', flush=True)
        print()


if __name__ == '__main__':
    init()
    tiles = init_tiles()
    board = init_board()
    print_board(board)


As always, any optimizations and critique is welcome!

Example Output:
This is some nice polished code. I have just a few remarks.

When initializing ELEMENTS, the piece names get pasted in twice.
Perhaps you'd like to loop over them,
adding a black and a white variant to the dict?
You might even associate the proper unicode code point
with each enum member, rather than calling auto().


        [(Color.BLACK, Piece.PAWN) for _ in range(8)],



You have nice helpers everywhere.
Except for the two lines about pawns.
Maybe you'd like a get_pawns(color) function?

Instead of enumerating row and then doing this:


        piece = ELEMENTS.get(piece)



consider running enumerate over map(ELEMENTS.get, row).