Advertisement
hkbruvold

navigation.lua

Apr 29th, 2014
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.26 KB | None | 0 0
  1. function newNav()
  2.     inav = {}
  3.    
  4.     -- location: {x, y, z, direction(0123 = s w n e)}
  5.     inav.loc = {nil, nil, nil, 0}
  6.    
  7.     -- file operation functions to save location and progress
  8.    
  9.     function inav.save(name, data)
  10.         local file = fs.open(name, "w")
  11.         file.write(textutils.serialize(data))
  12.         file.close()
  13.     end
  14.    
  15.     function inav.load(name)
  16.         local file = fs.open(name, "r")
  17.         local data = file.readAll()
  18.         file.close()
  19.         return textutils.unserialize(data)
  20.     end
  21.    
  22.     -- basic movement functions --
  23.     function inav.forward()
  24.         if turtle.forward() then
  25.             if inav.loc[4]%4 == 0 then inav.loc[3] = inav.loc[3] + 1
  26.             elseif inav.loc[4]%4 == 1 then inav.loc[1] = inav.loc[1] - 1
  27.             elseif inav.loc[4]%4 == 2 then inav.loc[3] = inav.loc[3] - 1
  28.             elseif inav.loc[4]%4 == 3 then inav.loc[1] = inav.loc[1] + 1
  29.             else print("moved, but location not updated. ERROR!") end
  30.             inav.save("location", inav.loc)
  31.             return true
  32.         end
  33.         return false
  34.     end
  35.    
  36.     function inav.back()
  37.         if turtle.back() then
  38.             if inav.loc[4]%4 == 0 then inav.loc[3] = inav.loc[3] - 1
  39.             elseif inav.loc[4]%4 == 1 then inav.loc[1] = inav.loc[1] + 1
  40.             elseif inav.loc[4]%4 == 2 then inav.loc[3] = inav.loc[3] + 1
  41.             elseif inav.loc[4]%4 == 3 then inav.loc[1] = inav.loc[1] - 1
  42.             else print("moved, but location not updated. ERROR!") end
  43.             inav.save("location", inav.loc)
  44.             return true
  45.         end
  46.         return false
  47.     end
  48.    
  49.     function inav.up()
  50.         if turtle.up() then
  51.             inav.loc[2] = inav.loc[2] + 1
  52.             inav.save("location", inav.loc)
  53.             return true
  54.         end
  55.         return false
  56.     end
  57.    
  58.     function inav.down()
  59.         if turtle.down() then
  60.             inav.loc[2] = inav.loc[2] - 1
  61.             inav.save("location", inav.loc)
  62.             return true
  63.         end
  64.         return false
  65.     end
  66.    
  67.     function inav.turnLeft()
  68.         if turtle.turnLeft() then
  69.             inav.loc[4] = inav.loc[4] - 1
  70.             inav.save("location", inav.loc)
  71.             return true
  72.         end
  73.         return false
  74.     end
  75.    
  76.     function inav.turnRight()
  77.         if turtle.turnRight() then
  78.             inav.loc[4] = inav.loc[4] + 1
  79.             inav.save("location", inav.loc)
  80.             return true
  81.         end
  82.         return false
  83.     end
  84.    
  85.     -- set current coordinates
  86.     function inav.setPos(x, y, z, direction)
  87.         inav.loc = {x, y, z, direction}
  88.         inav.save("location", inav.loc)
  89.     end
  90.    
  91.     -- get current coordinates
  92.     function inav.getPos()
  93.         return {inav.loc[1], inav.loc[2], inav.loc[3], inav.loc[4]%4}
  94.     end
  95.    
  96.     -- read location from save
  97.     function inav.readLocationSave()
  98.         inav.loc = inav.load("location")
  99.     end
  100.    
  101.     -- rotate to direction
  102.     function inav.rotate(direction)
  103.         local curDir = inav.loc[4]%4
  104.         local dir = direction%4
  105.         if math.abs(curDir - dir) == 2 then
  106.             while inav.turnLeft() == false do end
  107.             while inav.turnLeft() == false do end
  108.         elseif (curDir - 1)%4 == dir then
  109.             while inav.turnLeft() == false do end
  110.         elseif (curDir + 1)%4 == dir then
  111.             while inav.turnRight() == false do end
  112.         end
  113.     end
  114.    
  115.     -- move one step in direction (dig)
  116.     function inav.move(direction)
  117.         inav.rotate(direction)
  118.         turtle.dig()
  119.         return inav.forward()
  120.     end
  121.    
  122.     -- move up (dig)
  123.     function inav.moveUp()
  124.         turtle.digUp()
  125.         return inav.up()
  126.     end
  127.    
  128.     -- move down (dig)
  129.     function inav.moveDown()
  130.         turtle.digDown()
  131.         return inav.down()
  132.     end
  133.    
  134.     -- internal function to convert vector to unit vector
  135.     function inav.getUnitVector(vector)
  136.         local unitVec = {0, 0, 0,}
  137.         for i = 1,3 do
  138.             if vector[i] ~= 0 then
  139.                 unitVec[i] = vector[i]/math.abs(vector[i])
  140.             end
  141.         end
  142.         return unitVec
  143.     end
  144.    
  145.     -- internal function to convert direction to vector
  146.     function inav.getRotationVector(direction)
  147.         local vector = {0, 0}
  148.         if direction%4 == 0 then vector[2] = 1
  149.         elseif direction%4 == 1 then vector[1] = -1
  150.         elseif direction%4 == 2 then vector[2] = -1
  151.         elseif direction%4 == 3 then vector[1] = 1 end
  152.         return vector
  153.     end
  154.    
  155.     -- internal function to choose between east/west or north/south
  156.     function inav.getShortestDirections(unitVector, dirVector)
  157.         local shortest = {3, 3}
  158.         if unitVector[1] ~= 0 then -- if not only going east/west
  159.             shortest[1] = math.abs(unitVector[1] - dirVector[1])
  160.         end
  161.         if unitVector[3] ~= 0 then -- if not only going north/south
  162.             shortest[2] = math.abs(unitVector[3] - dirVector[2])
  163.         end
  164.         if unitVector[1] == 0 and unitVector[3] == 0 then -- if not moving at all
  165.             return nil
  166.         end
  167.         return shortest
  168.     end
  169.    
  170.     -- internal function to choose quickest direction
  171.     function inav.chooseShortestRotation(vector, curDir)
  172.         local deltaVector = inav.getUnitVector(vector)
  173.         local curVector = inav.getRotationVector(curDir)
  174.         local shortest = inav.getShortestDirections(deltaVector, curVector)
  175.        
  176.         if shortest == nil then return curDir end
  177.        
  178.         if shortest[1] < shortest[2] then -- if we're choosing east/west
  179.             if deltaVector[1] > 0 then -- if we're choosing east
  180.                 return 3
  181.             else -- else we choose west
  182.                 return 1
  183.             end
  184.         else -- else it is north/south
  185.             if deltaVector[3] > 0 then -- if we're choosing south
  186.                 return 0
  187.             else --else we choose north
  188.                 return 2
  189.             end
  190.         end
  191.         print("somthing went wrong when choosing direction")
  192.     end
  193.    
  194.     -- internal function to rotate to the other shortest direction
  195.     function inav.otherTurn(vector, curDir)
  196.         local unitVector = inav.getUnitVector(vector)
  197.         local dirVector = inav.getRotationVector(curDir)
  198.        
  199.         if dirVector[1] == 1 or dirVector[1] == -1 then
  200.             if unitVector[3] == 1 then return 0 end
  201.             if unitVector[3] == -1 then return 2 end
  202.         elseif dirVector[2] == 1 or dirVector[2] == -1 then
  203.             if unitVector[1] == 1 then return 3 end
  204.             if unitVector[1] == -1 then return 1 end
  205.         end
  206.         return curDir -- no better turns
  207.     end
  208.    
  209.     -- move to position and hopefully quickest way
  210.     function inav.moveTo(x, y, z)
  211.         local target = {}
  212.         if type(x) == "table" then target = x
  213.         else target = {x, y, z} end
  214.        
  215.         inav.save("lastMoveJob", target) -- save in case of interruption
  216.        
  217.         local vector = {target[1] - inav.loc[1], target[2] - inav.loc[2], target[3] - inav.loc[3]}
  218.         local bestRotation = nil
  219.         local newRotation = nil
  220.         local vertical = nil -- vertical toggle to know vertical direction
  221.         if vector[2] > 0 then vertical = 1
  222.         elseif vector[2] < 0 then vertical = -1
  223.         else vertical = 0 end
  224.        
  225.         -- loop to target
  226.         while vector[1] ~= 0 or vector[2] ~= 0 or vector[3] ~= 0 do
  227.             bestRotation = inav.chooseShortestRotation(vector, inav.loc[4])
  228.             inav.rotate(bestRotation)
  229.            
  230.             if vector[1] ~= 0 or vector[3] ~= 0 then -- try to move horisontal first
  231.                 if turtle.detect() then -- if block in front
  232.                     if vertical == 1 and not turtle.detectUp() then -- can we go up?
  233.                         inav.moveUp()
  234.                     elseif vertical == -1 and not turtle.detectDown() then -- can we go down?
  235.                         inav.moveDown()
  236.                     else -- try to turn
  237.                         newRotation = inav.otherTurn(vector, bestRotation)
  238.                         if newRotation == bestRotation then -- if no other turns
  239.                             inav.move(bestRotation)
  240.                         else
  241.                             inav.move(newRotation) -- move (and dig) the last direction
  242.                         end
  243.                     end
  244.                 else -- if no blocks, then move
  245.                     inav.move(bestRotation)
  246.                 end
  247.             else --by now we should be on x and z target
  248.                 if vertical == 1 then
  249.                     inav.moveUp()
  250.                 elseif vertical == -1 then
  251.                     inav.moveDown()
  252.                 end
  253.             end
  254.            
  255.             -- update vector and vertical toggle
  256.             vector = {target[1] - inav.loc[1], target[2] - inav.loc[2], target[3] - inav.loc[3]}
  257.             if vector[2] > 0 then vertical = 1
  258.             elseif vector[2] < 0 then vertical = -1
  259.             else vertical = 0 end
  260.         end
  261.     end
  262.    
  263.     function inav.resumeMove()
  264.         local lastMove = inav.load("lastMoveJob")
  265.         inav.moveTo(lastMove)
  266.     end
  267.    
  268.     if fs.exists("location") then
  269.         inav.readLocationSave()
  270.     end
  271.    
  272.     return inav
  273. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement