# How Can I Make my engine generate the best move faster?

Question:
My engine takes 30 secs to generate a move. When i decrease the time, the engine starts making mistakes. How can I make this time faster while still letting the engine generate a good move?
https://replit.com/@jcsan/Tortoi#main.py

``````import chess
import time
import chess.polyglot

board = chess.Board()
material = {
chess.PAWN:10.0,
chess.KNIGHT:32.0,
chess.BISHOP:33.3,
chess.ROOK:56.5,
chess.QUEEN:95.5,
chess.KING:200.0

}
scoring = {
'Pawn': [
0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 2, 3, 3, 2, 1, 1, 0, 0,
0, 2, 2, 0, 0, 0, 0, 0, 0, -2, -2, 0, 0, 0, 1, -1, -2, 0, 0, -2, -1, 1, 1, 2,
2, -2, -2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0
],
'Knight': [
-5, -4, -3, -3, -3, -3, -4, -5, -4, -2, 0, 0, 0, 0, -2, -4, -3, 0, 1, 1.5,
1.5, 1, 0, -3, -3, 0.5, 1.5, 2, 2, 1.5, 0.5, -3, -3, 0.5, 1.5, 2, 2, 1.5,
0.5, -3, -3, 0, 1, 1.5, 1.5, 1, 0, -3, -4, -2, 0, 0.5, 0.5, 0, -2, -4, -5,
-4, -3, -3, -3, -3, -4, -5
],
'Bishop': [
-2,
-1,
-1,
-1,
-1,
-1,
-1,
-2,
-1,
0.25,
0,
0,
0,
0,
0.25,
-1,
-1,
0,
1,
1,
1,
1,
0,
-1,
-1,
0,
1,
1.5,
1.5,
1,
0,
-1,
-1,
0,
1,
1.5,
1.5,
1,
0,
-1,
-1,
0,
1,
1,
1,
1,
0,
-1,
-1,
0.25,
0,
0,
0,
0,
0.25,
-1,
-2,
-1,
-1,
-1,
-1,
-1,
-1,
-2,
],
'Rook': [
0, 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 1, 1, 1, 1, 1, 0.5, -0.5, 0, 0, 0, 0, 0, 0,
-0.5, -0.5, 0, 0, 0, 0, 0, 0, -0.5, -0.5, 0, 0, 0, 0, 0, 0, -0.5, -0.5, 0, 0,
0, 0, 0, 0, -0.5, -0.5, 1, 1, 1, 1, 1, 1, -0.5, 0, 0, 0, 0.5, 0.5, 0, 0, 0
],
'Queen': [
-2, -1, -1, -0.5, -0.5, -1, -1, -2, -1, 0, 0.5, 0, 0, 0.5, 0, -1, -1, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, -1, -0.5, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5, 0, 0, 0.5,
0.5, 0.5, 0, 0, 0, -0.5, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5, -1, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, -1, -2, -1, -1, -0.5, -0.5, -1, -1, -2
],
'King': [
-3, -4, -4, -5, -5, -4, -4, -3, -3, -4, -4, -5, -5, -4, -4, -3, -3, -4, -4,
-5, -5, -4, -4, -3, -3, -4, -4, -5, -5, -4, -4, -3, -2, -3, -3, -4, -4, -3,
-3, -2, -1, -2, -2, -2, -2, -2, -2, -1, 2, 2, 0, 0, 0, 0, 2, 2, 2, 3, 1, 0,
0, 1, 3, 2
],
}

pawn_table = scoring['Pawn']
knight_table = scoring['Knight']
bishop_table = scoring['Bishop']
rook_table = scoring['Rook']
queen_table = scoring['Queen']
king_table = scoring['King']

def evaluate(board):
score = 0.00
pst_score = 0.00
pieces = board.piece_map()
for square, piece in pieces.items():
if piece.color:
score += material[piece.piece_type]
if piece.piece_type == chess.PAWN:
pst_score += pawn_table[square]
elif piece.piece_type == chess.KNIGHT:
pst_score += knight_table[square]
elif piece.piece_type == chess.BISHOP:
pst_score += bishop_table[square]
elif piece.piece_type == chess.ROOK:
pst_score += rook_table[square]
elif piece.piece_type == chess.QUEEN:
pst_score += queen_table[square]
elif piece.piece_type == chess.KING:
pst_score += king_table[square]
else:
score -= material[piece.piece_type]
if piece.piece_type == chess.PAWN:
pst_score -= pawn_table[chess.square_mirror(square)]
elif piece.piece_type == chess.KNIGHT:
pst_score -= knight_table[chess.square_mirror(square)]
elif piece.piece_type == chess.BISHOP:
pst_score -= bishop_table[chess.square_mirror(square)]
elif piece.piece_type == chess.ROOK:
pst_score -= rook_table[chess.square_mirror(square)]
elif piece.piece_type == chess.QUEEN:
pst_score -= queen_table[chess.square_mirror(square)]
elif piece.piece_type == chess.KING:
pst_score -= king_table[chess.square_mirror(square)]
if board.turn == chess.WHITE:
score += 0.4
else:
score -= 0.4
return score + pst_score

def highest_value(BOARD, depth=20, max_time=30):
start_time = time.time()
best_move = None
if BOARD.turn == chess.WHITE:
best_value = -float("inf")
else:
best_value = float("inf")
for d in range(1, depth + 1):
if time.time() - start_time > max_time:
break
for move in BOARD.legal_moves:
BOARD.push(move)
value = alpha_beta_search(BOARD, d)
BOARD.pop()
if BOARD.turn == chess.WHITE:
if value > best_value:
best_value = value
best_move = move
else:
if value < best_value:
best_value = value
best_move = move
return best_move

def alpha_beta_search(board,
depth,
alpha=-float("inf"),
beta=float("inf"),
maximizing_player=True):
if depth == 0 or board.is_game_over():
return evaluate(board)
if maximizing_player:
value = -float("inf")
for move in board.legal_moves:
board.push(move)
value = max(value, alpha_beta_search(board, depth - 1, alpha, beta, False))
board.pop()
alpha = max(alpha, value)
if alpha >= beta:
break
return value
else:
value = float("inf")
for move in board.legal_moves:
board.push(move)
value = min(value, alpha_beta_search(board, depth - 1, alpha, beta, True))
board.pop()
beta = min(beta, value)
if alpha >= beta:
break
return value

while True:

