Advertisement
gravitowl

Ecdysis

Dec 20th, 2024
28
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 12.22 KB | None | 0 0
  1. local DIRECTIONS = {
  2.     north = 0,
  3.     east = 1,
  4.     south = 2,
  5.     west = 3
  6. };
  7.  
  8. local DIRECTION_DELTAS = {
  9.     [DIRECTIONS.north] = { x = 0, y = 0, z = -1 },
  10.     [DIRECTIONS.east] = { x = 1, y = 0, z = 0 },
  11.     [DIRECTIONS.south] = { x = 0, y = 0, z = 1 },
  12.     [DIRECTIONS.west] = { x = -1, y = 0, z = 0 },
  13.     up = { x = 0, y = 1, z = 0 },
  14.     down = { x = 0, y = -1, z = 0 }
  15. };
  16.  
  17. local RELATIVE_DELTAS = {
  18.     forward = { x = 0, y = 0, z = -1 },
  19.     back = { x = 0, y = 0, z = 1 },
  20.     left = { x = -1, y = 0, z = 0 },
  21.     right = { x = 1, y = 0, z = 0 },
  22.     up = { x = 0, y = 1, z = 0 },
  23.     down = { x = 0, y = -1, z = 0 },
  24. }
  25.  
  26. local MOVE_DIRECTIONS = {
  27.     forward = 0,
  28.     back = 1,
  29.     up = 2,
  30.     down = 3
  31. }
  32.  
  33. local TURN_DIRECTIONS = {
  34.     right = 0,
  35.     left = 1,
  36. }
  37.  
  38. local DIRECTION = DIRECTIONS.north;
  39. local POSITION = {
  40.     x = 0,
  41.     y = 0,
  42.     z = 0,
  43. };
  44.  
  45. local function getPosition()
  46.     return POSITION;
  47. end
  48.  
  49. local function getDirection()
  50.     return DIRECTION;
  51. end
  52.  
  53. local function applyDirectionDelta(delta)
  54.     if delta == nil or delta == RELATIVE_DELTAS.up or delta == RELATIVE_DELTAS.down then
  55.         return delta
  56.     end
  57.  
  58.     -- Copy the delta to avoid mutation
  59.     local rotatedDelta = { x = delta.x, y = delta.y, z = delta.z }
  60.  
  61.     -- Apply 90° rotations based on DIRECTION
  62.     for _ = 1, DIRECTION do
  63.         rotatedDelta = {
  64.             x = -rotatedDelta.z, -- Rotating clockwise
  65.             y = rotatedDelta.y,
  66.             z = rotatedDelta.x,
  67.         }
  68.     end
  69.  
  70.     return rotatedDelta
  71. end
  72.  
  73. local function applyPositionDelta(delta)
  74.     return {
  75.         x = POSITION.x + delta.x,
  76.         y = POSITION.y + delta.y,
  77.         z = POSITION.z + delta.z
  78.     }
  79. end
  80.  
  81. local function isPositionAdjacent(position)
  82.     local dx = math.abs(position.x - POSITION.x);
  83.     local dy = math.abs(position.y - POSITION.y);
  84.     local dz = math.abs(position.z - POSITION.z);
  85.  
  86.     return (dx + dy + dz) == 1
  87. end
  88.  
  89. local function syncWithGPS()
  90.     local x, y, z = gps.locate();
  91.  
  92.     if not x then
  93.         return false, false;
  94.     end
  95.  
  96.     POSITION.x = x;
  97.     POSITION.y = y;
  98.     POSITION.z = z;
  99.  
  100.     if turtle.getFuelLevel() < 2 then
  101.         return true, false;
  102.     end
  103.  
  104.     local turnCount = 0;
  105.     local couldMove = false;
  106.    
  107.     for i=1, 4 do
  108.         couldMove = turtle.forward();
  109.         if couldMove then
  110.             break;
  111.         end
  112.         turtle.turnRight();
  113.         turnCount = turnCount + 1;
  114.     end
  115.  
  116.     if not couldMove then
  117.         return true, false;
  118.     end
  119.  
  120.     local new_x, new_y, new_z = gps.locate();
  121.  
  122.     if new_x and new_z then
  123.         local dx = new_x - x;
  124.         local dz = new_z - z;
  125.  
  126.         if dx == 1 then
  127.             DIRECTION = DIRECTIONS.east;
  128.         elseif dx == -1 then
  129.             DIRECTION = DIRECTIONS.west;
  130.         elseif dz == 1 then
  131.             DIRECTION = DIRECTIONS.south;
  132.         elseif dz == -1 then
  133.             DIRECTION = DIRECTIONS.north;
  134.         end
  135.     else
  136.         return true, false;
  137.     end
  138.  
  139.     turtle.back();
  140.  
  141.     for i=1, turnCount do
  142.         turtle.turnLeft();
  143.     end
  144.  
  145.     return true, true;
  146. end
  147.  
  148. local function move(direction)
  149.     if direction == MOVE_DIRECTIONS.forward then
  150.         local couldMove, error = turtle.forward();
  151.         if not couldMove then
  152.             return false, error
  153.         end
  154.        
  155.         POSITION = applyPositionDelta(DIRECTION_DELTAS[DIRECTION]);
  156.     elseif direction == MOVE_DIRECTIONS.back then
  157.         local couldMove, error = turtle.back();
  158.         if not couldMove then
  159.             return false, error
  160.         end
  161.        
  162.         POSITION = applyPositionDelta(DIRECTION_DELTAS[(DIRECTION + 2)%4]);
  163.     elseif direction == MOVE_DIRECTIONS.up then
  164.         local couldMove, error = turtle.up();
  165.         if not couldMove then
  166.             return false, error
  167.         end
  168.  
  169.         POSITION = applyPositionDelta(DIRECTION_DELTAS.up);
  170.     elseif direction == MOVE_DIRECTIONS.down then
  171.         local couldMove, error = turtle.down();
  172.         if not couldMove then
  173.             return false, error
  174.         end
  175.        
  176.         POSITION = applyPositionDelta(DIRECTION_DELTAS.down);
  177.     else
  178.         return false, "Invalid direction.";
  179.     end
  180.  
  181.     return true;
  182. end
  183.  
  184. local function forceMove(direction)
  185.     if turtle.getFuelLevel() == 0 then
  186.         return false, "Not enough fuel.";
  187.     end
  188.  
  189.     if direction == nil then
  190.         return false, "Invalid direction."
  191.     end
  192.  
  193.     while not move(direction) do
  194.         if direction == MOVE_DIRECTIONS.forward then
  195.             turtle.dig();
  196.         elseif direction == MOVE_DIRECTIONS.up then
  197.             turtle.digUp();
  198.         elseif direction == MOVE_DIRECTIONS.down then
  199.             turtle.digDown();
  200.         end
  201.     end
  202. end
  203.  
  204. local function forward() move(MOVE_DIRECTIONS.forward) end
  205. local function back() move(MOVE_DIRECTIONS.back) end
  206. local function up() move(MOVE_DIRECTIONS.forward) end
  207. local function down() move(MOVE_DIRECTIONS.down) end
  208.  
  209. local function forceForward() forceMove(MOVE_DIRECTIONS.forward) end
  210. local function forceUp() forceMove(MOVE_DIRECTIONS.up) end
  211. local function forceDown() forceMove(MOVE_DIRECTIONS.down) end
  212.  
  213. local function turn(amount, direction)
  214.     for _ = 1, amount do
  215.         if direction == TURN_DIRECTIONS.left then
  216.             turtle.turnLeft();
  217.             DIRECTION = (DIRECTION - 1 + 4) % 4;
  218.         elseif direction == TURN_DIRECTIONS.right then
  219.             turtle.turnRight();
  220.             DIRECTION = (DIRECTION + 1) % 4;
  221.         end
  222.  
  223.     end
  224. end
  225.  
  226. local function turnTo(direction)
  227.     local turnsRequired = (direction - DIRECTION + 4) % 4;
  228.  
  229.     if turnsRequired < 0 then
  230.         turn(math.abs(turnsRequired), TURN_DIRECTIONS.left);
  231.     elseif turnsRequired > 0 then
  232.         turn(turnsRequired, TURN_DIRECTIONS.right);
  233.     end
  234. end
  235.  
  236. local function turnLeft() turn(1, TURN_DIRECTIONS.left) end
  237. local function turnRight() turn(1, TURN_DIRECTIONS.right) end
  238.  
  239. local function hasEnoughFuel(minimumFuelLevel)
  240.     return turtle.getFuelLevel() >= minimumFuelLevel;
  241. end
  242.  
  243. local function moveTo(target)
  244.     local dx = target.x - POSITION.x;
  245.     local dy = target.y - POSITION.y;
  246.     local dz = target.z - POSITION.z;
  247.  
  248.     if not hasEnoughFuel(math.abs(dx) + math.abs(dy) + math.abs(dz)) then
  249.         return false, "Not enough fuel.";
  250.     end
  251.  
  252.     if dx > 0 then
  253.         turnTo(DIRECTIONS.east);
  254.     elseif dx < 0 then
  255.         turnTo(DIRECTIONS.west);
  256.     end
  257.  
  258.     for i=1, math.abs(dx) do
  259.         forceForward();
  260.     end
  261.  
  262.     if dz > 0 then
  263.         turnTo(DIRECTIONS.south);
  264.     elseif dz < 0 then
  265.         turnTo(DIRECTIONS.north)
  266.     end
  267.  
  268.     for i=1, math.abs(dz) do
  269.         forceForward();
  270.     end
  271.  
  272.     for i=1, math.abs(dy) do
  273.         if dy > 0 then
  274.             forceUp();
  275.         else
  276.             forceDown();
  277.         end
  278.     end
  279.  
  280.     return true;
  281. end
  282.  
  283. local function inspectSurroundings()
  284.     local surroundings = {};
  285.    
  286.     local hasBlock, data = turtle.inspect();
  287.     surroundings["forward"] = {
  288.         hasBlock = hasBlock,
  289.         data = data
  290.     };
  291.  
  292.     local hasBlock, data = turtle.inspectUp();
  293.     surroundings["up"] = {
  294.         hasBlock = hasBlock,
  295.         data = data
  296.     };
  297.  
  298.     local hasBlock, data = turtle.inspectDown();
  299.     surroundings["down"] = {
  300.         hasBlock = hasBlock,
  301.         data = data
  302.     };
  303.  
  304.     turtle.turnLeft();
  305.     local hasBlock, data = turtle.inspect();
  306.     surroundings["left"] = {
  307.         hasBlock = hasBlock,
  308.         data = data
  309.     };
  310.     turtle.turnRight();
  311.  
  312.  
  313.     turtle.turnRight();
  314.     local hasBlock, data = turtle.inspect();
  315.     surroundings["right"] = {
  316.         hasBlock = hasBlock,
  317.         data = data
  318.     };
  319.     turtle.turnLeft();
  320.  
  321.     return surroundings;
  322. end
  323.  
  324. local function hasItem(itemName)
  325.     for i=1, 16 do
  326.         local itemDetail = turtle.getItemDetail(i);
  327.  
  328.         if itemDetail and itemDetail.name == itemName then
  329.             return true;
  330.         end
  331.     end
  332.  
  333.     return false;
  334. end
  335.  
  336. local function getItemCount(itemName)
  337.     local count = 0;
  338.     for i=1, 16 do
  339.         local itemDetail = turtle.getItemDetail(i);
  340.  
  341.         if itemDetail and itemDetail.name == itemName then
  342.             count = count + turtle.getItemCount(i);            
  343.         end
  344.     end
  345.  
  346.     return count;
  347. end
  348.  
  349. local function findItem(itemName)
  350.     for i=1, 16 do
  351.         local itemDetail = turtle.getItemDetail(i);
  352.  
  353.         if itemDetail and itemDetail.name == itemName then
  354.             return i;
  355.         end
  356.     end
  357.  
  358.     return -1;
  359. end
  360.  
  361. local function getPositionKey(position)
  362.     return string.format("%d,%d,%d", position.x, position.y, position.z);
  363. end
  364.  
  365. local function findTravelPath(startPosition, endPosition, allowedPositions)
  366.     if allowedPositions ~= nil and not allowedPositions[getPositionKey(endPosition)] then
  367.         return false, nil;
  368.     end
  369.  
  370.     local function isPositionEqual(pos1, pos2)
  371.         return pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z;
  372.     end
  373.  
  374.     local function isPositionAllowed(position)
  375.         return allowedPositions == nil or allowedPositions[getPositionKey(position)];
  376.     end
  377.  
  378.     local function getNeighbours(position)
  379.         local checkDirections = {
  380.             { x =  1, y =  0, z =  0 },
  381.             { x = -1, y =  0, z =  0 },
  382.             { x =  0, y =  1, z =  0 },
  383.             { x =  0, y = -1, z =  0 },
  384.             { x =  0, y =  0, z =  1 },
  385.             { x =  0, y =  0, z = -1 },
  386.         }
  387.  
  388.         local neighbours = {};
  389.  
  390.         for _, direction in ipairs(checkDirections) do
  391.             local neighbourPosition = {
  392.                 x = position.x + direction.x,
  393.                 y = position.y + direction.y,
  394.                 z = position.z + direction.z
  395.             }
  396.             if isPositionAllowed(neighbourPosition) then
  397.                 table.insert(neighbours, neighbourPosition);
  398.             end
  399.         end
  400.  
  401.         return neighbours;
  402.     end
  403.  
  404.     local queue = { { position = startPosition, path = { startPosition } } };
  405.     local visited = {};
  406.  
  407.     while #queue > 0 do
  408.         local current = table.remove(queue, 1);
  409.         local currentPosition = current.position;
  410.         local currentPath = current.path;
  411.  
  412.         local key = getPositionKey(currentPosition);
  413.  
  414.         if isPositionEqual(currentPosition, endPosition) then
  415.             return true, currentPath;
  416.         end
  417.  
  418.         if visited[key] then
  419.             goto continue
  420.         end
  421.  
  422.         visited[key] = true;
  423.  
  424.         for _, neighbour in ipairs(getNeighbours(currentPosition)) do
  425.             if not visited[getPositionKey(neighbour)] then
  426.                 local newPath = { table.unpack(currentPath) };
  427.                 table.insert(newPath, neighbour);
  428.                 table.insert(queue, { position = neighbour, path = newPath });
  429.             end
  430.         end
  431.  
  432.         ::continue::
  433.     end
  434.  
  435.     return false, nil;
  436. end
  437.  
  438. local function pathfindToPosition(startPosition, endPosition, allowedPositions)
  439.     local couldFindPath, path = findTravelPath(startPosition, endPosition, allowedPositions);
  440.  
  441.     if not couldFindPath or path == nil then
  442.         print("COULD NOT FIND PATH");
  443.         return false;
  444.     end
  445.  
  446.     for _, position in pairs(path) do
  447.         if not moveTo(position) then
  448.             return false;
  449.         end
  450.     end
  451.  
  452.     return true;
  453. end
  454.  
  455. return {
  456.     getPosition = getPosition,
  457.     getDirection = getDirection,
  458.     directions = DIRECTIONS,
  459.     directionDeltas = DIRECTION_DELTAS,
  460.     relativeDeltas = RELATIVE_DELTAS,
  461.     turnDirections = TURN_DIRECTIONS,
  462.     syncWithGPS = syncWithGPS,
  463.     forward = forward,
  464.     back = back,
  465.     up = up,
  466.     down = down,
  467.     forceForward = forceForward,
  468.     forceUp = forceUp,
  469.     forceDown = forceDown,
  470.     turn = turn,
  471.     turnTo = turnTo,
  472.     turnLeft = turnLeft,
  473.     turnRight = turnRight,
  474.     applyPositionDelta = applyPositionDelta,
  475.     applyDirectionDelta = applyDirectionDelta,
  476.     isPositionAdjacent = isPositionAdjacent,
  477.     hasEnoughFuel = hasEnoughFuel,
  478.     moveTo = moveTo,
  479.     inspectSurroundings = inspectSurroundings,
  480.     hasItem = hasItem,
  481.     getItemCount = getItemCount,
  482.     findItem = findItem,
  483.     getPositionKey = getPositionKey,
  484.     findTravelPath = findTravelPath,
  485.     pathfindToPosition = pathfindToPosition,
  486. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement