From 38714bc2e8391eaf1b54c540e0a6f703b3384af7 Mon Sep 17 00:00:00 2001 From: orwell96 Date: Mon, 29 Aug 2016 21:53:41 +0200 Subject: implement track placing algorithm better --- trackplacer.lua | 133 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 79 insertions(+), 54 deletions(-) (limited to 'trackplacer.lua') diff --git a/trackplacer.lua b/trackplacer.lua index a864b35..a2b64bb 100644 --- a/trackplacer.lua +++ b/trackplacer.lua @@ -43,23 +43,23 @@ function tp.add_worked(nnprefix, suffix, rotation, cycle_follows) table.insert(tp.tracks[nnprefix].twrotate[suffix], rotation) end -function tp.find_adjacent_tracks(pos)--TODO vertical calculations(check node below) - local conn1=0 - while conn1<16 and not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, conn1)).name, advtrains.all_tracktypes) do - conn1=conn1+1 - end - if conn1>=16 then - return nil, nil - end - local conn2=0 - while conn2<16 and not advtrains.is_track_and_drives_on(minetest.get_node(advtrains.dirCoordSet(pos, conn2)).name, advtrains.all_tracktypes) or conn2==conn1 do - conn2=conn2+1 - end - if conn2>=16 then - return conn1, nil - end - return conn1, conn2 -end + +--[[ + rewrite algorithm. + selection criteria: these will never be changed or even selected: + - tracks being already connected on both sides + - tracks that are already connected on one side but are not bendable to the desired position + the following situations can occur: + 1. there are two more than two rails around + 1.1 there is one or more subset(s) that can be directly connected + -> choose the first possibility + 2.2 not + -> choose the first one and orient straight + 2. there's exactly 1 rail around + -> choose and orient straight + 3. there's no rail around + -> set straight +]] function tp.find_already_connected(pos)--TODO vertical calculations(check node below) local function istrackandbc(pos, conn) local cnode=minetest.get_node(advtrains.dirCoordSet(pos, conn)) @@ -70,51 +70,45 @@ function tp.find_already_connected(pos)--TODO vertical calculations(check node b end return false end - local conn1=0 - while conn1<16 and not istrackandbc(pos, conn1) do - conn1=conn1+1 - end - if conn1>=16 then - return nil, nil - end - local conn2=0 - while conn2<16 and not istrackandbc(pos, conn2) or conn2==conn1 do - conn2=conn2+1 + local dnode=minetest.get_node(pos) + local dconn1, dconn2=advtrains.get_track_connections(dnode.name, dnode.param2) + local t={[true]="true", [false]="false"} + if istrackandbc(pos, dconn1) and istrackandbc(pos, dconn2) then return dconn1, dconn2 + elseif istrackandbc(pos, dconn1) then return dconn1 + elseif istrackandbc(pos, dconn2) then return dconn2 end - if conn2>=16 then - return conn1, nil - end - return conn1, conn2 + return nil end - -function tp.placetrack(pos, nnpref) - local conn1, conn2=tp.find_adjacent_tracks(pos) +function tp.rail_and_can_be_bent(originpos, conn, nnpref) + local pos=advtrains.dirCoordSet(originpos, conn) + local newdir=(conn+8)%16 + local node=minetest.get_node(pos) local tr=tp.tracks[nnpref] - if not conn1 and not conn2 then - minetest.set_node(pos, {name=nnpref.."_"..tr.default}) - elseif conn1 and not conn2 then - if tr.single_conn[conn1] then - tp.try_adjust_rail(tr, advtrains.dirCoordSet(pos, conn1), (conn1+8)%16) - minetest.set_node(pos, tr.single_conn[conn1]) - else - minetest.set_node(pos, {name=nnpref.."_"..tr.default}) + if not advtrains.is_track_and_drives_on(node.name, advtrains.all_tracktypes) then + return false + end + --rail at other end? + local adj1, adj2=tp.find_already_connected(pos) + if adj1 and adj2 then + return false--dont destroy existing track + elseif adj1 and not adj2 then + if tr.double_conn[adj1.."_"..newdir] then + return true--if exists, connect new rail and old end end - elseif conn1 and conn2 then - if tr.double_conn[conn1.."_"..conn2] then - tp.try_adjust_rail(tr, advtrains.dirCoordSet(pos, conn1), (conn1+8)%16) - tp.try_adjust_rail(tr, advtrains.dirCoordSet(pos, conn2), (conn1+8)%16) - minetest.set_node(pos, tr.double_conn[conn1.."_"..conn2]) - elseif tr.single_conn[conn1] then --try at least one side - tp.try_adjust_rail(tr, advtrains.dirCoordSet(pos, conn1), (conn1+8)%16) - minetest.set_node(pos, tr.single_conn[conn1]) - else - minetest.set_node(pos, {name=nnpref.."_"..tr.default}) + return false + else + if tr.single_conn[newdir] then--just rotate old rail to right orientation + return true end + return false end end -function tp.try_adjust_rail(tr, pos, newdir) - --is rail already connected? +function tp.bend_rail(originpos, conn, nnpref) + local pos=advtrains.dirCoordSet(originpos, conn) + local newdir=(conn+8)%16 local node=minetest.get_node(pos) + local tr=tp.tracks[nnpref] + --is rail already connected? no need to bend. local conn1, conn2=advtrains.get_track_connections(node.name, node.param2) if newdir==conn1 or newdir==conn2 then return @@ -137,6 +131,37 @@ function tp.try_adjust_rail(tr, pos, newdir) return false end end +function tp.placetrack(pos, nnpref) + --1. find all rails that are likely to be connected + local tr=tp.tracks[nnpref] + local p_rails={} + for i=0,15 do + if tp.rail_and_can_be_bent(pos, i, nnpref) then + p_rails[#p_rails+1]=i + end + end + print(dump(p_rails)) + if #p_rails==0 then + minetest.set_node(pos, {name=nnpref.."_"..tr.default}) + elseif #p_rails==1 then + tp.bend_rail(pos, p_rails[1], nnpref) + minetest.set_node(pos, tr.single_conn[p_rails[1]]) + else + --iterate subsets + for k1, conn1 in ipairs(p_rails) do + for k2, conn2 in ipairs(p_rails) do + if k1~=k2 then + if (tr.double_conn[conn1.."_"..conn2]) then + tp.bend_rail(pos, conn1, nnpref) + tp.bend_rail(pos, conn2, nnpref) + minetest.set_node(pos, tr.double_conn[conn1.."_"..conn2]) + return + end + end + end + end + end +end function tp.register_track_placer(nnprefix, imgprefix, dispname) -- cgit v1.2.3