Chess: Simplify checks for king safe moves in bot

This commit is contained in:
Wuzzy 2023-07-19 18:00:07 +02:00
parent 2828e5644a
commit 9fd4bafee7
2 changed files with 25 additions and 54 deletions

View File

@ -884,7 +884,7 @@ end
-- * theoretical_moves: moves table returned by realchess.get_theoretical_moves_for()
-- * board: board table
-- * player: player color ("white" or "black")
function realchess.get_king_safe_move(theoretical_moves, board, player)
function realchess.get_king_safe_moves(theoretical_moves, board, player)
local safe_moves = {}
local safe_moves_count = 0
-- create a virtual board
@ -1917,19 +1917,19 @@ local function update_game_result(meta)
king_idx = black_king_idx
end
-- King attacked? This reduces the list of available moves,
-- so remove these, too and check if there are still any left.
-- King attacked?
local isKingAttacked = realchess.attacked(checkPlayer, king_idx, board_t)
if isKingAttacked then
meta:set_string(checkPlayer.."Attacked", "true")
local _, save_moves = realchess.get_king_safe_move(checkMoves, board_t, checkPlayer)
-- If not safe moves left, player can't move
if save_moves == 0 then
if checkPlayer == "black" then
blackCanMove = false
else
whiteCanMove = false
end
end
-- If not safe moves left, player can't move
local safe_moves, safe_moves_count = realchess.get_king_safe_moves(checkMoves, board_t, checkPlayer)
if safe_moves_count == 0 then
if checkPlayer == "black" then
blackCanMove = false
else
whiteCanMove = false
end
end

View File

@ -66,9 +66,13 @@ function chessbot.move(inv, meta)
botName = meta:get_string("playerBlack")
end
if (lastMove == opponentColor or ((botColor == "white" or botColor == "both") and lastMove == "")) and gameResult == "" then
local moves = realchess.get_theoretical_moves_for(meta, board_t, currentBotColor)
local choice_from, choice_to = best_move(moves)
local moves = realchess.get_theoretical_moves_for(meta, board_t, currentBotColor)
local safe_moves, safe_moves_count = realchess.get_king_safe_moves(moves, board_t, currentBotColor)
if safe_moves_count == 0 then
-- No safe move: stalemate or checkmate
end
local choice_from, choice_to = best_move(safe_moves)
if choice_from == nil then
-- No best move: stalemate or checkmate
return
@ -77,26 +81,6 @@ function chessbot.move(inv, meta)
local pieceFrom = inv:get_stack("board", choice_from):get_name()
local pieceTo = inv:get_stack("board", choice_to):get_name()
local black_king_idx, white_king_idx = realchess.locate_kings(board_t)
local bot_king_idx
if currentBotColor == "black" then
bot_king_idx = black_king_idx
else
bot_king_idx = white_king_idx
end
local botAttacked = realchess.attacked(currentBotColor, bot_king_idx, board_t)
local kingSafe = true
local bestMoveSaveFrom, bestMoveSaveTo
if botAttacked then
kingSafe = false
meta:set_string(currentBotColor.."Attacked", "true")
local safe_moves, save_moves_count = realchess.get_king_safe_move(moves, board_t, currentBotColor)
if save_moves_count >= 1 then
bestMoveSaveFrom, bestMoveSaveTo = best_move(safe_moves)
end
end
minetest.after(BOT_DELAY_MOVE, function()
local gameResult = meta:get_string("gameResult")
if gameResult ~= "" then
@ -109,33 +93,20 @@ function chessbot.move(inv, meta)
local lastMove = meta:get_string("lastMove")
local lastMoveTime = meta:get_int("lastMoveTime")
if lastMoveTime > 0 or lastMove == "" then
-- Set the bot name if not set already
if currentBotColor == "black" and meta:get_string("playerBlack") == "" then
meta:set_string("playerBlack", botName)
elseif currentBotColor == "white" and meta:get_string("playerWhite") == "" then
meta:set_string("playerWhite", botName)
end
local moveOK = false
if not kingSafe then
-- Make a move to put the king out of check
if bestMoveSaveTo ~= nil then
moveOK = realchess.move(meta, "board", bestMoveSaveFrom, "board", bestMoveSaveTo, botName)
if not moveOK then
minetest.log("error", "[xdecor] Chess: Bot tried to make an invalid move (to protect the king) from "..
realchess.index_to_notation(bestMoveSaveFrom).." to "..realchess.index_to_notation(bestMoveSaveTo))
end
else
-- No safe move left: checkmate or stalemate
return
end
else
-- Make a regular move
moveOK = realchess.move(meta, "board", choice_from, "board", choice_to, botName)
if not moveOK then
minetest.log("error", "[xdecor] Chess: Bot tried to make an invalid move from "..
realchess.index_to_notation(choice_from).." to "..realchess.index_to_notation(choice_to))
end
-- Make a move
local moveOK = realchess.move(meta, "board", choice_from, "board", choice_to, botName)
if not moveOK then
minetest.log("error", "[xdecor] Chess: Bot tried to make an invalid move from "..
realchess.index_to_notation(choice_from).." to "..realchess.index_to_notation(choice_to))
end
-- Bot resigns if it made an incorrect move
-- Bot resigns if it tried to make an invalid move
if not moveOK then
realchess.resign(meta, currentBotColor)
end