diff --git a/src/chess.lua b/src/chess.lua index b098330..bcf5766 100644 --- a/src/chess.lua +++ b/src/chess.lua @@ -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 diff --git a/src/chessbot.lua b/src/chessbot.lua index df6bed4..b467af9 100644 --- a/src/chessbot.lua +++ b/src/chessbot.lua @@ -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