Inksaver

tk.lua toolkit (requires libs):2023/10/05

Apr 20th, 2020 (edited)
3,972
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 422.98 KB | None | 0 0
  1. version = 20231005.1900
  2.  
  3. local tkVersion = version -- otherwise over-written by clsTurtle when loaded
  4. --[[
  5.     **********Toolkit v2**********
  6.     https://pastebin.com/UFvjc1bw
  7.     Last edited: see version YYYYMMDD.HHMM
  8.     if NOT online:
  9.         Make sure you create a folder 'lib' and place menu.lua and clsTurtle.lua into it
  10.     else
  11.         lib folder will be created and files obtained automatically!
  12.     end
  13. ]]
  14.  
  15. args = {...} -- eg "farm", "tree"
  16.  
  17. local menu, T
  18. --[[
  19. Computercraft started with mc version 1.7.10 and went to 1.8.9
  20. ccTweaked started around mc 1.12.2 and currently at 1.18
  21. mc 1.18 has new blocks and bedrock at -64, so needs to be taken into account.
  22. _HOST = The ComputerCraft and Minecraft version of the current computer environment.
  23. For example, ComputerCraft 1.93.0 (Minecraft 1.15.2).
  24. ]]
  25. local dbug = false -- debug is reserved word
  26. local bedrock = 0
  27. local netherBedrock = 0
  28. local ceiling = 255
  29. local deletesWater = false
  30. local brick = "minecraft:nether_brick" -- pre 1.16+ name
  31. local ccMajorVersion = _HOST:sub(15, _HOST:find("Minecraft") - 2) --eg ComputerCraft 1.93.0 (Minecraft 1.15.2)
  32. local ccMinorVersion = 0
  33. --[[
  34. Netherite level stand on 14
  35. Chunk borders F3+G or:
  36. math.floor(x / 16) * 16 add 16 for each border. same for z
  37. ]]
  38. function string:split(sSeparator, nMax, bRegexp, noEmpty)
  39.     --[[return a table split with sSeparator. noEmpty removes empty elements
  40.         use: tblSplit = SplitTest:split('~',[nil], [nil], false) or tblSplit = string.split(SplitTest, '~')]]  
  41.     assert(sSeparator ~= '','separator must not be empty string')
  42.     assert(nMax == nil or nMax >= 1, 'nMax must be >= 1 and not nil')
  43.     if noEmpty == nil then noEmpty = true end
  44.  
  45.     local aRecord = {}
  46.     local newRecord = {}
  47.     -- self refers to the 'string' being split
  48.     if self:len() > 0 then
  49.         local bPlain = not bRegexp
  50.         nMax = nMax or -1
  51.  
  52.         local nField, nStart = 1, 1
  53.         local nFirst,nLast = self:find(sSeparator, nStart, bPlain)
  54.         while nFirst and nMax ~= 0 do
  55.             aRecord[nField] = self:sub(nStart, nFirst-1)
  56.             nField = nField+1
  57.             nStart = nLast+1
  58.             nFirst,nLast = self:find(sSeparator, nStart, bPlain)
  59.             nMax = nMax-1
  60.         end
  61.         aRecord[nField] = self:sub(nStart)
  62.        
  63.         if noEmpty then --split on newline preserves empty values
  64.             for i = 1, #aRecord do
  65.                 if aRecord[i] ~= "" then
  66.                     table.insert(newRecord, aRecord[i])
  67.                 end
  68.             end
  69.         else
  70.             newRecord = aRecord
  71.         end
  72.     end
  73.    
  74.     return newRecord
  75. end
  76.  
  77. if tonumber(ccMajorVersion) == nil then -- 1.93.0 NAN
  78.     --ccMajorVersion = ccMajorVersion:sub(1, ccMajorVersion:find(".", 3, true) - 1)
  79.     local parts = ccMajorVersion:split(".")
  80.     ccMajorVersion = parts[1]
  81.     if parts[2] ~= nil then
  82.         ccMajorVersion = ccMajorVersion.."."..parts[2]
  83.     end
  84.     ccMajorVersion = tonumber(ccMajorVersion)
  85.     if parts[3] ~= nil then
  86.         ccMinorVersion = tonumber(parts[3])
  87.     end
  88. end
  89.  
  90. local mcMajorVersion = _HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 1) -- eg 1.18 or 1.20 -> 1.18, 1.20
  91. local mcMinorVersion = 0
  92. if tonumber(mcMajorVersion) == nil then -- 1.18.3 NAN
  93.     --mcMajorVersion = tonumber(_HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 3)) -- eg 1.19.4 -> 1.19
  94.     local parts = mcMajorVersion:split(".")
  95.     mcMajorVersion = parts[1]
  96.     if parts[2] ~= nil then
  97.         mcMajorVersion = mcMajorVersion.."."..parts[2]
  98.     end
  99.     mcMajorVersion = tonumber(mcMajorVersion)
  100.     if parts[3] ~= nil then
  101.         mcMinorVersion = tonumber(parts[3])
  102.     end
  103. end
  104.  
  105. if mcMajorVersion < 1.7  and mcMajorVersion >= 1.18 then -- 1.12 to 1.??
  106.     bedrock = -64
  107.     ceiling = 319
  108. end
  109. if mcMajorVersion < 1.7  and mcMajorVersion >= 1.16 then -- 1.12 to 1.??
  110.     brick = "minecraft:nether_bricks"
  111. end
  112. if mcMajorVersion < 1.7  and mcMajorVersion <= 1.12 then --- turtle in source deletes it. 1.7.10 to 1.12
  113.     deletesWater = true
  114. end
  115.  
  116. local utils = {}
  117.  
  118. function utils.tableConcat(tbl, sep)
  119.     local output = ""
  120.     for i,value in pairs(tbl) do
  121.         output = output .. tostring(value)
  122.         if i ~= #tbl then
  123.             output = output .. sep
  124.         end
  125.     end
  126.  
  127.     return output
  128. end
  129.  
  130. function utils.calculateDimensions(R)
  131.     if R.data == "" then -- not being called from other functions
  132.         if R.width == 0 then -- user chose auto settings
  133.             R.length = utils.calculateDistance(R.length) -- still facing forward
  134.             print("Calculated Length = "..R.length)
  135.             T:turnRight(1) -- ready to check width
  136.             R.width = utils.calculateDistance(R.width) -- now facing right
  137.             print("Calculated width = "..R.width)
  138.             T:go("R2F"..R.width - 1 .."L1".. "F"..R.length - 1 .."R2") -- back at start. width/length confirmed
  139.         end
  140.     end
  141.     if R.height == 0 then -- use auto settings based on water detection
  142.         R.height = 64
  143.     end
  144.     return R
  145. end
  146.  
  147. function utils.calculateDistance(estDistamcMajorVersionnce)
  148.     --[[
  149.     measure length
  150.     movement stops when either solid block in front or solid below
  151.     called from utils.calculateDimensions
  152.     ]]
  153.     local moves = 1
  154.     local nonSolidBelow = utils.clearVegetation("down")
  155.     if estDistance == 0 then
  156.         while nonSolidBelow and turtle.forward() do -- while able to move and air/water below
  157.             moves = moves + 1
  158.             nonSolidBelow = utils.clearVegetation("down")
  159.         end
  160.     else
  161.         while moves < estDistance * 2 do -- loop can only run for max of double estimated distance
  162.             if turtle.forward() then -- able to move forward
  163.                 moves = moves + 1
  164.             else
  165.                 break
  166.             end
  167.             if not utils.clearVegetation("down") then -- solid below
  168.                 turtle.back()
  169.                 moves = moves - 1
  170.                 break
  171.             end
  172.         end
  173.     end
  174.     return moves
  175. end
  176.  
  177. function utils.checkFuelNeeded(quantity)
  178.     local fuelNeeded = quantity - turtle.getFuelLevel() -- eg 600
  179.     if fuelNeeded > 0 then
  180.         if T:checkInventoryForItem({"minecraft:lava_bucket"}, {1}, false) == nil then  
  181.             if T:checkInventoryForItem({"coal"}, {math.ceil(fuelNeeded / 60)}, false) == nil then
  182.                 T:checkInventoryForItem({"planks"}, {math.ceil(fuelNeeded / 15)})
  183.             end
  184.         end
  185.         T:refuel(quantity, true)
  186.     end
  187. end
  188.  
  189. function utils.clearVegetation(direction)
  190.     local isAirWaterLava = true -- default true value air/water/lava presumed
  191.     -- blockType, blockModifier, data
  192.     local blockType, blockModifier = T:getBlockType(direction)
  193.     if blockType ~= "" then --not air
  194.         if T:isVegetation(blockType) then
  195.             T:dig(direction)
  196.         elseif blockType:find("water") == nil
  197.                and blockType:find("lava") == nil
  198.                and blockType:find("bubble") == nil
  199.                and blockType:find("ice") == nil then
  200.             -- NOT water, ice or lava
  201.             isAirWaterLava = false -- solid block
  202.         end
  203.     end
  204.    
  205.     return isAirWaterLava --clears any grass or sea plants, returns true if air or water, bubble column or ice
  206. end
  207.  
  208. function utils.createPath(R) -- 51
  209.     --[[places a path in air/lava/water. R can also be of type int]]
  210.     local length = 0
  211.     local reduce = false
  212.     local torchInterval = 8
  213.     if type(R) == "table" then
  214.         length = R.length
  215.         if R.data == "reduce" then
  216.             reduce = true
  217.         end
  218.         torchInterval = R.torchInterval
  219.     else
  220.         length = R
  221.     end
  222.     local numBlocks = 0
  223.    
  224.     if reduce then
  225.         T:forward(1)
  226.         local blockType = T:getBlockType("down")
  227.         local useBlock = blockType
  228.         while blockType == useBlock do
  229.             T:go("x2F1")
  230.             numBlocks = numBlocks + 1
  231.             blockType = T:getBlockType("down")
  232.         end
  233.         utils.goBack(numBlocks + 1)
  234.     else
  235.         for i = 1, 2 do
  236.             T:fillVoid("down", {}, false)
  237.             T:forward(1)
  238.             numBlocks = numBlocks + 1
  239.         end
  240.         local place = utils.clearVegetation("down")
  241.         while place do -- while air, water, normal ice, bubble column or lava below
  242.             if T:fillVoid("down", {}, false) then -- false if out of blocks
  243.                 T:forward(1)
  244.                 numBlocks = numBlocks + 1
  245.                 if numBlocks % torchInterval == 1 or numBlocks == 0 then
  246.                     if T:getItemSlot("minecraft:torch", -1) > 0 then
  247.                         T:turnRight(2)
  248.                         T:place("minecraft:torch", -1, "forward", false)
  249.                         T:turnRight(2)
  250.                     end
  251.                 end
  252.             else
  253.                 break
  254.             end
  255.             if length > 0 and numBlocks >= length then -- not infinite path (length = 0)
  256.                 break
  257.             end
  258.             place = utils.clearVegetation("down")
  259.         end
  260.     end
  261.     return {numBlocks} -- returned as a table in case called as task 51 back to main()
  262. end
  263.  
  264. function utils.createWalledSpace(D)
  265.     --[[
  266.     D.width  = #
  267.     D.length = #
  268.     D.height = #
  269.     D.ceiling = false
  270.     D.floor = false
  271.     D.vDirection = "U" or "D"
  272.     D.hDirection = "LR" or "RL"
  273.     D.goHome = true
  274.     T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  275.     ]]
  276.     local turn  = "R1"
  277.     local oTurn = "L1"
  278.     if D.hDirection == "RL" then
  279.         turn    = "L1"
  280.         oTurn   = "R1"
  281.     end
  282.     local placeF = "C1"
  283.  
  284.     local lib = {}
  285.    
  286.     function lib.getPlace(D, start, finish)
  287.         if start then                       -- start of build
  288.             if D.vDirection == "U" then     -- bottom and going up
  289.                 if D.floor then
  290.                     return "C2"
  291.                 end
  292.             else                            -- D.vDirection == "D"
  293.                 if D.ceiling then
  294.                     return "C0"
  295.                 end
  296.             end
  297.         elseif finish then                  -- end of build
  298.             if D.vDirection == "U" then     -- bottom and going up
  299.                 if D.ceiling then
  300.                     return "C0"
  301.                 end
  302.             else
  303.                 if D.floor then
  304.                     return "C2"
  305.                 end
  306.             end
  307.         end
  308.  
  309.         return ""                           -- start and finish both false
  310.     end
  311.    
  312.     function lib.layer(D, start, finish)
  313.         local outward = true
  314.         local place = lib.getPlace(D, start, finish)
  315.         for width = 1, D.width do
  316.             for length = 1, D.length do
  317.                 if start or finish then
  318.                     T:go(place, false, 0, true)-- place floor / ceiling
  319.                 end
  320.                 if width == 1 then
  321.                     T:go(oTurn..placeF..turn, false, 0, true)       -- face wall and check if block
  322.                 elseif width == D.width then                        -- checking opposite wall
  323.                     if outward then                                 -- travelling away from start
  324.                         T:go(turn..placeF..oTurn, false, 0, true)   -- face wall and check if block
  325.                     else                                            -- travelling towards start
  326.                         T:go(oTurn..placeF..turn, false, 0, true)   -- face wall and check if block
  327.                     end                
  328.                 end
  329.                 -- move forward
  330.                 if length < D.length then
  331.                     T:forward(1)
  332.                 end
  333.             end
  334.             if width < D.width then
  335.                 -- change direction
  336.                 if outward then
  337.                     T:go(placeF..turn.."F1"..oTurn..place..placeF..turn..turn, false, 0, true)
  338.                 else
  339.                     T:go(placeF..oTurn.."F1"..turn..place..placeF..oTurn..oTurn, false, 0, true)
  340.                 end
  341.                 outward = not outward
  342.             else
  343.                 if outward then
  344.                     T:go(placeF..oTurn.."F"..D.width -1 ..oTurn.."F"..D.length - 1 .."C1R2", false, 0, true)
  345.                 else
  346.                     T:go(placeF..turn.."F"..D.width -1 ..oTurn..placeF..turn..turn, false, 0, true)
  347.                 end
  348.             end
  349.         end
  350.     end
  351.    
  352.     T:go("R2"..placeF.."R2", false, 0, true)            -- place block behind
  353.     for height = 1, D.height do
  354.         if height == 1 then
  355.             lib.layer(D, true, false)                   -- first layer, so start = true, finish = false
  356.         elseif height == D.height then     
  357.             lib.layer(D, false, true)                   -- final layer, so start = false, finish = true
  358.         else
  359.             lib.layer(D, false, false)                  -- mid build layer, so start = false, finish = false
  360.         end
  361.         if height < D.height then                       -- go up or down unless finished build
  362.             T:go(D.vDirection.."1")
  363.         end
  364.     end
  365.     if D.goHome then-- ends at starting point
  366.         if D.vDirection == "U" then
  367.             T:down(D.height - 1)
  368.         else
  369.             T:up(D.height - 1)
  370.         end
  371.     end
  372. end
  373.  
  374. function utils.createWaterSource(level)
  375.     if level == nil then
  376.         level = 0
  377.     end
  378.     if level > 0 then
  379.         T:up(level)
  380.     elseif level < 0 then
  381.         T:down(math.abs(level))
  382.     end
  383.     -- assume on flat surface, but allow for blocks above
  384.     T:go("x0C2F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2", false, 0, false)
  385.     T:go("R1F1D1", false, 0, false) --move to corner and drop down
  386.     T:go("C2F1R1 C2F1R1 C2F1R1 C2F1R1", false, 0, false)
  387.     T:go("U1")
  388.     for i = 1, 2 do
  389.         T:placeWater("down")
  390.         T:go("F1R1F1R1", false, 0, false)
  391.     end
  392.     -- refill water buckets
  393.     for i = 1, 2 do
  394.         sleep(0.5)
  395.         T:placeWater("down")
  396.     end
  397.     T:go("R2F1R1F1R1")
  398.     -- end above lower left of pond (starting point)
  399.     return {}
  400. end
  401.  
  402. function utils.drainWaterLava(R) -- 84
  403.     local lib = {}
  404.        
  405.     function lib.startCorner()
  406.         -- assume starting mid 3 high column
  407.         T:go("D1C1R1C1 U1C1 L1C1 U1C1 R1C1 L1D1 C2C0", false, 0, true)
  408.         -- finished on same mid 3 high column with wall in front and right completed
  409.     end
  410.    
  411.     function lib.midWall()
  412.         -- assume starting mid 3 high column
  413.         T:go("D1R1C1 U1C1 U1C1 L1D1 C2C0", false, 0, true)
  414.         -- finished on same mid 3 high column with wall on right completed
  415.     end
  416.    
  417.     function lib.endCorner()
  418.         -- assume starting mid 3 high column
  419.         T:go("D1R1C1 R1C1 U1C1 L1C1 U1C1 R1C1 L2D1 C2C0", false, 0, true)
  420.         -- finished on same mid 3 high column with wall behind and right completed
  421.     end
  422.    
  423.     function lib.backTurn(offset)
  424.         -- assume starting mid 3 high column with completed wall behind
  425.         T:go("L1F"..offset.."L2C1 R1D1C1 U1C1 U1C1 D1")
  426.         -- end next row along the width, facing the back, mid point
  427.         -- wall ahead completed
  428.     end
  429.    
  430.     function lib.frontTurn()
  431.         -- assume starting mid 3 high column facing back
  432.         -- next move is to turn toward previous wall and remove
  433.  
  434.         T:go("L2D1C1 U1C1 U1C1 D1R1 C2C0 F1R2C1 L1")
  435.         -- end facing back ready to remove wall
  436.     end
  437.    
  438.     function lib.placeRetainingWall(distance)
  439.         -- assume starting above 3 block high area facing front (player)
  440.         --T:down(1)
  441.         for i = 1, distance do
  442.             if i == 1 then -- start wall
  443.                 lib.startCorner()
  444.             else
  445.                 if i < distance then -- mid wall
  446.                     lib.midWall()
  447.                 else -- end of the wall
  448.                     lib.endCorner()
  449.                 end
  450.             end
  451.             if i < distance then
  452.                 if not turtle.back() then
  453.                     T:go("R2F1R2")
  454.                 end
  455.                 T:go("C1", false, 0, true)
  456.             end
  457.         end
  458.         return 1
  459.     end
  460.        
  461.     function lib.placeDam(distance)
  462.         --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  463.         local waterPresent = false
  464.         for i = 1, distance do
  465.             if T:isWater("down") then
  466.                 waterPresent = true
  467.             end
  468.             T:go("C0C2")
  469.             if i < distance then
  470.                 if not turtle.back() then
  471.                     T:go("R2F1R2")
  472.                 end
  473.                 T:go("C1", false, 0, true)
  474.             end
  475.         end
  476.         return waterPresent
  477.     end
  478.    
  479.     function lib.removeDam(distance)
  480.         -- facing towards back, dig wall up down and ahead
  481.         for i = 1, distance do
  482.             T:go("x0x2")
  483.             if i < distance then
  484.                 T:forward(1)
  485.             end
  486.         end
  487.         T:turnRight(2)
  488.         -- end up back to retaining wall, mid point
  489.     end
  490.    
  491.     if R.data == "" then
  492.         if turtle.detectDown() then -- on solid surface
  493.             turtle.forward()
  494.         end
  495.     end
  496.     if deletesWater then --turtle replaces source so use clearSolid()
  497.         R.silent = true
  498.         R.down = true
  499.         R.up = false
  500.         clearSolid(R)
  501.     else -- mc 1.12.15+ turtle does NOT replace source blocks
  502.         -- place first stone along the length of water and measure length
  503.         R = utils.calculateDimensions(R)
  504.         local depth = 0
  505.         for h = 1, R.height do
  506.             local waterPresent = false -- resets at each level
  507.             local row = 0
  508.             T:go("R2D2", false, 0, true)    -- at start, level 2, facing towards the front, move backards
  509.             --lib.startCorner()
  510.             row = row + lib.placeRetainingWall(R.length)
  511.             lib.backTurn(1)
  512.             if lib.placeDam(R.length) then
  513.                 waterPresent = true
  514.             end
  515.             row = row + 1
  516.             -- left side wall has been built, 2 rows of walls laid. row = 2
  517.             while row < R.width - 1 do -- eg width=2, row=2, this will not run. width=5, row=2
  518.                 lib.frontTurn()
  519.                 lib.removeDam(R.length)
  520.                 lib.backTurn(2)
  521.                 if lib.placeDam(R.length) then
  522.                     waterPresent = true
  523.                 end
  524.                 row = row + 1
  525.             end
  526.             -- lay right wall
  527.             lib.frontTurn()
  528.             lib.removeDam(R.length)
  529.             lib.backTurn(2)
  530.             row = row + lib.placeRetainingWall(R.length)
  531.             lib.frontTurn()
  532.             lib.removeDam(R.length) -- faces to front on finish
  533.             T:go("L1F1R1")
  534.             lib.removeDam(R.length) -- faces to front on finish
  535.             depth = depth + 3
  536.             T:go("L1F"..R.width - 1 .."R1D1")
  537.             if depth == R.height or not waterPresent then -- still replacing water
  538.                 T:up(depth - 1) -- when h == R.height will go up
  539.                 break -- in case water dries up before loop has completed
  540.             end
  541.         end
  542.     end
  543.     return {}
  544. end
  545.  
  546. function utils.dropSand()
  547.     while not turtle.detectDown() do -- over water. will be infinite loop if out of sand
  548.         if not T:place("sand", -1, "down", false) then
  549.             print("Out of sand. Add more to continue...")
  550.             sleep(2)
  551.         end
  552.     end
  553.     return true --will only get to this point if turtle.detectDown() = true
  554. end
  555.  
  556. function utils.pause(R)
  557.     --[[
  558.     allows 2 turtles to co-operate
  559.     When they face each other and move together
  560.     R.side = "R" or "L"
  561.     ]]
  562.     local rsIn = rs.getAnalogueInput("front")
  563.     local rsOut = 1
  564.     local present = false
  565.     local confirmed = false
  566.     local timer = 0
  567.     local endTimer = 0
  568.     local finished = false
  569.     T:go(R.side.."1")
  570.     rs.setAnalogueOutput("front", 0) -- switch off output
  571.     local blockType = T:getBlockType("forward")
  572.     while blockType:find("turtle") == nil do
  573.         menu.colourWrite("Waiting for other turtle "..endTimer, colors.orange, nil, nil, false, true)
  574.         blockType = T:getBlockType("forward")
  575.         sleep(0.1)
  576.         timer = timer + 0.1
  577.         if timer >= 1 then
  578.             timer = 0
  579.             endTimer = endTimer + 1
  580.         end
  581.     end
  582.     timer = 0
  583.     endTimer = 0
  584.    
  585.     while not finished do
  586.         if endTimer == 0 then
  587.             if present then
  588.                 if confirmed then
  589.                     menu.colourWrite("Turtle confirmed: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
  590.                 else
  591.                     menu.colourWrite("Other turtle ok: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
  592.                 end
  593.             else
  594.                 menu.colourWrite("Waiting: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
  595.             end
  596.         end
  597.         sleep(0.1)
  598.         timer = timer + 1
  599.         if endTimer > 0 then
  600.             endTimer = endTimer + 1
  601.         end
  602.         if endTimer >= 10 then -- allows time for other computer to get ready
  603.             finished = true
  604.         end
  605.         rs.setAnalogueOutput("front", 1) -- output 1 as a signal initially
  606.         if present then
  607.             rs.setAnalogueOutput("front", rsOut) -- output 1 as a signal initially
  608.         end
  609.         rsIn = rs.getAnalogueInput("front")
  610.         if rsIn == 1 then
  611.             present = true
  612.             if not confirmed then
  613.                 rsOut = 7
  614.             end
  615.         elseif rsIn == 7 then
  616.             present = true
  617.             confirmed = true
  618.             rsOut = 15
  619.         elseif rsIn == 15 or confirmed then
  620.             menu.colourWrite("endTimer active = "..endTimer, colors.orange, nil, nil, false, true)
  621.             endTimer = endTimer + 1 -- start endTimer
  622.         end
  623.     end
  624.     T:go(R.side.."3")
  625.    
  626.     return rsIn -- 15
  627. end
  628.  
  629. function utils.startWaterFunction(inWater, onWater, maxDescent, goIn)
  630.     --[[
  631.         Use with utils.getWaterStatus
  632.         could be inWater and not onWater if on single layer of water with floor below
  633.     ]]
  634.     maxDescent = maxDescent or 1 -- prevents continuous down due to lack of water
  635.     if goIn == nil then -- turtle should submerge
  636.         goIn = true
  637.     end
  638.     local descent = 0 -- counter for going down
  639.     if inWater then -- job done
  640.         return inWater, onWater
  641.     end
  642.     if onWater and goIn then --inWater already returned so must be false
  643.         if turtle.down() then
  644.             if T:getBlockType("forward"):find("water") ~= nil or T:getBlockType("forward"):find("bubble") ~= nil then
  645.                 inWater = true
  646.                 return inWater, onWater
  647.             end
  648.         end
  649.     end
  650.     if not onWater then
  651.         T:forward(1)
  652.     end
  653.     -- should now be above water, but may be further down so onWater still false
  654.     while T:getBlockType("down"):find("water") == nil and T:getBlockType("down"):find("bubble") == nil do-- go down until water below
  655.         if turtle.down() then
  656.             descent = descent + 1
  657.             if descent >= maxDescent then -- limit descent in case no water present
  658.                 onWater = false
  659.                 return inWater, onWater -- false,false
  660.             end
  661.         else
  662.             onWater = false
  663.             return inWater, onWater -- false,false
  664.         end
  665.     end
  666.     -- now above water
  667.     if goIn then
  668.         turtle.down() -- now inside water block
  669.         inWater = true
  670.     end
  671.     return inWater, onWater
  672. end
  673.  
  674. function utils.fillBucket(direction)
  675.     if T:getWater(direction)  then
  676.         sleep(0.3)
  677.         return true
  678.     else
  679.         return false
  680.     end
  681. end
  682.  
  683. function utils.getEmptyBucketCount()
  684.     local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:bucket", -1)
  685.     return total
  686. end
  687.  
  688. function utils.getRoofStats(R)
  689.     local isWidthOdd = R.width % 2 == 1             -- is the width odd or even?
  690.     local isLengthOdd = R.length % 2 == 1           -- is the length odd or even?
  691.     if isWidthOdd then
  692.         R.height = math.floor(R.width / 2)          -- eg 7 x 5 roof, layers = 5 / 2 = 2
  693.     else
  694.         R.height = R.width / 2                      -- eg 17 x 8 roof, layers = 8 / 2 = 4
  695.     end
  696.    
  697.     local width = 2                                 -- assume even width with  2 block roof ridge
  698.     local length = R.length - R.height - 1          -- assume even width with  2 block roof ridge
  699.     if isWidthOdd then
  700.         width = 3                                   -- adjust to allow for single width roof ridge
  701.     end
  702.     if isLengthOdd then
  703.         length = R.length - R.height                -- adjust as 1 layer less
  704.     end
  705.    
  706.     return R, isWidthOdd, isLengthOdd, width, length
  707. end
  708.  
  709. function utils.getWater()
  710.     if deletesWater then
  711.         T:getWater("down") -- take water from source
  712.         sleep(0.2)
  713.         T:getWater("down") -- take water from source
  714.     else
  715.         if not turtle.detectDown() then
  716.             T:go("C2", false, 0, false)
  717.         end
  718.         T:getWater("forward") -- take water from source
  719.         sleep(0.2)
  720.         T:getWater("forward") -- take water from source
  721.     end
  722. end
  723.  
  724. function utils.getWaterBucketCount()
  725.     -- lastSlot, leastModifier, total, slotData  = T:getItemSlot(item, useDamage)
  726.     local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:water_bucket", -1)
  727.     return total
  728. end
  729.  
  730. function utils.getWaterStatus()
  731.     --[[ Usage:
  732.     local inWater, onWater = utils.getWaterStatus() -- returns turtle position near water
  733.     utils.startWaterFunction(onWater, inWater, 2, true) -- move INTO water max 2 blocks down
  734.     utils.startWaterFunction(onWater, inWater, 5, false) -- move ABOVE water max 5 blocks down
  735.     ]]
  736.     local onWater = false
  737.     local inWater = false
  738.     for i = 1, 4 do
  739.         if T:getBlockType("forward"):find("water") ~= nil  or T:getBlockType("forward"):find("bubble") ~= nil then
  740.             inWater = true
  741.         end
  742.         T:turnRight(1)
  743.     end
  744.     if T:getBlockType("down"):find("water") ~= nil or T:getBlockType("down"):find("bubble") ~= nil then
  745.         onWater = true
  746.     end
  747.     return inWater, onWater
  748. end
  749.  
  750. function utils.goBack(blocks)
  751.     blocks = blocks or 1
  752.     local success = true
  753.     for i = 1, blocks do
  754.         if not turtle.back() then
  755.             success = false
  756.             T:go("R2F1R2")
  757.         end
  758.     end
  759.    
  760.     return success
  761. end
  762.  
  763. function utils.getPrettyPrint(promptColour, menuPromptColour)
  764.     promptColour = promptColour or colors.yellow
  765.     menuPromptColour = menuPromptColour or colors.white
  766.    
  767.     local pp = {}
  768.     pp.prompt = promptColour
  769.     pp.itemColours = {}
  770.     pp.menuPrompt = menuPromptColour
  771.     pp.allowModifier = true -- can the menu return 'q' or 'h' / 'i'
  772.    
  773.     return pp
  774. end
  775.  
  776. function utils.move(R, blocks, reverse)
  777.     if reverse == nil then
  778.         reverse = false
  779.     end
  780.     if reverse then
  781.         if R.subChoice == 2 then -- reverse direction
  782.             T:up(blocks)
  783.         else
  784.             T:down(blocks)
  785.         end
  786.         return blocks * -1
  787.     else
  788.         if R.subChoice == 1 then
  789.             T:up(blocks)
  790.         else
  791.             T:down(blocks)
  792.         end
  793.         return blocks
  794.     end
  795. end
  796.  
  797. function utils.setStorageOptions()
  798.     local storage = ""
  799.     local storageBackup = ""
  800.     if T:getItemSlot("barrel") > 0 then
  801.         storage = "barrel"
  802.         storageBackup = "barrel"
  803.     end
  804.     if T:getItemSlot("chest") > 0 then
  805.         if storage == "" then
  806.             storage = "chest"
  807.         end
  808.         storageBackup = "chest"
  809.     end
  810.     return storage, storageBackup
  811. end
  812.  
  813. local pp = utils.getPrettyPrint()
  814.  
  815. local function buildWall(R)
  816.     -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  817.     local lib = {}
  818.    
  819.     function lib.singleLayer(R)
  820.         for l = 1, R.length do
  821.             if l == R.length and R.data == "house" then
  822.                 T:turnRight(1)
  823.             end
  824.             utils.goBack(1)
  825.             T:go("C1", false, 0, false, R.useBlockType)
  826.         end
  827.     end
  828.    
  829.     function lib.doubleLayer(R)
  830.         for l = 1, R.length do
  831.             T:go("C2", false, 0, false, R.useBlockType)
  832.             if l == R.length and R.data == "house" then
  833.                 T:turnRight(1)
  834.             end
  835.             utils.goBack(1)
  836.             T:go("C1", false, 0, false, R.useBlockType)
  837.         end
  838.     end
  839.    
  840.     function lib.tripleLayer(R)
  841.         for l = 1, R.length do
  842.             T:go("C2C0", false, 0, false, R.useBlockType)
  843.             if l == R.length and R.data == "house" then
  844.                 T:turnRight(1)
  845.             end
  846.             utils.goBack(1)
  847.             T:go("C1", false, 0, false, R.useBlockType)
  848.         end
  849.     end
  850.    
  851.     -- R.width preset to 1
  852.     local remaining = R.height
  853.    
  854.     if R.subChoice == 1 then
  855.         T:forward(1)            -- face forward, move over first block
  856.     end
  857.     if R.height > 1 then
  858.         T:up(1)                 -- go up 1 block
  859.     end
  860.     if R.data ~= "house" then
  861.         T:turnRight(2)              -- rotate 180
  862.     end
  863.     if R.height == 1 then       -- single block: place in front
  864.         lib.singleLayer(R)
  865.     elseif R.height == 2 then   -- 2 blocks, go backwards, place below and ahead
  866.         lib.doubleLayer(R)
  867.     else
  868.         while remaining >= 3 do
  869.             lib.tripleLayer(R)
  870.             remaining = remaining - 3
  871.             if remaining == 1 then
  872.                 T:go("U2F1R2")
  873.             elseif remaining > 1 then
  874.                 T:go("U3F1R2")
  875.             end
  876.         end
  877.         if remaining == 1 then
  878.             lib.singleLayer(R)
  879.         elseif remaining == 2 then
  880.             lib.doubleLayer(R)
  881.         end
  882.     end
  883.     if not R.silent then
  884.         while turtle.down() do end
  885.     end
  886.    
  887.     return {}
  888. end
  889.  
  890. local function buildStructure(R)
  891.     local lib = {}
  892.    
  893.     function lib.goDown(R)
  894.         --T:go("L1F1 R1F1 L1")  -- now on ground floor
  895.         if R.height > 1 then
  896.             T:down(1)
  897.         end
  898.     end
  899.     local buildHeight = R.height
  900.     local height = R.height
  901.     local width = R.width
  902.     local length = R.length
  903.    
  904.     if R.subChoice == 1 then
  905.         T:forward(1)            -- face forward, move over first block
  906.     end
  907.     if R.height > 3 then
  908.         R.height = 3
  909.     end
  910.     T:turnRight(2)
  911.     R.data = "house"
  912.     R.silent = true -- prevent return to ground after buildWall(R)
  913.     R.subChoice = 2 -- do not move forward when building walls
  914.     while height > 0 do
  915.         buildWall(R)
  916.        
  917.         lib.goDown(R)
  918.         R.length = width - 1
  919.         buildWall(R)
  920.         lib.goDown(R)
  921.        
  922.         R.length = length - 1
  923.         buildWall(R)
  924.         lib.goDown(R)
  925.        
  926.         R.length = width - 2
  927.         buildWall(R)
  928.         height = height - R.height  -- 1, 2 or 3
  929.         if height > 0 then
  930.             T:go("U2 R1F1 L1F1")
  931.             R.height = height
  932.             if height > 3 then
  933.                 R.height = 3
  934.             end
  935.             R.length = length
  936.         end
  937.     end
  938.    
  939.     T:go("U2F2")
  940.     while turtle.down() do end
  941.     T:go("R1F1R1")
  942.    
  943.     return {}
  944. end
  945.  
  946. local function buildGableRoof(R)
  947.     --[[
  948.     stairs placement:
  949.        _|   up
  950.      
  951.        T L  forward
  952.        _
  953.         |   down
  954.  
  955.     ]]
  956.     local lib = {}
  957.    
  958.     function lib.placeRoof(R, outward)
  959.         for i = 1, R.length + 2 do
  960.             if R.useBlockType:find("stairs") ~= nil then
  961.                 T:place("stairs", 0, "up")
  962.             else
  963.                 T:go("C0", false, 0, false, R.useBlockType)
  964.             end
  965.             if i < R.length + 2 then
  966.                 if outward then
  967.                     T:go("L1F1R1")
  968.                 else
  969.                     T:go("R1F1L1")
  970.                 end
  971.             end
  972.         end
  973.     end
  974.    
  975.     function lib.placeGable(R, outward)
  976.         local width = R.width
  977.         for h = 1, R.height do
  978.             for w = 1, width do
  979.                 T:go("C1")
  980.                 if w < width then
  981.                     if outward then
  982.                         T:go("L1F1R1")
  983.                     else
  984.                         T:go("R1F1L1")
  985.                     end
  986.                 end
  987.             end
  988.             if h < R.height then
  989.                 if outward then
  990.                     T:go("R1F1L1U1")
  991.                 else
  992.                     T:go("L1F1R1U1")
  993.                 end
  994.             end
  995.             width = width - 2
  996.             outward = not outward
  997.         end
  998.         return outward
  999.     end
  1000.    
  1001.     local outward = true
  1002.     -- go to centre of end wall if odd no, or half width if even
  1003.     R.height = math.floor(R.width / 2)
  1004.     local isOdd = R.width % 2 == 1
  1005.    
  1006.     utils.goBack(1)
  1007.     T:go("R1F"..R.height - 1 .."U"..R.height - 1)   -- top of roof, under top layer
  1008.     for h = 1, R.height + 1 do                      -- place tiles on left side of roof
  1009.         lib.placeRoof(R, outward)
  1010.         if h < R.height + 1 then
  1011.             utils.goBack(1)
  1012.             T:down(1)
  1013.             outward = not outward
  1014.         end
  1015.     end
  1016.     if isOdd then
  1017.         T:go("F"..R.height + 2 .."R2U"..R.height)
  1018.     else
  1019.         T:go("F"..R.height + 1 .."R2U"..R.height)
  1020.     end
  1021.     for h = 1, R.height + 1 do                      -- place tiles on right side of roof
  1022.         lib.placeRoof(R, outward)
  1023.         if h < R.height + 1 then
  1024.             utils.goBack(1)
  1025.             T:down(1)
  1026.             outward = not outward
  1027.         end
  1028.     end
  1029.     -- gable ends
  1030.     if outward then
  1031.         T:go("F1R1U1")
  1032.     else
  1033.         T:go("F1L1U1")
  1034.     end
  1035.     outward = lib.placeGable(R, outward)
  1036.     T:go("F2R2 C1R2F"..R.length - 1 .."D"..R.height - 1)
  1037.     if outward then
  1038.         T:go("R1F"..R.height - 1 .."R1")
  1039.     else
  1040.         T:go("L1F"..R.height - 1 .."L1")
  1041.     end
  1042.     outward = not outward
  1043.     outward = lib.placeGable(R, outward)
  1044.     if isOdd then
  1045.         if outward then
  1046.             T:go("L1F1R1U2F1")
  1047.         else
  1048.             T:go("R1F1L1U2F1")
  1049.         end
  1050.         for i = 1, R.length do
  1051.             T:go("C2F1", false, 0, false)
  1052.         end
  1053.         for i = 1, R.length + 2 do
  1054.             utils.goBack(1)
  1055.             T:place("slab", 0, "forward")
  1056.         end
  1057.     end
  1058.     while turtle.down() do end
  1059.    
  1060.     return {}
  1061. end
  1062.  
  1063. local function buildPitchedRoof(R)
  1064.     --[[
  1065.     stairs placement:
  1066.        _|   up
  1067.      
  1068.        T L  forward
  1069.        _
  1070.         |   down
  1071.  
  1072.     ]]
  1073.     local lib = {}
  1074.        
  1075.     function lib.placeRoofSection(length)
  1076.         -- starts facing centre of building
  1077.         for i = 1, length do
  1078.             if i < length then
  1079.                 if R.useBlockType:find("stairs") ~= nil then
  1080.                     T:place("stairs", 0, "up")
  1081.                 else
  1082.                     T:go("C0", false, 0, false, R.useBlockType)
  1083.                 end
  1084.                 T:go("L1F1R1")
  1085.             end
  1086.         end
  1087.         -- ends facing centre of building
  1088.     end
  1089.    
  1090.     function lib.placeRoof(R, width, length)
  1091.         lib.placeRoofSection(length)
  1092.         T:go("R1")
  1093.         lib.placeRoofSection(width)
  1094.         T:go("R1")
  1095.         lib.placeRoofSection(length)
  1096.         T:go("R1")
  1097.         lib.placeRoofSection(width)
  1098.     end
  1099.    
  1100.     function lib.placeSlabs(length)
  1101.         -- add slabs at top
  1102.         T:go("U2F1L1")
  1103.         if length > 1 then
  1104.             T:forward(length - 3)
  1105.             for i = 1, length - 3 do
  1106.                 T:place("slab", 0, "forward")
  1107.                 utils.goBack(1)
  1108.             end
  1109.             T:place("slab", 0, "forward")
  1110.         else
  1111.             T:place("slab", 0, "forward")
  1112.         end
  1113.         T:go("D2R1")
  1114.         utils.goBack(1)
  1115.     end
  1116.     --[[
  1117.     Turtle MUST be placed on left corner of shortest dimension
  1118.    
  1119.     ****   or T******
  1120.     ****      *******
  1121.     ****      *******
  1122.     ****
  1123.     T***
  1124.     shortest dimension is R.width
  1125.     if width is odd, ignore top layer as is only 1 block wide
  1126.     ]]
  1127.     local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0
  1128.     R, isWidthOdd, isLengthOdd, width, length = utils.getRoofStats(R)
  1129.     T:go("F"..R.height - 1 .."R1F"..R.height - 1 .."U"..R.height - 1)       -- top of roof, under top layer
  1130.     if isWidthOdd then
  1131.         lib.placeSlabs(length)
  1132.     end
  1133.     for h = 1, R.height + 1 do                      -- place tiles on left side of roof
  1134.         lib.placeRoof(R, width, length)
  1135.         length = length + 2                         -- increase dimensions
  1136.         width = width + 2
  1137.         if h < R.height + 1 then
  1138.             utils.goBack(1)
  1139.             T:go("D1R1")
  1140.             utils.goBack(1)
  1141.         end
  1142.     end
  1143.     while turtle.down() do end
  1144.    
  1145.     return {}
  1146. end
  1147.  
  1148. local function clearAndReplantTrees() -- 25
  1149.     --[[ clear all trees in a rectangle area defined by walls, fences or non-dirt blocks
  1150.     replant with same type of sapling. If original tree 2 blocks wide, replant 4 if possible. ]]
  1151.    
  1152.     local lib = {}
  1153.    
  1154.     function lib.getSaplingFromLogType(log)
  1155.         --[[ get type of sapling to plant from log type ]]
  1156.         if log:find("oak") ~= nil then
  1157.             return "minecraft:oak_sapling"
  1158.         elseif log:find("spruce") ~= nil then
  1159.             return "minecraft:spruce_sapling"
  1160.         elseif log:find("birch") ~= nil then
  1161.             return "minecraft:birch_sapling"
  1162.         elseif log:find("jungle") ~= nil then
  1163.             return "minecraft:jungle_sapling"
  1164.         elseif log:find("acacia") ~= nil then
  1165.             return "minecraft:acacia_sapling"
  1166.         elseif log:find("dark_oak") ~= nil then
  1167.             return "minecraft:dark_oak_sapling"
  1168.         end
  1169.         return "sapling"
  1170.     end
  1171.    
  1172.     function lib.plantSapling(sapling, double)
  1173.         --[[ plant sapling(s) ]]
  1174.         if sapling == "" or sapling == nil then sapling = "sapling" end
  1175.         T:up(1)
  1176.         lib.suck()
  1177.         if double then  -- check if enough saplings
  1178.             --slotData.lastSlot, slotData.leastModifier, total, slotData = T:getItemSlot(sapling, -1)
  1179.             local a, b, total, _ = T:getItemSlot(sapling, -1)
  1180.             if total >= 4 then
  1181.                 for i = 1, 4 do
  1182.                     T:place(sapling, -1, "down")
  1183.                     T:go("F1R1")
  1184.                 end
  1185.                 T:forward(1)        -- above pre-planted sapling
  1186.             else
  1187.                 if not T:place(sapling, -1, "down") then
  1188.                     T:place("sapling", -1, "down")
  1189.                 end
  1190.             end
  1191.         else
  1192.             if not T:place(sapling, -1, "down") then
  1193.                 T:place("sapling", -1, "down")
  1194.             end
  1195.         end
  1196.         turtle.select(1)
  1197.     end
  1198.        
  1199.     function lib.suck()
  1200.         --[[ Collect saplings, sticks and apples ]]
  1201.         turtle.select(1)
  1202.         turtle.suck()
  1203.         turtle.suckUp()
  1204.         turtle.suckDown()
  1205.     end
  1206.    
  1207.     function lib.turn(direction)
  1208.         --[[ change direction and return new value for direction ]]
  1209.         if direction == "r" then
  1210.             T:turnRight(1)
  1211.             direction = "l"
  1212.         else
  1213.             T:turnLeft(1)
  1214.             direction = "r"
  1215.         end
  1216.         return direction    -- will only change direction variable if return value is used
  1217.     end
  1218.    
  1219.     function lib.emptyInventory(blockTypeD)
  1220.         --[[ Empty all except 32 of each sapling and 1 chest ]]
  1221.         if blockTypeD == nil then
  1222.             blockTypeD = T:getBlockType("down")
  1223.         end
  1224.         if blockTypeD:find("chest") ~= nil or blockTypeD:find("barrel") ~= nil then
  1225.             -- empty logs, apples, sticks and all but 1 stack of each sapling type
  1226.             T:emptyInventorySelection("down", {"chest", "oak_sapling", "birch_sapling", "spruce_sapling", "acacia_sapling", "jungle_sapling","dark_oak_sapling"},{1, 32, 32, 32, 32, 32, 32})
  1227.             return true
  1228.         else
  1229.             return false
  1230.         end
  1231.     end
  1232.    
  1233.     function lib.moveDown(blockTypeD)
  1234.         --[[ move down until hit ground. Break leaves and continue ]]
  1235.         if blockTypeD == nil then
  1236.             blockTypeD = T:getBlockType("down")
  1237.         end
  1238.         while blockTypeD == "" or blockTypeD:find("leaves") ~= nil do   -- move down, breaking leavse
  1239.             T:down(1)
  1240.             lib.suck()
  1241.             blockTypeD = T:getBlockType("down")
  1242.         end
  1243.         return blockTypeD
  1244.     end
  1245.    
  1246.     function lib.moveForward()
  1247.         --[[ Move forward 1 block only, go down to ground while air or leaves below ]]
  1248.         local blockTypeF = T:getBlockType("forward")
  1249.         local blockTypeD = T:getBlockType("down")
  1250.         if blockTypeF == "" or blockTypeF:find("leaves") ~= nil then    -- air or leaves ahead
  1251.             T:forward(1)                                                -- move forward, breaking leaves
  1252.             T:dig("up")                                                 -- remove leaves / low branches above to allow space for player
  1253.             lib.suck()
  1254.             blockTypeD = lib.moveDown()
  1255.             if not lib.emptyInventory(blockTypeD) then                  -- check if above a corner chest / barrel
  1256.                 if lib.isBorder(blockTypeD) then                        -- not above chest so check if above border
  1257.                     return false, blockTypeD                            -- above a border block so stop
  1258.                 end
  1259.             end
  1260.             blockTypeF = T:getBlockType("forward")
  1261.             return true, blockTypeF                                     -- moved ok, could be air or block in front
  1262.         end
  1263.         return false, blockTypeF                                        -- did not move, obstacle in front NOT leaves or air
  1264.     end
  1265.    
  1266.     function lib.moveUp(blockTypeF)
  1267.         --[[ Move up until air in front (dig leaves / harvest tree) ]]
  1268.         if blockTypeF == nil then
  1269.             blockTypeF = T:getBlockType("forward")
  1270.         end
  1271.         while blockTypeF:find("dirt") ~= nil or
  1272.               blockTypeF:find("grass_block") ~= nil or
  1273.               T:isVegetation(blockTypeF) do -- go up while dirt, grass-block or any vegetation in front
  1274.             T:up(1)
  1275.             blockTypeF = T:getBlockType("forward")
  1276.             if blockTypeF:find("log") ~= nil then
  1277.                 lib.harvestTree(blockTypeF)
  1278.                 return T:getBlockType("forward")
  1279.             elseif blockTypeF:find("leaves") ~= nil then
  1280.                 T:dig("forward")
  1281.                 return ""
  1282.             end
  1283.         end
  1284.         return blockTypeF   -- should be "" (air) or any border block
  1285.     end
  1286.    
  1287.     function lib.harvestTree(blockTypeF)
  1288.         --[[ Fell tree, returns true if double size ]]
  1289.         -- clsTurtle.harvestTree(extend, craftChest, direction)
  1290.         local saplingType = lib.getSaplingFromLogType(blockTypeF)
  1291.         local double = T:harvestTree(false, false, "forward")   -- assume single tree, will auto-discover
  1292.         lib.plantSapling(saplingType, double)
  1293.     end
  1294.    
  1295.     function lib.safeMove()
  1296.         --[[ move forward until border reached. loop breaks at that point ]]
  1297.         local blockTypeF = ""
  1298.         local success = true
  1299.         while success do
  1300.             success, blockTypeF = lib.moveForward()             -- move forward 1 block, return block type ahead
  1301.             if not success then                                 -- did not move forwards, block in the way: either log, dirt/grass, border block or vegetation
  1302.                 if blockTypeF:find("log") then                  -- tree found
  1303.                     lib.harvestTree(blockTypeF)
  1304.                     success = true                              -- block (log) removed, try again
  1305.                 else
  1306.                     success = not lib.isBorder(blockTypeF)      -- Is at border?: if is at border success = false so loop stops
  1307.                     if success then                             -- Not at border. Dirt/grass vegetation in front
  1308.                         blockTypeF = lib.moveUp(blockTypeF)     -- move up until leaves/log/air
  1309.                         success = not lib.isBorder(blockTypeF)  -- Is at border?: if is at border success = false so loop stops
  1310.                         if success then                         -- keep moving forward
  1311.                             if blockTypeF:find("log") then      -- tree found
  1312.                                 lib.harvestTree(blockTypeF)
  1313.                             end
  1314.                                                                 -- else blockTypeF is air/leaves  border has been checked
  1315.                         end
  1316.                     end
  1317.                 end
  1318.             end                                                 -- else success = true, 1 block moved so continue
  1319.         end
  1320.     end
  1321.    
  1322.     function lib.isBorder(blockType)
  1323.         --[[ Is the block log, dirt, grass_block, vegetation: non-border, or other:border]]
  1324.         if blockType == nil then                    -- not passed as parameter
  1325.             blockType = T:getBlockType("forward")
  1326.         end
  1327.         if blockType == "" then                     -- air ahead: not border
  1328.             return false, ""
  1329.         else                                        -- could be border or other
  1330.             if blockType:find("dirt") ~= nil or blockType:find("grass_block") ~= nil or blockType:find("log") ~= nil then -- either dirt, grass block or log
  1331.                 return false, blockType             -- dirt, grass, log: not border
  1332.             end
  1333.             if T:isVegetation(blockType) then       -- vegetation found: not border
  1334.                 return false, blockType
  1335.             end
  1336.         end
  1337.         return true, blockType                      -- dirt, grass_block, log and vegetation eliminated:must be border
  1338.     end
  1339.    
  1340.     function lib.inPosition()
  1341.         --[[ check if in lower left corner ]]
  1342.         local inPosition = true         -- assume correct
  1343.         if not turtle.detectDown() then -- hanging in mid-air
  1344.             return false
  1345.         end
  1346.         T:turnLeft(1)
  1347.         if lib.isBorder() then
  1348.             -- so far so good
  1349.             T:turnLeft(1)
  1350.             if not lib.isBorder() then  -- not in correct place
  1351.                 inPosition = false
  1352.             end
  1353.             T:turnRight(2)              -- return to original position
  1354.         else
  1355.             inPosition = false
  1356.             T:turnRight(1)              -- return to original position
  1357.         end
  1358.         return inPosition
  1359.     end
  1360.    
  1361.     function lib.findBorder()
  1362.         --[[ assume started after reset. if log above harvest tree else return to ground. Find starting corner]]
  1363.         local blockType = T:getBlockType("up")                  -- dig any logs above, return to ground
  1364.         local log = "sapling"
  1365.         if blockType:find("log") ~= nil then                    -- originally felling a tree so complete it
  1366.             log = lib.getSaplingFromLogType(blockType)
  1367.             local double = T:harvestTree(false, false, "up")    -- assume single tree, will auto-discover
  1368.             lib.plantSapling(log, double)
  1369.         else                                                    -- no log above so go downm
  1370.             blockType = lib.moveDown()                          -- return to ground (or vegetation)
  1371.         end
  1372.         lib.safeMove()                                          -- move forward until border reached
  1373.         T:turnRight(1)
  1374.         lib.safeMove()                                          -- move forward until second border reached
  1375.         T:turnRight(1)                                          -- should now be in correct position
  1376.         lib.emptyInventory()                                    -- empty inventory if above a chest
  1377.     end
  1378.    
  1379.     local direction = "r"
  1380.     local blockTypeF = ""
  1381.     local success = false
  1382.     if not lib.inPosition() then
  1383.         lib.findBorder()
  1384.     end
  1385.     local secondBorderFound = false
  1386.     while not secondBorderFound do
  1387.         lib.safeMove()                                                      -- moves forward until reaches border forward or below
  1388.         lib.turn(direction)                                                 -- turn r or l. direction is not changed
  1389.         success, blockTypeF = lib.isBorder()                                -- no blockType passed as parameter so will return current block in new forward direction
  1390.         if success then
  1391.             secondBorderFound = true                                        -- game over
  1392.         elseif blockTypeF:find("log") ~= nil then                           -- tree in front
  1393.             lib.harvestTree(blockTypeF)
  1394.         elseif blockTypeF == "" or blockTypeF:find("leaves") ~= nil then    -- air or leaves in front
  1395.             T:forward(1)                                                    -- move forward 1 block
  1396.             lib.moveDown()                                                  -- go down if required
  1397.         elseif  blockTypeF:find("dirt") ~= nil or
  1398.                 blockTypeF:find("grass_block") ~= nil or
  1399.                 T:isVegetation(blockTypeF) then                             -- dirt, grass_block or vegetation in front
  1400.             blockTypeF = lib.moveUp(blockTypeF)                             -- move up until air or border ahead.
  1401.             if lib.isBorder(blockTypeF) then                                -- border ahead
  1402.                 secondBorderFound = true
  1403.             else                                                            -- air ahead                                   
  1404.                 T:forward(1)                                                -- move forward 1 block
  1405.             end
  1406.         end
  1407.         direction = lib.turn(direction)                                     -- turn r or l. direction is changed to opposite
  1408.     end
  1409.     lib.moveDown()                                                          -- return to ground level
  1410.     lib.emptyInventory()
  1411.     return {}
  1412. end
  1413.  
  1414. local function clearArea(R) -- 71, called from 22
  1415.     local evenWidth = false
  1416.     local evenHeight = false
  1417.     local loopWidth
  1418.     -- go(path, useTorch, torchInterval, leaveExisting)
  1419.     if R.width % 2 == 0 then
  1420.         evenWidth = true
  1421.         loopWidth = R.width / 2
  1422.     else
  1423.         loopWidth = math.ceil(R.width / 2)
  1424.     end
  1425.     if R.length % 2 == 0 then
  1426.         evenHeight = true
  1427.     end
  1428.     turtle.select(1)
  1429.     -- clear an area between 2 x 4 and 32 x 32
  1430.     -- if R.width is even no, then complete the up/down run
  1431.     -- if R.width odd no then finish at top of up run and reverse
  1432.     -- should be on flat ground, check voids below, harvest trees
  1433.     for x = 1, loopWidth do
  1434.         -- Clear first column (up)
  1435.         for y = 1, R.length do
  1436.             if R.useBlockType == "dirt" then
  1437.                 if not turtle.detectDown() then
  1438.                     T:place("minecraft:dirt", -1, "down", true)
  1439.                 else --if not water, dirt, grass , stone then replace with dirt
  1440.                     blockType, blockModifier = T:getBlockType("down")
  1441.                     if blockType ~= "" then
  1442.                         if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
  1443.                             turtle.digDown()
  1444.                             T:place("minecraft:dirt", -1, "down", true)
  1445.                         end
  1446.                     end
  1447.                 end
  1448.             end
  1449.             if y < R.length then
  1450.                 T:go("F1+1", false,0,false)
  1451.             end
  1452.         end
  1453.         -- clear second column (down)
  1454.         if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
  1455.             T:go("R1F1+1R1", false,0,false)
  1456.             for y = 1, R.length do
  1457.                 if R.useBlockType == "dirt" then
  1458.                     if not turtle.detectDown() then
  1459.                         T:place("minecraft:dirt", -1, "down", true)
  1460.                     else
  1461.                         blockType, blockModifier = T:getBlockType("down")
  1462.                         if blockType ~= "" then
  1463.                             if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
  1464.                                 turtle.digDown()
  1465.                                 T:place("minecraft:dirt", -1, "down", true)
  1466.                             end
  1467.                         end
  1468.                     end
  1469.                 end
  1470.                 if y < R.length then
  1471.                     T:go("F1+1", false, 0, false)
  1472.                 end
  1473.             end
  1474.             if x < loopWidth then
  1475.                 T:go("L1F1+1L1", false,0,false)
  1476.             else
  1477.                 T:turnRight(1)
  1478.                 T:forward(R.width - 1)
  1479.                 T:turnRight(1)
  1480.             end
  1481.         else -- equals R.width but is 1,3,5,7 etc
  1482.             T:turnLeft(2) --turn round 180
  1483.             T:forward(R.length - 1)
  1484.             T:turnRight(1)
  1485.             T:forward(R.width - 1)
  1486.             T:turnRight(1)
  1487.         end
  1488.     end
  1489.     return {}
  1490. end
  1491.  
  1492. local function clearRectangle(R) -- 72
  1493.     --local function clearRectangle(width, length, up, down)
  1494.     -- height = 0: one level, 1 = +up, 2 = +down, 3 = +up/down
  1495.     local lib = {}
  1496.     function lib.UpDown(length)
  1497.         for l = 1, length do
  1498.             T:go("x0x2F1x0x2")
  1499.         end
  1500.     end
  1501.    
  1502.     function lib.Up(length)
  1503.         for l = 1, length do
  1504.             T:go("x0F1x0")
  1505.         end
  1506.     end
  1507.    
  1508.     function lib.Down(length)
  1509.         for l = 1, length do
  1510.             T:go("x2F1x2")
  1511.         end
  1512.     end
  1513.    
  1514.     function lib.Forward(length)
  1515.         T:forward(length)
  1516.     end
  1517.    
  1518.     -- could be 1 wide x xx R.length (trench) R.up and return
  1519.     -- could be 2+ x 2+
  1520.     -- even no of runs return after last run
  1521.     -- odd no of runs forward, back, forward, reverse and return
  1522.     turtle.select(1)
  1523.     if R.width == 1 then                    -- single block trench ahead only
  1524.         if R.up and R.down then             -- single block wide trench dig R.up and R.down = 3 blocks deep
  1525.             lib.UpDown(R.length - 1)
  1526.         elseif R.up then                    -- single block wide trench dig R.up = 2 blocks deep
  1527.             lib.Up(R.length - 1)
  1528.         elseif R.down then              -- single block wide trench dig R.down = 2 blocks deep
  1529.             lib.Down(R.length - 1)
  1530.         else                            -- single block wide = 1 block deep
  1531.             lib.Forward(R.length - 1)
  1532.         end
  1533.         T:turnRight(2)                  -- turn at the top of the run
  1534.         T:forward(R.length - 1)         -- return to start
  1535.         T:turnRight(2)                  -- turn round to original position
  1536.     else                                -- R.width 2 or more blocks
  1537.         local iterations = 0            -- R.width = 2, 4, 6, 8 etc
  1538.         if R.width % 2 == 1 then        -- R.width = 3, 5, 7, 9 eg R.width 7
  1539.             iterations = (R.width - 1) / 2 -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
  1540.         else
  1541.             iterations = R.width / 2        -- iterations 1, 2, 3, 4 for widths 2, 4, 6, 8
  1542.         end
  1543.         for i = 1, iterations do        -- eg 3 blocks wide, iterations = 1
  1544.             if R.up and R.down then                         -- dig R.up and R.down
  1545.                 lib.UpDown(R.length - 1)
  1546.                 T:go("x0x2R1F1x0x2R1x0x2")              -- turn round
  1547.                 lib.UpDown(R.length - 1)
  1548.             elseif R.up then                                -- dig R.up
  1549.                 lib.Up(R.length - 1)
  1550.                 T:go("x0R1F1x0R1x0")
  1551.                 lib.Up(R.length - 1)
  1552.             elseif R.down then                          -- dig R.down
  1553.                 lib.Down(R.length - 1)
  1554.                 T:go("x2R1F1x2R1x2")
  1555.                 lib.Down(R.length - 1)
  1556.             else                                        -- no digging R.up or R.down
  1557.                 lib.Forward(R.length - 1)
  1558.                 T:go("R1F1R1")
  1559.                 lib.Forward(R.length - 1)
  1560.             end
  1561.             -- if 1 less than end, reposition for next run
  1562.             if i < iterations then
  1563.                 T:go("L1F1L1", false, 0, false)
  1564.             end
  1565.         end
  1566.         if R.width % 2 == 1 then  -- additional run and return to base needed
  1567.             T:go("L1F1L1", false, 0, false)
  1568.             if R.up and R.down then
  1569.                 lib.UpDown(R.length - 1)
  1570.             elseif R.up then
  1571.                 lib.Up(R.length - 1)
  1572.             elseif R.down then
  1573.                 lib.Down(R.length - 1)
  1574.             else
  1575.                 lib.Forward(R.length - 1)
  1576.             end
  1577.             T:turnRight(2)
  1578.             T:forward(R.length - 1)
  1579.         end
  1580.         T:go("R1F"..R.width - 1 .."R1", false, 0, false)
  1581.     end
  1582.     return {}
  1583. end
  1584.  
  1585. local function clearPerimeter(R) -- 74
  1586.     local lib = {}
  1587.     function lib.UpDown(length)
  1588.         for l = 1, length do
  1589.             T:go("x0x2F1x0x2")
  1590.         end
  1591.     end
  1592.    
  1593.     function lib.Up(length)
  1594.         for l = 1, length do
  1595.             T:go("x0F1x0")
  1596.         end
  1597.     end
  1598.    
  1599.     function lib.Down(length)
  1600.         for l = 1, length do
  1601.             T:go("x2F1x2")
  1602.         end
  1603.     end
  1604.    
  1605.     function lib.Forward(length)
  1606.         T:forward(length)
  1607.     end
  1608.    
  1609.     if R.up and R.down then
  1610.         for i = 1, 2 do
  1611.             lib.UpDown(R.length - 1)
  1612.             T:turnRight(1)
  1613.             lib.UpDown(R.width - 1)
  1614.             T:turnRight(1)
  1615.         end
  1616.     elseif R.up then
  1617.         for i = 1, 2 do
  1618.             lib.Up(R.length - 1)
  1619.             T:turnRight(1)
  1620.             lib.Up(R.width - 1)
  1621.             T:turnRight(1)
  1622.         end
  1623.     elseif R.down then
  1624.         for i = 1, 2 do
  1625.             lib.Down(R.length - 1)
  1626.             T:turnRight(1)
  1627.             lib.Down(R.width - 1)
  1628.             T:turnRight(1)
  1629.         end
  1630.     else
  1631.         for i = 1, 2 do
  1632.             lib.Forward(R.length - 1)
  1633.             T:turnRight(1)
  1634.             lib.Forward(R.width - 1)
  1635.             T:turnRight(1)
  1636.         end
  1637.     end
  1638.     return {}
  1639. end
  1640.  
  1641. local function clearBuilding(R) -- 75, 43
  1642.     --[[
  1643.     Clear the outer shell of a building, leaving inside untouched. Optional floor/ceiling removal
  1644.     clearBuilding(R)
  1645.     R.subChoice = 1-'up' or 2-'down'
  1646.     R.data.ceiling = true / false
  1647.     R.data.floor = true / false
  1648.     ]]
  1649.     local height = 1
  1650.     local remaining = R.height -- eg 5
  1651.     local start = true
  1652.     local finish = false
  1653.     local lib = {}
  1654.    
  1655.     function lib.floorOrCeiling(R)
  1656.         T:go("F1R1 F1L1")
  1657.         R.length = R.length - 2
  1658.         R.width = R.width - 2
  1659.         clearRectangle(R)
  1660.         R.length = R.length + 2
  1661.         R.width = R.width + 2
  1662.         T:go("L1F1R1")
  1663.         utils.goBack(1)
  1664.     end
  1665.    
  1666.     function lib.singleLayer(R)
  1667.         R.up = false
  1668.         R.down = false
  1669.         if start then
  1670.             if R.data.ceiling or R.data.floor then  -- floor / ceiling to go. only one layer, so clearRectangle
  1671.                 lib.floorOrCeiling(R)
  1672.             end
  1673.             start = false
  1674.         end
  1675.         if finish then
  1676.             if R.data.ceiling or R.data.floor then  -- floor / ceiling to go. only one layer, so clearRectangle
  1677.                 lib.floorOrCeiling(R)
  1678.             end
  1679.             finish = false
  1680.         end
  1681.         clearPerimeter(R)                       -- no floor / ceiling
  1682.     end
  1683.    
  1684.     function lib.doubleLayer(R)
  1685.         R.up = false
  1686.         R.down = false
  1687.         if start then
  1688.             if R.data.floor and R.subChoice == 1 then       -- going up and floor needs removing
  1689.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1690.             elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing
  1691.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1692.             end
  1693.             start = false
  1694.         end
  1695.         if finish then
  1696.             if R.data.ceiling and R.subChoice == 1 then     -- going down and ceiling needs removing
  1697.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1698.             elseif R.data.floor and R.subChoice == 2 then   -- going down and floor needs removing
  1699.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1700.             end
  1701.             finish = false
  1702.         end
  1703.         if R.subChoice == 1 then
  1704.             R.up = true
  1705.         else
  1706.             R.down = true
  1707.         end
  1708.         clearPerimeter(R)
  1709.     end
  1710.    
  1711.     function lib.tripleLayer(R)
  1712.         -- turtle in centre layer
  1713.         R.up = false
  1714.         R.down = false
  1715.         if start then
  1716.             if R.data.floor and R.subChoice == 1 then       -- going up and floor needs removing
  1717.                 height = height + utils.move(R, 1, true)    -- move down 1 block
  1718.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1719.                 height = height + utils.move(R, 1)      -- move up 1 block
  1720.             elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing
  1721.                 height = height + utils.move(R, 1, true)    -- move up 1 block
  1722.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1723.                 height = height + utils.move(R, 1)      -- move down 1 block
  1724.             end
  1725.             start = false
  1726.         end
  1727.         if finish then
  1728.             if R.data.ceiling and R.subChoice == 1 then     -- going up and ceiling needs removing
  1729.                 height = height + utils.move(R, 1, true)                    -- move down 1 block
  1730.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1731.                 height = height + utils.move(R, 1)                          -- move up 1 block
  1732.             elseif R.data.floor and R.subChoice == 2 then   -- going down and floor needs removing
  1733.                 height = height + utils.move(R, 1, true)                    -- move up 1 block
  1734.                 lib.floorOrCeiling(R)                       -- remove floor/ceiling
  1735.                 height = height + utils.move(R, 1)                          -- move up 1 block
  1736.             end
  1737.             finish = false
  1738.         end
  1739.         R.up = true
  1740.         R.down = true
  1741.         clearPerimeter(R)
  1742.     end
  1743.     --[[
  1744.     R.data = "up" or "down" as direction of travel
  1745.     R.up = true to remove ceiling
  1746.     R.down = true to remove floor
  1747.     ]]
  1748.     R.silent = true
  1749.     if R.height < 3 then                        --1-3 layers only
  1750.         if R.height == 1 then                   --one layer only
  1751.             lib.singleLayer(R)
  1752.         elseif R.height == 2 then               --2 layers only current + dig up/down
  1753.             lib.doubleLayer(R)
  1754.         end
  1755.     else -- 3 or more levels
  1756.         height = height + utils.move(R, 1)                          -- move up/down 1 block for first layer
  1757.         while remaining >= 3 do -- min 3 levels
  1758.             lib.tripleLayer(R)
  1759.             remaining = remaining - 3
  1760.             if remaining == 0 then              -- all finished
  1761.                 break
  1762.             elseif remaining == 1 then
  1763.                 height = height + utils.move(R, 2)                  -- move up/down 2 blocks
  1764.                 lib.singleLayer(R)
  1765.             elseif remaining == 2 then
  1766.                 height = height + utils.move(R, 2)                  -- move up/down 2 blocks
  1767.                 lib.doubleLayer(R)
  1768.             else
  1769.                 height = height + utils.move(R, 3)                  -- move up/down 3 blocks
  1770.                 if remaining == 3 then
  1771.                     finish = true
  1772.                 else
  1773.                     --height = height + 3
  1774.                 end
  1775.             end
  1776.         end
  1777.     end
  1778.    
  1779.     if height > 1 then
  1780.         utils.move(R, height - 1, true) -- reverse direction
  1781.     end
  1782.    
  1783.     return {}
  1784. end
  1785.  
  1786. local function clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- 19
  1787.     local lib = {}
  1788.    
  1789.     function lib.checkCobweb(directions, inInventory)
  1790.         assert(type(directions) == "table", "directions must be a table eg {'up','down'}")
  1791.         for _, direction in ipairs(directions) do
  1792.             local blockType = T:getBlockType(direction)
  1793.             if inInventory == "minecraft:diamond_sword" then -- using a sword
  1794.                 local side = "left"
  1795.                
  1796.                 if blockType:find("cobweb") ~= nil then
  1797.                     --clsTurtle.equip(self, side, useItem, useDamage)
  1798.                     if equippedRight == "minecraft:diamond_pickaxe" then
  1799.                         side = "right"
  1800.                     end
  1801.                     T:equip(side, "minecraft:diamond_sword")
  1802.                     T:dig(direction)
  1803.                     T:equip(side, "minecraft:diamond_pickaxe")
  1804.                 elseif blockType ~= "" then
  1805.                     T:dig(direction)
  1806.                 end
  1807.             else
  1808.                 T:dig(direction)
  1809.             end
  1810.         end
  1811.     end
  1812.  
  1813.     -- check position by rotating until facing away from wall
  1814.     length = 0
  1815.     torch = 0
  1816.     turns = 0
  1817.     while not turtle.detect() do
  1818.         T:turnRight(1)
  1819.         turns = turns + 1
  1820.         if turns > 4 then
  1821.             return {"I am not facing a wall. Unable to continue"}
  1822.         end
  1823.     end
  1824.     T:turnRight(2)
  1825.     -- move forward until obstructed, digging up/down. place torches
  1826.     while not turtle.detect() do
  1827.         lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  1828.         length = length + 1
  1829.         torch = torch + 1
  1830.         if torch == R.torchInterval then
  1831.             torch = 0
  1832.             T:place("minecraft:torch", -1, "down", false) ---(self, blockType, damageNo, direction, leaveExisting, signText)
  1833.         end
  1834.         lib.checkCobweb({"forward"}, inInventory) -- dig cobweb or any other block in front
  1835.         T:forward(1)
  1836.     end
  1837.     -- turn right, forward, right, return to start with up/down dig
  1838.     T:go("R1")
  1839.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  1840.     T:go("F1R1")
  1841.     for i = 1, length, 1 do
  1842.         lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
  1843.         T:forward(1)
  1844.     end
  1845.     -- move to other wall and repeat.
  1846.     T:go("R1")
  1847.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  1848.     T:go("F1")
  1849.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  1850.     T:go("F1R1")
  1851.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  1852.     for i = 1, length, 1 do
  1853.         lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
  1854.         T:forward(1)
  1855.     end
  1856.     lib.checkCobweb({"up", "down"}, inInventory) -- dig cobweb or any other block up/down/forward
  1857.    
  1858.     return {}
  1859. end
  1860.  
  1861. local function clearMonumentLayer(R) -- 85
  1862.     R.up = true
  1863.     R.down = true
  1864.     R.silent = true
  1865.     if R.subChoice == 0 then
  1866.         R.up = false
  1867.         R.down = false
  1868.     end
  1869.     -- send turtle down until it hits bottom
  1870.     -- then clear rectangle of given size
  1871.     -- start above water, usually on cobble scaffold above monument
  1872.     if T:detect("down") then -- in case not over wall
  1873.         T:forward(1)
  1874.     end
  1875.     local height = 1
  1876.     -- go down until solid block detected
  1877.     while utils.clearVegetation("down") do
  1878.         T:down(1)
  1879.         height = height + 1
  1880.     end
  1881.     T:down(1)
  1882.     height = height + 1
  1883.     clearRectangle(R)
  1884.     T:up(height - 1)
  1885.    
  1886.     return {}
  1887. end
  1888.  
  1889. local function clearWaterPlants(R) -- 87
  1890.     local lib = {}
  1891.    
  1892.     function lib.getLength()
  1893.         local length = 1
  1894.         print("Checking water length")
  1895.         while utils.clearVegetation("forward") do
  1896.             T:forward(1)
  1897.             length = length + 1
  1898.         end
  1899.         for i = 1, length do
  1900.             turtle.back()
  1901.         end
  1902.         return length
  1903.     end
  1904.    
  1905.     function lib.clearDown(D)
  1906.         while utils.clearVegetation("down") do --clears any grass or sea plants, returns true if air or water, bubble column or ice
  1907.             T:down(1)
  1908.             D.depth = D.depth + 1
  1909.         end
  1910.         -- if slab at bottom, replace with solid block
  1911.         D.blockType = T:getBlockType("down")
  1912.         if D.blockType:find("slab") ~= nil then
  1913.             T:go("C2")
  1914.         end
  1915.         if D.depth > D.maxDepth then
  1916.             D.maxDepth = D.depth
  1917.         end
  1918.        
  1919.         return D
  1920.     end
  1921.    
  1922.     function lib.clearLength(D)
  1923.         local moves = 0
  1924.         local blockHeight = 1
  1925.         D.floorLength = 0 -- reset
  1926.         while moves < D.length - 1 do
  1927.             if utils.clearVegetation("forward") then
  1928.                 T:forward(1)
  1929.                 moves = moves + 1
  1930.                 if turtle.detectUp() then -- could be on monument going under arch, or faulty monument floor
  1931.                     if not D.monumentArchesClear then
  1932.                         D = lib.checkArches(D)
  1933.                     end
  1934.                 end
  1935.                 local temp = D.depth
  1936.                 D = lib.clearDown(D) -- go down if in water/air
  1937.                 if blockHeight == 4 and D.depth - temp == 3 then -- could be just gone over 3 block high column in ocean monument
  1938.                     if not D.monumentTopClear then
  1939.                         D = lib.checkTop(D)
  1940.                     end
  1941.                     blockHeight = 1
  1942.                 end
  1943.                 if D.useBlockType == "prismarine" then
  1944.                     if D.blockType:find("prismarine") == nil then
  1945.                         -- on monument floor so restrict forward movement to 8 blocks
  1946.                         D.floorLength = D.floorLength + 1
  1947.                         if D.floorLength == 8 then
  1948.                             D.blockType = T:getBlockType("forward")
  1949.                             while D.blockType:find("prismarine") == nil do
  1950.                                 T:up(1)
  1951.                                 D.blockType = T:getBlockType("forward")
  1952.                             end
  1953.                             D.floorLength = 0
  1954.                         end
  1955.                     end
  1956.                 end
  1957.                 if moves >= D.length - 1 then
  1958.                     D.width = D.width + 1   -- another length completed so increase width
  1959.                     return D
  1960.                 end
  1961.             else -- block in front
  1962.                 blockHeight = 1
  1963.                 local waterAbove = utils.clearVegetation("up")
  1964.                 local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
  1965.                 while not waterAhead do     -- solid block in front
  1966.                     if waterAbove then      -- move up
  1967.                         T:up(1)
  1968.                         D.depth = D.depth - 1
  1969.                         blockHeight = blockHeight + 1
  1970.                         if D.depth < 1 then
  1971.                             D.width = D.width + 1   -- another length completed so increase width
  1972.                             return D
  1973.                         end
  1974.                     else                    -- block above so go back
  1975.                         while not waterAbove do
  1976.                             utils.goBack()  --  returns true if no object behind, but moves anyway
  1977.                             waterAbove = utils.clearVegetation("up")
  1978.                             moves = moves - 1
  1979.                             if moves == 0 then
  1980.                                 T:up(1)
  1981.                                 D.depth = D.depth - 1
  1982.                                 waterAbove = utils.clearVegetation("up")
  1983.                                 while not waterAbove do
  1984.                                     T:up(1)
  1985.                                     D.depth = D.depth - 1
  1986.                                 end
  1987.                             end
  1988.                         end
  1989.                         -- go up 1 to prevent loop
  1990.                         T:up(1)
  1991.                         D.depth = D.depth - 1
  1992.                     end
  1993.                     waterAbove = utils.clearVegetation("up")
  1994.                     waterAhead = utils.clearVegetation("forward")
  1995.                 end
  1996.             end
  1997.         end
  1998.         D.width = D.width + 1   -- another length completed so increase width
  1999.         D.maxDepth = D.maxDepth + 1 -- +1 to allow for starting pos in top layer
  2000.        
  2001.         return D
  2002.     end
  2003.    
  2004.     function lib.checkArches(D)
  2005.         -- gone under a block so could be monument arch (6)
  2006.         if T:getBlockType("up"):find("prismarine") ~= nil then -- confirm on monument, not previously cleared
  2007.             local direction = ""    -- initialise direction
  2008.             T:go("B1U2F1R1")
  2009.             if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess
  2010.                 direction = "R"
  2011.             else    -- wrong direction. turn round and check other side
  2012.                 T:go("R2")
  2013.                 if T:getBlockType("forward"):find("prismarine") ~= nil then
  2014.                     direction = "L"
  2015.                 end
  2016.             end
  2017.             local path = "U1F1 U1F3 D1F1 D1R2 U2F5 D2"
  2018.             --for i = 1, 6 do
  2019.             T:go(path) -- clears arch top 1 and returns
  2020.             T:go(direction.."1F6"..direction.."1")
  2021.             T:go(path) -- clears arch top 2 and returns
  2022.             T:go(direction.."1F6"..direction.."1")
  2023.             T:go(path) -- clears arch top 3 and returns
  2024.             T:go(direction.."1F9"..direction.."1")
  2025.             T:go(path) -- clears arch top 4 and returns
  2026.             T:go(direction.."1F6"..direction.."1")
  2027.             T:go(path) -- clears arch top 5 and returns
  2028.             T:go(direction.."1F6"..direction.."1")
  2029.             T:go(path) -- clears arch top 6 and returns
  2030.            
  2031.             T:go(direction.."3F34"..direction.."2D2F1")
  2032.             D.monumentArchesClear =  true
  2033.         end
  2034.         return D
  2035.     end
  2036.    
  2037.     function lib.checkTop(D)
  2038.         -- gone over 3 block column so could be at the top of ocean monument
  2039.         if T:getBlockType("down"):find("prismarine") ~= nil then -- confirm on monument, not previously cleared
  2040.             local direction = ""    -- initialise direction
  2041.             T:go("U3R1")            -- up to top of column and try right side
  2042.             if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess
  2043.                 direction = "L"
  2044.             else    -- wrong direction. turn round and check other side
  2045.                 T:go("R2")
  2046.                 if T:getBlockType("forward"):find("prismarine") ~= nil then
  2047.                     direction = "R"
  2048.                 end
  2049.             end
  2050.             if direction ~= "" then -- facing single block on layer 2
  2051.                 T:go("U1F6"..direction.."1F5".. direction.."1F5"..direction.."1F5"..direction.."1") -- clear 4 single blocks
  2052.                 T:go("F1U1"..direction.."1F1"..direction.."3") -- on top of monument
  2053.                 T:go("F3".. direction.."1F3"..direction.."1F3"..direction.."1F3"..direction.."3") -- clear top, face return
  2054.                 T:go("F2D5"..direction.."3B1")
  2055.             end
  2056.             D.monumentTopClear = true
  2057.         end
  2058.         return D
  2059.     end
  2060.    
  2061.     function lib.findBlockTypeEnd(D)
  2062.         D.blockType = "" -- reset
  2063.         repeat
  2064.             if utils.clearVegetation("forward") then
  2065.                 T:forward(1)
  2066.                 D = lib.clearDown(D) -- go down if in water/air, D.blockType is updated with floor type
  2067.             else -- block in front
  2068.                 local waterAbove = utils.clearVegetation("up")
  2069.                 local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
  2070.                 while not waterAhead do     -- solid block in front
  2071.                     if waterAbove then      -- move up
  2072.                         T:up(1)
  2073.                     else                    -- block above so go back
  2074.                         while not waterAbove do
  2075.                             utils.goBack()  --  returns true if no object behind, but moves anyway
  2076.                             waterAbove = utils.clearVegetation("up")
  2077.                         end
  2078.                     end
  2079.                     waterAbove = utils.clearVegetation("up")
  2080.                     waterAhead = utils.clearVegetation("forward")
  2081.                 end
  2082.             end
  2083.         until D.blockType:find(D.useBlockType) == nil
  2084.         -- now above a non-prismarine block, facing away from monument
  2085.         T:turnRight(2) -- facing monument
  2086.         D.blockType = T:getBlockType("forward")
  2087.         while D.blockType:find(D.useBlockType) ~= nil do
  2088.             T:up(1)
  2089.             D.blockType = T:getBlockType("forward")
  2090.         end
  2091.         T:go("F1L1")
  2092.         D.blockType = T:getBlockType("down")
  2093.         while D.blockType:find(D.useBlockType) ~= nil do
  2094.             T:forward(1)
  2095.             D.blockType = T:getBlockType("down")
  2096.         end
  2097.         turtle.back()
  2098.         -- should now be at end of monument base
  2099.     end
  2100.    
  2101.     function lib.turn(D)
  2102.         local direction = "R"
  2103.         if not D.facingForward then
  2104.             direction = "L"
  2105.         end
  2106.         T:go(direction.. 1)
  2107.         if utils.clearVegetation("forward") then
  2108.             T:forward(1)
  2109.             --D.depth = D.depth + lib.clearDown(depth)
  2110.             D = lib.clearDown(D)
  2111.         else
  2112.             while not utils.clearVegetation("forward") do
  2113.                 T:up(1)
  2114.                 D.depth = D.depth - 1
  2115.             end
  2116.             T:forward(1)
  2117.         end
  2118.         T:go(direction.. 1)
  2119.         D.facingForward = not D.facingForward
  2120.        
  2121.         return D
  2122.     end
  2123.  
  2124.     local D = {}
  2125.     D.depth = 0
  2126.     D.maxDepth = 0
  2127.     D.blockType = ""
  2128.     D.useBlockType = R.useBlockType -- "" or "prismarine"
  2129.     D.length = 0    -- copy of R.length used in lib.clearLength
  2130.     D.width = 0     -- increased every iteration
  2131.     D.facingForward = true
  2132.     D.monumentTopClear = false
  2133.     D.monumentArchesClear = false
  2134.     D.inWater = false
  2135.     D.onWater = false
  2136.     D.inWater, D.onWater = utils.getWaterStatus()
  2137.     D.floorLength = 0 -- used on monument floor
  2138.    
  2139.     if R.data == "clearWaterPlants" then -- NOT monument corner discovery
  2140.         D.inWater, D.onWater = utils.startWaterFunction(D.onWater, D.inWater, 2, true) -- move into water
  2141.         if R.length == 0 then
  2142.             R.length = lib.getLength()
  2143.         end
  2144.         if R.width == 0 then
  2145.             T:turnRight(1)
  2146.             R.width = lib.getLength()
  2147.             T:turnLeft(1)
  2148.         end
  2149.     end
  2150.     D.length = R.length
  2151.     D = lib.clearDown(D) -- go down to floor, set depth, maxDepth, blockType
  2152.     if R.data == "clearWaterPlants" then -- NOT monument corner discovery
  2153.         if R.width == 1 then
  2154.             print("Single row clearing")
  2155.             D = lib.clearLength(D) --D.width also increased
  2156.         else
  2157.             while D.width < R.width do -- D.width starts at 0
  2158.                 -- now on floor, move along sea/river bed following contour
  2159.                 D = lib.clearLength(D) --D.width also increased
  2160.                 -- now turn and repeat
  2161.                 if D.width < R.width then  
  2162.                     D = lib.turn(D)
  2163.                     if D.depth <= 0 then
  2164.                         break
  2165.                     end
  2166.                 end
  2167.             end
  2168.         end
  2169.         -- finished so return to surface
  2170.         T:up(1) -- up 1 to check for water below
  2171.         while T:getBlockType("down"):find("water") ~= nil do
  2172.             T:up(1)
  2173.         end
  2174.         T:down(2) -- return to surface
  2175.         --[[while utils.clearVegetation("forward") do
  2176.             T:forward(1)
  2177.         end]]
  2178.     elseif R.data == "oceanMonumentColumns" then -- monument corner discovery
  2179.         -- this function used to find edge of monument base
  2180.         if D.blockType:find(D.useBlockType) ~= nil then
  2181.             lib.findBlockTypeEnd(D)
  2182.             return {""}
  2183.         else
  2184.             T:up(D.depth)
  2185.             return {"Prismarine not found on ocean floor"}
  2186.         end
  2187.     end
  2188.     if R.silent then
  2189.         return {D.maxDepth, R.length}
  2190.     else
  2191.         return {""}
  2192.     end
  2193. end
  2194.  
  2195. local function clearMountainSide(R) -- 78
  2196.     --[[
  2197.     First row              outward  l  s  f  mid    (length, start, finish, midPoint)
  2198.  
  2199.           >|*|*|           true                     lib.clearRow() moves: 7-5=2, midPoint starts at 2
  2200.           +|*|*|
  2201.           +|*|*|
  2202.           ^|*|*|        <  false    7  5  6  2      lib.clearRow() moves: 9-2=7, midPoint starts at -4 -1 = -5
  2203.            |*|*|*|      +
  2204.          |*|*|*|*|*|    +
  2205.       >  |*|*|*|*|*|    ^  true     9  2  6  -4     lib.getStartingLength(). Ends 1 block after block finish
  2206.       ^|*|*|*|*|*|*|*|*|                            starts here, moves up 1
  2207.         1 2 3 4 5 6 7 8                             block index
  2208.          
  2209.     Second row                outward l  s  f  mid
  2210.                  <            false
  2211.                  +
  2212.           |*|*|  +
  2213.        >|*|*|*|*|^            true
  2214.        +|*|*|*|*|
  2215.        +|*|*|*|*|
  2216.        ^|*|*|*|*|          <  false   6  5  6  2
  2217.         |*|*|*|*|*|*|      +
  2218.       |*|*|*|*|*|*|*|*|    +
  2219.       |*|*|*|>|*|*|*|*|    ^  true    7+5   5 -7    lib.getHalf(R); goBack(7)
  2220.     |*|*|*|*|*|*|*|*|*|*|*|                           starts at midPoint of previous row eg block 4
  2221.      0 1 2 3 4 5 6 7 8 9 10
  2222.     ]]
  2223.    
  2224.     -- variables declared before lib for them to be used within lib as is then in scope
  2225.     local turn = "R"
  2226.     local oTurn = "L"
  2227.     if R.subChoice == 1 then    -- remove left side
  2228.         turn = "L"
  2229.         oTurn = "R"
  2230.     end
  2231.     local outward = true        -- direction flag
  2232.    
  2233.     local lib = {}
  2234.    
  2235.     function lib.isAnyAbove(above)
  2236.         T:saveToLog("lib.isAnyAbove: "..utils.tableConcat(above, ", "), false)
  2237.         for k,v in ipairs(above) do
  2238.             if v then
  2239.                 T:saveToLog("lib.isAnyAbove Found: "..k , false)
  2240.                 return true
  2241.             end
  2242.         end
  2243.         return false
  2244.     end
  2245.        
  2246.     function lib.clearLevel(R, above)   -- eg 9, 2, 6, -4 from lib.getStartingLength OR 7, 5, 6, 3 from previous
  2247.         -- clearLevel always follows either lib.getStartingLength or a previous lib.clearLevel
  2248.         -- midPoint should be adjusted as turtle moves to reflect current row length
  2249.         if #above == 0 then return above, 1 end
  2250.         --local index = 0
  2251.         local minMoves = math.floor(#above / 2)
  2252.         local up, forward, down = lib.getDetect()
  2253.         if outward then                                     -- follow table indexes
  2254.             for x = 1, minMoves do                          -- clear first half
  2255.                 above[x] = up                               -- reset this with new value
  2256.                 T:go("x0x2F1")                              -- clear and move forward
  2257.                 up, forward, down = lib.getDetect()
  2258.                 --index = index + 1
  2259.             end
  2260.             for x = minMoves + 1, #above do                 -- check remaing half and clear
  2261.                 T:go("x0x2")                                -- clear above / below
  2262.                 if above[x] then                            -- is a block recorded as present?(now below)
  2263.                     above[x] = up                           -- reset this with new value
  2264.                     T:forward(1)                            -- move forward
  2265.                     up, forward, down = lib.getDetect()
  2266.                     --index = index + 1
  2267.                 else
  2268.                     break
  2269.                 end
  2270.             end
  2271.         else                                                -- iterate table in reverse
  2272.             --index = #above
  2273.             for x = #above, minMoves, -1 do                 -- clear first half
  2274.                 above[x] = up                               -- reset this with new value
  2275.                 T:go("x0x2F1")                              -- clear and move forward
  2276.                 up, forward, down = lib.getDetect()
  2277.                 --index = index - 1
  2278.             end
  2279.             for x = minMoves - 1, 1, -1 do                  -- check remaing half and clear
  2280.                 T:go("x0x2")                                -- clear up / down
  2281.                 if above[x] then                            -- is a block recorded as present?(now below)
  2282.                     above[x] = up                           -- reset this with new value
  2283.                     T:forward(1)                            -- move forward
  2284.                     up, forward, down = lib.getDetect()
  2285.                     --index = index - 1
  2286.                 else
  2287.                     break
  2288.                 end
  2289.             end
  2290.         end
  2291.         T:go("x0x2 F1R2 x0x2 F1")                           -- face opposite direction, delete blocks above and below
  2292.         outward = not outward                               -- switch direction flag
  2293.         return above                                        -- eg {false, true, true, true, false}
  2294.     end
  2295.    
  2296.     function lib.getDetect()
  2297.         return turtle.detectUp(),  turtle.detect(),  turtle.detectDown()
  2298.     end
  2299.    
  2300.     function lib.getStartingLength(R)
  2301.         --[[
  2302.             length of column by excavating blocks above, ahead or below
  2303.             Rotate 180 at end of run ready to return
  2304.             already 1 block above ground
  2305.         ]]
  2306.         local above = {}                                    -- empty table of boolean values
  2307.         local length = 0                                    -- used as counter                         
  2308.         T:forward(1)                                        -- start check 1 block ahead
  2309.         local up, forward, down = lib.getDetect()           -- check if anything around current block
  2310.         if up or forward or down then                       -- block found nearby: continue
  2311.             while up or forward or down do                  -- while blocks ahead / up / down move forward
  2312.                 table.insert(above, up)
  2313.                 T:go("x0x2F1")
  2314.                 up, forward, down = lib.getDetect()         -- check if anything around current block
  2315.                 length = length + 1
  2316.                 if length >= R.length then                  -- check if going out of range
  2317.                     T:saveToLog("lib.getStartingLength(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
  2318.                     break
  2319.                 end
  2320.             end
  2321.             T:go("R2x0x2")                                  -- Rotate 180 and clear blocks above/below
  2322.         else                                                -- no blocks nearby: exit
  2323.             T:go("R2F1")                                    -- return to start position rotated 180
  2324.         end
  2325.         outward = not outward
  2326.  
  2327.         return above                                        -- above = {false, true, true, true, true, false, false}
  2328.     end
  2329.    
  2330.     function lib.firstRow(R)
  2331.         local height = 1                                    -- starts at ground level, but forced up 1
  2332.         T:up(1)
  2333.         local above = lib.getStartingLength(R)              -- clear the ground level and 1 above eg 9, 2, 5, 4
  2334.         if T:saveToLog("startLength: "..#above, true) then
  2335.             T:saveToLog(utils.tableConcat(above, ", "), false)
  2336.             if dbug then read() end
  2337.         end                                                 -- at end of first row as already turned 180, outward set to false in getStartingLength
  2338.         while lib.isAnyAbove(above) do
  2339.             T:go("U3")  -- go up 3
  2340.             height = height + 3
  2341.             above = lib.clearLevel(R, above)    -- returns start and finish of blocks above, rotates 180
  2342.             if T:saveToLog("checking level: "..height, true) then
  2343.                 T:saveToLog(utils.tableConcat(above, ", "), false)
  2344.                 if dbug then read() end
  2345.             end
  2346.         end                                                 -- first row all levels completed.
  2347.         T:down(height)                                      -- now on ground + 1, facing last column cleared.
  2348.        
  2349.         return above
  2350.     end
  2351.        
  2352.     function lib.deepCopy(tbl)
  2353.         local copy = {}
  2354.         for key, value in ipairs(tbl) do
  2355.             table.insert(copy, value)
  2356.         end
  2357.         return copy
  2358.     end
  2359.    
  2360.     function lib.getHalf(R, above)
  2361.         -- already 1 block above ground
  2362.         local maxLength = R.length
  2363.         local temp = {}
  2364.         local retValue = {}
  2365.         if #above > 0 then                              -- not empty table, so must be second half
  2366.             temp = lib.deepCopy(above)                  -- copy existing table
  2367.             above = {}                                  -- initialise above
  2368.         end
  2369.         local up, forward, down = lib.getDetect()
  2370.        
  2371.         while up or forward or down do                  -- while blocks ahead / up / down move forward
  2372.             T:go("x0x2F1")
  2373.             table.insert(above, up)
  2374.             up, forward, down = lib.getDetect()         -- check if anything around current block
  2375.            
  2376.             if #above >= math.floor(maxLength / 2) then -- check if going out of range
  2377.                 T:saveToLog("lib.getHalf(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
  2378.                 T:go("x0x2")
  2379.                 break
  2380.             end
  2381.         end
  2382.         T:turnRight(2)                                  -- ready for next half or return
  2383.         outward = not outward
  2384.         if #temp > 0 then                               -- completing a second half measurement
  2385.             for i = #above, 1, -1 do
  2386.                 table.insert(retValue, above[i])        -- combine 2 tables into 1
  2387.             end
  2388.             for i = 1, #temp do
  2389.                 table.insert(retValue, temp[i])
  2390.             end
  2391.         else
  2392.             retValue = above
  2393.         end
  2394.         return retValue
  2395.     end
  2396.    
  2397.     function lib.nextRow(R)
  2398.         local height = 1
  2399.         T:saveToLog("lib.nextRow(R)", false)
  2400.         T:up(1)
  2401.         local pattern = turn.."1F1"..turn.."1"
  2402.         if not outward then
  2403.             pattern = oTurn.."1F1"..oTurn.."1"
  2404.         end
  2405.         T:go(pattern)
  2406.         T:saveToLog("    T:go("..pattern..")", false)
  2407.         outward = not outward -- reverse direction flag
  2408.         -- now in next vertical row
  2409.         local above = lib.getHalf(R, {})
  2410.         local index = 0
  2411.         if T:saveToLog("\t  first half Length: "..#above.." Enter", true) then
  2412.             T:saveToLog(utils.tableConcat(above, ", "), false)
  2413.             if dbug then read() end
  2414.         end
  2415.         lib.returnToMidPoint(#above)                    -- return to starting point
  2416.         T:forward(1)       
  2417.         above = lib.getHalf(R, above)                   -- returns length - 1 eg 5, 4
  2418.         if T:saveToLog("\t  total length: "..#above.." Enter", true) then
  2419.             T:saveToLog(utils.tableConcat(above, ", "), false)
  2420.             if dbug then read() end
  2421.         end
  2422.        
  2423.         while lib.isAnyAbove(above) do
  2424.             T:go("U3")              -- go up 3
  2425.             height = height + 3     -- increment height
  2426.             T:saveToLog("\tClear height loop: height = "..height, false)
  2427.             above = lib.clearLevel(R, above)    -- returns start and finish of blocks above
  2428.         end
  2429.         T:down(height)  -- now on ground + 1
  2430.         lib.returnToMidPoint(above)
  2431.     end
  2432.    
  2433.     function lib.returnToMidPoint(above)
  2434.         --[[ value can be integer or table]]
  2435.         if type(above) == "table" then
  2436.             T:saveToLog("lib.returnToMidPoint("..#above..")", false)
  2437.             if #above > 0 then
  2438.                 local midPoint = math.floor(#above / 2)
  2439.                 if #above % 2 == 1 and  not outward then -- length is odd no
  2440.                     midPoint = math.ceil(#above / 2)
  2441.                     T:saveToLog("    midPoint adjusted "..midPoint..")", false)
  2442.                 end
  2443.                 T:saveToLog("    T:forward("..midPoint..")", false)
  2444.                 T:forward(midPoint)
  2445.             end
  2446.         else
  2447.             T:saveToLog("lib.returnToMidPoint("..above..")", false)
  2448.             if above > 0 then
  2449.                 T:saveToLog("    T:forward("..above..")", false)
  2450.                 T:forward(above)
  2451.             end
  2452.         end
  2453.         -- now back at starting point
  2454.     end
  2455.    
  2456.     -- Start here
  2457.     -- if "tk log d.." typed instead of "tk" will start logfile and display comments. read() will be activated for debugging
  2458.     T:saveToLog("Starting function clearMountainSide", false)
  2459.     local above = lib.firstRow(R)           -- outward depends on height eg 1-2 = false, 3-5 = true, 6-8 = false
  2460.     lib.returnToMidPoint(above)             -- return to mid first row of blocks
  2461.     for row = 1, R.width -1 do
  2462.         lib.nextRow(R)
  2463.     end
  2464.    
  2465.     return {}
  2466. end
  2467.  
  2468. local function clearSandWall(R) -- 81
  2469.     --dig down while on top of sand/red_sand/soul_sand
  2470.     local lib = {}
  2471.    
  2472.     function lib.checkAbove(height)
  2473.         if turtle.detectUp() then -- moved under a ledge
  2474.             T:go("B1U1")
  2475.             height = height - 1
  2476.         end
  2477.         return height
  2478.     end
  2479.    
  2480.     function lib.moveDown(height)
  2481.         blockType = T:getBlockType("down")
  2482.         while blockType:find("sand") ~= nil do
  2483.             T:down(1)
  2484.             height = height + 1
  2485.             blockType = T:getBlockType("down")
  2486.         end
  2487.         return height
  2488.     end
  2489.    
  2490.     function lib.moveForward(length)
  2491.         lib.digForward()
  2492.         T:forward(1)
  2493.         length = length + 1
  2494.         local blockType = T:getBlockType("forward")
  2495.         return length, blockType
  2496.     end
  2497.    
  2498.     function lib.digForward()
  2499.         while T:dig("forward") do
  2500.             while T:suck("forward") do end
  2501.             while T:suck("up") do end
  2502.         end
  2503.     end
  2504.    
  2505.     local moves  = 0
  2506.     local height = 0
  2507.     local length = 0
  2508.     local search = 0
  2509.     local reverse = false
  2510.     local blockType = T:getBlockType("down")
  2511.     if R.length == 0 then
  2512.         R.length = 64
  2513.     end
  2514.    
  2515.     print("Checking for sand below")
  2516.     while blockType:find("sand") == nil do --move forward until sand detected or 3 moves
  2517.         T:forward(1)
  2518.         search = search + 1
  2519.         blockType = T:getBlockType("down")
  2520.         if search > 3 then
  2521.             T:go("B"..search)
  2522.             return {"Unable to locate sand"}
  2523.         end
  2524.     end
  2525.     -- must be sand below
  2526.     height = lib.moveDown(height)   -- go down if sand below
  2527.     -- repeat until height == 0
  2528.     repeat -- starts at bottom of sand wall
  2529.         blockType = T:getBlockType("forward")
  2530.         if blockType:find("sand") ~= nil then -- sand in front
  2531.             length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
  2532.             if blockType == "" or  blockType:find("sand") ~= nil then -- sand or nothing in front
  2533.                 height = lib.moveDown(height)   -- go down if sand below
  2534.             end
  2535.         else -- solid block, air or water, not sand so move up
  2536.             if turtle.detect() then -- block in front
  2537.                 blockType = T:getBlockType("down")
  2538.                 if blockType:find("sand") ~= nil then -- sand below
  2539.                     T:dig("down")
  2540.                 end
  2541.                 T:up(1)
  2542.                 height = height - 1
  2543.             else -- air/water in front so move forward
  2544.                 if length < 60 then -- in case missing wall and in open ocean
  2545.                     length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
  2546.                     height = lib.checkAbove(height)
  2547.                 else -- already > monument length of 56
  2548.                     T:up(1)
  2549.                     height = height - 1
  2550.                 end
  2551.             end
  2552.         end
  2553.     until height == 0 or length == R.length
  2554.     blockType = T:getBlockType("down")
  2555.     if blockType:find("sand") ~= nil then -- sand below
  2556.         T:dig("down")
  2557.     end
  2558.     if height > 0 then -- finished as length ran out
  2559.         T:up(height)
  2560.     end
  2561.     -- stay at end of cleared wall unless user chose to return
  2562.     if R.data == "return" then
  2563.         T:go("R2F"..length.."R2")
  2564.     end
  2565.    
  2566.     return {}
  2567. end
  2568.  
  2569. local function clearSolid(R) -- 76
  2570.     --[[ direction = R.subChoice = 1 up or 2 down ]]
  2571.     local height = 1
  2572.     local remaining = R.height
  2573.     local lib = {}
  2574.    
  2575.     function lib.singleLayer(R)
  2576.         R.up = false
  2577.         R.down = false
  2578.         clearRectangle(R)
  2579.     end
  2580.    
  2581.     function lib.doubleLayer(R)
  2582.         R.up = false
  2583.         R.down = false
  2584.         if R.subChoice == 1 then
  2585.             R.up = true
  2586.         else
  2587.             R.down = true
  2588.         end
  2589.         clearRectangle(R)
  2590.     end
  2591.        
  2592.     function lib.tripleLayer(R)
  2593.         -- turtle in centre layer
  2594.         R.up = true
  2595.         R.down = true
  2596.         clearRectangle(R)
  2597.     end
  2598.  
  2599.     R.silent = true
  2600.     if R.height < 3 then                            --1-3 layers only
  2601.         if R.height == 1 then                       --one layer only
  2602.             lib.singleLayer(R)
  2603.         elseif R.height == 2 then                   --2 layers only current + dig up/down
  2604.             lib.doubleLayer(R)
  2605.         end
  2606.     else -- 3 or more levels
  2607.         height = height + utils.move(R, 1)          -- move up/down 1 block for first layer
  2608.         while remaining >= 3 do                     -- min 3 levels
  2609.             lib.tripleLayer(R)
  2610.             remaining = remaining - 3
  2611.             if remaining == 0 then                  -- all finished
  2612.                 break
  2613.             elseif remaining == 1 then
  2614.                 height = height + utils.move(R, 2)  -- move up/down 2 blocks
  2615.                 lib.singleLayer(R)
  2616.             elseif remaining == 2 then
  2617.                 height = height + utils.move(R, 2)  -- move up/down 2 blocks
  2618.                 lib.doubleLayer(R)
  2619.             else
  2620.                 height = height + utils.move(R, 3)  -- move up/down 3 blocks
  2621.                 if remaining == 3 then
  2622.                     finish = true
  2623.                 end
  2624.             end
  2625.         end
  2626.     end
  2627.    
  2628.     if height > 1 then
  2629.         utils.move(R, height - 1, true) -- reverse direction
  2630.     end
  2631.    
  2632.     return {}
  2633. end
  2634.  
  2635. local function clearSandCube(R) -- 81
  2636.     R.data = ""
  2637.     for w = 1, R.width do
  2638.         clearSandWall(R)
  2639.         if w < R.width then
  2640.             if w % 2 == 1 then
  2641.                 T:go("R1F1R1")
  2642.             else
  2643.                 T:go("L1F1L1")
  2644.             end
  2645.         end
  2646.     end
  2647.    
  2648.     return {}
  2649. end
  2650.  
  2651. local function clearWall(R) -- 73
  2652.     local lib = {}
  2653.    
  2654.     function lib.move(direction, blocks, reverse)
  2655.         --[[ Move up or down by blocks count ]]
  2656.         if reverse == nil then
  2657.             reverse = false
  2658.         end
  2659.         if reverse then
  2660.             if direction == "down" then -- reverse direction
  2661.                 T:up(blocks)
  2662.             else
  2663.                 T:down(blocks)
  2664.             end
  2665.         else
  2666.             if direction == "up" then
  2667.                 T:up(blocks)
  2668.             else
  2669.                 T:down(blocks)
  2670.             end
  2671.         end
  2672.         return blocks
  2673.     end
  2674.    
  2675.     function lib.singleLayer(length)
  2676.         T:go("F"..length - 1)
  2677.     end
  2678.    
  2679.     function lib.doubleLayer(modifier, length)
  2680.         for i = 1, length do
  2681.             if i < length then
  2682.                 T:go("x"..modifier.."F1")
  2683.             else
  2684.                 T:go("x"..modifier)
  2685.             end
  2686.         end
  2687.     end
  2688.    
  2689.     function lib.tripleLayer(direction, length)
  2690.         for i = 1, length do
  2691.             if i < length then
  2692.                 T:go("x0x2F1")
  2693.             else
  2694.                 T:go("x0x2")
  2695.             end
  2696.         end
  2697.     end
  2698.    
  2699.    
  2700.     -- R.width preset to 1
  2701.     -- R.subChoice = 1 up / 2 down
  2702.     if R.height < 3 then
  2703.         R.silent = true
  2704.     end
  2705.     -- dig along and up/down for specified R.length
  2706.     local modifier = "0"
  2707.     local direction = "U"
  2708.     local outbound = true
  2709.     local height = 0
  2710.     if R.subChoice == 2 then
  2711.          modifier = "2"
  2712.          direction = "D"
  2713.     end
  2714.     if R.height == 1 then               -- single block so dig and return
  2715.         lib.singleLayer(R.length)
  2716.     elseif R.height == 2 then
  2717.         lib.doubleLayer(modifier, R.length)
  2718.     else                                -- 4 blocks or more. start with bulk 3 blocks
  2719.         local remaining = R.height
  2720.         T:go(direction.."1")            -- up 1 or down 1
  2721.         height = 1
  2722.         while remaining >= 3 do
  2723.             lib.tripleLayer(direction, R.length)
  2724.             remaining = remaining - 3
  2725.            
  2726.             if remaining == 0 then      -- no more, return home, already in position
  2727.                
  2728.             elseif remaining == 1 or remaining == 2 then
  2729.                 T:go(direction.."2")
  2730.                 height = height + 2
  2731.             else
  2732.                 T:go(direction.."3")
  2733.                 height = height + 3
  2734.                 if remaining >= 3 then -- another iteration
  2735.                     T:go("R2")
  2736.                     outbound = not outbound
  2737.                 end
  2738.             end
  2739.         end
  2740.         -- 0, 1 or 2 layers left
  2741.         if remaining > 0 then
  2742.             T:go("R2")
  2743.             outbound = not outbound
  2744.             if remaining == 1 then
  2745.                 lib.singleLayer(R.length)
  2746.             elseif remaining == 2 then
  2747.                 lib.doubleLayer(modifier, R.length)
  2748.             end
  2749.         end
  2750.     end
  2751.     if outbound then
  2752.         T:go("R2F"..R.length)
  2753.     else
  2754.         T:forward(1)
  2755.     end
  2756.     direction = "D" -- reverse direction
  2757.     if R.subChoice == 2 then
  2758.          direction = "U"
  2759.     end
  2760.     if height > 0 then
  2761.         T:go(direction..height.."R2")
  2762.     else
  2763.         T:go("R2")
  2764.     end
  2765.     return {}
  2766. end
  2767.  
  2768. local function convertWater(R) -- 88
  2769.     --[[
  2770.     if dry need enough buckets to place along (width + length - 1) / 2
  2771.     use 12 buckets
  2772.     start on floor + 1
  2773.     place slab down and water up along 2 edges. stay on this level
  2774.     return round same 2 edges removing slabs and and placing them 1 above
  2775.     placeUp water onto slabs on both edges
  2776.     repeat recover slabs, place 1 above , placeUp water
  2777.    
  2778.     for sloping water, place full area with slabs
  2779.     place sloping water on top of slabs
  2780.     remove slabs
  2781.    
  2782.     ]]
  2783.     local lib = {}
  2784.    
  2785.     function lib.checkStartPosition()
  2786.         --[[
  2787.         0 T             -- T=turtle, W=wall, S=source, F=flowing
  2788.         1 W|S|F|F|F|F|F -- sloping flowing water
  2789.         2 W|F|F|F|F|F|F -- blocks removed after placing flowing water above
  2790.         3 W|S|S|S|S|S|S -- original sources
  2791.         4 W|?|?|?|?|?|? -- may be sources
  2792.         ]]
  2793.         -- need to be on floor or R.height if specified
  2794.         local depth = 0
  2795.         local blockType = T:getBlockType("down")
  2796.         local isWaterUp, isSourceUp = T:isWater("up")
  2797.         local isWaterForward, isSourceForward = T:isWater("forward")
  2798.         local isWaterDown, isSourceDown = T:isWater("down")
  2799.         print("Block below is "..blockType)
  2800.         print("Water above is "..tostring(isWaterUp))
  2801.         print("Water forward is "..tostring(isWaterForward))
  2802.         print("Water below is "..tostring(isWaterDown))
  2803.         if blockType:find("water") == nil then -- on at least level 0
  2804.             print("Moving forward in 2 seconds...")
  2805.             sleep(2)
  2806.             T:forward(1)
  2807.             blockType = T:getBlockType("down")
  2808.             if blockType:find("water") ~= nil then
  2809.                 print("Water found. Going down to floor")
  2810.                 depth = -1
  2811.             else
  2812.                 T:down(1)
  2813.                 blockType = T:getBlockType("down")
  2814.                 if blockType:find("water") ~= nil then
  2815.                     depth = -2
  2816.                 else
  2817.                     return 0, "Not close to water. Aborting..."
  2818.                 end
  2819.             end
  2820.         end
  2821.         while turtle.down() do
  2822.             depth = depth + 1
  2823.         end
  2824.         local emptyBuckets = utils.getEmptyBucketCount()
  2825.         for i = depth, 0, -1 do
  2826.             if emptyBuckets > 0 then
  2827.                 lib.fillBuckets()
  2828.                 emptyBuckets = utils.getEmptyBucketCount()
  2829.             end
  2830.             turtle.up()
  2831.         end
  2832.        
  2833.         return depth, ""
  2834.     end
  2835.    
  2836.     function lib.fillBuckets()
  2837.         local emptyBuckets = utils.getEmptyBucketCount()
  2838.         local direction = "forward"-- start with forward
  2839.         local isWater, isSource, isIce = T:isWater(direction)
  2840.         if emptyBuckets > 0 then
  2841.             if not isSource then
  2842.                 direction = "down"
  2843.                 isWater, isSource, isIce = T:isWater(direction)
  2844.                 if not isSource then
  2845.                     direction = "up"
  2846.                     isWater, isSource, isIce = T:isWater(direction)
  2847.                     if not isSource then
  2848.                         direction = ""
  2849.                     end
  2850.                 end
  2851.             end
  2852.             if direction == "" then
  2853.                 print("Unable to locate water source")
  2854.             else
  2855.                 for i = 1, emptyBuckets do
  2856.                     if utils.fillBucket(direction) then
  2857.                         print("Bucket filled "..direction)
  2858.                         sleep(0.3)
  2859.                     else
  2860.                         print("Unable to fill bucket ".. i .." / "..emptyBuckets)
  2861.                     end
  2862.                 end
  2863.             end
  2864.         end
  2865.         return utils.getWaterBucketCount()
  2866.     end
  2867.    
  2868.     function lib.placeSlabs(length)
  2869.         for i = 1, length do
  2870.             T:place("slab", -1, "down", false)
  2871.             if i < length then
  2872.                 T:forward(1)
  2873.             end
  2874.         end
  2875.     end
  2876.    
  2877.     function lib.placeSources(length, place)
  2878.         local moves = 1
  2879.         local waterBuckets = utils.getWaterBucketCount()
  2880.         -- place sources alternate positions + start and finish
  2881.         while moves < length do
  2882.             if place then
  2883.                 if T:placeWater("up") then
  2884.                     print("Placed source up")
  2885.                     waterBuckets = waterBuckets - 1
  2886.                 end
  2887.             end
  2888.             place = not place
  2889.             if moves < length then
  2890.                 T:forward(1)
  2891.                 moves = moves + 1
  2892.             end
  2893.             if waterBuckets == 0 then
  2894.                 T:down(1) -- break the slab below
  2895.                 waterBuckets = lib.fillBuckets()
  2896.                 T:up(1)
  2897.                 T:place("slab", -1, "down", false)
  2898.             end
  2899.         end
  2900.         if T:placeWater("up") then -- end of length
  2901.             print("Placed final source up")
  2902.         end
  2903.         return place
  2904.     end
  2905.    
  2906.     function lib.moveSlabs(length)
  2907.         for i = 1, length do
  2908.             T:dig("down")
  2909.             T:up(1)
  2910.             T:place("slab", -1, "down", true)
  2911.             if i < length then
  2912.                 T:forward(1)
  2913.                 T:down(1)
  2914.             end
  2915.         end
  2916.     end
  2917.    
  2918.     function lib.recoverSlabs(length)
  2919.         for i = 1, length do
  2920.             T:dig("down")
  2921.             if i < length then
  2922.                 T:forward(1)
  2923.             end
  2924.         end
  2925.     end
  2926.    
  2927.     local depth, message = lib.checkStartPosition()
  2928.     if message ~= "" then
  2929.         return {message}
  2930.     end
  2931.     local maxDepth = R.height
  2932.     local buckets = utils.getWaterBucketCount()
  2933.     R = utils.calculateDimensions(R) -- if R.width or R.length == 0
  2934.     T:down(depth)
  2935.     lib.placeSlabs(R.length)
  2936.     T:go("R1")
  2937.     lib.placeSlabs(R.width)
  2938.     T:go("R2")
  2939.    
  2940.     while depth > 0 do
  2941.         local place = true
  2942.         lib.fillBuckets()
  2943.         place = lib.placeSources(R.width, place)
  2944.         T:go("L1")
  2945.         place = lib.placeSources(R.length, place)
  2946.         lib.fillBuckets()
  2947.         T:go("R2")
  2948.         lib.moveSlabs(R.length) -- dig slab from below, move up and replace below
  2949.         T:go("R1F1D1")
  2950.         lib.moveSlabs(R.width - 1)
  2951.         T:go("R2") -- now moved up 1 layer
  2952.         depth = depth - 1
  2953.         if depth == 0 then
  2954.             place = lib.placeSources(R.width, true)
  2955.             T:go("L1")
  2956.             place = lib.placeSources(R.length, place)
  2957.             T:go("R2")
  2958.             lib.recoverSlabs(R.length)
  2959.             T:go("R1")
  2960.             lib.recoverSlabs(R.width)
  2961.         end
  2962.     end
  2963.    
  2964.     return {}
  2965. end
  2966.  
  2967. local function createBoatLift(R) -- 59 state:0=new, size:1=extend, side:0=left, 1=right
  2968.     -- build stepped lift with fencing gates and soul sand
  2969.     local lib = {}
  2970.    
  2971.     function lib.getWater(backToWater, downToWater)
  2972.         if backToWater > 0 then
  2973.             utils.goBack(backToWater)
  2974.         end
  2975.         if downToWater > 0 then
  2976.             T:down(downToWater)
  2977.         end
  2978.         T:getWater("down") -- take water from source
  2979.         sleep(0.2)
  2980.         T:getWater("down") -- take water from source
  2981.         if downToWater > 0 then
  2982.             T:up(downToWater)
  2983.         end
  2984.         if backToWater > 0 then
  2985.             T:forward(backToWater)
  2986.         end
  2987.     end
  2988.    
  2989.     --T:place(blockType, damageNo, direction, leaveExisting, signText)
  2990.    
  2991.     local backToWater = 0
  2992.     local downToWater = 0
  2993.    
  2994.     T:go("R1F1L1")                                      -- over canal facing forward
  2995.     for h = 1, R.height do
  2996.         lib.getWater(backToWater, downToWater)          -- check water supplies, return to starting position
  2997.         T:go("L1C1 R1D1 L1C1 R1", false, 0, false)      -- place towpath, forward, down, place towpath, face forward
  2998.         T:place("soul", -1, "down", false)              -- place soulsand down
  2999.         T:place("soul", -1, "forward", false)           -- place soulsand forward
  3000.         T:go("R1F1C1L1", false, 0, false)               -- place right towpath face forward
  3001.         T:place("soul", -1, "down", false)              -- place soulsand down
  3002.         T:place("soul", -1, "forward", false)           -- place soulsand forward
  3003.         T:go("U1 R1C1 L1")                              -- place towpath, face forward
  3004.         T:placeWater("down")                            -- place water down
  3005.         utils.goBack(1)
  3006.         T:place("gate", -1, "forward", false)           -- place fence gate
  3007.         T:go("R1C1 U1C1 D1 L2F1 C1R1 F1 L1C1R1")        -- over left soul sand
  3008.         T:placeWater("down")                            -- place water down
  3009.         utils.goBack(1)
  3010.         T:place("gate", -1, "forward", false)           -- place fence gate
  3011.         T:go("U1 L1C1 R1F1 L1C1 R1x1")                  -- facing forward first unit complete
  3012.         T:go("R1F1 L1x1 R1C1")
  3013.         utils.goBack(1)
  3014.         T:go("L1F1")
  3015.         if backToWater == 0 then
  3016.             backToWater = 1
  3017.         end
  3018.         backToWater = backToWater + 1
  3019.         downToWater = downToWater + 1
  3020.     end
  3021.    
  3022.     -- now finish the canal
  3023.     lib.getWater(backToWater, downToWater)
  3024.     T:go("D1 L1C1 U1C1")                    -- build left towpath, facing towpath, above water level
  3025.     T:go("R1F1 L1C1 D1C1")                  -- move forward, build towpath, facing towpath ground level
  3026.     T:go("R1C1 R1F1 L1C1 R1C1 U1C1")        -- build right towpath, facing towpath, above water level
  3027.     T:go("R1F1 L1C1 D1C1 U1")               -- build right towpath next to gate, facing towpath, above water level
  3028.     T:placeWater("down")
  3029.     utils.goBack(1)
  3030.     T:go("L1F1")
  3031.     T:placeWater("down")  
  3032.    
  3033.     return {}
  3034. end
  3035.  
  3036. local function createBorehole(R)
  3037.     --[[go down to bedrock and return. Chart all blocks dug/ passed through]]
  3038.     local diary = {}
  3039.     local lib = {}
  3040.     local depth = R.height  -- eg 63 start position
  3041.     local moves = 0
  3042.     --R.height = current level
  3043.    
  3044.     function lib.addBlock(depth, blockType, diary)
  3045.         if blockType == "" then
  3046.             blockType = "air"
  3047.         end
  3048.         table.insert(diary, blockType)
  3049.        
  3050.        
  3051.         --[[if blockType ~= "" then
  3052.             local add = true
  3053.             for k,v in pairs(diary) do
  3054.                 if blockType == v then
  3055.                     add = false
  3056.                     break
  3057.                 end
  3058.             end
  3059.             if add then
  3060.                 diary[depth] = blockType
  3061.             end
  3062.         end]]
  3063.        
  3064.         return diary
  3065.     end
  3066.    
  3067.     function lib.processItem(item)
  3068.         if item:find("minecraft") ~= nil then
  3069.             return item:sub(11)
  3070.         end
  3071.         return item
  3072.     end
  3073.    
  3074.     function lib.writeReport(R, diary)
  3075.         local numLevels = #diary                        -- eg 125 levels
  3076.         local levelsPerCol = math.ceil(numLevels / 4)   -- eg 31.25 -> 32
  3077.         local lines = {}
  3078.         for l = 1, levelsPerCol do                      -- add 32 empty strings
  3079.             table.insert(lines, "")
  3080.         end
  3081.         local lineNo = 1
  3082.         for k, v in ipairs(diary) do
  3083.             local level = R.height - k                  -- eg 63 range 63 to -59
  3084.             local lev = "      "
  3085.             local item = lib.processItem(v)
  3086.             if level < -9 then
  3087.                 lev = tostring(level).."   "            -- "-10   " to "-59   "
  3088.             elseif level < 0 then              
  3089.                 lev = "-0"..math.abs(level).."   "      -- "-09   " to "-01   "
  3090.             elseif level < 10 then
  3091.                 lev = " 0"..level.."   "                -- " 01   " to " 09   "
  3092.             elseif level < 100 then
  3093.                 lev = " "..level.."   "                 -- " 10   " to " 99   "
  3094.             else
  3095.                 lev = " "..level.."  "                  -- " 100  " to " 319  "
  3096.             end
  3097.             local output = lev..item                    -- eg "-10   grass_block"
  3098.             if #output > 20 then                        -- eg "-10   some_long_block_name"  
  3099.                 output = output:sub(1, 20)              -- eg "-10   some_long_block_"
  3100.             else
  3101.                 output = menu.padRight(output, 20, " ") -- eg "-10   grass_block     "
  3102.             end
  3103.             lines[lineNo] = lines[lineNo]..output       -- add new entry to this line
  3104.             lineNo = lineNo + 1                         -- increase line no
  3105.             if lineNo > levelsPerCol then               -- past last line number
  3106.                 lineNo = 1                              -- reset to 1
  3107.             end
  3108.         end
  3109.        
  3110.         local fileName = "borehole"..os.getComputerID()..".txt"
  3111.         local handle = fs.open(fileName, "w")       --create file eg "borehole0.txt"
  3112.         handle.writeLine("Level Block         Level Block         Level Block         Level Block")
  3113.         for k,v in ipairs(lines) do
  3114.             handle.writeLine(v)
  3115.         end
  3116.        
  3117.         handle.close()
  3118.        
  3119.         return fileName
  3120.     end
  3121.    
  3122.     local blockType = T:getBlockType("down")
  3123.     while T:down(1) do
  3124.         depth = depth - 1
  3125.         moves = moves + 1
  3126.         if depth == R.depth then
  3127.             break
  3128.         end
  3129.         diary = lib.addBlock(depth, blockType, diary)
  3130.         blockType = T:getBlockType("down")
  3131.     end
  3132.     local fileName = lib.writeReport(R, diary)
  3133.     T:up(moves)
  3134.    
  3135.     return {"File '"..fileName.."' written"}
  3136. end
  3137.  
  3138. local function createBubbleLift(R) -- 15
  3139.     local lib = {}
  3140.    
  3141.     function lib.addLayer()
  3142.         T:go("F2 L1C1 R1C1 R1C1 L1", false, 0, true)
  3143.         turtle.back()
  3144.         T:dig("up") -- clear block above so completed lift can be found
  3145.         T:placeWater("forward")
  3146.         turtle.back()
  3147.         T:go("C1x0")       
  3148.     end
  3149.    
  3150.     function lib.addSign()
  3151.         turtle.back()
  3152.         T:placeWater("forward")
  3153.         T:go("L1B1")
  3154.         T:place("sign", -1, "forward")
  3155.     end
  3156.    
  3157.     function lib.buildLift(toHeight)
  3158.         local built = lib.goToWater()       -- returns lift blocks already placed, total height of drop from starting point
  3159.         local toBuild = toHeight - built    -- no of blocks remaining to increase lift size
  3160.         local water = 0
  3161.         while toBuild > 0 do                -- at least 1 block height remaining
  3162.             water = lib.fillBuckets(toBuild, false) -- no of water buckets onboard (could be more than required)
  3163.             if water > toBuild then         -- more water than required
  3164.                 water = toBuild             -- reduce to correct amount
  3165.             end
  3166.             T:up(built)                     -- climb to top of existing lift
  3167.             while water > 0 and toBuild > 0 do
  3168.                 lib.addLayer()
  3169.                 water = water - 1
  3170.                 T:up(1)
  3171.                 toBuild = toBuild - 1
  3172.             end
  3173.             -- may still be some height to complete, but needs refill
  3174.             if toBuild > 0 then
  3175.                 built = lib.goToWater() --return to source
  3176.                 toBuild = toHeight - built
  3177.                 --lib.fillBuckets(toBuild)
  3178.             end
  3179.         end
  3180.     end
  3181.    
  3182.     function lib.cleanUp(fromHeight)
  3183.         local plug = false
  3184.         T:turnRight(2)
  3185.         for i = 1, fromHeight do
  3186.             plug = false
  3187.             if turtle.detect() then
  3188.                 plug = true
  3189.             end
  3190.             turtle.down()
  3191.             if plug then
  3192.                 T:place("stone", -1, "up")
  3193.             end
  3194.         end
  3195.         T:go("D1 C1R1x1 R1C1 R1F1 R1x1 L2x1 L1C1 x1") -- delete water sources
  3196.         T:go("D1 C1R1x1 R1")
  3197.         local blockType = T:getBlockType("forward")
  3198.         if blockType:find("dirt") == nil and blockType:find("soul") == nil then -- not dirt or soul sand in front
  3199.             T:go("C1")
  3200.         end
  3201.         T:go("R1F1 R1x1 L2x1 L1C1 x1")
  3202.     end
  3203.    
  3204.     function lib.fillBuckets(toBuild, withSort)
  3205.         local emptySlots, water = lib.stackBuckets(withSort)-- gets no of empty slots + no of water buckets
  3206.         if water < toBuild then                     -- no of water buckets onboard less than required quantity
  3207.             for i = 1, toBuild do                   -- fill required no of buckets up to max space in inventory
  3208.                 if emptySlots == 0 then             -- inventory full
  3209.                     break
  3210.                 else
  3211.                     if T:getWater("down") then
  3212.                         water = water + 1
  3213.                         sleep(0.5)
  3214.                     end
  3215.                 end
  3216.                 emptySlots = lib.getEmptySlots()
  3217.             end
  3218.         end
  3219.        
  3220.         return water
  3221.     end
  3222.    
  3223.     function lib.getEmptySlots()
  3224.         local empty = 0
  3225.         for i = 1, 16 do
  3226.             if turtle.getItemCount(i) == 0 then
  3227.                 empty = empty + 1
  3228.             end
  3229.         end
  3230.         return empty
  3231.     end
  3232.    
  3233.     function lib.goToWater()
  3234.         local built = 0 -- measures completed lift height
  3235.         while turtle.down() do -- takes turtle to bottom of water source
  3236.             if turtle.detect() then
  3237.                 built = built + 1
  3238.             end
  3239.         end
  3240.         T:up(1) -- above watersource ready to fill buckets
  3241.         -- height = height - 1
  3242.         -- built = built - 1 not required as next block is water source: not detected
  3243.         return built -- , height
  3244.     end
  3245.    
  3246.     function lib.stackBuckets(withSort)
  3247.         if withSort == nil then withSort = false end
  3248.         local data = {}
  3249.         local bucketSlot = 0
  3250.         local emptySlots = 0
  3251.         local water = 0
  3252.         if withSort then
  3253.             T:sortInventory()
  3254.         end
  3255.         for i = 1, 16 do
  3256.             -- find first empty bucket
  3257.             if turtle.getItemCount(i) > 0 then
  3258.                 data = turtle.getItemDetail(i)
  3259.                 if data.name == "minecraft:bucket" then
  3260.                     if bucketSlot == 0 then
  3261.                         bucketSlot = i
  3262.                     else
  3263.                         turtle.select(i)
  3264.                         turtle.transferTo(bucketSlot)
  3265.                     end
  3266.                 elseif data.name == "minecraft:water_bucket" then
  3267.                     water = water + 1
  3268.                 end
  3269.             else
  3270.                 emptySlots = emptySlots + 1
  3271.             end
  3272.         end
  3273.         return emptySlots, water
  3274.     end
  3275.    
  3276.    
  3277.     T:go("C1R1")                                                -- place block next to ladder support block, turn right to check ladder
  3278.     local blockType = T:getBlockType("forward")                 -- Is there a ladder to the right?
  3279.     if blockType:find("ladder") == nil then
  3280.         T:go("C1L2")                                            -- Place block as ladder not present
  3281.     else                                                        -- ladder present
  3282.         T:go("L2")                                              -- ready to check other side
  3283.     end
  3284.     blockType = T:getBlockType("forward")
  3285.     if blockType:find("ladder") == nil then
  3286.         T:go("C1R1")
  3287.     else
  3288.         T:go("R1")
  3289.     end
  3290.     blockType = T:getBlockType("down")
  3291.     local dirt = "minecraft:dirt"
  3292.     if T:getItemSlot("minecraft:soul_sand") > 0 then
  3293.         dirt = "minecraft:soul_sand"
  3294.     end
  3295.     if blockType:find("bedrock") ~= nil then
  3296.         utils.goBack(1)
  3297.         T:place(dirt, -1, "forward", false)                     -- placed at end of potential water source, next to ladder
  3298.     else
  3299.         T:place(dirt, -1, "down", false)                        -- placed in ground, next to ladder
  3300.         utils.goBack(1)
  3301.         T:placeWater("forward")                             -- place extra water source
  3302.     end
  3303.     T:go("R1C1 R2C1 L1F1C2 R1C1 L2C1 R1F1C2 R1C1 L1C1 L1C1 L1F1", false, 0, true)
  3304.     -- ready for water sources to be placed
  3305.     T:placeWater("forward")                                 -- place front water source
  3306.     T:turnRight(2)                                          -- facing backward
  3307.     T:placeWater("forward")                                 -- place back water source
  3308.     T:go("R2U1")                                            -- facing forward, U1, above centre of water source
  3309.     lib.fillBuckets(R.height, true)                         -- fill as many buckets as required or until inventory full, sort inventory as well
  3310.     local nextToLadder = false
  3311.     --T:go("F2R1")
  3312.     T:go("x0F1 x0F1C1 R1")                                  -- move forward 2 taking out blocks above, plug behind soul sand
  3313.     if T:getBlockType("forward"):find("ladder") == nil then -- no ladder here
  3314.         T:turnLeft(2)
  3315.         if T:getBlockType("forward"):find("ladder") ~= nil then -- ladder here
  3316.             nextToLadder = true
  3317.         end
  3318.         T:turnRight(1)
  3319.     else
  3320.         nextToLadder = true
  3321.         T:turnLeft(1)
  3322.     end
  3323.     -- now above soul sand, facing forward
  3324.     if nextToLadder then                                -- if nextToLadder, no need for signs
  3325.         utils.goBack(2)                                 -- return to source centre
  3326.     else
  3327.         T:go("F2 L1C1R1C1R1C1L1", false, 0, true)       -- prepare layer 1
  3328.         lib.addSign()
  3329.         T:go("U1F1R1F1 L1C1R1C1R1C1L1", false, 0, true) -- prepare layer 2
  3330.         lib.addSign()
  3331.         T:go("L1F1 R1F1R1", false, 0, true)             -- above source, level 2
  3332.     end
  3333.     -- ready to build lift
  3334.     lib.buildLift(R.height - 1)
  3335.     lib.cleanUp(R.height - 1)
  3336.    
  3337.     return {"Bubble lift created", "Check correct operation", "Check exit before using" }
  3338. end
  3339.  
  3340. local function createBubbleTrap(R) -- 34
  3341.     --[[
  3342.     Replace floor of existing volume of water with soulsand
  3343.     Used in river biome for squid farm. Area should be enclosed
  3344.     with solid walls surface to floor.
  3345.     Usually 7 blocks wide
  3346.     ]]
  3347.     local lib = {}
  3348.    
  3349.     function lib.clearDown(depth)
  3350.         while utils.clearVegetation("down") do
  3351.             T:down(1)
  3352.             depth = depth + 1
  3353.         end
  3354.         T:place("soul_sand", -1, "down", false)
  3355.         return depth
  3356.     end
  3357.    
  3358.     function lib.clearLength(length, depth)
  3359.         local moves = 0
  3360.         while moves < length - 1 do
  3361.             if utils.clearVegetation("forward") then
  3362.                 T:forward(1)
  3363.                 moves = moves + 1
  3364.                 depth = lib.clearDown(depth) -- go down if in water/air
  3365.                 if moves >= length - 1 then
  3366.                     return depth
  3367.                 end
  3368.             else -- block in front
  3369.                 local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
  3370.                 while not waterAhead do     -- solid block in front
  3371.                     T:up(1)
  3372.                     depth = depth - 1
  3373.                     if depth < 1 then
  3374.                         return 0
  3375.                     end
  3376.                     waterAhead = utils.clearVegetation("forward")
  3377.                 end
  3378.             end
  3379.         end
  3380.  
  3381.         return depth
  3382.     end
  3383.    
  3384.     function lib.turn(facingForward, depth)
  3385.         local direction = "R"
  3386.         if not facingForward then
  3387.             direction = "L"
  3388.         end
  3389.         T:go(direction.. 1)
  3390.         if utils.clearVegetation("forward") then
  3391.             T:forward(1)
  3392.             depth = depth + lib.clearDown(depth)
  3393.         else
  3394.             while not utils.clearVegetation("forward") do
  3395.                 T:up(1)
  3396.                 depth = depth - 1
  3397.             end
  3398.         end
  3399.         T:go(direction.. 1)
  3400.        
  3401.         return depth
  3402.     end
  3403.    
  3404.     local depth = 0
  3405.     local length = 0
  3406.     local width = 0
  3407.     local outbound = true
  3408.     local facingForward = true
  3409.     local inWater, onWater = utils.getWaterStatus()
  3410.     inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,true) -- move into water, max descent 2
  3411.     if R.length == 0 then
  3412.         R.length = lib.getLength()
  3413.     end
  3414.     if R.width == 0 then
  3415.         T:turnRight(1)
  3416.         R.width = lib.getLength()
  3417.         T:turnLeft(1)
  3418.     end
  3419.     -- go down to floor
  3420.     depth = lib.clearDown(depth)
  3421.     while width < R.width do
  3422.         -- now on floor, move along sea/river bed following contour
  3423.         depth = lib.clearLength(R.length, depth)
  3424.         width = width + 1
  3425.         -- now turn and repeat
  3426.         if width < R.width then
  3427.             depth = lib.turn(facingForward, depth)
  3428.             facingForward = not facingForward
  3429.         end
  3430.     end
  3431.     -- finished so return to surface
  3432.     T:up(1) -- up 1 to check for water below
  3433.     while T:isWater("down") do
  3434.         T:up(1)
  3435.     end
  3436.    
  3437.     return {}
  3438. end
  3439.  
  3440. local function createCorridor(R) -- 52
  3441.     --[[create a corridoor 2 blocks high, with floor and ceiling guaranteed
  3442.     T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)]]
  3443.     local lib = {}
  3444.    
  3445.     function lib.continue(R, currentSteps, totalSteps)
  3446.         if not R.silent then
  3447.             if currentSteps >= 64 and R.length == 0 then
  3448.                 -- request permission to continue if infinite
  3449.                 T:clear()
  3450.                 print("Completed "..totalSteps..". Ready for 64 more")
  3451.                 print("Do you want to continue? (y/n)")
  3452.                 response = read()
  3453.                 if response:lower() ~= "y" then
  3454.                     return true, 0
  3455.                 else
  3456.                     return false, currentSteps
  3457.                 end
  3458.             end
  3459.         end
  3460.         return true, currentSteps
  3461.     end
  3462.    
  3463.     function lib.seal()
  3464.         local blockType = T:getBlockType("forward")
  3465.         if blockType:find("water") ~= nil then
  3466.             T:place("stone", 0, "forward", false)
  3467.             return "water"  -- water found
  3468.         elseif blockType:find("lava") ~= nil then
  3469.             T:place("stone", 0, "forward", false)
  3470.             return "lava"   -- lava found
  3471.         end
  3472.         return ""   -- no water or lava
  3473.     end
  3474.    
  3475.     function lib.checkSeal(R)
  3476.         local fluidType = ""
  3477.         if R.data == "seal" then        -- check for lava/water at the sides
  3478.             T:turnRight(1)
  3479.             fluidType = lib.seal()      -- could be "", "water", "lava"
  3480.             T:turnLeft(2)
  3481.             local blockType = lib.seal()
  3482.             if fluidType == "" then     -- no water / lava so far
  3483.                 fluidType = blockType   -- could be "", "water", "lava"
  3484.             end
  3485.             T:turnRight(1)
  3486.         end
  3487.         return fluidType                -- could be "", "water", "lava"
  3488.     end
  3489.    
  3490.     function lib.placeTorch(R, torchSpaces, totalSteps)
  3491.         if R.torchInterval > 0 then -- torches onboard
  3492.             if torchSpaces == R.torchInterval then -- time to place another torch
  3493.                 if totalSteps < R.length then -- not at end of run
  3494.                     if T:getItemSlot("minecraft:torch") > 0 then
  3495.                         T:place("minecraft:torch", -1, "down")
  3496.                     end
  3497.                     torchSpaces = 1
  3498.                 end
  3499.             end
  3500.         end
  3501.         return torchSpaces -- original value or 1
  3502.     end
  3503.    
  3504.     local currentSteps = 0                  -- counter for infinite length. pause every 64 blocks
  3505.     local totalSteps = 0                    -- counter for all steps so far
  3506.     local torchSpaces = R.torchInterval     -- if torches present, counter to place with 8 blocks between
  3507.     local fluidType = ""
  3508.     local damLength = 0
  3509.     local damStarted = false
  3510.     local doContinue = true
  3511.     if T:getItemSlot("minecraft:torch") == 0 then
  3512.         R.torchInterval = 0 -- set to default 9 in getTask()
  3513.     end
  3514.     for steps = 1, R.length do
  3515.         -- starts on floor of tunnel
  3516.         doContinue, currentSteps = lib.continue(R, currentSteps, totalSteps) -- continue tunnelling?
  3517.         if not doContinue then
  3518.             break
  3519.         end
  3520.         T:go("C2U1C0", false, 0, true)      -- place floor, up 1, place ceiling
  3521.         fluidType = lib.checkSeal(R)        -- if R.data == "seal", check for water/lava at ceiling level
  3522.         if fluidType == "" then -- either R.data ~= "seal" or no fluid found
  3523.             torchSpaces = lib.placeTorch(R, torchSpaces, totalSteps) -- original value or 1 if torch placed
  3524.             T:go("F1D1")
  3525.         elseif fluidType == "water" then
  3526.             T:go("F1R2 C1D1 C1L2", false, 0, true)
  3527.             damStarted = true
  3528.             damLength = damLength + 1
  3529.         else    --lava
  3530.             T:go("F1D1")
  3531.         end
  3532.         blockType = lib.checkSeal(R)
  3533.         if blockType ~= "" then
  3534.             fluidType = blockType
  3535.         end
  3536.         currentSteps = currentSteps + 1
  3537.         totalSteps = totalSteps + 1
  3538.         torchSpaces = torchSpaces + 1
  3539.         if damStarted and fluidType == "" then -- was in water, but no more
  3540.             T:go("R2 F"..damLength + 1 .."U1L2F"..damLength + 1 .."D1")
  3541.             damStarted = false
  3542.         end
  3543.     end
  3544.     if fluidType ~= "" then -- water or lava found while tunnelling
  3545.         T:go("U1C0", false, 0, true)
  3546.         lib.checkSeal(R)
  3547.         T:go("C1", false, 0, true)
  3548.         T:down(1)
  3549.     end
  3550.     return {}
  3551. end
  3552.  
  3553. local function createDragonTrap() -- 49
  3554.     local lib = {}
  3555.    
  3556.     function lib.attack()
  3557.         local totalHitsF = 0
  3558.         local totalHitsU = 0
  3559.         local totalHitsD = 0
  3560.         while true do
  3561.             local hitF = false
  3562.             local hitU = false
  3563.             local hitD = false
  3564.             if turtle.attackUp() then
  3565.                 hitU = true
  3566.                 totalHitsU = totalHitsU + 1
  3567.             end
  3568.             if turtle.attackDown() then
  3569.                 hitD = true
  3570.                 totalHitsD = totalHitsD + 1
  3571.             end
  3572.             if turtle.attack() then
  3573.                 hitF = true
  3574.                 totalHitsF = totalHitsF + 1
  3575.             end
  3576.             if hitF or hitU or hitD then
  3577.                 print("hits forward: "..totalHitsF..", up: "..totalHitsU..", down: "..totalHitsD)
  3578.             end
  3579.         end
  3580.     end
  3581.     -- build up 145 blocks with ladders
  3582.     T:clear()
  3583.     menu.colourPrint("Press Enter to start 1 minute delay\n", colors.red)
  3584.     menu.colourPrint("Run to island centre across the bridge\n", colors.orange)
  3585.     menu.colourPrint("You have already made the bridge?...", colors.lime)
  3586.     read()
  3587.     for t = 60, 1, -1 do
  3588.         sleep(1)
  3589.         T:clear()
  3590.         io.write("Starting in "..t.. " seconds ")
  3591.     end
  3592.     for i = 1, 145 do
  3593.         T:go("U1C2")
  3594.         turtle.back()
  3595.         T:place("minecraft:ladder", -1, "down")
  3596.         turtle.forward()
  3597.     end
  3598.     T:go("R2F1C1 L1C1 L2C1 R1")
  3599.     for i = 1, 100 do
  3600.         T:go("F1C2U1C0D1")
  3601.     end
  3602.     T:forward(1)
  3603.     T:place("minecraft:obsidian", -1, "down")
  3604.     T:go("R2F1x2R2")
  3605.     T:placeWater("forward")
  3606.     T:go("R2F6R2")
  3607.     lib.attack()
  3608.    
  3609.     return {}
  3610. end
  3611.    
  3612. local function createEnderTower(stage) -- 66
  3613.     --[[ lower base = stage 1, upper base = 2, tower = 3 ]]
  3614.     local lib = {}
  3615.     --[[ go(path, useTorch, torchInterval, leaveExisting, preferredBlock) ]]
  3616.     function lib.getEmptySlots()
  3617.         local empty = 0
  3618.         for i = 1, 16 do
  3619.             if turtle.getItemCount(i) == 0 then
  3620.                 empty = empty + 1
  3621.             end
  3622.         end
  3623.         return empty
  3624.     end
  3625.  
  3626.     function lib.getStone(direction, stacks)
  3627.         --[[ get block user wants to use ]]
  3628.         local suck = turtle.suck   
  3629.         if direction == "down" then
  3630.             suck = turtle.suckDown
  3631.         end
  3632.         if T:getBlockType(direction) == "minecraft:chest" then
  3633.             T:sortInventory()
  3634.             local slot = T:getFirstEmptySlot() --find spare slot
  3635.             if slot > 0 then --empty slot found
  3636.                 turtle.select(1)
  3637.                 if stacks == 0 then
  3638.                     while suck() do end
  3639.                 else
  3640.                     for i = 1, stacks do -- get # stacks of stone from chest
  3641.                         suck()
  3642.                     end
  3643.                 end
  3644.                 if T:getSlotContains(slot) == "" then
  3645.                     return T:getMostItem()              -- empty chest
  3646.                 else
  3647.                     return T:getSlotContains(slot)      -- use this as default building block
  3648.                 end
  3649.             else
  3650.                 return T:getMostItem()              -- full inventory
  3651.             end
  3652.         else
  3653.             return T:getMostItem()              -- no chest
  3654.         end
  3655.     end
  3656.    
  3657.     function lib.stackBuckets()
  3658.         local data = {}
  3659.         local bucketSlot = 0
  3660.         local emptySlots = 0
  3661.         local water = 0
  3662.         T:sortInventory()
  3663.         for i = 1, 16 do
  3664.             -- find first empty bucket
  3665.             if turtle.getItemCount(i) > 0 then
  3666.                 data = turtle.getItemDetail(i)
  3667.                 if data.name == "minecraft:bucket" then
  3668.                     if bucketSlot == 0 then
  3669.                         bucketSlot = i
  3670.                     else
  3671.                         turtle.select(i)
  3672.                         turtle.transferTo(bucketSlot)
  3673.                     end
  3674.                 elseif data.name == "minecraft:water_bucket" then
  3675.                     water = water + 1
  3676.                 end
  3677.             else
  3678.                 emptySlots = emptySlots + 1
  3679.             end
  3680.         end
  3681.         return emptySlots, water
  3682.     end
  3683.    
  3684.     function lib.countWaterBuckets()
  3685.         local data = {}
  3686.         local buckets = 0
  3687.         for i = 1, 16 do
  3688.             data = turtle.getItemDetail(i)
  3689.             if data.name == "minecraft:water_bucket" then
  3690.                 buckets = buckets + 1
  3691.             end
  3692.         end
  3693.         return buckets
  3694.     end
  3695.    
  3696.     function lib.baseRun(preferredBlock, count, turn)
  3697.         for i = 1, count do
  3698.             T:go("C2F1", false, 0, false, preferredBlock)
  3699.         end
  3700.         T:go("C2"..turn, false, 0, false, preferredBlock)
  3701.     end
  3702.    
  3703.     function lib.outsideRun(preferredBlock)
  3704.         T:place("fence", -1, "down", false)
  3705.         T:forward(1)
  3706.         T:place(preferredBlock, -1, "down", false)
  3707.         T:forward(1)
  3708.         T:place(preferredBlock, -1, "down", false)
  3709.         T:forward(2)
  3710.         T:place(preferredBlock, -1, "down", false)
  3711.     end
  3712.    
  3713.     function lib.signRun(preferredBlock ,message)
  3714.         T:place(preferredBlock, -1, "down", false)
  3715.         T:forward(4)
  3716.         T:place(preferredBlock, -1, "down", false)
  3717.         turtle.back()
  3718.         turtle.back()
  3719.         T:down(1)
  3720.         T:place("sign", -1, "forward", false, message)
  3721.         T:go("U1F2")
  3722.     end
  3723.    
  3724.     function lib.goToWater(height)
  3725.         local built = 0 -- measures completed lift height
  3726.         while turtle.down() do -- takes turtle to bottom of water source
  3727.             height = height + 1
  3728.             if turtle.detect() then
  3729.                 built = built + 1
  3730.             end
  3731.         end
  3732.         T:up(1) -- above watersource assuming it is 1-1.5 blocks deep
  3733.         height = height - 1
  3734.         -- built = built - 1 not required as next block is water source: not detected
  3735.         return built, height
  3736.     end
  3737.    
  3738.     function lib.fillBuckets(toBuild)
  3739.         local emptySlots, water = lib.stackBuckets() -- gets no of empty slots + no of water buckets
  3740.         if water < toBuild then -- no of water buckets onboard less than required quantity
  3741.             for i = 1, toBuild do -- fill required no of buckets up to max space in inventory
  3742.                 emptySlots = lib.getEmptySlots()
  3743.                 if emptySlots == 0 then -- inventory full
  3744.                     break
  3745.                 else
  3746.                     if T:getWater("down") then
  3747.                         water = water + 1
  3748.                         sleep(0.5)
  3749.                     end
  3750.                 end
  3751.             end
  3752.         end
  3753.        
  3754.         return water
  3755.     end
  3756.    
  3757.     function lib.buildLift(preferredBlock)
  3758.         local built = 0 -- measures completed lift height
  3759.         local height = 0 -- measures total height from starting position
  3760.         built, height = lib.goToWater(height) -- returns lift blocks already placed, total height of drop from starting point
  3761.         local toBuild = height - built -- no of blocks to increase lift size
  3762.         while toBuild > 0 do -- at least 1 block height remaining
  3763.             local water = lib.fillBuckets(toBuild) -- no of water buckets onboard (could be more than required)
  3764.             if water > toBuild then
  3765.                 water = toBuild
  3766.             end
  3767.             while turtle.detect() do -- climb to top of existing lift
  3768.                 turtle.up()
  3769.                 height = height - 1
  3770.             end
  3771.             T:forward(1)
  3772.             for i = 1, water do -- build lift by no of water buckets
  3773.                 if T:placeWater("forward")  then
  3774.                     T:up(1)
  3775.                     height = height - 1
  3776.                     toBuild = toBuild - 1
  3777.                     T:place(preferredBlock, -1, "down", false)
  3778.                 end
  3779.             end
  3780.             turtle.back()
  3781.             -- may still be some height to complete, but needs refill
  3782.             if toBuild > 0 then
  3783.                 lib.goToWater(0) --return to source
  3784.                 lib.fillBuckets(toBuild)
  3785.             end
  3786.         end
  3787.         if height > 0 then -- if any remaining distance
  3788.             T:up(height)
  3789.         end
  3790.        
  3791.     end
  3792.    
  3793.     function lib.buildSection(preferredBlock, solid)
  3794.         -- builds a section without any blocks in the centre
  3795.         -- second layer of each section end walls have fence posts
  3796.         T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- first side solid row
  3797.         if solid then -- first layer of each section
  3798.             T:go("F1C2 F1R1", false, 0, false, preferredBlock) -- top side solid row
  3799.         else
  3800.             T:go("F1") -- top side solid row
  3801.             if not T:place("fence", -1, "down", false) then-- first side
  3802.                 T:place(preferredBlock, -1, "down", false)
  3803.             end
  3804.             T:go("F1R1") -- top side solid row
  3805.         end
  3806.         T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- far side solid row
  3807.         T:go("F1C2 F1R1U1", false, 0, false, preferredBlock) -- bottom side solid row
  3808.     end
  3809.     --[[
  3810.         clsTurtle methods:
  3811.         clsTurtle.place(self, blockType, damageNo, direction, leaveExisting)
  3812.         clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
  3813.     ]]
  3814.     -- remove 1 stack stone from chest
  3815.     local preferredBlock = lib.getStone("down", 1) -- use this as default building block
  3816.     if stage == 1 then
  3817.         -- build base floor
  3818.         --T:go("R2F2R1F3R1", false, 0, false, preferredBlock)
  3819.         T:go("R2F1C2R1F1C2F1C2F1C2R1", false, 0, false, preferredBlock)
  3820.         for i = 1, 2 do
  3821.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  3822.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  3823.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  3824.         end
  3825.         -- move back to centre, build water source, with soul sand at base of first source
  3826.         --T:go("R1F3L1C2F1C2F2D1", false, 0, false, preferredBlock) --just behind chest, 1 below ground level
  3827.         T:go("R1F3L1F2C2F1D1", false, 0, false, preferredBlock) --1 block behind chest, 1 below ground level
  3828.         T:place("minecraft:soul_sand", -1, "down", false) -- over block 1 of water source
  3829.         T:go("F1C2F1C2", false, 0, false, preferredBlock) -- over block 2 of water source
  3830.         T:go("F1C2U1C2", false, 0, false, preferredBlock) -- over block 4 of water source
  3831.         T:go("F1C2F1C2R2F5R2", false, 0, false, preferredBlock) -- over block 1 of water source
  3832.         T:placeWater("down")
  3833.         T:forward(2) -- over block 3 of water source
  3834.         T:placeWater("down")
  3835.         turtle.back() -- over block 2 of water source
  3836.         T:getWater("down")
  3837.         T:go("F2D1R2C2") -- over block 4 of water source
  3838.         T:go("U1", false, 0, false, preferredBlock)
  3839.         T:placeWater("down")
  3840.         T:forward(4)
  3841.         lib.stackBuckets() -- put all buckets in same slot
  3842.         T:dropItem("minecraft:dirt", "up", 0) -- drop dirt up:  clsTurtle.dropItem(self, item, direction, keepAmount)
  3843.         preferredBlock = lib.getStone("down", 6)
  3844.         T:go("R1F2R1U1") -- move to start position
  3845.         for i = 1, 2 do
  3846.             -- build first level of tower: 2 x outside run, 2 x sign run
  3847.             lib.outsideRun(preferredBlock)
  3848.             if i == 1 then -- place door
  3849.                 T:go("L1F1L1F1L1D1")
  3850.                 T:place("door", -1, "forward", false)
  3851.                 T:go("U1L1F1R1F1L1")
  3852.             end
  3853.             T:go("R1F1R1")
  3854.             lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
  3855.             T:go("L1F1L1C2", false, 0, false, preferredBlock)
  3856.             T:forward(4) -- miss out centre block
  3857.             T:place(preferredBlock, -1, "down", false)
  3858.             T:go("R1F1R1")
  3859.             lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
  3860.             T:go("L1F1L1")
  3861.             lib.outsideRun(preferredBlock)
  3862.             if i == 1 then -- layer 1
  3863.                 T:go("R1F1R1F1R1D1") -- place door
  3864.                 T:place("door", -1, "forward", false)
  3865.                 T:go("U1 R1F1 L1F5 L1U1 F2D1  F2R2 U1") -- go over door
  3866.             else -- layer 2
  3867.                 T:go("L1F5L1F6R2U1") -- over corner of lower platform
  3868.             end
  3869.         end
  3870.         for i = 1, 2 do -- build both sides of platform, leave centre missing
  3871.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  3872.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  3873.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  3874.         end
  3875.         T:go("R1F3L1C2F1C2F1C2F4C2F1C2F1C2", false, 0, false, preferredBlock) --fill in centre row
  3876.         --T:go("R2F6R1F1R1U1") -- go to start of tower base
  3877.         T:go("R2F7R2D3") -- go to start on top of chest
  3878.         T:sortInventory()
  3879.     elseif stage == 2 then
  3880.         -- start on top of chest, should have sufficient stone in inventory
  3881.         T:go("U3L1F1R1F1U1") -- go to start of tower base
  3882.         for i = 1, 7 do -- build 14 block high tower
  3883.             lib.buildSection(preferredBlock, false)
  3884.             lib.buildSection(preferredBlock, true)
  3885.         end
  3886.         T:go("R2F4R1F4R1", false, 0, false, preferredBlock) -- build upper platform (154 blocks remaining)
  3887.         for i = 1, 2 do -- build both sides of upper platform, leave centre missing
  3888.             lib.baseRun(preferredBlock, 12, "R1F1R1")
  3889.             lib.baseRun(preferredBlock, 12, "L1F1L1")
  3890.             lib.baseRun(preferredBlock, 12, "R1F1R1")
  3891.             lib.baseRun(preferredBlock, 12, "L1F1L1")
  3892.             lib.baseRun(preferredBlock, 12, "R1F6R1")
  3893.         end
  3894.         T:go("R1F5 L1C2 F1C2 F1C2 F1C2 F1C2 F4C2 F1C2 F1C2 F1C2 F1C2 ", false, 0, false, preferredBlock) --fill in centre row
  3895.         T:go("R2F5") -- return to drop area
  3896.         lib.buildLift(preferredBlock) -- build bubble lift
  3897.         T:go("F3R1F1R1U1") -- go to start of tower base
  3898.         T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock)      -- left side layer 21
  3899.         T:go("F2C2 F2C2 L1F1L1", false, 0, false, preferredBlock)   -- centre layer 21
  3900.         T:go("C2F4 C2R2U1", false, 0, false, preferredBlock)        -- right side layer 21
  3901.         T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock)      -- right side layer 22
  3902.         T:place("fence", -1, "down", false)                         -- fence centre of bottom side layer 22
  3903.         T:go("F2C2 F2L1F1L1", false, 0, false, preferredBlock)      -- centre layer 22
  3904.         T:go("C2F4 C2R2F2L1F1R2D2", false, 0, false, preferredBlock) --ready to place ladder
  3905.         T:place("ladder", -1, "forward", false)
  3906.         T:up(1)
  3907.         T:place("ladder", -1, "forward", false)
  3908.         --T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
  3909.         T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
  3910.         for i = 1, 2 do -- build both sides of platform, leave centre missing
  3911.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  3912.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  3913.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  3914.         end
  3915.         T:go("R1F3 L1C2 F1C2 F1C2 F1", false, 0, false, preferredBlock) --fill in centre row
  3916.         T:place("minecraft:soul_sand", -1, "down", false)
  3917.         T:go("F1C2 F2C2 F1C2 F1C2", false, 0, false, preferredBlock)
  3918.         T:go("R2F6R1F1R1U1") -- go to start of tower base
  3919.         -- build 2 levels, finish signs and ladders
  3920.         T:go("C2F2 R1D2 U1", false, 0, false, preferredBlock)
  3921.         T:place("ladder", -1, "down", false)
  3922.         T:turnRight(1)
  3923.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3924.         T:go("U1R2F2C2 R1F2C2 R1", false, 0, false, preferredBlock) --top right corner
  3925.         T:go("F4C2B2D1", false, 0, false, preferredBlock)
  3926.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3927.         T:go("U1F2R1F1C2F1R1U1", false, 0, false, preferredBlock) --ready for second level
  3928.         T:go("C2F2 R2D1", false, 0, false, preferredBlock)
  3929.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3930.         T:go("U1R2F2C2R1", false, 0, false, preferredBlock) --top left corner
  3931.         T:go("F1R1C2F4C2", false, 0, false, preferredBlock) --mid bottom row
  3932.         T:go("L1F1L1C2", false, 0, false, preferredBlock) -- bottom right corner
  3933.         T:go("F2R2D1", false, 0, false, preferredBlock)
  3934.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3935.         T:go("U1R2F2C2", false, 0, false, preferredBlock) -- top right corner
  3936.         -- return to chest
  3937.         T:go("L1F1L1 F5D23R2", false, 0, false, preferredBlock) -- return to chest
  3938.         T:sortInventory()
  3939.     elseif stage == 3 then
  3940.         --[[ move to top of structure
  3941.         | 4 |
  3942.         |3 5|
  3943.         | X |
  3944.         |2 6|
  3945.         | 1 |
  3946.         ]]
  3947.         local towerHeight = 128 -- even no only suggest 128
  3948.         while turtle.detect() do
  3949.             turtle.up()
  3950.         end
  3951.         T:go("F1U1", false, 0, false, preferredBlock) -- return to finish tower
  3952.         for i = 1, towerHeight do -- 1
  3953.             T:go("C2U1", false, 0, false, preferredBlock)
  3954.         end
  3955.         T:go("F1L1F1R1D2")
  3956.         while turtle.down() do -- 2
  3957.             T:fillVoid("up", {preferredBlock})
  3958.         end
  3959.         T:go("F1R2C1R2F1D1", false, 0, false, preferredBlock)
  3960.         for i = 1, towerHeight / 2 do -- 3
  3961.             T:go("U2C2", false, 0, false, preferredBlock)
  3962.         end
  3963.         T:go("U1F1R1F1R1D1", false, 0, false, preferredBlock) -- back of tower facing front
  3964.         local deviate = false
  3965.         while turtle.down() do -- 4
  3966.             T:place("fence", -1, "up", false)
  3967.             if turtle.down() then
  3968.                 T:fillVoid("up", {preferredBlock})
  3969.             else
  3970.                 T:go("F1R2C1R1F1R1D1", false, 0, false, preferredBlock)
  3971.                 deviate = true
  3972.                 break
  3973.             end
  3974.         end
  3975.         if not deviate then
  3976.             T:go("F1L1F1R1D1", false, 0, false, preferredBlock)
  3977.         end
  3978.         for i = 1, towerHeight / 2 do -- 5
  3979.             T:go("U2C2", false, 0, false, preferredBlock)
  3980.         end
  3981.         T:go("F2R2", false, 0, false, preferredBlock) -- facing back of tower
  3982.         while turtle.down() do -- 6
  3983.             T:fillVoid("up", {preferredBlock}) --layer 129
  3984.         end
  3985.         T:go("F1L2C1U"..towerHeight)
  3986.         T:go("F4R1F3R1U1", false, 0, false, preferredBlock)
  3987.         -- add small platform at the top
  3988.         lib.baseRun(preferredBlock, 8, "R1F1R1")
  3989.         lib.baseRun(preferredBlock, 8, "L1F3L1")
  3990.         lib.baseRun(preferredBlock, 8, "L1F1L1")
  3991.         lib.baseRun(preferredBlock, 8, "R1F1R1")
  3992.         T:go("C2 F1C2 F1C2 F4C2 F1C2 F1C2 R2F3", false, 0, false, preferredBlock) --fill in centre row
  3993.         lib.buildLift(preferredBlock) -- build bubble lift
  3994.     end
  3995.     return {}
  3996. end
  3997.  
  3998. local function createFarm(R, extend) -- 31
  3999.     -- if extend ~= nil then this has been called from createFarmExtension()
  4000.     -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  4001.     local lib = {}
  4002.     function lib.addWaterSource(R, pattern, storage)
  4003.         -- pattern = {"d","c","c","d"} t = place crafting  instead of dirt
  4004.         -- place(self, blockType, damageNo, direction, leaveExisting, signText)
  4005.         T:go("D1x2C2", false, 0, false, R.useBlockType)
  4006.         for i = 1, 4 do
  4007.             T:dig("forward")
  4008.             if pattern[i] == "d" then
  4009.                 T:place("dirt", -1, "forward", false)
  4010.             elseif pattern[i] == "t" then
  4011.                 --if not T:place("minecraft:crafting_table", -1, "forward", false) then
  4012.                 if T:place(storage, -1, "forward", false) then
  4013.                     if T:dropItem("crafting", "forward", 0) then
  4014.                         print("Crafting table -> buried storage")
  4015.                     end
  4016.                 else
  4017.                     T:place("dirt", -1, "forward", false) -- dirt if no storage available
  4018.                 end
  4019.             else
  4020.                 T:place(R.useBlockType, -1, "forward", false)
  4021.             end
  4022.             T:turnRight(1)
  4023.         end
  4024.         T:up(1)
  4025.         T:placeWater("down")
  4026.     end
  4027.    
  4028.     function lib.placeDirt(count, atCurrent)
  4029.         if atCurrent then
  4030.             local blockType = T:getBlockType("down")
  4031.             if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
  4032.                 T:place("dirt", -1, "down", false)
  4033.             end
  4034.         end
  4035.         for  i = 1, count do
  4036.             T:forward(1)
  4037.             T:dig("up")
  4038.             local blockType = T:getBlockType("down")
  4039.             if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
  4040.                 T:place("dirt", -1, "down", false)
  4041.             end
  4042.         end
  4043.     end
  4044.  
  4045.     function lib.placeStorage(storage, storageBackup)
  4046.         T:dig("down")
  4047.         if not T:place(storage, -1, "down", false) then-- place barrel/chest below
  4048.             T:place(storageBackup, -1, "down", false) -- place chest below
  4049.         end
  4050.     end
  4051.  
  4052.    
  4053.     -- extend "", "right" or "forward". only adds a single new farm.
  4054.     -- right adds farm and checks for existing front extensions, dealt with separately
  4055.     -- clsTurtle.place(blockType, damageNo, direction, leaveExisting)
  4056.     if extend == nil then
  4057.         extend = ""
  4058.     end
  4059.     local blockType = ""
  4060.     -- extend = "right": placed on cobble corner of existing farm facing right side
  4061.     -- extend = "front": placed on cobble corner of existing farm facing front
  4062.     -- else placed on ground at corner of potential new farm facing front
  4063.    
  4064.     local storage, storageBackup = utils.setStorageOptions()
  4065.     -- step 1 dig ditch round perimeter wall
  4066.     if extend == "right" then
  4067.         -- move to front corner ground ready for ditch
  4068.         T:go("F1L1F12D1R1", false, 0, false, R.useBlockType)
  4069.         -- cut ditch round new farm extension
  4070.         for i = 1, 12 do
  4071.             T:go("x0F1")
  4072.         end
  4073.         T:go("R1x0")
  4074.         for i = 1, 13 do
  4075.             T:go("x0F1")
  4076.         end
  4077.         T:go("R1x0")
  4078.         -- now at lower right corner. if extension below, do not cut ditch
  4079.         blockType = T:getBlockType("forward")
  4080.         if blockType:find("stone") ~= nil then -- already a farm extension on left side
  4081.             -- return to start for adding chests and walls
  4082.             T:go("U1R1F1L1F12", false, 0, false, R.useBlockType)
  4083.         else -- finish ditch
  4084.             for i = 1, 12 do
  4085.                 T:go("x0F1")
  4086.             end
  4087.             T:go("R1U1F1") -- on corner of new extension
  4088.         end
  4089.     elseif extend == "forward" then
  4090.         T:go("L1F2R1D1", false, 0, false, R.useBlockType)
  4091.         -- cut ditch round new farm extension
  4092.         for i = 1, 12 do
  4093.             T:go("x0F1", false, 0, false, R.useBlockType)
  4094.         end
  4095.         T:go("R1x0", false, 0, false, R.useBlockType)
  4096.         for i = 1, 13 do
  4097.             T:go("x0F1", false, 0, false, R.useBlockType)
  4098.         end
  4099.         T:go("R1x0", false, 0, false, R.useBlockType)
  4100.         for i = 1, 11 do
  4101.             T:go("x0F1", false, 0, false, R.useBlockType)
  4102.         end
  4103.         T:go("U1x0F1R1F12R1", false, 0, false, R.useBlockType) -- on corner of new extension
  4104.     else -- new farm. cut a groove round the entire farm base
  4105.         -- move to left side of intended wall
  4106.         T:go("L1F1x0R1", false, 0, false, R.useBlockType)
  4107.         for j = 1, 4 do
  4108.             for i = 1, 12 do
  4109.                 T:go("x0F1", false, 0, false, R.useBlockType)
  4110.             end
  4111.             T:go("R1x0F1", false, 0, false, R.useBlockType)
  4112.         end
  4113.         T:go("R1F1L1U1", false, 0, false, R.useBlockType)
  4114.     end
  4115.     -- stage 2 place sapling and double barrel/chest
  4116.     T:dig("down") --remove cobble if present
  4117.     T:place("dirt", -1, "down", false)
  4118.     T:go("F1R2")
  4119.     T:place("sapling", -1, "forward", false) -- plant sapling
  4120.     T:go("L1")
  4121.     lib.placeStorage(storage, storageBackup)
  4122.     T:go("L1F1R1")
  4123.     lib.placeStorage(storage, storageBackup)
  4124.     T:turnLeft(1)
  4125.     if extend == "right" then -- cobble wall exists so go forward to its end
  4126.         T:forward(9)
  4127.     else -- new farm or extend forward
  4128.         for i = 1, 9 do -- complete left wall to end of farm
  4129.             T:go("F1x0x2C2", false, 0, false, R.useBlockType)
  4130.         end
  4131.     end
  4132.     T:go("R1F1 R1x0 x2C2 F1D1", false, 0, false, R.useBlockType)-- turn round ready for first dirt col
  4133.     lib.addWaterSource(R, {"d","c","c","d"}, storage) -- water at top of farm
  4134.     lib.placeDirt(9, false) -- place dirt back to start
  4135.     lib.addWaterSource(R, {"c","c","t","d"}, storage) -- water source next to chests, includes crafting table
  4136.     T:go("U1F1R2")
  4137.     if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
  4138.         lib.placeStorage(storage, storageBackup)
  4139.     end
  4140.     T:go("R1F1L1")
  4141.     if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
  4142.         lib.placeStorage(storage, storageBackup)
  4143.     end
  4144.     T:go("F1D1")
  4145.     lib.placeDirt(9, true)
  4146.     local turn = "R"
  4147.     for i = 1, 7 do
  4148.         T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
  4149.         lib.placeDirt(9, true)
  4150.         if turn == "R" then
  4151.             turn = "L"
  4152.         else
  4153.             turn = "R"
  4154.         end
  4155.     end
  4156.     T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
  4157.     lib.addWaterSource(R, {"d","c","c","d"}, storage)
  4158.     lib.placeDirt(9, false)
  4159.     lib.addWaterSource(R, {"c","c","d","d"}, storage)
  4160.     T:go("F1U1R1C2x0F1x0x2C2R1", false, 0, false, R.useBlockType)
  4161.     for i = 1, 11 do
  4162.         T:go("F1x0x2C2", false, 0, false, R.useBlockType)
  4163.     end
  4164.     -- add barrel/chest to any existing farm extension to the right
  4165.     T:go("L1F1L1")
  4166.     if T:getBlockType("down"):find("stone") == nil then -- farm extension already exists to right
  4167.         lib.placeStorage(storage, storageBackup)
  4168.     end
  4169.     T:go("L1F11")
  4170.    
  4171.     return {"Modular farm completed"}
  4172. end
  4173.  
  4174. local function createFarmExtension(R) -- 32
  4175.     -- assume inventory contains 4 chests, 64 cobble, 128 dirt, 4 water, 1 sapling
  4176.     -- check position by rotating to face tree/sapling
  4177.     local doContinue = true
  4178.     local treePresent = false
  4179.     local extend = "right" -- default
  4180.     if R.subChoice == 1 then
  4181.         extend = "forward"
  4182.     end
  4183.     local storage, storageBackup = utils.setStorageOptions()
  4184.     local blockType = T:getBlockType("down")
  4185.     if blockType:find(storage) == nil and blockType:find(storageBackup) == nil then
  4186.         return
  4187.         {
  4188.             "Barrel or chest not present below\n",
  4189.             "Unable to calculate position",
  4190.             "Move me next to/front of the tree/sapling",
  4191.             "lower left corner of the existing farm."
  4192.         }
  4193.     else
  4194.         for i = 1, 4 do
  4195.             blockType = T:getBlockType("forward")
  4196.             if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
  4197.                 treePresent = true
  4198.                 break
  4199.             end
  4200.             T:turnRight()
  4201.         end
  4202.         if not treePresent then
  4203.             return
  4204.             {
  4205.                 "Unable to locate tree or sapling",
  4206.                 "Plant a sapling on the lower left",
  4207.                 "corner of the farm, or move me there"
  4208.             }
  4209.         end
  4210.     end
  4211.     if doContinue then -- facing tree. check if on front or l side of farm
  4212.         if extend == "forward" then
  4213.             T:go("R1F11") -- to other side of farm. may be stone or barrel/chest below
  4214.             blockType = T:getBlockType("down")
  4215.             if blockType:find(storage) ~= nil or blockType:find(storageBackup) ~= nil then
  4216.                 doContinue = false
  4217.             end
  4218.         else
  4219.             T:go("R2F9") -- to right of farm, may be sapling/tree in front
  4220.             blockType = T:getBlockType("forward")
  4221.             if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
  4222.                 doContinue = false
  4223.             end
  4224.         end
  4225.         if doContinue then -- extend farm.
  4226.             createFarm(R, extend)
  4227.         else
  4228.             return
  4229.             {
  4230.                 "This farm has already been extended",
  4231.                 "Move me next to/front of the tree / sapling",
  4232.                 "of the last extension in this direction."
  4233.             }
  4234.         end
  4235.     end
  4236.     return {"Modular crop farm extended"}
  4237. end
  4238.  
  4239. local function createFloorCeiling(R) -- 79 size integer 1 to 4
  4240.     --[[
  4241.     R.up = true for ceiling
  4242.     R.down = true for floor
  4243.     R.height = 0 for normal
  4244.     R.height combined with R.up/R.down used for remote access
  4245.     ]]
  4246.    
  4247.     local useBlock = T:getSlotContains(1)
  4248.     local waterPresent = false
  4249.    
  4250.     if R.useBlockType ~= "" then
  4251.         useBlock = R.useBlockType
  4252.     end
  4253.     print("Using ".. useBlock)
  4254.     local direction = "down"
  4255.     if R.up then
  4256.         direction = "up"
  4257.     end
  4258.     if R.height > 0 then -- remote placing. go up/down R.height first
  4259.         R.silent = true
  4260.         local depth = 0
  4261.         if R.down then -- floor could be under water
  4262.             while turtle.down() do
  4263.                 depth = depth + 1
  4264.             end
  4265.         elseif R.up then
  4266.             while turtle.up() do
  4267.                 depth = depth + 1
  4268.                 if depth > R.height + 3 then
  4269.                     break
  4270.                 end
  4271.             end
  4272.         end
  4273.         if not(R.height - depth <= 2 or depth - R.height <= 2) then
  4274.             T:up(depth)
  4275.             return {"Measured depth/height of "..depth.." > setting: "..R.height}
  4276.         end
  4277.         -- not returned so depth acceptable
  4278.     end
  4279.     -- check if block above/below
  4280.     local blockBelow = turtle.detectDown()
  4281.     local blockAbove = turtle.detectUp()
  4282.     if R.subChoice == 2 then -- New floor over existing
  4283.         -- if no block below, assume in correct position and continue
  4284.         -- else move up 1 and continue
  4285.         if blockBelow then T:up(1) end
  4286.     elseif R.subChoice == 4 then -- New ceiling under existing
  4287.         -- if no block above, assume in correct position and continue
  4288.         -- else move down 1 and continue
  4289.         if blockAbove then T:down(1) end
  4290.     end
  4291.    
  4292.     local evenWidth = false
  4293.     local evenHeight = false
  4294.     local loopWidth
  4295.     -- go(path, useTorch, torchInterval, leaveExisting)
  4296.     if R.width % 2 == 0 then
  4297.         evenWidth = true
  4298.         loopWidth = R.width / 2
  4299.     else
  4300.         loopWidth = math.ceil(R.width / 2)
  4301.     end
  4302.     if R.length % 2 == 0 then
  4303.         evenHeight = true
  4304.     end
  4305.     -- if R.width is even no, then complete the up/down run
  4306.     -- if R.width odd no then finish at top of up run and reverse
  4307.     for x = 1, loopWidth do
  4308.         -- Clear first column (up)
  4309.         local tAvailable = T:getStock(useBlock, -1)
  4310.         if tAvailable.total < R.length and not R.silent then
  4311.             return {"Insufficient resources to complete current row"}
  4312.         end
  4313.         for y = 1, R.length do
  4314.             local blockType = T:getBlockType("forward")
  4315.             if not waterPresent then
  4316.                 if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then
  4317.                     waterPresent = true
  4318.                 end
  4319.             end
  4320.             T:place(useBlock, -1, direction, false) -- leaveExisting = false
  4321.             if y < R.length then
  4322.                 T:go("F1", false, 0, false)
  4323.             end
  4324.         end
  4325.         -- clear second column (down)
  4326.         if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
  4327.             T:go("R1F1R1", false,0,false)
  4328.             tAvailable = T:getStock(useBlock, -1)
  4329.             if tAvailable.total < R.length and not R.silent then
  4330.                 return {"Insufficient resources to complete current row"}
  4331.             end
  4332.             for y = 1, R.length do
  4333.                 T:place(useBlock, -1, direction, false) -- leaveExisting = false
  4334.                 if y < R.length then
  4335.                     T:go("F1", false, 0, false)
  4336.                 end
  4337.             end
  4338.             if x < loopWidth then
  4339.                 T:go("L1F1L1", false,0,false)
  4340.             else
  4341.                 T:turnRight(1)
  4342.                 T:forward(R.width - 1)
  4343.                 T:turnRight(1)
  4344.             end
  4345.         else -- equals R.width but is 1,3,5,7 etc
  4346.             T:turnLeft(2) --turn round 180
  4347.             T:forward(R.length - 1)
  4348.             T:turnRight(1)
  4349.             T:forward(R.width - 1)
  4350.             T:turnRight(1)
  4351.         end
  4352.     end
  4353.     if waterPresent then
  4354.         return {"water or lava found"}
  4355.     end
  4356.     return {""}
  4357. end
  4358.  
  4359. local function createIceCanal(R) -- 55
  4360.     --[[
  4361.         R.subChoice =
  4362.         1: move right into canal, build left towpath
  4363.         2: build left towpath
  4364.         3: build right towpath
  4365.         4: move left into canal, build right towpath
  4366.         5/8: clear path 3 blocks high, place slabs/torches
  4367.         6/7: build alternating ice road / create 3 block high air gap (2 over water)
  4368.     ]]
  4369.     local oTurn = "R"
  4370.     if R.side == "R" then
  4371.         oTurn = "L"
  4372.     end
  4373.     local lib = {}
  4374.    
  4375.     function lib.convertTowpath(R)
  4376.         -- only used to convert existing water canal, so assume towpath already present
  4377.         -- starting position 1 block above existing towpath
  4378.         for i = 1, R.length do
  4379.             if turtle.detectDown() then                         -- eg existing torch
  4380.                 T:dig("down")
  4381.             end
  4382.             local placeSlab = true
  4383.             if R.torchInterval > 0 then                         -- place torches
  4384.                 if i == 1 or i % R.torchInterval == 0 then      -- ready to place torch
  4385.                     --go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  4386.                     T:go("C2x0", false, 0, false, R.useBlockType)-- place solid block below
  4387.                     T:go("F1R2x0")
  4388.                     T:place("torch", 0, "forward")              -- place torch, move forward
  4389.                     T:turnRight(2)                              -- turn round
  4390.                     placeSlab = false
  4391.                 end
  4392.             end
  4393.             if placeSlab then
  4394.                 T:dig("up")
  4395.                 if not T:place("slab", 0, "down") then          -- break if out of slabs
  4396.                     break
  4397.                 end
  4398.                 if i < R.length then
  4399.                     T:forward(1)                                -- move forward
  4400.                 end
  4401.             end
  4402.         end
  4403.     end
  4404.    
  4405.     function lib.iceCanalTowpath(R)
  4406.         -- move forward placing slabs along the way. If existing water canal, ceiling will be raised by 1 block
  4407.         local torchInterval = 0
  4408.         local placeIce = true
  4409.         for i = 1, R.length do
  4410.             local addTorch = false
  4411.             if R.torchInterval > 0 then
  4412.                 if i == 1 then addTorch = true end
  4413.                 if torchInterval >= R.torchInterval then
  4414.                     addTorch = true
  4415.                     torchInterval = 0
  4416.                 end
  4417.             end
  4418.             lib.iceCanalEdge(R, addTorch, i, placeIce)
  4419.             torchInterval = torchInterval + 1
  4420.             placeIce = not placeIce
  4421.         end
  4422.         T:go(oTurn.."1")
  4423.     end
  4424.    
  4425.     function lib.iceCanalEdge(R, addTorch, numBlocks, placeIce)
  4426.         -- starting position facing canal side
  4427.         local blockType = T:getBlockType("forward")         -- ? air / slab / other
  4428.         local isWater, isSource, isIce = T:isWater("down")  -- water / ice below
  4429.         if blockType:find("slab") == nil then               -- add slab
  4430.             if addTorch then                                -- check if torch needed
  4431.                 -- T:place(blockType, damageNo, direction, leaveExisting, signText)
  4432.                 if not T:place("stone", -1, "forward", false) then
  4433.                     T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
  4434.                 end
  4435.                 T:go("U1x1 U1x1 D1")                    -- water level to 2 above water level
  4436.                 if T:getItemSlot("minecraft:torch", -1) > 0 then
  4437.                     T:place("torch", -1, "forward", false)
  4438.                 end
  4439.                 T:down(1)                               -- back to above water level
  4440.                 if not isIce then                       -- break block below if NOT ice
  4441.                     T:dig("down")
  4442.                 end
  4443.             else
  4444.                 if not T:place("slab", -1, "forward", false) then
  4445.                     T:checkInventoryForItem({"slab"}, {R.length - numBlocks}, true)
  4446.                 end
  4447.                 if not isSource then                    -- NOT on water, so dig above
  4448.                     T:go("U1x1 U1x1 D2")
  4449.                 end
  4450.                 if not isIce and not isSource then
  4451.                     T:dig("down")
  4452.                 end
  4453.             end
  4454.         else -- slab already on side
  4455.             if addTorch then                            -- check if torch needed
  4456.                 T:dig("forward")
  4457.                 if not T:place("stone", -1, "forward", false) then
  4458.                     T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
  4459.                 end
  4460.                 T:go("U1x1 U1x1 D1")                    -- water level to 2 above water level
  4461.                 if T:getItemSlot("minecraft:torch", -1) > 0 then
  4462.                     T:place("torch", -1, "forward", false)
  4463.                 end
  4464.                 T:down(1)                               -- back to above water level
  4465.                 if not isIce then                       -- break block below if NOT ice
  4466.                     T:dig("down")
  4467.                 end
  4468.             end
  4469.         end
  4470.         if R.data == "ice" and placeIce and not isIce then -- R.data = "ice", placeIce = true, not already ice present
  4471.             T:place("ice", -1, "down", true)
  4472.         end
  4473.         if numBlocks < R.length then
  4474.             T:go(oTurn.."1F1"..R.side.."1")
  4475.         end
  4476.     end
  4477.    
  4478.     function lib.convertIcepath(length)
  4479.         -- use only for placing ice to convert a water canal
  4480.         -- place ice on alternate blocks until length reached or run out of ice
  4481.         local placeIce = true
  4482.         for i = 1, length do
  4483.             if T:getBlockType("down"):find("ice") == nil then -- no ice below
  4484.                 T:dig("down") -- remove any existing block
  4485.                 if placeIce then
  4486.                     if not T:place("ice", -1, "down", true) then -- out of ice
  4487.                         break
  4488.                     end
  4489.                     if i == length - 1 then
  4490.                         break
  4491.                     end
  4492.                 end
  4493.             else -- ice already below
  4494.                 placeIce = true
  4495.             end
  4496.             T:go("U1x0 D1F1")
  4497.             placeIce = not placeIce -- reverse action
  4498.         end
  4499.     end
  4500.    
  4501.     function lib.convertToAir(length)
  4502.         -- use only for converting a water canal. start at ground level
  4503.         -- dig up/down/forward to clear space
  4504.         for i = 1, length + 1 do
  4505.             T:go("U1x0D1")
  4506.             if i < length + 1 then
  4507.                 T:go("x2F1")
  4508.             else
  4509.                 T:dig("down")
  4510.             end
  4511.         end
  4512.     end
  4513.    
  4514.     function lib.initialise(R)
  4515.         if R.subChoice == 1 or R.subChoice == 4 then       
  4516.             local blockType = T:getBlockType("down")        -- ? at ground/water level or on top of existing slab
  4517.             if blockType:find("slab") ~= nil then           -- slab already present
  4518.                 T:go(oTurn.."1F1D1"..R.side.."2")           -- move right/left forward, down onto ice canal top, face canal wall
  4519.             elseif blockType:find("torch") ~= nil then
  4520.                 T:go(oTurn.."1F1D2"..R.side.."2")           -- move right/left forward, down onto ice canal top, face canal wall
  4521.             else                                            -- assume on ground / water level
  4522.                 T:go(oTurn.."1F1"..R.side.."2")             -- move right/left forward onto ice canal top, face canal wall
  4523.             end
  4524.         else
  4525.             if T:isWater("forward") then                    -- player put turtle inside canal water
  4526.                 T:up(1)
  4527.             end
  4528.             T:go(R.side.."1")                               -- face canal wall
  4529.         end
  4530.     end
  4531.    
  4532.     if R.length == 0 then R.length = 1024 end
  4533.  
  4534.     if R.subChoice <= 4  then                               -- towpath 1,2,3,4
  4535.         lib.initialise(R)                                   -- reposition
  4536.         lib.iceCanalTowpath(R)                              -- build towpath
  4537.     elseif R.subChoice == 5 or R.subChoice == 8 then        -- assume placed on towpath
  4538.         if T:getBlockType("down"):find("slab") ~= nil then  -- slab already present
  4539.             T:go("F1")
  4540.         else
  4541.             T:up(1)
  4542.         end
  4543.         lib.convertTowpath(R)
  4544.     elseif R.subChoice == 6 or R.subChoice == 7 then   
  4545.         if R.data == "ice" then                         -- assume placed on existing ice or initial ice position
  4546.             lib.convertIcepath(R.length)-- place ice
  4547.         else                                            -- assume placed on empty path
  4548.             lib.convertToAir(R.length)                  -- clear 3 high area
  4549.         end
  4550.     end
  4551.    
  4552.     return {}
  4553. end
  4554.  
  4555. local function createLadder(R) -- 12
  4556.     -- createLadder(R.data ="bedrock", R.height = 70, R.depth = -48)
  4557.     -- go(path, useTorch, torchInterval, leaveExisting)
  4558.     -- place(blockType, damageNo, direction, leaveExisting)
  4559.     local lib = {}
  4560.    
  4561.     function lib.placeLadder(direction, ledge, i, height)
  4562.         -- 1 check both sides and behind
  4563.         local fluid = false
  4564.         local block = T:isWaterOrLava("forward", ledge)
  4565.         if block:find("water") ~= nil or block:find("lava") ~= nil then
  4566.             --[[ surround 2 block shaft with blocks ]]
  4567.             T:go("R1C1 R1C1 R1C1 R1F1 L1C1 R1C1 R1C1 R1C1F1 R2C1 x1")
  4568.         else
  4569.             --[[ no water/lava so prepare ladder site]]
  4570.             T:go("F1 L1C1 R1C1 R1C1 L1B1", false, 0, true)
  4571.         end
  4572.         if not T:place("ladder", -1, "forward", false) then
  4573.             T:checkInventoryForItem({"ladder"}, {height - i}, false)
  4574.         end
  4575.         -- 3 check if ledge, torch
  4576.         if ledge == 0 and i > 1 then -- place block above unless new ladder
  4577.             T:place("common", -1, direction, false) -- any common block
  4578.         elseif ledge == 1 then
  4579.             T:place("minecraft:torch", -1, direction, false)
  4580.         elseif ledge == 2 then
  4581.             ledge = -1
  4582.         end
  4583.        
  4584.         return ledge
  4585.     end
  4586.    
  4587.     local retValue = {}
  4588.     local ledge = 0
  4589.     local height = math.abs(R.depth - R.height) --height of ladder
  4590.     local blockType = T:getBlockType("forward")
  4591.     if R.up then -- create ladder from current level to height specified
  4592.         for i = 1, height do -- go up, place ladder as you go
  4593.             ledge = lib.placeLadder("down", ledge, i, height) -- ladder placed forward, stone ledge for torch placed down
  4594.             if i <  height then
  4595.                 T:up(1)
  4596.                 ledge = ledge + 1
  4597.             end
  4598.         end    
  4599.     else -- R.down = true: ladder towards bedrock      
  4600.         local success = true
  4601.         local numBlocks, errorMsg = 0, ""
  4602.         T:down(1)
  4603.         for i = 1, height do -- go down, place ladder as you go
  4604.             ledge = lib.placeLadder("up", ledge, i, heigt) -- ladder placed forward, stone torch placed up
  4605.             --success, blocksMoved, errorMsg, blockType = clsTurtle.down(self, steps, getBlockType)
  4606.             if i < height then
  4607.                 success, numBlocks, errorMsg, blockType = T:down(1, true) -- true = return blockType
  4608.                 ledge = ledge + 1
  4609.             end
  4610.             -- if looking for stronghold then check for stone_bricks
  4611.             if blockType:find("stone_bricks") ~= nil then
  4612.                 table.insert(retValue, "Stronghold discovered")
  4613.                 break -- stop descent at stronghold
  4614.             end
  4615.         end
  4616.         -- if user requested shelter create chamber at this level
  4617.         if R.data == "chamber" then -- user has chosen to build a chamber
  4618.             table.insert(retValue, "Shelter constucted at level".. R.depth)
  4619.             if blockType:find("bedrock") ~= nil then
  4620.                 T:findBedrockTop(0) -- test to check if on safe level immediately above tallest bedrock
  4621.             end
  4622.             -- In shaft, facing start direction, on lowest safe level
  4623.             -- create a square space round shaft base, end facing original shaft, 1 space back
  4624.             T:go("L1n1 R1n3 R1n2 R1n3 R1n1", false, 0, true)
  4625.             T:go("U1Q1 R1Q3 R1Q2 R1Q3 R1Q1 R1D1", false, 0, true)
  4626.         end
  4627.     end
  4628.    
  4629.     return retValue
  4630. end
  4631.  
  4632. local function createLadderToWater(R) -- 86
  4633.     -- go down to water/lava with alternaate solid/open layers
  4634.     -- create a working area at the base
  4635.     -- Return to surface facing towards player placing ladders
  4636.     local inAir = true
  4637.     local numBlocks, errorMsg = 0, ""
  4638.     local height = 2
  4639.     local blockType = T:getBlockType("down")
  4640.     if blockType ~= "" then -- not over air
  4641.         T:forward(1)
  4642.     end
  4643.     T:go("R2D1") -- face player, go down 2
  4644.     while inAir do --success = false when hits water/lava
  4645.         blockType = T:isWaterOrLava("down")
  4646.         if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
  4647.             inAir = false
  4648.         end
  4649.         T:go("C1R1 C1R2 C1R1", false, 0, false) -- surround front  and sides with cobble
  4650.         if inAir then
  4651.             T:down(1)
  4652.             height = height + 1
  4653.         end
  4654.         T:place("ladder", 0, "up")
  4655.     end
  4656.     -- In shaft, facing opposite start direction, on water/lava, ladders above
  4657.     T:go("C2", false, 0, false)
  4658.     utils.goBack(1)
  4659.     T:place("ladder", 0, "forward")
  4660.     T:up(3)
  4661.     height = height - 3
  4662.     for i = 1, height do
  4663.         if i < height then
  4664.             T:go("C2U1", false, 0, false)
  4665.         else
  4666.             T:go("C2", false, 0, false)
  4667.         end
  4668.     end
  4669.  
  4670.     return {}
  4671. end
  4672.  
  4673. local function createMine() -- 11
  4674.     -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  4675.     T:clear()  
  4676.     T:go("m32U1R2M16", true, 8, true) -- mine ground level, go up, reverse and mine ceiling to mid-point
  4677.     T:go("U2D2") -- create space for chest
  4678.     T:place("minecraft:chest", -1, "up", false)
  4679.     T:emptyTrash("up")
  4680.     T:go("D1R1m16U1R2M16", true, 8, true) -- mine floor/ceiling of right side branch
  4681.     T:emptyTrash("up")
  4682.     T:go("D1m16U1R2M16", true, 8, true) -- mine floor/ceiling of left side branch
  4683.     T:emptyTrash("up")
  4684.     T:go("L1M15F1R1D1", true, 8, true) -- mine ceiling of entry corridor, turn right
  4685.     T:go("F1x0 F1x0 n14 R1n32 R1n32 R1n32 R1n14 F1x0 F1U1", true, 8, true)-- mine floor of 36 x 36 square corridor
  4686.     T:go("R1F16R2") --return to centre
  4687.     T:emptyTrash("up")
  4688.     T:go("F16R1") --return to entry shaft
  4689.     T:go("F2Q14R1Q32R1Q32R1Q32R1Q14F2R1", true, 8, true) --mine ceiling of 36x36 square corridor. return to entry shaft + 1
  4690.     T:go("F16R2") --return to centre
  4691.     T:emptyTrash("up")
  4692.     -- get rid of any remaining torches
  4693.     while T:getItemSlot("minecraft:torch", -1) > 0 do
  4694.         turtle.select(T:getItemSlot("minecraft:torch", -1))
  4695.         turtle.dropUp()
  4696.     end
  4697.     T:go("F16R1F1R1") --return to shaft + 1
  4698.     for i = 1, 8 do
  4699.         T:go("N32L1F1L1", true, 8, true)
  4700.         T:go("N16L1F"..(i * 2).."R2", true, 8, true)
  4701.         T:emptyTrash("up")
  4702.         if i < 8 then
  4703.             T:go("F"..(i * 2).."L1N16R1F1R1", true, 8, true)
  4704.         else
  4705.             T:go("F"..(i * 2).."L1N16L1", true, 8, true)
  4706.         end
  4707.     end
  4708.     T:go("F17L1") -- close gap in wall, return to ladder + 1
  4709.     for i = 1, 8 do
  4710.         T:go("N32R1F1R1", true, 8, true)
  4711.         T:go("N16R1F"..(i * 2).."R2", true, 8, true)
  4712.         T:emptyTrash("up")
  4713.         if i < 8 then
  4714.             T:go("F"..(i * 2).."R1N16L1F1L1", true, 8, true)
  4715.         else
  4716.             T:go("F"..(i * 2).."R1N16R1", true, 8, true)
  4717.         end
  4718.     end
  4719.     T:go("F16R1")
  4720.     T:clear()
  4721.     return{"Mining operation complete"}
  4722. end
  4723.  
  4724. local function createMobFarmCube(R) -- 61, 62
  4725.     --[[
  4726.     Part 1 / 3 Mob Spawner Farm
  4727.     blaze = true: blaze spawner in nether
  4728.         R.subChoice is set to:
  4729.         1 = on top of spawner
  4730.         2 = line of sight
  4731.         3 = room below
  4732.     blaze = false: overworld mob spawner
  4733.         R.subChoice is set to:
  4734.         1 = on top of spawner
  4735.         2 = bottom left corner
  4736.         3 = top left corner
  4737.         4 = bottom right, corner
  4738.         5 = top right corner
  4739.         R.width / R.length set by player (external size)
  4740.     ]]
  4741.     local blaze = true
  4742.     if R.data == "spawner" or R.data == "chest" then
  4743.         blaze = false
  4744.     end
  4745.     local continue = false
  4746.     if R.data == "restart" then
  4747.         continue = true
  4748.     end
  4749.     R.direction = "clock"       -- starting on right side
  4750.     if not blaze then
  4751.         print("R.width: "..tostring(R.width))
  4752.         R.width = R.width - 2       -- internal width
  4753.         R.length = R.length - 2     -- internal length
  4754.        
  4755.         if R.subChoice == 2 or R.subChoice == 3 then
  4756.             R.direction = "anticlock"
  4757.         end
  4758.     end
  4759.     -- R.data allows for 2-part operation "blaze" = main cube, "restart" = killzone
  4760.     T:clear()
  4761.     local lib = {}
  4762.    
  4763.     function lib.floorSection(length)
  4764.         for i = 1, length do        -- starts on top left corner
  4765.             T:go("C2")
  4766.             if i < length then
  4767.                 T:forward(1)
  4768.             else
  4769.                 T:go("R1F1")
  4770.             end
  4771.         end
  4772.     end
  4773.    
  4774.     function lib.wallSection(blaze)
  4775.         blaze = blaze or false
  4776.         for i = 1, 4 do
  4777.             for j = 1, 11 do
  4778.                 if blaze then
  4779.                     T:place("slab", 0, "up", false)
  4780.                     T:go("C2", false, 0, false)
  4781.                 else
  4782.                     T:go("C0C2", false, 0, false)
  4783.                 end
  4784.                 if j < 11 then
  4785.                     T:forward(1)
  4786.                     T:go("R2C1L2", false, 0, false)
  4787.                 else
  4788.                     T:turnRight(1)
  4789.                 end
  4790.             end
  4791.         end
  4792.     end
  4793.    
  4794.     function lib.ceiling(blaze)
  4795.         -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  4796.         -- all outer walls complete, now for remaining 9x9 ceiling
  4797.         blaze = blaze or false
  4798.         for i = 1, 9 do
  4799.             for j = 1, 9 do
  4800.                 if blaze then
  4801.                     T:place("slab", 0, "up", false)
  4802.                     T:dig("down")
  4803.                 else
  4804.                     T:go("C0x2", false, 0, true)
  4805.                 end
  4806.                 if j < 9 then
  4807.                     T:forward(1)
  4808.                 else    -- end of length
  4809.                     local place = false
  4810.                     if i%2 == 1 then -- odd numbers 1,3,5,7,9
  4811.                         if i < 9 then
  4812.                             place = true
  4813.                             T:go("R1F1 R1")
  4814.                         end
  4815.                     else
  4816.                         place = true
  4817.                         T:go("L1F1 L1")
  4818.                     end
  4819.                     if place then
  4820.                         if blaze then
  4821.                             T:place("slab", 0, "up", false)
  4822.                             T:dig("down")
  4823.                         else
  4824.                             T:go("C0x2", false, 0, true)
  4825.                         end
  4826.                     end
  4827.                 end
  4828.             end
  4829.         end
  4830.     end
  4831.    
  4832.     function lib.clearWall(length)
  4833.         for i = 1, 4 do
  4834.             for j = 1, length do
  4835.                 if j < length then
  4836.                     T:go("x0x2F1")
  4837.                 else
  4838.                     T:go("x0x2R1")
  4839.                 end
  4840.             end
  4841.         end
  4842.     end
  4843.    
  4844.     function lib.isSpawner()
  4845.         local blockType = T:getBlockType("down")
  4846.         if blockType:find("spawner") ~= nil then
  4847.             return true, "top"
  4848.         end
  4849.         blockType = T:getBlockType("up")
  4850.         if blockType:find("spawner") ~= nil then
  4851.             return true, "bottom"
  4852.         end
  4853.         blockType = T:getBlockType("forward")
  4854.         if blockType:find("spawner") ~= nil then
  4855.             return true, "forward"
  4856.         end
  4857.         return false, ""
  4858.     end
  4859.    
  4860.     function lib.placeFloor(width, length, blockType)
  4861.         -- T:place(blockType, damageNo, direction, leaveExisting, signText)
  4862.         for i = 1, width do            
  4863.             for j = 1, length do
  4864.                 T:place(blockType, -1, "down", false)
  4865.                 if j < length then
  4866.                     T:forward(1)
  4867.                 else
  4868.                     if i%2 == 1 then -- odd numbers 1,3,5,7,9
  4869.                         if i < width then
  4870.                             T:go("R1F1R1", false, 0, true)
  4871.                         end
  4872.                     else
  4873.                         T:go("L1F1L1", false, 0, true)
  4874.                     end
  4875.                 end
  4876.             end
  4877.         end
  4878.     end
  4879.    
  4880.     function lib.searchStrip(distance)
  4881.         --go forward until hit either a wall or a chest
  4882.         local blocks = 1
  4883.         print("Searching strip, distance = "..distance)
  4884.         while blocks < distance do --max travel is external width/length
  4885.             if turtle.forward() then
  4886.                 blocks = blocks + 1
  4887.             else
  4888.                 print("Checking for chest")
  4889.                 if lib.isChest("forward") then
  4890.                     if turtle.forward() then
  4891.                         blocks = blocks + 1
  4892.                     end
  4893.                 else
  4894.                     break
  4895.                 end
  4896.             end
  4897.         end
  4898.     end
  4899.    
  4900.     function lib.findChests(R)
  4901.         for i = 1, 4 do
  4902.             print("Searching wall "..i)
  4903.             if i == 1 or i == 3 then
  4904.                 lib.searchStrip(R.width)    -- find and empty chests along width
  4905.             else
  4906.                 lib.searchStrip(R.length)   -- find and empty chests along length
  4907.             end
  4908.             if R.direction == "clock" then
  4909.                 T:turnRight(1)
  4910.             else
  4911.                 T:turnLeft(1)
  4912.             end
  4913.         end
  4914.  
  4915.         -- checked all walls
  4916.         T:go("F".. math.floor(R.width / 2)) -- now at mid-dungeon, next to wall
  4917.         if T:getItemSlot("chest") > 0 then
  4918.             if R.direction == "clock" then
  4919.                 T:turnLeft(1)
  4920.             else
  4921.                 T:turnRight(1)
  4922.             end
  4923.             -- now at mid-dungeon, facing wall
  4924.             -- deposit chest outside the dungeon
  4925.             while turtle.back() do end -- backing spawner
  4926.             T:go("x0 F1x0 F1x0 F1x0 F1x0 F1x0 F1x0 x1x2")
  4927.             -- place(self, blockType, damageNo, direction, leaveExisting, signText)
  4928.             T:place("chest", -1, "forward", false)
  4929.             -- empty out all except stone and slab
  4930.             T:emptyInventorySelection("forward", {"cobble", "tuff", "slab", "granite", "andesite", "diorite" }, {0,0,0,0,0,0})
  4931.             T:turnLeft(2)
  4932.             T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements")
  4933.             while turtle.forward() do end -- facing spawner
  4934.         else
  4935.             if R.direction == "clock" then
  4936.                 T:turnRight(1)
  4937.             else
  4938.                 T:turnLeft(1)
  4939.             end
  4940.         end -- now at mid-dungeon, facing spawner
  4941.     end
  4942.    
  4943.     function lib.enterDungeon(R)
  4944.         --[[ find and empty any chests, return to dungeon wall ]]
  4945.         print("Entering dungeon")
  4946.         local blockType = T:getBlockType("forward")
  4947.         if blockType == "" then -- nothing in front.Error
  4948.             return false, "No block in front: Check position."
  4949.         else -- attempt entry into dungeon wall
  4950.             if R.subChoice == 2 then        -- bottom left
  4951.                 T:go("R1F1 L1U2 F2R1")
  4952.             elseif R.subChoice == 3 then    -- top left
  4953.                 T:go("R1F1 L1D1 F2R1")
  4954.             elseif R.subChoice == 4 then    -- bottom right
  4955.                 T:go("L1F1 R1U2 F2L1")
  4956.             elseif R.subChoice == 5 then    -- top right
  4957.                 T:go("L1F1 R1D1 F2L1")
  4958.             end
  4959.             while turtle.down() do end -- either on floor or chest
  4960.             if lib.isChest("down") then
  4961.                 turtle.down()
  4962.             end
  4963.             print("Searching for chests")
  4964.             lib.findChests(R)   -- go round inside walls  emptying chests. Finish mid-wall
  4965.         end
  4966.         return true, ""-- success, message
  4967.     end
  4968.    
  4969.     function lib.isChest(direction)
  4970.         direction = direction or "forward"
  4971.         local blockType = T:getBlockType(direction)
  4972.         if blockType:find("chest") ~= nil then -- chest found. early stages so empty and break it
  4973.             print("Chest found")
  4974.             while T:suck(direction) do end
  4975.             T:dig(direction, false) -- false prevents checking for chests
  4976.             return true
  4977.         elseif blockType:find("torch") ~= nil then
  4978.             print("Torch found")
  4979.             T:dig(direction, false) -- false prevents checking for chests
  4980.             return true
  4981.         end
  4982.         return false
  4983.     end
  4984.        
  4985.     function lib.findSpawner(blaze)
  4986.         local moves  = 0
  4987.         local quit = false
  4988.         -- assume turtle placed on centre of inside spawner wall in front of spawner
  4989.         -- or as close as possible in Nether
  4990.         print("Checking if next to spawner")
  4991.         local found, position = lib.isSpawner() -- true/false, top/bottom/nil
  4992.         if not found then -- move forward towards spawner
  4993.             print("Not close to spawner")
  4994.             while turtle.forward() and not quit do
  4995.                 moves = moves + 1
  4996.                 if moves > 16 then
  4997.                     quit = true
  4998.                 end
  4999.             end
  5000.             found, position = lib.isSpawner() -- true/false, top/bottom/nil
  5001.             if not found then
  5002.                 if blaze then -- could be behind a wall
  5003.                     print("Assuming blaze spawner behind a wall")
  5004.                     T:forward(1)
  5005.                     moves = moves + 1
  5006.                     while turtle.forward() and not quit do
  5007.                         moves = moves + 1
  5008.                         if moves > 16 then
  5009.                             quit = true
  5010.                         end
  5011.                     end
  5012.                     found, position = lib.isSpawner() -- true/false, top/bottom/nil
  5013.                     if not found then
  5014.                         T:go("R2F"..moves + 2 .."R2")
  5015.                     end
  5016.                 end
  5017.             end
  5018.         end
  5019.        
  5020.         return found, position
  5021.     end
  5022.    
  5023.    
  5024.     if not continue then -- new mob cube either dungeon or blaze
  5025.         -- clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
  5026.         -- determine spawner position level 4, move to top of spawner (level 6)
  5027.         print("Checking if already at spawner")
  5028.         local found, position = lib.isSpawner() -- already on spawner?
  5029.         if blaze then
  5030.             if not found then -- away from spawner
  5031.                 if R.subChoice == 3 then
  5032.                     T:go("U5")
  5033.                 end
  5034.                 found, position = lib.findSpawner(blaze)
  5035.             end
  5036.         else -- go to bottom of dungeon and empty chests
  5037.             if not found then --outside dungeon
  5038.                 local success, message = lib.enterDungeon(R)
  5039.                 if not success then
  5040.                     return {message}
  5041.                 end
  5042.                 found, position = lib.findSpawner(blaze) -- is spawner in front / above / below?
  5043.             end
  5044.         end
  5045.        
  5046.         if found then -- true: move to correct starting position
  5047.             --[[
  5048.             1 |c|c|c|c|c|c|c|c|c|c|c|
  5049.             2 |w| | | | | | | | | |w|
  5050.             3 |w| | | | | | | | | |w|
  5051.             4 |w| | | | | | | | | |w|
  5052.             5 |w| | | | | | | | | |w|
  5053.             6 |w| | | | |s| | | | |w|
  5054.             7 |w| | | | | | | | | |w|
  5055.             8 |w| | | | | | | | | |w|
  5056.             9 |w| | | | | | | | | |w|
  5057.            10 |w| | | | | | | | | |w| exit level for overworld
  5058.            11 |f|f|f|f|f|f|f|f|f|f|f|
  5059.            12 |f|f|f|f|f|f|f|f|f|f|f| sub floor for overworld
  5060.                1 2 3 4 5 6 7 8 9 1 1
  5061.                                  0 1
  5062.             ]]
  5063.             -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  5064.             if position == "bottom" then
  5065.                 T:go("B1U2F1")
  5066.             elseif position == "forward" then
  5067.                 T:go("U1F1")
  5068.             end
  5069.            
  5070.             T:up(1)
  5071.             T:place("slab", -1, "down", true)               -- place slab on top T:place(blockType, damageNo, direction, leaveExisting)
  5072.