if (len(list(book.find_all(board))) != 0):
board.push(book.weighted_choice(board).move)
time.sleep(1)
print(board)
print("  ")
else:
best_move = highest_value(board)
board.push(best_move)
print(board)
print("  ")
if board.can_claim_draw() == True:
print("draw")
break
```````

What are you decreasing the time for?

So the engine can make a move faster

you mean have it calculate the move faster? Thatās something called doing a PhD. Optimizing algorithms with new innovations is what papers are written about

Yes but what variable are you changing?

1 Like

This is the variable heās changing:

``````def highest_value(BOARD, depth=20, max_time=30):
``````

Also, if you want to decrease the `max_time` you need to make several improvements in your engine (Quiescence Search, Better evaluation function, parallel search, etc)

3 Likes

yes optimizations in general to minmax (heās using minmax right) will help, faster eval, and doing things in thread will make your program faster but I didnāt mean semantics I meant like actually decreasing the big o notation

2 Likes

How would i approach a Quiesence search?

1 Like

you would need to make the package yourself and implement minmax with some optimizations to āunstableā nodes

Is there any way i can improve the evaluate function?

1 Like

ĀÆ\_(ć)_/ĀÆ I mean I donāt see anything but thatās what @WindLother suggested; although, I canāt really find anything that would greatly improve speed

You need to consider more factors, ones that a high level player would do in a normal game, for example, you could take into account pawn structure, piece mobility, king safety, etc.

Taking king safety for example:

``````def king_safety(board):
king = board.king(board.turn)
if king is None:
return 0

safety_score = 0

# make your engine aware of king exposure
for square in chess.SquareSet(chess.BB_KING_ATTACKS[king]):
if square in board.attackers(not board.turn, square):
safety_score -= 1

# Note: you can consider other factors that players use to protect their king, like pawn shield.

return safety_score
``````
2 Likes

This is a good article to start:

1 Like

What would be the code for a quiesence search

They explained better here: Quiescence Search - Chessprogramming wiki

``````import chess
import time
import chess.polyglot
import os
board = chess.Board()
moves = ""
move_num = 0
material = {
chess.PAWN:10.0,
chess.KNIGHT:32.0,
chess.BISHOP:33.3,
chess.ROOK:56.5,
chess.QUEEN:95.5,
chess.KING:200.0

}
scoring = {
'Pawn': [
0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 2, 3, 3, 2, 1, 1, 0, 0,
0, 2, 2, 0, 0, 0, 0, 0, 0, -2, -2, 0, 0, 0, 1, -1, -2, 0, 0, -2, -1, 1, 1, 2,
2, -2, -2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0
],
'Knight': [
-5, -4, -3, -3, -3, -3, -4, -5, -4, -2, 0, 0, 0, 0, -2, -4, -3, 0, 1, 1.5,
1.5, 1, 0, -3, -3, 0.5, 1.5, 2, 2, 1.5, 0.5, -3, -3, 0.5, 1.5, 2, 2, 1.5,
0.5, -3, -3, 0, 1, 1.5, 1.5, 1, 0, -3, -4, -2, 0, 0.5, 0.5, 0, -2, -4, -5,
-4, -3, -3, -3, -3, -4, -5
],
'Bishop': [
-2,
-1,
-1,
-1,
-1,
-1,
-1,
-2,
-1,
0.25,
0,
0,
0,
0,
0.25,
-1,
-1,
0,
1,
1,
1,
1,
0,
-1,
-1,
0,
1,
1.5,
1.5,
1,
0,
-1,
-1,
0,
1,
1.5,
1.5,
1,
0,
-1,
-1,
0,
1,
1,
1,
1,
0,
-1,
-1,
0.25,
0,
0,
0,
0,
0.25,
-1,
-2,
-1,
-1,
-1,
-1,
-1,
-1,
-2,
],
'Rook': [
0, 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 1, 1, 1, 1, 1, 0.5, -0.5, 0, 0, 0, 0, 0, 0,
-0.5, -0.5, 0, 0, 0, 0, 0, 0, -0.5, -0.5, 0, 0, 0, 0, 0, 0, -0.5, -0.5, 0, 0,
0, 0, 0, 0, -0.5, -0.5, 1, 1, 1, 1, 1, 1, -0.5, 0, 0, 0, 0.5, 0.5, 0, 0, 0
],
'Queen': [
-2, -1, -1, -0.5, -0.5, -1, -1, -2, -1, 0, 0.5, 0, 0, 0.5, 0, -1, -1, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, -1, -0.5, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5, 0, 0, 0.5,
0.5, 0.5, 0, 0, 0, -0.5, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5, -1, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, -1, -2, -1, -1, -0.5, -0.5, -1, -1, -2
],
'King': [
-3, -4, -4, -5, -5, -4, -4, -3, -3, -4, -4, -5, -5, -4, -4, -3, -3, -4, -4,
-5, -5, -4, -4, -3, -3, -4, -4, -5, -5, -4, -4, -3, -2, -3, -3, -4, -4, -3,
-3, -2, -1, -2, -2, -2, -2, -2, -2, -1, 2, 2, 0, 0, 0, 0, 2, 2, 2, 3, 1, 0,
0, 1, 3, 2
],
}

pawn_table = scoring['Pawn']
knight_table = scoring['Knight']
bishop_table = scoring['Bishop']
rook_table = scoring['Rook']
queen_table = scoring['Queen']
king_table = scoring['King']

def evaluate(board):
if board.can_claim_draw() or board.is_stalemate() or board.is_insufficient_material():
score = 0.00
pst_score = 0.00
elif board.is_checkmate():
if board.turn == chess.BLACK:
score = float("inf")
pst_score = None
else:
score = -float("inf")
pst_score = None

else:
score = 0.00
pst_score = 0.00
pieces = board.piece_map()
for square, piece in pieces.items():
if piece.color:
score += material[piece.piece_type]
if piece.piece_type == chess.PAWN:
pst_score += pawn_table[square]
elif piece.piece_type == chess.KNIGHT:
pst_score += knight_table[square]
elif piece.piece_type == chess.BISHOP:
pst_score += bishop_table[square]
elif piece.piece_type == chess.ROOK:
pst_score += rook_table[square]
elif piece.piece_type == chess.QUEEN:
pst_score += queen_table[square]
elif piece.piece_type == chess.KING:
pst_score += king_table[square]
else:
score -= material[piece.piece_type]
if piece.piece_type == chess.PAWN:
pst_score -= pawn_table[chess.square_mirror(square)]
elif piece.piece_type == chess.KNIGHT:
pst_score -= knight_table[chess.square_mirror(square)]
elif piece.piece_type == chess.BISHOP:
pst_score -= bishop_table[chess.square_mirror(square)]
elif piece.piece_type == chess.ROOK:
pst_score -= rook_table[chess.square_mirror(square)]
elif piece.piece_type == chess.QUEEN:
pst_score -= queen_table[chess.square_mirror(square)]
elif piece.piece_type == chess.KING:
pst_score -= king_table[chess.square_mirror(square)]
if board.turn == chess.WHITE:
pst_score += 0.4
else:
pst_score -= 0.4
return score + pst_score

threshhold_depth = 20
def highest_value(board):
best_move = None
if board.turn == chess.WHITE:
best_value = -float("inf")
else:
best_value = float("inf")
for d in range(1, threshhold_depth + 1):
for move in board.legal_moves:
board.push(move)
value = alpha_beta_with_quiescence(board, threshhold_depth, float('-inf'), float('inf'), False)
board.pop()
if board.turn == chess.WHITE:
if value > best_value:
best_value = value
best_move = move
else:
if value < best_value:
best_value = value
best_move = move
return best_move

def alpha_beta_with_quiescence(board, depth, alpha, beta, maximizing_player):
if depth == 0 or board.is_game_over():
return evaluate(board)

if maximizing_player:
value = float('-inf')
for move in board.legal_moves:
board.push(move)
if board.is_capture(move):
value = max(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, False))
else:
value = max(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, False))
alpha = max(alpha, value)
board.pop()
if alpha >= beta:
break
return value
else:
value = float('inf')
for move in board.legal_moves:
board.push(move)
if board.is_capture(move):
value = min(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, True))
else:
value = min(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, True))
beta = min(beta, value)
board.pop()
if alpha >= beta:
break
return value

while True:

if (len(list(book.find_all(board))) != 0):
if board.turn == chess.WHITE:
move_num += 1
book_move = book.weighted_choice(board).move
moves = moves + " "+str(move_num) + ". "+str(book_move)
else:
book_move = book.weighted_choice(board).move
moves = moves +" "+ str(book_move) + " "
print(moves)
board.push(book_move)
time.sleep(1)
os.system("clear")
print(board)
else:
best_move = highest_value(board)
if board.turn == chess.WHITE:
move_num += 1
moves = moves + " "+ str(move_num) + ". "+str(best_move)
else:
moves = moves + " "+str(best_move) + " "
board.push(best_move)
os.system("clear")
print(moves)
print(board)
if board.can_claim_draw() == True:
print("draw")
break

``````

This is my new code. Would this be okay?

Click on the link to see other changes

ooh this is defenitely better!
Youāve added piece-square tables for each piece and you are dealing with special situations too.

Oh I also noticed somethings in your quiescence search and I have a few suggestions about your quiescence function (feel free to add them or not).

For example, you do not differ for capture and non-capture moves. The right thing to do is to only continue searching for capture moves when depth reaches 0. I suggest to create a separate function for the quiescence search

``````def quiescence_search(board, alpha, beta, maximizing_player):
if board.is_game_over():
return evaluate(board)

if maximizing_player:
value = float('-inf')
for move in board.legal_moves:
if board.is_capture(move):
board.push(move)
score = -quiescence_search(board, -beta, -alpha, False)
board.pop()

if score >= beta:
return beta
alpha = max(alpha, score)
else:
value = float('inf')
for move in board.legal_moves:
if board.is_capture(move):
board.push(move)
score = -quiescence_search(board, -beta, -alpha, True)
board.pop()

if score <= alpha:
return alpha
beta = min(beta, score)

return alpha if maximizing_player else beta
``````

So when depth reaches 0, the search will only continue for capturing moves.

After that you change your `alpha_beta_with_quiescence` to call the search from before.

``````def alpha_beta_with_quiescence(board, depth, alpha, beta, maximizing_player):
if depth == 0 or board.is_game_over():
return quiescence_search(board, alpha, beta, maximizing_player)

if maximizing_player:
value = float('-inf')
for move in board.legal_moves:
board.push(move)
value = max(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, False))
board.pop()
alpha = max(alpha, value)
if alpha >= beta:
break
else:
value = float('inf')
for move in board.legal_moves:
board.push(move)
value = min(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, True))
board.pop()
beta = min(beta, value)
if beta <= alpha:
break

return alpha if maximizing_player else beta
``````

So your full code to the quiescence function would be:

``````def quiescence_search(board, alpha, beta, maximizing_player):
if board.is_game_over():
return evaluate(board)

if maximizing_player:
value = float('-inf')
for move in board.legal_moves:
if board.is_capture(move):
board.push(move)
score = -quiescence_search(board, -beta, -alpha, False)
board.pop()

if score >= beta:
return beta
alpha = max(alpha, score)
else:
value = float('inf')
for move in board.legal_moves:
if board.is_capture(move):
board.push(move)
score = -quiescence_search(board, -beta, -alpha, True)
board.pop()

if score <= alpha:
return alpha
beta = min(beta, score)

return alpha if maximizing_player else beta

def alpha_beta_with_quiescence(board, depth, alpha, beta, maximizing_player):
if depth == 0 or board.is_game_over():
return quiescence_search(board, alpha, beta, maximizing_player)

if maximizing_player:
value = float('-inf')
for move in board.legal_moves:
board.push(move)
value = max(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, False))
board.pop()
alpha = max(alpha, value)
if alpha >= beta:
break
else:
value = float('inf')
for move in board.legal_moves:
board.push(move)
value = min(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, True))
board.pop()
beta = min(beta, value)
if beta <= alpha:
break

return alpha if maximizing_player else beta
``````

This will make the AI have a better understanding about the consequences of captures and checks that are beyond the maximum search depth.

But again, is only a suggestion! Feel free to make changes that would benefit you more.

2 Likes
``````import chess
import time
import chess.polyglot
import os
import random
board = chess.Board()
moves = ""
move_num = 0
material = {
chess.PAWN:10.0,
chess.KNIGHT:32.0,
chess.BISHOP:33.3,
chess.ROOK:56.5,
chess.QUEEN:95.5,
chess.KING:200.0

}
scoring = {
'Pawn': [
0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 5, 5, 5, 5, 5, 5, 1, 1, 2, 3, 3, 2, 1, 1, 0, 0,
0, 2, 2, 0, 0, 0, 0, 0, 0, -2, -2, 0, 0, 0, 1, -1, -2, 0, 0, -2, -1, 1, 1, 2,
2, -2, -2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0
],
'Knight': [
-5, -4, -3, -3, -3, -3, -4, -5, -4, -2, 0, 0, 0, 0, -2, -4, -3, 0, 1, 1.5,
1.5, 1, 0, -3, -3, 0.5, 1.5, 2, 2, 1.5, 0.5, -3, -3, 0.5, 1.5, 2, 2, 1.5,
0.5, -3, -3, 0, 1, 1.5, 1.5, 1, 0, -3, -4, -2, 0, 0.5, 0.5, 0, -2, -4, -5,
-4, -3, -3, -3, -3, -4, -5
],
'Bishop': [
-2,
-1,
-1,
-1,
-1,
-1,
-1,
-2,
-1,
0.25,
0,
0,
0,
0,
0.25,
-1,
-1,
0,
1,
1,
1,
1,
0,
-1,
-1,
0,
1,
1.5,
1.5,
1,
0,
-1,
-1,
0,
1,
1.5,
1.5,
1,
0,
-1,
-1,
0,
1,
1,
1,
1,
0,
-1,
-1,
0.25,
0,
0,
0,
0,
0.25,
-1,
-2,
-1,
-1,
-1,
-1,
-1,
-1,
-2,
],
'Rook': [
0, 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 1, 1, 1, 1, 1, 0.5, -0.5, 0, 0, 0, 0, 0, 0,
-0.5, -0.5, 0, 0, 0, 0, 0, 0, -0.5, -0.5, 0, 0, 0, 0, 0, 0, -0.5, -0.5, 0, 0,
0, 0, 0, 0, -0.5, -0.5, 1, 1, 1, 1, 1, 1, -0.5, 0, 0, 0, 0.5, 0.5, 0, 0, 0
],
'Queen': [
-2, -1, -1, -0.5, -0.5, -1, -1, -2, -1, 0, 0.5, 0, 0, 0.5, 0, -1, -1, 0.5,
0.5, 0.5, 0.5, 0.5, 0.5, -1, -0.5, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5, 0, 0, 0.5,
0.5, 0.5, 0, 0, 0, -0.5, 0, 0.5, 0.5, 0.5, 0.5, 0, -0.5, -1, 0.5, 0.5, 0.5,
0.5, 0.5, 0.5, -1, -2, -1, -1, -0.5, -0.5, -1, -1, -2
],
'King': [
-3, -4, -4, -5, -5, -4, -4, -3, -3, -4, -4, -5, -5, -4, -4, -3, -3, -4, -4,
-5, -5, -4, -4, -3, -3, -4, -4, -5, -5, -4, -4, -3, -2, -3, -3, -4, -4, -3,
-3, -2, -1, -2, -2, -2, -2, -2, -2, -1, 2, 2, 0, 0, 0, 0, 2, 2, 2, 3, 1, 0,
0, 1, 3, 2
],
}
pawn_table = scoring['Pawn']
knight_table = scoring['Knight']
bishop_table = scoring['Bishop']
rook_table = scoring['Rook']
queen_table = scoring['Queen']
king_table = scoring['King']
def mobility(board):
current = board.turn
board.turn = chess.WHITE
white_moves = len(list(board.legal_moves))
board.turn = chess.BLACK
black_moves = len(list(board.legal_moves))
board.turn = current
mobility_score = 0.4*(white_moves - black_moves)
return mobility_score
def evaluate(board):
if board.can_claim_draw() or board.is_stalemate() or board.is_insufficient_material():
score = 0.00
pst_score = 0.00
elif board.is_checkmate():
if board.turn == chess.BLACK:
score = float("inf")
pst_score = 0.00
else:
score = -float("inf")
pst_score = 0.00
else:
score = 0.00
pst_score = 0.00
pieces = board.piece_map()
for square, piece in pieces.items():
if piece.color:
score += material[piece.piece_type]
if piece.piece_type == chess.PAWN:
pst_score += pawn_table[square]
elif piece.piece_type == chess.KNIGHT:
pst_score += knight_table[square]
elif piece.piece_type == chess.BISHOP:
pst_score += bishop_table[square]
elif piece.piece_type == chess.ROOK:
pst_score += rook_table[square]
elif piece.piece_type == chess.QUEEN:
pst_score += queen_table[square]
elif piece.piece_type == chess.KING:
pst_score += king_table[square]
else:
score -= material[piece.piece_type]
if piece.piece_type == chess.PAWN:
pst_score -= pawn_table[chess.square_mirror(square)]
elif piece.piece_type == chess.KNIGHT:
pst_score -= knight_table[chess.square_mirror(square)]
elif piece.piece_type == chess.BISHOP:
pst_score -= bishop_table[chess.square_mirror(square)]
elif piece.piece_type == chess.ROOK:
pst_score -= rook_table[chess.square_mirror(square)]
elif piece.piece_type == chess.QUEEN:
pst_score -= queen_table[chess.square_mirror(square)]
elif piece.piece_type == chess.KING:
pst_score -= king_table[chess.square_mirror(square)]
if board.turn == chess.WHITE:
pst_score += 0.4
else:
pst_score -=0.4
mobility_score = mobility(board)
pst_score += mobility_score
return score + pst_score

threshhold_depth = 15
def highest_value(board):
start_time = time.time()
best_move = None
if board.turn == chess.WHITE:
best_value = -float("inf")
else:
best_value = float("inf")
for d in range(1, threshhold_depth + 1):
for move in board.legal_moves:
board.push(move)
if board.turn == chess.WHITE:
value = alpha_beta_with_quiescence(board, threshhold_depth, float('-inf'), float('inf'), True)
else:
value = alpha_beta_with_quiescence(board, threshhold_depth, float('-inf'), float('inf'), True)
board.pop()
if board.turn == chess.WHITE:
if value > best_value:
best_value = value
best_move = move
else:
if value < best_value:
best_value = value
best_move = move
if time.time() - start_time >= 5:
if best_move == None:
legals = list(board.legal_moves)
best_move = chess.Move.from_uci(random.choice(legals))
return best_move
break
return best_move

def quiescence_search(board, alpha, beta, maximizing_player):
if board.is_game_over():
return evaluate(board)

if maximizing_player:
value = float('-inf')
for move in board.legal_moves:
if board.is_capture(move):
board.push(move)
score = -quiescence_search(board, -beta, -alpha, False)
board.pop()

if score >= beta:
return beta
alpha = max(alpha, score)
else:
value = float('inf')
for move in board.legal_moves:
if board.is_capture(move):
board.push(move)
score = -quiescence_search(board, -beta, -alpha, True)
board.pop()

if score <= alpha:
return alpha
beta = min(beta, score)

return alpha if maximizing_player else beta

def alpha_beta_with_quiescence(board, depth, alpha, beta, maximizing_player):
if depth == 0 or board.is_game_over():
return quiescence_search(board, alpha, beta, maximizing_player)

if maximizing_player:
value = float('-inf')
for move in board.legal_moves:
board.push(move)
value = max(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, False))
board.pop()
alpha = max(alpha, value)
if alpha >= beta:
break
else:
value = float('inf')
for move in board.legal_moves:
board.push(move)
value = min(value, alpha_beta_with_quiescence(board, depth - 1, alpha, beta, True))
board.pop()
beta = min(beta, value)
if beta <= alpha:
break

return alpha if maximizing_player else beta
while True:

if (len(list(book.find_all(board))) != 0):
if board.turn == chess.WHITE:
move_num += 1
book_move = book.weighted_choice(board).move
moves = moves + " "+str(move_num) + ". "+str(book_move)
else:
book_move = book.weighted_choice(board).move
moves = moves +" "+ str(book_move) + " "
print(moves)
board.push(book_move)
time.sleep(1)
os.system("clear")
print(board)
else:
best_move = highest_value(board)
if board.turn == chess.WHITE:
move_num += 1
moves = moves + " "+ str(move_num) + ". "+str(best_move)
else:
moves = moves + " "+str(best_move) + " "
board.push(best_move)
os.system("clear")
print(moves)
print(board)
if board.can_claim_draw() == True:
print("draw")
break

``````

With this code it is still stuck after book moves and I dont know why

I would need more specific error messages or more details on how itās getting stuck.
Can you add some debugging prints in your `highest_value` function?

(And make sure the opening book is not corrupted)

``````def highest_value(board):
start_time = time.time()
best_move = None
if board.turn == chess.WHITE:
best_value = -float("inf")
else:
best_value = float("inf")
print(f"Initial best_value: {best_value}") # Insert debug print here
for d in range(1, threshhold_depth + 1):
print(f"Depth: {d}") # Here too
for move in board.legal_moves:
board.push(move)
if board.turn == chess.WHITE:
value = alpha_beta_with_quiescence(board, threshhold_depth, float('-inf'), float('inf'), True)
else:
value = alpha_beta_with_quiescence(board, threshhold_depth, float('-inf'), float('inf'), True)
print(f"Move: {move}, Value: {value}") # Another one here
board.pop()
if board.turn == chess.WHITE:
if value > best_value:
best_value = value
best_move = move
else:
if value < best_value:
best_value = value
best_move = move
if time.time() - start_time >= 5:
if best_move == None:
legals = list(board.legal_moves)
best_move = chess.Move.from_uci(random.choice(legals))
print(f"Timeout, selected move: {best_move}") # Here too
return best_move
break
print(f"Selected move: {best_move}") # Final debug, insert here too
return best_move

``````
1 Like