# Chess Game In Python With Source Code

The Chess Game In Python is a fully functional desktop application project that includes all of the components that IT students and computer-related courses will need for their college projects or for leisure time purposes. This Chess Game Program In Python is one of the world’s oldest and most popular board games. Whether you want to learn how to play chess, play casual games with your friends, or compete, you’ll find everything you need to know about how to design and play this game in Python. This Chess Game In Python With Source Code is beneficial for practicing Java development and gaining new skills. This project is quite useful, and the concept and logic are simple to grasp. The source code is open source and is free to use. Simply scroll down and click the download button.

## What Is Chess Game In Python?

This Chess Game Using Python contains everything I wrote, as well as some of the dictionary and methods listed above. We begin by creating the window object, which is the window that appears when the chess game is launched. The dimensions were set to 800×800, which corresponded to the tuple argument we provided. We chose 800 by 800 since the graphics for the chess pieces we designed were all 100×100 pixels, which meant the board would fit properly.

Code For Game in Python: Python Gam...
Code For Game in Python: Python Game Projects With Source Code 2021 | Best For Beginners

These node objects are the fundamental components of my software, and they are simply containers for chess pieces (which are emulated as chess board tiles in this case). Their row, column, x, and y co-ordinates are their properties. We need these separately because all of these nodes will be stored in an 8×8 2d list, so if we call it, we’ll need its row and col numbers, whereas if we’re drawing it on the screen, we’ll need its x,y pixel values (we could just do row*100, but that would risk us forgetting to add that one time in the entire code and having it break).

The draw function is used to draw the tile onto the screen (the black and white pattern), whereas the setup method is used to put any images onto the screen if there is a piece on the screen at that location. Using blit, you draw on the screen.

Draw grid creates the 2d list that will be used to access all of the nodes later, and make grid creates the grid’s boundaries (the black horizontal and vertical lines that separate the tiles). Every time the tick occurs, the update display is used to update the screen. I believe we selected to run the software at 20 frames per second to avoid overheating the CPU. This is obviously unsuitable for chess, but we didn’t want too much lag.

We need to figure out which tile the user has clicked on when they click on the screen, which is what find node does. Display potential moves is a function created by Edwin that simply takes a list of possible moves and changes the color of the tile to make it stand out for those moves.

When the screen updates, this change will be seen on the screen because Do move is used to create the swap on the screen by switching the values in my dictionary.

Because it’s difficult to remove the highlights for certain tiles, we opted to merely redraw the black colors for all of the tiles instead.

The main function then has a lot of common logic, which I assume you’re familiar with if you’re familiar with PyGame. I’ll also include a video in case you don’t have access to the internet.

## How To Play Chess Game In Python

Chess is a game played by two players on opposite sides of a 64-square board with alternating colors. A king, queen, two rooks, two bishops, two knights, and eight pawns are all given to each player at the start of the game. The goal of the game is to checkmate the other player’s king.

## Benefits Of Playing Chess Game In Python

• Chess helps memory – It should come as no surprise that expert chess players have great recall skills. After all, the game requires memorizing a great number of alternative moves and their outcomes. It’s also worth noting that experienced chess players do better in a particular type of memory called auditory memory. This is the ability to recall knowledge that has been acquired through hearing.
• Chess enhances planning skills – Chess games feature long periods of silent contemplation, during which players analyze each move. Players put a lot of effort into anticipating the reactions of their opponents and attempting to anticipate every potential circumstance. The practice of mind-careful thought and planning is one of the cognitive health benefits of chess.

## About the Project : Chess Game In Python With Source Code

The Python Chess Game Code is a simple desktop program built with the programming language Python. With the Python programming language, we can also make very interesting games. One of these games is Chess. The project system file has both a Python script and resource files. The game’s graphics are smooth, and it’s easy to figure out how to play. This Code For Chess Game In Python includes a tutorial and a code development guide. This is a simple and easy-to-understand learning project. Since Chess Game is open source, you can download the zip file and change it to fit your needs. You can also change this project to fit your needs and make a great advanced-level project out of it.

This Chess Game In Python Code includes a tutorial and a code development guide. This is a simple and easy-to-understand little project to help you learn. Chess is open source, so you can download the zip file and change it to fit your needs. You can also change this project to fit your needs and make a great project for an advanced level.

## The given code below is a python file for chess_gui.py

```# The GUI engine for Python Chess
#
# Author: Boo Sung Kim, Eddie Sharick
# Note: The pygame tutorial by Eddie Sharick was used for the GUI engine. The GUI code was altered by Boo Sung Kim to
# fit in with the rest of the project.
#
import chess_engine
import pygame as py

import ai_engine
from enums import Player

"""Variables"""
WIDTH = HEIGHT = 512  # width and height of the chess board
DIMENSION = 8  # the dimensions of the chess board
SQ_SIZE = HEIGHT // DIMENSION  # the size of each of the squares in the board
MAX_FPS = 15  # FPS for animations
IMAGES = {}  # images for the chess pieces
colors = [py.Color("white"), py.Color("gray")]

# TODO: AI black has been worked on. Mirror progress for other two modes
'''
Load images for the chess pieces
'''
for p in Player.PIECES:
IMAGES[p] = py.transform.scale(py.image.load("images/" + p + ".png"), (SQ_SIZE, SQ_SIZE))

def draw_game_state(screen, game_state, valid_moves, square_selected):
''' Draw the complete chess board with pieces

Keyword arguments:
:param screen       -- the pygame screen
:param game_state   -- the state of the current chess game
'''
draw_squares(screen)
highlight_square(screen, game_state, valid_moves, square_selected)
draw_pieces(screen, game_state)

def draw_squares(screen):
''' Draw the chess board with the alternating two colors

:param screen:          -- the pygame screen
'''
for r in range(DIMENSION):
for c in range(DIMENSION):
color = colors[(r + c) % 2]
py.draw.rect(screen, color, py.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))

def draw_pieces(screen, game_state):
''' Draw the chess pieces onto the board

:param screen:          -- the pygame screen
:param game_state:      -- the current state of the chess game
'''
for r in range(DIMENSION):
for c in range(DIMENSION):
piece = game_state.get_piece(r, c)
if piece is not None and piece != Player.EMPTY:
screen.blit(IMAGES[piece.get_player() + "_" + piece.get_name()],
py.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))

def highlight_square(screen, game_state, valid_moves, square_selected):
if square_selected != () and game_state.is_valid_piece(square_selected[0], square_selected[1]):
row = square_selected[0]
col = square_selected[1]

if (game_state.whose_turn() and game_state.get_piece(row, col).is_player(Player.PLAYER_1)) or \
(not game_state.whose_turn() and game_state.get_piece(row, col).is_player(Player.PLAYER_2)):
# hightlight selected square
s = py.Surface((SQ_SIZE, SQ_SIZE))
s.set_alpha(100)
s.fill(py.Color("blue"))
screen.blit(s, (col * SQ_SIZE, row * SQ_SIZE))

# highlight move squares
s.fill(py.Color("green"))

for move in valid_moves:
screen.blit(s, (move[1] * SQ_SIZE, move[0] * SQ_SIZE))

def main():
# Check for the number of players and the color of the AI
human_player = ""
while True:
try:
number_of_players = input("How many players (1 or 2)?\n")
if int(number_of_players) == 1:
number_of_players = 1
while True:
human_player = input("What color do you want to play (w or b)?\n")
if human_player is "w" or human_player is "b":
break
else:
print("Enter w or b.\n")
break
elif int(number_of_players) == 2:
number_of_players = 2
break
else:
print("Enter 1 or 2.\n")
except ValueError:
print("Enter 1 or 2.")

py.init()
screen = py.display.set_mode((WIDTH, HEIGHT))
clock = py.time.Clock()
game_state = chess_engine.game_state()
running = True
square_selected = ()  # keeps track of the last selected square
player_clicks = []  # keeps track of player clicks (two tuples)
valid_moves = []
game_over = False

ai = ai_engine.chess_ai()
game_state = chess_engine.game_state()
if human_player is 'b':
ai_move = ai.minimax_black(game_state, 3, -100000, 100000, True, Player.PLAYER_1)
game_state.move_piece(ai_move[0], ai_move[1], True)

while running:
for e in py.event.get():
if e.type == py.QUIT:
running = False
elif e.type == py.MOUSEBUTTONDOWN:
if not game_over:
location = py.mouse.get_pos()
col = location[0] // SQ_SIZE
row = location[1] // SQ_SIZE
if square_selected == (row, col):
square_selected = ()
player_clicks = []
else:
square_selected = (row, col)
player_clicks.append(square_selected)
if len(player_clicks) == 2:
# this if is useless right now
if (player_clicks[1][0], player_clicks[1][1]) not in valid_moves:
square_selected = ()
player_clicks = []
valid_moves = []
else:
game_state.move_piece((player_clicks[0][0], player_clicks[0][1]),
(player_clicks[1][0], player_clicks[1][1]), False)
square_selected = ()
player_clicks = []
valid_moves = []

if human_player is 'w':
ai_move = ai.minimax_white(game_state, 3, -100000, 100000, True, Player.PLAYER_2)
game_state.move_piece(ai_move[0], ai_move[1], True)
elif human_player is 'b':
ai_move = ai.minimax_black(game_state, 3, -100000, 100000, True, Player.PLAYER_1)
game_state.move_piece(ai_move[0], ai_move[1], True)
else:
valid_moves = game_state.get_valid_moves((row, col))
if valid_moves is None:
valid_moves = []
elif e.type == py.KEYDOWN:
if e.key == py.K_r:
game_over = False
game_state = chess_engine.game_state()
valid_moves = []
square_selected = ()
player_clicks = []
valid_moves = []
elif e.key == py.K_u:
game_state.undo_move()
print(len(game_state.move_log))

draw_game_state(screen, game_state, valid_moves, square_selected)

endgame = game_state.checkmate_stalemate_checker()
if endgame == 0:
game_over = True
draw_text(screen, "Black wins.")
elif endgame == 1:
game_over = True
draw_text(screen, "White wins.")
elif endgame == 2:
game_over = True
draw_text(screen, "Stalemate.")

clock.tick(MAX_FPS)
py.display.flip()

# elif human_player is 'w':
#     ai = ai_engine.chess_ai()
#     game_state = chess_engine.game_state()
#     valid_moves = []
#     while running:
#         for e in py.event.get():
#             if e.type == py.QUIT:
#                 running = False
#             elif e.type == py.MOUSEBUTTONDOWN:
#                 if not game_over:
#                     location = py.mouse.get_pos()
#                     col = location[0] // SQ_SIZE
#                     row = location[1] // SQ_SIZE
#                     if square_selected == (row, col):
#                         square_selected = ()
#                         player_clicks = []
#                     else:
#                         square_selected = (row, col)
#                         player_clicks.append(square_selected)
#                     if len(player_clicks) == 2:
#                         if (player_clicks[1][0], player_clicks[1][1]) not in valid_moves:
#                             square_selected = ()
#                             player_clicks = []
#                             valid_moves = []
#                         else:
#                             game_state.move_piece((player_clicks[0][0], player_clicks[0][1]),
#                                                   (player_clicks[1][0], player_clicks[1][1]), False)
#                             square_selected = ()
#                             player_clicks = []
#                             valid_moves = []
#
#                             ai_move = ai.minimax(game_state, 3, -100000, 100000, True, Player.PLAYER_2)
#                             game_state.move_piece(ai_move[0], ai_move[1], True)
#                     else:
#                         valid_moves = game_state.get_valid_moves((row, col))
#                         if valid_moves is None:
#                             valid_moves = []
#             elif e.type == py.KEYDOWN:
#                 if e.key == py.K_r:
#                     game_over = False
#                     game_state = chess_engine.game_state()
#                     valid_moves = []
#                     square_selected = ()
#                     player_clicks = []
#                     valid_moves = []
#                 elif e.key == py.K_u:
#                     game_state.undo_move()
#                     print(len(game_state.move_log))
#         draw_game_state(screen, game_state, valid_moves, square_selected)
#
#         endgame = game_state.checkmate_stalemate_checker()
#         if endgame == 0:
#             game_over = True
#             draw_text(screen, "Black wins.")
#         elif endgame == 1:
#             game_over = True
#             draw_text(screen, "White wins.")
#         elif endgame == 2:
#             game_over = True
#             draw_text(screen, "Stalemate.")
#
#         clock.tick(MAX_FPS)
#         py.display.flip()
#
# elif human_player is 'b':
#     pass

def draw_text(screen, text):
font = py.font.SysFont("Helvitca", 32, True, False)
text_object = font.render(text, False, py.Color("Black"))
text_location = py.Rect(0, 0, WIDTH, HEIGHT).move(WIDTH / 2 - text_object.get_width() / 2,
HEIGHT / 2 - text_object.get_height() / 2)
screen.blit(text_object, text_location)

if __name__ == "__main__":
main()
```

## The given code below is a python file for enums.py

```class Player:
PLAYER_1 = 'white'
PLAYER_2 = 'black'
EMPTY = -9
PIECES = ['white_r', 'white_n', 'white_b', 'white_q', 'white_k', 'white_p',
'black_r', 'black_n', 'black_b', 'black_q', 'black_k', 'black_p']
```

## The given code below is a python file for Piece.py

```#
# The Chess piece classes
#
# TODO: add checking if check after moving suggested move later

# General chess piece
from enums import Player

class Piece:
# Initialize the piece
def __init__(self, name, row_number, col_number, player):
self._name = name
self.row_number = row_number
self.col_number = col_number
self._player = player

# Get the x value
def get_row_number(self):
return self.row_number

# Get the y value
def get_col_number(self):
return self.col_number

# Get the name
def get_name(self):
return self._name

def get_player(self):
return self._player

def is_player(self, player_checked):
return self.get_player() == player_checked

def can_move(self, board, starting_square):
pass

def can_take(self, is_check):
pass

def change_row_number(self, new_row_number):
self.row_number = new_row_number

def change_col_number(self, new_col_number):
self.col_number = new_col_number

def get_valid_piece_takes(self, game_state):
pass

def get_valid_peaceful_moves(self, game_state):
pass

# Get moves
def get_valid_piece_moves(self, board):
pass

# Rook (R)
class Rook(Piece):
def __init__(self, name, row_number, col_number, player):
super().__init__(name, row_number, col_number, player)
self.has_moved = False

def get_valid_peaceful_moves(self, game_state):
return self.traverse(game_state)[0]

def get_valid_piece_takes(self, game_state):
return self.traverse(game_state)[1]

def get_valid_piece_moves(self, game_state):
return self.get_valid_peaceful_moves(game_state) + self.get_valid_piece_takes(game_state)

def traverse(self, game_state):
_peaceful_moves = []
_piece_takes = []

self._up = 1
self._down = 1
self._left = 1
self._right = 1

# Left of the Rook
self._breaking_point = False
while self.get_col_number() - self._left >= 0 and not self._breaking_point:
# when the square to the left is empty
if game_state.get_piece(self.get_row_number(), self.get_col_number() - self._left) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number(), self.get_col_number() - self._left))
self._left += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number(), self.get_col_number() - self._left) and \
not game_state.get_piece(self.get_row_number(), self.get_col_number() - self._left).is_player(self.get_player()):
_piece_takes.append((self.get_row_number(), self.get_col_number() - self._left))
self._breaking_point = True
else:
self._breaking_point = True

# Right of the Rook
self._breaking_point = False
while self.get_col_number() + self._right < 8 and not self._breaking_point:
# when the square to the left is empty
if game_state.get_piece(self.get_row_number(), self.get_col_number() + self._right) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number(), self.get_col_number() + self._right))
self._right += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number(), self.get_col_number() + self._right) and \
not game_state.get_piece(self.get_row_number(), self.get_col_number() + self._right).is_player(self.get_player()):
_piece_takes.append((self.get_row_number(), self.get_col_number() + self._right))
self._breaking_point = True
else:
self._breaking_point = True

# Below the Rook
self._breaking_point = False
while self.get_row_number() + self._down < 8 and not self._breaking_point:
# when the square to the left is empty
if game_state.get_piece(self.get_row_number() + self._down, self.get_col_number()) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number() + self._down, self.get_col_number()))
self._down += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number() + self._down, self.get_col_number()) and \
not game_state.get_piece(self.get_row_number() + self._down, self.get_col_number()).is_player(self.get_player()):
_piece_takes.append((self.get_row_number() + self._down, self.get_col_number()))
self._breaking_point = True
else:
self._breaking_point = True

# Above the Rook
self._breaking_point = False
while self.get_row_number() - self._up >= 0 and not self._breaking_point:
# when the square to the left is empty
if game_state.get_piece(self.get_row_number() - self._up, self.get_col_number()) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number() - self._up, self.get_col_number()))
self._up += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number() - self._up, self.get_col_number()) and \
not game_state.get_piece(self.get_row_number() - self._up, self.get_col_number()).is_player(self.get_player()):
_piece_takes.append((self.get_row_number() - self._up, self.get_col_number()))
self._breaking_point = True
else:
self._breaking_point = True
return (_peaceful_moves, _piece_takes)

# Knight (N)
class Knight(Piece):
def get_valid_peaceful_moves(self, game_state):
_moves = []
row_change = [-2, -2, -1, -1, +1, +1, +2, +2]
col_change = [-1, +1, -2, +2, -2, +2, +1, -1]

for i in range(0, 8):
new_row = self.get_row_number() + row_change[i]
new_col = self.get_col_number() + col_change[i]
evaluating_square = game_state.get_piece(new_row, new_col)
# when the square with new_row and new_col is empty
if evaluating_square == Player.EMPTY:
_moves.append((new_row, new_col))
return _moves

def get_valid_piece_takes(self, game_state):
_moves = []
row_change = [-2, -2, -1, -1, +1, +1, +2, +2]
col_change = [-1, +1, -2, +2, -2, +2, +1, -1]

for i in range(0, 8):
new_row = self.get_row_number() + row_change[i]
new_col = self.get_col_number() + col_change[i]
evaluating_square = game_state.get_piece(new_row, new_col)
# when the square with new_row and new_col contains a valid piece and the player is different
if game_state.is_valid_piece(new_row, new_col) and self.get_player() is not evaluating_square.get_player():
_moves.append((new_row, new_col))
return _moves

def get_valid_piece_moves(self, game_state):
# _moves = []# self._moves.clear()
# current_square_row = self.row_number  # The integer row value of the starting square
# current_square_col = self.col_number  # The integer col value of the starting square
#
# row_change = [-2, -2, -1, -1, +1, +1, +2, +2]
# col_change = [-1, +1, -2, +2, -2, +2, +1, -1]
#
# for i in range(0, 8):
#     new_row = current_square_row + row_change[i]
#     new_col = current_square_col + col_change[i]
#     evaluating_square = board.get_piece(new_row, new_col)
#     # when the square with new_row and new_col is empty
#     if evaluating_square == Player.EMPTY:
#         _moves.append((new_row, new_col))
#     # when the square with new_row and new_col contains a valid piece
#     if board.is_valid_piece(new_row, new_col):
#         # when the knight is white and the piece near the king is black
#         if self.is_player(Player.PLAYER_1) and evaluating_square.is_player(Player.PLAYER_2):
#             _moves.append((new_row, new_col))
#         # when the knight is black and the piece near the king is white
#         elif self.is_player(Player.PLAYER_2) and evaluating_square.is_player(Player.PLAYER_1):
#             _moves.append((new_row, new_col))
# return _moves
return self.get_valid_peaceful_moves(game_state) + self.get_valid_piece_takes(game_state)
# Bishop
class Bishop(Piece):
def __init__(self, name, row_number, col_number, player):
super().__init__(name, row_number, col_number, player)

def get_valid_piece_takes(self, game_state):
return self.traverse(game_state)[1]

def get_valid_peaceful_moves(self, game_state):
return self.traverse(game_state)[0]

def get_valid_piece_moves(self, game_state):
return self.get_valid_piece_takes(game_state) + self.get_valid_peaceful_moves(game_state)

def traverse(self, game_state):
_peaceful_moves = []
_piece_takes = []

self._breaking_point = False
self._up = 1
self._down = 1
self._left = 1
self._right = 1
while self.get_col_number() - self._left >= 0 and self.get_row_number() - self._up >= 0 and not self._breaking_point:
# when the square is empty
if game_state.get_piece(self.get_row_number() - self._up, self.get_col_number() - self._left) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number() - self._up, self.get_col_number() - self._left))
self._left += 1
self._up += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number() - self._up, self.get_col_number() - self._left) and \
not game_state.get_piece(self.get_row_number() - self._up, self.get_col_number() - self._left).is_player(self.get_player()):
_piece_takes.append((self.get_row_number() - self._up, self.get_col_number() - self._left))
self._breaking_point = True
else:
self._breaking_point = True

# Right up of the bishop
self._breaking_point = False
self._up = 1
self._down = 1
self._left = 1
self._right = 1
while self.get_col_number() + self._right < 8 and self.get_row_number() - self._up >= 0 and not self._breaking_point:
# when the square is empty
if game_state.get_piece(self.get_row_number() - self._up, self.get_col_number() + self._right) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number() - self._up, self.get_col_number() + self._right))
self._right += 1
self._up += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number() - self._up, self.get_col_number() + self._right) and \
not game_state.get_piece(self.get_row_number() - self._up, self.get_col_number() + self._right).is_player(self.get_player()):
_piece_takes.append((self.get_row_number() - self._up, self.get_col_number() + self._right))
self._breaking_point = True
else:
self._breaking_point = True

# Down left of the bishop
self._breaking_point = False
self._up = 1
self._down = 1
self._left = 1
self._right = 1
while self.get_col_number() - self._left >= 0 and self.get_row_number() + self._down < 8 and not self._breaking_point:
# when the square is empty
if game_state.get_piece(self.get_row_number() + self._down, self.get_col_number() - self._left) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number() + self._down, self.get_col_number() - self._left))
self._down += 1
self._left += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number() + self._down, self.get_col_number() - self._left) and \
not game_state.get_piece(self.get_row_number() + self._down, self.get_col_number() - self._left).is_player(self.get_player()):
_piece_takes.append((self.get_row_number() + self._down, self.get_col_number() - self._left))
self._breaking_point = True
else:
self._breaking_point = True

# Down right of the bishop
self._breaking_point = False
self._up = 1
self._down = 1
self._left = 1
self._right = 1
while self.get_col_number() + self._right < 8 and self.get_row_number() + self._down < 8 and not self._breaking_point:
# when the square is empty
if game_state.get_piece(self.get_row_number() + self._down, self.get_col_number() + self._right) is Player.EMPTY:
_peaceful_moves.append((self.get_row_number() + self._down, self.get_col_number() + self._right))
self._down += 1
self._right += 1
# when the square contains an opposing piece
elif game_state.is_valid_piece(self.get_row_number() + self._down, self.get_col_number() + self._right) and \
not game_state.get_piece(self.get_row_number() + self._down, self.get_col_number() + self._right).is_player(
self.get_player()):
_piece_takes.append((self.get_row_number() + self._down, self.get_col_number() + self._right))
self._breaking_point = True
else:
self._breaking_point = True
return (_peaceful_moves, _piece_takes)

# Pawn
class Pawn(Piece):
def get_valid_piece_takes(self, game_state):
_moves = []
if self.is_player(Player.PLAYER_1):
# when the square to the bottom left of the starting_square has a black piece
if game_state.is_valid_piece(self.get_row_number() + 1, self.get_col_number() - 1) and \
game_state.get_piece(self.get_row_number() + 1, self.get_col_number() - 1).is_player(Player.PLAYER_2):
_moves.append((self.get_row_number() + 1, self.get_col_number() - 1))
# when the square to the bottom right of the starting_square has a black piece
if game_state.is_valid_piece(self.get_row_number() + 1, self.get_col_number() + 1) and \
game_state.get_piece(self.get_row_number() + 1, self.get_col_number() + 1).is_player(Player.PLAYER_2):
_moves.append((self.get_row_number() + 1, self.get_col_number() + 1))
if game_state.can_en_passant(self.get_row_number(), self.get_col_number()):
_moves.append((self.get_row_number() + 1, game_state.previous_piece_en_passant()[1]))
# when the pawn is a black piece
elif self.is_player(Player.PLAYER_2):
# when the square to the top left of the starting_square has a white piece
if game_state.is_valid_piece(self.get_row_number() - 1, self.get_col_number() - 1) and \
game_state.get_piece(self.get_row_number() - 1, self.get_col_number() - 1).is_player(Player.PLAYER_1):
_moves.append((self.get_row_number() - 1, self.get_col_number() - 1))
# when the square to the top right of the starting_square has a white piece
if game_state.is_valid_piece(self.get_row_number() - 1, self.get_col_number() + 1) and \
game_state.get_piece(self.get_row_number() - 1, self.get_col_number() + 1).is_player(Player.PLAYER_1):
_moves.append((self.get_row_number() - 1, self.get_col_number() + 1))
if game_state.can_en_passant(self.get_row_number(), self.get_col_number()):
_moves.append((self.get_row_number() - 1, game_state.previous_piece_en_passant()[1]))
return _moves

def get_valid_peaceful_moves(self, game_state):
_moves = []
# when the pawn is a white piece
if self.is_player(Player.PLAYER_1):
# when the square right below the starting_square is empty
if game_state.get_piece(self.get_row_number() + 1, self.get_col_number()) == Player.EMPTY:
# when the pawn has not been moved yet
if self.get_row_number() == 1 and game_state.get_piece(self.get_row_number() + 2,
self.get_col_number()) == Player.EMPTY:
_moves.append((self.get_row_number() + 1, self.get_col_number()))
_moves.append((self.get_row_number() + 2, self.get_col_number()))
# when the pawn has already been moved
else:
_moves.append((self.get_row_number() + 1, self.get_col_number()))
# when the pawn is a black piece
elif self.is_player(Player.PLAYER_2):
# when the square right above is empty
if game_state.get_piece(self.get_row_number() - 1, self.get_col_number()) == Player.EMPTY:
# when the pawn has not been moved yet
if self.get_row_number() == 6 and game_state.get_piece(self.get_row_number() - 2,
self.get_col_number()) == Player.EMPTY:
_moves.append((self.get_row_number() - 1, self.get_col_number()))
_moves.append((self.get_row_number() - 2, self.get_col_number()))
# when the pawn has been moved
else:
_moves.append((self.get_row_number() - 1, self.get_col_number()))
return _moves

def get_valid_piece_moves(self, game_state):
# current_square_row = self.row_number  # The integer row value of the starting square
# current_square_col = self.col_number  # The integer col value of the starting square
#
# _moves = []# self._moves.clear()
# # when the pawn is a white piece
# if self.is_player(Player.PLAYER_1):
#     # when the square right below the starting_square is empty
#     if game_state.get_piece(current_square_row + 1, current_square_col) == Player.EMPTY:
#         # when the pawn has not been moved yet
#         if self.get_row_number() == 1 and game_state.get_piece(current_square_row +2, current_square_col) == Player.EMPTY:
#             _moves.append((current_square_row + 1, current_square_col))
#             _moves.append((current_square_row + 2, current_square_col))
#         # when the pawn has already been moved
#         else:
#             _moves.append((current_square_row + 1, current_square_col))
#     # when the square to the bottom left of the starting_square has a black piece
#     if game_state.is_valid_piece(current_square_row + 1, current_square_col - 1) and \
#             game_state.get_piece(current_square_row + 1, current_square_col - 1).is_player(Player.PLAYER_2):
#         _moves.append((current_square_row + 1, current_square_col - 1))
#     # when the square to the bottom right of the starting_square has a black piece
#     if game_state.is_valid_piece(current_square_row + 1, current_square_col + 1) and \
#             game_state.get_piece(current_square_row + 1, current_square_col + 1).is_player(Player.PLAYER_2):
#         _moves.append((current_square_row + 1, current_square_col + 1))
#     if game_state.can_en_passant(current_square_row, current_square_col):
#         _moves.append((current_square_row + 1, game_state.previous_piece_en_passant()[1]))
# # when the pawn is a black piece
# elif self.is_player(Player.PLAYER_2):
#     # when the square right above is empty
#     if game_state.get_piece(current_square_row - 1, current_square_col) == Player.EMPTY:
#         # when the pawn has not been moved yet
#         if self.get_row_number() == 6 and game_state.get_piece(current_square_row -2, current_square_col) == Player.EMPTY:
#             _moves.append((current_square_row - 1, current_square_col))
#             _moves.append((current_square_row - 2, current_square_col))
#         # when the pawn has been moved
#         else:
#             _moves.append((current_square_row - 1, current_square_col))
#     # when the square to the top left of the starting_square has a white piece
#     if game_state.is_valid_piece(current_square_row - 1, current_square_col - 1) and \
#             game_state.get_piece(current_square_row - 1, current_square_col - 1).is_player(Player.PLAYER_1):
#         _moves.append((current_square_row - 1, current_square_col - 1))
#     # when the square to the top right of the starting_square has a white piece
#     if game_state.is_valid_piece(current_square_row - 1, current_square_col + 1) and \
#             game_state.get_piece(current_square_row - 1, current_square_col + 1).is_player(Player.PLAYER_1):
#         _moves.append((current_square_row - 1, current_square_col + 1))
#     if game_state.can_en_passant(current_square_row, current_square_col):
#         _moves.append((current_square_row - 1, game_state.previous_piece_en_passant()[1]))
# return _moves
return self.get_valid_peaceful_moves(game_state) + self.get_valid_piece_takes(game_state)

# Queen
class Queen(Rook, Bishop):
def get_valid_peaceful_moves(self, game_state):
return (Rook.get_valid_peaceful_moves(Rook(self.get_name(), self.get_row_number(), self.get_col_number(), self.get_player()), game_state) +
Bishop.get_valid_peaceful_moves(Bishop(self.get_name(), self.get_row_number(), self.get_col_number(), self.get_player()), game_state))

def get_valid_piece_takes(self, game_state):
return (Rook.get_valid_piece_takes( Rook(self.get_name(), self.get_row_number(), self.get_col_number(), self.get_player()), game_state) +
Bishop.get_valid_piece_takes(Bishop(self.get_name(), self.get_row_number(), self.get_col_number(), self.get_player()), game_state))

def get_valid_piece_moves(self, game_state):
return (Rook.get_valid_piece_moves(Rook(self.get_name(), self.get_row_number(), self.get_col_number(), self.get_player()), game_state) +
Bishop.get_valid_piece_moves(Bishop(self.get_name(), self.get_row_number(), self.get_col_number(), self.get_player()), game_state))

# King
class King(Piece):
def get_valid_piece_takes(self, game_state):
_moves = []
row_change = [-1, +0, +1, -1, +1, -1, +0, +1]
col_change = [-1, -1, -1, +0, +0, +1, +1, +1]

for i in range(0, 8):
new_row = self.get_row_number() + row_change[i]
new_col = self.get_col_number() + col_change[i]
evaluating_square = game_state.get_piece(new_row, new_col)
# when the square with new_row and new_col contains a valid piece
if game_state.is_valid_piece(new_row, new_col):
# when the king is white and the piece near the king is black
if self.is_player(Player.PLAYER_1) and evaluating_square.is_player(Player.PLAYER_2):
_moves.append((new_row, new_col))
# when the king is black and the piece near the king is white
elif self.is_player(Player.PLAYER_2) and evaluating_square.is_player(Player.PLAYER_1):
_moves.append((new_row, new_col))
return _moves

def get_valid_peaceful_moves(self, game_state):
_moves = []
row_change = [-1, +0, +1, -1, +1, -1, +0, +1]
col_change = [-1, -1, -1, +0, +0, +1, +1, +1]

for i in range(0, 8):
new_row = self.get_row_number() + row_change[i]
new_col = self.get_col_number() + col_change[i]
evaluating_square = game_state.get_piece(new_row, new_col)
# when the square with new_row and new_col is empty
if evaluating_square == Player.EMPTY:
_moves.append((new_row, new_col))

if game_state.king_can_castle_left(self.get_player()):
if self.is_player(Player.PLAYER_1):
_moves.append((0, 1))
elif self.is_player(Player.PLAYER_2):
_moves.append((7, 1))
elif game_state.king_can_castle_right(self.get_player()):
if self.is_player(Player.PLAYER_1):
_moves.append((0, 5))
elif self.is_player(Player.PLAYER_2):
_moves.append((7, 5))
return _moves

def get_valid_piece_moves(self, game_state):
# _moves = []
# current_square_row = self.row_number  # The integer row value of the starting square
# current_square_col = self.col_number  # The integer col value of the starting square
#
# row_change = [-1, +0, +1, -1, +1, -1, +0, +1]
# col_change = [-1, -1, -1, +0, +0, +1, +1, +1]
# for i in range(0, 8):
#     new_row = current_square_row + row_change[i]
#     new_col = current_square_col + col_change[i]
#     evaluating_square = game_state.get_piece(new_row, new_col)
#     # when the square with new_row and new_col is empty
#     if evaluating_square == Player.EMPTY:
#         _moves.append((new_row, new_col))
#     # when the square with new_row and new_col contains a valid piece
#     if game_state.is_valid_piece(new_row, new_col):
#         # when the king is white and the piece near the king is black
#         if self.is_player(Player.PLAYER_1) and evaluating_square.is_player(Player.PLAYER_2):
#             _moves.append((new_row, new_col))
#         # when the king is black and the piece near the king is white
#         elif self.is_player(Player.PLAYER_2) and evaluating_square.is_player(Player.PLAYER_1):
#             _moves.append((new_row, new_col))
#
# if game_state.king_can_castle_left(self.get_player()):
#     if self.is_player(Player.PLAYER_1):
#         _moves.append((0, 1))
#     elif self.is_player(Player.PLAYER_2):
#         _moves.append((7, 1))
# elif game_state.king_can_castle_right(self.get_player()):
#     if self.is_player(Player.PLAYER_1):
#         _moves.append((0, 5))
#     elif self.is_player(Player.PLAYER_2):
#         _moves.append((7, 5))
# return _moves
return self.get_valid_peaceful_moves(game_state) + self.get_valid_piece_takes(game_state)
```

