Chess: Refactor en passant implementation

This commit is contained in:
Wuzzy 2023-07-16 08:36:19 +02:00
parent f88aa3a4aa
commit e28f2a1844

View File

@ -224,6 +224,23 @@ local function can_castle(meta, board, from_list, from_idx, to_idx)
end end
-- Checks if a square to check if there is a piece that can be captured en passant. Returns true if this
-- is the case, false otherwise.
-- Parameters:
-- * meta: chessboard node metadata
-- * victim_color: color of the opponent to capture a piece from. "white" or "black". (so in White's turn, pass "black" here)
-- * victim_index: board index of the square where you expect the victim to be
local function can_capture_en_passant(meta, victim_color, victim_index)
local inv = meta:get_inventory()
local victimPiece = inv:get_stack("board", victim_index)
local double_step_index = meta:get_int("prevDoublePawnStepTo")
local victim_name = victimPiece:get_name()
if double_step_index ~= 0 and double_step_index == victim_index and victim_name:find(victim_color) and victim_name:sub(11,14) == "pawn" then
return true
end
return false
end
-- Returns all theoretically possible moves from a given -- Returns all theoretically possible moves from a given
-- square, according to the piece it occupies. Ignores restrictions like check, etc. -- square, according to the piece it occupies. Ignores restrictions like check, etc.
-- If the square is empty, no moves are returned. -- If the square is empty, no moves are returned.
@ -271,18 +288,9 @@ local function get_theoretical_moves_from(meta, board, from_idx)
can_capture = true can_capture = true
else else
-- en passant -- en passant
local inv = meta:get_inventory() if can_capture_en_passant(meta, "black", xy_to_index(to_x, from_y)) then
local enPassantPiece = inv:get_stack("board", xy_to_index(to_x, from_y)) can_capture = true
local epp_meta = enPassantPiece:get_meta() en_passant = true
local epp_name = enPassantPiece:get_name()
if epp_name:find("black") and epp_name:sub(11,14) == "pawn" then
local pawn_no = epp_name:sub(-1)
local double_step_halfmove = meta:get_int("doublePawnStepB"..pawn_no)
local current_halfmove = get_current_halfmove(meta)
if double_step_halfmove ~= 0 and double_step_halfmove == current_halfmove then
can_capture = true
en_passant = true
end
end end
end end
if not can_capture then if not can_capture then
@ -335,18 +343,9 @@ local function get_theoretical_moves_from(meta, board, from_idx)
can_capture = true can_capture = true
else else
-- en passant -- en passant
local inv = meta:get_inventory() if can_capture_en_passant(meta, "white", xy_to_index(to_x, from_y)) then
local enPassantPiece = inv:get_stack("board", xy_to_index(to_x, from_y)) can_capture = true
local epp_meta = enPassantPiece:get_meta() en_passant = true
local epp_name = enPassantPiece:get_name()
if epp_name:find("white") and epp_name:sub(11,14) == "pawn" then
local pawn_no = epp_name:sub(-1)
local double_step_halfmove = meta:get_int("doublePawnStepW"..pawn_no)
local current_halfmove = get_current_halfmove(meta)
if double_step_halfmove ~= 0 and double_step_halfmove == current_halfmove then
can_capture = true
en_passant = true
end
end end
end end
if not can_capture then if not can_capture then
@ -1398,6 +1397,7 @@ function realchess.init(pos)
meta:set_int("castlingWhiteR", 1) meta:set_int("castlingWhiteR", 1)
meta:set_int("promotionPawnFromIdx", 0) meta:set_int("promotionPawnFromIdx", 0)
meta:set_int("promotionPawnToIdx", 0) meta:set_int("promotionPawnToIdx", 0)
meta:set_int("prevDoublePawnStepTo", 0)
meta:set_string("moves_raw", "") meta:set_string("moves_raw", "")
meta:set_string("eaten", "") meta:set_string("eaten", "")
@ -1499,6 +1499,7 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, player)
local to_x, to_y = index_to_xy(to_index) local to_x, to_y = index_to_xy(to_index)
local promotion = false local promotion = false
local doublePawnStep = nil
-- PAWN -- PAWN
if pieceFrom:sub(11,14) == "pawn" then if pieceFrom:sub(11,14) == "pawn" then
@ -1533,12 +1534,8 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, player)
if pieceTo ~= "" or from_y < 6 or pawnWhiteMove ~= "" then if pieceTo ~= "" or from_y < 6 or pawnWhiteMove ~= "" then
return return
end end
-- store this double step in meta (needed for en passant check) -- store the destination of this double step in meta (needed for en passant check)
local pawn_no = pieceFrom:sub(-1) doublePawnStep = to_index
local moves_raw = meta:get_string("moves_raw")
local mrsplit = string.split(moves_raw, ";")
local halfmove_no = #mrsplit + 1
meta:set_int("doublePawnStepW"..pawn_no, halfmove_no)
else else
return return
end end
@ -1564,17 +1561,9 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, player)
can_capture = true can_capture = true
else else
-- en passant -- en passant
local enPassantPiece = inv:get_stack(to_list, xy_to_index(to_x, from_y)) if can_capture_en_passant(meta, "black", xy_to_index(to_x, from_y)) then
local epp_meta = enPassantPiece:get_meta() can_capture = true
local epp_name = enPassantPiece:get_name() inv:set_stack(to_list, xy_to_index(to_x, from_y), "")
if epp_name:find("black") and epp_name:sub(11,14) == "pawn" then
local pawn_no = epp_name:sub(-1)
local double_step_halfmove = meta:get_int("doublePawnStepB"..pawn_no)
local current_halfmove = get_current_halfmove(meta)
if double_step_halfmove ~= 0 and double_step_halfmove == current_halfmove then
can_capture = true
inv:set_stack(to_list, xy_to_index(to_x, from_y), "")
end
end end
end end
if not can_capture then if not can_capture then
@ -1615,12 +1604,8 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, player)
if pieceTo ~= "" or from_y > 1 or pawnBlackMove ~= "" then if pieceTo ~= "" or from_y > 1 or pawnBlackMove ~= "" then
return return
end end
-- store this double step in meta (needed for en passant check) -- store the destination of this double step in meta (needed for en passant check)
local pawn_no = pieceFrom:sub(-1) doublePawnStep = to_index
local moves_raw = meta:get_string("moves_raw")
local mrsplit = string.split(moves_raw, ";")
local halfmove_no = #mrsplit + 1
meta:set_int("doublePawnStepB"..pawn_no, halfmove_no)
else else
return return
end end
@ -1646,17 +1631,9 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, player)
can_capture = true can_capture = true
else else
-- en passant -- en passant
local enPassantPiece = inv:get_stack(to_list, xy_to_index(to_x, from_y)) if can_capture_en_passant(meta, "white", xy_to_index(to_x, from_y)) then
local epp_meta = enPassantPiece:get_meta() can_capture = true
local epp_name = enPassantPiece:get_name() inv:set_stack(to_list, xy_to_index(to_x, from_y), "")
if epp_name:find("white") and epp_name:sub(11,14) == "pawn" then
local pawn_no = epp_name:sub(-1)
local double_step_halfmove = meta:get_int("doublePawnStepW"..pawn_no)
local current_halfmove = get_current_halfmove(meta)
if double_step_halfmove ~= 0 and double_step_halfmove == current_halfmove then
can_capture = true
inv:set_stack(to_list, xy_to_index(to_x, from_y), "")
end
end end
end end
if not can_capture then if not can_capture then
@ -1961,6 +1938,11 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, player)
if not promotion then if not promotion then
realchess.update_state(meta, from_index, to_index, thisMove) realchess.update_state(meta, from_index, to_index, thisMove)
end end
if doublePawnStep then
meta:set_int("prevDoublePawnStepTo", doublePawnStep)
else
meta:set_int("prevDoublePawnStepTo", 0)
end
if meta:get_string("playerWhite") == "" then if meta:get_string("playerWhite") == "" then
meta:set_string("playerWhite", playerWhite) meta:set_string("playerWhite", playerWhite)