Chess: Teach "AI" to play as White
This commit is contained in:
parent
3e8a155895
commit
a4a6b1005e
@ -963,6 +963,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("lastMove", "")
|
meta:set_string("lastMove", "")
|
||||||
meta:set_string("gameResult", "")
|
meta:set_string("gameResult", "")
|
||||||
meta:set_string("gameResultReason", "")
|
meta:set_string("gameResultReason", "")
|
||||||
@ -1624,8 +1625,17 @@ local function ai_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")
|
||||||
if lastMove == "white" and gameResult == "" then
|
if aiColor == "" then
|
||||||
|
aiColor = "black"
|
||||||
|
end
|
||||||
|
local opponentColor
|
||||||
|
if aiColor == "black" then
|
||||||
|
opponentColor = "white"
|
||||||
|
else
|
||||||
|
opponentColor = "black"
|
||||||
|
end
|
||||||
|
if (lastMove == opponentColor or (aiColor == "white" and lastMove == "")) and gameResult == "" then
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
local moves = {}
|
local moves = {}
|
||||||
|
|
||||||
@ -1633,7 +1643,7 @@ local function ai_move(inv, meta)
|
|||||||
local possibleMoves = get_possible_moves(board_t, i)
|
local possibleMoves = get_possible_moves(board_t, i)
|
||||||
local stack_name = inv:get_stack("board", i):get_name()
|
local stack_name = inv:get_stack("board", i):get_name()
|
||||||
|
|
||||||
if stack_name:find("black") then
|
if stack_name:find(aiColor) then
|
||||||
moves[tostring(i)] = possibleMoves
|
moves[tostring(i)] = possibleMoves
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1649,14 +1659,20 @@ local function ai_move(inv, meta)
|
|||||||
local pieceTo_s = pieceTo ~= "" and pieceTo:match(":(%w+_%w+)") or ""
|
local pieceTo_s = pieceTo ~= "" and pieceTo:match(":(%w+_%w+)") or ""
|
||||||
|
|
||||||
local board = board_to_table(inv)
|
local board = board_to_table(inv)
|
||||||
local black_king_idx = locate_kings(board)
|
local black_king_idx, white_king_idx = locate_kings(board)
|
||||||
local blackAttacked = attacked("black", black_king_idx, board)
|
local ai_king_idx
|
||||||
|
if aiColor == "black" then
|
||||||
|
ai_king_idx = black_king_idx
|
||||||
|
else
|
||||||
|
ai_king_idx = white_king_idx
|
||||||
|
end
|
||||||
|
local aiAttacked = attacked(aiColor, ai_king_idx, board)
|
||||||
local kingSafe = true
|
local kingSafe = true
|
||||||
local bestMoveSaveFrom, bestMoveSaveTo
|
local bestMoveSaveFrom, bestMoveSaveTo
|
||||||
|
|
||||||
if blackAttacked then
|
if aiAttacked then
|
||||||
kingSafe = false
|
kingSafe = false
|
||||||
meta:set_string("blackAttacked", "true")
|
meta:set_string(aiColor.."Attacked", "true")
|
||||||
local save_moves = {}
|
local save_moves = {}
|
||||||
|
|
||||||
for from_idx, _ in pairs(moves) do
|
for from_idx, _ in pairs(moves) do
|
||||||
@ -1665,11 +1681,15 @@ local function ai_move(inv, meta)
|
|||||||
local from_idx_bak, to_idx_bak = board[from_idx], board[to_idx]
|
local from_idx_bak, to_idx_bak = board[from_idx], board[to_idx]
|
||||||
board[to_idx] = board[from_idx]
|
board[to_idx] = board[from_idx]
|
||||||
board[from_idx] = ""
|
board[from_idx] = ""
|
||||||
black_king_idx = locate_kings(board)
|
black_king_idx, white_king_idx = locate_kings(board)
|
||||||
|
if aiColor == "black" then
|
||||||
if black_king_idx then
|
ai_king_idx = black_king_idx
|
||||||
blackAttacked = attacked("black", black_king_idx, board)
|
else
|
||||||
if not blackAttacked then
|
ai_king_idx = white_king_idx
|
||||||
|
end
|
||||||
|
if ai_king_idx then
|
||||||
|
aiAttacked = attacked(aiColor, ai_king_idx, board)
|
||||||
|
if not aiAttacked then
|
||||||
save_moves[from_idx] = save_moves[from_idx] or {}
|
save_moves[from_idx] = save_moves[from_idx] or {}
|
||||||
save_moves[from_idx][to_idx] = value
|
save_moves[from_idx][to_idx] = value
|
||||||
end
|
end
|
||||||
@ -1689,19 +1709,22 @@ local function ai_move(inv, meta)
|
|||||||
if gameResult ~= "" then
|
if gameResult ~= "" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local lastMove = meta:get_string("lastMove")
|
||||||
local lastMoveTime = meta:get_int("lastMoveTime")
|
local lastMoveTime = meta:get_int("lastMoveTime")
|
||||||
if lastMoveTime > 0 then
|
if lastMoveTime > 0 or lastMove == "" then
|
||||||
if not kingSafe then
|
if not kingSafe then
|
||||||
if bestMoveSaveTo ~= nil then
|
if bestMoveSaveTo ~= nil then
|
||||||
inv:set_stack("board", bestMoveSaveTo, board[bestMoveSaveFrom])
|
inv:set_stack("board", bestMoveSaveTo, board[bestMoveSaveFrom])
|
||||||
inv:set_stack("board", bestMoveSaveFrom, "")
|
inv:set_stack("board", bestMoveSaveFrom, "")
|
||||||
meta:set_string("blackAttacked", "")
|
meta:set_string(aiColor.."Attacked", "")
|
||||||
else
|
else
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if pieceFrom:find("pawn") and choice_to >= 57 and choice_to <= 64 then
|
if aiColor == "black" and pieceFrom:find("pawn") and choice_to >= 57 and choice_to <= 64 then
|
||||||
inv:set_stack("board", choice_to, "realchess:queen_black")
|
inv:set_stack("board", choice_to, "realchess:queen_black")
|
||||||
|
elseif aiColor == "white" and pieceFrom:find("pawn") and choice_to >= 1 and choice_to <= 8 then
|
||||||
|
inv:set_stack("board", choice_to, "realchess:queen_white")
|
||||||
else
|
else
|
||||||
inv:set_stack("board", choice_to, pieceFrom)
|
inv:set_stack("board", choice_to, pieceFrom)
|
||||||
end
|
end
|
||||||
@ -1710,18 +1733,26 @@ local function ai_move(inv, meta)
|
|||||||
end
|
end
|
||||||
|
|
||||||
board = board_to_table(inv)
|
board = board_to_table(inv)
|
||||||
local _, white_king_idx = locate_kings(board)
|
black_king_idx, white_king_idx = locate_kings(board)
|
||||||
local whiteAttacked = attacked("white", white_king_idx, board)
|
local opponent_king_idx
|
||||||
|
if opponentColor == "white" then
|
||||||
|
opponent_king_idx = white_king_idx
|
||||||
|
else
|
||||||
|
opponent_king_idx = black_king_idx
|
||||||
|
end
|
||||||
|
local opponentAttacked = attacked(opponentColor, opponent_king_idx, board)
|
||||||
|
|
||||||
if whiteAttacked then
|
if opponentAttacked then
|
||||||
meta:set_string("whiteAttacked", "true")
|
meta:set_string(opponentColor.."Attacked", "true")
|
||||||
end
|
end
|
||||||
|
|
||||||
if meta:get_string("playerBlack") == "" then
|
if aiColor == "black" and meta:get_string("playerBlack") == "" then
|
||||||
meta:set_string("playerBlack", AI_NAME)
|
meta:set_string("playerBlack", AI_NAME)
|
||||||
|
elseif aiColor == "white" and meta:get_string("playerWhite") == "" then
|
||||||
|
meta:set_string("playerWhite", AI_NAME)
|
||||||
end
|
end
|
||||||
|
|
||||||
meta:set_string("lastMove", "black")
|
meta:set_string("lastMove", aiColor)
|
||||||
meta:set_int("lastMoveTime", minetest.get_gametime())
|
meta:set_int("lastMoveTime", minetest.get_gametime())
|
||||||
|
|
||||||
add_move_to_moves_list(meta, pieceFrom, pieceTo, pieceTo_s, choice_from, choice_to)
|
add_move_to_moves_list(meta, pieceFrom, pieceTo, pieceTo_s, choice_from, choice_to)
|
||||||
@ -1729,6 +1760,7 @@ local function ai_move(inv, meta)
|
|||||||
update_game_result(meta)
|
update_game_result(meta)
|
||||||
|
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
|
else
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
else
|
else
|
||||||
@ -1762,15 +1794,26 @@ function realchess.fields(pos, _, fields, sender)
|
|||||||
if fields.single or fields.multi then
|
if fields.single or fields.multi then
|
||||||
meta:set_string("mode", (fields.single and "single" or "multi"))
|
meta:set_string("mode", (fields.single and "single" or "multi"))
|
||||||
if fields.single then
|
if fields.single then
|
||||||
|
-- AI plays a random color at random
|
||||||
|
local r = math.random(1,2)
|
||||||
|
if r == 1 then
|
||||||
|
meta:set_string("aiColor", "black")
|
||||||
meta:set_string("playerBlack", AI_NAME)
|
meta:set_string("playerBlack", AI_NAME)
|
||||||
|
else
|
||||||
|
meta:set_string("aiColor", "white")
|
||||||
|
meta:set_string("playerWhite", AI_NAME)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
ai_move(inv, meta)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Timeout is 5 min. by default for resetting the game (non-players only)
|
-- Timeout is 5 min. by default for resetting the game (non-players only)
|
||||||
|
-- Also allow instant reset before White and Black moved
|
||||||
if fields.new then
|
if fields.new then
|
||||||
if (playerWhite == playerName or playerBlack == playerName or playerWhite == "") then
|
if (playerWhite == playerName or playerBlack == playerName or playerWhite == "" or playerBlack == "") then
|
||||||
realchess.init(pos)
|
realchess.init(pos)
|
||||||
|
|
||||||
elseif lastMoveTime > 0 then
|
elseif lastMoveTime > 0 then
|
||||||
@ -1914,9 +1957,13 @@ 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")
|
||||||
|
if aiColor == "" then aiColor = "black" end
|
||||||
|
local lastMove = meta:get_string("lastMove")
|
||||||
|
if lastMove == "" then lastMove = "black" end
|
||||||
-- The AI always plays black; make sure it doesn't move twice in the case of a swap:
|
-- The AI always plays black; make sure it doesn't move twice in the case of a swap:
|
||||||
-- Only let it play if it didn't already play.
|
-- Only let it play if it didn't already play.
|
||||||
if meta:get_string("mode") == "single" and meta:get_string("lastMove") ~= "black" and meta:get_string("gameResult") == "" and not promo then
|
if meta:get_string("mode") == "single" and lastMove ~= aiColor and meta:get_string("gameResult") == "" and not promo then
|
||||||
ai_move(inv, meta)
|
ai_move(inv, meta)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1994,7 +2041,11 @@ function realchess.promote_pawn(meta, color, promoteTo)
|
|||||||
realchess.update_state(meta, from_idx, to_idx, color, stack:get_name())
|
realchess.update_state(meta, from_idx, to_idx, color, stack:get_name())
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
|
|
||||||
if meta:get_string("mode") == "single" and meta:get_string("lastMove") ~= "black" and meta:get_string("gameResult") == "" then
|
local aiColor = meta:get_string("aiColor")
|
||||||
|
if aiColor == "" then aiColor = "black" end
|
||||||
|
local lastMove = meta:get_string("lastMove")
|
||||||
|
if lastMove == "" then lastMove = "black" end
|
||||||
|
if meta:get_string("mode") == "single" and lastMove ~= aiColor and meta:get_string("gameResult") == "" then
|
||||||
ai_move(inv, meta)
|
ai_move(inv, meta)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
Loading…
Reference in New Issue
Block a user