Inksaver

tk.lua toolkit (requires libs):2023/09/27

Apr 20th, 2020 (edited)
3,099
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 411.71 KB | None | 0 0
  1. version = 20230927.1400
  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 part of 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.         for k,v in ipairs(above) do
  2237.             if v then
  2238.                 return true
  2239.             end
  2240.         end
  2241.         return false
  2242.     end
  2243.        
  2244.     function lib.clearLevel(R, above)   -- eg 9, 2, 6, -4 from lib.getStartingLength OR 7, 5, 6, 3 from previous
  2245.         -- clearLevel always follows either lib.getStartingLength or a previous lib.clearLevel
  2246.         -- midPoint should be adjusted as turtle moves to reflect current row length
  2247.         if #above == 0 then return above, 1 end
  2248.         local index = 0
  2249.         local minMoves = math.floor(#above / 2)
  2250.         local up, forward, down = lib.getDetect()
  2251.         if outward then                                     -- follow table indexes
  2252.             for x = 1, minMoves do                          -- clear first half
  2253.                 above[x] = up                               -- reset this with new value
  2254.                 T:go("x0x2F1")                              -- clear and move forward
  2255.                 up, forward, down = lib.getDetect()
  2256.                 index = index + 1
  2257.             end
  2258.             for x = minMoves + 1, #above do                 -- check remaing half and clear
  2259.                 if above[x] then                            -- is a block recorded as present?(now below)
  2260.                     above[x] = up                           -- reset this with new value
  2261.                     T:go("x0x2F1")                          -- clear and move forward
  2262.                     up, forward, down = lib.getDetect()
  2263.                     index = index + 1
  2264.                 else
  2265.                     break
  2266.                 end
  2267.             end
  2268.         else                                                -- iterate table in reverse
  2269.             index = #above
  2270.             for x = #above, minMoves, -1 do                 -- clear first half
  2271.                 above[x] = up                               -- reset this with new value
  2272.                 T:go("x0x2F1")                              -- clear and move forward
  2273.                 up, forward, down = lib.getDetect()
  2274.                 index = index - 1
  2275.             end
  2276.             for x = minMoves, 1, -1 do                      -- check remaing half and clear
  2277.                 if above[x] then                            -- is a block recorded as present?(now below)
  2278.                     above[x] = up                           -- reset this with new value
  2279.                     T:go("x0x2F1")                          -- clear and move forward
  2280.                     up, forward, down = lib.getDetect()
  2281.                     index = index - 1
  2282.                 else
  2283.                     break
  2284.                 end
  2285.             end
  2286.         end
  2287.         T:go("R2x0x2")                                      -- face opposite direction, delete blocks above and below
  2288.         outward = not outward                               -- switch direction flag
  2289.         return above, index                                 -- eg {false, true, true, true, false}, 5
  2290.     end
  2291.    
  2292.     function lib.getDetect()
  2293.         return turtle.detectUp(),  turtle.detect(),  turtle.detectDown()
  2294.     end
  2295.    
  2296.     function lib.getStartingLength(R)
  2297.         --[[
  2298.             length of column by excavating blocks above, ahead or below
  2299.             Rotate 180 at end of run ready to return
  2300.             already 1 block above ground
  2301.         ]]
  2302.         local above = {}                                    -- empty table of boolean values
  2303.         local length = 0                                    -- used as counter                         
  2304.         T:forward(1)                                        -- start check 1 block ahead
  2305.         local up, forward, down = lib.getDetect()           -- check if anything around current block
  2306.         if up or forward or down then                       -- block found nearby: continue
  2307.             while up or forward or down do                  -- while blocks ahead / up / down move forward
  2308.                 table.insert(above, up)
  2309.                 T:go("x0x2F1")
  2310.                 up, forward, down = lib.getDetect()         -- check if anything around current block
  2311.                 length = length + 1
  2312.                 if length >= R.length then                  -- check if going out of range
  2313.                     T:saveToLog("lib.getStartingLength(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
  2314.                     break
  2315.                 end
  2316.             end
  2317.             T:go("R2x0x2")                                  -- Rotate 180 and clear blocks above/below
  2318.         else                                                -- no blocks nearby: exit
  2319.             T:go("R2F1")                                    -- return to start position rotated 180
  2320.         end
  2321.         outward = not outward
  2322.  
  2323.         return above                                        -- above = {false, true, true, true, true, false, false}
  2324.     end
  2325.    
  2326.     function lib.firstRow(R)
  2327.         local height = 1                                    -- starts at ground level, but forced up 1
  2328.         T:up(1)
  2329.         local above = lib.getStartingLength(R)              -- clear the ground level and 1 above eg 9, 2, 5, 4
  2330.         if T:saveToLog("startLength: "..#above, true) then
  2331.             T:saveToLog(utils.tableConcat(above, ", "), false)
  2332.             if dbug then read() end
  2333.         end                                                 -- at end of first row as already turned 180, outward set to false in getStartingLength
  2334.         while lib.isAnyAbove(above) do
  2335.             T:go("U3")  -- go up 3
  2336.             height = height + 3
  2337.             above, index = lib.clearLevel(R, above, index)  -- returns start and finish of blocks above, rotates 180
  2338.             if T:saveToLog("checking level: "..height, true) then
  2339.                 T:saveToLog(utils.tableConcat(above, ", "), false)
  2340.                 if dbug then read() end
  2341.             end
  2342.         end                                                 -- first row all levels completed.
  2343.         T:down(height)                                      -- now on ground + 1, facing last column cleared.
  2344.        
  2345.         return above
  2346.     end
  2347.        
  2348.     function lib.deepCopy(tbl)
  2349.         local copy = {}
  2350.         for key, value in ipairs(tbl) do
  2351.             table.insert(copy, value)
  2352.         end
  2353.         return copy
  2354.     end
  2355.    
  2356.     function lib.getHalf(R, above)
  2357.         -- already 1 block above ground
  2358.         local maxLength = R.length
  2359.         local temp = {}
  2360.         local retValue = {}
  2361.         if #above > 0 then                              -- not empty table, so must be second half
  2362.             temp = lib.deepCopy(above)                  -- copy existing table
  2363.             above = {}                                  -- initialise above
  2364.         end
  2365.         local up, forward, down = lib.getDetect()
  2366.        
  2367.         while up or forward or down do                  -- while blocks ahead / up / down move forward
  2368.             T:go("x0x2F1")
  2369.             table.insert(above, up)
  2370.             up, forward, down = lib.getDetect()         -- check if anything around current block
  2371.            
  2372.             if #above >= math.floor(maxLength / 2) then -- check if going out of range
  2373.                 T:saveToLog("lib.getHalf(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
  2374.                 T:go("x0x2")
  2375.                 break
  2376.             end
  2377.         end
  2378.         T:turnRight(2)                                  -- ready for next half or return
  2379.         outward = not outward
  2380.         if #temp > 0 then                               -- completing a second half measurement
  2381.             for i = #above, 1, -1 do
  2382.                 table.insert(retValue, above[i])        -- combine 2 tables into 1
  2383.             end
  2384.             for i = 1, #temp do
  2385.                 table.insert(retValue, temp[i])
  2386.             end
  2387.         else
  2388.             retValue = above
  2389.         end
  2390.         return retValue
  2391.     end
  2392.    
  2393.     function lib.nextRow(R)
  2394.         local height = 1
  2395.         T:saveToLog("lib.nextRow(R)", false)
  2396.         T:up(1)
  2397.         local pattern = turn.."1F1"..turn.."1"
  2398.         if not outward then
  2399.             pattern = oTurn.."1F1"..oTurn.."1"
  2400.         end
  2401.         T:go(pattern)
  2402.         T:saveToLog("    T:go("..pattern..")", false)
  2403.         outward = not outward -- reverse direction flag
  2404.         -- now in next vertical row
  2405.         local above = lib.getHalf(R, {})
  2406.         local index = 0
  2407.         if T:saveToLog("\t  first half Length: "..#above.." Enter", true) and dbug then read() end
  2408.         lib.returnToMidPoint(#above)                                -- return to starting point
  2409.         above = lib.getHalf(R, above)       -- returns length - 1 eg 5, 4
  2410.         local midPoint = math.floor(#above / 2)
  2411.         if T:saveToLog("\t  total length: "..#above.." Enter", true) and dbug then read() end
  2412.  
  2413.         while lib.isAnyAbove(above) do
  2414.             T:go("U3")              -- go up 3
  2415.             height = height + 3     -- increment height
  2416.             T:saveToLog("\tClear height loop: height = "..height, false)
  2417.             above, index = lib.clearLevel(R, above) -- returns start and finish of blocks above
  2418.         end
  2419.         T:down(height)  -- now on ground + 1
  2420.         lib.returnToMidPoint(above)
  2421.     end
  2422.    
  2423.     function lib.returnToMidPoint(above)
  2424.         --[[ value can be integer or table]]
  2425.         if type(above) == "table" then
  2426.             T:saveToLog("lib.returnToMidPoint("..#above..")", false)
  2427.            
  2428.             if #above > 0 then
  2429.                 local midPoint = math.floor(#above / 2)
  2430.                 T:saveToLog("    T:forward("..midPoint..")", false)
  2431.                 T:forward(midPoint)
  2432.             end
  2433.         else
  2434.             T:saveToLog("lib.returnToMidPoint("..above..")", false)
  2435.             if above > 0 then
  2436.                 T:saveToLog("    T:forward("..above..")", false)
  2437.                 T:forward(above)
  2438.             end
  2439.         end
  2440.         -- now back at starting point
  2441.     end
  2442.    
  2443.     -- Start here
  2444.     -- if "tk log d.." typed instead of "tk" will start logfile and display comments. read() will be activated for debugging
  2445.     T:saveToLog("Starting function clearMountainSide", false)
  2446.     local above = lib.firstRow(R)           -- outward depends on height eg 1-2 = false, 3-5 = true, 6-8 = false
  2447.     lib.returnToMidPoint(above)             -- return to mid first row of blocks
  2448.     for row = 1, R.width -1 do
  2449.         lib.nextRow(R)
  2450.     end
  2451.    
  2452.     return {}
  2453. end
  2454.  
  2455. local function clearSandWall(R) -- 81
  2456.     --dig down while on top of sand/red_sand/soul_sand
  2457.     local lib = {}
  2458.    
  2459.     function lib.checkAbove(height)
  2460.         if turtle.detectUp() then -- moved under a ledge
  2461.             T:go("B1U1")
  2462.             height = height - 1
  2463.         end
  2464.         return height
  2465.     end
  2466.    
  2467.     function lib.moveDown(height)
  2468.         blockType = T:getBlockType("down")
  2469.         while blockType:find("sand") ~= nil do
  2470.             T:down(1)
  2471.             height = height + 1
  2472.             blockType = T:getBlockType("down")
  2473.         end
  2474.         return height
  2475.     end
  2476.    
  2477.     function lib.moveForward(length)
  2478.         lib.digForward()
  2479.         T:forward(1)
  2480.         length = length + 1
  2481.         local blockType = T:getBlockType("forward")
  2482.         return length, blockType
  2483.     end
  2484.    
  2485.     function lib.digForward()
  2486.         while T:dig("forward") do
  2487.             while T:suck("forward") do end
  2488.             while T:suck("up") do end
  2489.         end
  2490.     end
  2491.    
  2492.     local moves  = 0
  2493.     local height = 0
  2494.     local length = 0
  2495.     local search = 0
  2496.     local reverse = false
  2497.     local blockType = T:getBlockType("down")
  2498.     if R.length == 0 then
  2499.         R.length = 64
  2500.     end
  2501.    
  2502.     print("Checking for sand below")
  2503.     while blockType:find("sand") == nil do --move forward until sand detected or 3 moves
  2504.         T:forward(1)
  2505.         search = search + 1
  2506.         blockType = T:getBlockType("down")
  2507.         if search > 3 then
  2508.             T:go("B"..search)
  2509.             return {"Unable to locate sand"}
  2510.         end
  2511.     end
  2512.     -- must be sand below
  2513.     height = lib.moveDown(height)   -- go down if sand below
  2514.     -- repeat until height == 0
  2515.     repeat -- starts at bottom of sand wall
  2516.         blockType = T:getBlockType("forward")
  2517.         if blockType:find("sand") ~= nil then -- sand in front
  2518.             length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
  2519.             if blockType == "" or  blockType:find("sand") ~= nil then -- sand or nothing in front
  2520.                 height = lib.moveDown(height)   -- go down if sand below
  2521.             end
  2522.         else -- solid block, air or water, not sand so move up
  2523.             if turtle.detect() then -- block in front
  2524.                 blockType = T:getBlockType("down")
  2525.                 if blockType:find("sand") ~= nil then -- sand below
  2526.                     T:dig("down")
  2527.                 end
  2528.                 T:up(1)
  2529.                 height = height - 1
  2530.             else -- air/water in front so move forward
  2531.                 if length < 60 then -- in case missing wall and in open ocean
  2532.                     length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
  2533.                     height = lib.checkAbove(height)
  2534.                 else -- already > monument length of 56
  2535.                     T:up(1)
  2536.                     height = height - 1
  2537.                 end
  2538.             end
  2539.         end
  2540.     until height == 0 or length == R.length
  2541.     blockType = T:getBlockType("down")
  2542.     if blockType:find("sand") ~= nil then -- sand below
  2543.         T:dig("down")
  2544.     end
  2545.     if height > 0 then -- finished as length ran out
  2546.         T:up(height)
  2547.     end
  2548.     -- stay at end of cleared wall unless user chose to return
  2549.     if R.data == "return" then
  2550.         T:go("R2F"..length.."R2")
  2551.     end
  2552.    
  2553.     return {}
  2554. end
  2555.  
  2556. local function clearSolid(R) -- 76
  2557.     --[[ direction = R.subChoice = 1 up or 2 down ]]
  2558.     local height = 1
  2559.     local remaining = R.height
  2560.     local lib = {}
  2561.    
  2562.     function lib.singleLayer(R)
  2563.         R.up = false
  2564.         R.down = false
  2565.         clearRectangle(R)
  2566.     end
  2567.    
  2568.     function lib.doubleLayer(R)
  2569.         R.up = false
  2570.         R.down = false
  2571.         if R.subChoice == 1 then
  2572.             R.up = true
  2573.         else
  2574.             R.down = true
  2575.         end
  2576.         clearRectangle(R)
  2577.     end
  2578.        
  2579.     function lib.tripleLayer(R)
  2580.         -- turtle in centre layer
  2581.         R.up = true
  2582.         R.down = true
  2583.         clearRectangle(R)
  2584.     end
  2585.  
  2586.     R.silent = true
  2587.     if R.height < 3 then                            --1-3 layers only
  2588.         if R.height == 1 then                       --one layer only
  2589.             lib.singleLayer(R)
  2590.         elseif R.height == 2 then                   --2 layers only current + dig up/down
  2591.             lib.doubleLayer(R)
  2592.         end
  2593.     else -- 3 or more levels
  2594.         height = height + utils.move(R, 1)          -- move up/down 1 block for first layer
  2595.         while remaining >= 3 do                     -- min 3 levels
  2596.             lib.tripleLayer(R)
  2597.             remaining = remaining - 3
  2598.             if remaining == 0 then                  -- all finished
  2599.                 break
  2600.             elseif remaining == 1 then
  2601.                 height = height + utils.move(R, 2)  -- move up/down 2 blocks
  2602.                 lib.singleLayer(R)
  2603.             elseif remaining == 2 then
  2604.                 height = height + utils.move(R, 2)  -- move up/down 2 blocks
  2605.                 lib.doubleLayer(R)
  2606.             else
  2607.                 height = height + utils.move(R, 3)  -- move up/down 3 blocks
  2608.                 if remaining == 3 then
  2609.                     finish = true
  2610.                 end
  2611.             end
  2612.         end
  2613.     end
  2614.    
  2615.     if height > 1 then
  2616.         utils.move(R, height - 1, true) -- reverse direction
  2617.     end
  2618.    
  2619.     return {}
  2620. end
  2621.  
  2622. local function clearSandCube(R) -- 81
  2623.     R.data = ""
  2624.     for w = 1, R.width do
  2625.         clearSandWall(R)
  2626.         if w < R.width then
  2627.             if w % 2 == 1 then
  2628.                 T:go("R1F1R1")
  2629.             else
  2630.                 T:go("L1F1L1")
  2631.             end
  2632.         end
  2633.     end
  2634.    
  2635.     return {}
  2636. end
  2637.  
  2638. local function clearWall(R) -- 73
  2639.     local lib = {}
  2640.    
  2641.     function lib.move(direction, blocks, reverse)
  2642.         --[[ Move up or down by blocks count ]]
  2643.         if reverse == nil then
  2644.             reverse = false
  2645.         end
  2646.         if reverse then
  2647.             if direction == "down" then -- reverse direction
  2648.                 T:up(blocks)
  2649.             else
  2650.                 T:down(blocks)
  2651.             end
  2652.         else
  2653.             if direction == "up" then
  2654.                 T:up(blocks)
  2655.             else
  2656.                 T:down(blocks)
  2657.             end
  2658.         end
  2659.         return blocks
  2660.     end
  2661.    
  2662.     function lib.singleLayer(length)
  2663.         T:go("F"..length - 1)
  2664.     end
  2665.    
  2666.     function lib.doubleLayer(modifier, length)
  2667.         for i = 1, length do
  2668.             if i < length then
  2669.                 T:go("x"..modifier.."F1")
  2670.             else
  2671.                 T:go("x"..modifier)
  2672.             end
  2673.         end
  2674.     end
  2675.    
  2676.     function lib.tripleLayer(direction, length)
  2677.         for i = 1, length do
  2678.             if i < length then
  2679.                 T:go("x0x2F1")
  2680.             else
  2681.                 T:go("x0x2")
  2682.             end
  2683.         end
  2684.     end
  2685.    
  2686.    
  2687.     -- R.width preset to 1
  2688.     -- R.subChoice = 1 up / 2 down
  2689.     if R.height < 3 then
  2690.         R.silent = true
  2691.     end
  2692.     -- dig along and up/down for specified R.length
  2693.     local modifier = "0"
  2694.     local direction = "U"
  2695.     local outbound = true
  2696.     local height = 0
  2697.     if R.subChoice == 2 then
  2698.          modifier = "2"
  2699.          direction = "D"
  2700.     end
  2701.     if R.height == 1 then               -- single block so dig and return
  2702.         lib.singleLayer(R.length)
  2703.     elseif R.height == 2 then
  2704.         lib.doubleLayer(modifier, R.length)
  2705.     else                                -- 4 blocks or more. start with bulk 3 blocks
  2706.         local remaining = R.height
  2707.         T:go(direction.."1")            -- up 1 or down 1
  2708.         height = 1
  2709.         while remaining >= 3 do
  2710.             lib.tripleLayer(direction, R.length)
  2711.             remaining = remaining - 3
  2712.            
  2713.             if remaining == 0 then      -- no more, return home, already in position
  2714.                
  2715.             elseif remaining == 1 or remaining == 2 then
  2716.                 T:go(direction.."2")
  2717.                 height = height + 2
  2718.             else
  2719.                 T:go(direction.."3")
  2720.                 height = height + 3
  2721.                 if remaining >= 3 then -- another iteration
  2722.                     T:go("R2")
  2723.                     outbound = not outbound
  2724.                 end
  2725.             end
  2726.         end
  2727.         -- 0, 1 or 2 layers left
  2728.         if remaining > 0 then
  2729.             T:go("R2")
  2730.             outbound = not outbound
  2731.             if remaining == 1 then
  2732.                 lib.singleLayer(R.length)
  2733.             elseif remaining == 2 then
  2734.                 lib.doubleLayer(modifier, R.length)
  2735.             end
  2736.         end
  2737.     end
  2738.     if outbound then
  2739.         T:go("R2F"..R.length)
  2740.     else
  2741.         T:forward(1)
  2742.     end
  2743.     direction = "D" -- reverse direction
  2744.     if R.subChoice == 2 then
  2745.          direction = "U"
  2746.     end
  2747.     if height > 0 then
  2748.         T:go(direction..height.."R2")
  2749.     else
  2750.         T:go("R2")
  2751.     end
  2752.     return {}
  2753. end
  2754.  
  2755. local function convertWater(R) -- 88
  2756.     --[[
  2757.     if dry need enough buckets to place along (width + length - 1) / 2
  2758.     use 12 buckets
  2759.     start on floor + 1
  2760.     place slab down and water up along 2 edges. stay on this level
  2761.     return round same 2 edges removing slabs and and placing them 1 above
  2762.     placeUp water onto slabs on both edges
  2763.     repeat recover slabs, place 1 above , placeUp water
  2764.    
  2765.     for sloping water, place full area with slabs
  2766.     place sloping water on top of slabs
  2767.     remove slabs
  2768.    
  2769.     ]]
  2770.     local lib = {}
  2771.    
  2772.     function lib.checkStartPosition()
  2773.         --[[
  2774.         0 T             -- T=turtle, W=wall, S=source, F=flowing
  2775.         1 W|S|F|F|F|F|F -- sloping flowing water
  2776.         2 W|F|F|F|F|F|F -- blocks removed after placing flowing water above
  2777.         3 W|S|S|S|S|S|S -- original sources
  2778.         4 W|?|?|?|?|?|? -- may be sources
  2779.         ]]
  2780.         -- need to be on floor or R.height if specified
  2781.         local depth = 0
  2782.         local blockType = T:getBlockType("down")
  2783.         local isWaterUp, isSourceUp = T:isWater("up")
  2784.         local isWaterForward, isSourceForward = T:isWater("forward")
  2785.         local isWaterDown, isSourceDown = T:isWater("down")
  2786.         print("Block below is "..blockType)
  2787.         print("Water above is "..tostring(isWaterUp))
  2788.         print("Water forward is "..tostring(isWaterForward))
  2789.         print("Water below is "..tostring(isWaterDown))
  2790.         if blockType:find("water") == nil then -- on at least level 0
  2791.             print("Moving forward in 2 seconds...")
  2792.             sleep(2)
  2793.             T:forward(1)
  2794.             blockType = T:getBlockType("down")
  2795.             if blockType:find("water") ~= nil then
  2796.                 print("Water found. Going down to floor")
  2797.                 depth = -1
  2798.             else
  2799.                 T:down(1)
  2800.                 blockType = T:getBlockType("down")
  2801.                 if blockType:find("water") ~= nil then
  2802.                     depth = -2
  2803.                 else
  2804.                     return 0, "Not close to water. Aborting..."
  2805.                 end
  2806.             end
  2807.         end
  2808.         while turtle.down() do
  2809.             depth = depth + 1
  2810.         end
  2811.         local emptyBuckets = utils.getEmptyBucketCount()
  2812.         for i = depth, 0, -1 do
  2813.             if emptyBuckets > 0 then
  2814.                 lib.fillBuckets()
  2815.                 emptyBuckets = utils.getEmptyBucketCount()
  2816.             end
  2817.             turtle.up()
  2818.         end
  2819.        
  2820.         return depth, ""
  2821.     end
  2822.    
  2823.     function lib.fillBuckets()
  2824.         local emptyBuckets = utils.getEmptyBucketCount()
  2825.         local direction = "forward"-- start with forward
  2826.         local isWater, isSource, isIce = T:isWater(direction)
  2827.         if emptyBuckets > 0 then
  2828.             if not isSource then
  2829.                 direction = "down"
  2830.                 isWater, isSource, isIce = T:isWater(direction)
  2831.                 if not isSource then
  2832.                     direction = "up"
  2833.                     isWater, isSource, isIce = T:isWater(direction)
  2834.                     if not isSource then
  2835.                         direction = ""
  2836.                     end
  2837.                 end
  2838.             end
  2839.             if direction == "" then
  2840.                 print("Unable to locate water source")
  2841.             else
  2842.                 for i = 1, emptyBuckets do
  2843.                     if utils.fillBucket(direction) then
  2844.                         print("Bucket filled "..direction)
  2845.                         sleep(0.3)
  2846.                     else
  2847.                         print("Unable to fill bucket ".. i .." / "..emptyBuckets)
  2848.                     end
  2849.                 end
  2850.             end
  2851.         end
  2852.         return utils.getWaterBucketCount()
  2853.     end
  2854.    
  2855.     function lib.placeSlabs(length)
  2856.         for i = 1, length do
  2857.             T:place("slab", -1, "down", false)
  2858.             if i < length then
  2859.                 T:forward(1)
  2860.             end
  2861.         end
  2862.     end
  2863.    
  2864.     function lib.placeSources(length, place)
  2865.         local moves = 1
  2866.         local waterBuckets = utils.getWaterBucketCount()
  2867.         -- place sources alternate positions + start and finish
  2868.         while moves < length do
  2869.             if place then
  2870.                 if T:placeWater("up") then
  2871.                     print("Placed source up")
  2872.                     waterBuckets = waterBuckets - 1
  2873.                 end
  2874.             end
  2875.             place = not place
  2876.             if moves < length then
  2877.                 T:forward(1)
  2878.                 moves = moves + 1
  2879.             end
  2880.             if waterBuckets == 0 then
  2881.                 T:down(1) -- break the slab below
  2882.                 waterBuckets = lib.fillBuckets()
  2883.                 T:up(1)
  2884.                 T:place("slab", -1, "down", false)
  2885.             end
  2886.         end
  2887.         if T:placeWater("up") then -- end of length
  2888.             print("Placed final source up")
  2889.         end
  2890.         return place
  2891.     end
  2892.    
  2893.     function lib.moveSlabs(length)
  2894.         for i = 1, length do
  2895.             T:dig("down")
  2896.             T:up(1)
  2897.             T:place("slab", -1, "down", true)
  2898.             if i < length then
  2899.                 T:forward(1)
  2900.                 T:down(1)
  2901.             end
  2902.         end
  2903.     end
  2904.    
  2905.     function lib.recoverSlabs(length)
  2906.         for i = 1, length do
  2907.             T:dig("down")
  2908.             if i < length then
  2909.                 T:forward(1)
  2910.             end
  2911.         end
  2912.     end
  2913.    
  2914.     local depth, message = lib.checkStartPosition()
  2915.     if message ~= "" then
  2916.         return {message}
  2917.     end
  2918.     local maxDepth = R.height
  2919.     local buckets = utils.getWaterBucketCount()
  2920.     R = utils.calculateDimensions(R) -- if R.width or R.length == 0
  2921.     T:down(depth)
  2922.     lib.placeSlabs(R.length)
  2923.     T:go("R1")
  2924.     lib.placeSlabs(R.width)
  2925.     T:go("R2")
  2926.    
  2927.     while depth > 0 do
  2928.         local place = true
  2929.         lib.fillBuckets()
  2930.         place = lib.placeSources(R.width, place)
  2931.         T:go("L1")
  2932.         place = lib.placeSources(R.length, place)
  2933.         lib.fillBuckets()
  2934.         T:go("R2")
  2935.         lib.moveSlabs(R.length) -- dig slab from below, move up and replace below
  2936.         T:go("R1F1D1")
  2937.         lib.moveSlabs(R.width - 1)
  2938.         T:go("R2") -- now moved up 1 layer
  2939.         depth = depth - 1
  2940.         if depth == 0 then
  2941.             place = lib.placeSources(R.width, true)
  2942.             T:go("L1")
  2943.             place = lib.placeSources(R.length, place)
  2944.             T:go("R2")
  2945.             lib.recoverSlabs(R.length)
  2946.             T:go("R1")
  2947.             lib.recoverSlabs(R.width)
  2948.         end
  2949.     end
  2950.    
  2951.     return {}
  2952. end
  2953.  
  2954. local function createBoatLift(R) -- 59 state:0=new, size:1=extend, side:0=left, 1=right
  2955.     -- build stepped lift with fencing gates and soul sand
  2956.     local lib = {}
  2957.    
  2958.     function lib.getWater(backToWater, downToWater)
  2959.         if backToWater > 0 then
  2960.             utils.goBack(backToWater)
  2961.         end
  2962.         if downToWater > 0 then
  2963.             T:down(downToWater)
  2964.         end
  2965.         T:getWater("down") -- take water from source
  2966.         sleep(0.2)
  2967.         T:getWater("down") -- take water from source
  2968.         if downToWater > 0 then
  2969.             T:up(downToWater)
  2970.         end
  2971.         if backToWater > 0 then
  2972.             T:forward(backToWater)
  2973.         end
  2974.     end
  2975.    
  2976.     --T:place(blockType, damageNo, direction, leaveExisting, signText)
  2977.    
  2978.     local backToWater = 0
  2979.     local downToWater = 0
  2980.    
  2981.     T:go("R1F1L1")                                      -- over canal facing forward
  2982.     for h = 1, R.height do
  2983.         lib.getWater(backToWater, downToWater)          -- check water supplies, return to starting position
  2984.         T:go("L1C1 R1D1 L1C1 R1", false, 0, false)      -- place towpath, forward, down, place towpath, face forward
  2985.         T:place("soul", -1, "down", false)              -- place soulsand down
  2986.         T:place("soul", -1, "forward", false)           -- place soulsand forward
  2987.         T:go("R1F1C1L1", false, 0, false)               -- place right towpath face forward
  2988.         T:place("soul", -1, "down", false)              -- place soulsand down
  2989.         T:place("soul", -1, "forward", false)           -- place soulsand forward
  2990.         T:go("U1 R1C1 L1")                              -- place towpath, face forward
  2991.         T:placeWater("down")                            -- place water down
  2992.         utils.goBack(1)
  2993.         T:place("gate", -1, "forward", false)           -- place fence gate
  2994.         T:go("R1C1 U1C1 D1 L2F1 C1R1 F1 L1C1R1")        -- over left soul sand
  2995.         T:placeWater("down")                            -- place water down
  2996.         utils.goBack(1)
  2997.         T:place("gate", -1, "forward", false)           -- place fence gate
  2998.         T:go("U1 L1C1 R1F1 L1C1 R1x1")                  -- facing forward first unit complete
  2999.         T:go("R1F1 L1x1 R1C1")
  3000.         utils.goBack(1)
  3001.         T:go("L1F1")
  3002.         if backToWater == 0 then
  3003.             backToWater = 1
  3004.         end
  3005.         backToWater = backToWater + 1
  3006.         downToWater = downToWater + 1
  3007.     end
  3008.    
  3009.     -- now finish the canal
  3010.     lib.getWater(backToWater, downToWater)
  3011.     T:go("D1 L1C1 U1C1")                    -- build left towpath, facing towpath, above water level
  3012.     T:go("R1F1 L1C1 D1C1")                  -- move forward, build towpath, facing towpath ground level
  3013.     T:go("R1C1 R1F1 L1C1 R1C1 U1C1")        -- build right towpath, facing towpath, above water level
  3014.     T:go("R1F1 L1C1 D1C1 U1")               -- build right towpath next to gate, facing towpath, above water level
  3015.     T:placeWater("down")
  3016.     utils.goBack(1)
  3017.     T:go("L1F1")
  3018.     T:placeWater("down")  
  3019.    
  3020.     return {}
  3021. end
  3022.  
  3023. local function createBorehole(R)
  3024.     --[[go down to bedrock and return. Chart all blocks dug/ passed through]]
  3025.     local diary = {}
  3026.     local lib = {}
  3027.     local depth = R.height  -- eg 63 start position
  3028.     local moves = 0
  3029.     --R.height = current level
  3030.    
  3031.     function lib.addBlock(depth, blockType, diary)
  3032.         if blockType == "" then
  3033.             blockType = "air"
  3034.         end
  3035.         table.insert(diary, blockType)
  3036.        
  3037.        
  3038.         --[[if blockType ~= "" then
  3039.             local add = true
  3040.             for k,v in pairs(diary) do
  3041.                 if blockType == v then
  3042.                     add = false
  3043.                     break
  3044.                 end
  3045.             end
  3046.             if add then
  3047.                 diary[depth] = blockType
  3048.             end
  3049.         end]]
  3050.        
  3051.         return diary
  3052.     end
  3053.    
  3054.     function lib.processItem(item)
  3055.         if item:find("minecraft") ~= nil then
  3056.             return item:sub(11)
  3057.         end
  3058.         return item
  3059.     end
  3060.    
  3061.     function lib.writeReport(R, diary)
  3062.         local numLevels = #diary                        -- eg 125 levels
  3063.         local levelsPerCol = math.ceil(numLevels / 4)   -- eg 31.25 -> 32
  3064.         local lines = {}
  3065.         for l = 1, levelsPerCol do                      -- add 32 empty strings
  3066.             table.insert(lines, "")
  3067.         end
  3068.         local lineNo = 1
  3069.         for k, v in ipairs(diary) do
  3070.             local level = R.height - k                  -- eg 63 range 63 to -59
  3071.             local lev = "      "
  3072.             local item = lib.processItem(v)
  3073.             if level < -9 then
  3074.                 lev = tostring(level).."   "            -- "-10   " to "-59   "
  3075.             elseif level < 0 then              
  3076.                 lev = "-0"..math.abs(level).."   "      -- "-09   " to "-01   "
  3077.             elseif level < 10 then
  3078.                 lev = " 0"..level.."   "                -- " 01   " to " 09   "
  3079.             elseif level < 100 then
  3080.                 lev = " "..level.."   "                 -- " 10   " to " 99   "
  3081.             else
  3082.                 lev = " "..level.."  "                  -- " 100  " to " 319  "
  3083.             end
  3084.             local output = lev..item                    -- eg "-10   grass_block"
  3085.             if #output > 20 then                        -- eg "-10   some_long_block_name"  
  3086.                 output = output:sub(1, 20)              -- eg "-10   some_long_block_"
  3087.             else
  3088.                 output = menu.padRight(output, 20, " ") -- eg "-10   grass_block     "
  3089.             end
  3090.             lines[lineNo] = lines[lineNo]..output       -- add new entry to this line
  3091.             lineNo = lineNo + 1                         -- increase line no
  3092.             if lineNo > levelsPerCol then               -- past last line number
  3093.                 lineNo = 1                              -- reset to 1
  3094.             end
  3095.         end
  3096.        
  3097.         local fileName = "borehole"..os.getComputerID()..".txt"
  3098.         local handle = fs.open(fileName, "w")       --create file eg "borehole0.txt"
  3099.         handle.writeLine("Level Block         Level Block         Level Block         Level Block")
  3100.         for k,v in ipairs(lines) do
  3101.             handle.writeLine(v)
  3102.         end
  3103.        
  3104.         handle.close()
  3105.        
  3106.         return fileName
  3107.     end
  3108.    
  3109.     local blockType = T:getBlockType("down")
  3110.     while T:down(1) do
  3111.         depth = depth - 1
  3112.         moves = moves + 1
  3113.         if depth == R.depth then
  3114.             break
  3115.         end
  3116.         diary = lib.addBlock(depth, blockType, diary)
  3117.         blockType = T:getBlockType("down")
  3118.     end
  3119.     local fileName = lib.writeReport(R, diary)
  3120.     T:up(moves)
  3121.    
  3122.     return {"File '"..fileName.."' written"}
  3123. end
  3124.  
  3125. local function createBubbleLift(R) -- 15
  3126.     local lib = {}
  3127.    
  3128.     function lib.addLayer()
  3129.         T:go("F2 L1C1 R1C1 R1C1 L1", false, 0, true)
  3130.         turtle.back()
  3131.         T:dig("up") -- clear block above so completed lift can be found
  3132.         T:placeWater("forward")
  3133.         turtle.back()
  3134.         T:go("C1x0")       
  3135.     end
  3136.    
  3137.     function lib.addSign()
  3138.         turtle.back()
  3139.         T:placeWater("forward")
  3140.         T:go("L1B1")
  3141.         T:place("sign", -1, "forward")
  3142.     end
  3143.    
  3144.     function lib.buildLift(toHeight)
  3145.         local built = lib.goToWater()       -- returns lift blocks already placed, total height of drop from starting point
  3146.         local toBuild = toHeight - built    -- no of blocks remaining to increase lift size
  3147.         local water = 0
  3148.         while toBuild > 0 do                -- at least 1 block height remaining
  3149.             water = lib.fillBuckets(toBuild, false) -- no of water buckets onboard (could be more than required)
  3150.             if water > toBuild then         -- more water than required
  3151.                 water = toBuild             -- reduce to correct amount
  3152.             end
  3153.             T:up(built)                     -- climb to top of existing lift
  3154.             while water > 0 and toBuild > 0 do
  3155.                 lib.addLayer()
  3156.                 water = water - 1
  3157.                 T:up(1)
  3158.                 toBuild = toBuild - 1
  3159.             end
  3160.             -- may still be some height to complete, but needs refill
  3161.             if toBuild > 0 then
  3162.                 built = lib.goToWater() --return to source
  3163.                 toBuild = toHeight - built
  3164.                 --lib.fillBuckets(toBuild)
  3165.             end
  3166.         end
  3167.     end
  3168.    
  3169.     function lib.cleanUp(fromHeight)
  3170.         local plug = false
  3171.         T:turnRight(2)
  3172.         for i = 1, fromHeight do
  3173.             plug = false
  3174.             if turtle.detect() then
  3175.                 plug = true
  3176.             end
  3177.             turtle.down()
  3178.             if plug then
  3179.                 T:place("stone", -1, "up")
  3180.             end
  3181.         end
  3182.         T:go("D1 C1R1x1 R1C1 R1F1 R1x1 L2x1 L1C1 x1") -- delete water sources
  3183.         T:go("D1 C1R1x1 R1")
  3184.         local blockType = T:getBlockType("forward")
  3185.         if blockType:find("dirt") == nil and blockType:find("soul") == nil then -- not dirt or soul sand in front
  3186.             T:go("C1")
  3187.         end
  3188.         T:go("R1F1 R1x1 L2x1 L1C1 x1")
  3189.     end
  3190.    
  3191.     function lib.fillBuckets(toBuild, withSort)
  3192.         local emptySlots, water = lib.stackBuckets(withSort)-- gets no of empty slots + no of water buckets
  3193.         if water < toBuild then                     -- no of water buckets onboard less than required quantity
  3194.             for i = 1, toBuild do                   -- fill required no of buckets up to max space in inventory
  3195.                 if emptySlots == 0 then             -- inventory full
  3196.                     break
  3197.                 else
  3198.                     if T:getWater("down") then
  3199.                         water = water + 1
  3200.                         sleep(0.5)
  3201.                     end
  3202.                 end
  3203.                 emptySlots = lib.getEmptySlots()
  3204.             end
  3205.         end
  3206.        
  3207.         return water
  3208.     end
  3209.    
  3210.     function lib.getEmptySlots()
  3211.         local empty = 0
  3212.         for i = 1, 16 do
  3213.             if turtle.getItemCount(i) == 0 then
  3214.                 empty = empty + 1
  3215.             end
  3216.         end
  3217.         return empty
  3218.     end
  3219.    
  3220.     function lib.goToWater()
  3221.         local built = 0 -- measures completed lift height
  3222.         while turtle.down() do -- takes turtle to bottom of water source
  3223.             if turtle.detect() then
  3224.                 built = built + 1
  3225.             end
  3226.         end
  3227.         T:up(1) -- above watersource ready to fill buckets
  3228.         -- height = height - 1
  3229.         -- built = built - 1 not required as next block is water source: not detected
  3230.         return built -- , height
  3231.     end
  3232.    
  3233.     function lib.stackBuckets(withSort)
  3234.         if withSort == nil then withSort = false end
  3235.         local data = {}
  3236.         local bucketSlot = 0
  3237.         local emptySlots = 0
  3238.         local water = 0
  3239.         if withSort then
  3240.             T:sortInventory()
  3241.         end
  3242.         for i = 1, 16 do
  3243.             -- find first empty bucket
  3244.             if turtle.getItemCount(i) > 0 then
  3245.                 data = turtle.getItemDetail(i)
  3246.                 if data.name == "minecraft:bucket" then
  3247.                     if bucketSlot == 0 then
  3248.                         bucketSlot = i
  3249.                     else
  3250.                         turtle.select(i)
  3251.                         turtle.transferTo(bucketSlot)
  3252.                     end
  3253.                 elseif data.name == "minecraft:water_bucket" then
  3254.                     water = water + 1
  3255.                 end
  3256.             else
  3257.                 emptySlots = emptySlots + 1
  3258.             end
  3259.         end
  3260.         return emptySlots, water
  3261.     end
  3262.    
  3263.    
  3264.     T:go("C1R1")                                                -- place block next to ladder support block, turn right to check ladder
  3265.     local blockType = T:getBlockType("forward")                 -- Is there a ladder to the right?
  3266.     if blockType:find("ladder") == nil then
  3267.         T:go("C1L2")                                            -- Place block as ladder not present
  3268.     else                                                        -- ladder present
  3269.         T:go("L2")                                              -- ready to check other side
  3270.     end
  3271.     blockType = T:getBlockType("forward")
  3272.     if blockType:find("ladder") == nil then
  3273.         T:go("C1R1")
  3274.     else
  3275.         T:go("R1")
  3276.     end
  3277.     blockType = T:getBlockType("down")
  3278.     local dirt = "minecraft:dirt"
  3279.     if T:getItemSlot("minecraft:soul_sand") > 0 then
  3280.         dirt = "minecraft:soul_sand"
  3281.     end
  3282.     if blockType:find("bedrock") ~= nil then
  3283.         utils.goBack(1)
  3284.         T:place(dirt, -1, "forward", false)                     -- placed at end of potential water source, next to ladder
  3285.     else
  3286.         T:place(dirt, -1, "down", false)                        -- placed in ground, next to ladder
  3287.         utils.goBack(1)
  3288.         T:placeWater("forward")                             -- place extra water source
  3289.     end
  3290.     T:go("R1C1 R2C1 L1F1C2 R1C1 L2C1 R1F1C2 R1C1 L1C1 L1C1 L1F1", false, 0, true)
  3291.     -- ready for water sources to be placed
  3292.     T:placeWater("forward")                                 -- place front water source
  3293.     T:turnRight(2)                                          -- facing backward
  3294.     T:placeWater("forward")                                 -- place back water source
  3295.     T:go("R2U1")                                            -- facing forward, U1, above centre of water source
  3296.     lib.fillBuckets(R.height, true)                         -- fill as many buckets as required or until inventory full, sort inventory as well
  3297.     local nextToLadder = false
  3298.     --T:go("F2R1")
  3299.     T:go("x0F1 x0F1C1 R1")                                  -- move forward 2 taking out blocks above, plug behind soul sand
  3300.     if T:getBlockType("forward"):find("ladder") == nil then -- no ladder here
  3301.         T:turnLeft(2)
  3302.         if T:getBlockType("forward"):find("ladder") ~= nil then -- ladder here
  3303.             nextToLadder = true
  3304.         end
  3305.         T:turnRight(1)
  3306.     else
  3307.         nextToLadder = true
  3308.         T:turnLeft(1)
  3309.     end
  3310.     -- now above soul sand, facing forward
  3311.     if nextToLadder then                                -- if nextToLadder, no need for signs
  3312.         utils.goBack(2)                                 -- return to source centre
  3313.     else
  3314.         T:go("F2 L1C1R1C1R1C1L1", false, 0, true)       -- prepare layer 1
  3315.         lib.addSign()
  3316.         T:go("U1F1R1F1 L1C1R1C1R1C1L1", false, 0, true) -- prepare layer 2
  3317.         lib.addSign()
  3318.         T:go("L1F1 R1F1R1", false, 0, true)             -- above source, level 2
  3319.     end
  3320.     -- ready to build lift
  3321.     lib.buildLift(R.height - 1)
  3322.     lib.cleanUp(R.height - 1)
  3323.    
  3324.     return {"Bubble lift created", "Check correct operation", "Check exit before using" }
  3325. end
  3326.  
  3327. local function createBubbleTrap(R) -- 34
  3328.     --[[
  3329.     Replace floor of existing volume of water with soulsand
  3330.     Used in river biome for squid farm. Area should be enclosed
  3331.     with solid walls surface to floor.
  3332.     Usually 7 blocks wide
  3333.     ]]
  3334.     local lib = {}
  3335.    
  3336.     function lib.clearDown(depth)
  3337.         while utils.clearVegetation("down") do
  3338.             T:down(1)
  3339.             depth = depth + 1
  3340.         end
  3341.         T:place("soul_sand", -1, "down", false)
  3342.         return depth
  3343.     end
  3344.    
  3345.     function lib.clearLength(length, depth)
  3346.         local moves = 0
  3347.         while moves < length - 1 do
  3348.             if utils.clearVegetation("forward") then
  3349.                 T:forward(1)
  3350.                 moves = moves + 1
  3351.                 depth = lib.clearDown(depth) -- go down if in water/air
  3352.                 if moves >= length - 1 then
  3353.                     return depth
  3354.                 end
  3355.             else -- block in front
  3356.                 local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
  3357.                 while not waterAhead do     -- solid block in front
  3358.                     T:up(1)
  3359.                     depth = depth - 1
  3360.                     if depth < 1 then
  3361.                         return 0
  3362.                     end
  3363.                     waterAhead = utils.clearVegetation("forward")
  3364.                 end
  3365.             end
  3366.         end
  3367.  
  3368.         return depth
  3369.     end
  3370.    
  3371.     function lib.turn(facingForward, depth)
  3372.         local direction = "R"
  3373.         if not facingForward then
  3374.             direction = "L"
  3375.         end
  3376.         T:go(direction.. 1)
  3377.         if utils.clearVegetation("forward") then
  3378.             T:forward(1)
  3379.             depth = depth + lib.clearDown(depth)
  3380.         else
  3381.             while not utils.clearVegetation("forward") do
  3382.                 T:up(1)
  3383.                 depth = depth - 1
  3384.             end
  3385.         end
  3386.         T:go(direction.. 1)
  3387.        
  3388.         return depth
  3389.     end
  3390.    
  3391.     local depth = 0
  3392.     local length = 0
  3393.     local width = 0
  3394.     local outbound = true
  3395.     local facingForward = true
  3396.     local inWater, onWater = utils.getWaterStatus()
  3397.     inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,true) -- move into water, max descent 2
  3398.     if R.length == 0 then
  3399.         R.length = lib.getLength()
  3400.     end
  3401.     if R.width == 0 then
  3402.         T:turnRight(1)
  3403.         R.width = lib.getLength()
  3404.         T:turnLeft(1)
  3405.     end
  3406.     -- go down to floor
  3407.     depth = lib.clearDown(depth)
  3408.     while width < R.width do
  3409.         -- now on floor, move along sea/river bed following contour
  3410.         depth = lib.clearLength(R.length, depth)
  3411.         width = width + 1
  3412.         -- now turn and repeat
  3413.         if width < R.width then
  3414.             depth = lib.turn(facingForward, depth)
  3415.             facingForward = not facingForward
  3416.         end
  3417.     end
  3418.     -- finished so return to surface
  3419.     T:up(1) -- up 1 to check for water below
  3420.     while T:isWater("down") do
  3421.         T:up(1)
  3422.     end
  3423.    
  3424.     return {}
  3425. end
  3426.  
  3427. local function createCorridor(R) -- 52
  3428.     --[[create a corridoor 2 blocks high, with floor and ceiling guaranteed]]
  3429.     local lib = {}
  3430.    
  3431.     function lib.continue(R, currentSteps, totalSteps)
  3432.         if not R.silent then
  3433.             if currentSteps >= 64 and R.length == 0 then
  3434.                 -- request permission to continue if infinite
  3435.                 T:clear()
  3436.                 print("Completed "..totalSteps..". Ready for 64 more")
  3437.                 print("Do you want to continue? (y/n)")
  3438.                 response = read()
  3439.                 if response:lower() ~= "y" then
  3440.                     return true, 0
  3441.                 else
  3442.                     return false, currentSteps
  3443.                 end
  3444.             end
  3445.         end
  3446.         return true, currentSteps
  3447.     end
  3448.    
  3449.     function lib.seal()
  3450.         local blockType = T:getBlockType("forward")
  3451.         if blockType:find("water") ~= nil then
  3452.             T:place("stone", 0, "forward", false)
  3453.             return "water"  -- water found
  3454.         elseif blockType:find("lava") ~= nil then
  3455.             T:place("stone", 0, "forward", false)
  3456.             return "lava"   -- lava found
  3457.         end
  3458.         return ""   -- no water or lava
  3459.     end
  3460.    
  3461.     function lib.checkSeal(R)
  3462.         local fluidType = ""
  3463.         if R.data == "seal" then        -- check for lava/water at the sides
  3464.             T:turnRight(1)
  3465.             fluidType = lib.seal()      -- could be "", "water", "lava"
  3466.             T:turnLeft(2)
  3467.             local blockType = lib.seal()
  3468.             if fluidType == "" then     -- no water / lava so far
  3469.                 fluidType = blockType   -- could be "", "water", "lava"
  3470.             end
  3471.             T:turnRight(1)
  3472.         end
  3473.         return fluidType                -- could be "", "water", "lava"
  3474.     end
  3475.    
  3476.     function lib.placeTorch(R, torchSpaces, totalSteps)
  3477.         if R.torchInterval > 0 then -- torches onboard
  3478.             if torchSpaces == R.torchInterval then -- time to place another torch
  3479.                 if totalSteps < R.length then -- not at end of run
  3480.                     if T:getItemSlot("minecraft:torch") > 0 then
  3481.                         T:place("minecraft:torch", -1, "down")
  3482.                     end
  3483.                     torchSpaces = 1
  3484.                 end
  3485.             end
  3486.         end
  3487.         return torchSpaces -- original value or 1
  3488.     end
  3489.    
  3490.     local currentSteps = 0                  -- counter for infinite length. pause every 64 blocks
  3491.     local totalSteps = 0                    -- counter for all steps so far
  3492.     local torchSpaces = R.torchInterval     -- if torches present, counter to place with 8 blocks between
  3493.     local fluidType = ""
  3494.     local damLength = 0
  3495.     local damStarted = false
  3496.     local doContinue = true
  3497.     if T:getItemSlot("minecraft:torch") == 0 then
  3498.         R.torchInterval = 0 -- set to default 9 in getTask()
  3499.     end
  3500.     for steps = 1, R.length do
  3501.         -- starts on floor of tunnel
  3502.         doContinue, currentSteps = lib.continue(R, currentSteps, totalSteps) -- continue tunnelling?
  3503.         if not doContinue then
  3504.             break
  3505.         end
  3506.         T:go("C2U1C0", false, 0, true)  -- place floor, up 1, place ceiling
  3507.         fluidType = lib.checkSeal(R)        -- if R.data == "seal", check for water/lava at ceiling level
  3508.         if fluidType == "" then -- either R.data ~= "seal" or no fluid found
  3509.             torchSpaces = lib.placeTorch(R, torchSpaces, totalSteps) -- original value or 1 if torch placed
  3510.             T:go("F1D1", false, 0, true)
  3511.         elseif fluidType == "water" then
  3512.             T:go("F1R2 C1D1 C1L2")
  3513.             damStarted = true
  3514.             damLength = damLength + 1
  3515.         else    --lava
  3516.             T:go("F1D1", false, 0, true)
  3517.         end
  3518.         blockType = lib.checkSeal(R)
  3519.         if blockType ~= "" then
  3520.             fluidType = blockType
  3521.         end
  3522.         currentSteps = currentSteps + 1
  3523.         totalSteps = totalSteps + 1
  3524.         torchSpaces = torchSpaces + 1
  3525.         if damStarted and fluidType == "" then -- was in water, but no more
  3526.             T:go("R2 F"..damLength + 1 .."U1L2F"..damLength + 1 .."D1")
  3527.             damStarted = false
  3528.         end
  3529.     end
  3530.     if fluidType ~= "" then -- water or lava found while tunnelling
  3531.         T:go("U1C0")
  3532.         lib.checkSeal(R)
  3533.         T:go("C1")
  3534.         T:down(1)
  3535.     end
  3536.     return {}
  3537. end
  3538.  
  3539. local function createDragonTrap() -- 49
  3540.     local lib = {}
  3541.    
  3542.     function lib.attack()
  3543.         local totalHitsF = 0
  3544.         local totalHitsU = 0
  3545.         local totalHitsD = 0
  3546.         while true do
  3547.             local hitF = false
  3548.             local hitU = false
  3549.             local hitD = false
  3550.             if turtle.attackUp() then
  3551.                 hitU = true
  3552.                 totalHitsU = totalHitsU + 1
  3553.             end
  3554.             if turtle.attackDown() then
  3555.                 hitD = true
  3556.                 totalHitsD = totalHitsD + 1
  3557.             end
  3558.             if turtle.attack() then
  3559.                 hitF = true
  3560.                 totalHitsF = totalHitsF + 1
  3561.             end
  3562.             if hitF or hitU or hitD then
  3563.                 print("hits forward: "..totalHitsF..", up: "..totalHitsU..", down: "..totalHitsD)
  3564.             end
  3565.         end
  3566.     end
  3567.     -- build up 145 blocks with ladders
  3568.     for i = 1, 145 do
  3569.         T:go("U1C2")
  3570.         turtle.back()
  3571.         T:place("minecraft:ladder", -1, "down")
  3572.         turtle.forward()
  3573.     end
  3574.     T:go("R2F1C1 L1C1 L2C1 R1")
  3575.     for i = 1, 100 do
  3576.         T:go("F1C2U1C0D1")
  3577.     end
  3578.     T:forward(1)
  3579.     T:place("minecraft:obsidian", -1, "down")
  3580.     T:go("R2F1x2R2")
  3581.     T:placeWater("forward")
  3582.     T:go("R2F6R2")
  3583.     lib.attack()
  3584.     return {}
  3585. end
  3586.    
  3587. local function createEnderTower(stage) -- 66
  3588.     --[[ lower base = stage 1, upper base = 2, tower = 3 ]]
  3589.     local lib = {}
  3590.     --[[ go(path, useTorch, torchInterval, leaveExisting, preferredBlock) ]]
  3591.     function lib.getEmptySlots()
  3592.         local empty = 0
  3593.         for i = 1, 16 do
  3594.             if turtle.getItemCount(i) == 0 then
  3595.                 empty = empty + 1
  3596.             end
  3597.         end
  3598.         return empty
  3599.     end
  3600.  
  3601.     function lib.getStone(direction, stacks)
  3602.         --[[ get block user wants to use ]]
  3603.         local suck = turtle.suck   
  3604.         if direction == "down" then
  3605.             suck = turtle.suckDown
  3606.         end
  3607.         if T:getBlockType(direction) == "minecraft:chest" then
  3608.             T:sortInventory()
  3609.             local slot = T:getFirstEmptySlot() --find spare slot
  3610.             if slot > 0 then --empty slot found
  3611.                 turtle.select(1)
  3612.                 if stacks == 0 then
  3613.                     while suck() do end
  3614.                 else
  3615.                     for i = 1, stacks do -- get # stacks of stone from chest
  3616.                         suck()
  3617.                     end
  3618.                 end
  3619.                 if T:getSlotContains(slot) == "" then
  3620.                     return T:getMostItem()              -- empty chest
  3621.                 else
  3622.                     return T:getSlotContains(slot)      -- use this as default building block
  3623.                 end
  3624.             else
  3625.                 return T:getMostItem()              -- full inventory
  3626.             end
  3627.         else
  3628.             return T:getMostItem()              -- no chest
  3629.         end
  3630.     end
  3631.    
  3632.     function lib.stackBuckets()
  3633.         local data = {}
  3634.         local bucketSlot = 0
  3635.         local emptySlots = 0
  3636.         local water = 0
  3637.         T:sortInventory()
  3638.         for i = 1, 16 do
  3639.             -- find first empty bucket
  3640.             if turtle.getItemCount(i) > 0 then
  3641.                 data = turtle.getItemDetail(i)
  3642.                 if data.name == "minecraft:bucket" then
  3643.                     if bucketSlot == 0 then
  3644.                         bucketSlot = i
  3645.                     else
  3646.                         turtle.select(i)
  3647.                         turtle.transferTo(bucketSlot)
  3648.                     end
  3649.                 elseif data.name == "minecraft:water_bucket" then
  3650.                     water = water + 1
  3651.                 end
  3652.             else
  3653.                 emptySlots = emptySlots + 1
  3654.             end
  3655.         end
  3656.         return emptySlots, water
  3657.     end
  3658.    
  3659.     function lib.countWaterBuckets()
  3660.         local data = {}
  3661.         local buckets = 0
  3662.         for i = 1, 16 do
  3663.             data = turtle.getItemDetail(i)
  3664.             if data.name == "minecraft:water_bucket" then
  3665.                 buckets = buckets + 1
  3666.             end
  3667.         end
  3668.         return buckets
  3669.     end
  3670.    
  3671.     function lib.baseRun(preferredBlock, count, turn)
  3672.         for i = 1, count do
  3673.             T:go("C2F1", false, 0, false, preferredBlock)
  3674.         end
  3675.         T:go("C2"..turn, false, 0, false, preferredBlock)
  3676.     end
  3677.    
  3678.     function lib.outsideRun(preferredBlock)
  3679.         T:place("fence", -1, "down", false)
  3680.         T:forward(1)
  3681.         T:place(preferredBlock, -1, "down", false)
  3682.         T:forward(1)
  3683.         T:place(preferredBlock, -1, "down", false)
  3684.         T:forward(2)
  3685.         T:place(preferredBlock, -1, "down", false)
  3686.     end
  3687.    
  3688.     function lib.signRun(preferredBlock ,message)
  3689.         T:place(preferredBlock, -1, "down", false)
  3690.         T:forward(4)
  3691.         T:place(preferredBlock, -1, "down", false)
  3692.         turtle.back()
  3693.         turtle.back()
  3694.         T:down(1)
  3695.         T:place("sign", -1, "forward", false, message)
  3696.         T:go("U1F2")
  3697.     end
  3698.    
  3699.     function lib.goToWater(height)
  3700.         local built = 0 -- measures completed lift height
  3701.         while turtle.down() do -- takes turtle to bottom of water source
  3702.             height = height + 1
  3703.             if turtle.detect() then
  3704.                 built = built + 1
  3705.             end
  3706.         end
  3707.         T:up(1) -- above watersource assuming it is 1-1.5 blocks deep
  3708.         height = height - 1
  3709.         -- built = built - 1 not required as next block is water source: not detected
  3710.         return built, height
  3711.     end
  3712.    
  3713.     function lib.fillBuckets(toBuild)
  3714.         local emptySlots, water = lib.stackBuckets() -- gets no of empty slots + no of water buckets
  3715.         if water < toBuild then -- no of water buckets onboard less than required quantity
  3716.             for i = 1, toBuild do -- fill required no of buckets up to max space in inventory
  3717.                 emptySlots = lib.getEmptySlots()
  3718.                 if emptySlots == 0 then -- inventory full
  3719.                     break
  3720.                 else
  3721.                     if T:getWater("down") then
  3722.                         water = water + 1
  3723.                         sleep(0.5)
  3724.                     end
  3725.                 end
  3726.             end
  3727.         end
  3728.        
  3729.         return water
  3730.     end
  3731.    
  3732.     function lib.buildLift(preferredBlock)
  3733.         local built = 0 -- measures completed lift height
  3734.         local height = 0 -- measures total height from starting position
  3735.         built, height = lib.goToWater(height) -- returns lift blocks already placed, total height of drop from starting point
  3736.         local toBuild = height - built -- no of blocks to increase lift size
  3737.         while toBuild > 0 do -- at least 1 block height remaining
  3738.             local water = lib.fillBuckets(toBuild) -- no of water buckets onboard (could be more than required)
  3739.             if water > toBuild then
  3740.                 water = toBuild
  3741.             end
  3742.             while turtle.detect() do -- climb to top of existing lift
  3743.                 turtle.up()
  3744.                 height = height - 1
  3745.             end
  3746.             T:forward(1)
  3747.             for i = 1, water do -- build lift by no of water buckets
  3748.                 if T:placeWater("forward")  then
  3749.                     T:up(1)
  3750.                     height = height - 1
  3751.                     toBuild = toBuild - 1
  3752.                     T:place(preferredBlock, -1, "down", false)
  3753.                 end
  3754.             end
  3755.             turtle.back()
  3756.             -- may still be some height to complete, but needs refill
  3757.             if toBuild > 0 then
  3758.                 lib.goToWater(0) --return to source
  3759.                 lib.fillBuckets(toBuild)
  3760.             end
  3761.         end
  3762.         if height > 0 then -- if any remaining distance
  3763.             T:up(height)
  3764.         end
  3765.        
  3766.     end
  3767.    
  3768.     function lib.buildSection(preferredBlock, solid)
  3769.         -- builds a section without any blocks in the centre
  3770.         -- second layer of each section end walls have fence posts
  3771.         T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- first side solid row
  3772.         if solid then -- first layer of each section
  3773.             T:go("F1C2 F1R1", false, 0, false, preferredBlock) -- top side solid row
  3774.         else
  3775.             T:go("F1") -- top side solid row
  3776.             if not T:place("fence", -1, "down", false) then-- first side
  3777.                 T:place(preferredBlock, -1, "down", false)
  3778.             end
  3779.             T:go("F1R1") -- top side solid row
  3780.         end
  3781.         T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- far side solid row
  3782.         T:go("F1C2 F1R1U1", false, 0, false, preferredBlock) -- bottom side solid row
  3783.     end
  3784.     --[[
  3785.         clsTurtle methods:
  3786.         clsTurtle.place(self, blockType, damageNo, direction, leaveExisting)
  3787.         clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
  3788.     ]]
  3789.     -- remove 1 stack stone from chest
  3790.     local preferredBlock = lib.getStone("down", 1) -- use this as default building block
  3791.     if stage == 1 then
  3792.         -- build base floor
  3793.         --T:go("R2F2R1F3R1", false, 0, false, preferredBlock)
  3794.         T:go("R2F1C2R1F1C2F1C2F1C2R1", false, 0, false, preferredBlock)
  3795.         for i = 1, 2 do
  3796.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  3797.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  3798.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  3799.         end
  3800.         -- move back to centre, build water source, with soul sand at base of first source
  3801.         --T:go("R1F3L1C2F1C2F2D1", false, 0, false, preferredBlock) --just behind chest, 1 below ground level
  3802.         T:go("R1F3L1F2C2F1D1", false, 0, false, preferredBlock) --1 block behind chest, 1 below ground level
  3803.         T:place("minecraft:soul_sand", -1, "down", false) -- over block 1 of water source
  3804.         T:go("F1C2F1C2", false, 0, false, preferredBlock) -- over block 2 of water source
  3805.         T:go("F1C2U1C2", false, 0, false, preferredBlock) -- over block 4 of water source
  3806.         T:go("F1C2F1C2R2F5R2", false, 0, false, preferredBlock) -- over block 1 of water source
  3807.         T:placeWater("down")
  3808.         T:forward(2) -- over block 3 of water source
  3809.         T:placeWater("down")
  3810.         turtle.back() -- over block 2 of water source
  3811.         T:getWater("down")
  3812.         T:go("F2D1R2C2") -- over block 4 of water source
  3813.         T:go("U1", false, 0, false, preferredBlock)
  3814.         T:placeWater("down")
  3815.         T:forward(4)
  3816.         lib.stackBuckets() -- put all buckets in same slot
  3817.         T:dropItem("minecraft:dirt", "up", 0) -- drop dirt up:  clsTurtle.dropItem(self, item, direction, keepAmount)
  3818.         preferredBlock = lib.getStone("down", 6)
  3819.         T:go("R1F2R1U1") -- move to start position
  3820.         for i = 1, 2 do
  3821.             -- build first level of tower: 2 x outside run, 2 x sign run
  3822.             lib.outsideRun(preferredBlock)
  3823.             if i == 1 then -- place door
  3824.                 T:go("L1F1L1F1L1D1")
  3825.                 T:place("door", -1, "forward", false)
  3826.                 T:go("U1L1F1R1F1L1")
  3827.             end
  3828.             T:go("R1F1R1")
  3829.             lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
  3830.             T:go("L1F1L1C2", false, 0, false, preferredBlock)
  3831.             T:forward(4) -- miss out centre block
  3832.             T:place(preferredBlock, -1, "down", false)
  3833.             T:go("R1F1R1")
  3834.             lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
  3835.             T:go("L1F1L1")
  3836.             lib.outsideRun(preferredBlock)
  3837.             if i == 1 then -- layer 1
  3838.                 T:go("R1F1R1F1R1D1") -- place door
  3839.                 T:place("door", -1, "forward", false)
  3840.                 T:go("U1 R1F1 L1F5 L1U1 F2D1  F2R2 U1") -- go over door
  3841.             else -- layer 2
  3842.                 T:go("L1F5L1F6R2U1") -- over corner of lower platform
  3843.             end
  3844.         end
  3845.         for i = 1, 2 do -- build both sides of platform, leave centre missing
  3846.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  3847.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  3848.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  3849.         end
  3850.         T:go("R1F3L1C2F1C2F1C2F4C2F1C2F1C2", false, 0, false, preferredBlock) --fill in centre row
  3851.         --T:go("R2F6R1F1R1U1") -- go to start of tower base
  3852.         T:go("R2F7R2D3") -- go to start on top of chest
  3853.         T:sortInventory()
  3854.     elseif stage == 2 then
  3855.         -- start on top of chest, should have sufficient stone in inventory
  3856.         T:go("U3L1F1R1F1U1") -- go to start of tower base
  3857.         for i = 1, 7 do -- build 14 block high tower
  3858.             lib.buildSection(preferredBlock, false)
  3859.             lib.buildSection(preferredBlock, true)
  3860.         end
  3861.         T:go("R2F4R1F4R1", false, 0, false, preferredBlock) -- build upper platform (154 blocks remaining)
  3862.         for i = 1, 2 do -- build both sides of upper platform, leave centre missing
  3863.             lib.baseRun(preferredBlock, 12, "R1F1R1")
  3864.             lib.baseRun(preferredBlock, 12, "L1F1L1")
  3865.             lib.baseRun(preferredBlock, 12, "R1F1R1")
  3866.             lib.baseRun(preferredBlock, 12, "L1F1L1")
  3867.             lib.baseRun(preferredBlock, 12, "R1F6R1")
  3868.         end
  3869.         T:go("R1F5 L1C2 F1C2 F1C2 F1C2 F1C2 F4C2 F1C2 F1C2 F1C2 F1C2 ", false, 0, false, preferredBlock) --fill in centre row
  3870.         T:go("R2F5") -- return to drop area
  3871.         lib.buildLift(preferredBlock) -- build bubble lift
  3872.         T:go("F3R1F1R1U1") -- go to start of tower base
  3873.         T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock)      -- left side layer 21
  3874.         T:go("F2C2 F2C2 L1F1L1", false, 0, false, preferredBlock)   -- centre layer 21
  3875.         T:go("C2F4 C2R2U1", false, 0, false, preferredBlock)        -- right side layer 21
  3876.         T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock)      -- right side layer 22
  3877.         T:place("fence", -1, "down", false)                         -- fence centre of bottom side layer 22
  3878.         T:go("F2C2 F2L1F1L1", false, 0, false, preferredBlock)      -- centre layer 22
  3879.         T:go("C2F4 C2R2F2L1F1R2D2", false, 0, false, preferredBlock) --ready to place ladder
  3880.         T:place("ladder", -1, "forward", false)
  3881.         T:up(1)
  3882.         T:place("ladder", -1, "forward", false)
  3883.         --T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
  3884.         T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
  3885.         for i = 1, 2 do -- build both sides of platform, leave centre missing
  3886.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  3887.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  3888.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  3889.         end
  3890.         T:go("R1F3 L1C2 F1C2 F1C2 F1", false, 0, false, preferredBlock) --fill in centre row
  3891.         T:place("minecraft:soul_sand", -1, "down", false)
  3892.         T:go("F1C2 F2C2 F1C2 F1C2", false, 0, false, preferredBlock)
  3893.         T:go("R2F6R1F1R1U1") -- go to start of tower base
  3894.         -- build 2 levels, finish signs and ladders
  3895.         T:go("C2F2 R1D2 U1", false, 0, false, preferredBlock)
  3896.         T:place("ladder", -1, "down", false)
  3897.         T:turnRight(1)
  3898.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3899.         T:go("U1R2F2C2 R1F2C2 R1", false, 0, false, preferredBlock) --top right corner
  3900.         T:go("F4C2B2D1", false, 0, false, preferredBlock)
  3901.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3902.         T:go("U1F2R1F1C2F1R1U1", false, 0, false, preferredBlock) --ready for second level
  3903.         T:go("C2F2 R2D1", false, 0, false, preferredBlock)
  3904.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3905.         T:go("U1R2F2C2R1", false, 0, false, preferredBlock) --top left corner
  3906.         T:go("F1R1C2F4C2", false, 0, false, preferredBlock) --mid bottom row
  3907.         T:go("L1F1L1C2", false, 0, false, preferredBlock) -- bottom right corner
  3908.         T:go("F2R2D1", false, 0, false, preferredBlock)
  3909.         T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
  3910.         T:go("U1R2F2C2", false, 0, false, preferredBlock) -- top right corner
  3911.         -- return to chest
  3912.         T:go("L1F1L1 F5D23R2", false, 0, false, preferredBlock) -- return to chest
  3913.         T:sortInventory()
  3914.     elseif stage == 3 then
  3915.         --[[ move to top of structure
  3916.         | 4 |
  3917.         |3 5|
  3918.         | X |
  3919.         |2 6|
  3920.         | 1 |
  3921.         ]]
  3922.         local towerHeight = 128 -- even no only suggest 128
  3923.         while turtle.detect() do
  3924.             turtle.up()
  3925.         end
  3926.         T:go("F1U1", false, 0, false, preferredBlock) -- return to finish tower
  3927.         for i = 1, towerHeight do -- 1
  3928.             T:go("C2U1", false, 0, false, preferredBlock)
  3929.         end
  3930.         T:go("F1L1F1R1D2")
  3931.         while turtle.down() do -- 2
  3932.             T:fillVoid("up", {preferredBlock})
  3933.         end
  3934.         T:go("F1R2C1R2F1D1", false, 0, false, preferredBlock)
  3935.         for i = 1, towerHeight / 2 do -- 3
  3936.             T:go("U2C2", false, 0, false, preferredBlock)
  3937.         end
  3938.         T:go("U1F1R1F1R1D1", false, 0, false, preferredBlock) -- back of tower facing front
  3939.         local deviate = false
  3940.         while turtle.down() do -- 4
  3941.             T:place("fence", -1, "up", false)
  3942.             if turtle.down() then
  3943.                 T:fillVoid("up", {preferredBlock})
  3944.             else
  3945.                 T:go("F1R2C1R1F1R1D1", false, 0, false, preferredBlock)
  3946.                 deviate = true
  3947.                 break
  3948.             end
  3949.         end
  3950.         if not deviate then
  3951.             T:go("F1L1F1R1D1", false, 0, false, preferredBlock)
  3952.         end
  3953.         for i = 1, towerHeight / 2 do -- 5
  3954.             T:go("U2C2", false, 0, false, preferredBlock)
  3955.         end
  3956.         T:go("F2R2", false, 0, false, preferredBlock) -- facing back of tower
  3957.         while turtle.down() do -- 6
  3958.             T:fillVoid("up", {preferredBlock}) --layer 129
  3959.         end
  3960.         T:go("F1L2C1U"..towerHeight)
  3961.         T:go("F4R1F3R1U1", false, 0, false, preferredBlock)
  3962.         -- add small platform at the top
  3963.         lib.baseRun(preferredBlock, 8, "R1F1R1")
  3964.         lib.baseRun(preferredBlock, 8, "L1F3L1")
  3965.         lib.baseRun(preferredBlock, 8, "L1F1L1")
  3966.         lib.baseRun(preferredBlock, 8, "R1F1R1")
  3967.         T:go("C2 F1C2 F1C2 F4C2 F1C2 F1C2 R2F3", false, 0, false, preferredBlock) --fill in centre row
  3968.         lib.buildLift(preferredBlock) -- build bubble lift
  3969.     end
  3970.     return {}
  3971. end
  3972.  
  3973. local function createFarm(R, extend) -- 31
  3974.     -- if extend ~= nil then this has been called from createFarmExtension()
  3975.     -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  3976.     local lib = {}
  3977.     function lib.addWaterSource(R, pattern, storage)
  3978.         -- pattern = {"d","c","c","d"} t = place crafting  instead of dirt
  3979.         -- place(self, blockType, damageNo, direction, leaveExisting, signText)
  3980.         T:go("D1x2C2", false, 0, false, R.useBlockType)
  3981.         for i = 1, 4 do
  3982.             T:dig("forward")
  3983.             if pattern[i] == "d" then
  3984.                 T:place("dirt", -1, "forward", false)
  3985.             elseif pattern[i] == "t" then
  3986.                 --if not T:place("minecraft:crafting_table", -1, "forward", false) then
  3987.                 if T:place(storage, -1, "forward", false) then
  3988.                     if T:dropItem("crafting", "forward", 0) then
  3989.                         print("Crafting table -> buried storage")
  3990.                     end
  3991.                 else
  3992.                     T:place("dirt", -1, "forward", false) -- dirt if no storage available
  3993.                 end
  3994.             else
  3995.                 T:place(R.useBlockType, -1, "forward", false)
  3996.             end
  3997.             T:turnRight(1)
  3998.         end
  3999.         T:up(1)
  4000.         T:placeWater("down")
  4001.     end
  4002.    
  4003.     function lib.placeDirt(count, atCurrent)
  4004.         if atCurrent then
  4005.             local blockType = T:getBlockType("down")
  4006.             if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
  4007.                 T:place("dirt", -1, "down", false)
  4008.             end
  4009.         end
  4010.         for  i = 1, count do
  4011.             T:forward(1)
  4012.             T:dig("up")
  4013.             local blockType = T:getBlockType("down")
  4014.             if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
  4015.                 T:place("dirt", -1, "down", false)
  4016.             end
  4017.         end
  4018.     end
  4019.  
  4020.     function lib.placeStorage(storage, storageBackup)
  4021.         T:dig("down")
  4022.         if not T:place(storage, -1, "down", false) then-- place barrel/chest below
  4023.             T:place(storageBackup, -1, "down", false) -- place chest below
  4024.         end
  4025.     end
  4026.  
  4027.    
  4028.     -- extend "", "right" or "forward". only adds a single new farm.
  4029.     -- right adds farm and checks for existing front extensions, dealt with separately
  4030.     -- clsTurtle.place(blockType, damageNo, direction, leaveExisting)
  4031.     if extend == nil then
  4032.         extend = ""
  4033.     end
  4034.     local blockType = ""
  4035.     -- extend = "right": placed on cobble corner of existing farm facing right side
  4036.     -- extend = "front": placed on cobble corner of existing farm facing front
  4037.     -- else placed on ground at corner of potential new farm facing front
  4038.    
  4039.     local storage, storageBackup = utils.setStorageOptions()
  4040.     -- step 1 dig ditch round perimeter wall
  4041.     if extend == "right" then
  4042.         -- move to front corner ground ready for ditch
  4043.         T:go("F1L1F12D1R1", false, 0, false, R.useBlockType)
  4044.         -- cut ditch round new farm extension
  4045.         for i = 1, 12 do
  4046.             T:go("x0F1")
  4047.         end
  4048.         T:go("R1x0")
  4049.         for i = 1, 13 do
  4050.             T:go("x0F1")
  4051.         end
  4052.         T:go("R1x0")
  4053.         -- now at lower right corner. if extension below, do not cut ditch
  4054.         blockType = T:getBlockType("forward")
  4055.         if blockType:find("stone") ~= nil then -- already a farm extension on left side
  4056.             -- return to start for adding chests and walls
  4057.             T:go("U1R1F1L1F12", false, 0, false, R.useBlockType)
  4058.         else -- finish ditch
  4059.             for i = 1, 12 do
  4060.                 T:go("x0F1")
  4061.             end
  4062.             T:go("R1U1F1") -- on corner of new extension
  4063.         end
  4064.     elseif extend == "forward" then
  4065.         T:go("L1F2R1D1", false, 0, false, R.useBlockType)
  4066.         -- cut ditch round new farm extension
  4067.         for i = 1, 12 do
  4068.             T:go("x0F1", false, 0, false, R.useBlockType)
  4069.         end
  4070.         T:go("R1x0", false, 0, false, R.useBlockType)
  4071.         for i = 1, 13 do
  4072.             T:go("x0F1", false, 0, false, R.useBlockType)
  4073.         end
  4074.         T:go("R1x0", false, 0, false, R.useBlockType)
  4075.         for i = 1, 11 do
  4076.             T:go("x0F1", false, 0, false, R.useBlockType)
  4077.         end
  4078.         T:go("U1x0F1R1F12R1", false, 0, false, R.useBlockType) -- on corner of new extension
  4079.     else -- new farm. cut a groove round the entire farm base
  4080.         -- move to left side of intended wall
  4081.         T:go("L1F1x0R1", false, 0, false, R.useBlockType)
  4082.         for j = 1, 4 do
  4083.             for i = 1, 12 do
  4084.                 T:go("x0F1", false, 0, false, R.useBlockType)
  4085.             end
  4086.             T:go("R1x0F1", false, 0, false, R.useBlockType)
  4087.         end
  4088.         T:go("R1F1L1U1", false, 0, false, R.useBlockType)
  4089.     end
  4090.     -- stage 2 place sapling and double barrel/chest
  4091.     T:dig("down") --remove cobble if present
  4092.     T:place("dirt", -1, "down", false)
  4093.     T:go("F1R2")
  4094.     T:place("sapling", -1, "forward", false) -- plant sapling
  4095.     T:go("L1")
  4096.     lib.placeStorage(storage, storageBackup)
  4097.     T:go("L1F1R1")
  4098.     lib.placeStorage(storage, storageBackup)
  4099.     T:turnLeft(1)
  4100.     if extend == "right" then -- cobble wall exists so go forward to its end
  4101.         T:forward(9)
  4102.     else -- new farm or extend forward
  4103.         for i = 1, 9 do -- complete left wall to end of farm
  4104.             T:go("F1x0x2C2", false, 0, false, R.useBlockType)
  4105.         end
  4106.     end
  4107.     T:go("R1F1 R1x0 x2C2 F1D1", false, 0, false, R.useBlockType)-- turn round ready for first dirt col
  4108.     lib.addWaterSource(R, {"d","c","c","d"}, storage) -- water at top of farm
  4109.     lib.placeDirt(9, false) -- place dirt back to start
  4110.     lib.addWaterSource(R, {"c","c","t","d"}, storage) -- water source next to chests, includes crafting table
  4111.     T:go("U1F1R2")
  4112.     if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
  4113.         lib.placeStorage(storage, storageBackup)
  4114.     end
  4115.     T:go("R1F1L1")
  4116.     if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
  4117.         lib.placeStorage(storage, storageBackup)
  4118.     end
  4119.     T:go("F1D1")
  4120.     lib.placeDirt(9, true)
  4121.     local turn = "R"
  4122.     for i = 1, 7 do
  4123.         T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
  4124.         lib.placeDirt(9, true)
  4125.         if turn == "R" then
  4126.             turn = "L"
  4127.         else
  4128.             turn = "R"
  4129.         end
  4130.     end
  4131.     T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
  4132.     lib.addWaterSource(R, {"d","c","c","d"}, storage)
  4133.     lib.placeDirt(9, false)
  4134.     lib.addWaterSource(R, {"c","c","d","d"}, storage)
  4135.     T:go("F1U1R1C2x0F1x0x2C2R1", false, 0, false, R.useBlockType)
  4136.     for i = 1, 11 do
  4137.         T:go("F1x0x2C2", false, 0, false, R.useBlockType)
  4138.     end
  4139.     -- add barrel/chest to any existing farm extension to the right
  4140.     T:go("L1F1L1")
  4141.     if T:getBlockType("down"):find("stone") == nil then -- farm extension already exists to right
  4142.         lib.placeStorage(storage, storageBackup)
  4143.     end
  4144.     T:go("L1F11")
  4145.    
  4146.     return {"Modular farm completed"}
  4147. end
  4148.  
  4149. local function createFarmExtension(R) -- 32
  4150.     -- assume inventory contains 4 chests, 64 cobble, 128 dirt, 4 water, 1 sapling
  4151.     -- check position by rotating to face tree/sapling
  4152.     local doContinue = true
  4153.     local treePresent = false
  4154.     local extend = "right" -- default
  4155.     if R.subChoice == 1 then
  4156.         extend = "forward"
  4157.     end
  4158.     local storage, storageBackup = utils.setStorageOptions()
  4159.     local blockType = T:getBlockType("down")
  4160.     if blockType:find(storage) == nil and blockType:find(storageBackup) == nil then
  4161.         return
  4162.         {
  4163.             "Barrel or chest not present below\n",
  4164.             "Unable to calculate position",
  4165.             "Move me next to/front of the tree/sapling",
  4166.             "lower left corner of the existing farm."
  4167.         }
  4168.     else
  4169.         for i = 1, 4 do
  4170.             blockType = T:getBlockType("forward")
  4171.             if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
  4172.                 treePresent = true
  4173.                 break
  4174.             end
  4175.             T:turnRight()
  4176.         end
  4177.         if not treePresent then
  4178.             return
  4179.             {
  4180.                 "Unable to locate tree or sapling",
  4181.                 "Plant a sapling on the lower left",
  4182.                 "corner of the farm, or move me there"
  4183.             }
  4184.         end
  4185.     end
  4186.     if doContinue then -- facing tree. check if on front or l side of farm
  4187.         if extend == "forward" then
  4188.             T:go("R1F11") -- to other side of farm. may be stone or barrel/chest below
  4189.             blockType = T:getBlockType("down")
  4190.             if blockType:find(storage) ~= nil or blockType:find(storageBackup) ~= nil then
  4191.                 doContinue = false
  4192.             end
  4193.         else
  4194.             T:go("R2F9") -- to right of farm, may be sapling/tree in front
  4195.             blockType = T:getBlockType("forward")
  4196.             if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
  4197.                 doContinue = false
  4198.             end
  4199.         end
  4200.         if doContinue then -- extend farm.
  4201.             createFarm(R, extend)
  4202.         else
  4203.             return
  4204.             {
  4205.                 "This farm has already been extended",
  4206.                 "Move me next to/front of the tree / sapling",
  4207.                 "of the last extension in this direction."
  4208.             }
  4209.         end
  4210.     end
  4211.     return {"Modular crop farm extended"}
  4212. end
  4213.  
  4214. local function createFloorCeiling(R) -- 79 size integer 1 to 4
  4215.     --[[
  4216.     R.up = true for ceiling
  4217.     R.down = true for floor
  4218.     R.height = 0 for normal
  4219.     R.height combined with R.up/R.down used for remote access
  4220.     ]]
  4221.    
  4222.     local useBlock = T:getSlotContains(1)
  4223.     local waterPresent = false
  4224.    
  4225.     if R.useBlockType ~= "" then
  4226.         useBlock = R.useBlockType
  4227.     end
  4228.     print("Using ".. useBlock)
  4229.     local direction = "down"
  4230.     if R.up then
  4231.         direction = "up"
  4232.     end
  4233.     if R.height > 0 then -- remote placing. go up/down R.height first
  4234.         R.silent = true
  4235.         local depth = 0
  4236.         if R.down then -- floor could be under water
  4237.             while turtle.down() do
  4238.                 depth = depth + 1
  4239.             end
  4240.         elseif R.up then
  4241.             while turtle.up() do
  4242.                 depth = depth + 1
  4243.                 if depth > R.height + 3 then
  4244.                     break
  4245.                 end
  4246.             end
  4247.         end
  4248.         if not(R.height - depth <= 2 or depth - R.height <= 2) then
  4249.             T:up(depth)
  4250.             return {"Measured depth/height of "..depth.." > setting: "..R.height}
  4251.         end
  4252.         -- not returned so depth acceptable
  4253.     end
  4254.     -- check if block above/below
  4255.     local blockBelow = turtle.detectDown()
  4256.     local blockAbove = turtle.detectUp()
  4257.     if R.subChoice == 2 then -- New floor over existing
  4258.         -- if no block below, assume in correct position and continue
  4259.         -- else move up 1 and continue
  4260.         if blockBelow then T:up(1) end
  4261.     elseif R.subChoice == 4 then -- New ceiling under existing
  4262.         -- if no block above, assume in correct position and continue
  4263.         -- else move down 1 and continue
  4264.         if blockAbove then T:down(1) end
  4265.     end
  4266.    
  4267.     local evenWidth = false
  4268.     local evenHeight = false
  4269.     local loopWidth
  4270.     -- go(path, useTorch, torchInterval, leaveExisting)
  4271.     if R.width % 2 == 0 then
  4272.         evenWidth = true
  4273.         loopWidth = R.width / 2
  4274.     else
  4275.         loopWidth = math.ceil(R.width / 2)
  4276.     end
  4277.     if R.length % 2 == 0 then
  4278.         evenHeight = true
  4279.     end
  4280.     -- if R.width is even no, then complete the up/down run
  4281.     -- if R.width odd no then finish at top of up run and reverse
  4282.     for x = 1, loopWidth do
  4283.         -- Clear first column (up)
  4284.         local tAvailable = T:getStock(useBlock, -1)
  4285.         if tAvailable.total < R.length and not R.silent then
  4286.             return {"Insufficient resources to complete current row"}
  4287.         end
  4288.         for y = 1, R.length do
  4289.             local blockType = T:getBlockType("forward")
  4290.             if not waterPresent then
  4291.                 if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then
  4292.                     waterPresent = true
  4293.                 end
  4294.             end
  4295.             T:place(useBlock, -1, direction, false) -- leaveExisting = false
  4296.             if y < R.length then
  4297.                 T:go("F1", false, 0, false)
  4298.             end
  4299.         end
  4300.         -- clear second column (down)
  4301.         if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
  4302.             T:go("R1F1R1", false,0,false)
  4303.             tAvailable = T:getStock(useBlock, -1)
  4304.             if tAvailable.total < R.length and not R.silent then
  4305.                 return {"Insufficient resources to complete current row"}
  4306.             end
  4307.             for y = 1, R.length do
  4308.                 T:place(useBlock, -1, direction, false) -- leaveExisting = false
  4309.                 if y < R.length then
  4310.                     T:go("F1", false, 0, false)
  4311.                 end
  4312.             end
  4313.             if x < loopWidth then
  4314.                 T:go("L1F1L1", false,0,false)
  4315.             else
  4316.                 T:turnRight(1)
  4317.                 T:forward(R.width - 1)
  4318.                 T:turnRight(1)
  4319.             end
  4320.         else -- equals R.width but is 1,3,5,7 etc
  4321.             T:turnLeft(2) --turn round 180
  4322.             T:forward(R.length - 1)
  4323.             T:turnRight(1)
  4324.             T:forward(R.width - 1)
  4325.             T:turnRight(1)
  4326.         end
  4327.     end
  4328.     if waterPresent then
  4329.         return {"water or lava found"}
  4330.     end
  4331.     return {""}
  4332. end
  4333.  
  4334. local function createIceCanal(R) -- 55
  4335.     --[[
  4336.         R.subChoice =
  4337.         1: move right into canal, build left towpath
  4338.         2: build left towpath
  4339.         3: build right towpath
  4340.         4: move left into canal, build right towpath
  4341.         5/8: clear path 3 blocks high, place slabs/torches
  4342.         6/7: build alternating ice road / create 3 block high air gap (2 over water)
  4343.     ]]
  4344.     local oTurn = "R"
  4345.     if R.side == "R" then
  4346.         oTurn = "L"
  4347.     end
  4348.     local lib = {}
  4349.    
  4350.     function lib.convertTowpath(R)
  4351.         -- only used to convert existing water canal, so assume towpath already present
  4352.         -- starting position 1 block above existing towpath
  4353.         for i = 1, R.length do
  4354.             if turtle.detectDown() then                         -- eg existing torch
  4355.                 T:dig("down")
  4356.             end
  4357.             local placeSlab = true
  4358.             if R.torchInterval > 0 then                         -- place torches
  4359.                 if i == 1 or i % R.torchInterval == 0 then      -- ready to place torch
  4360.                     --go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  4361.                     T:go("C2x0", false, 0, false, R.useBlockType)-- place solid block below
  4362.                     T:go("F1R2x0")
  4363.                     T:place("torch", 0, "forward")              -- place torch, move forward
  4364.                     T:turnRight(2)                              -- turn round
  4365.                     placeSlab = false
  4366.                 end
  4367.             end
  4368.             if placeSlab then
  4369.                 T:dig("up")
  4370.                 if not T:place("slab", 0, "down") then          -- break if out of slabs
  4371.                     break
  4372.                 end
  4373.                 if i < R.length then
  4374.                     T:forward(1)                                -- move forward
  4375.                 end
  4376.             end
  4377.         end
  4378.     end
  4379.    
  4380.     function lib.iceCanalTowpath(R)
  4381.         -- move forward placing slabs along the way. If existing water canal, ceiling will be raised by 1 block
  4382.         local torchInterval = 0
  4383.         local placeIce = true
  4384.         for i = 1, R.length do
  4385.             local addTorch = false
  4386.             if R.torchInterval > 0 then
  4387.                 if i == 1 then addTorch = true end
  4388.                 if torchInterval >= R.torchInterval then
  4389.                     addTorch = true
  4390.                     torchInterval = 0
  4391.                 end
  4392.             end
  4393.             lib.iceCanalEdge(R, addTorch, i, placeIce)
  4394.             torchInterval = torchInterval + 1
  4395.             placeIce = not placeIce
  4396.         end
  4397.         T:go(oTurn.."1")
  4398.     end
  4399.    
  4400.     function lib.iceCanalEdge(R, addTorch, numBlocks, placeIce)
  4401.         -- starting position facing canal side
  4402.         local blockType = T:getBlockType("forward")         -- ? air / slab / other
  4403.         local isWater, isSource, isIce = T:isWater("down")  -- water / ice below
  4404.         if blockType:find("slab") == nil then               -- add slab
  4405.             if addTorch then                                -- check if torch needed
  4406.                 -- T:place(blockType, damageNo, direction, leaveExisting, signText)
  4407.                 if not T:place("stone", -1, "forward", false) then
  4408.                     T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
  4409.                 end
  4410.                 T:go("U1x1 U1x1 D1")                    -- water level to 2 above water level
  4411.                 if T:getItemSlot("minecraft:torch", -1) > 0 then
  4412.                     T:place("torch", -1, "forward", false)
  4413.                 end
  4414.                 T:down(1)                               -- back to above water level
  4415.                 if not isIce then                       -- break block below if NOT ice
  4416.                     T:dig("down")
  4417.                 end
  4418.             else
  4419.                 if not T:place("slab", -1, "forward", false) then
  4420.                     T:checkInventoryForItem({"slab"}, {R.length - numBlocks}, true)
  4421.                 end
  4422.                 if not isSource then                    -- NOT on water, so dig above
  4423.                     T:go("U1x1 U1x1 D2")
  4424.                 end
  4425.                 if not isIce and not isSource then
  4426.                     T:dig("down")
  4427.                 end
  4428.             end
  4429.         else -- slab already on side
  4430.             if addTorch then                            -- check if torch needed
  4431.                 T:dig("forward")
  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.             end
  4444.         end
  4445.         if R.data == "ice" and placeIce and not isIce then -- R.data = "ice", placeIce = true, not already ice present
  4446.             T:place("ice", -1, "down", true)
  4447.         end
  4448.         if numBlocks < R.length then
  4449.             T:go(oTurn.."1F1"..R.side.."1")
  4450.         end
  4451.     end
  4452.    
  4453.     function lib.convertIcepath(length)
  4454.         -- use only for placing ice to convert a water canal
  4455.         -- place ice on alternate blocks until length reached or run out of ice
  4456.         local placeIce = true
  4457.         for i = 1, length do
  4458.             if T:getBlockType("down"):find("ice") == nil then -- no ice below
  4459.                 T:dig("down") -- remove any existing block
  4460.                 if placeIce then
  4461.                     if not T:place("ice", -1, "down", true) then -- out of ice
  4462.                         break
  4463.                     end
  4464.                     if i == length - 1 then
  4465.                         break
  4466.                     end
  4467.                 end
  4468.             else -- ice already below
  4469.                 placeIce = true
  4470.             end
  4471.             T:go("U1x0 D1F1")
  4472.             placeIce = not placeIce -- reverse action
  4473.         end
  4474.     end
  4475.    
  4476.     function lib.convertToAir(length)
  4477.         -- use only for converting a water canal. start at ground level
  4478.         -- dig up/down/forward to clear space
  4479.         for i = 1, length + 1 do
  4480.             T:go("U1x0D1")
  4481.             if i < length + 1 then
  4482.                 T:go("x2F1")
  4483.             else
  4484.                 T:dig("down")
  4485.             end
  4486.         end
  4487.     end
  4488.    
  4489.     function lib.initialise(R)
  4490.         if R.subChoice == 1 or R.subChoice == 4 then       
  4491.             local blockType = T:getBlockType("down")        -- ? at ground/water level or on top of existing slab
  4492.             if blockType:find("slab") ~= nil then           -- slab already present
  4493.                 T:go(oTurn.."1F1D1"..R.side.."2")           -- move right/left forward, down onto ice canal top, face canal wall
  4494.             elseif blockType:find("torch") ~= nil then
  4495.                 T:go(oTurn.."1F1D2"..R.side.."2")           -- move right/left forward, down onto ice canal top, face canal wall
  4496.             else                                            -- assume on ground / water level
  4497.                 T:go(oTurn.."1F1"..R.side.."2")             -- move right/left forward onto ice canal top, face canal wall
  4498.             end
  4499.         else
  4500.             if T:isWater("forward") then                    -- player put turtle inside canal water
  4501.                 T:up(1)
  4502.             end
  4503.             T:go(R.side.."1")                               -- face canal wall
  4504.         end
  4505.     end
  4506.    
  4507.     if R.length == 0 then R.length = 1024 end
  4508.  
  4509.     if R.subChoice <= 4  then                               -- towpath 1,2,3,4
  4510.         lib.initialise(R)                                   -- reposition
  4511.         lib.iceCanalTowpath(R)                              -- build towpath
  4512.     elseif R.subChoice == 5 or R.subChoice == 8 then        -- assume placed on towpath
  4513.         if T:getBlockType("down"):find("slab") ~= nil then  -- slab already present
  4514.             T:go("F1")
  4515.         else
  4516.             T:up(1)
  4517.         end
  4518.         lib.convertTowpath(R)
  4519.     elseif R.subChoice == 6 or R.subChoice == 7 then   
  4520.         if R.data == "ice" then                         -- assume placed on existing ice or initial ice position
  4521.             lib.convertIcepath(R.length)-- place ice
  4522.         else                                            -- assume placed on empty path
  4523.             lib.convertToAir(R.length)                  -- clear 3 high area
  4524.         end
  4525.     end
  4526.    
  4527.     return {}
  4528. end
  4529.  
  4530. local function createLadder(R) -- 12
  4531.     -- createLadder(R.data ="bedrock", R.height = 70, R.depth = -48)
  4532.     -- go(path, useTorch, torchInterval, leaveExisting)
  4533.     -- place(blockType, damageNo, direction, leaveExisting)
  4534.     local lib = {}
  4535.    
  4536.     function lib.placeLadder(direction, ledge, i, height)
  4537.         -- 1 check both sides and behind
  4538.         local fluid = false
  4539.         local block = T:isWaterOrLava("forward", ledge)
  4540.         if block:find("water") ~= nil or block:find("lava") ~= nil then
  4541.             --[[ surround 2 block shaft with blocks ]]
  4542.             T:go("R1C1 R1C1 R1C1 R1F1 L1C1 R1C1 R1C1 R1C1F1 R2C1 x1")
  4543.         else
  4544.             --[[ no water/lava so prepare ladder site]]
  4545.             T:go("F1 L1C1 R1C1 R1C1 L1B1", false, 0, true)
  4546.         end
  4547.         if not T:place("ladder", -1, "forward", false) then
  4548.             T:checkInventoryForItem({"ladder"}, {height - i}, false)
  4549.         end
  4550.         -- 3 check if ledge, torch
  4551.         if ledge == 0 and i > 1 then -- place block above unless new ladder
  4552.             T:place("common", -1, direction, false) -- any common block
  4553.         elseif ledge == 1 then
  4554.             T:place("minecraft:torch", -1, direction, false)
  4555.         elseif ledge == 2 then
  4556.             ledge = -1
  4557.         end
  4558.        
  4559.         return ledge
  4560.     end
  4561.    
  4562.     local retValue = {}
  4563.     local ledge = 0
  4564.     local height = math.abs(R.depth - R.height) --height of ladder
  4565.     local blockType = T:getBlockType("forward")
  4566.     if R.up then -- create ladder from current level to height specified
  4567.         for i = 1, height do -- go up, place ladder as you go
  4568.             ledge = lib.placeLadder("down", ledge, i, height) -- ladder placed forward, stone ledge for torch placed down
  4569.             if i <  height then
  4570.                 T:up(1)
  4571.                 ledge = ledge + 1
  4572.             end
  4573.         end    
  4574.     else -- R.down = true: ladder towards bedrock      
  4575.         local success = true
  4576.         local numBlocks, errorMsg = 0, ""
  4577.         T:down(1)
  4578.         for i = 1, height do -- go down, place ladder as you go
  4579.             ledge = lib.placeLadder("up", ledge, i, heigt) -- ladder placed forward, stone torch placed up
  4580.             --success, blocksMoved, errorMsg, blockType = clsTurtle.down(self, steps, getBlockType)
  4581.             if i < height then
  4582.                 success, numBlocks, errorMsg, blockType = T:down(1, true) -- true = return blockType
  4583.                 ledge = ledge + 1
  4584.             end
  4585.             -- if looking for stronghold then check for stone_bricks
  4586.             if blockType:find("stone_bricks") ~= nil then
  4587.                 table.insert(retValue, "Stronghold discovered")
  4588.                 break -- stop descent at stronghold
  4589.             end
  4590.         end
  4591.         -- if user requested shelter create chamber at this level
  4592.         if R.data == "chamber" then -- user has chosen to build a chamber
  4593.             table.insert(retValue, "Shelter constucted at level".. R.depth)
  4594.             if blockType:find("bedrock") ~= nil then
  4595.                 T:findBedrockTop(0) -- test to check if on safe level immediately above tallest bedrock
  4596.             end
  4597.             -- In shaft, facing start direction, on lowest safe level
  4598.             -- create a square space round shaft base, end facing original shaft, 1 space back
  4599.             T:go("L1n1 R1n3 R1n2 R1n3 R1n1", false, 0, true)
  4600.             T:go("U1Q1 R1Q3 R1Q2 R1Q3 R1Q1 R1D1", false, 0, true)
  4601.         end
  4602.     end
  4603.    
  4604.     return retValue
  4605. end
  4606.  
  4607. local function createLadderToWater(R) -- 86
  4608.     -- go down to water/lava with alternaate solid/open layers
  4609.     -- create a working area at the base
  4610.     -- Return to surface facing towards player placing ladders
  4611.     local inAir = true
  4612.     local numBlocks, errorMsg = 0, ""
  4613.     local height = 2
  4614.     local blockType = T:getBlockType("down")
  4615.     if blockType ~= "" then -- not over air
  4616.         T:forward(1)
  4617.     end
  4618.     T:go("R2D1") -- face player, go down 2
  4619.     while inAir do --success = false when hits water/lava
  4620.         blockType = T:isWaterOrLava("down")
  4621.         if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
  4622.             inAir = false
  4623.         end
  4624.         T:go("C1R1 C1R2 C1R1", false, 0, false) -- surround front  and sides with cobble
  4625.         if inAir then
  4626.             T:down(1)
  4627.             height = height + 1
  4628.         end
  4629.         T:place("ladder", 0, "up")
  4630.     end
  4631.     -- In shaft, facing opposite start direction, on water/lava, ladders above
  4632.     T:go("C2", false, 0, false)
  4633.     utils.goBack(1)
  4634.     T:place("ladder", 0, "forward")
  4635.     T:up(3)
  4636.     height = height - 3
  4637.     for i = 1, height do
  4638.         if i < height then
  4639.             T:go("C2U1", false, 0, false)
  4640.         else
  4641.             T:go("C2", false, 0, false)
  4642.         end
  4643.     end
  4644.  
  4645.     return {}
  4646. end
  4647.  
  4648. local function createMine() -- 11
  4649.     -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  4650.     T:clear()  
  4651.     T:go("m32U1R2M16", true, 8, true) -- mine ground level, go up, reverse and mine ceiling to mid-point
  4652.     T:go("U2D2") -- create space for chest
  4653.     T:place("minecraft:chest", -1, "up", false)
  4654.     T:emptyTrash("up")
  4655.     T:go("D1R1m16U1R2M16", true, 8, true) -- mine floor/ceiling of right side branch
  4656.     T:emptyTrash("up")
  4657.     T:go("D1m16U1R2M16", true, 8, true) -- mine floor/ceiling of left side branch
  4658.     T:emptyTrash("up")
  4659.     T:go("L1M15F1R1D1", true, 8, true) -- mine ceiling of entry corridor, turn right
  4660.     T:go("F1x0 F1x0 n14 R1n32 R1n32 R1n32 R1n14 F1x0 F1U1", true, 8, true)-- mine floor of 36 x 36 square corridor
  4661.     T:go("R1F16R2") --return to centre
  4662.     T:emptyTrash("up")
  4663.     T:go("F16R1") --return to entry shaft
  4664.     T:go("F2Q14R1Q32R1Q32R1Q32R1Q14F2R1", true, 8, true) --mine ceiling of 36x36 square corridor. return to entry shaft + 1
  4665.     T:go("F16R2") --return to centre
  4666.     T:emptyTrash("up")
  4667.     -- get rid of any remaining torches
  4668.     while T:getItemSlot("minecraft:torch", -1) > 0 do
  4669.         turtle.select(T:getItemSlot("minecraft:torch", -1))
  4670.         turtle.dropUp()
  4671.     end
  4672.     T:go("F16R1F1R1") --return to shaft + 1
  4673.     for i = 1, 8 do
  4674.         T:go("N32L1F1L1", true, 8, true)
  4675.         T:go("N16L1F"..(i * 2).."R2", true, 8, true)
  4676.         T:emptyTrash("up")
  4677.         if i < 8 then
  4678.             T:go("F"..(i * 2).."L1N16R1F1R1", true, 8, true)
  4679.         else
  4680.             T:go("F"..(i * 2).."L1N16L1", true, 8, true)
  4681.         end
  4682.     end
  4683.     T:go("F17L1") -- close gap in wall, return to ladder + 1
  4684.     for i = 1, 8 do
  4685.         T:go("N32R1F1R1", true, 8, true)
  4686.         T:go("N16R1F"..(i * 2).."R2", true, 8, true)
  4687.         T:emptyTrash("up")
  4688.         if i < 8 then
  4689.             T:go("F"..(i * 2).."R1N16L1F1L1", true, 8, true)
  4690.         else
  4691.             T:go("F"..(i * 2).."R1N16R1", true, 8, true)
  4692.         end
  4693.     end
  4694.     T:go("F16R1")
  4695.     T:clear()
  4696.     return{"Mining operation complete"}
  4697. end
  4698.  
  4699. local function createMobFarmCube(R) -- 61, 62
  4700.     --[[
  4701.     Part 1 / 3 Mob Spawner Farm
  4702.     blaze = true: blaze spawner in nether
  4703.         R.subChoice is set to:
  4704.         1 = on top of spawner
  4705.         2 = line of sight
  4706.         3 = room below
  4707.     blaze = false: overworld mob spawner
  4708.         R.subChoice is set to:
  4709.         1 = on top of spawner
  4710.         2 = bottom left corner
  4711.         3 = top left corner
  4712.         4 = bottom right, corner
  4713.         5 = top right corner
  4714.         R.width / R.length set by player (external size)
  4715.     ]]
  4716.     local blaze = true
  4717.     if R.data == "spawner" or R.data == "chest" then
  4718.         blaze = false
  4719.     end
  4720.     local continue = false
  4721.     if R.data == "restart" then
  4722.         continue = true
  4723.     end
  4724.     R.direction = "clock"       -- starting on right side
  4725.     if not blaze then
  4726.         print("R.width: "..tostring(R.width))
  4727.         R.width = R.width - 2       -- internal width
  4728.         R.length = R.length - 2     -- internal length
  4729.        
  4730.         if R.subChoice == 2 or R.subChoice == 3 then
  4731.             R.direction = "anticlock"
  4732.         end
  4733.     end
  4734.     -- R.data allows for 2-part operation "blaze" = main cube, "restart" = killzone
  4735.     T:clear()
  4736.     local lib = {}
  4737.    
  4738.     function lib.floorSection(length)
  4739.         for i = 1, length do        -- starts on top left corner
  4740.             T:go("C2")
  4741.             if i < length then
  4742.                 T:forward(1)
  4743.             else
  4744.                 T:go("R1F1")
  4745.             end
  4746.         end
  4747.     end
  4748.    
  4749.     function lib.wallSection(blaze)
  4750.         blaze = blaze or false
  4751.         for i = 1, 4 do
  4752.             for j = 1, 11 do
  4753.                 if blaze then
  4754.                     T:place("slab", 0, "up", false)
  4755.                     T:go("C2", false, 0, false)
  4756.                 else
  4757.                     T:go("C0C2", false, 0, false)
  4758.                 end
  4759.                 if j < 11 then
  4760.                     T:forward(1)
  4761.                     T:go("R2C1L2", false, 0, false)
  4762.                 else
  4763.                     T:turnRight(1)
  4764.                 end
  4765.             end
  4766.         end
  4767.     end
  4768.    
  4769.     function lib.ceiling(blaze)
  4770.         -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  4771.         -- all outer walls complete, now for remaining 9x9 ceiling
  4772.         blaze = blaze or false
  4773.         for i = 1, 9 do
  4774.             for j = 1, 9 do
  4775.                 if blaze then
  4776.                     T:place("slab", 0, "up", false)
  4777.                     T:dig("down")
  4778.                 else
  4779.                     T:go("C0x2", false, 0, true)
  4780.                 end
  4781.                 if j < 9 then
  4782.                     T:forward(1)
  4783.                 else    -- end of length
  4784.                     local place = false
  4785.                     if i%2 == 1 then -- odd numbers 1,3,5,7,9
  4786.                         if i < 9 then
  4787.                             place = true
  4788.                             T:go("R1F1 R1")
  4789.                         end
  4790.                     else
  4791.                         place = true
  4792.                         T:go("L1F1 L1")
  4793.                     end
  4794.                     if place then
  4795.                         if blaze then
  4796.                             T:place("slab", 0, "up", false)
  4797.                             T:dig("down")
  4798.                         else
  4799.                             T:go("C0x2", false, 0, true)
  4800.                         end
  4801.                     end
  4802.                 end
  4803.             end
  4804.         end
  4805.     end
  4806.    
  4807.     function lib.clearWall(length)
  4808.         for i = 1, 4 do
  4809.             for j = 1, length do
  4810.                 if j < length then
  4811.                     T:go("x0x2F1")
  4812.                 else
  4813.                     T:go("x0x2R1")
  4814.                 end
  4815.             end
  4816.         end
  4817.     end
  4818.    
  4819.     function lib.isSpawner()
  4820.         local blockType = T:getBlockType("down")
  4821.         if blockType:find("spawner") ~= nil then
  4822.             return true, "top"
  4823.         end
  4824.         blockType = T:getBlockType("up")
  4825.         if blockType:find("spawner") ~= nil then
  4826.             return true, "bottom"
  4827.         end
  4828.         blockType = T:getBlockType("forward")
  4829.         if blockType:find("spawner") ~= nil then
  4830.             return true, "forward"
  4831.         end
  4832.         return false, ""
  4833.     end
  4834.    
  4835.     function lib.placeFloor(width, length, blockType)
  4836.         -- T:place(blockType, damageNo, direction, leaveExisting, signText)
  4837.         for i = 1, width do            
  4838.             for j = 1, length do
  4839.                 T:place(blockType, -1, "down", false)
  4840.                 if j < length then
  4841.                     T:forward(1)
  4842.                 else
  4843.                     if i%2 == 1 then -- odd numbers 1,3,5,7,9
  4844.                         if i < width then
  4845.                             T:go("R1F1R1", false, 0, true)
  4846.                         end
  4847.                     else
  4848.                         T:go("L1F1L1", false, 0, true)
  4849.                     end
  4850.                 end
  4851.             end
  4852.         end
  4853.     end
  4854.    
  4855.     function lib.searchStrip(distance)
  4856.         --go forward until hit either a wall or a chest
  4857.         local blocks = 1
  4858.         print("Searching strip, distance = "..distance)
  4859.         while blocks < distance do --max travel is external width/length
  4860.             if turtle.forward() then
  4861.                 blocks = blocks + 1
  4862.             else
  4863.                 print("Checking for chest")
  4864.                 if lib.isChest("forward") then
  4865.                     if turtle.forward() then
  4866.                         blocks = blocks + 1
  4867.                     end
  4868.                 else
  4869.                     break
  4870.                 end
  4871.             end
  4872.         end
  4873.     end
  4874.    
  4875.     function lib.findChests(R)
  4876.         for i = 1, 4 do
  4877.             print("Searching wall "..i)
  4878.             if i == 1 or i == 3 then
  4879.                 lib.searchStrip(R.width)    -- find and empty chests along width
  4880.             else
  4881.                 lib.searchStrip(R.length)   -- find and empty chests along length
  4882.             end
  4883.             if R.direction == "clock" then
  4884.                 T:turnRight(1)
  4885.             else
  4886.                 T:turnLeft(1)
  4887.             end
  4888.         end
  4889.  
  4890.         -- checked all walls
  4891.         T:go("F".. math.floor(R.width / 2)) -- now at mid-dungeon, next to wall
  4892.         if T:getItemSlot("chest") > 0 then
  4893.             if R.direction == "clock" then
  4894.                 T:turnLeft(1)
  4895.             else
  4896.                 T:turnRight(1)
  4897.             end
  4898.             -- now at mid-dungeon, facing wall
  4899.             -- deposit chest outside the dungeon
  4900.             while turtle.back() do end -- backing spawner
  4901.             T:go("x0 F1x0 F1x0 F1x0 F1x0 F1x0 F1x0 x1x2")
  4902.             -- place(self, blockType, damageNo, direction, leaveExisting, signText)
  4903.             T:place("chest", -1, "forward", false)
  4904.             -- empty out all except stone and slab
  4905.             T:emptyInventorySelection("forward", {"cobble", "tuff", "slab", "granite", "andesite", "diorite" }, {0,0,0,0,0,0})
  4906.             T:turnLeft(2)
  4907.             T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements")
  4908.             while turtle.forward() do end -- facing spawner
  4909.         else
  4910.             if R.direction == "clock" then
  4911.                 T:turnRight(1)
  4912.             else
  4913.                 T:turnLeft(1)
  4914.             end
  4915.         end -- now at mid-dungeon, facing spawner
  4916.     end
  4917.    
  4918.     function lib.enterDungeon(R)
  4919.         --[[ find and empty any chests, return to dungeon wall ]]
  4920.         print("Entering dungeon")
  4921.         local blockType = T:getBlockType("forward")
  4922.         if blockType == "" then -- nothing in front.Error
  4923.             return false, "No block in front: Check position."
  4924.         else -- attempt entry into dungeon wall
  4925.             if R.subChoice == 2 then        -- bottom left
  4926.                 T:go("R1F1 L1U2 F2R1")
  4927.             elseif R.subChoice == 3 then    -- top left
  4928.                 T:go("R1F1 L1D1 F2R1")
  4929.             elseif R.subChoice == 4 then    -- bottom right
  4930.                 T:go("L1F1 R1U2 F2L1")
  4931.             elseif R.subChoice == 5 then    -- top right
  4932.                 T:go("L1F1 R1D1 F2L1")
  4933.             end
  4934.             while turtle.down() do end -- either on floor or chest
  4935.             if lib.isChest("down") then
  4936.                 turtle.down()
  4937.             end
  4938.             print("Searching for chests")
  4939.             lib.findChests(R)   -- go round inside walls  emptying chests. Finish mid-wall
  4940.         end
  4941.         return true, ""-- success, message
  4942.     end
  4943.    
  4944.     function lib.isChest(direction)
  4945.         direction = direction or "forward"
  4946.         local blockType = T:getBlockType(direction)
  4947.         if blockType:find("chest") ~= nil then -- chest found. early stages so empty and break it
  4948.             print("Chest found")
  4949.             while T:suck(direction) do end
  4950.             T:dig(direction, false) -- false prevents checking for chests
  4951.             return true
  4952.         elseif blockType:find("torch") ~= nil then
  4953.             print("Torch found")
  4954.             T:dig(direction, false) -- false prevents checking for chests
  4955.             return true
  4956.         end
  4957.         return false
  4958.     end
  4959.        
  4960.     function lib.findSpawner(blaze)
  4961.         local moves  = 0
  4962.         local quit = false
  4963.         -- assume turtle placed on centre of inside spawner wall in front of spawner
  4964.         -- or as close as possible in Nether
  4965.         print("Checking if next to spawner")
  4966.         local found, position = lib.isSpawner() -- true/false, top/bottom/nil
  4967.         if not found then -- move forward towards spawner
  4968.             print("Not close to spawner")
  4969.             while turtle.forward() and not quit do
  4970.                 moves = moves + 1
  4971.                 if moves > 16 then
  4972.                     quit = true
  4973.                 end
  4974.             end
  4975.             found, position = lib.isSpawner() -- true/false, top/bottom/nil
  4976.             if not found then
  4977.                 if blaze then -- could be behind a wall
  4978.                     print("Assuming blaze spawner behind a wall")
  4979.                     T:forward(1)
  4980.                     moves = moves + 1
  4981.                     while turtle.forward() and not quit do
  4982.                         moves = moves + 1
  4983.                         if moves > 16 then
  4984.                             quit = true
  4985.                         end
  4986.                     end
  4987.                     found, position = lib.isSpawner() -- true/false, top/bottom/nil
  4988.                     if not found then
  4989.                         T:go("R2F"..moves + 2 .."R2")
  4990.                     end
  4991.                 end
  4992.             end
  4993.         end
  4994.        
  4995.         return found, position
  4996.     end
  4997.    
  4998.    
  4999.     if not continue then -- new mob cube either dungeon or blaze
  5000.         -- clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
  5001.         -- determine spawner position level 4, move to top of spawner (level 6)
  5002.         print("Checking if already at spawner")
  5003.         local found, position = lib.isSpawner() -- already on spawner?
  5004.         if blaze then
  5005.             if not found then -- away from spawner
  5006.                 if R.subChoice == 3 then
  5007.                     T:go("U5")
  5008.                 end
  5009.                 found, position = lib.findSpawner(blaze)
  5010.             end
  5011.         else -- go to bottom of dungeon and empty chests
  5012.             if not found then --outside dungeon
  5013.                 local success, message = lib.enterDungeon(R)
  5014.                 if not success then
  5015.                     return {message}
  5016.                 end
  5017.                 found, position = lib.findSpawner(blaze) -- is spawner in front / above / below?
  5018.             end
  5019.         end
  5020.        
  5021.         if found then -- true: move to correct starting position
  5022.             --[[
  5023.             1 |c|c|c|c|c|c|c|c|c|c|c|
  5024.             2 |w| | | | | | | | | |w|
  5025.             3 |w| | | | | | | | | |w|
  5026.             4 |w| | | | | | | | | |w|
  5027.             5 |w| | | | | | | | | |w|
  5028.             6 |w| | | | |s| | | | |w|
  5029.             7 |w| | | | | | | | | |w|
  5030.             8 |w| | | | | | | | | |w|
  5031.             9 |w| | | | | | | | | |w|
  5032.            10 |w| | | | | | | | | |w| exit level for overworld
  5033.            11 |f|f|f|f|f|f|f|f|f|f|f|
  5034.            12 |f|f|f|f|f|f|f|f|f|f|f| sub floor for overworld
  5035.                1 2 3 4 5 6 7 8 9 1 1
  5036.                                  0 1
  5037.             ]]
  5038.             -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  5039.             if position == "bottom" then
  5040.                 T:go("B1U2F1")
  5041.             elseif position == "forward" then
  5042.                 T:go("U1F1")
  5043.             end
  5044.            
  5045.             T:up(1)
  5046.             T:place("slab", -1, "down", true)               -- place slab on top T:place(blockType, damageNo, direction, leaveExisting)
  5047.             -- go up 2 blocks, forward 5, right, forward 5, right
  5048.             T:go("U2F5 R1F5 R1")                            -- Level 2: now placed 1 below ceiling inside wall, top right corner of new dungeon
  5049.             lib.wallSection(blaze)                          -- fix layers 1, 2, 3 including ceiling margin turtle at Level 2           
  5050.             T:go("F1R2 C1L1 F1R2 C1R1", false, 0, false)    -- exit wall, repair behind, still Level 2
  5051.             lib.ceiling(blaze)                              -- fix ceiling, end opposite corner to start
  5052.             T:go("R2D3")                                    -- clear the inner walls inside original dungeon
  5053.             lib.clearWall(9)                                -- clear the 9 x 9 area around the spawner
  5054.             T:go("F1R1F1L1")
  5055.             lib.clearWall(7)                                -- clear the 7 x 7 area around the spawner
  5056.             T:go("F1R1F1L1")
  5057.             lib.clearWall(5)                                -- clear the 5 x 5 area around the spawner. Also needed for cave spiders
  5058.             T:go("R2F1R1F1R1")
  5059.             T:go("F7R1 F8L1F1R2", false, 0, false)          -- return from ceiling, enter wall below previous section: Level 5
  5060.             lib.wallSection()                               -- deal with areas from spawner level up (4,5,6). walls only   
  5061.             T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8
  5062.             clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 7,8,9
  5063.             T:go("L1F1 L1F1L2", false,