Chess: Rename "AI" to "bot"
This commit is contained in:
parent
6c9d60ca1d
commit
4d43874b87
111
src/chess.lua
111
src/chess.lua
@ -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!")
|
||||||
|
Loading…
Reference in New Issue
Block a user