Chess: Restrict 'same position' rule a bit
This commit is contained in:
parent
05be3093d5
commit
95b28937d7
@ -1245,12 +1245,28 @@ local function get_positions_history(meta)
|
|||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Record the position no. of the position from which
|
||||||
|
-- all positions before that can be ignored
|
||||||
|
-- when counting same positions.
|
||||||
|
-- This number is updated each time an irreversible
|
||||||
|
-- move is made:
|
||||||
|
-- * pawn move
|
||||||
|
-- * capturing move
|
||||||
|
-- * loss of castling rights
|
||||||
|
-- * loss of (theoretical) en passant availability
|
||||||
|
-- This works cuz when an irreversible move is made,
|
||||||
|
-- it is impossible for this and all positions before
|
||||||
|
-- that to occur again so the "repetition counter"
|
||||||
|
-- for each of these position never increases again.
|
||||||
|
local no_repetitions_before = 1
|
||||||
|
|
||||||
local moves_raw = meta:get_string("moves_raw")
|
local moves_raw = meta:get_string("moves_raw")
|
||||||
local moves_split = string.split(moves_raw, ";")
|
local moves_split = string.split(moves_raw, ";")
|
||||||
local positions_list = ""
|
local positions_list = ""
|
||||||
local board = table.copy(starting_grid)
|
local board = table.copy(starting_grid)
|
||||||
local castling_state = { true, true, true, true }
|
local castling_state = { true, true, true, true }
|
||||||
local castling_str = castling_to_string(unpack(castling_state))
|
local castling_str = castling_to_string(unpack(castling_state))
|
||||||
|
local pawn_double_step_index
|
||||||
positions_list = {}
|
positions_list = {}
|
||||||
|
|
||||||
local current_player = "w"
|
local current_player = "w"
|
||||||
@ -1273,6 +1289,11 @@ local function get_positions_history(meta)
|
|||||||
else
|
else
|
||||||
current_player = "w"
|
current_player = "w"
|
||||||
end
|
end
|
||||||
|
-- Reset repetition counter on piece capture
|
||||||
|
if pieceTo ~= "" then
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
|
|
||||||
-- Piece movement
|
-- Piece movement
|
||||||
board[to_idx] = board[from_idx]
|
board[to_idx] = board[from_idx]
|
||||||
board[from_idx] = ""
|
board[from_idx] = ""
|
||||||
@ -1291,24 +1312,34 @@ local function get_positions_history(meta)
|
|||||||
if (from_x == 4 and to_x == 2) then
|
if (from_x == 4 and to_x == 2) then
|
||||||
board[60] = board[57]
|
board[60] = board[57]
|
||||||
board[57] = ""
|
board[57] = ""
|
||||||
|
no_repetitions_before = m
|
||||||
elseif (from_x == 4 and to_x == 6) then
|
elseif (from_x == 4 and to_x == 6) then
|
||||||
board[62] = board[64]
|
board[62] = board[64]
|
||||||
board[64] = ""
|
board[64] = ""
|
||||||
|
no_repetitions_before = m
|
||||||
end
|
end
|
||||||
elseif (from_y == 0 and to_y == 0) then
|
elseif (from_y == 0 and to_y == 0) then
|
||||||
if (from_x == 4 and to_x == 2) then
|
if (from_x == 4 and to_x == 2) then
|
||||||
board[4] = board[1]
|
board[4] = board[1]
|
||||||
board[1] = ""
|
board[1] = ""
|
||||||
|
no_repetitions_before = m
|
||||||
elseif (from_x == 4 and to_x == 6) then
|
elseif (from_x == 4 and to_x == 6) then
|
||||||
board[6] = board[8]
|
board[6] = board[8]
|
||||||
board[8] = ""
|
board[8] = ""
|
||||||
|
no_repetitions_before = m
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Lose castling rights on any king move
|
-- Lose castling rights on any king move
|
||||||
if pieceFrom:find("white") then
|
if pieceFrom:find("white") then
|
||||||
|
if castling_state[1] or castling_state[2] then
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
castling_state[1] = false
|
castling_state[1] = false
|
||||||
castling_state[2] = false
|
castling_state[2] = false
|
||||||
else
|
else
|
||||||
|
if castling_state[3] or castling_state[4] then
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
castling_state[3] = false
|
castling_state[3] = false
|
||||||
castling_state[4] = false
|
castling_state[4] = false
|
||||||
end
|
end
|
||||||
@ -1317,20 +1348,43 @@ local function get_positions_history(meta)
|
|||||||
elseif pieceFrom:sub(11,14) == "rook" then
|
elseif pieceFrom:sub(11,14) == "rook" then
|
||||||
if from_idx == 57 then
|
if from_idx == 57 then
|
||||||
-- white queenside
|
-- white queenside
|
||||||
castling_state[2] = false
|
if castling_state[2] then
|
||||||
|
castling_state[2] = false
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
elseif from_idx == 64 then
|
elseif from_idx == 64 then
|
||||||
-- white kingside
|
-- white kingside
|
||||||
castling_state[1] = false
|
if castling_state[1] then
|
||||||
|
castling_state[1] = false
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
elseif from_idx == 1 then
|
elseif from_idx == 1 then
|
||||||
-- black queenside
|
-- black queenside
|
||||||
castling_state[4] = false
|
if castling_state[4] then
|
||||||
|
castling_state[4] = false
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
elseif from_idx == 8 then
|
elseif from_idx == 8 then
|
||||||
-- black kingside
|
-- black kingside
|
||||||
castling_state[3] = false
|
if castling_state[3] then
|
||||||
|
castling_state[3] = false
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local pawn_double_step_index
|
-- Pawn movement resets repetition counter
|
||||||
|
if pieceFrom:sub(11,14) == "pawn" then
|
||||||
|
no_repetitions_before = m
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Loss of (theoretical) en passant capture availability
|
||||||
|
-- resets repetition counter
|
||||||
|
if pawn_double_step_index then
|
||||||
|
no_repetitions_before = m
|
||||||
|
pawn_double_step_index = nil
|
||||||
|
end
|
||||||
|
|
||||||
if pieceTo == "" and pieceFrom:sub(11,14) == "pawn" then
|
if pieceTo == "" and pieceFrom:sub(11,14) == "pawn" then
|
||||||
-- En passant (remove captured pawn)
|
-- En passant (remove captured pawn)
|
||||||
if from_x ~= to_x then
|
if from_x ~= to_x then
|
||||||
@ -1341,7 +1395,7 @@ local function get_positions_history(meta)
|
|||||||
epp_y = to_y - 1
|
epp_y = to_y - 1
|
||||||
end
|
end
|
||||||
board[xy_to_index(to_x, epp_y)] = ""
|
board[xy_to_index(to_x, epp_y)] = ""
|
||||||
-- Double pawn step (record positoin)
|
-- Double pawn step (record pos)
|
||||||
elseif math.abs(from_y-to_y) == 2 then
|
elseif math.abs(from_y-to_y) == 2 then
|
||||||
pawn_double_step_index = to_idx
|
pawn_double_step_index = to_idx
|
||||||
end
|
end
|
||||||
@ -1356,7 +1410,7 @@ local function get_positions_history(meta)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local p=#positions_list
|
local p=#positions_list
|
||||||
return positions_list
|
return positions_list, no_repetitions_before
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns the highest number of positions that are repeated
|
-- Returns the highest number of positions that are repeated
|
||||||
@ -1364,11 +1418,13 @@ end
|
|||||||
-- Arguments:
|
-- Arguments:
|
||||||
-- * positions: positions history list returned by get_position_history()
|
-- * positions: positions history list returned by get_position_history()
|
||||||
-- * stop_counting_at: stop counting when this many repetitons have been found (optional)
|
-- * stop_counting_at: stop counting when this many repetitons have been found (optional)
|
||||||
local function count_repeated_positions(positions, stop_counting_at)
|
-- * first_position: index of first position to check (default: 1)
|
||||||
|
local function count_repeated_positions(positions, stop_counting_at, first_position)
|
||||||
-- Count how often each position occurred
|
-- Count how often each position occurred
|
||||||
local positions_counter = {}
|
local positions_counter = {}
|
||||||
local maxRepeatedPositions = 0
|
local maxRepeatedPositions = 0
|
||||||
for p = 1, #positions do
|
first_position = first_position or 1
|
||||||
|
for p = first_position, #positions do
|
||||||
local position = positions[p]
|
local position = positions[p]
|
||||||
if positions_counter[position] == nil then
|
if positions_counter[position] == nil then
|
||||||
positions_counter[position] = 1
|
positions_counter[position] = 1
|
||||||
@ -1733,8 +1789,8 @@ local function update_formspec(meta)
|
|||||||
|
|
||||||
-- "same position has occured 3 times" rule
|
-- "same position has occured 3 times" rule
|
||||||
-- Count how often each position occurred
|
-- Count how often each position occurred
|
||||||
local positions = get_positions_history(meta)
|
local positions, first_p = get_positions_history(meta)
|
||||||
local maxRepeatedPositions = count_repeated_positions(positions, 3)
|
local maxRepeatedPositions = count_repeated_positions(positions, 3, first_p)
|
||||||
if maxRepeatedPositions == 2 then
|
if maxRepeatedPositions == 2 then
|
||||||
-- If the same position is about to occur 3 times.
|
-- If the same position is about to occur 3 times.
|
||||||
-- Will trigger "draw claim" mode in which player must do the final move that triggers the draw.
|
-- Will trigger "draw claim" mode in which player must do the final move that triggers the draw.
|
||||||
@ -1969,9 +2025,9 @@ local function update_game_result(meta)
|
|||||||
-- First, generate the position history
|
-- First, generate the position history
|
||||||
local forceRepetitionDraw = false
|
local forceRepetitionDraw = false
|
||||||
local chosenRepetitionDraw = false
|
local chosenRepetitionDraw = false
|
||||||
local positions = get_positions_history(meta)
|
local positions, first_p = get_positions_history(meta)
|
||||||
-- Then count the repeated positions
|
-- Then count the repeated positions
|
||||||
local maxRepeatedPositions = count_repeated_positions(positions, 5)
|
local maxRepeatedPositions = count_repeated_positions(positions, 5, first_p)
|
||||||
if maxRepeatedPositions >= 3 then
|
if maxRepeatedPositions >= 3 then
|
||||||
chosenRepetitionDraw = true
|
chosenRepetitionDraw = true
|
||||||
end
|
end
|
||||||
@ -2878,8 +2934,8 @@ function realchess.fields(pos, _, fields, sender)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local positions = get_positions_history(meta)
|
local positions, first_p = get_positions_history(meta)
|
||||||
local maxRepeatedPositions = count_repeated_positions(positions, 3)
|
local maxRepeatedPositions = count_repeated_positions(positions, 3, first_p)
|
||||||
if maxRepeatedPositions == 2 then
|
if maxRepeatedPositions == 2 then
|
||||||
meta:set_string("drawClaim", "same_position_3")
|
meta:set_string("drawClaim", "same_position_3")
|
||||||
update_formspec(meta)
|
update_formspec(meta)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user