## The given code below is a python file for chess_engine.py

```#
# The Chess Board class
# Will store the state of the chess game, print the chess board, find valid moves, store move logs.
#
# Note: move log class inspired by Eddie Sharick
#
from Piece import Rook, Knight, Bishop, Queen, King, Pawn
from enums import Player

'''
r \ c     0           1           2           3           4           5           6           7
0   [(r=0, c=0), (r=0, c=1), (r=0, c=2), (r=0, c=3), (r=0, c=4), (r=0, c=5), (r=0, c=6), (r=0, c=7)]
1   [(r=1, c=0), (r=1, c=1), (r=1, c=2), (r=1, c=3), (r=1, c=4), (r=1, c=5), (r=1, c=6), (r=1, c=7)]
2   [(r=2, c=0), (r=2, c=1), (r=2, c=2), (r=2, c=3), (r=2, c=4), (r=2, c=5), (r=2, c=6), (r=2, c=7)]
3   [(r=3, c=0), (r=3, c=1), (r=3, c=2), (r=3, c=3), (r=3, c=4), (r=3, c=5), (r=3, c=6), (r=3, c=7)]
4   [(r=4, c=0), (r=4, c=1), (r=4, c=2), (r=4, c=3), (r=4, c=4), (r=4, c=5), (r=4, c=6), (r=4, c=7)]
5   [(r=5, c=0), (r=5, c=1), (r=5, c=2), (r=5, c=3), (r=5, c=4), (r=5, c=5), (r=5, c=6), (r=5, c=7)]
6   [(r=6, c=0), (r=6, c=1), (r=6, c=2), (r=6, c=3), (r=6, c=4), (r=6, c=5), (r=6, c=6), (r=6, c=7)]
7   [(r=7, c=0), (r=7, c=1), (r=7, c=2), (r=7, c=3), (r=7, c=4), (r=7, c=5), (r=7, c=6), (r=7, c=7)]
'''

# TODO: Flip the board according to the player
# TODO: Pawns are usually indicated by no letters
# TODO: stalemate
# TODO: move logs - fix king castle boolean update
# TODO: change move method argument about is_ai into something more elegant
class game_state:
# Initialize 2D array to represent the chess board
def __init__(self):
# The board is a 2D array
# TODO: Change to a numpy format later
self.white_captives = []
self.black_captives = []
self.move_log = []
self.white_turn = True
self.can_en_passant_bool = False
self._en_passant_previous = (-1, -1)
self.checkmate = False
self.stalemate = False

self._is_check = False
self._white_king_location = [0, 3]
self._black_king_location = [7, 3]

self.white_king_can_castle = [True, True,
True]  # Has king not moved, has Rook1(col=0) not moved, has Rook2(col=7) not moved
self.black_king_can_castle = [True, True, True]

# Initialize White pieces
white_rook_1 = Rook('r', 0, 0, Player.PLAYER_1)
white_rook_2 = Rook('r', 0, 7, Player.PLAYER_1)
white_knight_1 = Knight('n', 0, 1, Player.PLAYER_1)
white_knight_2 = Knight('n', 0, 6, Player.PLAYER_1)
white_bishop_1 = Bishop('b', 0, 2, Player.PLAYER_1)
white_bishop_2 = Bishop('b', 0, 5, Player.PLAYER_1)
white_queen = Queen('q', 0, 4, Player.PLAYER_1)
white_king = King('k', 0, 3, Player.PLAYER_1)
white_pawn_1 = Pawn('p', 1, 0, Player.PLAYER_1)
white_pawn_2 = Pawn('p', 1, 1, Player.PLAYER_1)
white_pawn_3 = Pawn('p', 1, 2, Player.PLAYER_1)
white_pawn_4 = Pawn('p', 1, 3, Player.PLAYER_1)
white_pawn_5 = Pawn('p', 1, 4, Player.PLAYER_1)
white_pawn_6 = Pawn('p', 1, 5, Player.PLAYER_1)
white_pawn_7 = Pawn('p', 1, 6, Player.PLAYER_1)
white_pawn_8 = Pawn('p', 1, 7, Player.PLAYER_1)
self.white_pieces = [white_rook_1, white_rook_2, white_knight_1, white_knight_2, white_bishop_1, white_bishop_2,
white_queen, white_king, white_pawn_1, white_pawn_2, white_pawn_3, white_pawn_4,
white_pawn_5,
white_pawn_6, white_pawn_7, white_pawn_8]

# Initialize Black Pieces
black_rook_1 = Rook('r', 7, 0, Player.PLAYER_2)
black_rook_2 = Rook('r', 7, 7, Player.PLAYER_2)
black_knight_1 = Knight('n', 7, 1, Player.PLAYER_2)
black_knight_2 = Knight('n', 7, 6, Player.PLAYER_2)
black_bishop_1 = Bishop('b', 7, 2, Player.PLAYER_2)
black_bishop_2 = Bishop('b', 7, 5, Player.PLAYER_2)
black_queen = Queen('q', 7, 4, Player.PLAYER_2)
black_king = King('k', 7, 3, Player.PLAYER_2)
black_pawn_1 = Pawn('p', 6, 0, Player.PLAYER_2)
black_pawn_2 = Pawn('p', 6, 1, Player.PLAYER_2)
black_pawn_3 = Pawn('p', 6, 2, Player.PLAYER_2)
black_pawn_4 = Pawn('p', 6, 3, Player.PLAYER_2)
black_pawn_5 = Pawn('p', 6, 4, Player.PLAYER_2)
black_pawn_6 = Pawn('p', 6, 5, Player.PLAYER_2)
black_pawn_7 = Pawn('p', 6, 6, Player.PLAYER_2)
black_pawn_8 = Pawn('p', 6, 7, Player.PLAYER_2)
self.black_pieces = [black_rook_1, black_rook_2, black_knight_1, black_knight_2, black_bishop_1, black_bishop_2,
black_queen, black_king, black_pawn_1, black_pawn_2, black_pawn_3, black_pawn_4,
black_pawn_5,
black_pawn_6, black_pawn_7, black_pawn_8]

self.board = [
[white_rook_1, white_knight_1, white_bishop_1, white_king, white_queen, white_bishop_2, white_knight_2,
white_rook_2],
[white_pawn_1, white_pawn_2, white_pawn_3, white_pawn_4, white_pawn_5, white_pawn_6, white_pawn_7,
white_pawn_8],
[Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY,
Player.EMPTY],
[Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY,
Player.EMPTY],
[Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY,
Player.EMPTY],
[Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY, Player.EMPTY,
Player.EMPTY],
[black_pawn_1, black_pawn_2, black_pawn_3, black_pawn_4, black_pawn_5, black_pawn_6, black_pawn_7,
black_pawn_8],
[black_rook_1, black_knight_1, black_bishop_1, black_king, black_queen, black_bishop_2, black_knight_2,
black_rook_2]
]

def get_piece(self, row, col):
if (0 <= row < 8) and (0 <= col < 8):
return self.board[row][col]

def is_valid_piece(self, row, col):
evaluated_piece = self.get_piece(row, col)
return (evaluated_piece is not None) and (evaluated_piece != Player.EMPTY)

def get_valid_moves(self, starting_square):
'''
remove pins from valid moves (unless the pinned piece move can get rid of a check and checks is empty
remove move from valid moves if the move falls within a check piece's valid move
if the moving piece is a king, the ending square cannot be in a check
'''

current_row = starting_square[0]
current_col = starting_square[1]

if self.is_valid_piece(current_row, current_col):
valid_moves = []
moving_piece = self.get_piece(current_row, current_col)
if self.get_piece(current_row, current_col).is_player(Player.PLAYER_1):
king_location = self._white_king_location
else:
king_location = self._black_king_location
group = self.check_for_check(king_location, moving_piece.get_player())
checking_pieces = group[0]
pinned_pieces = group[1]
pinned_checks = group[2]
initial_valid_piece_moves = moving_piece.get_valid_piece_moves(self)

# immediate check
if checking_pieces:
for move in initial_valid_piece_moves:
can_move = True
for piece in checking_pieces:
if moving_piece.get_name() is "k":
temp = self.board[current_row][current_col]
self.board[current_row][current_col] = Player.EMPTY
temp2 = self.board[move[0]][move[1]]
self.board[move[0]][move[1]] = temp
if not self.check_for_check(move, moving_piece.get_player())[0]:
pass
else:
can_move = False
self.board[current_row][current_col] = temp
self.board[move[0]][move[1]] = temp2
elif move == piece and len(checking_pieces) == 1 and moving_piece.get_name() is not "k" and \
(current_row, current_col) not in pinned_pieces:
pass
elif move != piece and len(checking_pieces) == 1 and moving_piece.get_name() is not "k" and \
(current_row, current_col) not in pinned_pieces:
temp = self.board[move[0]][move[1]]
self.board[move[0]][move[1]] = moving_piece
self.board[current_row][current_col] = Player.EMPTY
if self.check_for_check(king_location, moving_piece.get_player())[0]:
can_move = False
self.board[current_row][current_col] = moving_piece
self.board[move[0]][move[1]] = temp
else:
can_move = False
if can_move:
valid_moves.append(move)
self._is_check = True
# pinned checks
elif pinned_pieces and moving_piece.get_name() is not "k":
if starting_square not in pinned_pieces:
for move in initial_valid_piece_moves:
valid_moves.append(move)
elif starting_square in pinned_pieces:
for move in initial_valid_piece_moves:

temp = self.board[move[0]][move[1]]
self.board[move[0]][move[1]] = moving_piece
self.board[current_row][current_col] = Player.EMPTY
if not self.check_for_check(king_location, moving_piece.get_player())[0]:
valid_moves.append(move)
self.board[current_row][current_col] = moving_piece
self.board[move[0]][move[1]] = temp
else:
if moving_piece.get_name() is "k":
for move in initial_valid_piece_moves:
temp = self.board[current_row][current_col]
temp2 = self.board[move[0]][move[1]]
self.board[current_row][current_col] = Player.EMPTY
self.board[move[0]][move[1]] = temp
if not self.check_for_check(move, moving_piece.get_player())[0]:
valid_moves.append(move)
self.board[current_row][current_col] = temp
self.board[move[0]][move[1]] = temp2
else:
for move in initial_valid_piece_moves:
valid_moves.append(move)
# if not valid_moves:
#     if self._is_check:
#         self.checkmate = True
#     else:
#         self.stalemate = True
# else:
#     self.checkmate = False
#     self.stalemate = False
return valid_moves
else:
return None

# 0 if white lost, 1 if black lost, 2 if stalemate, 3 if not game over
def checkmate_stalemate_checker(self):
all_white_moves = self.get_all_legal_moves(Player.PLAYER_1)
all_black_moves = self.get_all_legal_moves(Player.PLAYER_2)
if self._is_check and self.whose_turn() and not all_white_moves:
print("white lost")
return 0
elif self._is_check and not self.whose_turn() and not all_black_moves:
print("black lost")
return 1
elif not all_white_moves and not all_black_moves:
return 2
else:
return 3

def get_all_legal_moves(self, player):
# _all_valid_moves = [[], []]
# for row in range(0, 8):
#     for col in range(0, 8):
#         if self.is_valid_piece(row, col) and self.get_piece(row, col).is_player(player):
#             valid_moves = self.get_valid_moves((row, col))
#             if valid_moves:
#                 _all_valid_moves[0].append((row, col))
#                 _all_valid_moves[1].append(valid_moves)
_all_valid_moves = []
for row in range(0, 8):
for col in range(0, 8):
if self.is_valid_piece(row, col) and self.get_piece(row, col).is_player(player):
valid_moves = self.get_valid_moves((row, col))
for move in valid_moves:
_all_valid_moves.append(((row, col), move))
return _all_valid_moves

def king_can_castle_left(self, player):
if player is Player.PLAYER_1:
return self.white_king_can_castle[0] and self.white_king_can_castle[1] and \
self.get_piece(0, 1) is Player.EMPTY and self.get_piece(0, 2) is Player.EMPTY and not self._is_check
else:
return self.black_king_can_castle[0] and self.black_king_can_castle[1] and \
self.get_piece(7, 1) is Player.EMPTY and self.get_piece(7, 2) is Player.EMPTY and not self._is_check

def king_can_castle_right(self, player):
if player is Player.PLAYER_1:
return self.white_king_can_castle[0] and self.white_king_can_castle[2] and \
self.get_piece(0, 6) is Player.EMPTY and self.get_piece(0, 5) is Player.EMPTY and not self._is_check
else:
return self.black_king_can_castle[0] and self.black_king_can_castle[2] and \
self.get_piece(7, 6) is Player.EMPTY and self.get_piece(7, 5) is Player.EMPTY and not self._is_check

def promote_pawn(self, starting_square, moved_piece, ending_square):
while True:
new_piece_name = input("Change pawn to (r, n, b, q):\n")
piece_classes = {"r": Rook, "n": Knight, "b": Bishop, "q": Queen}
if new_piece_name in piece_classes:
move = chess_move(starting_square, ending_square, self, self._is_check)

new_piece = piece_classes[new_piece_name](new_piece_name, ending_square[0],
ending_square[1], moved_piece.get_player())
self.board[ending_square[0]][ending_square[1]] = new_piece
self.board[moved_piece.get_row_number()][moved_piece.get_col_number()] = Player.EMPTY
moved_piece.change_row_number(ending_square[0])
moved_piece.change_col_number(ending_square[1])
move.pawn_promotion_move(new_piece)
self.move_log.append(move)
break
else:
print("Please choose from these four: r, n, b, q.\n")

def promote_pawn_ai(self, starting_square, moved_piece, ending_square):
move = chess_move(starting_square, ending_square, self, self._is_check)
# The ai can only promote the pawn to queen
new_piece = Queen("q", ending_square[0], ending_square[1], moved_piece.get_player())
self.board[ending_square[0]][ending_square[1]] = new_piece
self.board[moved_piece.get_row_number()][moved_piece.get_col_number()] = Player.EMPTY
moved_piece.change_row_number(ending_square[0])
moved_piece.change_col_number(ending_square[1])
move.pawn_promotion_move(new_piece)
self.move_log.append(move)

# have to fix en passant for ai
def can_en_passant(self, current_square_row, current_square_col):
return False
# if is_ai:
#     return False
# else:
#     return self.can_en_passant_bool and current_square_row == self.previous_piece_en_passant()[0] \
#            and abs(current_square_col - self.previous_piece_en_passant()[1]) == 1

def previous_piece_en_passant(self):
return self._en_passant_previous

# Move a piece
def move_piece(self, starting_square, ending_square, is_ai):
current_square_row = starting_square[0]  # The integer row value of the starting square
current_square_col = starting_square[1]  # The integer col value of the starting square
next_square_row = ending_square[0]  # The integer row value of the ending square
next_square_col = ending_square[1]  # The integer col value of the ending square

if self.is_valid_piece(current_square_row, current_square_col) and \
(((self.whose_turn() and self.get_piece(current_square_row, current_square_col).is_player(
Player.PLAYER_1)) or
(not self.whose_turn() and self.get_piece(current_square_row, current_square_col).is_player(
Player.PLAYER_2)))):

# The chess piece at the starting square
moving_piece = self.get_piece(current_square_row, current_square_col)

valid_moves = self.get_valid_moves(starting_square)

temp = True

if ending_square in valid_moves:
moved_to_piece = self.get_piece(next_square_row, next_square_col)
if moving_piece.get_name() is "k":
if moving_piece.is_player(Player.PLAYER_1):
if moved_to_piece == Player.EMPTY and next_square_col == 1 and self.king_can_castle_left(
moving_piece.get_player()):
move = chess_move(starting_square, ending_square, self, self._is_check)
move.castling_move((0, 0), (0, 2), self)
self.move_log.append(move)

# move rook
self.get_piece(0, 0).change_col_number(2)

self.board[0][2] = self.board[0][0]
self.board[0][0] = Player.EMPTY

self.white_king_can_castle[0] = False
self.white_king_can_castle[1] = False

elif moved_to_piece == Player.EMPTY and next_square_col == 5 and self.king_can_castle_right(
moving_piece.get_player()):
move = chess_move(starting_square, ending_square, self, self._is_check)
move.castling_move((0, 7), (0, 4), self)
self.move_log.append(move)
# move rook
self.get_piece(0, 7).change_col_number(4)

self.board[0][4] = self.board[0][7]
self.board[0][7] = Player.EMPTY

self.white_king_can_castle[0] = False
self.white_king_can_castle[2] = False
else:
move = chess_move(starting_square, ending_square, self, self._is_check)
self.move_log.append(move)
self.white_king_can_castle[0] = False
self._white_king_location = (next_square_row, next_square_col)
else:
if moved_to_piece == Player.EMPTY and next_square_col == 1 and self.king_can_castle_left(
moving_piece.get_player()):
move = chess_move(starting_square, ending_square, self, self._is_check)
move.castling_move((7, 0), (7, 2), self)
self.move_log.append(move)

self.get_piece(7, 0).change_col_number(2)
# move rook
self.board[7][2] = self.board[7][0]
self.board[7][0] = Player.EMPTY

self.black_king_can_castle[0] = False
self.black_king_can_castle[1] = False
elif moved_to_piece == Player.EMPTY and next_square_col == 5 and self.king_can_castle_right(
moving_piece.get_player()):
move = chess_move(starting_square, ending_square, self, self._is_check)
move.castling_move((7, 7), (7, 4), self)
self.move_log.append(move)

self.get_piece(0, 7).change_col_number(4)

# move rook
self.board[7][4] = self.board[7][7]
self.board[7][7] = Player.EMPTY

self.black_king_can_castle[0] = False
self.black_king_can_castle[2] = False
else:
move = chess_move(starting_square, ending_square, self, self._is_check)
self.move_log.append(move)
self.black_king_can_castle[0] = False
self._black_king_location = (next_square_row, next_square_col)
# self.can_en_passant_bool = False  WHAT IS THIS
elif moving_piece.get_name() is "r":
if moving_piece.is_player(Player.PLAYER_1) and current_square_col == 0:
self.white_king_can_castle[1] = False
elif moving_piece.is_player(Player.PLAYER_1) and current_square_col == 7:
self.white_king_can_castle[2] = False
elif moving_piece.is_player(Player.PLAYER_2) and current_square_col == 0:
self.white_king_can_castle[1] = False
elif moving_piece.is_player(Player.PLAYER_2) and current_square_col == 7:
self.white_king_can_castle[2] = False
self.move_log.append(chess_move(starting_square, ending_square, self, self._is_check))
self.can_en_passant_bool = False
elif moving_piece.get_name() is "p":
# Promoting white pawn
if moving_piece.is_player(Player.PLAYER_1) and next_square_row == 7:
# print("promoting white pawn")
if is_ai:
self.promote_pawn_ai(starting_square, moving_piece, ending_square)
else:
self.promote_pawn(starting_square, moving_piece, ending_square)
temp = False
# Promoting black pawn
elif moving_piece.is_player(Player.PLAYER_2) and next_square_row == 0:
# print("promoting black pawn")
if is_ai:
self.promote_pawn_ai(starting_square, moving_piece, ending_square)
else:
self.promote_pawn(starting_square, moving_piece, ending_square)
temp = False
# Moving pawn forward by two
# Problem with Pawn en passant ai
elif abs(next_square_row - current_square_row) == 2 and current_square_col == next_square_col:
# print("move pawn forward")
self.move_log.append(chess_move(starting_square, ending_square, self, self._is_check))
# self.can_en_passant_bool = True
self._en_passant_previous = (next_square_row, next_square_col)
# en passant
elif abs(next_square_row - current_square_row) == 1 and abs(
current_square_col - next_square_col) == 1 and \
self.can_en_passant(current_square_row, current_square_col):
# print("en passant")
if moving_piece.is_player(Player.PLAYER_1):
move = chess_move(starting_square, ending_square, self, self._is_check)
move.en_passant_move(self.board[next_square_row - 1][next_square_col],
(next_square_row - 1, next_square_col))
self.move_log.append(move)
self.board[next_square_row - 1][next_square_col] = Player.EMPTY
else:
move = chess_move(starting_square, ending_square, self, self._is_check)
move.en_passant_move(self.board[next_square_row + 1][next_square_col],
(next_square_row + 1, next_square_col))
self.move_log.append(move)
self.board[next_square_row + 1][next_square_col] = Player.EMPTY
# moving forward by one or taking a piece
else:
self.move_log.append(chess_move(starting_square, ending_square, self, self._is_check))
self.can_en_passant_bool = False
else:
self.move_log.append(chess_move(starting_square, ending_square, self, self._is_check))
self.can_en_passant_bool = False

if temp:
moving_piece.change_row_number(next_square_row)
moving_piece.change_col_number(next_square_col)
self.board[next_square_row][next_square_col] = self.board[current_square_row][current_square_col]
self.board[current_square_row][current_square_col] = Player.EMPTY

self.white_turn = not self.white_turn

else:
pass

def undo_move(self):
if self.move_log:
undoing_move = self.move_log.pop()
if undoing_move.castled is True:
self.board[undoing_move.starting_square_row][
undoing_move.starting_square_col] = undoing_move.moving_piece
self.board[undoing_move.ending_square_row][undoing_move.ending_square_col] = undoing_move.removed_piece
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_row_number(
undoing_move.starting_square_row)
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_col_number(
undoing_move.starting_square_col)

self.board[undoing_move.rook_starting_square[0]][
undoing_move.rook_starting_square[1]] = undoing_move.moving_rook
self.board[undoing_move.rook_ending_square[0]][undoing_move.rook_ending_square[1]] = Player.EMPTY
undoing_move.moving_rook.change_row_number(undoing_move.rook_starting_square[0])
undoing_move.moving_rook.change_col_number(undoing_move.rook_starting_square[1])
if undoing_move.moving_piece is Player.PLAYER_1:
if undoing_move.rook_starting_square[1] == 0:
self.white_king_can_castle[0] = True
self.white_king_can_castle[1] = True
elif undoing_move.rook_starting_square[1] == 7:
self.white_king_can_castle[0] = True
self.white_king_can_castle[2] = True
else:
if undoing_move.rook_starting_square[1] == 0:
self.black_king_can_castle[0] = True
self.black_king_can_castle[1] = True
elif undoing_move.rook_starting_square[1] == 7:
self.black_king_can_castle[0] = True
self.black_king_can_castle[2] = True
elif undoing_move.pawn_promoted is True:
self.board[undoing_move.starting_square_row][
undoing_move.starting_square_col] = undoing_move.moving_piece
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_row_number(
undoing_move.starting_square_row)
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_col_number(
undoing_move.starting_square_col)

self.board[undoing_move.ending_square_row][undoing_move.ending_square_col] = undoing_move.removed_piece
if undoing_move.removed_piece != Player.EMPTY:
self.get_piece(undoing_move.ending_square_row, undoing_move.ending_square_col).change_row_number(
undoing_move.ending_square_row)
self.get_piece(undoing_move.ending_square_row, undoing_move.ending_square_col).change_col_number(
undoing_move.ending_square_col)
elif undoing_move.en_passaned is True:
self.board[undoing_move.starting_square_row][
undoing_move.starting_square_col] = undoing_move.moving_piece
self.board[undoing_move.ending_square_row][undoing_move.ending_square_col] = undoing_move.removed_piece
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_row_number(
undoing_move.starting_square_row)
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_col_number(
undoing_move.starting_square_col)

self.board[undoing_move.en_passant_eaten_square[0]][
undoing_move.en_passant_eaten_square[1]] = undoing_move.en_passant_eaten_piece
self.can_en_passant_bool = True
else:
self.board[undoing_move.starting_square_row][
undoing_move.starting_square_col] = undoing_move.moving_piece
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_row_number(
undoing_move.starting_square_row)
self.get_piece(undoing_move.starting_square_row, undoing_move.starting_square_col).change_col_number(
undoing_move.starting_square_col)

self.board[undoing_move.ending_square_row][undoing_move.ending_square_col] = undoing_move.removed_piece
if undoing_move.removed_piece != Player.EMPTY:
self.get_piece(undoing_move.ending_square_row, undoing_move.ending_square_col).change_row_number(
undoing_move.ending_square_row)
self.get_piece(undoing_move.ending_square_row, undoing_move.ending_square_col).change_col_number(
undoing_move.ending_square_col)

self.white_turn = not self.white_turn
# if undoing_move.in_check:
#     self._is_check = True
if undoing_move.moving_piece.get_name() is 'k' and undoing_move.moving_piece.get_player() is Player.PLAYER_1:
self._white_king_location = (undoing_move.starting_square_row, undoing_move.starting_square_col)
elif undoing_move.moving_piece.get_name() is 'k' and undoing_move.moving_piece.get_player() is Player.PLAYER_2:
self._black_king_location = (undoing_move.starting_square_row, undoing_move.starting_square_col)

return undoing_move
else:
print("Back to the beginning!")

# true if white, false if black
def whose_turn(self):
return self.white_turn

'''
check for immediate check
- check 8 directions and 8 knight squares
check for pins
- whatever blocked from above is a pin

- if immediate check, change check value to true
- list valid moves to prevent check but not remove pin
- if there are no valid moves to prevent check, checkmate
'''

def check_for_check(self, king_location, player):
# self._is_check = False
_checks = []
_pins = []
_pins_check = []

king_location_row = king_location[0]
king_location_col = king_location[1]

_up = 1
_down = 1
_left = 1
_right = 1

# Left of the king
_possible_pin = ()
while king_location_col - _left >= 0 and self.get_piece(king_location_row,
king_location_col - _left) is not None:
if self.is_valid_piece(king_location_row, king_location_col - _left) and \
self.get_piece(king_location_row, king_location_col - _left).is_player(player) and \
self.get_piece(king_location_row, king_location_col - _left).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row, king_location_col - _left)
else:
break
elif self.is_valid_piece(king_location_row, king_location_col - _left) and \
not self.get_piece(king_location_row, king_location_col - _left).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row,
king_location_col - _left).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row, king_location_col - _left))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row,
king_location_col - _left).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row, king_location_col - _left))
break
_left += 1

# right of the king
_possible_pin = ()
while king_location_col + _right < 8 and self.get_piece(king_location_row,
king_location_col + _right) is not None:
if self.is_valid_piece(king_location_row, king_location_col + _right) and \
self.get_piece(king_location_row, king_location_col + _right).is_player(player) and \
self.get_piece(king_location_row, king_location_col + _right).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row, king_location_col + _right)
else:
break
elif self.is_valid_piece(king_location_row, king_location_col + _right) and \
not self.get_piece(king_location_row, king_location_col + _right).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row,
king_location_col + _right).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row, king_location_col + _right))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row,
king_location_col + _right).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row, king_location_col + _right))
break
_right += 1

# below the king
_possible_pin = ()
while king_location_row + _down < 8 and self.get_piece(king_location_row + _down,
king_location_col) is not None:
if self.is_valid_piece(king_location_row + _down, king_location_col) and \
self.get_piece(king_location_row + _down, king_location_col).is_player(player) and \
self.get_piece(king_location_row + _down, king_location_col).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row + _down, king_location_col)
else:
break
elif self.is_valid_piece(king_location_row + _down, king_location_col) and \
not self.get_piece(king_location_row + _down, king_location_col).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row + _down,
king_location_col).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row + _down, king_location_col))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row + _down,
king_location_col).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row + _down, king_location_col))
break
_down += 1

# above the king
_possible_pin = ()
while king_location_row - _up >= 0 and self.get_piece(king_location_row - _up, king_location_col) is not None:
if self.is_valid_piece(king_location_row - _up, king_location_col) and \
self.get_piece(king_location_row - _up, king_location_col).is_player(player) and \
self.get_piece(king_location_row - _up, king_location_col).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row - _up, king_location_col)
else:
break
elif self.is_valid_piece(king_location_row - _up, king_location_col) and \
not self.get_piece(king_location_row - _up, king_location_col).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row - _up,
king_location_col).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row - _up, king_location_col))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row - _up,
king_location_col).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row - _up, king_location_col))
break
_up += 1

# left up
_up = 1
_left = 1
_possible_pin = ()
while king_location_col - _left >= 0 and king_location_row - _up >= 0 and \
self.get_piece(king_location_row - _up, king_location_col - _left) is not None:
if self.is_valid_piece(king_location_row - _up, king_location_col - _left) and \
self.get_piece(king_location_row - _up, king_location_col - _left).is_player(player) and \
self.get_piece(king_location_row - _up, king_location_col - _left).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row - _up, king_location_col - _left)
else:
break
elif self.is_valid_piece(king_location_row - _up, king_location_col - _left) and \
not self.get_piece(king_location_row - _up, king_location_col - _left).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row - _up,
king_location_col - _left).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row - _up, king_location_col - _left))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row - _up,
king_location_col - _left).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row - _up, king_location_col - _left))
break
_left += 1
_up += 1

# right up
_up = 1
_right = 1
_possible_pin = ()
while king_location_col + _right < 8 and king_location_row - _up >= 0 and \
self.get_piece(king_location_row - _up, king_location_col + _right) is not None:
if self.is_valid_piece(king_location_row - _up, king_location_col + _right) and \
self.get_piece(king_location_row - _up, king_location_col + _right).is_player(player) and \
self.get_piece(king_location_row - _up, king_location_col + _right).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row - _up, king_location_col + _right)
else:
break
elif self.is_valid_piece(king_location_row - _up, king_location_col + _right) and \
not self.get_piece(king_location_row - _up, king_location_col + _right).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row - _up,
king_location_col + _right).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row - _up, king_location_col + _right))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row - _up,
king_location_col + _right).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row - _up, king_location_col + _right))
break
_right += 1
_up += 1

# left down
_down = 1
_left = 1
_possible_pin = ()
while king_location_col - _left >= 0 and king_location_row + _down < 8 and \
self.get_piece(king_location_row + _down, king_location_col - _left) is not None:
if self.is_valid_piece(king_location_row + _down, king_location_col - _left) and \
self.get_piece(king_location_row + _down, king_location_col - _left).is_player(player) and \
self.get_piece(king_location_row + _down, king_location_col - _left).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row + _down, king_location_col - _left)
else:
break
elif self.is_valid_piece(king_location_row + _down, king_location_col - _left) and \
not self.get_piece(king_location_row + _down, king_location_col - _left).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row + _down,
king_location_col - _left).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row + _down, king_location_col - _left))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row + _down,
king_location_col - _left).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row + _down, king_location_col - _left))
break
_left += 1
_down += 1

# right down
_down = 1
_right = 1
_possible_pin = ()
while king_location_col + _right < 8 and king_location_row + _down < 8 and \
self.get_piece(king_location_row + _down, king_location_col + _right) is not None:
if self.is_valid_piece(king_location_row + _down, king_location_col + _right) and \
self.get_piece(king_location_row + _down, king_location_col + _right).is_player(player) and \
self.get_piece(king_location_row + _down, king_location_col + _right).get_name() is not "k":
if not _possible_pin:
_possible_pin = (king_location_row + _down, king_location_col + _right)
else:
break
elif self.is_valid_piece(king_location_row + _down, king_location_col + _right) and \
not self.get_piece(king_location_row + _down, king_location_col + _right).is_player(player):
if _possible_pin:
temp = self.board[_possible_pin[0]][_possible_pin[1]]
self.board[_possible_pin[0]][_possible_pin[1]] = Player.EMPTY
if (king_location_row, king_location_col) in self.get_piece(king_location_row + _down,
king_location_col + _right).get_valid_piece_takes(
self):
_pins.append(_possible_pin)
_pins_check.append((king_location_row + _down, king_location_col + _right))
self.board[_possible_pin[0]][_possible_pin[1]] = temp
else:
if (king_location_row, king_location_col) in self.get_piece(king_location_row + _down,
king_location_col + _right).get_valid_piece_takes(
self):
# self._is_check = True
_checks.append((king_location_row + _down, king_location_col + _right))
break
_right += 1
_down += 1

# knights
row_change = [-2, -2, -1, -1, +1, +1, +2, +2]
col_change = [-1, +1, -2, +2, -2, +2, +1, -1]
for i in range(0, 8):
if self.is_valid_piece(king_location_row + row_change[i], king_location_col + col_change[i]) and \
not self.get_piece(king_location_row + row_change[i], king_location_col + col_change[i]).is_player(
player):
if (king_location_row, king_location_col) in self.get_piece(king_location_row + row_change[i],
king_location_col + col_change[
i]).get_valid_piece_takes(self):
# self._is_check = True
_checks.append((king_location_row + row_change[i], king_location_col + col_change[i]))
# print([_checks, _pins, _pins_check])
return [_checks, _pins, _pins_check]

class chess_move():
def __init__(self, starting_square, ending_square, game_state, in_check):
self.starting_square_row = starting_square[0]
self.starting_square_col = starting_square[1]
self.moving_piece = game_state.get_piece(self.starting_square_row, self.starting_square_col)
self.in_check = in_check

self.ending_square_row = ending_square[0]
self.ending_square_col = ending_square[1]
if game_state.is_valid_piece(self.ending_square_row, self.ending_square_col):
self.removed_piece = game_state.get_piece(self.ending_square_row, self.ending_square_col)
else:
self.removed_piece = Player.EMPTY

self.castled = False
self.rook_starting_square = None
self.rook_ending_square = None
self.moving_rook = None

self.pawn_promoted = False
self.replacement_piece = None

self.en_passaned = False
self.en_passant_eaten_piece = None
self.en_passant_eaten_square = None

def castling_move(self, rook_starting_square, rook_ending_square, game_state):
self.castled = True
self.rook_starting_square = rook_starting_square
self.rook_ending_square = rook_ending_square
self.moving_rook = game_state.get_piece(rook_starting_square[0], rook_starting_square[1])

def pawn_promotion_move(self, new_piece):
self.pawn_promoted = True
self.replacement_piece = new_piece

def en_passant_move(self, eaten_piece, eaten_piece_square):
self.en_passaned = True
self.en_passant_eaten_piece = eaten_piece
self.en_passant_eaten_square = eaten_piece_square

def get_moving_piece(self):
return self.moving_piece
```

