-forward_down fixes
-added scripts
This commit is contained in:
parent
5d8617de1a
commit
182d81acec
10
init.lua
10
init.lua
@ -79,7 +79,7 @@ function getSandboxEnv (name)
|
|||||||
backward = function(item, inventory) return commands.insert_item(name,item, inventory,4) end,
|
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,
|
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,
|
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
|
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,
|
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,
|
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,
|
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,
|
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,
|
colorize = core.colorize,
|
||||||
tonumber = tonumber,
|
tonumber = tonumber, pairs = pairs,
|
||||||
pairs = pairs,
|
ipairs = ipairs, error = error, type=type,
|
||||||
ipairs = ipairs,
|
|
||||||
error = error,
|
|
||||||
|
|
||||||
--_ccounter = basic_robot.data[name].ccounter, -- counts how many executions of critical spots in script
|
--_ccounter = basic_robot.data[name].ccounter, -- counts how many executions of critical spots in script
|
||||||
|
|
||||||
|
175
scripts/avl_tree~.lua
Normal file
175
scripts/avl_tree~.lua
Normal 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
|
150
scripts/battle_minesweeper.lua
Normal file
150
scripts/battle_minesweeper.lua
Normal 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
195
scripts/blackbox.lua
Normal 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
195
scripts/blackbox_game.lua
Normal 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::
|
108
scripts/hash_table_implementation.lua
Normal file
108
scripts/hash_table_implementation.lua
Normal 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
38
scripts/messenger.lua
Normal 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
72
scripts/minesweeper.lua
Normal 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
|
72
scripts/minesweeper_game.lua
Normal file
72
scripts/minesweeper_game.lua
Normal 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
104
scripts/radix_sort.lua
Normal 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
90
scripts/serialization.lua
Normal 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
142
scripts/shop.lua
Normal 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
|
24
scripts/simple_layout_gen.lua
Normal file
24
scripts/simple_layout_gen.lua
Normal 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()
|
Loading…
x
Reference in New Issue
Block a user