--- See https://github.com/kilbith/realchess for the main repository
-
local realchess = {}
screwdriver = screwdriver or {}
-local function index_to_xy(index)
- index = index - 1
- local x = index % 8
- local y = (index - x) / 8
+local function index_to_xy(idx)
+ idx = idx - 1
+ local x = idx % 8
+ local y = (idx - x) / 8
return x, y
end
function realchess.init(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
-
- inv:set_size("board", 64)
local formspec = [[ size[8,8.6;]
bgcolor[#080808BB;true]
listcolors[#00000000;#00000000;#00000000;#30434C;#FFF] ]]
meta:set_string("formspec", formspec)
-
meta:set_string("infotext", "Chess Board")
meta:set_string("playerBlack", "")
meta:set_string("playerWhite", "")
meta:set_string("lastMove", "")
- meta:set_int("lastMoveTime", 0)
meta:set_string("winner", "")
+
+ meta:set_int("lastMoveTime", 0)
meta:set_int("castlingBlackL", 1)
meta:set_int("castlingBlackR", 1)
meta:set_int("castlingWhiteL", 1)
"realchess:pawn_black_5",
"realchess:pawn_black_6",
"realchess:pawn_black_7",
- "realchess:pawn_black_8",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
+ "realchess:pawn_black_8",
+ '','','','','','','','','','','','','','','','',
+ '','','','','','','','','','','','','','','','',
"realchess:pawn_white_1",
"realchess:pawn_white_2",
"realchess:pawn_white_3",
"realchess:knight_white_2",
"realchess:rook_white_2"
})
+
+ inv:set_size("board", 64)
end
-function realchess.move(pos, from_list, from_index, to_list, to_index, count, player)
+function realchess.move(pos, from_list, from_index, to_list, to_index, _, player)
if from_list ~= "board" and to_list ~= "board" then
return 0
end
local from_x, from_y = index_to_xy(from_index)
local to_x, to_y = index_to_xy(to_index)
- if pieceFrom:find("pawn") then
+ if pieceFrom:sub(11,14) == "pawn" then
if thisMove == "white" then
+ local pawnWhiteMove = inv:get_stack(from_list, xy_to_index(from_x, from_y - 1)):get_name()
-- white pawns can go up only
if from_y - 1 == to_y then
if from_x == to_x then
return 0
end
elseif from_y - 2 == to_y then
- if pieceTo ~= "" or from_y < 6 or inv:get_stack(from_list, xy_to_index(from_x, from_y - 1)):get_name() ~= "" then
+ if pieceTo ~= "" or from_y < 6 or pawnWhiteMove ~= "" then
return 0
end
else
return 0
end
elseif thisMove == "black" then
+ local pawnBlackMove = inv:get_stack(from_list, xy_to_index(from_x, from_y + 1)):get_name()
-- black pawns can go down only
if from_y + 1 == to_y then
if from_x == to_x then
return 0
end
elseif from_y + 2 == to_y then
- if pieceTo ~= "" or from_y > 1 or inv:get_stack(from_list, xy_to_index(from_x, from_y + 1)):get_name() ~= "" then
+ if pieceTo ~= "" or from_y > 1 or pawnBlackMove ~= "" then
return 0
end
else
return 0
end
- elseif pieceFrom:find("rook") then
+ elseif pieceFrom:sub(11,14) == "rook" then
if from_x == to_x then
-- moving vertically
if from_y < to_y then
return 0
end
- if thisMove == "white" then
- if pieceFrom:find("1") then
- meta:set_int("castlingWhiteL", 0)
- elseif pieceFrom:find("2") then
- meta:set_int("castlingWhiteR", 0)
- end
- elseif thisMove == "black" then
- if pieceFrom:find("1") then
+ if thisMove == "white" or thisMove == "black" then
+ if pieceFrom:sub(-1) == "1" then
meta:set_int("castlingWhiteL", 0)
- elseif pieceFrom:find("2") then
+ elseif pieceFrom:sub(-1) == "2" then
meta:set_int("castlingWhiteR", 0)
end
end
- elseif pieceFrom:find("knight") then
+ elseif pieceFrom:sub(11,16) == "knight" then
-- get relative pos
local dx = from_x - to_x
local dy = from_y - to_y
-- get absolute values
- if dx < 0 then
- dx = -dx
- end
- if dy < 0 then
- dy = -dy
- end
+ if dx < 0 then dx = -dx end
+ if dy < 0 then dy = -dy end
-- sort x and y
- if dx > dy then
- dx, dy = dy, dx
- end
+ if dx > dy then dx, dy = dy, dx end
-- ensure that dx == 1 and dy == 2
if dx ~= 1 or dy ~= 2 then
-- just ensure that destination cell does not contain friend piece
-- ^ it was done already thus everything ok
- elseif pieceFrom:find("bishop") then
+ elseif pieceFrom:sub(11,16) == "bishop" then
-- get relative pos
local dx = from_x - to_x
local dy = from_y - to_y
-- get absolute values
- if dx < 0 then
- dx = -dx
- end
- if dy < 0 then
- dy = -dy
- end
+ if dx < 0 then dx = -dx end
+ if dy < 0 then dy = -dy end
-- ensure dx and dy are equal
- if dx ~= dy then
- return 0
- end
+ if dx ~= dy then return 0 end
if from_x < to_x then
if from_y < to_y then
end
end
- elseif pieceFrom:find("queen") then
+ elseif pieceFrom:sub(11,15) == "queen" then
local dx = from_x - to_x
local dy = from_y - to_y
-- get absolute values
- if dx < 0 then
- dx = -dx
- end
- if dy < 0 then
- dy = -dy
- end
+ if dx < 0 then dx = -dx end
+ if dy < 0 then dy = -dy end
-- ensure valid relative move
if dx ~= 0 and dy ~= 0 and dx ~= dy then
end
end
- elseif pieceFrom:find("king") then
+ elseif pieceFrom:sub(11,14) == "king" then
local dx = from_x - to_x
local dy = from_y - to_y
local check = true
if thisMove == "white" then
if from_y == 7 and to_y == 7 then
if to_x == 1 then
- if meta:get_int("castlingWhiteL") == 1 and inv:get_stack(from_list, 57):get_name() == "realchess:rook_white_1" then
+ local castlingWhiteL = meta:get_int("castlingWhiteL")
+ local idx57 = inv:get_stack(from_list, 57):get_name()
+
+ if castlingWhiteL == 1 and idx57 == "realchess:rook_white_1" then
for i = 58, from_index - 1 do
if inv:get_stack(from_list, i):get_name() ~= "" then
return 0
check = false
end
elseif to_x == 6 then
- if meta:get_int("castlingWhiteR") == 1 and inv:get_stack(from_list, 64):get_name() == "realchess:rook_white_2" then
+ local castlingWhiteR = meta:get_int("castlingWhiteR")
+ local idx64 = inv:get_stack(from_list, 64):get_name()
+
+ if castlingWhiteR == 1 and idx64 == "realchess:rook_white_2" then
for i = from_index + 1, 63 do
if inv:get_stack(from_list, i):get_name() ~= "" then
return 0
elseif thisMove == "black" then
if from_y == 0 and to_y == 0 then
if to_x == 1 then
- if meta:get_int("castlingBlackL") == 1 and inv:get_stack(from_list, 1):get_name() == "realchess:rook_black_1" then
+ local castlingBlackL = meta:get_int("castlingBlackL")
+ local idx1 = inv:get_stack(from_list, 1):get_name()
+
+ if castlingBlackL == 1 and idx1 == "realchess:rook_black_1" then
for i = 2, from_index - 1 do
if inv:get_stack(from_list, i):get_name() ~= "" then
return 0
check = false
end
elseif to_x == 6 then
- if meta:get_int("castlingBlackR") == 1 and inv:get_stack(from_list, 8):get_name() == "realchess:rook_black_2" then
+ local castlingBlackR = meta:get_int("castlingBlackR")
+ local idx8 = inv:get_stack(from_list, 1):get_name()
+
+ if castlingBlackR == 1 and idx8 == "realchess:rook_black_2" then
for i = from_index + 1, 7 do
if inv:get_stack(from_list, i):get_name() ~= "" then
return 0
end
if check then
- if dx < 0 then
- dx = -dx
- end
- if dy < 0 then
- dy = -dy
- end
-
- if dx > 1 or dy > 1 then
- return 0
- end
+ if dx < 0 then dx = -dx end
+ if dy < 0 then dy = -dy end
+ if dx > 1 or dy > 1 then return 0 end
end
if thisMove == "white" then
meta:set_string("playerBlack", playerBlack)
meta:set_string("lastMove", thisMove)
meta:set_int("lastMoveTime", minetest.get_gametime())
+ local lastMove = meta:get_string("lastMove")
- if meta:get_string("lastMove") == "black" then
+ if lastMove == "black" then
minetest.chat_send_player(playerWhite, "["..os.date("%H:%M:%S").."] "..
- playerName.." has moved a "..pieceFrom:match(":(.-)%_")..", it's now your turn.")
- elseif meta:get_string("lastMove") == "white" then
+ playerName.." moved a "..pieceFrom:match(":(%a+)")..", it's now your turn.")
+ elseif lastMove == "white" then
minetest.chat_send_player(playerBlack, "["..os.date("%H:%M:%S").."] "..
- playerName.." has moved a "..pieceFrom:match(":(.-)%_")..", it's now your turn.")
+ playerName.." moved a "..pieceFrom:match(":(%a+)")..", it's now your turn.")
end
- if pieceTo:find("king") then
+ if pieceTo:sub(11,14) == "king" then
minetest.chat_send_player(playerBlack, playerName.." won the game.")
minetest.chat_send_player(playerWhite, playerName.." won the game.")
meta:set_string("winner", thisMove)
return minutes.." min. "..seconds.." sec."
end
-function realchess.fields(pos, formname, fields, sender)
+function realchess.fields(pos, _, fields, sender)
local playerName = sender:get_player_name()
local meta = minetest.get_meta(pos)
local timeout_limit = meta:get_int("lastMoveTime") + 300
+ local playerWhite = meta:get_string("playerWhite")
+ local playerBlack = meta:get_string("playerBlack")
+ local lastMoveTime = meta:get_int("lastMoveTime")
if fields.quit then return end
-- timeout is 5 min. by default for resetting the game (non-players only)
- if fields.new and (meta:get_string("playerWhite") == playerName or
- meta:get_string("playerBlack") == playerName) then
+ if fields.new and (playerWhite == playerName or playerBlack == playerName) then
realchess.init(pos)
- elseif fields.new and meta:get_int("lastMoveTime") ~= 0 and
- minetest.get_gametime() >= timeout_limit and
- (meta:get_string("playerWhite") ~= playerName or
- meta:get_string("playerBlack") ~= playerName) then
+ elseif fields.new and lastMoveTime ~= 0 and minetest.get_gametime() >= timeout_limit and
+ (playerWhite ~= playerName or playerBlack ~= playerName) then
realchess.init(pos)
else
minetest.chat_send_player(playerName, "[!] You can't reset the chessboard, a game has been started.\n"..
local meta = minetest.get_meta(pos)
local playerName = player:get_player_name()
local timeout_limit = meta:get_int("lastMoveTime") + 300
+ local lastMoveTime = meta:get_int("lastMoveTime")
-- timeout is 5 min. by default for digging the chessboard (non-players only)
- if meta:get_int("lastMoveTime") ~= 0 and minetest.get_gametime() <= timeout_limit then
+ return (lastMoveTime == 0 and minetest.get_gametime() > timeout_limit) or
minetest.chat_send_player(playerName, "[!] You can't dig the chessboard, a game has been started.\n"..
"Reset it first if you're a current player, or dig again in "..timeout_format(timeout_limit))
- return false
- end
-
- return true
end
-function realchess.on_move(pos, from_list, from_index, to_list, to_index, count, player)
+function realchess.on_move(pos, from_list, from_index)
local inv = minetest.get_meta(pos):get_inventory()
inv:set_stack(from_list, from_index, '')
return false