|
|
|
@ -30,81 +30,54 @@ 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 captureses = {} |
|
|
|
|
local captured = false |
|
|
|
|
for i,v in pairs(neighbor_dirs(pos)) do |
|
|
|
|
local new_pos = pos + directions[v] |
|
|
|
|
--[[ |
|
|
|
|
E: empty |
|
|
|
|
Stype: a go stone of some type |
|
|
|
|
W: full block wall |
|
|
|
|
WE0-WE3: edge concrete |
|
|
|
|
WC0-WC3: corner concrete |
|
|
|
|
--]] |
|
|
|
|
local function _check_position_uncached(pos) |
|
|
|
|
local node = minetest.get_node(pos) |
|
|
|
|
local reg_item = minetest.registered_items[node.name] |
|
|
|
|
|
|
|
|
|
local hash = minetest.hash_node_position(new_pos) |
|
|
|
|
if not reg_item then |
|
|
|
|
return "W" |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
local checked = false |
|
|
|
|
for i2,v2 in pairs(captureses) do |
|
|
|
|
if v2.stones[hash] then |
|
|
|
|
checked = true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if reg_item.groups and reg_item.groups.go_stone then |
|
|
|
|
return "S" .. reg_item.go_team |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if not checked then |
|
|
|
|
local node = check_position(new_pos) |
|
|
|
|
if (node:byte(1) == S) and (not (node:sub(2, -1) == our_stone)) then |
|
|
|
|
local captures = check_captures(new_pos) |
|
|
|
|
captured = captured or captures.capture |
|
|
|
|
captureses[#captureses+1] = captures |
|
|
|
|
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 captured then |
|
|
|
|
for i,v in pairs(captureses) do |
|
|
|
|
if v.capture then |
|
|
|
|
local proximal = {} |
|
|
|
|
|
|
|
|
|
for i2, v2 in pairs(v.stones) do |
|
|
|
|
nodecore.set_loud(v2, {name = "nc_fire:fire"}) |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- todo: spawn itemstack of captured stones somehow |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
if solid_drawtypes[reg_item.drawtype] and not reg_item.groups.falling_node then |
|
|
|
|
return "W" |
|
|
|
|
else |
|
|
|
|
local captures = check_captures(pos) |
|
|
|
|
if captures.capture then |
|
|
|
|
minetest.chat_send_all("You gotcher self a suicide move right there! size: "..#(captures.stones)) |
|
|
|
|
-- todo: replace with itemstack of one stone |
|
|
|
|
end |
|
|
|
|
return "E" |
|
|
|
|
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 |
|
|
|
|
local function check_position(pos) |
|
|
|
|
local hash = minetest.hash_node_position(pos) |
|
|
|
|
if cache[hash] then |
|
|
|
|
return cache[hash] |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
return neighbors |
|
|
|
|
local ret = _check_position_uncached(pos) |
|
|
|
|
cache[hash] = ret |
|
|
|
|
return ret |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
-- check for walls, physical or implied |
|
|
|
|
function edge_check(pos, dir, terminate) |
|
|
|
|
local function edge_check(pos, dir, terminate) |
|
|
|
|
local under = check_position(pos + down) |
|
|
|
|
|
|
|
|
|
if under:byte(1) == W and under:len() == 3 then |
|
|
|
@ -125,50 +98,21 @@ function edge_check(pos, dir, terminate) |
|
|
|
|
return false |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--[[ |
|
|
|
|
E: empty |
|
|
|
|
Stype: a go stone of some type |
|
|
|
|
W: full block wall |
|
|
|
|
WE0-WE3: edge concrete |
|
|
|
|
WC0-WC3: corner concrete |
|
|
|
|
give valid neighbor directions from a position, excluding solid blocks |
|
|
|
|
and also respecting borders indicated by goban 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 |
|
|
|
|
local 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 |
|
|
|
|
|
|
|
|
|
if solid_drawtypes[reg_item.drawtype] and not reg_item.groups.falling_node then |
|
|
|
|
return "W" |
|
|
|
|
else |
|
|
|
|
return "E" |
|
|
|
|
end |
|
|
|
|
return neighbors |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
--[[ |
|
|
|
@ -176,7 +120,7 @@ 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 function check_captures(pos) |
|
|
|
|
local group = {pos} |
|
|
|
|
local stones = {[minetest.hash_node_position(pos)] = pos} |
|
|
|
|
local checked = {} |
|
|
|
@ -210,29 +154,60 @@ function check_captures(pos) |
|
|
|
|
return {capture = true, stones = stones} |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
function lc_liberties.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 captureses = {} |
|
|
|
|
local captured = false |
|
|
|
|
for i,v in pairs(neighbor_dirs(pos)) do |
|
|
|
|
local new_pos = pos + directions[v] |
|
|
|
|
|
|
|
|
|
local hash = minetest.hash_node_position(new_pos) |
|
|
|
|
|
|
|
|
|
local checked = false |
|
|
|
|
for i2,v2 in pairs(captureses) do |
|
|
|
|
if v2.stones[hash] then |
|
|
|
|
checked = true |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
if not checked then |
|
|
|
|
local node = check_position(new_pos) |
|
|
|
|
if (node:byte(1) == S) and (not (node:sub(2, -1) == our_stone)) then |
|
|
|
|
local captures = check_captures(new_pos) |
|
|
|
|
captured = captured or captures.capture |
|
|
|
|
captureses[#captureses+1] = captures |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
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 |
|
|
|
|
if captured then |
|
|
|
|
for i,v in pairs(captureses) do |
|
|
|
|
if v.capture then |
|
|
|
|
local proximal = {} |
|
|
|
|
|
|
|
|
|
for i2, v2 in pairs(v.stones) do |
|
|
|
|
nodecore.set_loud(v2, {name = "nc_fire:fire"}) |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
print(indent..tostring(t)) |
|
|
|
|
|
|
|
|
|
-- todo: spawn itemstack of captured stones somehow |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
else |
|
|
|
|
local captures = check_captures(pos) |
|
|
|
|
if captures.capture then |
|
|
|
|
minetest.chat_send_all("You gotcher self a suicide move right there! size: "..#(captures.stones)) |
|
|
|
|
-- todo: replace with itemstack of one stone |
|
|
|
|
end |
|
|
|
|
end |
|
|
|
|
sub_print_r(t," ") |
|
|
|
|
end |
|
|
|
|
|
|
|
|
|
|
|
|
|
|