First i have to say that i do not fully understand your code, because i dont speak Czech. Also i think your "negamax" algorithm is called minimax (its the same as the one i once programmed and i the tutorials i followed it was called minimax)
But I found your mistake. Your evaluate_board function does only check for draw or checkmate. If none of both conditions are met, it returns None. Then in your negamax function if the evaluation is None and if the depth == 0, 0 gets returned.
So your engine thinks the position is a draw no matter what. You will need some logic to actually evaluate the position. You should rewrite this:
to something like this:
You are already checking if the game is over before your if statement, so you can remove board.is_game_over(). Then you will have to write logic to assign a given position a value which determines if the position is good or bad. I would recommend to count the pieces for the beginning
I have a rather simple chess endgame Python code implementinng `negamax strategy` given below but it behaves strange.
Negamax means that when both players play fully rationally the best move leading to the quickest mate or the longest defense by both sides.
It prints correctly this position, but the best move `Kb2c2` is not even considered when I have printed all legal moves.
I'm even unable to force the code `consider` at any stage of searching the best move by white king `K`.
I would like if some can dig into the code and tell me what's wrong **huh**
The output:
. . . . . . . .
. . . k . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. K . p . . . .
. . . . . . . .
Na tahu je: bílý (white to move in Czech language)
b2c3
<LegalMoveGenerator at 0x1d473d26b50 (Ke8, Kd8, Kc8, Ke7, Kc7, Ke6, Kd6, Kc6, d1=Q, d1=R, d1=B, d1=N+)>
<LegalMoveGenerator at 0x1d473d26250 (Kd4, Kc4, Kb4, Kd3, Kb3, Kxd2, Kc2, Kb2)>
<LegalMoveGenerator at 0x1d473d24050 (Kf8, Kd8, Kf7, Ke7, Kd7, d1=Q+, d1=R+, d1=B, d1=N)>
<LegalMoveGenerator at 0x1d473d25e10 (Ke5, Kd5, Kc5, Ke4, Kc4, Ke3, Kd3, Kc3)>
<LegalMoveGenerator at 0x1d473d25110 (Kg8, Ke8, Kg7, Kf7, Ke7, d1=Q, d1=R, d1=B, d1=N)>
<LegalMoveGenerator at 0x1d473d27110 (Kf6, Ke6, Kd6, Kf5, Kd5, Kf4, Ke4, Kd4)>
The code:
[python]import chess
import time
import threading
# Globální proměnná pro sledování počtu prohledaných pozic
positions_count = 0
def update_positions_count(last_time_printed):
global positions_count
while not board.is_game_over():
if time.time() - last_time_printed > 1:
print(f"\rProhledaných pozic: {positions_count}", end='')
last_time_printed = time.time()
def evaluate_board(board, depth):
global positions_count
positions_count += 1
if board.is_checkmate():
return 10000 - depth
if board.is_stalemate() or board.can_claim_draw():
return 0
return None
# ... negamax, find_best_move ...
# Negamax algoritmus
def negamax(board, depth, alpha, beta, color):
evaluated = evaluate_board(board, depth)
if evaluated is not None:
return color * evaluated
if depth == 0 or board.is_game_over():
return 0
max_eval = float('-inf')
print(board.legal_moves)
for move in board.legal_moves:
board.push(move)
eval = -negamax(board, depth - 1, -beta, -alpha, -color)
board.pop()
max_eval = max(max_eval, eval)
alpha = max(alpha, eval)
if alpha >= beta:
break
return max_eval
def find_best_move(board, depth):
best_move = None
best_value = float('-inf')
alpha = float('-inf')
beta = float('inf')
color = 1 if board.turn else -1
print(f"Na tahu je: {'bílý' if board.turn else 'černý'}")
for move in board.legal_moves:
print(move.uci()) # Vypíše tahy ve formátu UCI
if move.uci() == "c1c2": # Příklad pro tah bílého krále
print("HERE")
board.push(move)
board_value = -negamax(board, depth - 1, -beta, -alpha, -color)
board.pop()
if board_value > best_value:
best_value = board_value
best_move = move
return best_move
# Hlavní část kódu
#start_position = "8/8/8/8/8/7Q/k7/2K5 w - - 0 1"
#start_position = "8/3k4/8/8/8/8/1K6/8 w - - 0 1"
start_position = "8/3k4/8/8/8/8/1K1p4/8 w - - 0 1"
board = chess.Board(start_position)
depth = 11 # Můžete zvážit snížení hloubky pro rychlejší výsledky
last_time_printed = time.time()
positions_count_thread = threading.Thread(target=update_positions_count, args=(last_time_printed,), daemon=True)
positions_count_thread.start()
print(board)
print()
while not board.is_game_over():
best_move = find_best_move(board, depth)
if best_move is not None:
board.push(best_move)
print("\n", board) # Vytiskne šachovnici po provedení nejlepšího tahu
else:
print("Žádný další legální tah není možný.")
break
print("\nKonec hry")[/python]