## The given code below is a python file for ai_engine.py

```#
# The Chess AI class
# Will utilize minimax and alpha beta pruning
#
# Author: Boo Sung Kim
# Note: Code inspired from the pseudocode by Sebastian Lague
# from enums import Player
# TODO: switch undo moves to stack data structure
import chess_engine
from enums import Player

class chess_ai:
'''
call minimax with alpha beta pruning
evaluate board
get the value of each piece
'''
def minimax_white(self, game_state, depth, alpha, beta, maximizing_player, player_color):
csc = game_state.checkmate_stalemate_checker()
if maximizing_player:
if csc == 0:
return 5000000
elif csc == 1:
return -5000000
elif csc == 2:
return 100
elif not maximizing_player:
if csc == 1:
return 5000000
elif csc == 0:
return -5000000
elif csc == 2:
return 100

if depth <= 0 or csc != 3:
return self.evaluate_board(game_state, Player.PLAYER_1)

if maximizing_player:
max_evaluation = -10000000
all_possible_moves = game_state.get_all_legal_moves("black")
for move_pair in all_possible_moves:
game_state.move_piece(move_pair[0], move_pair[1], True)
evaluation = self.minimax_white(game_state, depth - 1, alpha, beta, False, "white")
game_state.undo_move()

if max_evaluation < evaluation:
max_evaluation = evaluation
best_possible_move = move_pair
alpha = max(alpha, evaluation)
if beta <= alpha:
break
if depth == 3:
return best_possible_move
else:
return max_evaluation
else:
min_evaluation = 10000000
all_possible_moves = game_state.get_all_legal_moves("white")
for move_pair in all_possible_moves:
game_state.move_piece(move_pair[0], move_pair[1], True)
evaluation = self.minimax_white(game_state, depth - 1, alpha, beta, True, "black")
game_state.undo_move()

if min_evaluation > evaluation:
min_evaluation = evaluation
best_possible_move = move_pair
beta = min(beta, evaluation)
if beta <= alpha:
break
if depth == 3:
return best_possible_move
else:
return min_evaluation

def minimax_black(self, game_state, depth, alpha, beta, maximizing_player, player_color):
csc = game_state.checkmate_stalemate_checker()
if maximizing_player:
if csc == 1:
return 5000000
elif csc == 0:
return -5000000
elif csc == 2:
return 100
elif not maximizing_player:
if csc == 0:
return 5000000
elif csc == 1:
return -5000000
elif csc == 2:
return 100

if depth <= 0 or csc != 3:
return self.evaluate_board(game_state, Player.PLAYER_2)

if maximizing_player:
max_evaluation = -10000000
all_possible_moves = game_state.get_all_legal_moves("white")
for move_pair in all_possible_moves:
game_state.move_piece(move_pair[0], move_pair[1], True)
evaluation = self.minimax_black(game_state, depth - 1, alpha, beta, False, "black")
game_state.undo_move()

if max_evaluation < evaluation:
max_evaluation = evaluation
best_possible_move = move_pair
alpha = max(alpha, evaluation)
if beta <= alpha:
break
if depth == 3:
return best_possible_move
else:
return max_evaluation
else:
min_evaluation = 10000000
all_possible_moves = game_state.get_all_legal_moves("black")
for move_pair in all_possible_moves:
game_state.move_piece(move_pair[0], move_pair[1], True)
evaluation = self.minimax_black(game_state, depth - 1, alpha, beta, True, "white")
game_state.undo_move()

if min_evaluation > evaluation:
min_evaluation = evaluation
best_possible_move = move_pair
beta = min(beta, evaluation)
if beta <= alpha:
break
if depth == 3:
return best_possible_move
else:
return min_evaluation

def evaluate_board(self, game_state, player):
evaluation_score = 0
for row in range(0, 8):
for col in range(0, 8):
if game_state.is_valid_piece(row, col):
evaluated_piece = game_state.get_piece(row, col)
evaluation_score += self.get_piece_value(evaluated_piece, player)
return evaluation_score

def get_piece_value(self, piece, player):
if player is Player.PLAYER_1:
if piece.is_player("black"):
if piece.get_name() is "k":
return 1000
elif piece.get_name() is "q":
return 100
elif piece.get_name() is "r":
return 50
elif piece.get_name() is "b":
return 30
elif piece.get_name() is "n":
return 30
elif piece.get_name() is "p":
return 10
else:
if piece.get_name() is "k":
return -1000
elif piece.get_name() is "q":
return -100
elif piece.get_name() is "r":
return -50
elif piece.get_name() is "b":
return -30
elif piece.get_name() is "n":
return -30
elif piece.get_name() is "p":
return -10
else:
if piece.is_player("white"):
if piece.get_name() is "k":
return 1000
elif piece.get_name() is "q":
return 100
elif piece.get_name() is "r":
return 50
elif piece.get_name() is "b":
return 30
elif piece.get_name() is "n":
return 30
elif piece.get_name() is "p":
return 10
else:
if piece.get_name() is "k":
return -1000
elif piece.get_name() is "q":
return -100
elif piece.get_name() is "r":
return -50
elif piece.get_name() is "b":
return -30
elif piece.get_name() is "n":
return -30
elif piece.get_name() is "p":
return -10```

To start executing this Chess Game In Python, make sure you have PyCharm IDE  installed in your computer.

By the way if you are new to python programming and you don’t know what would be the the Python IDE to use, I have here a list of Best Python IDE for Windows, Linux, Mac OS that will suit for you. I also have here How to Download and Install Latest Version of Python on Windows.

## Chess Game In Python : Steps on how to run to run the project

Time needed: 5 minutes.

These are the steps on how to run Chess Game In Python

• Step 2: Extract file.

Next, after you finished download the source code, extract the zip file.

• Step 3: Open Project Path and Open CMD (Command Prompt).

In order for you to run the project, you just need to open the project path and type CMD. The first thing you need to do is type py chess_gui.py in the command prompt. After that, just wait for a few seconds to load the system.