-forward_down fixes

-added scripts
master
rnd1 2017-04-05 11:24:54 +02:00
parent 5d8617de1a
commit 182d81acec
13 changed files with 1369 additions and 6 deletions

View File

@ -79,7 +79,7 @@ function getSandboxEnv (name)
backward = function(item, inventory) return commands.insert_item(name,item, inventory,4) end,
down = function(item, inventory) return commands.insert_item(name,item, inventory,6) end,
up = function(item, inventory) return commands.insert_item(name,item, inventory,5) end,
forward_down = function() return commands.insert_item(name,item, inventory,7) end,
forward_down = function(item, inventory) return commands.insert_item(name,item, inventory,7) end,
},
take = { -- takes item from inventory and puts it in robot inventory
@ -99,7 +99,7 @@ function getSandboxEnv (name)
backward = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,4) end,
down = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,6) end,
up = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,5) end,
forward_down = function(item, inventory) return commands.check_inventory(name,itemname, inventory,i,7) end,
forward_down = function(item, inventory,i) return commands.check_inventory(name,itemname, inventory,i,7) end,
self = function(itemname, inventory,i) return commands.check_inventory(name,itemname, inventory,i,0) end,
},
@ -425,10 +425,8 @@ function getSandboxEnv (name)
},
colorize = core.colorize,
tonumber = tonumber,
pairs = pairs,
ipairs = ipairs,
error = error,
tonumber = tonumber, pairs = pairs,
ipairs = ipairs, error = error, type=type,
--_ccounter = basic_robot.data[name].ccounter, -- counts how many executions of critical spots in script

175
scripts/avl_tree~.lua Normal file
View File

@ -0,0 +1,175 @@
-- 1. MEMORY MANAGEMENT using array with addresses
-- note: this is all done "automatic" in c with malloc
mem = {};
mem.size = 10; -- how many available addresses in memory for each of internally used arrays
mem.freestk = {}; -- stack of free addresses in memory
mem.stkidx = mem.size;
for i = 1,mem.size do mem.freestk[i]=mem.size-i+1 end -- so: freestk = {memsize, memsize-1,...., 2, 1 } and head is at last one
mem.allocate = function() -- pop free spot from stack
if mem.stkidx>0 then
mem.stkidx = mem.stkidx -1
return mem.freestk[mem.stkidx+1]
end
end
mem.free = function(addr) -- release spot and mark it as free
if mem.stkidx>=mem.size then -- cant release anymore, all is free
return
end
mem.stkidx = mem.stkidx +1;
mem.freestk[mem.stkidx ] = addr;
end
-- 2. BALANCED BINARY SEARCH TREES USING POINTERS created with above MEMORY MANAGEMENT
idx = mem.allocate();
tree = {};
tree.data = { root = 0, count = 0, -- current root, element count
left = {0}, parent = {0}, right = {0}, -- links
key = {0}, -- value
heightl = {0}, heightr = {0} -- needed for balancing
};
-- root: idx of root element, count: how many elements in tree
-- 6 arrays with data for node stored at address i in memory:
-- left[i] == left child, right[i] = right child, parent[i] = parent, key[i] = stored value, if value left[i]== 0 then no left child...
-- heightl[i] = height of left subtree, heightr[i] = height of right subtree
-- NOTE: initially a root node is added
tree.insert = function (value)
local data = tree.data;
local idx = data.root;
if data.count == 0 then data.key[idx] = key; data.count = 1 return true end -- just set root key and exit
local key;
local cidx; -- child idx
while (true) do -- insert into tree by walking deeper and doing comparisons
key = data.key[idx];
if value<key then
cidx = data.left[idx];
else
cidx = data.right[idx];
end
if cidx == 0 then -- we hit nonexistent child, lets insert here
cidx = mem.allocate();
if not cidx then return "out of space" end
data.count = data.count+1
data.key[cidx] = value;
data.parent[cidx]=idx;data.left[cidx]=0;data.right[cidx]=0;
data.heightl[cidx]=0;data.heightr[cidx]=0;
-- update all heights for parents and find possible violation of balance property
local vidx = 0; -- index where violation happens
local vdir = 0; -- type of violation: 1: in left tree , 2: in right tree
while (idx~=0) do
if data.left[idx] == cidx then
data.heightl[idx]=data.heightl[idx]+1
else
data.heightr[idx]=data.heightr[idx]+1;
end
if data.heightl[idx]>data.heightr[idx]+1 then
vidx = idx; vdir = 1
elseif data.heightr[idx]>data.heightl[idx]+1 then
vidx = idx; vdir = 2
end
cidx = idx; -- set new child
idx = data.parent[idx]; -- set new parent
end
if vidx~=0 then
say("violation vidx " .. vidx .. " direction " .. vdir)
-- TO DO: apply internal tree rotation to restore balance
if vdir == 1 then -- left violation
--[[ need to reconnect 3 nodes:
D <- vidx C
/ \ / \
C E => A D
/ \ / \
A B B E
CHANGES:
C: new parent is old parent of D, new children are A,D
B: new parent D,
D: new parent is C, new children are B,E
--]]
local Didx = vidx; local Dpar = data.parent[Didx];
local Cidx = data.left[Didx];
local Bidx = data.right[Cidx];
local Aidx = data.left[Cidx];
data.parent[Cidx] = Dpar;data.left[Cidx] = Aidx;data.right[Cidx] = Didx;
data.parent[Bidx] = Didx;
data.parent[Didx] = Cidx;data.left[Didx] = Bidx;
else -- right violation
--[[ need to reconnect 3 nodes:
B <-vidx C
/ \ / \
A C => B E
/ \ / \
D E A D
CHANGES:
B: new parent C, new children A,D
C: new parent is old parent of B, new children are B,E
D: new parent is B
--]]
local Bidx = vidx; local Bpar = data.parent[Bidx];
local Cidx = data.right[Bidx];
local Didx = data.left[Cidx];
data.parent[Bidx] = Cidx;data.right[Bidx] = data.left[Cidx]
data.parent[Cidx] = Bpar;data.left[Cidx] = Bidx;
data.parent[Didx] = Bidx;
end
end
else
-- we go deeper
idx = cidx;
end
end
tree.find = function(value)
local idx = data.root;
while (idx~=0) do
key = data.key[idx];
if key == value then return idx end
if value<key then
idx = data.left[idx];
else
idx = data.right[idx];
end
end
end
tree.next = function(idx)
local right = data.right[idx];
local nidx = 0;
if right~=0 then
--TO DO: smallest idx in right subtree
else
if data.parent[idx]==0 then
return 0
end
end
end
tree.remove = function(idx)
--TO DO :
-- 1.find next element
-- put it where idx was and move subtree..
end
end

