QuickMuffin8782-Alt

sturtle api clone

Dec 19th, 2020 (edited)
461
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[ smartTurtle API version 2.0 by seiterarch - Save as sTurtle.
  2. This is a complete overhaul of the sTurtle API - more integrity, less unavoidable sanity checking.
  3. Position tracking is now persistent, using the same basis as Minecraft.  The file "position" will be used.
  4. slot tracking is session-persistent starting from the first use of sTurtle.select
  5. bypass = true will skip input sterilization for most functions - this may cause errors.
  6.  
  7. License:  This code is completely free to use and distribute.  Attribution would be nice, but I'm not too bothered.]]
  8.  
  9. assert(turtle, "sTurtle must be loaded on a turtle.")
  10.  
  11. --Define position ring and slot tracking variable.
  12. --It might be worth re-factoring these with metatables, but this should be possible later without changing the interface.
  13. local pos = {0, 0, 0, 0}
  14. local currentSlot = 1
  15.  
  16. --Some useful values and tables
  17. local DIRECTIONS = {"forward", "right", "back", "left", "up", "down"}
  18. local FACES = {"front", "right", "back", "left", "top", "bottom"}
  19. local TIMEOUT = 20 --Number of failed attacks before a turtle gives up trying to move.  Roughly 10ths of a second.
  20.  
  21.  
  22. --[[ Utility Functions ]]
  23.  
  24. --Sterilization functions.  A bad argument causes false to be returned (to ease debugging).
  25. --If nil(or false) is passed then the default is returned.
  26. --Directions and faces are given by an entry of the respective list or the index of said entry.
  27. function nForm(n, default, modulus)        --Integers.  If modulus (an integer) is defined then result is modular.
  28.     if n then
  29.         n = tonumber(n)
  30.         if not n then return false end
  31.     else
  32.         return default
  33.     end
  34.    
  35.     n = math.floor(n)
  36.    
  37.     --Find the basis of n's equivalence class in Zmod(modulus)
  38.     if modulus then
  39.         m = nForm(modulus)
  40.         assert(m, "nForm received bad modulus argument")
  41.         n = n % m
  42.     end
  43.    
  44.     return n
  45. end
  46. function dirForm(dir, default)             --Cardinal directions.  
  47.     if dir then
  48.         for i=1, 6 do
  49.             if dir == i or dir == DIRECTIONS[i] then
  50.                 return DIRECTIONS[i]
  51.             end
  52.         end
  53.     else
  54.         return default
  55.     end
  56.    
  57.     return false
  58. end
  59. function faceForm(face, default)           --Computer faces.  Mostly useful for redstone.  
  60.     if face then
  61.         for i=1, 6 do
  62.             if face == i or face == FACES[i] then
  63.                 return FACES[i]
  64.             end
  65.         end
  66.     else
  67.         return default
  68.     end
  69.    
  70.     return false
  71. end
  72. function slotForm(slot, default)           --Inventory slot index.  Values outside the range return are mapped onto it in case you want to do math.
  73.     if slot then
  74.         slot = nForm(slot, default, 16)
  75.         if slot == 0 then slot = 16 end
  76.         return slot --false will be passed if nForm returned false
  77.     else
  78.         return default
  79.     end
  80. end
  81.  
  82. --Direction and face conversion and inversion functions may be useful. dirRev is for inverting the direction of a turn
  83. --If sterilization is bypassed, an argument of nil (or false) will pass through.
  84. function dirToFace(dir, bypass)
  85.     if not bypass then
  86.         dir = dirForm(dir)
  87.         assert(dir, "sTurtle.dirToFace received invalid argument")
  88.     elseif not dir then
  89.         return dir
  90.     end
  91.    
  92.     local face = nil
  93.     for i=1,6 do
  94.         if dir == DIRECTIONS[i] then
  95.             return FACES[i]
  96.         end
  97.     end
  98.    
  99.     error("sTurtle.dirToFace() received invalid argument")
  100. end
  101. function faceToDir(face, bypass)
  102.     if not bypass then
  103.         face = faceForm(face)
  104.         assert(face, "sTurtle.faceToDir() received invalid argument")
  105.     elseif not face then
  106.         return face
  107.     end
  108.    
  109.     for i=1,6 do
  110.         if face == FACES[i] then
  111.             return DIRECTIONS[i]
  112.         end
  113.     end
  114.    
  115.     error("sTurtle.faceToDir() received invalid argument")
  116. end
  117. function dirInv(dir, bypass)
  118.     if not bypass then
  119.         dir = dirForm(dir)
  120.         assert(dir, "sTurtle.dirInv received invalid argument")
  121.     end
  122.    
  123.     if dir == DIRECTIONS[1] then dir = DIRECTIONS[3]
  124.     elseif dir == DIRECTIONS[2] then dir = DIRECTIONS[4]
  125.     elseif dir == DIRECTIONS[3] then dir = DIRECTIONS[1]
  126.     elseif dir == DIRECTIONS[4] then dir = DIRECTIONS[2]
  127.     elseif dir == DIRECTIONS[5] then dir = DIRECTIONS[6]
  128.     elseif dir == DIRECTIONS[6] then dir = DIRECTIONS[5]
  129.     elseif dir then
  130.         error("sTurtle.dirInv received invalid argument")
  131.     end
  132.    
  133.     return dir
  134. end
  135. function faceInv(face, bypass)
  136.     if not bypass then
  137.         face = faceForm(face)
  138.         assert(face, "sTurtle.faceInv received invalid argument")
  139.     elseif not face then
  140.         return face
  141.     end
  142.    
  143.     --Convert argument to direction, invert and then return to face
  144.     return dirToFace(dirInv(faceToDir(face, true), true), true)
  145. end
  146. function dirRev(dir, bypass)
  147.     if not bypass then
  148.         dir = dirForm(dir)
  149.         assert(dir, "sTurtle.dirRev received invalid argument")
  150.     end
  151.    
  152.     if dir == DIRECTIONS[1] then dir = DIRECTIONS[1]
  153.     elseif dir == DIRECTIONS[2] then dir = DIRECTIONS[4]
  154.     elseif dir == DIRECTIONS[3] then dir = DIRECTIONS[3]
  155.     elseif dir == DIRECTIONS[4] then dir = DIRECTIONS[2]
  156.     elseif dir == DIRECTIONS[5] then dir = DIRECTIONS[5]
  157.     elseif dir == DIRECTIONS[6] then dir = DIRECTIONS[6]
  158.     elseif dir then
  159.         error("sTurtle.dirRev received invalid argument")
  160.     end
  161.    
  162.     return dir
  163. end
  164.  
  165. --Lets you change the default TIMEOUT if you so wish.  Not currently persistant across reboot.
  166. function setTIMEOUT(x)
  167.     TIMEOUT = nForm(x, TIMEOUT)
  168. end
  169.  
  170.  
  171. --[[ Data storage functions ]]
  172.  
  173. --Save and load functions for pos. Custom file names can be passed (excluding false and nil).
  174. --Intended to be used for storing common positions only; /position is continually updated.
  175. function savePos(name)
  176.     if name then
  177.         name = tostring(name)
  178.     else
  179.         name = "position"
  180.     end
  181.    
  182.     local f = fs.open(name, 'w')
  183.     f.write(textutils.serialize(pos))
  184.     f.close()
  185. end
  186. function loadPos(name)
  187.     if name then
  188.         name = tostring(name)
  189.     else
  190.         name = "position"
  191.     end
  192.    
  193.     assert(fs.exists(name), name .. " does not exist.")
  194.    
  195.     local f = fs.open(name, 'r')
  196.     pos = textutils.unserialize(f.readAll())
  197.     f.close()
  198.    
  199.     print("Position data loaded.")
  200. end
  201.  
  202. --Set and retrieve functions for pos
  203. --Passing nil for any of setPos' arguments causes them to remain as they were. (This also happens for invalid args.)
  204. function setPos(x, y, z, f)
  205.     pos[1] = nForm(x) or pos[1]
  206.     pos[2] = nForm(y) or pos[2]
  207.     pos[3] = nForm(z) or pos[3]
  208.     pos[4] = nForm(f, nil, 4) or pos[4]
  209.    
  210.     savePos()
  211. end
  212.  
  213. function getPos()
  214.     return pos[1], pos[2], pos[3], pos[4]
  215. end
  216.  
  217.  
  218. --[[ Movement Functions ]]
  219.  
  220. --Turn functions. Positions updated/saved before motion as this leaves the smallest window for failure.
  221. --turn() takes a direction (string) relative to current facing, or a number of right turns.
  222. function turn(dir, bypass)
  223.     if type(dir) == "number" then
  224.         dir = dirForm(nForm(dir, nil, 4) + 1)
  225.     elseif not bypass then
  226.         dir = dirForm(dir, "right")
  227.         assert(dir, "sTurtle.turn received an invalid argument.")
  228.     end
  229.    
  230.     if dir == 'right' then
  231.         pos[4] = (pos[4] + 1) % 4
  232.         savePos()
  233.         turtle.turnRight()
  234.     elseif dir == 'back' then
  235.         pos[4] = (pos[4] + 1) % 4
  236.         savePos()
  237.         turtle.turnRight()
  238.         pos[4] = (pos[4] + 1) % 4
  239.         savePos()
  240.         turtle.turnRight()
  241.     elseif dir == 'left' then
  242.         pos[4] = (pos[4] + 3) % 4
  243.         savePos()
  244.         turtle.turnLeft()
  245.     end
  246. end
  247.  
  248. --turnTo() takes destination f co-ord.
  249. function turnTo(f, bypass)
  250.     if not bypass then
  251.         f = nForm(f, 0)
  252.         assert(f, "sTurtle.turnTo received an invalid argument.")
  253.     end
  254.    
  255.     local diff = (f - pos[4]) % 4
  256.    
  257.     if diff == 1 then turn("right", true)
  258.     elseif diff == 2 then turn("back", true)
  259.     elseif diff == 3 then turn("left", true)
  260.     end
  261.    
  262.     savePos()
  263. end
  264.  
  265. --Basic cardinal direction movement.
  266. function forward(n, bypass)
  267.     --Sterilize inputs if bypass is not true.
  268.     if not bypass then
  269.         n = nForm(n, 1)
  270.         assert(n, "sTurtle.forward received an invalid argument.")
  271.     end
  272.    
  273.     for i=1, n do
  274.         if not(turtle.forward()) then
  275.             return false
  276.         end
  277.        
  278.         --Position tracking
  279.         if pos[4]==0 then pos[3] = pos[3]+1
  280.         elseif pos[4]==1 then pos[1] = pos[1]-1
  281.         elseif pos[4]==2 then pos[3] = pos[3]-1
  282.         elseif pos[4]==3 then pos[1] = pos[1]+1
  283.         end
  284.        
  285.         --Record movement
  286.         savePos()
  287.     end
  288.    
  289.     return true
  290. end
  291. function back(n, bypass)
  292.     if not bypass then
  293.         n = nForm(n, 1)
  294.         assert(n, "sTurtle.back received an invalid argument.")
  295.     end
  296.    
  297.     for i=1, n do
  298.         if not(turtle.back()) then
  299.             return false
  300.         end
  301.        
  302.         if pos[4]==0 then pos[3] = pos[3]+1
  303.         elseif pos[4]==1 then pos[1] = pos[1]-1
  304.         elseif pos[4]==2 then pos[3] = pos[3]-1
  305.         elseif pos[4]==3 then pos[1] = pos[1]+1
  306.         end
  307.         savePos()
  308.     end
  309.    
  310.     return true
  311. end
  312. function up(n, bypass)
  313.     if not bypass then
  314.         n = nForm(n, 1)
  315.         assert(n, "sTurtle.up received an invalid argument.")
  316.     end
  317.    
  318.     for i=1, n do
  319.         if not(turtle.up()) then
  320.             return false
  321.         end
  322.        
  323.         pos[2] = pos[2] + 1
  324.         savePos()
  325.     end
  326.    
  327.     return true
  328. end
  329. function down(n, bypass)
  330.     if not bypass then
  331.         n = nForm(n, 1)
  332.         assert(n, "sTurtle.down received an invalid argument.")
  333.     end
  334.    
  335.     for i=1, n do
  336.         if not(turtle.down()) then
  337.             return false
  338.         end
  339.        
  340.         pos[2] = pos[2] - 1
  341.         savePos()
  342.     end
  343.    
  344.     return true
  345. end
  346.  
  347. --Strafes
  348. function left(n, bypass)
  349.     if not bypass then
  350.         n = nForm(n, 1)
  351.         assert(n, "sTurtle.left received an invalid argument.")
  352.     end
  353.    
  354.     local result = false
  355.  
  356.     turn("left", true)
  357.     result = forward(n, true)
  358.     turn("right", true)
  359.  
  360.     return result
  361. end
  362. function right(n, bypass)
  363.     if not bypass then
  364.         n = nForm(n, 1)
  365.         assert(n, "sTurtle.right received an invalid argument.")
  366.     end
  367.  
  368.     local result = false
  369.  
  370.     turn("right", true)
  371.     result = forward(n, true)
  372.     turn("left", true)
  373.  
  374.     return result
  375. end
  376.  
  377. --Abbreviated versions of the above for ease of use and some backwards compatability
  378. function f(n, bypass)
  379.     return forward(n, bypass)
  380. end
  381. function b(n, bypass)
  382.     return back(n, bypass)
  383. end
  384. function u(n, bypass)
  385.     return up(n, bypass)
  386. end
  387. function d(n, bypass)
  388.     return down(n, bypass)
  389. end
  390. function l(n, bypass)
  391.     return left(n, bypass)
  392. end
  393. function r(n, bypass)
  394.     return right(n, bypass)
  395. end
  396.  
  397. --Destructive movement functions.  Return false if turtle encounters an immovable obstacle, otherwise true.
  398. --If an obstacle is encountered, turtle will attempt to dig or attack depending on the presence of blocks.
  399. function mine(n, bypass) --forward
  400.     if not bypass then
  401.         n = nForm(n, 1)
  402.         assert(n, "sTurtle.mine received an invalid argument.")
  403.     end
  404.    
  405.     local delay = 0
  406.    
  407.     for i=1, n do
  408.         while not forward(1, true) do
  409.             if turtle.detect() and not turtle.dig() then
  410.                 return false
  411.            
  412.             elseif not turtle.attack() then
  413.                 delay = delay + 1
  414.                 if delay >= TIMEOUT then
  415.                     return false
  416.                 end
  417.                 sleep(0.1)
  418.             end
  419.            
  420.         end
  421.         delay = 0
  422.     end
  423.    
  424.     return true
  425. end
  426. function mineUp(n, bypass)
  427.     if not bypass then
  428.         n = nForm(n, 1)
  429.         assert(n, "sTurtle.mineUp received an invalid argument.")
  430.     end
  431.    
  432.     local delay = 0
  433.    
  434.     for i=1, n do
  435.         while not up(1, true) do
  436.             if turtle.detectUp() and not turtle.digUp() then
  437.                 return false
  438.            
  439.             elseif not turtle.attackUp() then
  440.                 delay = delay + 1
  441.                 if delay >= TIMEOUT then
  442.                     return false
  443.                 end
  444.                 sleep(0.1)
  445.             end
  446.            
  447.         end
  448.         delay = 0
  449.     end
  450.    
  451.     return true
  452. end
  453. function mineDown(n, bypass)
  454.     if not bypass then
  455.         n = nForm(n, 1)
  456.         assert(n, "sTurtle.mineDown received an invalid argument.")
  457.     end
  458.    
  459.     delay = 0
  460.    
  461.     for i=1, n do
  462.         while not down(1, true) do
  463.             if turtle.detectDown() and not turtle.digDown() then
  464.                 return false
  465.                
  466.             elseif not turtle.attackDown() then
  467.                 delay = delay + 1
  468.                 if delay >= TIMEOUT then
  469.                     return false
  470.                 end
  471.                 sleep(0.1)
  472.             end
  473.            
  474.         end
  475.         delay = 0
  476.     end
  477.    
  478.     return true
  479. end
  480.  
  481.  
  482. --[[ Inventory functions ]]
  483.  
  484. --Select function that accepts nil for no change and keeps track of current slot.
  485. --Slot tracking is not persistent across reboot.
  486. function select(slot, bypass)
  487.     if not bypass then
  488.         slot = slotForm(slot)
  489.         if slot == false then
  490.             error("sTurtle.select received an invalid argument.")
  491.         end
  492.     end
  493.    
  494.     if not slot then return true end
  495.     local result = turtle.select(slot)
  496.     currentSlot = slot
  497.    
  498.     return result
  499. end
  500.  
  501. function getCurrentSlot()
  502.     return currentSlot
  503. end
  504.  
  505. --Pass an array of slots to to get the total itemCount across the array.  Duplicate entries counted twice. Nil allowed.
  506. function countAll(slotList, bypass)
  507.     assert(type(slotList) == "table", "sTurtle.countAll recieved non-array argument.")
  508.     if not bypass then
  509.         for i,slot in ipairs(slotList) do
  510.             slotList[i] = slotForm(slot)
  511.             if slotList[i] == false then
  512.                 error("sTurtle.countAll received an invalid argument.")
  513.             end
  514.         end
  515.     end
  516.    
  517.     local count = 0
  518.    
  519.     for i, slot in ipairs(slotList) do
  520.         count = count + turtle.getItemCount(slot)
  521.     end
  522.    
  523.     return count
  524. end
  525.  
  526. --Returns an array of slots with the same contents as the given slot.
  527. function getMatchingSlots(slot, bypass)
  528.     if not bypass then
  529.         slot = slotForm(slot)
  530.         if slot == false then
  531.             error("sTurtle.getMatchingSlots received an invalid argument.")
  532.         end
  533.     end
  534.    
  535.     --create some useful variables
  536.     local initialSlot = currentSlot
  537.     local nextIndex = 1
  538.     local slots = {}
  539.    
  540.     for i=1,16 do
  541.         if i ~= slot then
  542.             select(i, true)
  543.             if turtle.compareTo(slot) then
  544.                 slots[nextIndex] = i
  545.                 nextIndex = nextIndex + 1
  546.             end
  547.         else
  548.             slots[nextIndex] = i
  549.             nextIndex = nextIndex + 1
  550.         end
  551.     end
  552.    
  553.     --return to initial slot
  554.     select(initialSlot, true)
  555.     return slots
  556. end
  557.  
  558. --Extension of the drop functions.  drops count of items.  If count is negative, all but -count items in the slot are dropped.
  559. function deposit(dir, slot, count, bypass)
  560.     if not bypass then
  561.         dir = dirForm(dir, "forward")
  562.         slot = slotForm(slot, currentSlot)
  563.         count = nForm(count, 64)
  564.         assert(dir and slot and count, "sTurtle.deposit received an invalid argument.")
  565.     end
  566.    
  567.     local initialSlot = currentSlot
  568.     local toDrop = nil
  569.    
  570.     if count >= 0 then
  571.         toDrop = count
  572.     else
  573.         toDrop = turtle.getItemCount(slot) + count
  574.     end
  575.    
  576.     --save time if nothing is to be dropped
  577.     if toDrop <= 0 then return true end
  578.    
  579.     turn(dir, true)
  580.     select(slot, true)
  581.    
  582.     if dir == "up" then
  583.         turtle.dropUp(toDrop)
  584.     elseif dir == "down" then
  585.         turtle.dropDown(toDrop)
  586.     else
  587.         turtle.drop(toDrop)
  588.     end
  589.    
  590.     select(initialSlot, true)
  591.     turn(dirRev(dir, true), true)
  592.     return true
  593. end
  594.  
  595. --Deposit all matching items.  keepOne = true keeps a single item in the specified slot
  596. function depositAll(dir, slot, keepOne, bypass)
  597.     if not bypass then
  598.         dir = dirForm(dir, "forward")
  599.         slot = slotForm(slot, currentSlot)
  600.         assert(dir and slot, "sTurtle.depositAll received an invalid argument.")
  601.     end
  602.    
  603.     local initialSlot = currentSlot
  604.     local slotList = getMatchingSlots(slot, true)
  605.     local dir2 = dir
  606.    
  607.     if countAll(slotList, true) == 0 then return true end
  608.    
  609.     --dir2 is the direction to pass into the deposit subFunction.  The turtle will have already turned.
  610.     if dir2 == DIRECTIONS[2] then dir2 = DIRECTIONS[1]
  611.     elseif dir2 == DIRECTIONS[3] then dir2 = DIRECTIONS[1]
  612.     elseif dir2 == DIRECTIONS[4] then dir2 = DIRECTIONS[1]
  613.     end
  614.    
  615.     turn(dir, true)
  616.    
  617.     --Iterate through the list of slots with matching contents
  618.     for i, s in ipairs(slotList) do
  619.         select(s, true)
  620.         if s ~= slot or not keepOne then
  621.             deposit(dir2, s, 64, true)
  622.         else
  623.             --leave one item in the slot if it is the selected slot and keepOne is true
  624.             deposit(dir2, s, -1, true)
  625.         end
  626.     end
  627.    
  628.     select(initialSlot, true)
  629.     turn(dirRev(dir, true), true)
  630.     return true
  631. end
  632.  
  633.  
  634. --[[ Extension functions ]]
  635.  
  636. --If detect is given a valid slot argument, it will compare to the item in that slot.
  637. function detect(dir, slot, bypass)
  638.     if not bypass then
  639.         dir = dirForm(dir, "front")
  640.         slot = slotForm(slot, currentSlot)
  641.         assert(dir and slot, "sTurtle.detect received an invalid argument.")
  642.     end
  643.    
  644.     if not slot then
  645.         assert(turtle.getItemCount(slot), "Detect cannot compare to an empty slot.")
  646.     end
  647.    
  648.     local initialSlot = currentSlot
  649.     local isTrue = false
  650.     turn(dir, true)
  651.    
  652.     detected = false
  653.     if slot then
  654.         select(slot, true)
  655.        
  656.         if dir == "up" then
  657.             detected = turtle.compareUp()
  658.         elseif dir == down then
  659.             detected = turtle.compareDown()
  660.         else
  661.             detected = turtle.compare()
  662.         end
  663.     else
  664.         if dir == "up" then
  665.             detected = turtle.detectUp()
  666.         elseif dir == down then
  667.             detected = turtle.detectDown()
  668.         else
  669.             detected = turtle.detect()
  670.         end
  671.     end
  672.    
  673.     select(initialSlot, true)
  674.     turn(dirRev(dir, true), true)
  675.     return detected
  676. end
  677.  
  678. --dig() will attempt to account for sand/gravel at the cost of a little extra time.
  679. function dig(dir, bypass)
  680.     if not bypass then
  681.         dir = dirForm(dir, "forward")
  682.         assert(dir, "sTurtle.dig received an invalid argument.")
  683.     end
  684.    
  685.     turn(dir, true)
  686.    
  687.     if dir == "down" and turtle.detectDown() then
  688.         turtle.digDown()
  689.     elseif dir == "up" then
  690.         while turtle.detectUp() do
  691.             turtle.digUp()
  692.             sleep(0.1)
  693.         end
  694.     else
  695.         while turtle.detect() do
  696.             turtle.dig()
  697.             sleep(0.1)
  698.         end
  699.     end
  700.    
  701.     turn(dirRev(dir, true), true)
  702. end
  703.  
  704. --Places a block from the given slot in the direction specified.  If slot is nil, the currently selected slot is used.
  705. --If replace is false/nil, currently present blocks will to be replaced.  signText only relevant when placing to a side.
  706. --Will not place if the block in the position is of the same type as that being placed.
  707. function place(dir, slot, replace, bypass, signText)
  708.     if not bypass then
  709.         dir = dirForm(dir, "forward")
  710.         slot = slotForm(slot, currentSlot)
  711.         assert(dir and slot, "sTurtle.place received an invalid argument.")
  712.     end
  713.    
  714.     local result = false
  715.     local initialSlot = currentSlot
  716.    
  717.     turn(dir, true)
  718.     select(slot, true)
  719.    
  720.     if dir == "up" then
  721.         if turtle.detectUp() then
  722.             if replace and not turtle.compareUp() then
  723.                 dig("up", true)
  724.                 result = turtle.placeUp()
  725.             else
  726.                 result = true
  727.             end
  728.         else
  729.             result = turtle.placeUp()
  730.         end
  731.        
  732.     elseif dir == "down" then
  733.         if turtle.detectDown() then
  734.             if replace and not turtle.compareDown() then
  735.                 dig("down", true)
  736.                 result = turtle.placeDown()
  737.             else
  738.                 result = true
  739.             end
  740.         else
  741.             result = turtle.placeDown()
  742.         end
  743.    
  744.     else
  745.         if turtle.detect() then
  746.             if replace and not turtle.compare() then
  747.                 dig("forward", true)
  748.                 result = turtle.place(signText)
  749.             else
  750.                 result = true
  751.             end
  752.         else
  753.             result = turtle.place()
  754.         end
  755.     end
  756.    
  757.     select(initialSlot, true)
  758.     turn(dirRev(dir, true), true)
  759.     return result
  760. end
  761.  
  762.  
  763. --[[ GPS interaction (requires modem) ]]
  764.  
  765. --Function to find partial co-ordinates after a reboot by utilising GPS.  Useful for high-motion systems
  766. --that may have been part-way through a move during reboot.  Uses the saved value of f.
  767. function gpsLocate()
  768.     loadPos()
  769.  
  770.     local p1 = vector.new(gps.locate(5))
  771.     if p1.x == nil then
  772.         print("Failed to find GPS signal.  Using prior co-ordinates")
  773.         return false
  774.     end
  775.    
  776.     setPos(p1.x, p1.y, p1.z, nil)  
  777.     return true
  778. end
  779.    
  780. --More robust function to find full co-ordinates via GPS.
  781. function gpsInit()
  782.     local p1 = vector.new(gps.locate(5))
  783.     if p1.x == nil then
  784.         print("Failed to find GPS signal.  Using prior co-ordinates")
  785.         return false
  786.     end
  787.    
  788.     local hasMoved = false
  789.     for i=1, 4 do
  790.         if forward(1, true) then
  791.             hasMoved = true
  792.             break
  793.         else
  794.             turn("right", true)
  795.         end
  796.     end
  797.     if not hasMoved then
  798.         print("Turtle must be able to move in order to get co-ordinate data")
  799.         return false
  800.     end
  801.    
  802.     local p2 = vector.new(gps.locate(5))
  803.     if p2.x == nil then
  804.         print("Failed to find GPS signal.  Using prior co-ordinates")
  805.         init()
  806.         return false
  807.     end
  808.    
  809.     --Find the co-ordinate difference caused by movement
  810.     p1 = p2:sub(p1)
  811.    
  812.     local f = 0
  813.     assert(p1.y == 0, "Critical GPS network failure: poorly defined co-ordinates.")
  814.     if p1.x == 1 and p1.z == 0 then
  815.         f = 3
  816.     elseif p1.x == -1 and p1.z == 0 then
  817.         f = 1
  818.     elseif p1.x == 0 and p1.z == 1 then
  819.         f = 0
  820.     elseif p1.x == 0 and p1.z == -1 then
  821.         f = 2
  822.     else
  823.         error("Critical GPS network failure: poorly defined co-ordinates.")
  824.     end
  825.    
  826.     setPos(p2.x, p2.y, p2.z, f)
  827.     select(1, true)
  828.     return true
  829. end
  830.    
  831. --Simple GPS host setup using internal co-ordinates.  Warning: Internal co-ordinates are not necessarily synchronised other hosts.
  832. function gpsHost()
  833.     shell.run("gps", "host", pos[1], pos[2], pos[3])
  834. end
  835.  
  836.  
  837. --[[ Other ]]
  838. --Initialize function.  Not strictly necessary, but highly suggested.  "gpsInit() select(1, true)" also works.
  839. function init()
  840.     --Create or retrieve position data
  841.     if fs.exists("position") then
  842.         loadPos()
  843.     else
  844.         savePos()
  845.     end
  846.    
  847.     select(1, true)
  848. end
Add Comment
Please, Sign In to add comment