Chess Things

Chess Things

·

4 min read

Just some learnings from doing chess coding problems.

Chessboard Representation

A chessboard can be represented as a two-dimensional array of the Cartesian product to represent a 8x8 grid. More background in the Applications of Cartesian Products article.

201843.image0.jpg

import numpy as np
file, rank = "abcdefgh", "12345678"
files, ranks = list(file), list(rank)
board = []
for f in ranks[::-1]:
    row = []
    for r in files:
        row.append(r + f)
    board.append(row)
print(np.matrix(board))

We use numpy to display the 2D-array in matrix form:

[['a8' 'b8' 'c8' 'd8' 'e8' 'f8' 'g8' 'h8']
 ['a7' 'b7' 'c7' 'd7' 'e7' 'f7' 'g7' 'h7']
 ['a6' 'b6' 'c6' 'd6' 'e6' 'f6' 'g6' 'h6']
 ['a5' 'b5' 'c5' 'd5' 'e5' 'f5' 'g5' 'h5']
 ['a4' 'b4' 'c4' 'd4' 'e4' 'f4' 'g4' 'h4']
 ['a3' 'b3' 'c3' 'd3' 'e3' 'f3' 'g3' 'h3']
 ['a2' 'b2' 'c2' 'd2' 'e2' 'f2' 'g2' 'h2']
 ['a1' 'b1' 'c1' 'd1' 'e1' 'f1' 'g1' 'h1']]

Black/White Cells

If we wanted to add the alternating black/white colors for rank and file to better represent the board:

import numpy as np
file, rank = "abcdefgh", "12345678"
files, ranks = list(file), list(rank)
board = []
for i, f in enumerate(ranks[::-1]):
    row = []
    i = i % 2 # Even if 0 and odd if 1.
    for j, r in enumerate(files):
        c = '_b' if j & 1 else '_w' # Odd if j & 1 == 1 else even.
        if i:
            c = '_w' if j & 1 else '_b'
        row.append(f + r + c )
    board.append(row)
print(np.matrix(board))

We use modulo (%) and bitwise and (&) to determine either even or odd for i and j.

[['8a_w' '8b_b' '8c_w' '8d_b' '8e_w' '8f_b' '8g_w' '8h_b']
 ['7a_b' '7b_w' '7c_b' '7d_w' '7e_b' '7f_w' '7g_b' '7h_w']
 ['6a_w' '6b_b' '6c_w' '6d_b' '6e_w' '6f_b' '6g_w' '6h_b']
 ['5a_b' '5b_w' '5c_b' '5d_w' '5e_b' '5f_w' '5g_b' '5h_w']
 ['4a_w' '4b_b' '4c_w' '4d_b' '4e_w' '4f_b' '4g_w' '4h_b']
 ['3a_b' '3b_w' '3c_b' '3d_w' '3e_b' '3f_w' '3g_b' '3h_w']
 ['2a_w' '2b_b' '2c_w' '2d_b' '2e_w' '2f_b' '2g_w' '2h_b']
 ['1a_b' '1b_w' '1c_b' '1d_w' '1e_b' '1f_w' '1g_b' '1h_w']]

Translation from Algebraic Notation to Index Notation

Sometimes we may want to translate a chess piece position from algebraic notation ("A3") to index notation (cell[0][3]). Note algebraic notation is A/1 based.

Using translate table:

def get_position_translate(piece):
     f, r = "abcdefgh", "01234567"
     tbl = str.maketrans(c, n)
     return (int(piece[0].translate(tbl)), int(piece[1])-1)

Using ASCII code:

def get_position_ascii(piece):
    return (ord(piece[0].upper()) -  ord('A'), int(piece[1])-1)

Pawn Movement

def pawn_moves(face_north, rank, file):
    '''
    Returns position of pawn next move.  Pawn can only move forward.
    If invalid move then returns current cell/squre/position.
    param: face_north - bool - Facing north or south.
    param: rank - int - The horizontal/row zero-based index.
    param: file - int - The vertical/column zero-based index.
    '''
    if face_north:
        if file < 8:
            return (rank, file+1)
    elif file > 0:
        return (rank, file-1)
    return (rank, file)

Knight Movement

Best to determine possible 8 positions and then filter by whether or not they are on the board.

def knight_moves(rank, file):
    '''
    param: rank - int - The horizontal/row zero-based index.
    param: file - int - The vertical/column zero-based index.
    '''
    if (0 > rank or rank > 8) or (0 > file or file > 8):
        return (rank, file)
    possible_moves = [(1, 2), (2, 1), (-1, 2), (1, -2), (-1, -2), (-2, -1), (2, -1), (-2, 1)]
    moves = [(rank + r, file + f) for r, f in possible_moves
        if 0 <= rank + r < 8 and  0 <= file + f < 8]
    return moves

Alternative

def possible_knight_movesx(rank, file):
    '''
    param: rank - int - The horizontal/row zero-based index.
    param: file - int - The vertical/column zero-based index.
    '''
    if (0 > rank or rank > 8) or (0 > file or file > 8):
        return (rank, file)
    possible_moves = [(-2, -1), (-1, -2), (-2, 1), (-1, 2)] # The Top half. Left/Right mirror doesn't work.
    possible_moves += ([(x*-1, y*-1) for x,y in possible_moves])
    moves = [(rank + r, file + f) for r, f in possible_moves
        if 0 <= rank + r < 8 and  0 <= file + f < 8]
    return moves

Bishop Movement

TODO

Rook Movement

TODO

Queen Movement

TODO

King Movement

TODO

Amazon Movement

TODO