Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 75 additions & 7 deletions chessington/engine/pieces.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,81 @@ class Pawn(Piece):
"""
def get_available_moves(self, board) -> List[Square]:
current_square = board.find_piece(self)
if self.player == Player.BLACK:
square_in_front = Square.at(current_square.row - 1, current_square.col)
return [square_in_front]
else:
square_in_front = Square.at(current_square.row + 1, current_square.col)
return [square_in_front]
moves = []

if self.player == Player.BLACK:
# Black pawn moves down (decreasing row)
new_row = current_square.row - 1

# 1. FORWARD MOVEMENT
if new_row >= 0:
one_square = Square.at(new_row, current_square.col)
if board.get_piece(one_square) is None:
moves.append(one_square)

# Two-square move from starting position
if current_square.row == 6:
two_square_row = current_square.row - 2
if two_square_row >= 0:
two_squares = Square.at(two_square_row, current_square.col)
if board.get_piece(two_squares) is None:
moves.append(two_squares)

# 2. DIAGONAL CAPTURE MOVES
if new_row >= 0: # Make sure we're not going off the board
# Check diagonal left (column - 1)
if current_square.col - 1 >= 0: # Don't go off left edge
diagonal_left = Square.at(new_row, current_square.col - 1)
piece_on_diagonal = board.get_piece(diagonal_left)
# Can capture if there's an enemy piece (different player)
if piece_on_diagonal is not None and piece_on_diagonal.player != self.player:
moves.append(diagonal_left)

# Check diagonal right (column + 1)
if current_square.col + 1 <= 7: # Don't go off right edge
diagonal_right = Square.at(new_row, current_square.col + 1)
piece_on_diagonal = board.get_piece(diagonal_right)
# Can capture if there's an enemy piece (different player)
if piece_on_diagonal is not None and piece_on_diagonal.player != self.player:
moves.append(diagonal_right)

else: # WHITE player
# White pawn moves up (increasing row)
new_row = current_square.row + 1

# 1. FORWARD MOVEMENT
if new_row <= 7:
one_square = Square.at(new_row, current_square.col)
if board.get_piece(one_square) is None:
moves.append(one_square)

# Two-square move from starting position
if current_square.row == 1:
two_square_row = current_square.row + 2
if two_square_row <= 7:
two_squares = Square.at(two_square_row, current_square.col)
if board.get_piece(two_squares) is None:
moves.append(two_squares)

# 2. DIAGONAL CAPTURE MOVES
if new_row <= 7: # Make sure we're not going off the board
# Check diagonal left (column - 1)
if current_square.col - 1 >= 0: # Don't go off left edge
diagonal_left = Square.at(new_row, current_square.col - 1)
piece_on_diagonal = board.get_piece(diagonal_left)
# Can capture if there's an enemy piece (different player)
if piece_on_diagonal is not None and piece_on_diagonal.player != self.player:
moves.append(diagonal_left)

# Check diagonal right (column + 1)
if current_square.col + 1 <= 7: # Don't go off right edge
diagonal_right = Square.at(new_row, current_square.col + 1)
piece_on_diagonal = board.get_piece(diagonal_right)
# Can capture if there's an enemy piece (different player)
if piece_on_diagonal is not None and piece_on_diagonal.player != self.player:
moves.append(diagonal_right)

return moves

class Knight(Piece):
"""
Expand Down Expand Up @@ -91,4 +159,4 @@ class King(Piece):
"""

def get_available_moves(self, board):
return []
return []
234 changes: 233 additions & 1 deletion tests/test_pieces.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,236 @@ def test_black_pawn_cannot_move_down_two_squares_if_already_moved():

# Assert
assert Square.at(4, 4) in moves
assert Square.at(3, 4) not in moves
assert Square.at(3, 4) not in moves

@staticmethod
def test_white_pawn_cannot_move_if_piece_in_front():

# Arrange
board = Board.empty()
pawn = Pawn(Player.WHITE)
pawn_square = Square.at(4, 4)
board.set_piece(pawn_square, pawn)

obstructing_square = Square.at(5, 4)
obstruction = Pawn(Player.BLACK)
board.set_piece(obstructing_square, obstruction)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert len(moves) == 0

@staticmethod
def test_black_pawn_cannot_move_if_piece_in_front():

# Arrange
board = Board.empty()
pawn = Pawn(Player.BLACK)
pawn_square = Square.at(4, 4)
board.set_piece(pawn_square, pawn)

obstructing_square = Square.at(3, 4)
obstruction = Pawn(Player.WHITE)
board.set_piece(obstructing_square, obstruction)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert len(moves) == 0

@staticmethod
def test_white_pawn_cannot_move_two_squares_if_piece_two_in_front():

# Arrange
board = Board.empty()
pawn = Pawn(Player.WHITE)
pawn_square = Square.at(1, 4)
board.set_piece(pawn_square, pawn)

obstructing_square = Square.at(3, 4)
obstruction = Pawn(Player.BLACK)
board.set_piece(obstructing_square, obstruction)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert obstructing_square not in moves

@staticmethod
def test_black_pawn_cannot_move_two_squares_if_piece_two_in_front():

# Arrange
board = Board.empty()
pawn = Pawn(Player.BLACK)
pawn_square = Square.at(6, 4)
board.set_piece(pawn_square, pawn)

obstructing_square = Square.at(4, 4)
obstruction = Pawn(Player.WHITE)
board.set_piece(obstructing_square, obstruction)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert obstructing_square not in moves

@staticmethod
def test_white_pawn_cannot_move_two_squares_if_piece_one_in_front():

# Arrange
board = Board.empty()
pawn = Pawn(Player.WHITE)
pawn_square = Square.at(1, 4)
board.set_piece(pawn_square, pawn)

obstructing_square = Square.at(2, 4)
obstruction = Pawn(Player.BLACK)
board.set_piece(obstructing_square, obstruction)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert Square.at(3, 4) not in moves

@staticmethod
def test_black_pawn_cannot_move_two_squares_if_piece_one_in_front():

# Arrange
board = Board.empty()
pawn = Pawn(Player.BLACK)
pawn_square = Square.at(6, 4)
board.set_piece(pawn_square, pawn)

obstructing_square = Square.at(5, 4)
obstruction = Pawn(Player.WHITE)
board.set_piece(obstructing_square, obstruction)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert Square.at(4, 4) not in moves

@staticmethod
def test_white_pawn_cannot_move_at_top_of_board():

# Arrange
board = Board.empty()
pawn = Pawn(Player.WHITE)
square = Square.at(7, 4)
board.set_piece(square, pawn)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert len(moves) == 0

@staticmethod
def test_black_pawn_cannot_move_at_bottom_of_board():

# Arrange
board = Board.empty()
pawn = Pawn(Player.BLACK)
square = Square.at(0, 4)
board.set_piece(square, pawn)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert len(moves) == 0

@staticmethod
def test_white_pawns_can_capture_diagonally():

# Arrange
board = Board.empty()
pawn = Pawn(Player.WHITE)
pawn_square = Square.at(3, 4)
board.set_piece(pawn_square, pawn)

enemy1 = Pawn(Player.BLACK)
enemy1_square = Square.at(4, 5)
board.set_piece(enemy1_square, enemy1)

enemy2 = Pawn(Player.BLACK)
enemy2_square = Square.at(4, 3)
board.set_piece(enemy2_square, enemy2)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert enemy1_square in moves
assert enemy2_square in moves

@staticmethod
def test_black_pawns_can_capture_diagonally():

# Arrange
board = Board.empty()
pawn = Pawn(Player.BLACK)
pawn_square = Square.at(3, 4)
board.set_piece(pawn_square, pawn)

enemy1 = Pawn(Player.WHITE)
enemy1_square = Square.at(2, 5)
board.set_piece(enemy1_square, enemy1)

enemy2 = Pawn(Player.WHITE)
enemy2_square = Square.at(2, 3)
board.set_piece(enemy2_square, enemy2)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert enemy1_square in moves
assert enemy2_square in moves

@staticmethod
def test_white_pawns_cannot_move_diagonally_except_to_capture():

# Arrange
board = Board.empty()
pawn = Pawn(Player.WHITE)
pawn_square = Square.at(3, 4)
board.set_piece(pawn_square, pawn)

friendly = Pawn(Player.WHITE)
friendly_square = Square.at(4, 5)
board.set_piece(friendly_square, friendly)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert Square.at(4, 3) not in moves
assert Square.at(4, 5) not in moves

@staticmethod
def test_black_pawns_cannot_move_diagonally_except_to_capture():

# Arrange
board = Board.empty()
pawn = Pawn(Player.BLACK)
pawn_square = Square.at(3, 4)
board.set_piece(pawn_square, pawn)

friendly = Pawn(Player.BLACK)
friendly_square = Square.at(2, 5)
board.set_piece(friendly_square, friendly)

# Act
moves = pawn.get_available_moves(board)

# Assert
assert Square.at(2, 3) not in moves
assert Square.at(2, 5) not in moves