def pawn_moves(pos: Position, game: Game) -> List[Move]: """Return list of <game.turn> pawn moves. pawn moves = positions_under_threat + move forward + en_passant """ # Init move list moves = [] # Check if position under threat occupied with opponent pieces or en_passant possible. for pos_under_threat in PositionsUnderThreat.positions_under_pawn_threat( pos, game.turn, game.board): move = Move(pos, pos_under_threat) if PositionsUnderThreat.is_position_enemy( pos_under_threat, game.turn, game.board) or move in PieceMoves.en_passant_moves( pos, game): moves.append(move) # Check forward move. shift_forward_y = 1 if game.turn == Colour.WHITE else -1 pos_forward = Position(pos.x, pos.y + shift_forward_y) if game.board.is_position_empty(pos_forward): move = Move(pos, pos_forward) moves.append(move) # Check double move forward shift_forward_y = 2 if game.turn == Colour.WHITE else -2 pos_d_forward = Position(pos.x, pos.y + shift_forward_y) if (game.board.is_position_empty(pos_forward) and game.board.is_position_empty(pos_d_forward) and not PieceMoves.is_piece_touched(pos, game)): move = Move(pos, pos_d_forward) moves.append(move) return moves
def test_positions_under_knight_threat(self): """Test of positions_under_knight_threat() method.""" assert sorted( PositionsUnderThreat.positions_under_knight_threat( Position(7, 6), Colour.WHITE, self.board)) == [Position(5, 7), Position(6, 4)]
def is_check(board: Board, colour: Colour) -> bool: """Check if <colour> side got check. check = at least one opponent piece aims at own king """ # Retrieve king position king_pos = board.get_positions_for_piece(Piece(PieceType.KING, colour))[0] return king_pos in PositionsUnderThreat.all_positions_under_threat_for_side( colour, board)
def king_moves(pos: Position, game: Game) -> List[Position]: """Return list of <game.turn> king moves. king moves = positions_under_threat + castling """ moves = [ Move(pos, pos_threat) for pos_threat in PositionsUnderThreat.positions_under_king_threat( pos, game.turn, game.board) ] return [*PieceMoves.castling_moves(pos, game), *moves]
def rook_moves(pos: Position, game: Game) -> List[Move]: """Return list of <game.turn> rook moves. rook moves = positions_under_threat """ moves = [ Move(pos, pos_threat) for pos_threat in PositionsUnderThreat.positions_under_rook_threat( pos, game.turn, game.board) ] return moves
def test_positions_under_king_threat(self): """Test of positions_under_king_threat() method.""" assert sorted( PositionsUnderThreat.positions_under_king_threat( Position(4, 4), Colour.WHITE, self.board)) == [ Position(3, 3), Position(3, 5), Position(4, 5), Position(5, 3) ]
def test_positions_under_threat(self): """Test of positions_under_threat() method.""" assert sorted( PositionsUnderThreat.positions_under_threat( Position(4, 4), Pieces.WHITE_KING, self.board)) == [ Position(3, 3), Position(3, 5), Position(4, 5), Position(5, 3) ]
def castling_moves(pos: Position, game: Game) -> List[Move]: """Return list of <game.turn> castling moves. Check is taking into account!!! """ # Init catling list. castling = [] # Retrieve piece at start position. piece_start = game.board.get_piece(pos) # Retrieve positions under threat (important info for castling). pos_under_threat = PositionsUnderThreat.all_positions_under_threat_for_side( game.turn, game.board) # Check if piece piece at start position King with no threat/check. if (piece_start is not None and piece_start.type == PieceType.KING and not PieceMoves.is_piece_touched(pos, game) and pos not in pos_under_threat): # Short castling. _1r_ means 1 pos to the right from white side. is_1r_pos_avail = ( game.board.is_position_empty(Position(pos.x + 1, pos.y)) and Position(pos.x + 1, pos.y) not in pos_under_threat) is_2r_pos_avail = ( game.board.is_position_empty(Position(pos.x + 2, pos.y)) and Position(pos.x + 2, pos.y) not in pos_under_threat) is_3r_pos_rook = ( not game.board.is_position_empty(Position(pos.x + 3, pos.y)) and game.board.get_piece(Position( pos.x + 3, pos.y)).type == PieceType.ROOK) if (is_1r_pos_avail and is_2r_pos_avail and is_3r_pos_rook and not PieceMoves.is_piece_touched( Position(pos.x + 3, pos.y), game)): move = Move(pos, Position(pos.x + 2, pos.y)) castling.append(move) # Long castling. _1l_ means 1 pos to the left from white side. is_1l_pos_avail = ( game.board.is_position_empty(Position(pos.x - 1, pos.y)) and Position(pos.x - 1, pos.y) not in pos_under_threat) is_2l_pos_avail = ( game.board.is_position_empty(Position(pos.x - 2, pos.y)) and Position(pos.x - 2, pos.y) not in pos_under_threat) is_4l_pos_rook = ( not game.board.is_position_empty(Position(pos.x - 4, pos.y)) and game.board.get_piece(Position( pos.x - 4, pos.y)).type == PieceType.ROOK) if (is_1l_pos_avail and is_2l_pos_avail and is_4l_pos_rook and game.board.is_position_empty(Position( pos.x - 3, pos.y)) and not PieceMoves.is_piece_touched( Position(pos.x - 4, pos.y), game)): move = Move(pos, Position(pos.x - 2, pos.y)) castling.append(move) return castling
def test_positions_under_rook_threat(self): """Test of positions_under_rook_threat() method.""" assert sorted( PositionsUnderThreat.positions_under_rook_threat( Position(3, 7), Colour.WHITE, self.board)) == [ Position(0, 7), Position(1, 7), Position(2, 7), Position(3, 5), Position(3, 6), Position(4, 7), Position(5, 7), ]
def test_positions_under_queen_threat(self): """Test of positions_under_queen_threat() method.""" assert sorted( PositionsUnderThreat.positions_under_queen_threat( Position(5, 5), Colour.WHITE, self.board)) == [ Position(4, 5), Position(4, 6), Position(5, 6), Position(5, 7), Position(6, 4), Position(6, 5), Position(7, 3), Position(7, 5), ]
def test_all_positions_under_threat_for_side(self): """Test of all_positions_under_threat_for_side() method.""" assert sorted( PositionsUnderThreat.all_positions_under_threat_for_side( Colour.WHITE, self.board)) == [ Position(3, 4), Position(3, 7), Position(4, 7), Position(5, 4), Position(5, 5), Position(5, 6), Position(6, 7), Position(7, 7), ]
def test_positions_under_pawn_threat(self): """Test of positions_under_pawn_threat() method.""" assert not PositionsUnderThreat.positions_under_pawn_threat( Position(4, 3), Colour.WHITE, self.board) assert sorted( PositionsUnderThreat.positions_under_pawn_threat( Position(3, 4), Colour.WHITE, self.board)) == [Position(2, 5), Position(4, 5)] assert sorted( PositionsUnderThreat.positions_under_pawn_threat( Position(5, 4), Colour.WHITE, self.board)) == [Position(4, 5), Position(6, 5)] assert sorted( PositionsUnderThreat.positions_under_pawn_threat( Position(0, 6), Colour.WHITE, self.board)) == [Position(1, 7)] assert not PositionsUnderThreat.positions_under_pawn_threat( Position(7, 7), Colour.WHITE, self.board) assert PositionsUnderThreat.positions_under_pawn_threat( Position(4, 5), Colour.BLACK, self.board) == [Position(3, 4), Position(5, 4)]