-sound for robots

-check operations code
-energy rewrite
master
rnd1 2017-07-01 23:00:16 +02:00
parent c3b8f19c83
commit 08f61c0865
17 changed files with 451 additions and 73 deletions

View File

@ -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,
}

View File

@ -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

54
misc_commands.lua Normal file
View File

@ -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})

View File

@ -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

184
scripts/multiplication.lua Normal file
View File

@ -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

22
scripts/simple_parser.lua Normal file
View File

@ -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

BIN
sounds/Dtmf0.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf1.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf2.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf3.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf4.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf5.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf6.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf7.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf8.ogg Normal file

Binary file not shown.

BIN
sounds/Dtmf9.ogg Normal file

Binary file not shown.

BIN
textures/chars.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB