X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=chess.lua;h=8e0691e0bc966744f2d4748ceae418c9674991df;hb=28877e7b4fd225638b1251333d319e9fc523bf96;hp=3bedaaa31ff06309f25afc0a443f63fff840ca91;hpb=20c9ea62ce3e27a1bf04853be34a44269d9b8dfe;p=xdecor.git diff --git a/chess.lua b/chess.lua index 3bedaaa..8e0691e 100644 --- a/chess.lua +++ b/chess.lua @@ -1,11 +1,10 @@ --- 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 @@ -16,25 +15,22 @@ end function realchess.init(pos) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() - local slots = "listcolors[#00000000;#00000000;#00000000;#30434C;#FFF]" - local formspec - - inv:set_size("board", 64) - - meta:set_string("formspec", - "size[8,8.6;]".. - "bgcolor[#080808BB;true]".. - "background[0,0;8,8;chess_bg.png]".. - "button[3.1,7.8;2,2;new;New game]".. - "list[context;board;0,0;8,8;]".. - slots) - + + local formspec = [[ size[8,8.6;] + bgcolor[#080808BB;true] + background[0,0;8,8;chess_bg.png] + button[3.1,7.8;2,2;new;New game] + list[context;board;0,0;8,8;] + 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) @@ -56,11 +52,9 @@ function realchess.init(pos) "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", @@ -78,9 +72,11 @@ function realchess.init(pos) "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 @@ -138,8 +134,9 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -151,18 +148,21 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl elseif from_x - 1 == to_x or from_x + 1 == to_x then if not pieceTo:find("black") then return 0 + elseif to_index >= 1 and to_index <= 8 then + inv:set_stack(from_list, from_index, "realchess:queen_white") end else 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 @@ -174,12 +174,14 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl elseif from_x - 1 == to_x or from_x + 1 == to_x then if not pieceTo:find("white") then return 0 + elseif to_index >= 57 and to_index <= 64 then + inv:set_stack(from_list, from_index, "realchess:queen_black") end else 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 @@ -208,7 +210,7 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -252,37 +254,25 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -291,23 +281,17 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl -- 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 @@ -347,17 +331,13 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -436,7 +416,7 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -444,7 +424,10 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -455,7 +438,10 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -470,7 +456,10 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -481,7 +470,10 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -496,16 +488,9 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 @@ -521,14 +506,17 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl 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 - minetest.chat_send_player(playerWhite, playerName.." has moved a "..pieceFrom:match("%a+:(%a+)")..", it's now your turn.") - elseif meta:get_string("lastMove") == "white" then - minetest.chat_send_player(playerBlack, playerName.." has moved a "..pieceFrom:match("%a+:(%a+)")..", it's now your turn.") + if lastMove == "black" then + minetest.chat_send_player(playerWhite, "["..os.date("%H:%M:%S").."] ".. + 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.." 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) @@ -537,50 +525,54 @@ function realchess.move(pos, from_list, from_index, to_list, to_index, count, pl return 1 end -function realchess.fields(pos, formname, fields, sender) +local function timeout_format(timeout_limit) + local time_remaining = timeout_limit - minetest.get_gametime() + local minutes = math.floor(time_remaining / 60) + local seconds = time_remaining % 60 + + if minutes == 0 then return seconds.." sec." end + return minutes.." min. "..seconds.." sec." +end + +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 - -- the chess can't be reset during a started game unless if nobody has played during a while (~5 min. by default) - if fields.new and (meta:get_string("playerWhite") == playerName or - meta:get_string("playerBlack") == playerName) then + -- timeout is 5 min. by default for resetting the game (non-players only) + 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() >= meta:get_int("lastMoveTime") + 250 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.\nIf you are not a current player, try again after a while.") + minetest.chat_send_player(playerName, "[!] You can't reset the chessboard, a game has been started.\n".. + "If you are not a current player, try again in "..timeout_format(timeout_limit)) end end function realchess.dig(pos, player) 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") - -- the chess can't be dug during a started game unless if nobody has played during a while (~5 min. by default) - if meta:get_int("lastMoveTime") ~= 0 and - minetest.get_gametime() <= meta:get_int("lastMoveTime") + 250 then - minetest.chat_send_player(playerName, "You can't dig the chessboard, a game has been started.\nReset it first if you're a current player, or try digging again after a while.") - return false - end - - return true + -- timeout is 5 min. by default for digging the chessboard (non-players only) + 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)) 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 end -function realchess.take(pos, listname, index, stack, player) - return 0 -end - minetest.register_node(":realchess:chessboard", { description = "Chess Board", drawtype = "nodebox", @@ -588,19 +580,18 @@ minetest.register_node(":realchess:chessboard", { paramtype2 = "facedir", inventory_image = "chessboard_top.png", wield_image = "chessboard_top.png", - tiles = {"chessboard_top.png", "chessboard_top.png", - "chessboard_sides.png", "chessboard_sides.png", - "chessboard_top.png", "chessboard_top.png"}, - groups = {choppy=3, flammable=3}, + tiles = {"chessboard_top.png", "chessboard_top.png", "chessboard_sides.png"}, + groups = {choppy=3, oddly_breakable_by_hand=2, flammable=3}, sounds = default.node_sound_wood_defaults(), - node_box = {type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, -0.4375, 0.5}}, + node_box = {type = "fixed", fixed = {-.375, -.5, -.375, .375, -.4375, .375}}, sunlight_propagates = true, + on_rotate = screwdriver.rotate_simple, can_dig = realchess.dig, on_construct = realchess.init, on_receive_fields = realchess.fields, allow_metadata_inventory_move = realchess.move, on_metadata_inventory_move = realchess.on_move, - allow_metadata_inventory_take = realchess.take + allow_metadata_inventory_take = function() return 0 end }) local function register_piece(name, count) @@ -632,11 +623,3 @@ register_piece("bishop", 2) register_piece("queen") register_piece("king") -minetest.register_craft({ - output = "realchess:chessboard", - recipe = { - {"dye:black", "dye:white", "dye:black"}, - {"stairs:slab_wood", "stairs:slab_wood", "stairs:slab_wood"} - } -}) -