Boolean function to determine if white king is in check given positions on a chess board

Question:

I am trying to write a program that will return True if the white king on a chess board is in check. The pieces on the board are generated as a string and formatted as such, where the lowercase values are white and the uppercase are black.:

r*x***k****p***P*****Q*****kp****K*****p***Pb****p***PP***X***KR
| | |X| | | |K|R|
| |p| | | |P|P| |
| | | |P|b| | | |
| |K| | | | | |p|
| | | |k|p| | | |
| | | | | |Q| | |
| | | |p| | | |P|
|r| |x| | | |k| |

I understand how to transform the units on the board into x and y coordinates, and the mathematical operations of the pieces on the board (check pawns on +7 and +9, check rooks on …-2, -1, +1,+2… and …-16, -8, +8, +16…, but i can’t translate this to python, or stop the check if it hits another piece or before it goes "past" the board and loops around again. Here is my code so far, but nothing really working correctly:

def white_check(coded_position):
    w_king = coded_position.find("x")
    w_king_x = w_king%8
    w_king_y = w_king//8
    result = False
    print(w_king)

    # This doesn't work if king is on x = 0 or 8
    # Returns true if pawn checks
    # if coded_position[w_king+7] == "P" or coded_position[w_king+9] == "P":
        #result = True

    # try using for loops and going up 1 / 8 at a time and trying each case for rooks / and bishops
    # checks right side for rooks
    for i in range(w_king,w_king-w_king_x+8):
        if coded_position[i] != "*" and coded_position[i] != "K":
            result = False
            break
        if coded_position[i] == "K":
            result = True

    # checks left side for rooks
    for i in range(w_king,w_king-w_king_x,-1):
        if coded_position[i] != "*" and coded_position[i] != "K":
            result = False
            break
        if coded_position[i] == "K":
            result = True

    print(result)
    return result

I think I am really over-complicating this, is there anything obvious that I am missing?

Asked By: Nykis

||

Answers:

I’m not going to give you code (right now at least), but I can give some steps.

Currently looks like you are storing everything as an index on the long input line. This makes it harder, so step one is to represent the board as a list of strings, where is one is 8 long.

The result you want is

board = ["r*x***k*",
         "***p***P",
         "*****Q**",
         "***kp***",
         "*K*****p",
         "***Pb***",
         "*p***PP*",
         "**X***KR"]

So now the white king is at board[0][2], and black is moving up the board. Let’s call this (0, 2).

Now you need to work out if (0, 2) is in check. The way I would do this is work out for each type of piece, where one could be, to put this position in check. You could store this as a list of differences from the current king location, and for each of those you check if the thing that’s in them is the piece that can cause check.

movements = {
    "P": [(1,-1), (1,1)],
    "R": [*[(0, i), (0, -i), (i, 0), (-i, 0)] for i in range(7)],
}

Here are movements for a pawn and rook. If there is a pawn on (0, 2)+(1, 1) or (0, 2)+(1,-1), and those positions are inside the grid, the pawn is checking (0, 2).

To be inside the grid, both numbers have to be between 0 and 7 inclusive.

For the rook it’s a bit more complicated. Positions a rook can attack from are when either the row is the same or the column is the same, that’s why there’s always a 0 in one of the movements above. With the rook you have the added complexity, that you have to discount anything that’s in the way. It might be easier to search everything left of the king, right of, above, and below, and stop searching that when

  • You reach the edge of the board – not being checked from this direction
  • You meet a piece that’s not a rook – not being checked from this direction by a rook
  • You meet a rook – you’re in check…

I think that’s enough to complete this. Remember, you don’t have to check every single location, you just need to find one piece that’s threatening the king.


Afterwards it’s fairly simple to work out if a king is in checkmate, because it’s just if a king is in check, and all the places around it are also in check, or invalid places.

Answered By: blueteeth

I think you are making this more complicated than it is. Here are the steps I would use:

  1. Find the king positions.

  2. Loop through all 8 directions from that location in a nested loop.

  3. When you reach a white piece (uppercase letter), break that direction.

  4. When you reach end of board, break that direction.

  5. If you reach a black piece (lowercase) you have 4 options to check:

    a. Piece is orthogonally from king and is a rook

    b. Piece is diagonally from king and is a bishop

    c. Piece is 1 square away diagonally from king and is a pawn

    d. Any direction and piece is a queen

If any of a-d is True, then return True (king is in check). If the entire loop ends, return False.

If you need I can give you the code for my checker.

Answered By: Eli
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.