8

This question addresses building a Chess engine. I've done just that, and in my humble opinion quite elegantly. But I'm missing my ending conditions.

Here are some pseudopython functions that I use.

# Move from position old to new
def move(old, new):
    if is_legal(old, new):
        # Eat and move
        if is_legal(new, enemy_king) or check_in_los(enemy_king, old):
            # Set check on enemy king
        if piece_type == 'Pawn' and position at the end of board:
            # Convert to Queen

def is_legal(old, new):
    # Assure piece is moving, it's your own and new position not on another own piece
    # Based on piece type, assure it's maneuvering properly
    # Assure there are no pieces in between the positions if applicable

    if piece_type == 'King':
        is_checked(new)  # Not moving to a checked square
    elif checked:
        # Assure check is removed
    else:
        check_in_los(own_king, old)  # Moving the piece does not create a check from behind

# Determine if king is checked from line of sight
def check_in_los(king_pos, direction):
    # Divide path into single-square steps
    # Find next piece in direction by incrementing king position by step
    if is_legal(next, king_pos):
        # King is checked from direction

# Determine if king is checked
def is_checked(king_pos):
    # Check if knight positions around kings contain enemy knights
    # For every 8 directions around king, check_in_los(king, direction)

Now on to the check mate. It would be trivial to check every position around the king if it is a legal position to be in, but that's not quite enough.

Consider the following scenario where the white king is being threatened:

   A    B    C    D    E    F    G    H
1  BR |    | BR |    |    |    |    |   
2     |    |    |    |    |    |    |   
3     |    |    |    |    |    |    |   
4     |    |    |    |    |    |    |   
5     |    |    |    |    |    |    |   
6     |    |    |    |    |    |    |   
7     |    |    |    | WN |    |    |   
8     | WK | BQ |    |    |    |    |   

The king (B8) has no legal moves left, but the knight (E7) can save him by eating the queen. Similarly if the placement of the queen is switched and the knight is a rook instead:

   A    B    C    D    E    F    G    H
1  BR |    | BR |    |    |    |    |   
2     |    |    |    |    |    |    |   
3     |    |    |    |    |    |    |   
4     | BQ |    |    |    |    |    |   
5     |    |    |    |    |    |    |   
6     |    |    |    |    |    |    |   
7     |    |    |    | WR |    |    |   
8     | WK |    |    |    |    |    |   

The white rook can save the king by moving to B7.

A naïve approach to checking for a mate would I guess involve checking every possibility, but that seems wasteful.

What would be a good way of achieving this? Preferably using the functions already in place. I'm also open to other approaches if needed. It crossed my mind that maybe it would be helpful to keep track of the checking pieces or even every square that is being checked and the checking pattern of each piece individually, but I'm not sure..

Felix
  • 387

5 Answers5

6

This is one of those situation where the human mind have an advantage over a computer. It is fairly simple to for a human to decide if a position in chess is a check mate or not.

We can discard most moves as having no relevance to the position. Creating an algorithm that discards those moves is quite tricky.

The simple solution of just going through all possible moves (which at most can be in the region of 40-50 with many pieces on the board, often far less) is perhaps naive but it is fast and uses far less effort than trying to device an algorithm to decide if a position is check mate or not.

Imaging a position where a knight and a bishop checks the king, you can take the knight but it is still check from the bishop. Or you can take a queen checking the king, but the piece that can do that can't be moved because that would cause a check from a rook.

It really gets very complex very fast. Why not spend the same time improving other parts of the program?

That is the reason why https://chess.stackexchange.com/questions/13871/check-for-checkmate mentioned by Ewan in the comments says that stockfish tries all moves and if there aren't any legal moves then it is check mate (similar to stale mate if there is no check in the first place).

Robbie Dee
  • 9,823
Bent
  • 2,596
3

When you are generating all possible moves and evaluate them for the best, you are for sure taking into account the value of pieces that might be taken.

Just use the same method, and give the King a very high value; that is the usual approach.
There is no magic shortcut to recognize a checkmate - remember it is defined as 'the King will be unavoidably captured in the next move'.

Stopping a chess game one move before the capture of the King is a historic courtesy. It's fine to do the same in your program, but there is no need or gain from inventing a different mechanic.

Aganju
  • 1,473
2

Doesn't this requirement simply fall out of whatever routine determines the best move to make at each point in the game?

You aren't allowed to end your move with your king in check. That's not a valid move, so the movement routine should never pick it.

So after the opponent's move, try to determine the best move you can make as normal. If there is no move that is legal, then the game is over. If the king is currently in check, then it's checkmate, otherwise it's stalemate.

Simon B
  • 9,772
0

In the same boat, my game does not have an ai opponent, I had no need to find a best move yet. I can boil this down to a few scenarios, which I think you have already done. First can you move the king out of check. That is a straight forward check if you maintain indicators that indicate which squares are threatened by the opposite player. Second case is, can the king take a piece to get out of check. This may involve recalculating the threat board for several pieces. The third more complicated case is a check to see if another piece can be moved to remove the king from check. It is interesting that the solution to the third case involves iterating though moves in a similar way to finding the best move. If I end up implementing the solution then I will have done most of the work involved with building an computer opponent.

0

As a building-block for your code we first write a method that checks whether a king is under attack.

To see if A’s king is under attack we check if there is an opposing pawn, knight or king in the attack positions. If not then we find the first piece in every direction (up, down, left, right, diagonal) and if there is a piece in that direction, and the next piece is an opposing piece, and it is a rook or queen on the same row/column, or a bishop/queen on the diagonal, then the king is attacked. (The same rules apply for other figures, except for the en-pas sent rule for pawns, but we don’t need that here).

Moves that leave your king under attack are illegal. You find any valid move. If you have a valid move then you are not checkmate or stalemate. If there is no valid move, then you are checkmate if your king is under attack, and stalemate if your king is not under attack.

There are some special rules. Castling is not allowed while in check, and castling over a field that is attacked is not allowed.

You may be able to find faster that any move while the king is attacked leaves the king attacked, because the same attack might work after a move.

PS. It is not enough to check if the king is under attack only after the king moves. For example moving a piece that is between the king and a possible attacker can put the king under attack.

gnasher729
  • 49,096