8
\$\begingroup\$

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:

ex

\$\endgroup\$
1
  • \$\begingroup\$ Sorry to those who worked on reviews prior to these edits. Being unclear as to what a follow-up would be in this context lead me to make things more complicated than they are. Edits are final on my end; happy reviewing! \$\endgroup\$
    – T145
    Nov 6, 2019 at 0:41

1 Answer 1

1
\$\begingroup\$

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).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.