Implement modular scan strategies
This commit is contained in:
parent
6c28791112
commit
61bef0e040
19
location.lua
19
location.lua
@ -154,4 +154,21 @@ function new( x, y, z, h )
|
|||||||
}
|
}
|
||||||
setmetatable( l, lmetatable )
|
setmetatable( l, lmetatable )
|
||||||
return l
|
return l
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local headings = {
|
||||||
|
[vector.new(0, 0, 1)] = 0,
|
||||||
|
[vector.new(-1, 0, 0)] = 1,
|
||||||
|
[vector.new(0, 0, -1)] = 2,
|
||||||
|
[vector.new(1, 0, 0)] = 3,
|
||||||
|
[vector.new(0, 1, 0)] = 4,
|
||||||
|
[vector.new(0, -1, 0)] = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
function headingFromDelta(delta)
|
||||||
|
for vec, dir in pairs(headings) do
|
||||||
|
if aStar.vectorEquals(delta, vec) then
|
||||||
|
return dir
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@ -2,6 +2,7 @@ local apis = {
|
|||||||
"remoteMap",
|
"remoteMap",
|
||||||
"aStar",
|
"aStar",
|
||||||
"location",
|
"location",
|
||||||
|
"scanStrategy",
|
||||||
}
|
}
|
||||||
for _, api in ipairs(apis) do
|
for _, api in ipairs(apis) do
|
||||||
if not _G[api] then
|
if not _G[api] then
|
||||||
@ -49,23 +50,6 @@ local function distanceFunc(a, b)
|
|||||||
return aStar.distance(a, b) -- we dont know anything useful so just calc the distance
|
return aStar.distance(a, b) -- we dont know anything useful so just calc the distance
|
||||||
end
|
end
|
||||||
|
|
||||||
local directions = {
|
|
||||||
[vector.new(0, 0, 1)] = 0,
|
|
||||||
[vector.new(-1, 0, 0)] = 1,
|
|
||||||
[vector.new(0, 0, -1)] = 2,
|
|
||||||
[vector.new(1, 0, 0)] = 3,
|
|
||||||
[vector.new(0, 1, 0)] = 4,
|
|
||||||
[vector.new(0, -1, 0)] = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function deltaToDirection(delta)
|
|
||||||
for vec, dir in pairs(directions) do
|
|
||||||
if aStar.vectorEquals(delta, vec) then
|
|
||||||
return dir
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function tryMove()
|
local function tryMove()
|
||||||
for i = 1, 4 do
|
for i = 1, 4 do
|
||||||
if turtle.forward() then
|
if turtle.forward() then
|
||||||
@ -107,31 +91,16 @@ local function findPosition()
|
|||||||
error("no gps signal - phase 2")
|
error("no gps signal - phase 2")
|
||||||
end
|
end
|
||||||
|
|
||||||
local direction = deltaToDirection(p1 - p2)
|
local currentDirection = location.headingFromDelta(p1 - p2)
|
||||||
if direction and direction < 4 then
|
if currentDirection and currentDirection < 4 then
|
||||||
return location.new(p2.x, p2.y, p2.z, direction)
|
return location.new(p2.x, p2.y, p2.z, currentDirection)
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function detect(currPos, adjPos)
|
|
||||||
local direction = deltaToDirection(adjPos - currPos)
|
|
||||||
if direction then
|
|
||||||
position:setHeading(direction)
|
|
||||||
if direction == 4 then
|
|
||||||
return turtle.detectUp()
|
|
||||||
elseif direction == 5 then
|
|
||||||
return turtle.detectDown()
|
|
||||||
else
|
|
||||||
return turtle.detect()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function inspect(currPos, adjPos)
|
local function inspect(currPos, adjPos)
|
||||||
local direction = deltaToDirection(adjPos - currPos)
|
local direction = location.headingFromDelta(adjPos - currPos)
|
||||||
if direction then
|
if direction then
|
||||||
position:setHeading(direction)
|
position:setHeading(direction)
|
||||||
if direction == 4 then
|
if direction == 4 then
|
||||||
@ -145,81 +114,35 @@ local function inspect(currPos, adjPos)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local function updateCoord(coord, isBlocked)
|
local function updateSessionMap(coord, isBlocked)
|
||||||
if isBlocked then
|
if isBlocked then
|
||||||
sessionMap:set(coord, SESSION_COORD_BLOCKED)
|
sessionMap:set(coord, SESSION_COORD_BLOCKED)
|
||||||
serverMap:set(coord, UPDATE_COORD_BLOCKED)
|
|
||||||
else
|
else
|
||||||
sessionMap:set(coord, SESSION_COORD_CLEAR)
|
sessionMap:set(coord, SESSION_COORD_CLEAR)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function updateServerMap(coord, isBlocked)
|
||||||
|
if isBlocked then
|
||||||
|
serverMap:set(coord, UPDATE_COORD_BLOCKED)
|
||||||
|
else
|
||||||
serverMap:set(coord, UPDATE_COORD_CLEAR)
|
serverMap:set(coord, UPDATE_COORD_CLEAR)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function detectAll(currPos)
|
local function scan(currentPosition)
|
||||||
for _, pos in ipairs(aStar.adjacent(currPos)) do -- better order of checking directions
|
local strategy = scanStrategy.getBest()
|
||||||
updateCoord(pos, detect(currPos, pos))
|
if strategy then
|
||||||
end
|
strategy.execute(currentPosition, updateSessionMap, updateServerMap)
|
||||||
end
|
serverMap:check()
|
||||||
|
serverMap:pushUpdates()
|
||||||
local function findSensor()
|
|
||||||
for _, side in ipairs({"left", "right"}) do
|
|
||||||
if peripheral.getType(side) == "turtlesensorenvironment" then
|
|
||||||
return side
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
local function scan(currPos)
|
|
||||||
local sensorSide = findSensor()
|
|
||||||
if sensorSide then
|
|
||||||
local rawBlockInfo = peripheral.call(sensorSide, "sonicScan")
|
|
||||||
local sortedBlockInfo = aStar.newMap()
|
|
||||||
for _, blockInfo in ipairs(rawBlockInfo) do
|
|
||||||
sortedBlockInfo:set(currPos + vector.new(blockInfo.x, blockInfo.y, blockInfo.z), blockInfo)
|
|
||||||
end
|
|
||||||
local toCheckQueue = {}
|
|
||||||
for _, pos in ipairs(aStar.adjacent(currPos)) do
|
|
||||||
if sortedBlockInfo:get(pos) then
|
|
||||||
table.insert(toCheckQueue, pos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
while toCheckQueue[1] do
|
|
||||||
local pos = table.remove(toCheckQueue, 1)
|
|
||||||
local blockInfo = sortedBlockInfo:get(pos)
|
|
||||||
if blockInfo.type == "AIR" then
|
|
||||||
for _, pos2 in ipairs(aStar.adjacent(pos)) do
|
|
||||||
local blockInfo2 = sortedBlockInfo:get(pos2)
|
|
||||||
if blockInfo2 and not blockInfo2.checked then
|
|
||||||
table.insert(toCheckQueue, pos2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
updateCoord(pos, false)
|
|
||||||
else
|
|
||||||
updateCoord(pos, true)
|
|
||||||
end
|
|
||||||
blockInfo.checked = true
|
|
||||||
end
|
|
||||||
for _, blockInfo in ipairs(rawBlockInfo) do
|
|
||||||
local pos = currPos + vector.new(blockInfo.x, blockInfo.y, blockInfo.z)
|
|
||||||
local blockInfo = sortedBlockInfo:get(pos)
|
|
||||||
if not blockInfo.checked then
|
|
||||||
if blockInfo.type == "AIR" then
|
|
||||||
sessionMap:set(pos, SESSION_COORD_CLEAR)
|
|
||||||
else
|
|
||||||
sessionMap:set(pos, SESSION_COORD_BLOCKED)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
detectAll(currPos)
|
-- throw error ?
|
||||||
end
|
end
|
||||||
serverMap:check()
|
|
||||||
serverMap:pushUpdates()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function move(currPos, adjPos)
|
local function move(currPos, adjPos)
|
||||||
local direction = deltaToDirection(adjPos - currPos)
|
local direction = location.headingFromDelta(adjPos - currPos)
|
||||||
if direction then
|
if direction then
|
||||||
position:setHeading(direction)
|
position:setHeading(direction)
|
||||||
if direction == 4 then
|
if direction == 4 then
|
||||||
@ -356,3 +279,7 @@ function getPosition()
|
|||||||
return position:value()
|
return position:value()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function addScanStrategy(strategy)
|
||||||
|
scanStrategy.add(strategy)
|
||||||
|
end
|
||||||
|
|||||||
84
netNav/scanStrategy.lua
Normal file
84
netNav/scanStrategy.lua
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
local strategies = {}
|
||||||
|
|
||||||
|
local function compareStrategies(a, b)
|
||||||
|
return a.priority > b.priority
|
||||||
|
end
|
||||||
|
|
||||||
|
function add(strategy)
|
||||||
|
table.insert(strategies, strategy)
|
||||||
|
table.sort(strategies, compareStrategies)
|
||||||
|
end
|
||||||
|
|
||||||
|
function getBest()
|
||||||
|
for _, strategy in ipairs(strategies) do
|
||||||
|
if strategy.isAvailable() then
|
||||||
|
return strategy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--===== SET UP VANILLA SCAN STRATEGY =====--
|
||||||
|
local function detect(currPos, adjPos)
|
||||||
|
local heading = location.headingFromDelta(adjPos - currPos)
|
||||||
|
if heading then
|
||||||
|
currPos:setHeading(heading)
|
||||||
|
if heading == 4 then
|
||||||
|
return turtle.detectUp()
|
||||||
|
elseif heading == 5 then
|
||||||
|
return turtle.detectDown()
|
||||||
|
else
|
||||||
|
return turtle.detect()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local vanillaScanStrategy = {
|
||||||
|
priority = 0, -- lowest priority
|
||||||
|
isAvailable = function() return true end, -- always available
|
||||||
|
execute = function(currentPosition, updateSessionMap, updateServerMap)
|
||||||
|
for _, pos in ipairs(aStar.adjacent(currentPosition)) do -- find better order of checking directions
|
||||||
|
local isBlocked = detect(currentPosition, pos)
|
||||||
|
updateSessionMap(pos, isBlocked)
|
||||||
|
updateServerMap(pos, isBlocked)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
add(vanillaScanStrategy)
|
||||||
|
|
||||||
|
--===== LOAD STRATEGIES FROM NET NAV STRATEGY FOLDER
|
||||||
|
local function loadStrategy(path)
|
||||||
|
local name = fs.getName(path)
|
||||||
|
if name:sub(-4) == ".lua" then
|
||||||
|
name = name:sub(1, -5)
|
||||||
|
end
|
||||||
|
|
||||||
|
local tEnv = {}
|
||||||
|
setmetatable(tEnv, {__index = _G})
|
||||||
|
local fnAPI, err = loadfile(path, tEnv)
|
||||||
|
if fnAPI then
|
||||||
|
local ok, err = pcall(fnAPI)
|
||||||
|
if not ok then
|
||||||
|
return printError("Failed to load strategy " .. name .. " due to " .. err, 1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return printError("Failed to load strategy " .. name .. " due to " .. err, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(tEnv.new) == "function" then
|
||||||
|
local strategy = tEnv.new()
|
||||||
|
add(strategy)
|
||||||
|
else
|
||||||
|
return printError("Failed to find constructor for strategy " .. name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local STRATEGY_FOLDER = "netNavScanStrategies"
|
||||||
|
|
||||||
|
if fs.exists(STRATEGY_FOLDER) and fs.isDir(STRATEGY_FOLDER) then
|
||||||
|
for _, file in ipairs(fs.list(STRATEGY_FOLDER)) do
|
||||||
|
local path = fs.combine(STRATEGY_FOLDER, file)
|
||||||
|
loadStrategy(path)
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
x
Reference in New Issue
Block a user