|
|
|
-- LUALOCALS < ---------------------------------------------------------
|
|
|
|
local include, nodecore, pairs, string, table
|
|
|
|
= include, nodecore, pairs, string, table
|
|
|
|
local string_lower
|
|
|
|
= string.lower
|
|
|
|
|
|
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
|
|
|
|
--nodecore.gametime
|
|
|
|
|
|
|
|
local cache = {}
|
|
|
|
|
|
|
|
local directions = { [0] =
|
|
|
|
vector.new(0, 0, -1),
|
|
|
|
vector.new(-1, 0, 0),
|
|
|
|
vector.new(0, 0, 1),
|
|
|
|
vector.new(1, 0, 0),
|
|
|
|
}
|
|
|
|
|
|
|
|
local down = vector.new(0, -1, 0)
|
|
|
|
|
|
|
|
local solid_drawtypes = {
|
|
|
|
normal = true,
|
|
|
|
glasslike_framed = true,
|
|
|
|
}
|
|
|
|
|
|
|
|
local S = ("S"):byte(1)
|
|
|
|
local W = ("W"):byte(1)
|
|
|
|
local E = ("E"):byte(1)
|
|
|
|
local C = ("C"):byte(1)
|
|
|
|
|
|
|
|
function handle_placement(pos)
|
|
|
|
cache = {}
|
|
|
|
--minetest.chat_send_all(tostring(pos))
|
|
|
|
--nodecore.node_sound(pos, "dug")
|
|
|
|
|
|
|
|
local our_stone = check_position(pos)
|
|
|
|
if not (our_stone:byte(1) == S) then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
our_stone = our_stone:sub(2, -1)
|
|
|
|
|
|
|
|
local captured = false
|
|
|
|
for i,v in pairs(neighbor_dirs(pos)) do
|
|
|
|
local node = check_position(pos + directions[v])
|
|
|
|
if node:byte(1) == S then
|
|
|
|
if not (node:sub(2, -1) == our_stone) then
|
|
|
|
local captures = check_captures(pos + directions[v])
|
|
|
|
if not (#captures == 0) then
|
|
|
|
minetest.chat_send_all("You gotcher self a capture right there! size: "..#captures)
|
|
|
|
captured = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if not captured then
|
|
|
|
local captures = check_captures(pos)
|
|
|
|
if not (#captures == 0) then
|
|
|
|
minetest.chat_send_all("You gotcher self a suicide move right there! size: "..#captures)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
--[[
|
|
|
|
give valid neighbor directions from a position, excluding solid blocks
|
|
|
|
and also respecting borders indicated by goban concrete
|
|
|
|
--]]
|
|
|
|
function neighbor_dirs(pos)
|
|
|
|
local neighbors = {}
|
|
|
|
for i,v in pairs(directions) do
|
|
|
|
if not edge_check(pos, i) then
|
|
|
|
if not (check_position(pos + directions[i]):byte(1) == W) then
|
|
|
|
neighbors[#neighbors+1] = i
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return neighbors
|
|
|
|
end
|
|
|
|
|
|
|
|
-- check for walls, physical or implied
|
|
|
|
function edge_check(pos, dir, terminate)
|
|
|
|
local under = check_position(pos + down)
|
|
|
|
|
|
|
|
if under:byte(1) == W and under:len() == 3 then
|
|
|
|
local corner = (under:byte(2) == C)
|
|
|
|
local edge_dir = tonumber(under:sub(3, 3))
|
|
|
|
|
|
|
|
if (dir == edge_dir) or (corner and (dir == (edge_dir+1)%4)) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if not terminate then
|
|
|
|
if edge_check(pos+directions[dir], (dir+2)%4, true) then
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--[[
|
|
|
|
E: empty
|
|
|
|
Stype: a go stone of some type
|
|
|
|
W: full block wall
|
|
|
|
WE0-WE3: edge concrete
|
|
|
|
WC0-WC3: corner concrete
|
|
|
|
--]]
|
|
|
|
function check_position(pos)
|
|
|
|
local hash = minetest.hash_node_position(pos)
|
|
|
|
if cache[hash] then
|
|
|
|
return cache[hash]
|
|
|
|
end
|
|
|
|
|
|
|
|
local ret = _check_position_uncached(pos)
|
|
|
|
cache[hash] = ret
|
|
|
|
return ret
|
|
|
|
end
|
|
|
|
|
|
|
|
function _check_position_uncached(pos)
|
|
|
|
local node = minetest.get_node(pos)
|
|
|
|
local reg_item = minetest.registered_items[node.name]
|
|
|
|
|
|
|
|
if not reg_item then
|
|
|
|
return "W"
|
|
|
|
end
|
|
|
|
|
|
|
|
if reg_item.groups and reg_item.groups.go_stone then
|
|
|
|
return "S" .. reg_item.go_team
|
|
|
|
end
|
|
|
|
|
|
|
|
if reg_item.pattern_def then
|
|
|
|
if reg_item.pattern_def.name == "edgy" then
|
|
|
|
return "WE" .. node.param2
|
|
|
|
elseif reg_item.pattern_def.name == "corny" then
|
|
|
|
return "WC" .. node.param2
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if solid_drawtypes[reg_item.drawtype] and not reg_item.groups.falling_node then
|
|
|
|
return "W"
|
|
|
|
else
|
|
|
|
return "E"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
--[[
|
|
|
|
Scans for a connected group, until enumerating the whole group, or
|
|
|
|
finding a liberty. Returns list of captured nodes, or empty list if
|
|
|
|
no captures.
|
|
|
|
--]]
|
|
|
|
function check_captures(pos)
|
|
|
|
local group = {pos}
|
|
|
|
local checked = {[minetest.hash_node_position(pos)] = true}
|
|
|
|
local team = check_position(pos):sub(2,-1)
|
|
|
|
|
|
|
|
local probe = 0
|
|
|
|
while probe < #group do
|
|
|
|
probe = probe + 1
|
|
|
|
pos = group[probe]
|
|
|
|
|
|
|
|
for i,v in pairs(neighbor_dirs(pos)) do
|
|
|
|
local newpos = pos + directions[v]
|
|
|
|
local newhash = minetest.hash_node_position(newpos)
|
|
|
|
|
|
|
|
if not checked[newhash] then
|
|
|
|
checked[newhash] = true
|
|
|
|
|
|
|
|
local newnode = check_position(newpos)
|
|
|
|
|
|
|
|
if newnode:byte(1) == E then
|
|
|
|
return {}
|
|
|
|
elseif newnode:byte(1) == S and
|
|
|
|
newnode:sub(2, -1) == team then
|
|
|
|
group[#group+1] = newpos
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
return group
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function print_r ( t )
|
|
|
|
local print_r_cache={}
|
|
|
|
local function sub_print_r(t,indent)
|
|
|
|
if (print_r_cache[tostring(t)]) then
|
|
|
|
print(indent.."*"..tostring(t))
|
|
|
|
else
|
|
|
|
print_r_cache[tostring(t)]=true
|
|
|
|
if (type(t)=="table") then
|
|
|
|
for pos,val in pairs(t) do
|
|
|
|
if (type(val)=="table") then
|
|
|
|
print(indent.."["..pos.."] => "..tostring(t).." {")
|
|
|
|
sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
|
|
|
|
print(indent..string.rep(" ",string.len(pos)+6).."}")
|
|
|
|
else
|
|
|
|
print(indent.."["..pos.."] => "..tostring(val))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
print(indent..tostring(t))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
sub_print_r(t," ")
|
|
|
|
end
|