Chess: Rename "AI" to "bot"

This commit is contained in:
Wuzzy 2023-07-16 20:16:57 +02:00
parent 6c9d60ca1d
commit 4d43874b87

View File

@ -3,9 +3,11 @@ local S = minetest.get_translator("xdecor")
local FS = function(...) return minetest.formspec_escape(S(...)) end local FS = function(...) return minetest.formspec_escape(S(...)) end
local ALPHA_OPAQUE = minetest.features.use_texture_alpha_string_modes and "opaque" or false local ALPHA_OPAQUE = minetest.features.use_texture_alpha_string_modes and "opaque" or false
local AI_NAME = S("Dumb AI") -- Note: Asterisks added to avoid confusion with a player name
local AI_DELAY_MOVE = 1.0 -- because asterisks are forbidden in player names.
local AI_DELAY_PROMOTE = 1.0 local BOT_NAME = "*"..S("Weak Computer").."*"
local BOT_DELAY_MOVE = 1.0
local BOT_DELAY_PROMOTE = 1.0
screwdriver = screwdriver or {} screwdriver = screwdriver or {}
@ -315,7 +317,7 @@ end
-- * from_idx: -- * from_idx:
-- returns: table with the keys used as destination indices -- returns: table with the keys used as destination indices
-- Any key with a numeric value is a possible destination. -- Any key with a numeric value is a possible destination.
-- The numeric value is a move rating for AI and is 0 by default. -- The numeric value is a move rating for the bot and is 0 by default.
-- Example: { [4] = 0, [9] = 0 } -- can move to squares 4 and 9 -- Example: { [4] = 0, [9] = 0 } -- can move to squares 4 and 9
local function get_theoretical_moves_from(meta, board, from_idx) local function get_theoretical_moves_from(meta, board, from_idx)
local piece, color = board[from_idx]:match(":(%w+)_(%w+)") local piece, color = board[from_idx]:match(":(%w+)_(%w+)")
@ -748,7 +750,7 @@ end
-- } -- }
-- origin_index is the board index for the square to start the piece from (as string) -- origin_index is the board index for the square to start the piece from (as string)
-- and this is the key for a list of destination indixes. -- and this is the key for a list of destination indixes.
-- r1, r2, r3 ... are numeric values (normally 0) to "rate" this square for AI. -- r1, r2, r3 ... are numeric values (normally 0) to "rate" this square for the bot.
local function get_theoretical_moves_for(meta, board, player) local function get_theoretical_moves_for(meta, board, player)
local moves = {} local moves = {}
for i = 1, 64 do for i = 1, 64 do
@ -1463,7 +1465,7 @@ local function update_formspec(meta)
promotion = meta:get_string("promotionActive") promotion = meta:get_string("promotionActive")
end end
local promotion_formstring = "" local promotion_formstring = ""
local aiColor = meta:get_string("aiColor") local botColor = meta:get_string("botColor")
-- Show promotion prompt to ask player to choose to which piece to promote a pawn to -- Show promotion prompt to ask player to choose to which piece to promote a pawn to
if promotion == "black" then if promotion == "black" then
@ -1471,7 +1473,7 @@ local function update_formspec(meta)
promotion_formstring = promotion_formstring =
"label[10.1,6.35;"..FS("PROMOTION\nFOR BLACK!").."]" .. "label[10.1,6.35;"..FS("PROMOTION\nFOR BLACK!").."]" ..
"animated_image[10.05,7.2;2,2;p_img_white;pawn_black_promo_anim.png;5;100]" "animated_image[10.05,7.2;2,2;p_img_white;pawn_black_promo_anim.png;5;100]"
if aiColor ~= "black" then if botColor ~= "black" then
-- Hide buttons if computer player promotes -- Hide buttons if computer player promotes
promotion_formstring = promotion_formstring .. promotion_formstring = promotion_formstring ..
"label[13.15,6.35;"..FS("Promote pawn to:").."]" .. "label[13.15,6.35;"..FS("Promote pawn to:").."]" ..
@ -1486,7 +1488,7 @@ local function update_formspec(meta)
promotion_formstring = promotion_formstring =
"label[10.1,6.35;"..FS("PROMOTION\nFOR WHITE!").."]" .. "label[10.1,6.35;"..FS("PROMOTION\nFOR WHITE!").."]" ..
"animated_image[10.05,7.2;2,2;p_img_white;pawn_white_promo_anim.png;5;100]" "animated_image[10.05,7.2;2,2;p_img_white;pawn_white_promo_anim.png;5;100]"
if aiColor ~= "white" then if botColor ~= "white" then
-- Hide buttons if computer player promotes -- Hide buttons if computer player promotes
promotion_formstring = promotion_formstring .. promotion_formstring = promotion_formstring ..
"label[13.15,6.35;"..FS("Promote pawn to:").."]" .. "label[13.15,6.35;"..FS("Promote pawn to:").."]" ..
@ -1735,7 +1737,7 @@ function realchess.init(pos)
meta:set_string("infotext", S("Chess Board")) meta:set_string("infotext", S("Chess Board"))
meta:set_string("playerBlack", "") meta:set_string("playerBlack", "")
meta:set_string("playerWhite", "") meta:set_string("playerWhite", "")
meta:set_string("aiColor", "") meta:set_string("botColor", "")
meta:set_string("lastMove", "") meta:set_string("lastMove", "")
meta:set_string("gameResult", "") meta:set_string("gameResult", "")
meta:set_string("gameResultReason", "") meta:set_string("gameResultReason", "")
@ -2334,24 +2336,24 @@ function realchess.move(meta, from_list, from_index, to_list, to_index, playerNa
return true return true
end end
local function ai_move(inv, meta) local function bot_move(inv, meta)
local board_t = board_to_table(inv) local board_t = board_to_table(inv)
local lastMove = meta:get_string("lastMove") local lastMove = meta:get_string("lastMove")
local gameResult = meta:get_string("gameResult") local gameResult = meta:get_string("gameResult")
local aiColor = meta:get_string("aiColor") local botColor = meta:get_string("botColor")
if aiColor == "" then if botColor == "" then
aiColor = "black" botColor = "black"
end end
local opponentColor local opponentColor
if aiColor == "black" then if botColor == "black" then
opponentColor = "white" opponentColor = "white"
else else
opponentColor = "black" opponentColor = "black"
end end
if (lastMove == opponentColor or (aiColor == "white" and lastMove == "")) and gameResult == "" then if (lastMove == opponentColor or (botColor == "white" and lastMove == "")) and gameResult == "" then
update_formspec(meta) update_formspec(meta)
local moves = get_theoretical_moves_for(meta, board_t, aiColor) local moves = get_theoretical_moves_for(meta, board_t, botColor)
local choice_from, choice_to = best_move(moves) local choice_from, choice_to = best_move(moves)
if choice_from == nil then if choice_from == nil then
@ -2364,26 +2366,26 @@ local function ai_move(inv, meta)
local board = board_to_table(inv) local board = board_to_table(inv)
local black_king_idx, white_king_idx = locate_kings(board) local black_king_idx, white_king_idx = locate_kings(board)
local ai_king_idx local bot_king_idx
if aiColor == "black" then if botColor == "black" then
ai_king_idx = black_king_idx bot_king_idx = black_king_idx
else else
ai_king_idx = white_king_idx bot_king_idx = white_king_idx
end end
local aiAttacked = attacked(aiColor, ai_king_idx, board) local botAttacked = attacked(botColor, bot_king_idx, board)
local kingSafe = true local kingSafe = true
local bestMoveSaveFrom, bestMoveSaveTo local bestMoveSaveFrom, bestMoveSaveTo
if aiAttacked then if botAttacked then
kingSafe = false kingSafe = false
meta:set_string(aiColor.."Attacked", "true") meta:set_string(botColor.."Attacked", "true")
local is_safe, safe_moves = has_king_safe_move(moves, board, aiColor) local is_safe, safe_moves = has_king_safe_move(moves, board, botColor)
if is_safe then if is_safe then
bestMoveSaveFrom, bestMoveSaveTo = best_move(safe_moves) bestMoveSaveFrom, bestMoveSaveTo = best_move(safe_moves)
end end
end end
minetest.after(AI_DELAY_MOVE, function() minetest.after(BOT_DELAY_MOVE, function()
local gameResult = meta:get_string("gameResult") local gameResult = meta:get_string("gameResult")
if gameResult ~= "" then if gameResult ~= "" then
return return
@ -2391,18 +2393,18 @@ local function ai_move(inv, meta)
local lastMove = meta:get_string("lastMove") local lastMove = meta:get_string("lastMove")
local lastMoveTime = meta:get_int("lastMoveTime") local lastMoveTime = meta:get_int("lastMoveTime")
if lastMoveTime > 0 or lastMove == "" then if lastMoveTime > 0 or lastMove == "" then
if aiColor == "black" and meta:get_string("playerBlack") == "" then if botColor == "black" and meta:get_string("playerBlack") == "" then
meta:set_string("playerBlack", AI_NAME) meta:set_string("playerBlack", BOT_NAME)
elseif aiColor == "white" and meta:get_string("playerWhite") == "" then elseif botColor == "white" and meta:get_string("playerWhite") == "" then
meta:set_string("playerWhite", AI_NAME) meta:set_string("playerWhite", BOT_NAME)
end end
local moveOK = false local moveOK = false
if not kingSafe then if not kingSafe then
-- Make a move to put the king out of check -- Make a move to put the king out of check
if bestMoveSaveTo ~= nil then if bestMoveSaveTo ~= nil then
moveOK = realchess.move(meta, "board", bestMoveSaveFrom, "board", bestMoveSaveTo, AI_NAME) moveOK = realchess.move(meta, "board", bestMoveSaveFrom, "board", bestMoveSaveTo, BOT_NAME)
if not moveOK then if not moveOK then
minetest.log("error", "[xdecor] Chess: AI tried to make an invalid move (to protect the king) from ".. minetest.log("error", "[xdecor] Chess: Bot tried to make an invalid move (to protect the king) from "..
index_to_notation(bestMoveSaveFrom).." to "..index_to_notation(bestMoveSaveTo)) index_to_notation(bestMoveSaveFrom).." to "..index_to_notation(bestMoveSaveTo))
end end
else else
@ -2410,16 +2412,16 @@ local function ai_move(inv, meta)
end end
else else
-- Make a regular move -- Make a regular move
moveOK = realchess.move(meta, "board", choice_from, "board", choice_to, AI_NAME) moveOK = realchess.move(meta, "board", choice_from, "board", choice_to, BOT_NAME)
if not moveOK then if not moveOK then
minetest.log("error", "[xdecor] Chess: AI tried to make an invalid move from ".. minetest.log("error", "[xdecor] Chess: Bot tried to make an invalid move from "..
index_to_notation(choice_from).." to "..index_to_notation(choice_to)) index_to_notation(choice_from).." to "..index_to_notation(choice_to))
end end
end end
-- AI resigns if it made an incorrect move -- Bot resigns if it made an incorrect move
if not moveOK then if not moveOK then
meta:set_string("gameResultReason", "resign") meta:set_string("gameResultReason", "resign")
if aiColor == "black" then if botColor == "black" then
meta:set_string("gameResult", "whiteWon") meta:set_string("gameResult", "whiteWon")
add_special_to_moves_list(meta, "whiteWon") add_special_to_moves_list(meta, "whiteWon")
else else
@ -2435,11 +2437,11 @@ local function ai_move(inv, meta)
end end
end end
local function ai_promote(inv, meta, pawnIndex) local function bot_promote(inv, meta, pawnIndex)
minetest.after(AI_DELAY_MOVE, function() minetest.after(BOT_DELAY_MOVE, function()
local aiColor = meta:get_string("aiColor") local botColor = meta:get_string("botColor")
-- Always promote to queen -- Always promote to queen
realchess.promote_pawn(meta, aiColor, "queen") realchess.promote_pawn(meta, botColor, "queen")
end) end)
end end
@ -2470,13 +2472,13 @@ function realchess.fields(pos, _, fields, sender)
if fields.single_w or fields.single_b or fields.multi then if fields.single_w or fields.single_b or fields.multi then
meta:set_string("mode", ((fields.single_w or fields.single_b) and "single" or "multi")) meta:set_string("mode", ((fields.single_w or fields.single_b) and "single" or "multi"))
if fields.single_w then if fields.single_w then
meta:set_string("aiColor", "black") meta:set_string("botColor", "black")
meta:set_string("playerBlack", AI_NAME) meta:set_string("playerBlack", BOT_NAME)
elseif fields.single_b then elseif fields.single_b then
meta:set_string("aiColor", "white") meta:set_string("botColor", "white")
meta:set_string("playerWhite", AI_NAME) meta:set_string("playerWhite", BOT_NAME)
local inv = meta:get_inventory() local inv = meta:get_inventory()
ai_move(inv, meta) bot_move(inv, meta)
end end
update_formspec(meta) update_formspec(meta)
return return
@ -2633,17 +2635,16 @@ function realchess.move_piece(meta, pieceFrom, from_list, from_index, to_list, t
end end
update_formspec(meta) update_formspec(meta)
local aiColor = meta:get_string("aiColor") local botColor = meta:get_string("botColor")
if aiColor == "" then aiColor = "black" end if botColor == "" then botColor = "black" end
local lastMove = meta:get_string("lastMove") local lastMove = meta:get_string("lastMove")
if lastMove == "" then lastMove = "black" end if lastMove == "" then lastMove = "black" end
-- The AI always plays black; make sure it doesn't move twice in the case of a swap: -- Let the bot play when it its turn
-- Only let it play if it didn't already play. if meta:get_string("mode") == "single" and lastMove ~= botColor and meta:get_string("gameResult") == "" then
if meta:get_string("mode") == "single" and lastMove ~= aiColor and meta:get_string("gameResult") == "" then
if not promo then if not promo then
ai_move(inv, meta) bot_move(inv, meta)
else else
ai_promote(inv, meta, to_index) bot_promote(inv, meta, to_index)
end end
end end
end end
@ -2725,12 +2726,12 @@ function realchess.promote_pawn(meta, color, promoteTo)
realchess.update_state(meta, from_idx, to_idx, color, promoteFrom:get_name(), pstr) realchess.update_state(meta, from_idx, to_idx, color, promoteFrom:get_name(), pstr)
update_formspec(meta) update_formspec(meta)
local aiColor = meta:get_string("aiColor") local botColor = meta:get_string("botColor")
if aiColor == "" then aiColor = "black" end if botColor == "" then botColor = "black" end
local lastMove = meta:get_string("lastMove") local lastMove = meta:get_string("lastMove")
if lastMove == "" then lastMove = "black" end if lastMove == "" then lastMove = "black" end
if meta:get_string("mode") == "single" and lastMove ~= aiColor and meta:get_string("gameResult") == "" then if meta:get_string("mode") == "single" and lastMove ~= botColor and meta:get_string("gameResult") == "" then
ai_move(inv, meta) bot_move(inv, meta)
end end
else else
minetest.log("error", "[xdecor] Chess: Could not find pawn to promote!") minetest.log("error", "[xdecor] Chess: Could not find pawn to promote!")