View File

@ -0,0 +1,150 @@
if not data then
m=10;n=10;
players = {};
paused = true
turn = 2;
t = 0;
SIGNUP = 0; GAME = 1; INTERMISSION = 2
state = SIGNUP
t0 = _G.minetest.get_gametime();spawnpos = self.spawnpos() -- place mines
data = {};
init_game = function()
data = {}; minescount = 32
for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
if not data[1] then data[1] = {} end if not data[2] then data[2] = {} end -- create 2x2 safe area
data[1][1] = 0;data[1][2] = 0;data[2][1] = 0;data[2][2] = 0;
minescount = 0;
for i = 1,m do for j = 1,n do -- render game
if data[i] and data[i][j] == 1 then minescount = minescount + 1 end
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:button808080" then
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},2)
end
end end
keyboard.set({x=spawnpos.x+1,y=spawnpos.y,z=spawnpos.z+1},4) -- safe start spot
end
get_mine_count = function(i,j)
if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
for k = -1,1 do for l = -1,1 do
if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
end end
return count
end
chk_mines = function()
local count = minescount;
for i=1,m do for j=1,n do
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})=="basic_robot:buttonFF8080" and data[i] and data[i][j]==1 then
count=count-1
end
end end
return count
end
greeting = function()
_G.minetest.chat_send_all(colorize("red","#BATTLE MINESWEEPER : two player battle in minesweeper. say join to play.\nRules: 1. each player has 5 second turn to make a move 2. if you dont make move you lose\n3. if you make move in other player turn you lose. 4. if you hit bomb or mark bomb falsely you lose"))
end
player_lost = function ()
for i=1,#players do
local player = _G.minetest.get_player_by_name(players[i]);
if player then player:setpos({x=spawnpos.x,y=spawnpos.y+10,z=spawnpos.z}) end
end
state = INTERMISSION; t = 0
end
function change_turn()
if turn == 1 then
_G.minetest.sound_play("default_break_glass",{pos=spawnpos, max_hear_distance = 100})
else
_G.minetest.sound_play("note_a",{pos=spawnpos, max_hear_distance = 100})
end
if paused == false then
say(players[turn] .. " lost : didn't make a move");
player_lost()
else
if turn == 1 then turn = 2 else turn = 1 end
self.label("turn " .. turn .. " " .. players[turn])
t=0
paused = false
end
end
init_game()
greeting()
self.listen(1)
end
if state == SIGNUP then
speaker,msg = self.listen_msg()
if speaker then
if msg == "join" then
players[#players+1] = speaker;
local plist = ""; for i=1,#players do plist = plist .. players[i] .. ", " end
_G.minetest.chat_send_all("BATTLE MINESWEEPER, current players : " .. plist)
if #players >= 2 then
state = GAME
change_turn();
keyboard.get(); t=0;
for i = 1, #players do
local player = _G.minetest.get_player_by_name(players[i]);
if player then player:setpos({x=spawnpos.x,y=spawnpos.y+1,z=spawnpos.z}) end
end
_G.minetest.chat_send_all(colorize("red","BATTLE MINESWEEPER " .. m .. "x" ..n .. " with " .. minescount .. " mines.\n" .. players[turn] .. " its your move!"))
end
end
end
elseif state == GAME then
t = t + 1;
if t>5 then -- change of turn
change_turn()
end
event = keyboard.get();
if event and event.type == 2 and not paused then
if event.puncher == players[turn] then
local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
if x<1 or x>m or z<1 or z>n then
else
local ppos = player.getpos(event.puncher)
if ppos and math.abs(ppos.x-event.x)<0.5 and math.abs(ppos.z-event.z)<0.5 then -- just mark mine
if data[x] and data[x][z] == 1 then
if keyboard.read({x=event.x,y=event.y,z=event.z})~="basic_robot:button808080" then
keyboard.set({x=event.x,y=event.y,z=event.z},2)
else
keyboard.set({x=event.x,y=event.y,z=event.z},3)
end
else
say(event.puncher .. " lost : marked a bomb where it was none! ");
player_lost()
end
else
if data[x] and data[x][z]==1 then
_G.minetest.sound_play("tnt_boom",{pos=spawnpos, max_hear_distance = 100})
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},3)
say(event.puncher .. " lost : punched a bomb! ");
player_lost()
else
local count = get_mine_count(x,z);
if count == 0 then keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4)
else keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},7+count) end
end
end
end
paused = true
else
say(event.puncher .. " lost : played out of his/her turn"); player_lost()
end
end
elseif state == INTERMISSION then
t=t+1; if t> 15 then state = SIGNUP;players = {}; paused = true; init_game(); greeting() end
end

