parent
c3b8f19c83
commit
08f61c0865
82
commands.lua
82
commands.lua
|
@ -44,6 +44,19 @@ local function pos_in_dir(obj, dir) -- position after we move in specified direc
|
|||
return pos
|
||||
end
|
||||
|
||||
local check_operations = function(name, quit)
|
||||
if basic_robot.maxoperations~=0 then
|
||||
local data = basic_robot.data[name];
|
||||
local operations = data.operations;
|
||||
if operations > 0 then data.operations = operations-1 else
|
||||
if quit then
|
||||
error("robot out of available operations in one step."); return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
basic_robot.commands.move = function(name,dir)
|
||||
local obj = basic_robot.data[name].obj;
|
||||
local pos = pos_in_dir(obj, dir)
|
||||
|
@ -65,9 +78,6 @@ basic_robot.commands.move = function(name,dir)
|
|||
-- obj:set_animation({x=81,y=160})
|
||||
-- end
|
||||
|
||||
|
||||
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
@ -80,11 +90,7 @@ end
|
|||
basic_robot.commands.dig = function(name,dir)
|
||||
|
||||
local energy = 0;
|
||||
if basic_robot.maxenergy~=0 then
|
||||
local data = basic_robot.data[name];
|
||||
energy = data.energy;
|
||||
if energy > 0 then data.energy = energy-1 else return false end
|
||||
end
|
||||
check_operations(name);
|
||||
|
||||
local obj = basic_robot.data[name].obj;
|
||||
local pos = pos_in_dir(obj, dir)
|
||||
|
@ -351,11 +357,7 @@ end
|
|||
basic_robot.commands.attack = function(name, target) -- attack range 4, damage 5
|
||||
|
||||
local energy = 0;
|
||||
if basic_robot.maxenergy~=0 then
|
||||
local data = basic_robot.data[name];
|
||||
energy = data.energy;
|
||||
if energy > 0 then data.energy = energy-1 else return false end
|
||||
end
|
||||
check_operations(name);
|
||||
|
||||
local reach = 4;
|
||||
local damage = 5;
|
||||
|
@ -625,7 +627,8 @@ basic_robot.commands.keyboard = {
|
|||
}
|
||||
|
||||
basic_robot.commands.craftcache = {};
|
||||
basic_robot.commands.craft = function(item, name)
|
||||
|
||||
basic_robot.commands.craft = function(item, mode, name)
|
||||
if not item then return end
|
||||
|
||||
local cache = basic_robot.commands.craftcache[name];
|
||||
|
@ -673,6 +676,8 @@ basic_robot.commands.craft = function(item, name)
|
|||
--minetest.chat_send_all(item)
|
||||
--minetest.chat_send_all(dump(itemlist))
|
||||
|
||||
if mode == 1 then return itemlist end
|
||||
|
||||
-- check if all items from itemlist..
|
||||
-- craft item
|
||||
|
||||
|
@ -714,7 +719,7 @@ end)
|
|||
|
||||
basic_robot.technic = { -- data cache
|
||||
fuels = {}, --[fuel] = value
|
||||
smelts = {}, -- item = [cooktime, cookeditem, aftercookeditem]
|
||||
smelts = {}, -- [item] = [cooktime, cookeditem, aftercookeditem]
|
||||
|
||||
grinder_recipes = { --[in] ={fuel cost, out, quantity of material required for processing}
|
||||
["default:stone"] = {2,"default:sand",1},
|
||||
|
@ -754,6 +759,7 @@ basic_robot.technic = { -- data cache
|
|||
}
|
||||
|
||||
local chk_machine_level = function(inv,level) -- does machine have upgrade to be classified with at least "level"
|
||||
if level < 1 then level = 1 end
|
||||
local upg = {"default:diamondblock","default:mese","default:goldblock"};
|
||||
for i = 1,#upg do
|
||||
if not inv:contains_item("main",ItemStack(upg[i].. " " .. level)) then return false end
|
||||
|
@ -761,11 +767,14 @@ local chk_machine_level = function(inv,level) -- does machine have upgrade to be
|
|||
return true
|
||||
end
|
||||
|
||||
|
||||
basic_robot.commands.machine = {
|
||||
|
||||
-- convert fuel into energy
|
||||
generate_power = function(name,input, amount) -- fuel used, if no fuel then amount specifies how much energy builtin generator should produce
|
||||
|
||||
check_operations(name, true)
|
||||
|
||||
if amount and amount>0 then -- attempt to generate power from builtin generator
|
||||
local pos = basic_robot.data[name].spawnpos; -- position of spawner block
|
||||
local inv = minetest.get_meta(pos):get_inventory();
|
||||
|
@ -778,11 +787,7 @@ basic_robot.commands.machine = {
|
|||
end
|
||||
|
||||
local energy = 0; -- can only do one step at a run time
|
||||
if basic_robot.maxenergy~=0 then
|
||||
local data = basic_robot.data[name];
|
||||
energy = data.energy;
|
||||
if energy > 0 then data.energy = energy-1 else error("only one generate_power per run step allowed"); return end
|
||||
end
|
||||
|
||||
|
||||
if string.find(input," ") then return nil, "1: can convert only one item at once" end
|
||||
|
||||
|
@ -797,6 +802,8 @@ basic_robot.commands.machine = {
|
|||
local fueladd, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = {stack}})
|
||||
if fueladd.time > 0 then
|
||||
add_energy = fueladd.time;
|
||||
else
|
||||
return nil, "3: material can not be used as a fuel"
|
||||
end
|
||||
if add_energy>0 then basic_robot.technic.fuels[input] = add_energy/40 end
|
||||
end
|
||||
|
@ -813,15 +820,7 @@ basic_robot.commands.machine = {
|
|||
smelt = function(name,input,amount) -- input material, amount of energy used for smelt
|
||||
|
||||
local energy = 0; -- can only do one step at a run time
|
||||
if basic_robot.maxenergy~=0 then
|
||||
local data = basic_robot.data[name];
|
||||
energy = data.energy;
|
||||
if energy > 0 then
|
||||
data.energy = energy-1
|
||||
else
|
||||
error("only one smelt per run step allowed"); return
|
||||
end
|
||||
end
|
||||
check_operations(name,true)
|
||||
|
||||
if string.find(input," ") then return nil, "0: only one item per smelt" end
|
||||
|
||||
|
@ -845,7 +844,7 @@ basic_robot.commands.machine = {
|
|||
|
||||
local data = basic_robot.data[name]
|
||||
energy = data.menergy or 0; -- machine energy
|
||||
if energy<=cost then return nil,"1: not enough energy" end
|
||||
if energy<cost then return nil,"1: not enough energy" end
|
||||
|
||||
local stack = ItemStack(input);
|
||||
if not inv:contains_item("main",stack) then return nil, "2: no input materials" end
|
||||
|
@ -853,13 +852,15 @@ basic_robot.commands.machine = {
|
|||
local src_time = (data.src_time or 0)+smelttimeboost;
|
||||
|
||||
-- get smelting data
|
||||
local smelts = basic_robot.technic.fuels[input];
|
||||
local smelts = basic_robot.technic.smelts[input];
|
||||
if not smelts then
|
||||
local cooked, aftercooked;
|
||||
cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = {stack}})
|
||||
if cooked.time>0 then
|
||||
basic_robot.technic.fuels[input] = {cooked.time, cooked.item, aftercooked.items[1]};
|
||||
smelts = basic_robot.technic.fuels[input];
|
||||
basic_robot.technic.smelts[input] = {cooked.time, cooked.item, aftercooked.items[1]};
|
||||
smelts = basic_robot.technic.smelts[input];
|
||||
else
|
||||
return nil, "3: material can not be smelted"
|
||||
end
|
||||
end
|
||||
local cooktime = smelts[1]; local cookeditem = smelts[2]; local aftercookeditem = smelts[3]
|
||||
|
@ -890,7 +891,7 @@ basic_robot.commands.machine = {
|
|||
local inv = minetest.get_meta(pos):get_inventory();
|
||||
|
||||
--level requirement
|
||||
local level = math.floor((cost-1)/3)
|
||||
local level = math.floor((cost-1)/3);
|
||||
|
||||
if not chk_machine_level(inv,level) then error("0: tried to grind " .. input .. " requires upgrade level at least " .. level) return end
|
||||
|
||||
|
@ -943,22 +944,15 @@ basic_robot.commands.machine = {
|
|||
if not tdata then return nil, "target inactive" end
|
||||
|
||||
local energy = 0; -- can only do one step at a run time
|
||||
if basic_robot.maxenergy~=0 then
|
||||
local data = basic_robot.data[name];
|
||||
energy = data.energy;
|
||||
if energy > 0 then
|
||||
data.energy = energy-1
|
||||
else
|
||||
error("only one transfer per run step allowed"); return
|
||||
end
|
||||
end
|
||||
check_operations(name, true);
|
||||
|
||||
energy = data.menergy or 0;
|
||||
if amount>energy then return nil,"energy too low" end
|
||||
|
||||
if not tdata.menergy then tdata.menergy = 0 end
|
||||
tdata.menergy = tdata.menergy + amount
|
||||
data.energy = energy - amount;
|
||||
data.menergy = energy - amount;
|
||||
return true
|
||||
|
||||
end,
|
||||
}
|
91
init.lua
91
init.lua
|
@ -8,13 +8,13 @@ basic_robot.call_limit = 48; -- how many execution calls per script run allowed
|
|||
basic_robot.bad_inventory_blocks = { -- disallow taking from these nodes inventories
|
||||
["craft_guide:sign_wall"] = true,
|
||||
}
|
||||
basic_robot.maxenergy = 1; -- how much energy available per run, 0 = unlimited
|
||||
basic_robot.maxoperations = 1; -- how many operations available per run, 0 = unlimited
|
||||
basic_robot.use_coal = true; -- does robot require coal to dig stone?
|
||||
----------------------
|
||||
|
||||
|
||||
|
||||
basic_robot.version = "02/07a";
|
||||
basic_robot.version = "06/18a";
|
||||
|
||||
basic_robot.data = {}; -- stores all robot data
|
||||
--[[
|
||||
|
@ -27,6 +27,7 @@ basic_robot.ids = {}; -- stores maxid for all players
|
|||
basic_robot.data.listening = {}; -- which robots listen to chat
|
||||
dofile(minetest.get_modpath("basic_robot").."/commands.lua")
|
||||
|
||||
local check_code, preprocess_code,is_inside_string;
|
||||
|
||||
|
||||
|
||||
|
@ -38,6 +39,8 @@ function getSandboxEnv (name)
|
|||
local env =
|
||||
{
|
||||
pcall=pcall,
|
||||
robot_version = function() return basic_robot.version end,
|
||||
|
||||
move = { -- changes position of robot
|
||||
left = function() return commands.move(name,1) end,
|
||||
right = function() return commands.move(name,2) end,
|
||||
|
@ -118,8 +121,8 @@ function getSandboxEnv (name)
|
|||
return commands.pickup(r, name);
|
||||
end,
|
||||
|
||||
craft = function(item)
|
||||
return commands.craft(item, name)
|
||||
craft = function(item, mode)
|
||||
return commands.craft(item, mode, name)
|
||||
end,
|
||||
|
||||
self = {
|
||||
|
@ -187,6 +190,11 @@ function getSandboxEnv (name)
|
|||
obj:setpos({x=pos.x,y=pos.y+1,z=pos.z}); obj:setyaw(0);
|
||||
end,
|
||||
|
||||
set_libpos = function(pos)
|
||||
local pos = basic_robot.data[name].spawnpos; local meta = minetest.get_meta(pos);
|
||||
meta:set_string("libpos",pos.x .. " " .. pos.y .. " " .. pos.z)
|
||||
end,
|
||||
|
||||
spam = function (mode) -- allow more than one msg per "say"
|
||||
if mode == 1 then
|
||||
basic_robot.data[name].allow_spam = true
|
||||
|
@ -241,6 +249,20 @@ function getSandboxEnv (name)
|
|||
commands.display_text(obj,text,linesize,size)
|
||||
end,
|
||||
|
||||
sound = function(sample,volume)
|
||||
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
|
||||
|
@ -318,7 +340,7 @@ function getSandboxEnv (name)
|
|||
backward = function(stringname,mode) return commands.read_text(name,mode,4,stringname) end,
|
||||
down = function(stringname,mode) return commands.read_text(name,mode,6,stringname) end,
|
||||
up = function(stringname,mode) return commands.read_text(name,mode,5,stringname) end,
|
||||
forward_down = function() return commands.read_text(name,mode,7,stringname) end,
|
||||
forward_down = function(stringname,mode) return commands.read_text(name,mode,7,stringname) end,
|
||||
},
|
||||
|
||||
write_text = { -- returns text
|
||||
|
@ -328,12 +350,12 @@ function getSandboxEnv (name)
|
|||
backward = function(text) return commands.write_text(name,4,text) end,
|
||||
down = function(text) return commands.write_text(name,6,text) end,
|
||||
up = function(text) return commands.write_text(name,5,text) end,
|
||||
forward_down = function() return commands.write_text(name,7,text) end,
|
||||
forward_down = function(text) return commands.write_text(name,7,text) end,
|
||||
|
||||
},
|
||||
|
||||
say = function(text)
|
||||
if not basic_robot.data[name].quiet_mode then
|
||||
say = function(text, owneronly)
|
||||
if not basic_robot.data[name].quiet_mode and not owneronly then
|
||||
minetest.chat_send_all("<robot ".. name .. "> " .. text)
|
||||
if not basic_robot.data[name].allow_spam then
|
||||
basic_robot.data[name].quiet_mode=true
|
||||
|
@ -380,6 +402,15 @@ function getSandboxEnv (name)
|
|||
end,
|
||||
|
||||
run = function(script)
|
||||
if basic_robot.data[name].isadmin ~= 1 then
|
||||
local err = check_code(script);
|
||||
script = preprocess_code(script);
|
||||
if err then
|
||||
minetest.chat_send_player(name,"#ROBOT CODE CHECK ERROR : " .. err)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local ScriptFunc, CompileError = loadstring( script )
|
||||
if CompileError then
|
||||
minetest.chat_send_player(name, "#code.run: compile error " .. CompileError )
|
||||
|
@ -470,10 +501,9 @@ end
|
|||
|
||||
-- code checker
|
||||
|
||||
local function check_code(code)
|
||||
|
||||
check_code = function(code)
|
||||
--"while ", "for ", "do ","goto ",
|
||||
local bad_code = {"repeat ", "until ", "_ccounter", "_G", "while%(", "while{", "pcall","\\\""}
|
||||
local bad_code = {"repeat", "until", "_ccounter", "_G", "while%(", "while{", "pcall","\\\""}
|
||||
|
||||
for _, v in pairs(bad_code) do
|
||||
if string.find(code, v) then
|
||||
|
@ -484,7 +514,7 @@ local function check_code(code)
|
|||
end
|
||||
|
||||
|
||||
local function is_inside_string(pos,script)
|
||||
is_inside_string = function(pos,script)
|
||||
local i1=string.find (script, "\"", 1);
|
||||
if not i1 then
|
||||
return false
|
||||
|
@ -514,7 +544,7 @@ end
|
|||
|
||||
-- COMPILATION
|
||||
|
||||
local function preprocess_code(script)
|
||||
preprocess_code = function(script)
|
||||
--[[ idea: in each local a = function (args) ... end insert counter like:
|
||||
local a = function (args) counter() ... end
|
||||
when counter exceeds limit exit with error
|
||||
|
@ -535,9 +565,10 @@ local function preprocess_code(script)
|
|||
found = false;
|
||||
i2 = nil;
|
||||
|
||||
-- i1 = where its looking
|
||||
|
||||
i2=string.find (script, "while ", i1) -- fix while OK
|
||||
if i2 then
|
||||
--minetest.chat_send_all("while0");
|
||||
if not is_inside_string(i2,script) then
|
||||
local i21 = i2;
|
||||
i2=string.find(script, "do", i2);
|
||||
|
@ -566,7 +597,7 @@ local function preprocess_code(script)
|
|||
i2=string.find (script, "for ", i1) -- fix for OK
|
||||
if i2 then
|
||||
if not is_inside_string(i2,script) then
|
||||
i2=string.find(script, "do ", i2);
|
||||
i2=string.find(script, "do", i2);
|
||||
if i2 then
|
||||
script = script.sub(script,1, i2+1) .. _increase_ccounter .. script.sub(script, i2+2);
|
||||
i1=i2+string.len(_increase_ccounter);
|
||||
|
@ -633,7 +664,7 @@ local function runSandbox( name)
|
|||
end
|
||||
|
||||
data.ccounter = 0;
|
||||
data.energy = 1;
|
||||
data.operations = 1;
|
||||
|
||||
setfenv( ScriptFunc, data.sandbox )
|
||||
|
||||
|
@ -716,7 +747,7 @@ local function init_robot(obj)
|
|||
end
|
||||
|
||||
minetest.register_entity("basic_robot:robot",{
|
||||
energy = 1,
|
||||
operations = 1,
|
||||
owner = "",
|
||||
name = "",
|
||||
hp_max = 100,
|
||||
|
@ -789,7 +820,7 @@ minetest.register_entity("basic_robot:robot",{
|
|||
if self.timer>self.timestep and self.running == 1 then
|
||||
self.timer = 0;
|
||||
local err = runSandbox(self.name);
|
||||
if err then
|
||||
if err and type(err) == "string" then
|
||||
local i = string.find(err,":");
|
||||
if i then err = string.sub(err,i+1) end
|
||||
if string.sub(err,-5)~="abort" then
|
||||
|
@ -927,7 +958,7 @@ local spawn_robot = function(pos,node,ttl)
|
|||
if not data.sandbox then data.sandbox = getSandboxEnv (name) end
|
||||
|
||||
-- actual code run process
|
||||
data.ccounter = 0;data.energy = 1;
|
||||
data.ccounter = 0;data.operations = 1;
|
||||
|
||||
setfenv(data.bytecode, data.sandbox )
|
||||
|
||||
|
@ -1087,7 +1118,7 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
|
|||
" if index>0 it returns itemname. if itemname == \"\" it checks if inventory empty\n"..
|
||||
" activate.direction(mode) activates target block\n"..
|
||||
" pickup(r) picks up all items around robot in radius r<8 and returns list or nil\n"..
|
||||
" craft(item) crafts item if required materials are present in inventory\n"..
|
||||
" craft(item,mode) crafts item if required materials are present in inventory. mode = 1 returns recipe\n"..
|
||||
" take.direction(item, inventory) takes item from target inventory into robot inventory\n"..
|
||||
" read_text.direction(stringname,mode) reads text of signs, chests and other blocks, optional stringname for other meta,\n mode 1 read number\n"..
|
||||
" write_text.direction(text,mode) writes text to target block as infotext\n"..
|
||||
|
@ -1118,20 +1149,22 @@ local on_receive_robot_form = function(pos, formname, fields, sender)
|
|||
" self.fire_pos() returns last hit position\n"..
|
||||
" self.label(text) changes robot label\n"..
|
||||
" self.display_text(text,linesize,size) displays text instead of robot face\n"..
|
||||
" self.sound(sample,volume) plays sound named 'sample' at robot location\n"..
|
||||
" rom is aditional table that can store persistent data, like rom.x=1\n"..
|
||||
"**KEYBOARD : place spawner at coordinates (20i,40j+1,20k) to monitor events\n"..
|
||||
" keyboard.get() returns table {x=..,y=..,z=..,puncher = .. , type = .. } for keyboard event\n"..
|
||||
" keyboard.set(pos,type) set key at pos of type 0=air, 1..6, limited to range 10 around\n"..
|
||||
" keyboard.read(pos) return node name at pos\n"..
|
||||
"**TECHNIC FUNCTIONALITY: namespace 'machine'\n" ..
|
||||
"**TECHNIC FUNCTIONALITY: namespace 'machine'. most functions return true or nil, error\n" ..
|
||||
" energy() displays available energy\n"..
|
||||
" generate_power(fuel, amount) attempt to generate power from fuel material, if\n" ..
|
||||
" amount>0 try generate amount of power using builtin generator - this requires\n" ..
|
||||
" generate_power(fuel, amount) = energy, attempt to generate power from fuel material,\n" ..
|
||||
" if amount>0 try generate amount of power using builtin generator - this requires\n" ..
|
||||
" 40 gold/mese/diamonblock upgrades for each 1 amount\n"..
|
||||
" smelt(input,amount) works as a furnace, if amount>0 try to use power to smelt -\n" ..
|
||||
" requires 10 upgrades for each 1 amount, energy cost is: 1/40*(1+amount)\n"..
|
||||
" smelt(input,amount) = progress/true. works as a furnace, if amount>0 try to\n" ..
|
||||
" use power to smelt - requires 10 upgrades for each 1 amount, energy cost is:\n"..
|
||||
" 1/40*(1+amount)\n"..
|
||||
" grind(input) - grinds input material, requires upgrades for harder material\n"..
|
||||
" compress(input) requires upgrades - energy intensive process\n" ..
|
||||
" compress(input) - requires upgrades - energy intensive process\n" ..
|
||||
" transfer_power(amount,target_robot_name)\n";
|
||||
|
||||
text = minetest.formspec_escape(text);
|
||||
|
@ -1296,15 +1329,15 @@ minetest.register_on_player_receive_fields(
|
|||
elseif fields.right then
|
||||
pcall(function () commands.move(name,2) end)
|
||||
elseif fields.dig then
|
||||
pcall(function () basic_robot.data[name].energy = 1; commands.dig(name,3) end)
|
||||
pcall(function () basic_robot.data[name].operations = 1; commands.dig(name,3) end)
|
||||
elseif fields.up then
|
||||
pcall(function () commands.move(name,5) end)
|
||||
elseif fields.down then
|
||||
pcall(function () commands.move(name,6) end)
|
||||
elseif fields.digdown then
|
||||
pcall(function () basic_robot.data[name].energy = 1; commands.dig(name,6) end)
|
||||
pcall(function () basic_robot.data[name].operations = 1; commands.dig(name,6) end)
|
||||
elseif fields.digup then
|
||||
pcall(function () basic_robot.data[name].energy = 1; commands.dig(name,5) end)
|
||||
pcall(function () basic_robot.data[name].operations = 1; commands.dig(name,5) end)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
|
|
@ -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,91 @@
|
|||
if not s then
|
||||
-- init
|
||||
bots = {[4] = {}, [5] = {}}; -- [type] = {{1,1,10}, {3,2,10}}; -- {x,y,hp}
|
||||
arena = {}; --[x][z] = {type, idx}
|
||||
for i = -10,10 do arena[i] = {} for j=-10,10 do arena[i][j] = {0,0} end end
|
||||
centerpos = self.spawnpos(); centerpos.y = centerpos.y+2
|
||||
TYPE = 4; -- 4,5 defines which bots are on the move/attack
|
||||
DIR = 1
|
||||
s=0
|
||||
t=0
|
||||
-- load user progs
|
||||
_,script1 = book.read(1);_,script2 = book.read(2);
|
||||
prog1, _ = _G.loadstring( script1 ); prog2, _ = _G.loadstring( script2 );
|
||||
|
||||
spawn_bot = function (x,z,type)
|
||||
if arena[x] and arena[x][z] and arena[x][z][1] == 0 then
|
||||
keyboard.set({x=centerpos.x+x,y=centerpos.y,z=centerpos.z+z},type)
|
||||
table.insert(bots[type],{x,z,10})
|
||||
arena[x][z] = {type,#bots[type]}
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
move_bot = function (i,dx,dz)
|
||||
local bot = bots[TYPE][i];if not bot then return false end
|
||||
if math.abs(dx)>1 or math.abs(dz)>1 then return false end
|
||||
local x1=bot[1]+dx; local z1=bot[2]+dz;
|
||||
if math.abs(x1)>10 or math.abs(z1)>10 then return false end
|
||||
if arena[x1] and arena[x1][z1] and arena[x1][z1][1] == 0 then else return false end
|
||||
|
||||
keyboard.set({x=centerpos.x+bot[1],y=centerpos.y,z=centerpos.z+bot[2]},0);
|
||||
keyboard.set({x=centerpos.x+x1,y=centerpos.y,z=centerpos.z+z1},TYPE);
|
||||
arena[bot[1]][bot[2]] = {0,0}
|
||||
arena[x1][z1] = {TYPE,i}
|
||||
|
||||
bot[1]=x1;bot[2]=z1;
|
||||
end
|
||||
|
||||
attack_bot = function(i,dx,dz)
|
||||
local bot = bots[TYPE][i];if not bot then return false end
|
||||
if math.abs(dx)>1 or math.abs(dz)>1 then return false end
|
||||
local x1=bot[1]+dx; local z1=bot[2]+dz;
|
||||
if math.abs(x1)>10 or math.abs(z1)>10 then return false end
|
||||
if arena[x1] and arena[x1][z1] and arena[x1][z1][1] == 0 then return false end
|
||||
local type = arena[x1][z1][1]; local idx = arena[x1][z1][2];
|
||||
local tbot = bots[type][idx];
|
||||
if not tbot then return false end
|
||||
tbot[3]=tbot[3]-5;
|
||||
if tbot[3]<=0 then
|
||||
keyboard.set({x=centerpos.x+tbot[1],y=centerpos.y,z=centerpos.z+tbot[2]},0);
|
||||
table.remove(bots[type],idx);
|
||||
arena[x1][z1] = {0,0}
|
||||
end
|
||||
end
|
||||
|
||||
read_arena = function(x,z)
|
||||
local data = arena[x][z];
|
||||
if not data then return end
|
||||
return {data[1],data[2]};
|
||||
end
|
||||
|
||||
read_bots = function (type, idx)
|
||||
local data = bots[type][idx];
|
||||
if not data then return end
|
||||
return {data[1],data[2],data[3]}
|
||||
end
|
||||
end
|
||||
|
||||
if t%10 == 0 then
|
||||
spawn_bot(0,-10,4)
|
||||
spawn_bot(0,10,5)
|
||||
end
|
||||
t=t+1
|
||||
self.label(#bots[4] .. " " .. #bots[5])
|
||||
|
||||
-- PROGRAM RULES:
|
||||
-- not allowed to modify api code: TYPE, bots,t,s, spawn_bot, move_bot, attack_bot, read_arena, read_bots
|
||||
-- only allowed to move bot or attack, but not to dig/place
|
||||
|
||||
TYPE = 4+(t%2);
|
||||
DIR = - DIR
|
||||
|
||||
if TYPE == 5 then
|
||||
_G.setfenv(prog1, _G.basic_robot.data[self.name()].sandbox )
|
||||
_,err = pcall(prog1)
|
||||
else
|
||||
_G.setfenv(prog2, _G.basic_robot.data[self.name()].sandbox )
|
||||
_,err = pcall(prog2)
|
||||
end
|
||||
if err then say(err) self.remove() end
|
|
@ -0,0 +1,184 @@
|
|||
if not number then
|
||||
number = {};
|
||||
number.base = 10; -- what base: 2-10
|
||||
number.data = {};
|
||||
number.size = -1;
|
||||
|
||||
function number:tostring()
|
||||
local ret = ""
|
||||
--say("tostring size " .. self.size)
|
||||
for i = self.size,1,-1 do ret = ret .. (self.data[i] or "X").."" end
|
||||
return ret
|
||||
end
|
||||
|
||||
function number:new(data)
|
||||
local o = {};_G.setmetatable(o, self); o.data = {};
|
||||
for i = 1,#data do o.data[i] = data[i] end -- do copy otherwise it just saves reference
|
||||
o.size = #data;
|
||||
self.__index = self; return o
|
||||
end
|
||||
|
||||
number.add = function (lhs, rhs,res)
|
||||
local n1 = lhs.size;local n2 = rhs.size;local n = math.max(n1,n2);
|
||||
local carry=0, sum; local base = lhs.base;
|
||||
local out = false;
|
||||
if not res then res = number:new({}) out = true end
|
||||
local data = res.data
|
||||
for i = 1,n do
|
||||
sum = (lhs.data[i] or 0)+(rhs.data[i] or 0)+carry;
|
||||
if carry>0 then carry = 0 end
|
||||
if sum>=base then data[i]=sum-base; carry = 1 else data[i] = sum end
|
||||
end
|
||||
if carry>0 then data[n+1]=1 res.size = n+1 else res.size = n end
|
||||
if out then return res end
|
||||
end
|
||||
|
||||
number.__add = add;
|
||||
|
||||
function number:set(m)
|
||||
local data = self.data;
|
||||
local mdata = m.data;
|
||||
for i=1,#mdata do
|
||||
data[i]=mdata[i];
|
||||
end
|
||||
self.size = m.size;
|
||||
end
|
||||
|
||||
-- 'slow' long multiply
|
||||
number.multiply = function (lhs, rhs, res)
|
||||
local n1 = lhs.size;local n2 = rhs.size;local n = n1+n2;
|
||||
--say("multiply sizes " .. n1 .. "," .. n2)
|
||||
local out = false;
|
||||
if not res then res = number:new({}); out = true end;
|
||||
res.size = n1+n2-1;
|
||||
res.data = {} -- if data not cleared it will interfere with result!
|
||||
local data = res.data;
|
||||
local c,prod,carry = 0; local base = lhs.base;
|
||||
for i=1,n1 do
|
||||
carry = 0;
|
||||
c = lhs.data[i] or 0;
|
||||
for j = 1,n2 do -- multiply with i-th digit and add to result
|
||||
prod = (data[i+j-1] or 0)+c*(rhs.data[j] or 0)+carry;
|
||||
carry = math.floor(prod / base);
|
||||
prod = prod % base;
|
||||
data[i+j-1] = (prod)%base;
|
||||
end
|
||||
if carry>0 then data[i+n2] = (data[i+n2] or 0)+ carry ;if res.size<i+n2 then res.size = i+n2 end end
|
||||
end
|
||||
if out then return res end
|
||||
end
|
||||
|
||||
--TO DO
|
||||
number.karatsuba_multiply = function(lhs,rhs,res)
|
||||
local n1 = lhs.size;local n2 = rhs.size;
|
||||
local n0 = math.max(n1,n2);
|
||||
if n0< 2 then -- normal multiply for "normal" sized numbers
|
||||
number.multiply(lhs, rhs, res)
|
||||
return
|
||||
end
|
||||
|
||||
n0 = math.floor(n0/2);
|
||||
local n = n1+n2;
|
||||
|
||||
local a1 = number:new({});
|
||||
local tdata = a1.data; local sdata = lhs.data;
|
||||
for i = 1,n0 do tdata[i] = sdata[i] or 0 end; a1.size = n0;
|
||||
local a2 = number:new({}); tdata = a2.data;
|
||||
for i = n0+1,n1 do tdata[i-n0] = sdata[i] or 0 end; a2.size = n1-n0;
|
||||
|
||||
local b1 = number:new({});
|
||||
local tdata = b1.data; sdata = rhs.data;
|
||||
for i = 1,n0 do tdata[i] = sdata[i] or 0 end; b1.size = n0;
|
||||
local b2 = number:new({}); tdata = b2.data;
|
||||
for i = n0+1,n1 do tdata[i-n0] = sdata[i] or 0 end; b2.size = n1-n0;
|
||||
|
||||
--say("a1 " .. a1:tostring())
|
||||
--say("a2 " .. a2:tostring())
|
||||
|
||||
--say("b1 " .. b1:tostring())
|
||||
--say("b2 " .. b2:tostring())
|
||||
|
||||
|
||||
local A = number:new({}); number.karatsuba_multiply(a1,b1,A);
|
||||
local B = number:new({}); number.karatsuba_multiply(a2,b2,B);
|
||||
local C = number:new({}); number.karatsuba_multiply(a1+a2,b1+b2,C);
|
||||
--== C-A-B
|
||||
--TODO minus, reassemble together..
|
||||
|
||||
end
|
||||
|
||||
karatsuba_multiply_test = function()
|
||||
--local in2 = number:new({2,1,1})
|
||||
--local in1 = number:new({2,1,1})
|
||||
local res = number:new({});
|
||||
local in1 = number:new({3,1,4}); --413
|
||||
local in2 = number:new({7,2,5}); -- 527
|
||||
number.karatsuba_multiply(in1,in2,res)
|
||||
end
|
||||
|
||||
karatsuba_multiply_test()
|
||||
|
||||
|
||||
multiply_test = function()
|
||||
--local in2 = number:new({2,1,1})
|
||||
--local in1 = number:new({2,1,1})
|
||||
local res = number:new({});
|
||||
local in1 = number:new({4})
|
||||
number.multiply(in1,in1,res)
|
||||
say("mult check 1 " .. res:tostring())
|
||||
--say("mult check 2 " .. number.multiply(in1,in2):tostring())
|
||||
|
||||
end
|
||||
--multiply_test()
|
||||
|
||||
number.__mul = number.multiply;
|
||||
|
||||
number.power = function(n,power_) -- calculate high powers efficiently - number of steps is log_2(power)
|
||||
local power = power_;
|
||||
local input = number:new(n.data);
|
||||
local out = number:new({});
|
||||
|
||||
local count = 0;
|
||||
|
||||
local r; local powerplan = {}; -- 0: just square a->a^2, 1 = square and multiply a-> a*a^2
|
||||
while (power>0) do
|
||||
r=power%2; powerplan[#powerplan+1] = r; power = (power-r)/2
|
||||
end
|
||||
|
||||
for i = #powerplan-1,1,-1 do
|
||||
|
||||
number.multiply(input,input,out);
|
||||
|
||||
if powerplan[i] == 1 then
|
||||
input,out = out, input;
|
||||
number.multiply(input,n,out); count = count + 2
|
||||
else count = count + 1;
|
||||
end
|
||||
|
||||
input,out = out, input;
|
||||
end
|
||||
|
||||
return input
|
||||
end
|
||||
|
||||
split = function(s,k)
|
||||
local ret = "";
|
||||
local j=1,length; length = string.len(s)/k
|
||||
for i = 1, length do
|
||||
j = (i-1)*k+1;
|
||||
ret = ret .. string.sub(s,j,j+k-1) .. "\n"
|
||||
end
|
||||
--say("j " .. j)
|
||||
if j>1 then j = j+k end
|
||||
ret = ret .. string.sub(s,j)
|
||||
return ret
|
||||
end
|
||||
|
||||
self.spam(1)
|
||||
|
||||
-- little endian ! lower bits first ..
|
||||
|
||||
--n = number:new({7,1,0,2}); local power = 2017;
|
||||
--self.label(split(n:tostring().."^"..power .. " = " .. number.power(n,power):tostring(),100))
|
||||
--2017^2017 = 3906...
|
||||
end
|
|
@ -0,0 +1,22 @@
|
|||
if not text then
|
||||
text = "diamond 3;mese 4;gold 2;diamond 1;"
|
||||
function parse(text)
|
||||
ret = {};
|
||||
for a,b in text:gmatch("(%w+) (%w+)%;") do
|
||||
ret[a] = (ret[a] or 0) + (tonumber(b) or 0)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function export(array)
|
||||
ret = "";
|
||||
for k,v in pairs(array) do
|
||||
ret = ret .. (_G.tostring(k) or "") .. " " .. (_G.tostring(v) or "") ..";"
|
||||
end
|
||||
return ret
|
||||
end
|
||||
say("input: " .. text)
|
||||
local arr = parse(text);
|
||||
say("parsed text: " .. string.gsub(_G.dump(arr),"\n",""))
|
||||
say("back to string :" .. export(arr))
|
||||
end
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 3.8 KiB |
Loading…
Reference in New Issue