MKlegoman357

Turtle move API with position and heading tracking

Nov 29th, 2020 (edited)
486
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local headings = {"north", "east", "south", "west"}
  2.  
  3. for i, value in ipairs(headings) do
  4.     headings[value] = i
  5. end
  6.  
  7. local function min(a, b)
  8.     return a < b and a or b
  9. end
  10.  
  11. local function max(a, b)
  12.     return a > b and a or b
  13. end
  14.  
  15. local function abs(x)
  16.     return x < 0 and -x or x
  17. end;
  18.  
  19. local function contains(table, item)
  20.     for i, value in ipairs(table) do
  21.         if value == item then
  22.             return true
  23.         end
  24.     end
  25.  
  26.     return false
  27. end
  28.  
  29. local function getVectorFromHeading(heading)
  30.     if heading == "north" then return vector.new(0, 0, -1) end
  31.     if heading == "east" then return vector.new(1, 0, 0) end
  32.     if heading == "south" then return vector.new(0, 0, 1) end
  33.     if heading == "west" then return vector.new(-1, 0, 0) end
  34.  
  35.     return vector.new(0, 0, 0)
  36. end
  37.  
  38. local function getHeadingFromVector(offset, defaultHeading)
  39.     if offset.x ~= 0 then
  40.         return offset.x < 0 and "west" or "east"
  41.     elseif offset.z ~= 0 then
  42.         return offset.z < 0 and "north" or "south"
  43.     end
  44.  
  45.     return defaultHeading or headings[1]
  46. end
  47.  
  48. local function getStepWithBreak(step, breakBlocks)
  49.     return function ()
  50.         while not step() do
  51.             if not breakBlocks() then
  52.                 return false
  53.             end
  54.         end
  55.  
  56.         return true
  57.     end
  58. end
  59.  
  60. local function moveTurtle(move, amount, step, moveOffset)
  61.     local movedAmount = vector.new(0, 0, 0)
  62.  
  63.     for i = 1, amount do
  64.         local moved = step()
  65.  
  66.         if not moved then break end
  67.  
  68.         movedAmount = movedAmount + moveOffset
  69.     end
  70.  
  71.     move.currentPos = move.currentPos + movedAmount
  72.  
  73.     local moved = abs(movedAmount.x) + abs(movedAmount.y) + abs(movedAmount.z)
  74.  
  75.     return moved == amount, moved
  76. end
  77.  
  78. local function turnTurtle(move, amount, turn, turnDirection)
  79.     local turnedAmount = 0
  80.  
  81.     for i = 1, amount do
  82.         local moved = turn()
  83.  
  84.         if not moved then break end
  85.  
  86.         turnedAmount = turnedAmount + turnDirection
  87.     end
  88.  
  89.     local normalizedTurnedAmount = turnedAmount % 4
  90.     local headingIndex = (headings[move.currentHeading] - 1 + normalizedTurnedAmount) % 4 + 1
  91.  
  92.     move.currentHeading = headings[headingIndex]
  93.  
  94.     return turnedAmount == amount, turnedAmount
  95. end
  96.  
  97. local function turtleDig(detect, inspect, dig, blockBlacklist)
  98.     while detect() do
  99.         if blockBlacklist then
  100.             local ok, block = inspect()
  101.  
  102.             if ok and contains(blockBlacklist, block.name) then
  103.                 return false
  104.             end
  105.         end
  106.  
  107.         if not dig() then
  108.             return false
  109.         end
  110.     end
  111.  
  112.     return true
  113. end
  114.  
  115. local function wrapNumber(x, maxValue)
  116.     x = x % maxValue
  117.  
  118.     if x < 1 then
  119.         x = x + maxValue
  120.     end
  121.  
  122.     return x
  123. end
  124.  
  125. local function getHeadingInDirection(currentHeading, direction)
  126.     local index = wrapNumber(headings[currentHeading] + direction, 4)
  127.  
  128.     return headings[index]
  129. end
  130.  
  131. local function getRequiredTurns(currentHeading, targetHeading, direction)
  132.     local turns
  133.  
  134.     if direction < 0 then
  135.         turns = wrapNumber(headings[currentHeading] - headings[targetHeading], 4)
  136.     else
  137.         turns = wrapNumber(headings[targetHeading] - headings[currentHeading], 4)
  138.     end
  139.  
  140.     if turns == 4 then
  141.         return 0
  142.     end
  143.  
  144.     return turns
  145. end
  146.  
  147. local function getFastestTurnDirection(currentHeading, targetHeading)
  148.     local leftTurns = getRequiredTurns(currentHeading, targetHeading, -1)
  149.     local rightTurns = getRequiredTurns(currentHeading, targetHeading, 1)
  150.  
  151.     return leftTurns < rightTurns and -1 or 1
  152. end
  153.  
  154. local move = {
  155.     headings = headings;
  156.  
  157.     getVectorFromHeading = getVectorFromHeading;
  158.     getHeadingInDirection = getHeadingInDirection;
  159.     getRequiredTurns = getRequiredTurns;
  160.     getFastestTurnDirection = getFastestTurnDirection;
  161.  
  162.     currentPos = vector.new(0, 0, 0);
  163.  
  164.     currentHeading = headings[1];
  165.  
  166.     setCurrentPos = function (self, pos, heading)
  167.         self.currentPos = pos
  168.         self.currentHeading = heading
  169.     end;
  170.  
  171.     forward = function (self, amount, tryBreakBlocks, blockBlacklist)
  172.         local step = not tryBreakBlocks and turtle.forward or getStepWithBreak(turtle.forward, function ()
  173.             return self:dig(blockBlacklist)
  174.         end)
  175.  
  176.         return moveTurtle(self, amount or 1, step, getVectorFromHeading(self.currentHeading))
  177.     end;
  178.  
  179.     back = function (self, amount, tryBreakBlocks, blockBlacklist)
  180.         local step = not tryBreakBlocks and turtle.forward or getStepWithBreak(turtle.back, function ()
  181.             self:turnLeft(2)
  182.             local dug = self:dig(blockBlacklist)
  183.             self:turnLeft(2)
  184.             return dug
  185.         end)
  186.  
  187.         return moveTurtle(self, amount or 1, step, getVectorFromHeading(self.currentHeading) * -1)
  188.     end;
  189.  
  190.     up = function (self, amount, tryBreakBlocks, blockBlacklist)
  191.         local step = not tryBreakBlocks and turtle.up or getStepWithBreak(turtle.up, function ()
  192.             return self:digUp(blockBlacklist)
  193.         end)
  194.  
  195.         return moveTurtle(self, amount or 1, step, vector.new(0, 1, 0))
  196.     end;
  197.  
  198.     down = function (self, amount, tryBreakBlocks, blockBlacklist)
  199.         local step = not tryBreakBlocks and turtle.down or getStepWithBreak(turtle.down, function ()
  200.             return self:digDown(blockBlacklist)
  201.         end)
  202.  
  203.         return moveTurtle(self, amount or 1, step, vector.new(0, -1, 0))
  204.     end;
  205.  
  206.     turnLeft = function (self, amount)
  207.         return turnTurtle(self, amount or 1, turtle.turnLeft, -1)
  208.     end;
  209.  
  210.     turnRight = function (self, amount)
  211.         return turnTurtle(self, amount or 1, turtle.turnRight, 1)
  212.     end;
  213.  
  214.     turnTo = function (self, heading)
  215.         local turnDirection = getFastestTurnDirection(self.currentHeading, heading)
  216.         local turnAmount = getRequiredTurns(self.currentHeading, heading, turnDirection)
  217.  
  218.         if turnAmount > 0 then
  219.             if turnDirection < 0 then
  220.                 return self:turnLeft(turnAmount)
  221.             else
  222.                 return self:turnRight(turnAmount)
  223.             end
  224.         end
  225.  
  226.         return true, 0
  227.     end;
  228.  
  229.     dig = function (self, blockBlacklist)
  230.         return turtleDig(turtle.detect, turtle.inspect, turtle.dig, blockBlacklist)
  231.     end;
  232.  
  233.     digUp = function (self, blockBlacklist)
  234.         return turtleDig(turtle.detectUp, turtle.inspectUp, turtle.digUp, blockBlacklist)
  235.     end;
  236.  
  237.     digDown = function (self, blockBlacklist)
  238.         return turtleDig(turtle.detectDown, turtle.inspectDown, turtle.digDown, blockBlacklist)
  239.     end;
  240.  
  241.     goTo = function (self, targetPos, breakBlocks, blockBlacklist)
  242.         local movedAmount = 0
  243.         local offset = targetPos - self.currentPos
  244.  
  245.         if offset.x ~= 0 then
  246.             local heading = getHeadingFromVector(vector.new(offset.x, 0, 0), self.currentHeading)
  247.  
  248.             self:turnTo(heading)
  249.             local moved, amount = self:forward(abs(offset.x), breakBlocks, blockBlacklist)
  250.  
  251.             movedAmount = movedAmount + amount
  252.  
  253.             if not moved then
  254.                 return false, movedAmount
  255.             end
  256.         end
  257.  
  258.         if offset.z ~= 0 then
  259.             local heading = getHeadingFromVector(vector.new(0, 0, offset.z), self.currentHeading)
  260.  
  261.             self:turnTo(heading)
  262.             local moved, amount = self:forward(abs(offset.z), breakBlocks, blockBlacklist)
  263.  
  264.             movedAmount = movedAmount + amount
  265.  
  266.             if not moved then
  267.                 return false, movedAmount
  268.             end
  269.         end
  270.  
  271.         if offset.y ~= 0 then
  272.             if offset.y > 0 then
  273.                 local moved, amount = self:up(offset.y, breakBlocks, blockBlacklist)
  274.  
  275.                 movedAmount = movedAmount + amount
  276.  
  277.                 if not moved then
  278.                     return false, movedAmount
  279.                 end
  280.             else
  281.                 local moved, amount = self:down(-offset.y, breakBlocks, blockBlacklist)
  282.  
  283.                 movedAmount = movedAmount + amount
  284.  
  285.                 if not moved then
  286.                     return false, movedAmount
  287.                 end
  288.             end
  289.         end
  290.  
  291.         return true, movedAmount
  292.     end;
  293. }
  294.  
  295. return move
  296.  
RAW Paste Data