195
scripts/blackbox.lua Normal file
View File

@ -0,0 +1,195 @@
--black box by rnd, 03/18/2017
--https://en.wikipedia.org/wiki/Black_Box_(game)
if not data then
m=8;n=8;turn = 0;
attempts = 1;
self.spam(1);t0 = _G.minetest.get_gametime();
spawnpos = self.spawnpos()
data = {};
for i = 1,m do data[i]={}; for j = 1,n do data[i][j]=0 end end
for i=1,4 do -- put in 4 atoms randomly
data[math.random(m)][math.random(n)] = 1
end
render_board = function(mode) -- mode 0 : render without solution, 1: render solution
for i = 1,m do for j = 1,n do -- render game
if mode == 0 or data[i][j] == 0 then
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:button808080" then
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},2)
end
else
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},3)
end
end end
end
get_dirl = function(dir)
local dirl; -- direction left
if dir[1] > 0.5 then dirl = {0,-1}
elseif dir[1] < -0.5 then dirl = {0,1}
elseif dir[2] > 0.5 then dirl = {-1,0}
elseif dir[2] < -0.5 then dirl = {1,0}
end
return dirl
end
read_pos = function(x,z)
if x<1 or x>m or z<1 or z>n then return nil end
return data[x][z]
end
newdir = function(x,z,dir) -- where will ray go next
local retdir = {dir[1],dir[2]};
local xf = x+dir[1]; local zf = z+dir[2] -- forward
local dirl = get_dirl(dir)
local nodef = read_pos(xf,zf)
local nodel = read_pos(xf + dirl[1],zf + dirl[2])
local noder = read_pos(xf - dirl[1],zf - dirl[2])
if nodef == 1 then
retdir = {0,0} -- ray hit something
elseif nodel == 1 and noder ~= 1 then
retdir = {-dirl[1],-dirl[2]}
elseif nodel ~= 1 and noder == 1 then
retdir = {dirl[1],dirl[2]}
elseif nodel == 1 and noder == 1 then
retdir = {-dir[1],-dir[2]}
end
return retdir
end
shootray = function(x,z,dir)
--say("ray starts " .. x .. " " .. z .. " dir " .. dir[1] .. " " .. dir[2])
local xp = x; local zp = z;
local dirp = {dir[1],dir[2]};
local maxstep = m*n;
for i = 1,maxstep do
dirp = newdir(xp,zp,dirp);
if dirp[1]==0 and dirp[2]==0 then return -i end -- hit
xp=xp+dirp[1];zp=zp+dirp[2];
if xp<1 or xp>m or zp<1 or zp>n then return i,{xp,zp} end -- out
end
return 0 -- hit
end
count = 0; -- how many letters were used up
border_start_ray = function(x,z)
local rdir
if x==0 then rdir = {1,0}
elseif x == m+1 then rdir = {-1,0}
elseif z == 0 then rdir = {0,1}
elseif z == n+1 then rdir = {0,-1}
end
if rdir then
local result,out = shootray(x,z,rdir);
if result >= 0 then
if out then
if out[1]==x and out[2]==z then -- got back where it originated, reflection
keyboard.set({x=spawnpos.x+out[1],y=spawnpos.y,z=spawnpos.z+out[2]},1);
else
if result<=1 then
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},6); -- immediate bounce off
else
local nodename = "default:obsidian_letter_"..string.char(97+count) .. "u";
_G.minetest.set_node(
{x=spawnpos.x+out[1],y=spawnpos.y+1,z=spawnpos.z+out[2]},
{name = nodename, param2 = 1})
_G.minetest.set_node(
{x=spawnpos.x+x,y=spawnpos.y+1,z=spawnpos.z+z},
{name = nodename, param2 = 1})
count = count + 1;
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4);
keyboard.set({x=spawnpos.x+out[1],y=spawnpos.y,z=spawnpos.z+out[2]},4);
end
end
end
elseif result<0 then
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},3); -- hit
end
end
end
-- initial border loop and marking
--render blue border
for i = 1,m do keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+0},5) keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+n+1},5) end
for j = 1,n do keyboard.set({x=spawnpos.x+0,y=spawnpos.y,z=spawnpos.z+j},5) keyboard.set({x=spawnpos.x+m+1,y=spawnpos.y,z=spawnpos.z+j},5) end
for i = 1,m do keyboard.set({x=spawnpos.x+i,y=spawnpos.y+1,z=spawnpos.z+0},0) keyboard.set({x=spawnpos.x+i,y=spawnpos.y+1,z=spawnpos.z+n+1},0) end
for j = 1,n do keyboard.set({x=spawnpos.x+0,y=spawnpos.y+1,z=spawnpos.z+j},0) keyboard.set({x=spawnpos.x+m+1,y=spawnpos.y+1,z=spawnpos.z+j},0) end
z=0 -- bottom
for x = 1,m do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
x=m+1 -- right
for z = 1,n do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
z=n+1 -- top
for x = m,1,-1 do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
x=0 -- left
for z = n,1,-1 do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
check_solution = function()
for i = 1,m do
for j = 1,n do
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}) == "basic_robot:buttonFF8080" then -- red
if data[i][j]~=1 then return false end
else
if data[i][j]~=0 then return false end
end
end
end
return true
end
--render board
render_board(0)
keyboard.set({x=spawnpos.x,y=spawnpos.y,z=spawnpos.z-1},5)
end
event = keyboard.get();
if event then
local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
if x<1 or x>m or z<1 or z>n then
if event.type == 5 then
if check_solution() then
say("#BLACKBOX : CONGRATULATIONS! " .. event.puncher .. " found all atoms after " .. attempts .. " tries."); self.remove()
else
say("#BLACKBOX : " .. event.puncher .. " failed to detect atoms after " .. attempts .. " attempts.")
attempts = attempts+1
end
end
else -- interior punch
nodetype = 2;
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button808080" then
nodetype = 3
end
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},nodetype);
end
end
::END::

195
scripts/blackbox_game.lua Normal file
View File

@ -0,0 +1,195 @@
--black box by rnd, 03/18/2017
--https://en.wikipedia.org/wiki/Black_Box_(game)
if not data then
m=8;n=8;turn = 0;
attempts = 1;
self.spam(1);t0 = _G.minetest.get_gametime();
spawnpos = self.spawnpos()
data = {};
for i = 1,m do data[i]={}; for j = 1,n do data[i][j]=0 end end
for i=1,4 do -- put in 4 atoms randomly
data[math.random(m)][math.random(n)] = 1
end
render_board = function(mode) -- mode 0 : render without solution, 1: render solution
for i = 1,m do for j = 1,n do -- render game
if mode == 0 or data[i][j] == 0 then
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:button808080" then
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},2)
end
else
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},3)
end
end end
end
get_dirl = function(dir)
local dirl; -- direction left
if dir[1] > 0.5 then dirl = {0,-1}
elseif dir[1] < -0.5 then dirl = {0,1}
elseif dir[2] > 0.5 then dirl = {-1,0}
elseif dir[2] < -0.5 then dirl = {1,0}
end
return dirl
end
read_pos = function(x,z)
if x<1 or x>m or z<1 or z>n then return nil end
return data[x][z]
end
newdir = function(x,z,dir) -- where will ray go next
local retdir = {dir[1],dir[2]};
local xf = x+dir[1]; local zf = z+dir[2] -- forward
local dirl = get_dirl(dir)
local nodef = read_pos(xf,zf)
local nodel = read_pos(xf + dirl[1],zf + dirl[2])
local noder = read_pos(xf - dirl[1],zf - dirl[2])
if nodef == 1 then
retdir = {0,0} -- ray hit something
elseif nodel == 1 and noder ~= 1 then
retdir = {-dirl[1],-dirl[2]}
elseif nodel ~= 1 and noder == 1 then
retdir = {dirl[1],dirl[2]}
elseif nodel == 1 and noder == 1 then
retdir = {-dir[1],-dir[2]}
end
return retdir
end
shootray = function(x,z,dir)
--say("ray starts " .. x .. " " .. z .. " dir " .. dir[1] .. " " .. dir[2])
local xp = x; local zp = z;
local dirp = {dir[1],dir[2]};
local maxstep = m*n;
for i = 1,maxstep do
dirp = newdir(xp,zp,dirp);
if dirp[1]==0 and dirp[2]==0 then return -i end -- hit
xp=xp+dirp[1];zp=zp+dirp[2];
if xp<1 or xp>m or zp<1 or zp>n then return i,{xp,zp} end -- out
end
return 0 -- hit
end
count = 0; -- how many letters were used up
border_start_ray = function(x,z)
local rdir
if x==0 then rdir = {1,0}
elseif x == m+1 then rdir = {-1,0}
elseif z == 0 then rdir = {0,1}
elseif z == n+1 then rdir = {0,-1}
end
if rdir then
local result,out = shootray(x,z,rdir);
if result >= 0 then
if out then
if out[1]==x and out[2]==z then -- got back where it originated, reflection
keyboard.set({x=spawnpos.x+out[1],y=spawnpos.y,z=spawnpos.z+out[2]},1);
else
if result<=1 then
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},6); -- immediate bounce off
else
local nodename = "default:obsidian_letter_"..string.char(97+count) .. "u";
_G.minetest.set_node(
{x=spawnpos.x+out[1],y=spawnpos.y+1,z=spawnpos.z+out[2]},
{name = nodename, param2 = 1})
_G.minetest.set_node(
{x=spawnpos.x+x,y=spawnpos.y+1,z=spawnpos.z+z},
{name = nodename, param2 = 1})
count = count + 1;
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4);
keyboard.set({x=spawnpos.x+out[1],y=spawnpos.y,z=spawnpos.z+out[2]},4);
end
end
end
elseif result<0 then
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},3); -- hit
end
end
end
-- initial border loop and marking
--render blue border
for i = 1,m do keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+0},5) keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+n+1},5) end
for j = 1,n do keyboard.set({x=spawnpos.x+0,y=spawnpos.y,z=spawnpos.z+j},5) keyboard.set({x=spawnpos.x+m+1,y=spawnpos.y,z=spawnpos.z+j},5) end
for i = 1,m do keyboard.set({x=spawnpos.x+i,y=spawnpos.y+1,z=spawnpos.z+0},0) keyboard.set({x=spawnpos.x+i,y=spawnpos.y+1,z=spawnpos.z+n+1},0) end
for j = 1,n do keyboard.set({x=spawnpos.x+0,y=spawnpos.y+1,z=spawnpos.z+j},0) keyboard.set({x=spawnpos.x+m+1,y=spawnpos.y+1,z=spawnpos.z+j},0) end
z=0 -- bottom
for x = 1,m do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
x=m+1 -- right
for z = 1,n do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
z=n+1 -- top
for x = m,1,-1 do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
x=0 -- left
for z = n,1,-1 do
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button8080FF" then
border_start_ray(x,z)
end
end
check_solution = function()
for i = 1,m do
for j = 1,n do
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}) == "basic_robot:buttonFF8080" then -- red
if data[i][j]~=1 then return false end
else
if data[i][j]~=0 then return false end
end
end
end
return true
end
--render board
render_board(0)
keyboard.set({x=spawnpos.x,y=spawnpos.y,z=spawnpos.z-1},5)
end
event = keyboard.get();
if event then
local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
if x<1 or x>m or z<1 or z>n then
if event.type == 5 then
if check_solution() then
say("#BLACKBOX : CONGRATULATIONS! " .. event.puncher .. " found all atoms after " .. attempts .. " tries."); self.remove()
else
say("#BLACKBOX : " .. event.puncher .. " failed to detect atoms after " .. attempts .. " attempts.")
attempts = attempts+1
end
end
else -- interior punch
nodetype = 2;
if keyboard.read({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z}) == "basic_robot:button808080" then
nodetype = 3
end
keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},nodetype);
end
end
::END::

View File

@ -0,0 +1,108 @@
if not get_hash then
get_hash = function(s,p)
if not s then return end
local h = 0; local n = string.len(s);local m = 4; -- put 4 characters together
local r = 0;local i = 0;
while i<n do
i=i+1;r = 256*r+ string.byte(s,i);
if i%m == 0 then h=h+(r%p) r=0 end
end
if i%m~=0 then h=h+(r%p) end
return h%p
end
hashdb = {}; --array with entries: [hash] = list of possible hits
insert = function(key,value)
local hash = get_hash(key,10011);
local data = hashdb[hash]; if data == nil then hashdb[hash] = {}; data = hashdb[hash] end
data[#data+1]={key,value};
return hash
end
lookup = function(key)
local hash = get_hash(key,10011);
if not hash then return end
local data = hashdb[hash];
if not data then return nil end
for i = 1,#data do
if data[i][1]==key then return data[i][2] end
end
return nil
end
analyse = function()
local count = 0; local maxlen = 0; local maxidx = 1; local n = #hashdb;
for i = 1, 10000 do
local data = hashdb[i];
if data then
local length = #data;
if length > maxlen then maxlen = length; maxidx = i end
count = count + 1
end
end
if maxlen>0 then
local data = hashdb[maxidx];
say("number of used hash entries is " .. count .. ", average " .. (step/count) .. " entries per hash, "..
" max length of list is " .. maxlen .. " at hash ".. maxidx )--.. " : " ..
--string.gsub(_G.dump(data),"\n","") )
end
end
-- LOAD DICTIONARY WORDS into hashtable
lang = "german"
fname = "F:\\games\\rpg\\minetest-0415server\\mods\\basic_translate\\"..lang;
local f = _G.assert(_G.io.open(fname, "r"));local dicts = f:read("*all");f:close()
step = 0; maxwords = 10000;
i=0
dict = {}; -- for comparison
while(step<maxwords) do
step=step+1
i1 = string.find(dicts,"\t",i+1)
i2 = string.find(dicts,"\n",i+1)
if not i2 then break end
local word = string.sub(dicts, i+1,i1-1);
local tword = string.sub(dicts, i1+1,i2-1);
insert(word, tword) -- load into hashtable
dict[word]=tword
i=i2
end
self.listen(1)
self.spam(1)
say(step .. " words loaded")
end
-- handle chat event
speaker,msg = self.listen_msg()
if msg then
if msg == "?*" then
local n = 1000000; local msg = "hello"
local ret = "";
local t1 = os.clock();
for i = 1, n do ret = lookup(msg) end; t1 = os.clock()-t1;
local t2 = os.clock();
for i = 1, n do ret = dict[msg] end
t2 = os.clock()-t2;
say(t1 .. " " .. t2)
elseif msg == "??" then
analyse()
elseif string.sub(msg,1,1)=="?" then
msg = string.sub(msg,2);
local ret = lookup(msg);
if ret then say("found entry for " .. msg .. " : " .. ret) else say("entry not found") end
end
end

38
scripts/messenger.lua Normal file
View File

@ -0,0 +1,38 @@
if not s then
s=0
msgsize = 2500;
_,text = book.read(1);text = text or "";
write_msg = function(sender,msg)
local newsize = string.len(text)+string.len(msg);
if newsize>msgsize then return "messages space exceeded" end
text = text .. "\n"..os.date() .. " " .. sender .. ": " .. msg;
book.write(1,"messages",text)
end
end
--textarea[X,Y;W,H;name;label;default]
--button[X,Y;W,H;name;label]
if s == 0 then
players = find_player(4);
if players and players[1] then
s=1
local form = "size[8,4.5]" ..
"textarea[0,0;9,4.5;msg;MESSAGE FOR ADMIN;]"..
"button_exit[-0.5,4.15;2,1;send;send]"
self.show_form(players[1],form)
end
elseif s==1 then
sender,fields = self.read_form();
if sender then
if fields.send then
msg = fields.msg;
if msg and msg~="" then
write_msg(sender,msg);activate.up(1)
_G.minetest.chat_send_player(sender,"#mailbot: message has been stored")
end
end
self.remove()
end
end

72
scripts/minesweeper.lua Normal file
View File

