Logikraft/circuits.lua

210 lines
6.6 KiB
Lua

-- component {
-- inputs: ["in1": bit, "in2": bit, "inB": byte],
-- outputs: ["out": byte],
-- name: alu0,
-- optiCompute: fun
-- contents: {
--
-- }
-- }
function logikraft.computeCircuit(circuit, input)
end
local function has_value (tab, len, val)
for i = 1, len do
if tab[i].x == val.x and tab[i].y == val.y and tab[i].z == val.z then
return true
end
end
return false
end
function logikraft.discoverBlocks(pos)
local i = 2
local j = 1
local poz = {}
poz[1] = pos
while (j<i)
do
local p = poz[j]
j = j+1
local neighbourhood = {
{x = p.x+1, y = p.y, z = p.z},
{x = p.x-1, y = p.y, z = p.z},
{x = p.x, y = p.y+1, z = p.z},
{x = p.x, y = p.y-1, z = p.z},
{x = p.x, y = p.y, z = p.z+1},
{x = p.x, y = p.y, z = p.z-1}
}
for p2=1,6
do
local n = neighbourhood[p2]
if((not has_value(poz,i-1,n)) and (minetest.get_item_group(minetest.get_node(n).name,"circuitry")==1))
then
poz[i] = n
i = i+1
end
end
end
minetest.chat_send_all("Discovered ".. (i-1) .. " blocks")
return poz
end
local function collapseConnectionsStep(connz)
for k,conna in ipairs(connz)
do
for l,connb in ipairs(connz)
do
if k<l
then
local match = table.findMatch1(conna.conn,connb.conn)
if match
then
-- we add connb\m[2] to conna\m[1], and then we remove connb
table.remove(conna.conn,match[1])
for i,x in pairs(connb.conn) do
if i ~= match[2] then table.insert(conna.conn,x) end
end
-- And we merge the node lists
for i,x in ipairs(connb.nodes) do
table.insert(conna.nodes,x)
end
table.remove(connz,l)
return true
end
end
end
end
return false
end
function logikraft.collapseConnections(connz)
while collapseConnectionsStep(connz)
do end
end
-- {x,y,z,d=0 if x+, 1 if z+}
function logikraft.compileCircuit(poz)
local components = {}
local connections = {}
for i,pos in ipairs(poz)
do
local node = minetest.get_node(pos)
if logikraft.cablenodes[node.name]
then
-- It is a cable
local conns = logikraft.cables[logikraft.cablenodes[node.name]].conns
for j,c in ipairs(conns)
do
if not (c == 1 or c == 2 or c == 4 or c == 8 or c == 17 or c == 18 or c == 20 or c == 24)
then
local newconn = {}
if math.fmod(math.floor(c/1),2)==1
then table.insert(newconn,{x=pos.x-1,y=pos.y,z=pos.z,d=0}) end
if math.fmod(math.floor(c/2),2)==1
then table.insert(newconn,{x=pos.x,y=pos.y,z=pos.z-1,d=1}) end
if math.fmod(math.floor(c/4),2)==1
then table.insert(newconn,{x=pos.x,y=pos.y,z=pos.z,d=0}) end
if math.fmod(math.floor(c/8),2)==1
then table.insert(newconn,{x=pos.x,y=pos.y,z=pos.z,d=1}) end
local pos2 = table.copy(pos)
pos2.conn = j
table.insert(connections,{nodes = {pos2},conn = newconn})
end
end
elseif logikraft.componentnodes[node.name]
then
-- It is a component
local cpblock = logikraft.componentnodes[node.name]
if cpblock.x == 1 and cpblock.y == 1
then
local component = logikraft.components[cpblock.name]
local cp = {type = cpblock.name, ports = {}, pos = pos}
-- Left
if component.ports.left
then
for j,n in pairs(component.ports.left)
do
if n
then
cp.ports[n] = {x=pos.x-1,y=pos.y,z=pos.z+j-1,d=0}
end
end
end
-- Right
if component.ports.right
then
for j,n in pairs(component.ports.right)
do
if n
then
cp.ports[n] = {x=pos.x+component.width-1,y=pos.y,z=pos.z+j-1,d=0}
end
end
end
-- Top
if component.ports.top
then
for j,n in pairs(component.ports.top)
do
if n
then
cp.ports[n] = {x=pos.x+j-1,y=pos.y,z=pos.z+component.height-1,d=1}
end
end
end
-- Bottom
if component.ports.bottom
then
for j,n in pairs(component.ports.bottom)
do
if n
then
cp.ports[n] = {x=pos.x+j-1,y=pos.y,z=pos.z-1,d=1}
end
end
end
-- If we have a meta name, we save it
local meta = minetest.get_meta(pos)
if meta:get_string("logikraft:name") ~= ""
then cp.name = meta:get_string("logikraft:name")
end
table.insert(components,cp)
-- We do everything in the 0 0 block, we ignore the others
end
-- else we just ignore
end
end
logikraft.collapseConnections(connections)
-- We replace the index of the connection in the components
for k,cmp in pairs(components)
do
for pn,x in pairs(cmp.ports)
do
-- We find the connection with this port
local theconn = 0
for i,connz in ipairs(connections)
do
if table.getkey1(connz.conn,x) -- if x in connz
then theconn = i end
end
cmp.ports[pn] = theconn
end
end
-- We remove conn data from the connections, the index in now enough
for k,conn in ipairs(connections)
do
connections[k] = connections[k].nodes
end
print("Discovered:")
print(dump(components))
print(dump(connections))
return {components = components, connections = connections}
end