Chess: Improve draw claim interface

This commit is contained in:
Wuzzy 2023-07-19 16:54:30 +02:00
parent 3faa0317da
commit 9e8474f320

View File

@ -29,6 +29,13 @@ local ENABLE_CHESS_GAMES = true
-- and enables a "Bot vs Bot" gamemode for testing the bot -- and enables a "Bot vs Bot" gamemode for testing the bot
local CHESS_DEBUG = false local CHESS_DEBUG = false
-- Number of consecutive halfmoves in which no pawn was moved
-- and no piece was captured after which a player can claim a draw.
local DRAWCLAIM_LONGGAME_PLAYER = 100 -- 50-move rule
-- Number of consecutive halfmoves in which no pawn was moved
-- and no piece was captured after which the game draw automatically.
local DRAWCLAIM_LONGGAME_FORCE = 150 -- 75-move rule
-- Bot names -- Bot names
local BOT_NAME = NS("Weak Computer") local BOT_NAME = NS("Weak Computer")
-- Bot names in Bot vs Bot mode -- Bot names in Bot vs Bot mode
@ -1757,6 +1764,27 @@ local function update_formspec(meta)
end end
end end
local drawClaim = meta:get_string("drawClaim")
local draw_claim_formstring = ""
if drawClaim ~= "" and gameResult == "" then
if lastMove == "black" or lastMove == "" then
draw_claim_formstring = "label[10.1,6.35;"..FS("DRAW CLAIM\nBY WHITE!").."]"
else
draw_claim_formstring = "label[10.1,6.35;"..FS("DRAW CLAIM\nBY BLACK!").."]"
end
if drawClaim == "50_move_rule" then
eaten_img = ""
draw_claim_formstring = draw_claim_formstring ..
"image[10.05,7.2;2,2;chess_draw_50move_next.png]"..
"textarea[13,6.35;2.2,3.2;;;"..FS("The player has invoked the 50-move rule for the next move. The next move might draw the game.").."]"
elseif drawClaim == "same_position_3" then
eaten_img = ""
draw_claim_formstring = draw_claim_formstring ..
"image[10.05,7.2;2,2;chess_draw_repeat3_next.png]"..
"textarea[13,6.35;2.2,3.2;;;"..FS("The player has invoked the threefold-repetition rule for the next move. The next move might draw the game.").."]"
end
end
-- Resign / Start new game -- Resign / Start new game
local game_buttons = "" local game_buttons = ""
game_buttons = game_buttons .. "button[13.36,0.26;2,0.8;new;"..FS("New game").."]" game_buttons = game_buttons .. "button[13.36,0.26;2,0.8;new;"..FS("New game").."]"
@ -1768,24 +1796,21 @@ local function update_formspec(meta)
"tooltip[resign;"..FS("Resign").."]" "tooltip[resign;"..FS("Resign").."]"
end end
local drawClaim = meta:get_string("drawClaim")
if playerActionsAvailable and drawClaim == "" then if playerActionsAvailable and drawClaim == "" then
-- 50-move rule -- 50-move rule
local halfmoveClock = meta:get_int("halfmoveClock") local halfmoveClock = meta:get_int("halfmoveClock")
if halfmoveClock == 99 then if halfmoveClock == DRAWCLAIM_LONGGAME_PLAYER - 1 then
-- When the 50 moves without capture / pawn move is about to occur. -- When the 50 moves without capture / pawn move is about to occur.
-- 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
game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move_next.png;draw_50_moves;]".. game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move_next.png;draw_50_moves;]"..
"tooltip[draw_50_moves;".. "tooltip[draw_50_moves;"..
FS("Invoke the 50-move rule for your next move.").."\n".. FS("Invoke the 50-move rule for your next move").."]"
FS("If invoked and in the next turn, no piece is captured and no pawn is moved, the game will be drawn.").."]" elseif halfmoveClock >= DRAWCLAIM_LONGGAME_PLAYER then
elseif halfmoveClock >= 100 then
-- When the 50 moves without capture / pawn move have occured occur. -- When the 50 moves without capture / pawn move have occured occur.
-- Will insta-draw. -- Will insta-draw.
game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move.png;draw_50_moves;]".. game_buttons = game_buttons .. "image_button[13.36,9.7;0.8,0.8;chess_draw_50move.png;draw_50_moves;]"..
"tooltip[draw_50_moves;".. "tooltip[draw_50_moves;"..
FS("Invoke the 50-move rule and draw the game.").."\n".. FS("Invoke the 50-move rule and draw the game").."]"
FS("(In the last 50 moves of each player, no pawn moved and no piece was captured.)").."]"
end end
-- Threefold repetition rule -- Threefold repetition rule
@ -1797,37 +1822,16 @@ local function update_formspec(meta)
-- Will insta-draw. -- Will insta-draw.
game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3.png;draw_repeat_3;]".. game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3.png;draw_repeat_3;]"..
"tooltip[draw_repeat_3;".. "tooltip[draw_repeat_3;"..
FS("Invoke the threefold repetition rule and draw the game.").."\n".. FS("Invoke the threefold repetition rule and draw the game").."]"
FS("(The same position has occured at least 3 times.)").."]"
elseif maxRepeatedPositions >= 2 then elseif maxRepeatedPositions >= 2 then
-- If the same position may be about to occur 3 times. -- If the same position may be 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.
game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3_next.png;draw_repeat_3;]".. game_buttons = game_buttons .. "image_button[12.36,9.7;0.8,0.8;chess_draw_repeat3_next.png;draw_repeat_3;]"..
"tooltip[draw_repeat_3;".. "tooltip[draw_repeat_3;"..
FS("Invoke the threefold repetition rule for your next move.").."\n".. FS("Invoke the threefold repetition rule for your next move").."]"
FS("If invoked and the next move repeats a position for a 3rd time, the game will be drawn.").."]"
end end
end end
local s_draw_claim = ""
-- Change interface when in "draw claim" mode to make the move
-- that triggers the draw condition
if drawClaim == "50_move_rule" then
eaten_img = ""
s_draw_claim = "" ..
"image[13.36,9.7;0.8,0.8;chess_draw_50move_next.png]" ..
"tooltip[13.36,9.7;0.8,0.8;"..
FS("Draw claim active: 50-move rule").."\n"..
FS("If no pawn moves and no capture occurs in the next move, the game is drawn.").."]"
elseif drawClaim == "same_position_3" then
eaten_img = ""
s_draw_claim = "" ..
"image[12.36,9.7;0.8,0.8;chess_draw_repeat3_next.png]" ..
"tooltip[12.36,9.7;0.8,0.8;"..
FS("Draw claim active: Threefold repetition").."\n"..
FS("If the next move repeats the same position for a 3rd time, the game is drawn.").."]"
end
local debug_formstring = "" local debug_formstring = ""
if CHESS_DEBUG then if CHESS_DEBUG then
-- Write a debug string in the formspec based on FEN -- Write a debug string in the formspec based on FEN
@ -1868,8 +1872,8 @@ local function update_formspec(meta)
"label[2.2,10.21;" .. turnWhite .. minetest.formspec_escape(status_white) .. "]" .. "label[2.2,10.21;" .. turnWhite .. minetest.formspec_escape(status_white) .. "]" ..
whiteArr .. whiteArr ..
"table[9.9,1.25;5.45,4;moves;" .. moves .. ";"..mlistlen.."]" .. "table[9.9,1.25;5.45,4;moves;" .. moves .. ";"..mlistlen.."]" ..
s_draw_claim ..
promotion_formstring .. promotion_formstring ..
draw_claim_formstring ..
eaten_img .. eaten_img ..
game_buttons .. game_buttons ..
debug_formstring debug_formstring
@ -1987,19 +1991,20 @@ local function update_game_result(meta)
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by dead position") minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw by dead position")
end end
local drawClaim = meta:get_string("drawClaim")
-- 75-move rule. Automatically draw game if the last 75 moves of EACH player (thus 150 halfmoves) -- 75-move rule. Automatically draw game if the last 75 moves of EACH player (thus 150 halfmoves)
-- neither moved a pawn or captured a piece. -- neither moved a pawn or captured a piece.
-- Important: This rule MUST be checked AFTER checkmate because checkmate takes precedence. -- Important: This rule MUST be checked AFTER checkmate because checkmate takes precedence.
if meta:get_int("halfmoveClock") >= 150 then if meta:get_int("halfmoveClock") >= DRAWCLAIM_LONGGAME_FORCE then
meta:set_string("gameResult", "draw") meta:set_string("gameResult", "draw")
meta:set_string("gameResultReason", "75_move_rule") meta:set_string("gameResultReason", "75_move_rule")
add_special_to_moves_list(meta, "draw") add_special_to_moves_list(meta, "draw")
local msg = S("No piece was captured and no pawn was moved for 75 consecutive moves of each player. It's a draw!") local msg = S("No piece was captured and no pawn was moved for 75 consecutive moves of each player. It's a draw!")
send_message_2(playerWhite, playerBlack, msg, botColor) send_message_2(playerWhite, playerBlack, msg, botColor)
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw via the 75-move rule") minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw via the 75-move rule")
-- 50-move rule, after a player issued a draw claim when the halfmove clock was at 99. -- 50-move rule, after a player issued a draw claim for their next move.
-- If no pawn moved nor a piece was captured for >= 100 halfmoves, the game is drawn. -- If no pawn moved nor a piece was captured for >= 100 halfmoves, the game is drawn.
elseif meta:get_int("halfmoveClock") >= 100 and meta:get_string("drawClaim") == "50_move_rule" then elseif meta:get_int("halfmoveClock") >= DRAWCLAIM_LONGGAME_PLAYER and drawClaim == "50_move_rule" then
meta:set_string("drawClaim", "") meta:set_string("drawClaim", "")
meta:set_string("gameResult", "draw") meta:set_string("gameResult", "draw")
meta:set_string("gameResultReason", "50_move_rule") meta:set_string("gameResultReason", "50_move_rule")
@ -2018,7 +2023,7 @@ local function update_game_result(meta)
send_message(other, S("@1 has drawn the game by invoking the 50-move rule.", claimer), botColor) send_message(other, S("@1 has drawn the game by invoking the 50-move rule.", claimer), botColor)
end end
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because "..claimer.." has invoked the 50-move rule") minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because "..claimer.." has invoked the 50-move rule")
elseif meta:get_string("drawClaim") == "50_move_rule" then elseif drawClaim == "50_move_rule" then
local claimer, other local claimer, other
if lastMove == "black" or lastMove == "" then if lastMove == "black" or lastMove == "" then
claimer = playerWhite claimer = playerWhite
@ -2102,7 +2107,7 @@ local function update_game_result(meta)
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because the same position has appeared 5 times") minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because the same position has appeared 5 times")
-- threefold repetition -- threefold repetition
elseif chosenRepetitionDraw and meta:get_string("drawClaim") == "same_position_3" then elseif chosenRepetitionDraw and drawClaim == "same_position_3" then
meta:set_string("drawClaim", "") meta:set_string("drawClaim", "")
meta:set_string("gameResult", "draw") meta:set_string("gameResult", "draw")
meta:set_string("gameResultReason", "same_position_3") meta:set_string("gameResultReason", "same_position_3")
@ -2121,7 +2126,7 @@ local function update_game_result(meta)
send_message(other, S("@1 has drawn the game by invoking the threefold repetition rule.", claimer), botColor) send_message(other, S("@1 has drawn the game by invoking the threefold repetition rule.", claimer), botColor)
end end
minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because "..claimer.." has invoked the threefold repetition rule") minetest.log("action", "[xdecor] Chess: A game between "..playerWhite.." and "..playerBlack.." ended in a draw because "..claimer.." has invoked the threefold repetition rule")
elseif meta:get_string("drawClaim") == "same_position_3" then elseif drawClaim == "same_position_3" then
local claimer, other local claimer, other
if lastMove == "black" or lastMove == "" then if lastMove == "black" or lastMove == "" then
claimer = playerWhite claimer = playerWhite
@ -2917,7 +2922,7 @@ function realchess.fields(pos, _, fields, sender)
end end
local halfmoveClock = meta:get_int("halfmoveClock") local halfmoveClock = meta:get_int("halfmoveClock")
if halfmoveClock >= 100 then if halfmoveClock >= DRAWCLAIM_LONGGAME_PLAYER then
meta:set_string("gameResult", "draw") meta:set_string("gameResult", "draw")
meta:set_string("gameResultReason", "50_move_rule") meta:set_string("gameResultReason", "50_move_rule")
add_special_to_moves_list(meta, "draw") add_special_to_moves_list(meta, "draw")