@ -0,0 +1,72 @@
if not data then
m=10;n=10; minescount = 32;
t0 = _G.minetest.get_gametime();
data = {}; spawnpos = self.spawnpos() -- place mines
for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
if not data[1] then data[1] = {} end if not data[2] then data[2] = {} end -- create 2x2 safe area
data[1][1] = 0;data[1][2] = 0;data[2][1] = 0;data[2][2] = 0;
minescount = 0;
for i = 1,m do for j = 1,n do -- render game
if data[i] and data[i][j] == 1 then minescount = minescount + 1 end
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:button808080" then
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},2)
end
end end
keyboard.set({x=spawnpos.x+1,y=spawnpos.y,z=spawnpos.z+1},4) -- safe start spot
get_mine_count = function(i,j)
if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
for k = -1,1 do for l = -1,1 do
if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
end end
return count
end
chk_mines = function()
local count = minescount;
for i=1,m do for j=1,n do
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})=="basic_robot:buttonFF8080" and data[i] and data[i][j]==1 then
count=count-1
end
end end
return count
end
say("minesweeper " .. m .. "x" ..n .. " with " .. minescount .. " mines ")
self.label("find all hidden mines! mark mine by standing on top of block and punch,\notherwise it will uncover the block (and possibly explode).")
end
event = keyboard.get();
if event then
local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
if x<1 or x>m or z<1 or z>n then
if x == 0 and z == 1 then
local count = chk_mines();
if count == 0 then
t0 = _G.minetest.get_gametime() - t0;
say("congratulations! " .. event.puncher .. " discovered all mines in " .. t0 .. " s")
_G.minetest.add_item({x=spawnpos.x,y=spawnpos.y+1,z=spawnpos.z},_G.itemstack("default:diamond 5")) -- diamond reward
else
say("FAIL! " .. count .. " mines remaining ")
end
self.remove()
end
elseif event.type == 2 then
local ppos = player.getpos(event.puncher)
if ppos and math.abs(ppos.x-event.x)<0.5 and math.abs(ppos.z-event.z)<0.5 then -- just mark mine
if keyboard.read({x=event.x,y=event.y,z=event.z})~="basic_robot:button808080" then
keyboard.set({x=event.x,y=event.y,z=event.z},2)
else
keyboard.set({x=event.x,y=event.y,z=event.z},3)
end
else
if data[x] and data[x][z]==1 then
say("boom! "..event.puncher .. " is dead ");keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},3);self.remove()
else
local count = get_mine_count(x,z);
if count == 0 then keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4)
else keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},7+count) end
end
end
end
end

View File

@ -0,0 +1,72 @@
if not data then
m=10;n=10; minescount = 32;
t0 = _G.minetest.get_gametime();
data = {}; spawnpos = self.spawnpos() -- place mines
for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
if not data[1] then data[1] = {} end if not data[2] then data[2] = {} end -- create 2x2 safe area
data[1][1] = 0;data[1][2] = 0;data[2][1] = 0;data[2][2] = 0;
minescount = 0;
for i = 1,m do for j = 1,n do -- render game
if data[i] and data[i][j] == 1 then minescount = minescount + 1 end
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})~="basic_robot:button808080" then
keyboard.set({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j},2)
end
end end
keyboard.set({x=spawnpos.x+1,y=spawnpos.y,z=spawnpos.z+1},4) -- safe start spot
get_mine_count = function(i,j)
if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
for k = -1,1 do for l = -1,1 do
if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
end end
return count
end
chk_mines = function()
local count = minescount;
for i=1,m do for j=1,n do
if keyboard.read({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j})=="basic_robot:buttonFF8080" and data[i] and data[i][j]==1 then
count=count-1
end
end end
return count
end
say("minesweeper " .. m .. "x" ..n .. " with " .. minescount .. " mines ")
self.label("find all hidden mines! mark mine by standing on top of block and punch,\notherwise it will uncover the block (and possibly explode).")
end
event = keyboard.get();
if event then
local x = event.x - spawnpos.x;local y = event.y - spawnpos.y;local z = event.z - spawnpos.z;
if x<1 or x>m or z<1 or z>n then
if x == 0 and z == 1 then
local count = chk_mines();
if count == 0 then
t0 = _G.minetest.get_gametime() - t0;
say("congratulations! " .. event.puncher .. " discovered all mines in " .. t0 .. " s")
_G.minetest.add_item({x=spawnpos.x,y=spawnpos.y+1,z=spawnpos.z},_G.itemstack("default:diamond 5")) -- diamond reward
else
say("FAIL! " .. count .. " mines remaining ")
end
self.remove()
end
elseif event.type == 2 then
local ppos = player.getpos(event.puncher)
if ppos and math.abs(ppos.x-event.x)<0.5 and math.abs(ppos.z-event.z)<0.5 then -- just mark mine
if keyboard.read({x=event.x,y=event.y,z=event.z})~="basic_robot:button808080" then
keyboard.set({x=event.x,y=event.y,z=event.z},2)
else
keyboard.set({x=event.x,y=event.y,z=event.z},3)
end
else
if data[x] and data[x][z]==1 then
say("boom! "..event.puncher .. " is dead ");keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},3);self.remove()
else
local count = get_mine_count(x,z);
if count == 0 then keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},4)
else keyboard.set({x=spawnpos.x+x,y=spawnpos.y,z=spawnpos.z+z},7+count) end
end
end
end
end

104
scripts/radix_sort.lua Normal file
View File

