parent
ac1817dc9e
commit
8db6acb801
41
commands.lua
41
commands.lua
|
@ -136,12 +136,12 @@ basic_robot.commands.dig = function(name,dir)
|
|||
|
||||
--require energy to dig
|
||||
if basic_robot.dig_require_energy then
|
||||
local digcost = basic_robot.digcosts[nodename];
|
||||
local digcost = basic_robot.digcosts[nodename] or 1/(5*25); -- default 1/5th of stone dig
|
||||
if digcost then
|
||||
local data = basic_robot.data[name];
|
||||
local energy = (data.menergy or 0) - digcost;
|
||||
if energy<0 then
|
||||
error("need " .. digcost .. " energy to dig " .. nodename .. ". Use machine.generate(...) to get some energy.");
|
||||
error("need " .. digcost .. " energy to dig " .. nodename .. ". Use machine.generate to get some energy.");
|
||||
end
|
||||
data.menergy = energy;
|
||||
end
|
||||
|
@ -183,19 +183,6 @@ basic_robot.commands.insert_item = function(name,item, inventory,dir)
|
|||
|
||||
local inv = minetest.get_meta(pos):get_inventory();
|
||||
|
||||
-- fertilize if soil
|
||||
if item == "farming:fertilizer" then
|
||||
local stack = ItemStack(item);
|
||||
if minetest.get_node(tpos).name == "farming:soil_wet" and (meta:get_int("admin")==1 or inv:contains_item("main", stack)) then
|
||||
inv:remove_item("main", stack);
|
||||
local nutrient = tmeta:get_int("nutrient"); nutrient = nutrient + 10; if nutrient>20 then nutrient = 20 end
|
||||
tmeta:set_int("nutrient",nutrient);
|
||||
minetest.set_node({x=tpos.x,y=tpos.y+1,z=tpos.z},{name = "air"})
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local tinv = minetest.get_meta(tpos):get_inventory();
|
||||
|
||||
if not inventory then inventory = "main"; end
|
||||
|
@ -866,30 +853,26 @@ basic_robot.technic = { -- data cache
|
|||
["default:cobble"] = {1,"default:gravel",1},
|
||||
["default:gravel"] = {0.5,"default:dirt",1},
|
||||
["default:dirt"] = {0.5,"default:clay_lump 4",1},
|
||||
["es:aikerum_crystal"] ={16,"es:aikerum_dust 2",1}, -- added for es mod
|
||||
["es:ruby_crystal"] = {16,"es:ruby_dust 2",1},
|
||||
["es:emerald_crystal"] = {16,"es:emerald_dust 2",1},
|
||||
["es:purpellium_lump"] = {16,"es:purpellium_dust 2",1},
|
||||
["default:obsidian_shard"] = {199,"default:lava_source",1},
|
||||
["gloopblocks:basalt"] = {1, "default:cobble",1}, -- enable coble farms with gloopblocks mod
|
||||
["default:ice"] = {1, "default:snow 4",1},
|
||||
["darkage:silt_lump"]={1,"darkage:chalk_powder",1},
|
||||
["default:diamond"] = {16, "basic_machines:diamond_dust_33 2", 1},
|
||||
["default:diamond"] = {16, "basic_machines:diamond_dust_00 2", 1},
|
||||
["default:ice"] = {1, "default:snow", 1},
|
||||
["moreores:tin_lump"] = {4,"basic_machines:tin_dust_33 2",1},
|
||||
["moreores:tin_lump"] = {4,"basic_machines:tin_dust_00 2",1},
|
||||
["default:obsidian_shard"] = {199, "default:lava_source",1},
|
||||
["default:mese_crystal"] = {8, "basic_machines:mese_dust_33 2",1},
|
||||
["default:mese_crystal"] = {8, "basic_machines:mese_dust_00 2",1},
|
||||
["moreores:mithril_ingot"] = {16, "basic_machines:mithril_dust_33 2",1},
|
||||
["moreores:silver_ingot"] = {5, "basic_machines:silver_dust_33 2",1},
|
||||
["moreores:tin_ingot"] = {4,"basic_machines:tin_dust_33 2",1},
|
||||
["moreores:tin_ingot"] = {4,"basic_machines:tin_dust_00 2",1},
|
||||
["moreores:mithril_lump"] = {16, "basic_machines:mithril_dust_33 2",1},
|
||||
["default:steel_ingot"] = {4, "basic_machines:iron_dust_33 2",1},
|
||||
["default:steel_ingot"] = {4, "basic_machines:iron_dust_00 2",1},
|
||||
["moreores:silver_lump"] = {5, "basic_machines:silver_dust_33 2",1},
|
||||
["default:gold_ingot"] = {6, "basic_machines:gold_dust_33 2", 1},
|
||||
["default:copper_ingot"] = {4, "basic_machines:copper_dust_33 2",1},
|
||||
["default:gold_lump"] = {6, "basic_machines:gold_dust_33 2", 1},
|
||||
["default:iron_lump"] = {4, "basic_machines:iron_dust_33 2",1},
|
||||
["default:copper_lump"] = {4, "basic_machines:copper_dust_33 2",1},
|
||||
["default:gold_ingot"] = {6, "basic_machines:gold_dust_00 2", 1},
|
||||
["default:copper_ingot"] = {4, "basic_machines:copper_dust_00 2",1},
|
||||
["default:gold_lump"] = {6, "basic_machines:gold_dust_00 2", 1},
|
||||
["default:iron_lump"] = {4, "basic_machines:iron_dust_00 2",1},
|
||||
["default:copper_lump"] = {4, "basic_machines:copper_dust_00 2",1},
|
||||
},
|
||||
|
||||
compressor_recipes = { --[in] ={fuel cost, out, quantity of material required for processing}
|
||||
|
|
75
init.lua
75
init.lua
|
@ -4,8 +4,8 @@
|
|||
basic_robot = {};
|
||||
------ SETTINGS --------
|
||||
basic_robot.call_limit = {50,200,1500,10^9}; -- how many execution calls per script run allowed, for auth levels 0,1,2 (normal, robot, puzzle, admin)
|
||||
basic_robot.entry_count = 2 -- how many robots ordinary player can have
|
||||
basic_robot.advanced_count = 16 -- how many robots player with robot privs can have
|
||||
basic_robot.count = {2,4,16,128} -- how many robots player can have
|
||||
|
||||
basic_robot.radius = 32; -- divide whole world into blocks of this size - used for managing events like keyboard punches
|
||||
basic_robot.password = "raN___dOM_ p4S"; -- IMPORTANT: change it before running mod, password used for authentifications
|
||||
|
||||
|
@ -25,7 +25,7 @@ basic_robot.bad_inventory_blocks = { -- disallow taking from these nodes invento
|
|||
|
||||
basic_robot.http_api = minetest.request_http_api();
|
||||
|
||||
basic_robot.version = "2019/01/13a";
|
||||
basic_robot.version = "2019/02/16a";
|
||||
|
||||
basic_robot.gui = {}; local robogui = basic_robot.gui -- gui management
|
||||
basic_robot.data = {}; -- stores all robot related data
|
||||
|
@ -217,29 +217,6 @@ function getSandboxEnv (name)
|
|||
return commands.display_text(obj,text,linesize,size)
|
||||
end,
|
||||
|
||||
sound = function(sample,volume, pos)
|
||||
if pos then
|
||||
return minetest.sound_play( sample,
|
||||
{
|
||||
pos = pos,
|
||||
gain = volume or 1,
|
||||
max_hear_distance = 32, -- default, uses an euclidean metric
|
||||
})
|
||||
end
|
||||
|
||||
local obj = basic_robot.data[name].obj;
|
||||
return minetest.sound_play( sample,
|
||||
{
|
||||
object = obj,
|
||||
gain = volume or 1,
|
||||
max_hear_distance = 32, -- default, uses an euclidean metric
|
||||
})
|
||||
end,
|
||||
|
||||
sound_stop = function(handle)
|
||||
minetest.sound_stop(handle)
|
||||
end,
|
||||
|
||||
},
|
||||
|
||||
machine = {-- adds technic like functionality to robots: power generation, smelting, grinding, compressing
|
||||
|
@ -478,7 +455,9 @@ function getSandboxEnv (name)
|
|||
|
||||
if authlevel>=1 then -- robot privs
|
||||
|
||||
|
||||
env.self.sound = minetest.sound_play
|
||||
env.self.sound_stop = minetest.sound_stop
|
||||
|
||||
env.table = {
|
||||
concat = table.concat,
|
||||
insert = table.insert,
|
||||
|
@ -512,7 +491,6 @@ function getSandboxEnv (name)
|
|||
end
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
env.self.read_form = function()
|
||||
local fields = basic_robot.data[name].read_form;
|
||||
|
@ -590,9 +568,9 @@ local identify_strings = function(code) -- returns list of positions {start,end}
|
|||
local i = 0; local j; local _; local length = string.len(code);
|
||||
local mode = 0; -- 0: not in string, 1: in '...' string, 2: in "..." string, 3. in [==[ ... ]==] string
|
||||
local modes = {
|
||||
{"'","'"},
|
||||
{"\"","\""},
|
||||
{"%[=*%[","%]=*%]"}
|
||||
{"'","'"}, -- inside ' '
|
||||
{"\"","\""}, -- inside " "
|
||||
{"%[=*%[","%]=*%]"}, -- inside [=[ ]=]
|
||||
}
|
||||
local ret = {}
|
||||
while i < length do
|
||||
|
@ -615,7 +593,7 @@ local identify_strings = function(code) -- returns list of positions {start,end}
|
|||
else
|
||||
_,j = string.find(code,modes[mode][2],i); -- search for closing pair
|
||||
if not j then break end
|
||||
if (mode~=2 or string.sub(code,j-1,j-1) ~= "\\") then -- not (" and \")
|
||||
if (mode~=2 or (string.sub(code,j-1,j-1) ~= "\\") or string.sub(code,j-2,j-1) == "\\\\") then -- not (" and not \" - but "\\" is allowed)
|
||||
ret[#ret][2] = j
|
||||
mode = 0
|
||||
end
|
||||
|
@ -626,6 +604,7 @@ local identify_strings = function(code) -- returns list of positions {start,end}
|
|||
return ret
|
||||
end
|
||||
|
||||
|
||||
is_inside_string = function(strings,pos) -- is position inside one of the strings?
|
||||
local low = 1; local high = #strings;
|
||||
if high == 0 then return false end
|
||||
|
@ -805,10 +784,24 @@ end
|
|||
|
||||
-- note: to see memory used by lua in kbytes: collectgarbage("count")
|
||||
|
||||
local get_authlevel = function(name) -- given player name return auth level
|
||||
local privs = minetest.get_player_privs(name);
|
||||
local authlevel = 0;
|
||||
if privs.privs then -- set auth level depending on privs
|
||||
authlevel = 3
|
||||
elseif privs.puzzle then
|
||||
authlevel = 2
|
||||
elseif privs.robot then
|
||||
authlevel = 1
|
||||
else
|
||||
authlevel = 0
|
||||
end
|
||||
return authlevel
|
||||
end
|
||||
|
||||
local function setupid(owner)
|
||||
local privs = minetest.get_player_privs(owner); if not privs then return end
|
||||
local maxid = basic_robot.entry_count;
|
||||
if privs.robot or privs.puzzle then maxid = basic_robot.advanced_count end -- max id's per user
|
||||
local maxid = basic_robot.count[get_authlevel(owner)+1] or 2;
|
||||
basic_robot.ids[owner] = {id = 1, maxid = maxid}; --active id for remove control
|
||||
end
|
||||
|
||||
|
@ -1584,6 +1577,7 @@ minetest.register_on_player_receive_fields(
|
|||
data.text = text or ""
|
||||
data.title = fields.title or ""
|
||||
data.text_len = #data.text
|
||||
data.description = fields.title or ""
|
||||
data.page = 1
|
||||
data.owner = data.owner or ""
|
||||
local lpp = 14
|
||||
|
@ -1645,17 +1639,7 @@ minetest.register_node("basic_robot:spawner", {
|
|||
local owner = placer:get_player_name();
|
||||
meta:set_string("owner", owner);
|
||||
|
||||
local privs = minetest.get_player_privs(placer:get_player_name());
|
||||
local authlevel = 0;
|
||||
if privs.privs then -- set auth level depending on privs
|
||||
authlevel = 3
|
||||
elseif privs.puzzle then
|
||||
authlevel = 2
|
||||
elseif privs.robot then
|
||||
authlevel = 1
|
||||
else
|
||||
authlevel = 0
|
||||
end
|
||||
local authlevel = get_authlevel(placer:get_player_name());
|
||||
|
||||
meta:set_int("authlevel",authlevel)
|
||||
local sec_hash = minetest.get_password_hash("",authlevel .. owner .. basic_robot.password) -- 'digitally sign' authlevel using password
|
||||
|
@ -1749,6 +1733,7 @@ minetest.register_craftitem("basic_robot:control", {
|
|||
local ids = basic_robot.ids[owner]; if not ids then setupid(owner) end
|
||||
local id = basic_robot.ids[owner].id or 1; -- read active id for player
|
||||
local name = owner..id;
|
||||
|
||||
local form =
|
||||
"size[9.5,1.25]" .. -- width, height
|
||||
"textarea[1.25,-0.25;8.75,2.25;code;;".. code.."]"..
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
//lua minetest.get_player_by_name("rnd"):set_properties({visual_size = {x=1,y=1}})
|
||||
|
||||
local name = "rnd"; local player = minetest.get_player_by_name(name); player:set_properties({visual = "upright_sprite"});player:set_properties({textures={"default_tool_diamondpick.png"}})
|
||||
|
||||
|
||||
// change to robot
|
||||
local name = "rnd"; local player = minetest.get_player_by_name(name); player:set_properties({visual = "cube"});player:set_properties({textures={"arrow.png^[transformR90","basic_machine_side.png","basic_machine_side.png","basic_machine_side.png","face.png","basic_machine_side.png"}});player:set_properties({collisionbox={-0.5,-0.5,-0.5,0.5,0.5,0.5}})
|
||||
|
||||
//LawnGreen
|
||||
|
||||
local name = "rnd"; local player = minetest.get_player_by_name(name); player:set_properties({visual = "sprite"});player:set_properties({textures={"farming_bottle_ethanol.png"}});player:set_properties({collisionbox={-0.5,-0.5,-0.5,0.5,0.5,0.5}});player:set_properties({visual_size = {x=2,y=2}})
|
||||
|
||||
//farming_blueberry_muffin
|
||||
local name = "rnd"; local player = minetest.get_player_by_name(name); player:set_properties({visual = "cube"});player:set_properties({textures={"farming_pumpkin_face_off.png","farming_pumpkin_face_off.png","farming_pumpkin_face_off.png","farming_pumpkin_face_off.png","farming_pumpkin_face_off.png","farming_pumpkin_face_off.png"}});player:set_properties({collisionbox={-0.5,-0.5,-0.5,0.5,0.5,0.5}})
|
||||
|
||||
--nyan cat
|
||||
//lua local name = "rnd"; local player = minetest.get_player_by_name(name); player:set_properties({visual = "cube"});player:set_properties({textures = {"nyancat_side.png", "nyancat_side.png", "nyancat_side.png","nyancat_side.png", "nyancat_front.png", "nyancat_back.png"}});player:set_properties({collisionbox={-0.5,-0.5,-0.5,0.5,0.5,0.5}})
|
||||
|
||||
|
||||
|
||||
local name = "rnd1"; local player = minetest.get_player_by_name(name); player:set_nametag_attributes({text = "Friend of Giorge"});
|
||||
|
||||
//lua local player = minetest.get_player_by_name("pro2");minetest.sound_play("nyan",{object = player,gain = 1.0,max_hear_distance = 8,loop = false})
|
||||
|
||||
|
||||
//lua local player = minetest.get_player_by_name("rnd");player:set_properties({visual = "mesh",textures = {"mobs_spider.png"},mesh = "mobs_spider.x",visual_size = {x=7,y=7}})
|
||||
|
||||
|
||||
//lua local player = minetest.get_player_by_name("rnd");player:set_properties({visual = "mesh",textures = {"mobs_dungeon_master.png"},mesh = "mobs_dungeon_master.b3d",visual_size = {x=1,y=1}})
|
||||
|
||||
//lua local player = minetest.get_player_by_name("best");player:set_properties({visual = "mesh",textures = {"zmobs_mese_monster.png"},mesh = "zmobs_mese_monster.x",visual_size = {x=1,y=1}})
|
||||
|
||||
//lua local player = minetest.get_player_by_name("rnd1");player:set_properties({visual = "mesh",textures = {"mobs_oerkki.png"},mesh = "mobs_oerkki.b3d",visual_size = {x=1,y=1}})
|
||||
|
||||
//lua local player = minetest.get_player_by_name("rnd1");player:set_properties({visual = "mesh",textures = {"mobs_stone_monster.png"},mesh = "mobs_stone_monster.b3d",visual_size = {x=1,y=1}})
|
||||
|
||||
|
||||
mesh = "zmobs_lava_flan.x",
|
||||
textures = {
|
||||
{"zmobs_lava_flan.png"},
|
||||
{"zmobs_lava_flan2.png"},
|
||||
{"zmobs_lava_flan3.png"},
|
||||
},
|
||||
----------------------------------------------
|
||||
|
||||
|
||||
|
||||
//lua local player = minetest.get_player_by_name("towner");player:set_physics_override({speed=0.05})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
-- simple box pushing game, rnd
|
||||
|
||||
if not init then
|
||||
spos = self.spawnpos(); spos.x = spos.x +5; spos.z = spos.z +5;
|
||||
|
||||
for i = 1, 2 do
|
||||
for j = 1,2 do
|
||||
puzzle.set_node({x=spos.x+i,y=spos.y,z=spos.z+j}, {name = "basic_robot:buttonFFFFFF"})
|
||||
end
|
||||
end
|
||||
|
||||
init = true
|
||||
players = find_player(5);
|
||||
if not players then say("no players nearby") self.remove() end
|
||||
say("BOX PUSH demo. punch the white box to move it around ")
|
||||
|
||||
pushables = {[1] = true} -- button types
|
||||
canpushnodes = {["air"] = 1, ["basic_robot:button8080FF"] = 2} -- 1 push node, 2 absorb node
|
||||
end
|
||||
|
||||
event = keyboard.get()
|
||||
if event then
|
||||
local boxtype = event.type
|
||||
if pushables[boxtype] then
|
||||
player = puzzle.get_player(event.puncher)
|
||||
local pos = player:getpos();
|
||||
local boxpos = {x = event.x, y = event.y, z = event.z};
|
||||
local diff = { pos.x-boxpos.x, pos.z-boxpos.z};
|
||||
|
||||
local newx,newz
|
||||
if math.abs(diff[1])>math.abs(diff[2]) then -- punch in x-direction
|
||||
newx = boxpos.x - (diff[1]>0 and 1 or -1)
|
||||
newz = boxpos.z
|
||||
else
|
||||
newx = boxpos.x
|
||||
newz = boxpos.z - (diff[2]>0 and 1 or -1)
|
||||
end
|
||||
|
||||
local newnode = puzzle.get_node({x=newx, y= boxpos.y, z= newz}).name
|
||||
|
||||
|
||||
local canpush = canpushnodes[newnode]
|
||||
if canpush then
|
||||
local oldnode = puzzle.get_node(boxpos).name
|
||||
puzzle.set_node(boxpos,{name= "air"}) -- remove node
|
||||
if canpush == 1 then -- simply move the box
|
||||
newnode = oldnode
|
||||
elseif canpush == 2 then -- absorb the box
|
||||
newnode = newnode
|
||||
end
|
||||
|
||||
puzzle.set_node({x=newx, y= boxpos.y, z= newz}, {name = newnode})
|
||||
end
|
||||
end
|
||||
--say(serialize(event))
|
||||
end
|
|
@ -0,0 +1,103 @@
|
|||
-- sokoban 3D, rnd
|
||||
|
||||
if not init then
|
||||
spos = self.spawnpos(); spos.x = spos.x +5; spos.z = spos.z +5;
|
||||
|
||||
for i = 1, 2 do
|
||||
for j = 1,2 do
|
||||
puzzle.set_node({x=spos.x+i,y=spos.y,z=spos.z+j}, {name = "basic_robot:buttonFFFFFF"})
|
||||
end
|
||||
end
|
||||
|
||||
init = true
|
||||
players = find_player(5);
|
||||
if not players then say("no players nearby") self.remove() end
|
||||
|
||||
puzzle.get_player(players[1]):set_physics_override({jump = 0.85}) -- just allow jump on 1 block up
|
||||
say("BOX PUSH demo. punch the white box to move it around ")
|
||||
|
||||
self.label(
|
||||
"SOKOBAN 3D. RULES:\n1. pushable blocks: white,gray,yellow. you can not push block if another block is on top of it,\n2. elevator block: yellow - can push other blocks on top of it,"..
|
||||
"\n3. if block falls it breaks, unless it falls less than 1 deep onto green block\n"..
|
||||
"4. if you push block into blue it dissapears\n"..
|
||||
"5. you can only push block by standing close in front of it, not too low below it or too high above it\n"..
|
||||
"LEVEL 1: push white block on top of red block")
|
||||
|
||||
pushables = {[1] = true,[2] = true,[6] = true} -- button types: white,gray, yellow
|
||||
canpushnodes = {-- you can push into these nodes, 1 push node, 2 absorb node, 3 = elevator
|
||||
["air"] = 1,
|
||||
["basic_robot:button8080FF"] = 2,
|
||||
["basic_robot:buttonFFFF80"] = 3,
|
||||
}
|
||||
end
|
||||
|
||||
event = keyboard.get()
|
||||
if event then
|
||||
local boxtype = event.type
|
||||
if pushables[boxtype] then
|
||||
player = puzzle.get_player(event.puncher)
|
||||
local pos = player:getpos();
|
||||
local boxpos = {x = event.x, y = event.y, z = event.z};
|
||||
local diff = { pos.x-boxpos.x, pos.z-boxpos.z, pos.y - boxpos.y}; -- x,z,y
|
||||
|
||||
local newx,newy,newz
|
||||
newy = boxpos.y
|
||||
local allowpush = true
|
||||
|
||||
--self.label(diff[3])
|
||||
if diff[3]<-1.5 or diff[3]>0.5 then allowpush = false end -- dont allow to push if height difference to large
|
||||
|
||||
if math.abs(diff[1])>math.abs(diff[2]) then -- punch in x-direction
|
||||
newx = boxpos.x - (diff[1]>0 and 1 or -1)
|
||||
newz = boxpos.z
|
||||
if math.abs(diff[1])<0.7 or math.abs(diff[1])>1 then allowpush = false end -- dont allow push if too close
|
||||
if math.abs(diff[2]) > 0.25 then allowpush = false end -- must stand in front to push, not from side
|
||||
else
|
||||
newx = boxpos.x
|
||||
newz = boxpos.z - (diff[2]>0 and 1 or -1)
|
||||
if math.abs(diff[2])<0.7 or math.abs(diff[2])>1 then allowpush = false end -- dont allow push if too close
|
||||
if math.abs(diff[1]) > 0.25 then allowpush = false end -- must stand in front to push, not from side
|
||||
end
|
||||
|
||||
--self.label(diff[1] .. " " .. diff[2] .. " " .. diff[3])
|
||||
|
||||
local newnode = puzzle.get_node({x=newx, y= boxpos.y, z= newz}).name
|
||||
|
||||
|
||||
local canpush = canpushnodes[newnode]
|
||||
if allowpush and canpush then
|
||||
local oldnode = puzzle.get_node(boxpos).name
|
||||
|
||||
if canpush == 1 then -- simply move the box
|
||||
newnode = oldnode
|
||||
elseif canpush == 2 then -- absorb the box
|
||||
newnode = newnode
|
||||
elseif canpush == 3 then
|
||||
newnode = oldnode
|
||||
newy = newy+1
|
||||
end
|
||||
|
||||
|
||||
|
||||
local nodeabove = puzzle.get_node({x=boxpos.x, y=boxpos.y+1, z= boxpos.z}).name
|
||||
if nodeabove ~="air" then allowpush = false end -- no floating nodes allowed
|
||||
|
||||
local nodebelow = puzzle.get_node({x=newx, y=newy-1, z= newz}).name
|
||||
if nodebelow == "air" then
|
||||
if puzzle.get_node({x=newx, y=newy-2, z= newz}).name ~= "basic_robot:button80FF80" then
|
||||
newnode = "air"
|
||||
else
|
||||
newy=newy-1
|
||||
end
|
||||
end -- fall down
|
||||
|
||||
|
||||
|
||||
if allowpush then
|
||||
puzzle.set_node(boxpos,{name= "air"}) -- remove node
|
||||
puzzle.set_node({x=newx, y= newy, z= newz}, {name = newnode})
|
||||
end
|
||||
end
|
||||
end
|
||||
--say(serialize(event))
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
if not init then
|
||||
text = " hello world "
|
||||
name = "rnd"
|
||||
m = 8;
|
||||
idx = 0;
|
||||
n = string.len(text)
|
||||
|
||||
player = puzzle.get_player(name)
|
||||
inv = player:get_inventory()
|
||||
inv:set_list("main",{})
|
||||
init = true
|
||||
|
||||
end
|
||||
|
||||
for i = 1, m do
|
||||
local j = (idx+i)%n + 1
|
||||
local c = string.byte(text,j)-97;
|
||||
if c<0 or c>30 then c = -97 end
|
||||
inv:set_stack("main", i,puzzle.ItemStack("basic_robot:button_" ..(97+c)))
|
||||
end
|
||||
|
||||
idx = (idx + 1) % n
|
||||
--self.remove()
|
|
@ -25,18 +25,8 @@ if not fetch then
|
|||
self.label(os.date("%X") ..', cmd : ' .. req)
|
||||
local i = string.find(req," !")
|
||||
if i then
|
||||
local cmd = string.sub(req,i+2)
|
||||
if cmd == "players" then
|
||||
local players = minetest.get_connected_players();
|
||||
out = {};
|
||||
for i = 1,#players do out[i] = players[i]:get_player_name() end
|
||||
MT2web("online players : " .. table.concat(out,", "))
|
||||
else
|
||||
run_commmand(cmd)
|
||||
end
|
||||
run_commmand(string.sub(req,i+2))
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -59,8 +49,6 @@ if not fetch then
|
|||
fetch({url = "http://".. address .. "/mtmsg/"..message, timeout = 5}, result)
|
||||
end
|
||||
MT2web("minetest robot started and listening.")
|
||||
|
||||
self.listen(1)
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
-- ACTIVITY GENERATOR + modified /status
|
||||
-- makes server appear more active: virtual players join/leave, talk
|
||||
|
||||
if not init then
|
||||
minetest.forceload_block(self.pos(),true)
|
||||
self.label("activity generator")
|
||||
local chatc = _G.core.registered_chatcommands["status"];
|
||||
if chatc then
|
||||
|
||||
if not rom.chatc then rom.chatc = chatc end
|
||||
--self.label(serialize(chatc))
|
||||
hidden_players = {
|
||||
rnd = false,
|
||||
}
|
||||
|
||||
extra_players = {
|
||||
"Piojoblanco","Bryan0911","EmmaBTS","atmaca","pausc05","bobo","marquez","Maike-008","odiseu","jere700182","_z","erick07","elvergalarga01","follow","Mantano10","AW","0987654321","lavraimeriem","formless","kanekii","cuchita","X_Pro_X","Tron","MGPe","Budrow42","lahina","shaahin18","dolphin","Stickman301","Galves58","Appelbaum747jdjxi","agy","E23","Utsler26","Rafael_Aaron_PROOO","cloe","Athans82","Love_Girl","jklu","Marne485hv","xXNicoXx","Dootson22","squad","fatima","Cucuzza62"
|
||||
}
|
||||
extra_joined = {};
|
||||
|
||||
greetings = {"hi","hello","pls help","help","how to play?", "i have only 2 blocks?","cool",":(","someone help","HI"}
|
||||
|
||||
_G.core.registered_chatcommands["status"] =
|
||||
{
|
||||
description = "Print server status",
|
||||
func = function(name, param)
|
||||
local connected = minetest.get_connected_players();
|
||||
local ret = {};
|
||||
for i = 1,#connected do
|
||||
local pname = connected[i]:get_player_name();
|
||||
if not hidden_players[pname] then ret[#ret+1] = pname end
|
||||
end
|
||||
local clients = table.concat(ret,", ");
|
||||
local extras = {};
|
||||
for name,_ in pairs(extra_joined) do extras[#extras+1] = name end
|
||||
if #extras>0 then clients = clients ..", " .. table.concat(extras, ", ") end
|
||||
return true, "# Server: version=0.4.17.1, uptime = ".. math.floor(minetest.get_server_uptime()*10)/10 ..", max_lag = 0.1, clients = {".. clients .. "}"
|
||||
|
||||
end,
|
||||
}
|
||||
|
||||
--_G.core.registered_chatcommands["status"] = rom.chatc -- uncomment this to restore
|
||||
|
||||
end
|
||||
t=0
|
||||
init = true
|
||||
end
|
||||
t=t+1;
|
||||
|
||||
if t%5 == 0 then
|
||||
local r = math.random(10)
|
||||
if r <= 2 then -- add random new player
|
||||
--say(t)
|
||||
local idx = math.random(#extra_players)
|
||||
local pname = extra_players[idx];
|
||||
if pname and not extra_joined[pname] then
|
||||
extra_joined[pname] = true
|
||||
minetest.chat_send_all("*** " .. pname .. " joined the game.")
|
||||
end
|
||||
elseif r<=4 then -- disconnect random extra
|
||||
local count = 0;
|
||||
for pname,_ in pairs(extra_joined) do count = count + 1 end
|
||||
local idx = math.random(count)
|
||||
count = 0;
|
||||
for pname,_ in pairs(extra_joined) do
|
||||
count = count + 1
|
||||
if count == idx then
|
||||
minetest.chat_send_all("*** " .. pname .. " left the game.")
|
||||
extra_joined[pname] = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif r<=6 then -- chat
|
||||
if math.random(5) == 1 then
|
||||
local count = 0
|
||||
for pname,_ in pairs(extra_joined) do count = count + 1 end
|
||||
local idx = math.random(count)
|
||||
count = 0;
|
||||
for pname,_ in pairs(extra_joined) do
|
||||
count = count + 1
|
||||
if count == idx then
|
||||
r = math.random(#greetings);
|
||||
minetest.chat_send_all("<" .. pname .. "> " ..greetings[r])
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--self.remove()
|
|
@ -0,0 +1,23 @@
|
|||
-- simple chat board by rnd
|
||||
if not init then init = true
|
||||
|
||||
pos = self.pos()
|
||||
|
||||
|
||||
write_text = function(text,size)
|
||||
for x=0,size-1 do
|
||||
for y = size-1,0,-1 do
|
||||
local c = (string.byte(text, (size-1-y)*size+(x+1)) or 32)-97
|
||||
puzzle.set_node({x=pos.x+x+1,y=pos.y+y,z=pos.z},{name = "basic_robot:button_"..(97+c)})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.listen(1)
|
||||
|
||||
end
|
||||
|
||||
speaker,msg= self.listen_msg()
|
||||
if msg then
|
||||
write_text(msg,15)
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
compact_inventory = function(item)
|
||||
local size = 32
|
||||
local count = 0
|
||||
|
||||
for i = 1,size do
|
||||
local stringname = check_inventory.self("","main",i);
|
||||
local itemname, j = stringname:match("(%S+) (%d+)")
|
||||
if itemname == item then
|
||||
count = count + tonumber(j)
|
||||
end
|
||||
end
|
||||
|
||||
say(string.format("total count of %s is %s",item,count))
|
||||
|
||||
insert.forward(string.format("%s %s",item,count)) -- will join all items together
|
||||
end
|
|
@ -0,0 +1,297 @@
|
|||
-- subdivide rectangular area made from various node types into union of disjoint contigious boxes,
|
||||
-- box count should be small, by rnd 2018
|
||||
|
||||
if not init then
|
||||
init = true -- map saver
|
||||
local dout = function(msg) minetest.chat_send_player("rnd", msg) end
|
||||
|
||||
minidx = 1 -- minimal position index not yet in box collection
|
||||
|
||||
blockdata = {}; --[1] = {p1,p2} [2] = list of nodenames, [3] = list [x][y][z] = nodename idx
|
||||
|
||||
|
||||
table_copy = function(tab)
|
||||
local out = {};
|
||||
for k,v in pairs(tab) do
|
||||
out[k] = v
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
read_block = function(p1,p2,data)
|
||||
if p1.x>p2.x or p1.y>p2.y or p1.z>p2.z then return end -- p1 coords must be smaller than p2 coords
|
||||
|
||||
data[1] = {{x=p1.x,y=p1.y,z=p1.z},{x=p2.x-p1.x+1,y=p2.y-p1.y+1,z=p2.z-p1.z+1}} -- startpos, dimensions
|
||||
|
||||
local nodedb = {} -- [nodename] = node idx
|
||||
local nodelist = {} -- list of nodes: nodename1, nodename2,...
|
||||
local nodes = {} -- table containing nodes [x][y][z] = node idx
|
||||
local ncount = 0;
|
||||
local idx = 0
|
||||
for x = p1.x, p2.x do
|
||||
nodes[x-p1.x+1] = {}
|
||||
for y = p1.y, p2.y do
|
||||
nodes[x-p1.x+1][y-p1.y+1] = {}
|
||||
for z = p1.z, p2.z do
|
||||
idx=idx+1
|
||||
local nodename = minetest.get_node({x=x,y=y,z=z}).name
|
||||
local nidx = nodedb[nodename]
|
||||
if not nidx then
|
||||
ncount = ncount + 1
|
||||
nodedb[nodename] = ncount;
|
||||
nodelist[ncount] = nodename
|
||||
nidx = ncount
|
||||
end
|
||||
--nodes[idx] = nidx
|
||||
nodes[x-p1.x+1][y-p1.y+1][z-p1.z+1 ] = nidx
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
data[2] = nodelist
|
||||
data[3] = nodes
|
||||
end
|
||||
|
||||
id2pos = function(idx,blockdata) -- idx starts with 0
|
||||
local dx = blockdata[1][2].x
|
||||
local dy = blockdata[1][2].y
|
||||
local dz = blockdata[1][2].z
|
||||
|
||||
-- idx = z*dx*dy + y*dx + dx
|
||||
local x = idx % dx;
|
||||
idx = (idx - x)/dx
|
||||
local y = idx % dy; -- y = y % (dy)
|
||||
local z = (idx - y)/dy
|
||||
return {x=x, y = y, z=z}
|
||||
end
|
||||
|
||||
pos2id = function(pos,blockdata)
|
||||
local dx = blockdata[1][2].x
|
||||
local dy = blockdata[1][2].y
|
||||
local dz = blockdata[1][2].z
|
||||
|
||||
local x = pos.x - blockdata[1][2].x;
|
||||
local y = pos.y - blockdata[1][2].y;
|
||||
local z = pos.z - blockdata[1][2].z;
|
||||
return z*dx*dy + y*dx + dx
|
||||
end
|
||||
|
||||
get_box = function(pos, blockdata, boxdata) -- return p1,p2, nodeidx defining largest contiguos box containing pos (all relative coordinates)
|
||||
|
||||
local nodeidx = blockdata[3][pos.x][pos.y][pos.z];
|
||||
|
||||
local active_dir = {[1]=true,[2]=true,[3]=true,[4]=true,[5]=true,[6]=true}; -- which dirs to search: x-,x+ y-,y+ z-,z+
|
||||
local p1 = {x=pos.x,y=pos.y,z=pos.z} -- search limits
|
||||
local p2 = {x=pos.x,y=pos.y,z=pos.z}
|
||||
local stop = false;
|
||||
|
||||
local steps = 0
|
||||
while not stop and steps < 10000 do -- steps 'safety'
|
||||
steps = steps + 1
|
||||
--dout("step " .. steps .. " p1 " .. serialize(p1) .. " p2 " .. serialize(p2) .. " dirs " .. serialize(active_dir))
|
||||
stop = true
|
||||
for idx,_ in pairs(active_dir) do -- try expansion in different directions
|
||||
stop = false -- still something to do
|
||||
if idx<=2 then
|
||||
local x
|
||||
if idx == 1 then x = p1.x-1 else x=p2.x+1 end
|
||||
if blockdata[3][x] then
|
||||
local bdata = blockdata[3][x];
|
||||
for y = p1.y,p2.y do
|
||||
for z = p1.z,p2.z do
|
||||
if bdata[y][z]~= nodeidx or (boxdata and boxdata[x] and boxdata[x][y] and boxdata[x][y][z]) then
|
||||
active_dir[idx] = nil; goto ex; -- not contiguous anymore
|
||||
end
|
||||
end
|
||||
end
|
||||
::ex::
|
||||
else
|
||||
active_dir[idx] = nil -- out of bounds, remove direction
|
||||
end
|
||||
if active_dir[idx] then -- expansion succesful
|
||||
if idx == 1 then p1.x = p1.x -1 else p2.x = p2.x+1 end
|
||||
end
|
||||
|
||||
elseif idx>=5 then
|
||||
local z
|
||||
if idx == 5 then z = p1.z-1 else z=p2.z+1 end
|
||||
local bdata = blockdata[3]
|
||||
if bdata[1][1][z] then
|
||||
for x = p1.x,p2.x do
|
||||
for y = p1.y,p2.y do
|
||||
if bdata[x][y][z]~= nodeidx or (boxdata and boxdata[x] and boxdata[x][y] and boxdata[x][y][z]) then
|
||||
active_dir[idx] = nil;goto ex; -- lua only breaks out of 1 loop :(
|
||||
end
|
||||
end
|
||||
end
|
||||
::ex::
|
||||
else
|
||||
active_dir[idx] = nil -- out of bounds, remove direction
|
||||
end
|
||||
|
||||
if active_dir[idx] then -- expansion succesful
|
||||
if idx == 5 then p1.z = p1.z -1 else p2.z = p2.z+1 end
|
||||
end
|
||||
else
|
||||
local y
|
||||
if idx == 3 then y = p1.y-1 else y=p2.y+1 end
|
||||
local bdata = blockdata[3]
|
||||
if bdata[1][y] then
|
||||
for x = p1.x,p2.x do
|
||||
for z = p1.z,p2.z do
|
||||
if bdata[x][y][z]~= nodeidx or (boxdata and boxdata[x] and boxdata[x][y] and boxdata[x][y][z]) then
|
||||
active_dir[idx] = nil; goto ex; -- not contiguous anymore
|
||||
end
|
||||
end
|
||||
end
|
||||
::ex::
|
||||
else
|
||||
active_dir[idx] = nil -- out of bounds, remove direction
|
||||
end
|
||||
|
||||
if active_dir[idx] then -- expansion succesful
|
||||
if idx == 3 then p1.y = p1.y-1 else p2.y = p2.y+1 end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end --try to expand: -x +x -y +y -z +z -x +x -y ... when not possible remove direction from list
|
||||
end
|
||||
|
||||
return {p1,p2, nodeidx}
|
||||
end
|
||||
|
||||
get_boxes = function(blockdata,boxdata)
|
||||
|
||||
local dx = blockdata[1][2].x
|
||||
local dy = blockdata[1][2].y
|
||||
local dz = blockdata[1][2].z
|
||||
|
||||
for k,v in pairs(boxdata) do boxdata[k] = nil end
|
||||
local res = {}; -- list of boxes
|
||||
|
||||
|
||||
for x=1,dx do
|
||||
boxdata[x] = {}
|
||||
for y = 1,dy do
|
||||
boxdata[x][y] = {}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local xc, yc,zc;
|
||||
xc = 1 ; yc = 1; zc = 1; -- current 'working' coordinates in block
|
||||
|
||||
local steps = 0;
|
||||
local stop = false;
|
||||
|
||||
while not stop and steps < 1000 do
|
||||
steps = steps + 1
|
||||
stop = true
|
||||
|
||||
-- find 'next' coordinate thats not yet marked: todo - fix bugs here, skipping/unnecessary ...
|
||||
|
||||
xc = 1; -- set 1st index ( inner loop) to start
|
||||
--dout("step " .. steps ..", search start xc yc zc ".. xc .. " " .. yc .. " " .. zc)
|
||||
|
||||
local x,y,z;x= xc; y=yc; z = zc;
|
||||
while (z<=dz) do
|
||||
while (y<=dy) do
|
||||
while (x<=dx) do
|
||||
if not boxdata[x][y][z] then
|
||||
--dout("step " .. steps .. ", next point: " .. x .. " " .. y .. " " .. z)
|
||||
stop = false; xc = x; yc=y; zc = z; goto ex
|
||||
end
|
||||
x=x+1
|
||||
end
|
||||
y=y+1; x=1; -- reset x-loop
|
||||
end
|
||||
z=z+1; y=1; -- reset y-loop
|
||||
end
|
||||
|
||||
--dout("no unmarked point left, dim dx dy dz : " .. dx .. " " .. dy .. " " .. dz)
|
||||
|
||||
::ex::
|
||||
if stop then break end
|
||||
|
||||
--if box non air add it
|
||||
|
||||
local box = get_box({x=xc,y=yc,z=zc},blockdata, boxdata);
|
||||
if blockdata[2][box[3]]~= "air" then
|
||||
res[#res+1] = box
|
||||
end
|
||||
-- mark box area as done
|
||||
|
||||
for x = box[1].x, box[2].x do
|
||||
for y = box[1].y, box[2].y do
|
||||
for z = box[1].z, box[2].z do
|
||||
boxdata[x][y][z] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--dout("boxdata " .. serialize(boxdata))
|
||||
end
|
||||
|
||||
return res
|
||||
end
|
||||
|
||||
render_boxes = function(blockdata,boxes)
|
||||
local dx = blockdata[1][2].x
|
||||
local dy = blockdata[1][2].y
|
||||
local dz = blockdata[1][2].z
|
||||
|
||||
local x0 = blockdata[1][1].x
|
||||
local y0 = blockdata[1][1].y
|
||||
local z0 = blockdata[1][1].z
|
||||
|
||||
|
||||
local nodelist = {
|
||||
"wool:white","wool:red","wool:green","wool:blue","wool:yellow", "wool:cyan","wool:pink",
|
||||
"wool:brown","wool:magenta","wool:orange","wool:violet"
|
||||
}
|
||||
local nodelen = #nodelist
|
||||
|
||||
for x = 1, dx do
|
||||
for y = 1, dy do
|
||||
for z = 1, dz do
|
||||
minetest.set_node({x = x0+x-1, y= y0+y-1+ (dy + 1), z = z0+z-1},{name = "air"})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
for i = 1,#boxes do
|
||||
for x = boxes[i][1].x, boxes[i][2].x do
|
||||
for y = boxes[i][1].y, boxes[i][2].y do
|
||||
for z = boxes[i][1].z, boxes[i][2].z do
|
||||
--minetest.set_node({x = x0+x-1, y= y0+y-1+ (dy + 4), z = z0+z-1},{name = blockdata[2][boxes[i][3] ] })
|
||||
minetest.set_node({x = x0+x-1, y= y0+y-1+ (dy + 4), z = z0+z-1},{name = nodelist[1+((i-1) % nodelen)]})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--p1 = {x=-57,y=6,z=14};p2 = {x=-54,y=6,z=17}
|
||||
p1 = {x=-45,y=502,z=-45};p2 = {x=-30,y=504,z=-30}
|
||||
|
||||
read_block(p1,p2,blockdata) -- careful, all p1 coords must be smaller than p2 coords coordinatewise
|
||||
--self.label(serialize(blockdata))
|
||||
|
||||
-- 7 numbers per box: pos1, pos2, nodeidx. There are n^2 numbers for nxn grid, so for boxes to be efficient
|
||||
-- 7*boxcount<n^3 or boxcount< n^3/7
|
||||
|
||||
--box = get_box({x=3,y=1,z=2},blockdata)
|
||||
--say(serialize(box))
|
||||
|
||||
local boxdata = {};
|
||||
local boxes = get_boxes(blockdata,boxdata);
|
||||
self.label("dimensions " .. blockdata[1][2].x .. " " .. blockdata[1][2].y .. " " .. blockdata[1][2].z .. ", n^3/7 = " .. blockdata[1][2].x*blockdata[1][2].y*blockdata[1][2].z/7 .. ", boxes " .. #boxes )
|
||||
--dout(serialize(boxes))
|
||||
|
||||
render_boxes(blockdata,boxes)
|
||||
|
||||
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
-- send data from robot to irc client, rnd 2018 ( works on vanessae skyblock)
|
||||
|
||||
if not init then
|
||||
ircchat = minetest.registered_chatcommands["irc_msg"].func;
|
||||
name = "r_n_d" -- client on irc you want to send msg too
|
||||
ircchat("ROBOT", name .." " .. "hello irc world") -- chat will appear as coming from <ROBOT> on skyblock
|
||||
init = true
|
||||
end
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
local serialize = function(tab) -- helper function
|
||||
local out = {};
|
||||
for k,v in pairs(tab) do
|
||||
if type(v)~= "table" then
|
||||
out[#out+1] = ""..k .." = " ..v
|
||||
else
|
||||
out[#out+1] = ""..k .. " = " .. serialize(v)
|
||||
end
|
||||
end
|
||||
|
||||
return "{"..table.concat(out,", ").."}"
|
||||
end
|
|
@ -0,0 +1,46 @@
|
|||
-- simple turtlebot with loops, rnd, 30 mins
|
||||
|
||||
if not init then
|
||||
init = true
|
||||
commands = {
|
||||
["f"] = function() move.forward() end,
|
||||
["l"] = function() move.left() end,
|
||||
["r"] = function() move.right() end,
|
||||
["u"] = function() move.up() end,
|
||||
["d"] = function() move.down() end,
|
||||
[">"] = function() turn.right() end,
|
||||
["<"] = function() turn.left() end,
|
||||
["p"] = function() place.down("default:dirt") end,
|
||||
["P"] = function() place.forward_down("default:dirt") end,
|
||||
}
|
||||
|
||||
program = "R3[Pfu]<"
|
||||
loop = {start = 1, quit = 1, count = 1};
|
||||
|
||||
step = 1
|
||||
end
|
||||
|
||||
c = string.sub(program,step,step)
|
||||
if c == "R" then -- loop
|
||||
local i = string.find(program,"%[",step+1);
|
||||
loop.count = tonumber(string.sub(program,step+1, i-1)) or 1;
|
||||
loop.start = i+1;
|
||||
i = string.find(program,"]",i+1);
|
||||
loop.quit = i-1
|
||||
step = loop.start-1
|
||||
else -- normal command
|
||||
command = commands[c];
|
||||
if command then
|
||||
command()
|
||||
elseif step>string.len(program) then
|
||||
step = 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
self.label(step)
|
||||
step = step +1
|
||||
if loop.count>0 then -- are we in loop?
|
||||
if step>loop.quit then loop.count = loop.count - 1; step = loop.start end
|
||||
if loop.count == 0 then step = loop.quit + 2 end
|
||||
end
|
|
@ -0,0 +1,89 @@
|
|||
-- digital money: transform items into key (stand on chest and write \buy) and later get them back (\sell code)
|
||||
|
||||
--[[
|
||||
instructions: put items in chest, stand on top of it and say: \buy. this gives you code, you can later write in
|
||||
'\sell code' and get stuff back.
|
||||
--]]
|
||||
|
||||
if not init then
|
||||
self.label("digital banker bot")
|
||||
password = "super secret password"
|
||||
buydb = {};
|
||||
starttime = minetest.get_gametime()
|
||||
|
||||
_G.minetest.forceload_block(self.pos(),true)
|
||||
|
||||
import_inventory = function(pos) -- read inventory and output digital money
|
||||
local meta = minetest.get_meta(pos); if not meta then return end
|
||||
local inv = meta:get_inventory(); if not inv then return end
|
||||
if not inv:get_size("main") then return end
|
||||
if inv:is_empty("main") then return end
|
||||
|
||||
local invlist = {};
|
||||
for i = 1, inv:get_size("main") do
|
||||
local stack = inv:get_stack("main", i):to_string();
|
||||
local i = string.find(stack, " ");
|
||||
local itemname = stack;
|
||||
local count = 0;
|
||||
if i then
|
||||
itemname = string.sub(stack,1,i-1)
|
||||
count = count + (tonumber(string.sub(stack,i+1)) or 1)
|
||||
end
|
||||
if count == 0 then count = 1 end
|
||||
if itemname ~= "" then invlist[itemname] = (invlist[itemname] or 0) + count end
|
||||
end
|
||||
|
||||
local t = minetest.get_gametime()
|
||||
local out = string.sub(serialize(invlist),7)
|
||||
inv:set_list("main",{})
|
||||
return minetest.get_password_hash("",t .. out .. password) .. " " .. t .. " " .. out
|
||||
|
||||
end
|
||||
|
||||
export_inventory = function(speaker,msg) -- import digital money and give items
|
||||
local i1 = string.find(msg," "); if not i1 then return end
|
||||
local i2 = string.find(msg," ",i1+1); if not i2 then return end
|
||||
local sig = string.sub(msg,1,i1-1);
|
||||
local t = tonumber(string.sub(msg,i1+1,i2-1)) or 0;
|
||||
local out = string.sub(msg,i2+1);
|
||||
local sigm = minetest.get_password_hash("",t .. out .. password);
|
||||
if sigm~=sig then return end
|
||||
|
||||
if t< starttime then return end -- invalid time, before bot start
|
||||
|
||||
if buydb[t] then -- already used, prevent double spending
|
||||
return
|
||||
else
|
||||
buydb[t] = true;
|
||||
end
|
||||
|
||||
local p = minetest.get_player_by_name(speaker);
|
||||
local inv = p:get_inventory();
|
||||
local invlist = deserialize("return " ..out);
|
||||
for item, count in pairs(invlist) do
|
||||
inv:add_item("main", item .. (count==1 and "" or " " .. count))
|
||||
end
|
||||
end
|
||||
|
||||
round = function(x) if x>0 then return math.floor(x+0.5) else return -math.floor(-x+0.5) end end
|
||||
|
||||
init = true
|
||||
self.listen(1)
|
||||
end
|
||||
|
||||
speaker,msg = self.listen_msg()
|
||||
if msg then
|
||||
if msg == "buy" then
|
||||
local pos = minetest.get_player_by_name(speaker):getpos();
|
||||
pos.x = round(pos.x);pos.y = round(pos.y);pos.z = round(pos.z)
|
||||
if pos.y>0 then pos.y = pos.y-1 end
|
||||
local out = import_inventory(pos);
|
||||
if out then
|
||||
local text = "Your code is between BEGIN and END:\nBEGIN\n" .. out.."\nEND\nSave it for future use, to reclaim items say: /sell code. code is valid until next restart."
|
||||
local form = "size[8,8]".. "textarea[0.,0;11.,9.5;text;digital money;".. minetest.formspec_escape(text) .. "]"
|
||||
self.show_form(speaker, form)
|
||||
end
|
||||
elseif string.sub(msg,1,4) == "sell" then
|
||||
export_inventory(speaker,string.sub(msg,6))
|
||||
end
|
||||
end
|
|
@ -0,0 +1,42 @@
|
|||
if not init then init = true
|
||||
horses = {10,5,5,5,5,5}; -- ratings, probability that horse wins is proportional to its rating
|
||||
|
||||
|
||||
|
||||
local rndseed = 1;
|
||||
local random = function(n)
|
||||
rndseed = (48271*rndseed)% 2147483647;
|
||||
return rndseed % n
|
||||
end
|
||||
|
||||
-- race simulation: output is winner, 2nd, 3rd, ...
|
||||
-- algorithm sketch: first choose 1st, then from remainder select 2nd, then ...
|
||||
|
||||
race = function(horses)
|
||||
|
||||
rndseed = os.time()
|
||||
local n = #horses; local sum = 0
|
||||
local res = {};
|
||||
for i = 1,n do sum = sum + horses[i]; res[i]=i end
|
||||
|
||||
for i = 1,n do
|
||||
-- select random idx from i..n as winner of i-th round
|
||||
local sel = random(sum);
|
||||
--find first j such that partial sums i,..,j exceed sel ( probability that horse will be selected is proportional to its rating)
|
||||
local psum = 0; local j = n
|
||||
for k = i,n do
|
||||
psum = psum + horses[res[k]]
|
||||
if psum>= sel then j = k break end
|
||||
end
|
||||
--dout(i..". j= " ..j .. ", sel " .. sel )
|
||||
|
||||
--swap j-th and i-th to put selected horse on i-th position
|
||||
local tmp = res[j]; res[j] = res[i]; res[i] = tmp
|
||||
sum = sum - horses[ tmp ] -- remove winner from sum
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
self.label( serialize(race(horses)) )
|
||||
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
-- pathfinder robot
|
||||
|
||||
if not init then
|
||||
max_jump = 1
|
||||
max_drop = 1
|
||||
searchdistance = 10
|
||||
move.forward(); move.down()
|
||||
pos1 = self.pos()
|
||||
pos2 = {x = -70 , y = -1, z = -123 }
|
||||
path = minetest.find_path(pos1,pos2,searchdistance,max_jump,max_drop,"Dijkstra")
|
||||
if not path then say("i dont know how to get there :(") self.remove() end
|
||||
|
||||
say("im going to " .. pos2.x .. " " .. pos2.y .. " " .. pos2.z .. ", will be there in " .. #path .. " seconds")
|
||||
-- self.label(serialize(path))
|
||||
step = 0
|
||||
obj = _G.basic_robot.data[self.name()].obj
|
||||
init = true
|
||||
end
|
||||
|
||||
if step<#path then
|
||||
step = step + 1
|
||||
pos = path[step]
|
||||
obj:setpos(pos)
|
||||
if step == #path then say("arrived at destination.") end
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
--TODO: unfinished
|
||||
if not init then
|
||||
state = 0
|
||||
init = true
|
||||
walkdb = {};
|
||||
spos = self.spawnpos();
|
||||
step = 0
|
||||
startstep = 0; -- mark the step when next walk around begins
|
||||
|
||||
local get_dir = function()
|
||||
local dir = self.viewdir()
|
||||
end
|
||||
|
||||
rot_left = function(dir) local tmp = dir.x;dir.x = -dir.z; dir.z = tmp end
|
||||
|
||||
rot_right = function(dir) local tmp = dir.x;dir.x = dir.z; dir.z = -tmp end
|
||||
|
||||
end
|
||||
|
||||
if state == 0 then
|
||||
if not move.forward() then state = 1; turn.right(); startstep = 1 end
|
||||
elseif state == 1 then
|
||||
step = step + 1
|
||||
local pos = self.pos();
|
||||
local x = pos.x-spos.x; local z = pos.z-spos.z;
|
||||
if not walkdb[x] then walkdb[x] = {} end walkdb[x][z] = step; -- add position
|
||||
local dir = self.viewdir();
|
||||
|
||||
local node = read_node.left();
|
||||
|
||||
|
||||
|
||||
rot_left(dir) -- rotate left
|
||||
local xr = x + dir.x; local zr = z + dir.z
|
||||
|
||||
if node == "air" and (not dir[xr] or not dir[xr][zr]) then turn.left() end
|
||||
if not move.forward() and (not dir[xn] or not dir[xn][zn]) then turn.right() move.forward() end
|
||||
end
|
||||
|
||||
self.label(state)
|
|
@ -0,0 +1,46 @@
|
|||
-- simple turtlebot with loops, rnd, 30 mins
|
||||
|
||||
if not init then
|
||||
init = true
|
||||
commands = {
|
||||
["f"] = function() move.forward() end,
|
||||
["l"] = function() move.left() end,
|
||||
["r"] = function() move.right() end,
|
||||
["u"] = function() move.up() end,
|
||||
["d"] = function() move.down() end,
|
||||
[">"] = function() turn.right() end,
|
||||
["<"] = function() turn.left() end,
|
||||
["p"] = function() place.down("default:dirt") end,
|
||||
["P"] = function() place.forward_down("default:dirt") end,
|
||||
}
|
||||
|
||||
program = "R3[Pfu]<"
|
||||
loop = {start = 1, quit = 1, count = 1};
|
||||
|
||||
step = 1
|
||||
end
|
||||
|
||||
c = string.sub(program,step,step)
|
||||
if c == "R" then -- loop
|
||||
local i = string.find(program,"%[",step+1);
|
||||
loop.count = tonumber(string.sub(program,step+1, i-1)) or 1;
|
||||
loop.start = i+1;
|
||||
i = string.find(program,"]",i+1);
|
||||
loop.quit = i-1
|
||||
step = loop.start-1
|
||||
else -- normal command
|
||||
command = commands[c];
|
||||
if command then
|
||||
command()
|
||||
elseif step>string.len(program) then
|
||||
step = 0
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
self.label(step)
|
||||
step = step +1
|
||||
if loop.count>0 then -- are we in loop?
|
||||
if step>loop.quit then loop.count = loop.count - 1; step = loop.start end
|
||||
if loop.count == 0 then step = loop.quit + 2 end
|
||||
end
|
|
@ -0,0 +1,73 @@
|
|||
-- 3d printer bot, made by rnd in 30 mins
|
||||
if not init then
|
||||
|
||||
nx = 5; ny = 5; nz = 5
|
||||
data = {}; -- [nx][nz][ny]
|
||||
|
||||
rndseed = 1;
|
||||
random = function(n)
|
||||
rndseed = (48271*rndseed)% 2147483647;
|
||||
return rndseed % n
|
||||
end
|
||||
|
||||
for i = 1,nx do
|
||||
data[i]={}
|
||||
for j = 1,nz do
|
||||
data[i][j] = {}
|
||||
for k = 1,ny do
|
||||
if random(2) == 1 then data[i][j][k] = true end -- make random structure
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local spos = self.spawnpos(); spos.y = spos.y+1; spos.z = spos.z+1
|
||||
state = 1; -- walk in x way, state = 1: build up
|
||||
x=1; z = 1; y = 1; angle = -90
|
||||
zc = 1; worky = 1;
|
||||
|
||||
get_worky = function()
|
||||
worky = 0
|
||||
local dataxz = data[x][zc]
|
||||
if not dataxz then return end
|
||||
for k = ny,1,-1 do if dataxz[k] then worky = k break end end
|
||||
end
|
||||
get_worky()
|
||||
|
||||
move.forward(); move.right()
|
||||
init = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
if state == 0 then -- walk around
|
||||
if z>=nz then
|
||||
x = x+1; z=0;
|
||||
turn.angle(angle); move.forward(); turn.angle(angle)
|
||||
angle = -angle;
|
||||
if x>nx then self.remove() end
|
||||
else
|
||||
move.forward()
|
||||
end
|
||||
z=z+1
|
||||
if angle<0 then zc = z else zc = nz-z+1 end
|
||||
get_worky() -- is there anything to print at x,z?
|
||||
if worky>0 then state = 1 y = 1 end
|
||||
|
||||
self.label("walking at " .. x .. " " .. zc .. ", worky = " .. worky)
|
||||
elseif state == 1 then -- make coloumn
|
||||
|
||||
if y>=worky+1 then
|
||||
state = 2 -- go down ladder
|
||||
else
|
||||
place.down("default:ladder")
|
||||
y=y+1; move.up()
|
||||
end
|
||||
self.label("going up " .. x .. " " .. zc .. ", y = " .. (y-1))
|
||||
elseif state == 2 then -- go down and build
|
||||
dig.down();move.down();
|
||||
|
||||
if data[x][zc][y-1] then place.up("default:dirt") end
|
||||
y=y-1
|
||||
self.label("going down at " .. x .. " " .. zc .. ", y = " .. (y-1))
|
||||
if y<2 then state = 0; y = 1 end
|
||||
end
|
BIN
sounds/Dtmf0.ogg
BIN
sounds/Dtmf0.ogg
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue