From ed931905bec87b54063fe468b1ea3a54ebd64fcf Mon Sep 17 00:00:00 2001 From: Jean-Patrick Guerrero Date: Sat, 25 Aug 2018 12:55:03 +0200 Subject: [PATCH] Fix checkmate logic --- src/chess.lua | 105 ++++++++++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 46 deletions(-) diff --git a/src/chess.lua b/src/chess.lua index 1931490..53d05f1 100644 --- a/src/chess.lua +++ b/src/chess.lua @@ -27,7 +27,16 @@ local rookThreats = {false, true, false, true, true, false, true, false} local queenThreats = {true, true, true, true, true, true, true, true} local kingThreats = {true, true, true, true, true, true, true, true} -local function attacked(color, idx, inv) +local function board_to_table(inv) + local t = {} + for i = 1, 64 do + t[#t + 1] = inv:get_stack("board", i):get_name() + end + + return t +end + +local function attacked(color, idx, board) local threatDetected = false local kill = color == "white" local pawnThreats = {kill, false, kill, false, false, not kill, false, not kill} @@ -43,7 +52,7 @@ local function attacked(color, idx, inv) if row >= 1 and row <= 8 and col >= 1 and col <= 8 then local square = get_square(row, col) - local square_name = inv:get_stack("board", square):get_name() + local square_name = board[square] local piece, pieceColor = square_name:match(":(%w+)_(%w+)") if piece then @@ -75,10 +84,10 @@ local function attacked(color, idx, inv) return threatDetected end -local function locate_kings(inv) +local function locate_kings(board) local Bidx, Widx for i = 1, 64 do - local piece, color = inv:get_stack("board", i):get_name():match(":(%w+)_(%w+)") + local piece, color = board[i]:match(":(%w+)_(%w+)") if piece == "king" then if color == "black" then Bidx = i @@ -683,22 +692,25 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, _, player meta:set_int("castlingWhiteL", 0) meta:set_int("castlingWhiteR", 0) - local whiteAttacked = attacked("white", to_index, inv) - if whiteAttacked then - return 0 - end - elseif thisMove == "black" then meta:set_int("castlingBlackL", 0) meta:set_int("castlingBlackR", 0) - - local blackAttacked = attacked("black", to_index, inv) - if blackAttacked then - return 0 - end end end + local board = board_to_table(inv) + board[to_index] = board[from_index] + board[from_index] = "" + + local black_king_idx, white_king_idx = locate_kings(board) + local blackAttacked = attacked("black", black_king_idx, board) + local whiteAttacked = attacked("white", white_king_idx, board) + + if (thisMove == "black" and blackAttacked) or + (thisMove == "white" and whiteAttacked) then + return 0 + end + lastMove = thisMove meta:set_string("lastMove", lastMove) @@ -713,6 +725,39 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, _, player return 1 end +function realchess.on_move(pos, from_list, from_index) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + inv:set_stack(from_list, from_index, '') + + local board = board_to_table(inv) + local black_king_idx, white_king_idx = locate_kings(board) + local black_king_attacked = attacked("black", black_king_idx, board) + local white_king_attacked = attacked("white", white_king_idx, board) + + local playerWhite = meta:get_string("playerWhite") + local playerBlack = meta:get_string("playerBlack") + + local moves = meta:get_string("moves") + local eaten_img = meta:get_string("eaten_img") + local lastMove = meta:get_string("lastMove") + local turnBlack = minetest.colorize("#000001", (lastMove == "white" and playerBlack ~= "") and + playerBlack .. "..." or playerBlack) + local turnWhite = minetest.colorize("#000001", (lastMove == "black" and playerWhite ~= "") and + playerWhite .. "..." or playerWhite) + local check_s = minetest.colorize("#FF0000", "\\[check\\]") + + local formspec = fs .. + "label[1.9,0.3;" .. turnBlack .. (black_king_attacked and " " .. check_s or "") .. "]" .. + "label[1.9,9.15;" .. turnWhite .. (white_king_attacked and " " .. check_s or "") .. "]" .. + "table[8.9,1.05;5.07,3.75;moves;" .. moves:sub(1,-2) .. ";1]" .. + eaten_img + + meta:set_string("formspec", formspec) + + return false +end + local function timeout_format(timeout_limit) local time_remaining = timeout_limit - minetest.get_gametime() local minutes = math.floor(time_remaining / 60) @@ -771,38 +816,6 @@ function realchess.dig(pos, player) timeout_format(timeout_limit)) end -function realchess.on_move(pos, from_list, from_index) - local meta = minetest.get_meta(pos) - local inv = meta:get_inventory() - inv:set_stack(from_list, from_index, '') - - local black_king_idx, white_king_idx = locate_kings(inv) - local black_king_attacked = attacked("black", black_king_idx, inv) - local white_king_attacked = attacked("white", white_king_idx, inv) - - local playerWhite = meta:get_string("playerWhite") - local playerBlack = meta:get_string("playerBlack") - - local moves = meta:get_string("moves") - local eaten_img = meta:get_string("eaten_img") - local lastMove = meta:get_string("lastMove") - local turnBlack = minetest.colorize("#000001", (lastMove == "white" and playerBlack ~= "") and - playerBlack .. "..." or playerBlack) - local turnWhite = minetest.colorize("#000001", (lastMove == "black" and playerWhite ~= "") and - playerWhite .. "..." or playerWhite) - local check_s = minetest.colorize("#FF0000", "\\[check\\]") - - local formspec = fs .. - "label[1.9,0.3;" .. turnBlack .. (black_king_attacked and " " .. check_s or "") .. "]" .. - "label[1.9,9.15;" .. turnWhite .. (white_king_attacked and " " .. check_s or "") .. "]" .. - "table[8.9,1.05;5.07,3.75;moves;" .. moves:sub(1,-2) .. ";1]" .. - eaten_img - - meta:set_string("formspec", formspec) - - return false -end - minetest.register_node(":realchess:chessboard", { description = "Chess Board", drawtype = "nodebox", -- 2.44.0