@ -0,0 +1,104 @@
if not integer_sort then
-- sorts input according to keys, changes ordering to permutation corresponding to new order
integer_sort = function(input, keys, ordering,temp_ordering, m) -- input, keys same length n, m = how many keys, O(2*n+m)
local n = #input;
local freq = {} -- frequencies of keys
local kpos = {} -- position of keys in sorted array
for i=1,n do -- count how many occurences - O(n)
local key = keys[ordering[i]]+1;
freq[key]=(freq[key] or 0)+1
temp_ordering[i]=ordering[i];
end
local curpos = 1;kpos[1]=1;
for i =1,m-1 do -- determine positions of keys in final sorted array - O(m)
curpos = curpos + (freq[i] or 0);
kpos[i+1]=curpos -- {2=3, 3 = 6,..., n-1 = 321}
end
-- actually place values here
for i = 1,n do -- O(n)
local key = keys[temp_ordering[i]]+1;
local pos = kpos[key];
ordering[pos] = temp_ordering[i];
kpos[key]=kpos[key]+1; -- move to next spot for that key place
end
end
permutate = function(input,ordering)
local output = {};
for i =1,#input do
output[i] = input[ordering[i]]
end
return output
end
get_digits = function(Num,d,base) -- number, how many digits, what base
local digits = {};
local num = Num;
local r;
for i = 1, d do
r = num % base;
digits[#digits+1] = r;
num = (num-r)/base
end
return digits
end
dumparr = function(array)
if _G.type(array) ~= "table" then return array end
local ret = "{";
for i =1,#array-1 do
ret = ret .. dumparr(array[i]) .. ","
end
ret = ret .. dumparr(array[#array])
return ret .. "}"
end
radix_sort = function(input,d,base) -- array of numbers; base is also number of keys = m, d = how many steps of sorting = number of digits for single number
out = out .."\nRADIX SORT\n\narray to be sorted " .. dumparr(input)
local n = #input;
local ordering = {}; local temp_ordering = {}; for i = 1, n do ordering[i]=i end
local keys = {};
local keylist = {};
for i = 1,n do
keylist[i] = get_digits(input[i],d,base)
end
out = out .."\nlist of keys - ".. d .. " digits of base " .. base .. " expansion of numbers : \n" ..
dumparr(keylist)
for step = 1, d do
for i =1,n do
keys[i] = keylist[i][step];
end
integer_sort(input, keys, ordering, temp_ordering, base)
out = out .."\n"..step .. ". pass integer_sort : " .. dumparr(permutate(input,ordering))
end
out = out .. "\nradix sort final result : " .. dumparr(permutate(input,ordering))
end
--input = {"a","b","c","d","e"}
--keys = {5,3,4,1,2}
--ordering = {}; temp_ordering = {}; for i = 1, #input do ordering[i]=i end
--m=5;
--integer_sort(input, keys, ordering, temp_ordering,m);
--say(string.gsub(_G.dump(ordering),"\n",""))
--say(string.gsub(_G.dump(permutate(input,ordering)),"\n",""))
out = ""; self.label("")
input = {23,42,15,8,87};
radix_sort(input,5,3) -- d, base
self.display_text(out,60,3)
end

90
scripts/serialization.lua Normal file
View File

@ -0,0 +1,90 @@
if not itemlist then
inv2string = function(name)
local inv = _G.minetest.get_player_by_name(name):get_inventory()
local list = ""
for i = 1,32 do
local item = inv:get_stack("main", i):to_string()
list = list .. item .. ","
end
return name .. "," .. list
end
string2inv = function(str)
local i = string.find(str,",");
local name = string.sub(str,1,i-1);
local step = 0
local invlist = {};
while i and step < 33 do
step = step +1
local i1 = string.find(str,",",i+1)
if not i1 then break end
invlist[#invlist+1]=string.sub(str,i+1,i1-1)
i=i1
end
return name, invlist
end
array2string = function(array)
if _G.type(array) ~= "table" then return array end
local ret = "{";
for i =1,#array-1 do
ret = ret .. array2string(array[i]) .. ","
end
ret = ret .. array2string(array[#array])
return ret .. "}"
end
string2array = function(str)
if not string.find(str,"{") then return str end
local lvl = 1; local n = string.len(str);
local i1,i2,count;
count = 0; --1 = {}, 2 = ,
local arr = {}; i1 = 2;
for i =2,n do
local c = string.sub(str,i,i);
if c == "{" then
lvl = lvl+1
elseif c == "}" then
lvl = lvl -1
elseif c == "," and lvl == 1 then
i2 = i;
count = count+1
arr[count] = string2array(string.sub(str,i1,i2-1)); i1 = i2+1
end
end
if i1< n then count = count+1 ; arr[count] = string2array(string.sub(str,i1,n-1)) end
return arr
end
local arr = {{1,{2,4}},{3,4},{0,{2}},-2};
--local arr = {1,2,3}
self.spam(1)
say("original array : ".. string.gsub(_G.dump(arr),"\n","") )
local str = array2string(arr);
say("array2string : " .. str)
local arr1 = string2array(str);
say("string2array: " .. string.gsub(_G.dump(arr1),"\n",""))
player = find_player(2);
itemlist = {};
if player then
local list = inv2string(player[1])
local name,invlist = string2inv(list)
list = "UNIT TEST inv2string\n"..list .. "\nUNIT TEST string2inv\n".. "name = " .. name .."\n".. string.gsub(_G.dump(invlist),"\n","")
form = "size[8,8.5]" ..
"textarea[0,0;7.75,7.5;list;list;" .. list .. "]";
self.show_form(player[1],form)
end
end
sender,fields = self.read_form();
if sender then
if fields.list then
if string.sub(fields.list,1,3) == "DCL" then
local sel = tonumber(string.sub(fields.list,5)) or 1
say("you selected item " .. itemlist[sel])
end
end
if fields.quit then self.remove() end
end

142
scripts/shop.lua Normal file
View File

@ -0,0 +1,142 @@
if not s then
s=0;item = 1; price =""; buyer = ""
_G.minetest.forceload_block(self.pos(),true)
_G.basic_robot.data[self.name()].obj:set_properties({nametag = ""})
self.listen(1);self.spam(1)
shoplist = {};
--scan shops:
pos = self.pos(); pos.y=pos.y-5; pos.x=pos.x-6
pos1 = {x=pos.x-8,y=pos.y-2,z=pos.z-8};pos2 = {x=pos.x+8,y=pos.y+2,z=pos.z+8};
local shoppos = _G.minetest.find_nodes_in_area(pos1, pos2, "shop:shop");
--say("scanning... i found " .. #shoppos .. " shops ");
count = 0
for _,p in pairs(shoppos) do
local inv = _G.minetest.get_meta(p):get_inventory()
local s = inv:get_list("sell");local b = inv:get_list("buy")
local k = s[1]:to_string();
local v = b[1]:to_string();
if (k and k~="") and (v and v~="") then count = count +1 shoplist[count] = {k,v} end
end
local f_sort = function(a,b) return a[1]<b[1] end;
table.sort(shoplist,f_sort)
itemlist = ""; count = 0;
shopinventory = {};
for k,v in pairs(shoplist) do
if v[1] then
count = count +1
itemlist = itemlist .. string.format("%-5s%-40s%-32s",k,v[1],v[2]) .. ","
end
end
t = 0; ct = 0; ci = 0
say("scanning shops ... completed. Added " .. count .. " items for sale ");
end
ct=ct+1
if ct%5 == 0 then
ct=0
ctext = "say #shop to buy";
if ci>0 and ci<=count then
if shoplist[ci] then
iname = shoplist[ci][1];local p=string.find(iname,":"); if p then iname = string.sub(iname,p+1) end
sname = shoplist[ci][2];p=string.find(sname,":"); if p then sname = string.sub(sname,p+1) end
ctext = "#SHOP ".. ci .."\n" ..iname .. "\nPRICE\n" .. sname
end
ci=ci+1
elseif ci == count+1 then ci=0
elseif ci == 0 then ci=1
end
text = "SHOP ROBOT"..os.date("%x") .." " .. os.date("%H:%M:%S").. "\n\n"..ctext
self.display_text(text,10,3);
end
speaker,msg = self.listen_msg()
if msg then
if s == 0 then
if string.sub(msg,1,5)=="#shop" then
if msg == "#shop" then
--say("say #shop command, where command is list OR armor OR item number. Example: #shop list or #shop 1")
local list = "1,2,3";
local form = "size[8,8.5]" ..
"label[0.,0.5;ID]"..
"label[0.4,0.5;BUY]"..
"label[3.,0.5;SELL]" ..
"field[7.2,0.25;1.,1;count;count;".. 1 .."]"..
"button[5.,-0.05;2.,1;ARMOR;ARMOR]"..
"textlist[0,1;7.75,7.5;list;" .. itemlist .. "]";
self.show_form(speaker,form)
end
end
elseif s == 1 then
if string.sub(msg,1,3)~="buy" then
t=t+1; if t>1 then say("timeout. trade cancelled."); s = 0 end
else
s=0
end
end
end
sender,fields = self.read_form()
if sender then
local sel = fields.list; --"CHG:3"
--say( string.gsub(_G.dump(fields),"\n",""))
if sel and string.sub(sel,1,3) == "DCL" then
local quantity = tonumber(fields.count) or 1;
local select = tonumber(string.sub(sel,5) or "") or 1;
local item, price
if shoplist[select] then
item,price = shoplist[select][1],shoplist[select][2];
end
local player = _G.minetest.get_player_by_name(sender);
if player and item and price then
local inv = player:get_inventory();
if quantity > 99 then quantity = 99 end
if quantity > 1 then
local k = 1;
local i = string.find(price," ");
if i then
k = tonumber(string.sub(price,i+1)) or 1
price = string.sub(price,1,i-1).. " " .. k*quantity
else
price = price.. " " .. quantity
end
k=1;i = string.find(item," ");
if i then
k = tonumber(string.sub(item,i+1)) or 1
item = string.sub(item,1,i-1).. " " .. k*quantity
else
item = item .. " " .. quantity
end
end
if inv:contains_item("main", price ) then
inv:remove_item("main",price)
inv:add_item("main",item)
_G.minetest.chat_send_player(sender,"#SHOP ROBOT: " .. item .. " sold to " .. sender .. " for " .. price)
else
_G.minetest.chat_send_player(sender,"#SHOP ROBOT: you dont have " .. price .. " in inventory ")
end
end
elseif fields.ARMOR then
local player = _G.minetest.get_player_by_name(sender);
if player then
local inv = player:get_inventory();
if inv:contains_item("main",_G.ItemStack("default:diamond 30")) then
player:set_armor_groups({fleshy = 50})
_G.minetest.chat_send_player(sender,"#SHOP ROBOT: you bought 50% damage reduction.")
else
_G.minetest.chat_send_player(sender,"#SHOP ROBOT: you need 30 diamonds to get armor effect")
end
end
end
end

View File

@ -0,0 +1,24 @@
if not data then
m=50;n=50; minescount = m*n/10;
t0 = _G.minetest.get_gametime();
data = {}; spawnpos = self.spawnpos();
for i = 1, minescount do local i = math.random(m); local j = math.random(n); if not data[i] then data[i] = {} end; data[i][j] = 1; end
get_mine_count = function(i,j)
if i<0 or i>m+1 or j<0 or j>n+1 then return 0 end; count = 0
for k = -1,1 do for l = -1,1 do
if data[i+k] and data[i+k][j+l] == 1 then count = count +1 end
end end
return count
end
for i = 1,m do for j = 1,n do
if get_mine_count(i,j) > 0 or (data[i] and data[i][j] == 1) then
_G.minetest.swap_node({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}, {name = "basic_robot:buttonFFFFFF"})
else
_G.minetest.swap_node({x=spawnpos.x+i,y=spawnpos.y,z=spawnpos.z+j}, {name = "default:dirt"})
end
end end
end
self.remove()