Inksaver

tk.lua toolkit (requires libs):2024/11/22

Apr 20th, 2020 (edited)
4,794
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 529.14 KB | None | 0 0
  1. version = 20241122.1730
  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.21.1
  21. mc 1.18 onwards 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. local barrelItems = nil -- list of items and the barrels where they are usually found
  34. local chestItems = nil  -- list of items and the chests where they are usually found
  35. --[[
  36. Netherite level stand on 14
  37. Chunk borders F3+G or:
  38. math.floor(x / 16) * 16 add 16 for each border. same for z
  39. ]]
  40. function string:split(sSeparator, nMax, bRegexp, noEmpty)
  41.     --[[return a table split with sSeparator. noEmpty removes empty elements
  42.         use: tblSplit = SplitTest:split('~',[nil], [nil], false) or tblSplit = string.split(SplitTest, '~')]]  
  43.     assert(sSeparator ~= '','separator must not be empty string')
  44.     assert(nMax == nil or nMax >= 1, 'nMax must be >= 1 and not nil')
  45.     if noEmpty == nil then noEmpty = true end
  46.  
  47.     local aRecord = {}
  48.     local newRecord = {}
  49.     -- self refers to the 'string' being split
  50.     if self:len() > 0 then
  51.         local bPlain = not bRegexp
  52.         nMax = nMax or -1
  53.  
  54.         local nField, nStart = 1, 1
  55.         local nFirst,nLast = self:find(sSeparator, nStart, bPlain)
  56.         while nFirst and nMax ~= 0 do
  57.             aRecord[nField] = self:sub(nStart, nFirst-1)
  58.             nField = nField+1
  59.             nStart = nLast+1
  60.             nFirst,nLast = self:find(sSeparator, nStart, bPlain)
  61.             nMax = nMax-1
  62.         end
  63.         aRecord[nField] = self:sub(nStart)
  64.        
  65.         if noEmpty then --split on newline preserves empty values
  66.             for i = 1, #aRecord do
  67.                 if aRecord[i] ~= "" then
  68.                     table.insert(newRecord, aRecord[i])
  69.                 end
  70.             end
  71.         else
  72.             newRecord = aRecord
  73.         end
  74.     end
  75.    
  76.     return newRecord
  77. end
  78.  
  79. if tonumber(ccMajorVersion) == nil then -- 1.93.0 NAN
  80.     --ccMajorVersion = ccMajorVersion:sub(1, ccMajorVersion:find(".", 3, true) - 1)
  81.     local parts = ccMajorVersion:split(".")
  82.     ccMajorVersion = parts[1]
  83.     if parts[2] ~= nil then
  84.         ccMajorVersion = ccMajorVersion.."."..parts[2]
  85.     end
  86.     ccMajorVersion = tonumber(ccMajorVersion)
  87.     if parts[3] ~= nil then
  88.         ccMinorVersion = tonumber(parts[3])
  89.     end
  90. end
  91.  
  92. local mcMajorVersion = _HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 1) -- eg 1.18 or 1.20 -> 1.18, 1.20
  93. local mcMinorVersion = 0
  94. if tonumber(mcMajorVersion) == nil then -- 1.18.3 NAN
  95.     --mcMajorVersion = tonumber(_HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 3)) -- eg 1.19.4 -> 1.19
  96.     local parts = mcMajorVersion:split(".")
  97.     mcMajorVersion = parts[1]
  98.     if parts[2] ~= nil then
  99.         mcMajorVersion = mcMajorVersion.."."..parts[2]
  100.     end
  101.     mcMajorVersion = tonumber(mcMajorVersion)
  102.     if parts[3] ~= nil then
  103.         mcMinorVersion = tonumber(parts[3])
  104.     end
  105. end
  106.  
  107. if mcMajorVersion < 1.7  and mcMajorVersion >= 1.18 then -- 1.12 to 1.??
  108.     bedrock = -64
  109.     ceiling = 319
  110. end
  111. if mcMajorVersion < 1.7  and mcMajorVersion >= 1.16 then -- 1.12 to 1.??
  112.     brick = "minecraft:nether_bricks"
  113. end
  114. if mcMajorVersion < 1.7  and mcMajorVersion <= 1.12 then --- turtle in source deletes it. 1.7.10 to 1.12
  115.     deletesWater = true
  116. end
  117.  
  118. local utils = {}
  119. local network = {}
  120.  
  121. function network.addToStorageList(storageType, itemKey, storageName, writeToFile)
  122.     -- itemKey is a table, so is passed byRef. No need to return a value
  123.     -- eg itemKey: [ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96"}
  124.     -- storageName = "minecraft:barrel_99"
  125.     local itemTable = {}
  126.     if storageType == "chest" then
  127.         itemTable = chestItems[itemKey] -- eg [ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96"}
  128.     else
  129.         itemTable = barrelItems[itemKey]
  130.     end
  131.     if itemTable == nil then                -- key does not match. This item not previously stored
  132.         if storageType == "chest" then
  133.             chestItems[itemKey] = {storageName} -- eg U.chestItems[minecraft:diorite] = {chest_105}
  134.         else
  135.             barrelItems[itemKey] = {storageName}
  136.         end
  137.     else
  138.         for _, storage in ipairs(itemTable) do  -- is "minecraft:barrel_99" already in the list?
  139.             if storage == storageName then
  140.                 return  -- exit function
  141.             end
  142.         end
  143.         -- not found so add to table. return not required as funcion is ended
  144.         table.insert(itemTable, storageName)    -- add to table eg table[ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96",, "minecraft:barrel_99"}
  145.     end
  146.     if writeToFile then
  147.         network.updateList(storageType)
  148.     end
  149. end
  150.  
  151. function network.attachModem()
  152.     -- modem cannot be "attached". Has to be player right-click!
  153.     -- place on  top or next to a modem and ask player to right-click
  154.     T:clear()
  155.     menu.colourPrint("Please right-click on the modem(s) I am next to or above/below"..
  156.                     "\nThe centre square should be lit red.\n"..
  157.                     "If embedded use narrow gap at side\n", colors.red)
  158.     local event, side = os.pullEvent("peripheral")
  159.     for timer = 5, 0, -1 do
  160.         -- text, fg, bg, width, isInput, cr
  161.         menu.colourWrite("Thanks. continuing in ".. timer.." seconds", colors.lime, colors.black, 0, false, true)
  162.         sleep(1)
  163.     end
  164. end
  165.  
  166. function network.checkInventory(inventory, itemName, itemsPerSlot, matchPart)
  167.     --[[
  168.     Find an item already in an inventory
  169.     inventory = The wrapped inventory or it's name
  170.     itemName = The name of the item to find.
  171.     return no of items already present, and storage space for additional
  172.     ]]
  173.     itemsPerSlot = itemsPerSlot or 64
  174.     matchPart = matchPart or ""
  175.     local contents = nil
  176.     local numSlots = 0
  177.     if type(inventory) == "string" then
  178.         contents = peripheral.call(inventory, "list")
  179.         numSlots = peripheral.call(inventory, "size")
  180.         --assert(contents ~= nil, "Nil contents from inventory "..tostring(inventory))
  181.         T:saveToLog("network.checkInventory('"..inventory.."', itemName = "..itemName..", itemsPerSlot = "..itemsPerSlot..", matchPart = "..tostring(matchPart))
  182.     else
  183.         contents = inventory.list()
  184.         numSlots = inventory.size()
  185.     end
  186.     local inStock = 0
  187.     local partMatch = false
  188.     local canStore = 0
  189.     if contents ~= nil then
  190.         T:saveToLog("#slots in use = "..#contents)
  191.         canStore = (numSlots - #contents) * itemsPerSlot    -- capacity of empty slots
  192.         for slot, item in pairs(contents) do
  193.             if item.name == itemName then
  194.                 inStock = inStock  + item.count
  195.                 canStore = canStore + itemsPerSlot - item.count
  196.             else
  197.                 if matchPart ~= "" then -- eg check for "cobblestone" or "slab"
  198.                     if item.name:find(matchPart) ~= nil then
  199.                         partMatch = true
  200.                     end
  201.                 end
  202.             end
  203.         end
  204.     end
  205.     T:saveToLog("network.checkInventory return inStock = "..inStock..", canStore = "..canStore..", partMatch = "..tostring(partMatch))
  206.     return inStock, canStore, partMatch -- eg 1, 3647, false if contains only 1 matching item in otherwise empty chest
  207. end
  208.  
  209. function network.emptyInventory(R, barrels, chests, sticksAsFuel)
  210.     --[[network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)]]
  211.     if not T:isEmpty() then
  212.         if sticksAsFuel then
  213.             utils.useSticksAsFuel()
  214.         end
  215.         for _, item in ipairs(barrels) do
  216.             network.sendItemToNetworkStorage(R, "barrel", item, 0)
  217.         end
  218.         for _, item in ipairs(chests) do
  219.             network.sendItemToNetworkStorage(R, "chest", item, 0)
  220.         end
  221.     end
  222. end
  223.  
  224. function network.loadStorageLists()
  225.     local lib = {}
  226.    
  227.     function lib.createList(storageType)
  228.         local storage, turtleName, storageNames = network.wrapModem(R, storageType) -- list of barrel/chest peripherals, name of turtle, names of barrels / chests
  229.         local total = 0
  230.         local locations = {}
  231.         for _, store in pairs(storageNames) do                  -- eg "minecraft:chest_1"
  232.             T:clear()              
  233.             T:saveToLog("Checking "..store.. " contents")       -- eg "checking minecraft:chest_1 contents"
  234.             local contents = peripheral.call(store, "list")     -- list of items / slots for this chest
  235.             for slot, item in pairs(contents) do                -- for each item check if this storage is listed
  236.                 if locations[item.name] == nil then             -- this item not yet found
  237.                     locations[item.name] = {store}              -- add to table eg locations["minecraft:cobblestone"] = {"minecraft:chest_1"}
  238.                 else                                            -- already has at least 1 location
  239.                     network.addToStorageList(storageType, locations[item.name], store, false)
  240.                 end
  241.             end
  242.             total = total + 1
  243.         end
  244.         T:saveToLog("found ".. total.." "..storageType)
  245.         local output = textutils.serialize(locations)       -- serialise to json ready to write to file
  246.         local fileName = storageType.."Items.lua"           -- barrelList.lua or chestList.lua
  247.         local outputHandle = fs.open(fileName, "w")         -- open file
  248.         outputHandle.writeLine("return")                    -- start file with return
  249.         outputHandle.write(output)                          -- add serialised table
  250.         outputHandle.close()                                -- close file
  251.        
  252.         return locations
  253.     end
  254.    
  255.     function lib.listNeedUpdating(storageType, list)
  256.         -- see if named chest/barrel in list is found in fresh peripheral.find
  257.         -- turtle may have moved to a different network
  258.         -- list = eg [ "minecraft:stick" ] = {"minecraft:barrel_91","minecraft:barrel_114"}
  259.         local rawStorage = {peripheral.find(storageType)}
  260.         if not utils.isTableEmpty(rawStorage) then      -- chests / barrels are attached see if they match
  261.             for item, storeList in pairs(list) do       -- existing storage names can be found here
  262.                 local found = false
  263.                 for key, value in ipairs(rawStorage) do -- look in the fresh list of storage names to see if there are missing entries
  264.                     local name = peripheral.getName(value)             
  265.                     for _, storageName in ipairs(storeList) do  -- check each storage name found
  266.                         if storageName == name then     -- recorded name matches, check next one
  267.                             found = true
  268.                             break
  269.                         end
  270.                     end
  271.                     if found then break end
  272.                 end
  273.                 if not found then
  274.                     -- no match in existing list for this storage: list needs updating
  275.                     return true-- list does not match
  276.                 end
  277.             end
  278.         end
  279.         return false    -- list is ok
  280.     end
  281.    
  282.     local _, turtleName, storageNames = network.wrapModem(R, "chest")   -- _, name of turtle, list of names of storage
  283.     if turtleName == "Modem not found" then return turtleName end
  284.     local redo = false
  285.     if barrelItems == nil then  -- not yet loaded
  286.         T:saveToLog("barrelItems == nil")
  287.         if fs.exists("barrelItems.lua") then
  288.             T:saveToLog("require('barrelItems')")
  289.             barrelItems = require("barrelItems")    -- global variable
  290.             redo = lib.listNeedUpdating("barrel", barrelItems)
  291.         else
  292.             T:saveToLog("lib.createList('barrel'")
  293.             barrelItems = lib.createList("barrel")
  294.         end
  295.     end
  296.     if chestItems == nil then   -- not yet loaded
  297.         T:saveToLog("chestItems == nil")
  298.         if fs.exists("chestItems.lua") then
  299.             T:saveToLog("require('chestItems')")
  300.             chestItems = require("chestItems")  -- global variable
  301.             redo = lib.listNeedUpdating("chest", barrelItems)
  302.         else
  303.             T:saveToLog("lib.createList('chest'")
  304.             chestItems = lib.createList("chest")
  305.         end
  306.     end
  307.     if redo then
  308.         barrelItems = lib.createList("barrel")
  309.         chestItems = lib.createList("chest")
  310.     end
  311. end
  312.  
  313. function network.findEmptySlot(list, size)
  314.     --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
  315.     Find the first empty slot in a chest.
  316.     list = list of items in the chest/barrel/dropper
  317.     size = The size of the inventory
  318.     return integer? slot The slot number of the first empty slot, or nil if none are empty.
  319.     ]]
  320.     for slot = 1, size do
  321.         if not list[slot] then
  322.             return slot
  323.         end
  324.     end
  325.    
  326.     return nil
  327. end
  328.  
  329. function network.findItemCountInInventory(list, itemName, exactMatch)
  330.     --[[
  331.     Find an item in an inventory
  332.     list = The list of items in the inventory
  333.     itemName = The name of the item to find.
  334.     return integer? The slot number of the item, or nil if not found.
  335.     ]]
  336.     exactMatch = exactMatch or false
  337.     if type(list) == "string" then
  338.         list = peripheral.call(list, "list")
  339.     end
  340.     local retValue = nil
  341.     local count = 0
  342.     for slot, item in pairs(list) do
  343.         local found = false
  344.         if exactMatch then
  345.             if item.name == itemName then found = true end
  346.         else
  347.             if item.name:find(itemName) ~= nil then found = true end
  348.         end
  349.         if found then
  350.             if retValue == nil then
  351.                 retValue = {}
  352.             end
  353.             table.insert(retValue,{slot, item.count}) -- eg {1, 64}
  354.             count = count + item.count
  355.         end
  356.     end
  357.     return count, retValue -- either nil or eg {{1, 64},{4, 22}}
  358. end
  359.  
  360. function network.findItemInInventory(inventory, itemName, exactMatch)
  361.     --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
  362.     Find an item in an inventory
  363.     inventory = name of inventory or wrapped peripheral
  364.     itemName = The name of the item to find.
  365.     return integer?, integer? The slot number and count of the item, or nil if not found.
  366.     ]]
  367.     exactMatch = exactMatch or false
  368.     if type(inventory) == "string" then
  369.         T:saveToLog("network.findItemInInventory("..inventory..", "..itemName..", exactMatch = "..tostring(exactMatch)..")", true)
  370.         contents = peripheral.call(inventory, "list")
  371.     else    -- should be supplied with .list() already
  372.         T:saveToLog("network.findItemInInventory(<inventory>, "..itemName..", exactMatch = "..tostring(exactMatch)..")", true)
  373.         contents = inventory
  374.     end
  375.     --T:saveToLog("contents = "..table.concat(contents, ", "))
  376.     --utils.writeTraceTable("contents = ", contents)
  377.     if contents ~= nil then
  378.         for slot, item in pairs(contents) do
  379.             --T:saveToLog("item.name = "..item.name..", item.count = "..item.count)
  380.             if exactMatch then
  381.                 if item.name == itemName then
  382.                     T:saveToLog("Item found in "..slot..", quantity = "..item.count)
  383.                     return slot, item.count
  384.                 end
  385.             else
  386.                 if (item.name):find(itemName) ~= nil then
  387.                     T:saveToLog("Matching Item found in "..slot..", quantity = "..item.count)
  388.                     return slot, item.count
  389.                 end
  390.             end
  391.         end
  392.     end
  393.     T:saveToLog("Item not found")
  394.     return 0,0
  395. end
  396.  
  397. function network.getItemFromNetwork(storageType, itemRequired, countRequired, toTurtleSlot, ignoreStock)
  398.     local lib = {}
  399.    
  400.     function lib.getItem(storageTable, turtleName, itemRequired, countRequired, toTurtleSlot, sent)
  401.         local exit = false
  402.         for k, storageName in pairs(storageTable) do    -- eg {"minecraft:barrel_17", "minecraft:barrel_18"...}
  403.             local available, data = network.findItemCountInInventory(storageName, itemRequired, false)      -- either nil or eg {{1, 64},{4, 22}}
  404.             T:saveToLog("network.findItemCountInInventory("..storageName..", "..itemRequired..", false")
  405.             if data ~= nil then
  406.                 for i = 1, #data do
  407.                     local request = countRequired
  408.                     if countRequired > 64 then
  409.                         request = 64
  410.                     end
  411.                     local received = network.sendItemsToTurtle(turtleName, storageName, data[i][1], request, toTurtleSlot)  -- request items, returns number sent
  412.                     if received == nil then received = 0 end
  413.                     sent = sent + received
  414.                     T:saveToLog("received = "..received..", request = "..request.." from "..storageName..", sent = "..sent)
  415.                     if sent >= countRequired then
  416.                         exit = true
  417.                         break
  418.                     end         -- job done, no need to check remaining slots
  419.                     countRequired = countRequired - sent            -- this line not reached if sent >= count
  420.                 end
  421.             end
  422.             --if sent >= countRequired then break end               -- no need to check other storage
  423.             --if countRequired <= 0 then break end
  424.             if exit then
  425.                 return sent, countRequired
  426.             end
  427.         end
  428.        
  429.         return sent, countRequired
  430.     end
  431.    
  432.     -- eg slot, count = network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
  433.     -- storageType either "chest" or "barrel"
  434.     if countRequired == nil then return 0,0 end
  435.     --if toTurtleSlot not specified then nil = use any slot
  436.     ignoreStock = ignoreStock or false  -- return only no of items obtained from storage
  437.     T:saveToLog("network.getItemFromNetwork(storageType = "..storageType..", itemRequired = ".. itemRequired..
  438.                 ", countRequired = ".. countRequired..", toTurtleSlot = "..tostring(toTurtleSlot)..", ignoreStock = "..tostring(ignoreStock))
  439.     -- Must be next to a modem: MUST remove crafting table if modem on that side. Other tools ok
  440.     local sent = 0
  441.     local turtleSlot, turtleCount = T:getItemSlot(itemRequired) -- check local stock
  442.     if not ignoreStock then -- take account of existing items and reduce count accordingly
  443.         countRequired = countRequired - turtleCount
  444.     end
  445.     local savedItems = nil
  446.     if storageType == "barrel" then
  447.         savedItems = barrelItems
  448.     elseif storageType == "chest" then
  449.         savedItems = chestItems
  450.     end
  451.     local storage, turtleName, storageNames = network.wrapModem(R, storageType) -- list of chest/barrel peripherals, name of turtle, list of storage names
  452.     --if turtleName == "Modem not found" then return 0, nil, nil, turtleName end
  453.     if countRequired > 0 then                       -- not enough in stock, or ignore current stock
  454.         -- check if item in storageLists
  455.         local testStores = nil
  456.         if savedItems[itemRequired] ~= nil then -- only works with full item names
  457.             T:saveToLog("savedItems key in list: "..textutils.serialise(savedItems[itemRequired], {compact = true}))
  458.             testStores = savedItems[itemRequired]
  459.         else
  460.             for key, value in pairs(savedItems) do
  461.                 if key:find(itemRequired)~= nil then
  462.                     T:saveToLog("savedItems found in list: "..textutils.serialise(value, {compact = true}))
  463.                     testStores = value
  464.                     break
  465.                 end
  466.             end
  467.         end
  468.         if testStores == nil then   -- no match in storage lists
  469.             T:saveToLog("Unable to find recorded storage, using all "..storageType.."s")
  470.             sent, countRequired = lib.getItem(storageNames, turtleName, itemRequired, countRequired, toTurtleSlot, sent)
  471.         else -- match found, list of storage availble -- eg {"minecraft:barrel_17", "minecraft:barrel_18"...}
  472.             T:saveToLog("Using recorded list alias 'testStores'")
  473.             sent, countRequired = lib.getItem(testStores, turtleName, itemRequired, countRequired, toTurtleSlot, sent)
  474.         end
  475.     end
  476.         -- slotData.lastSlot, total, slotData -- integer, integer, table
  477.     local data = {}
  478.     turtleSlot, turtleCount, data = T:getItemSlot(itemRequired)
  479.     T:saveToLog("turtleSlot = "..turtleSlot..", turtleCount = "..turtleCount..", sent = "..sent) --..", data = "..textutils.serialise(data))
  480.     if ignoreStock then
  481.         return turtleSlot, sent -- 0 -> count
  482.     else
  483.         return turtleSlot, turtleCount  -- 0 -> count
  484.     end
  485. end
  486.  
  487. function network.getSlotContains(inventoryName, inSlot)
  488.     local list = peripheral.call(inventoryName, "list")
  489.     for slot, item in pairs(list) do
  490.         if inSlot == slot then
  491.             return item.name
  492.         end
  493.     end
  494.     return ""
  495. end
  496.  
  497. function network.moveItem(inventoryName, itemName, toSlot)
  498.     --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
  499.     Move a specific item to specific slot eg 1, moving other items out of the way if needed.
  500.     inventoryName = The name of the chest/barrel/dropper to search.
  501.     itemName = The name of the item to find.
  502.     toSlot optional. default is slot 1
  503.     return boolean success Whether or not the item was successfully moved to toSlot (or already existed there)
  504.     ]]
  505.     toSlot = toSlot or 1
  506.     local list = peripheral.call(inventoryName, "list")
  507.     local size = peripheral.call(inventoryName, "size")
  508.     local slot = network.findItemInInventory(list, itemName)
  509.  
  510.   -- If the item didn't exist, or is already in the first slot, we're done.
  511.     if not slot then
  512.         T:saveToLog("network.moveItem(): Item not found")
  513.         return false
  514.     end
  515.     if slot == toSlot then
  516.         return true
  517.     end
  518.  
  519.     -- If an item is blocking the first slot (we already know it's not the one we want), we need to move it.
  520.     if list[toSlot] then
  521.         T:saveToLog("network.moveItem() Slot "..toSlot.." occupied, moving..")
  522.         local emptySlot = network.findEmptySlot(list, size)
  523.  
  524.         -- If there are no empty slots, we can't move the item.
  525.         if not emptySlot then
  526.             T:saveToLog("network.moveItem(): No empty slots")
  527.             return false
  528.         end
  529.  
  530.         -- Move the item to the first empty slot.
  531.        
  532.         if not network.moveItemStack(inventoryName, toSlot, emptySlot) then
  533.             T:saveToLog("network.moveItem(): Failed to move item to slot " .. emptySlot)
  534.             return false
  535.         end
  536.  
  537.         T:saveToLog("network.moveItem(): Moved item to slot " .. emptySlot)
  538.     end
  539.  
  540.     -- Move the item to slot 1.
  541.     if not network.moveItemStack(inventoryName, slot, toSlot) then
  542.         T:saveToLog("network.moveItem(): Failed to move item to slot "..toSlot)
  543.         return false
  544.     end
  545.  
  546.     T:saveToLog("network.moveItem(): Moved item to slot "..toSlot)
  547.     return true
  548. end
  549.  
  550. function network.moveItemsFromTurtle(turtleName, toInventoryName, fromTurtleSlot, quantity, toSlot)
  551.     --[[
  552.     Move quantity of an item from one inventory to another. Turtles MUST use attachedInventory.pullItems()
  553.     eg network.moveItemsFromTurtle(turtleName, chestName, turtleSlot, turtleCount, nil)
  554.     turtleName:         The name of the turtle (via getLocalName())
  555.     toInventoryName:    The name of the inventory to move items into.
  556.     fromTurtleSlot:     The slot to move from. must be pre-determined for the item required
  557.     quantity:           The amount to transfer (nil for full stack)
  558.     toSlot:             The slot to move to. (nil will use any available slot(s))
  559.     ]]
  560.     return peripheral.call(toInventoryName, "pullItems", turtleName, fromTurtleSlot, quantity, toSlot)
  561. end
  562.  
  563. function network.moveItemStack(inventoryName, fromSlot, toSlot)
  564.     --[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
  565.     Move an item from one slot to another in a given inventory.
  566.     inventoryName The name of the inventory to move items in.
  567.     fromSlot The slot to move from.
  568.     toSlot The slot to move to.
  569.     ]]
  570.     return peripheral.call(inventoryName, "pushItems", inventoryName, fromSlot, nil, toSlot)
  571. end
  572.  
  573. function network.sendItemToNetworkStorage(R, storageType, itemToSend, amountToSend)
  574.     -- used to remove items from turtle inventory
  575.     -- Must be next to a modem: MUST remove crafting table if modem on that side. Other tools ok
  576.     local lib = {}
  577.    
  578.     function lib.sendItem(savedItems, peripheralNames, turtleName, turtleSlot, item, slotCount, itemsPerSlot)
  579.         local storageToUse = ""
  580.         local storageList = lib.getStorageFromList(savedItems, item, slotCount, itemsPerSlot)   -- try from savedList
  581.         if storageList == nil then  -- no match found, but use first one found with network.wrapModem
  582.             T:saveToLog("No storage with matching items found, using first empty chest")
  583.             storageToUse = lib.findEmptyStorage(peripheralNames, item, itemsPerSlot, slotCount)
  584.         else
  585.             T:saveToLog("Storage with matching items found, checking capacity")
  586.             storageToUse  = lib.checkCapacity(storageList, item, slotCount, itemsPerSlot)
  587.             if storageToUse == "" then  -- no capacity in known storage list, so start a new one
  588.                 storageToUse = lib.findEmptyStorage(peripheralNames, item, itemsPerSlot, slotCount)
  589.             end
  590.         end
  591.         --network.moveItemsFromTurtle(turtleName, toInventoryName, fromTurtleSlot, quantity, toSlot)
  592.         T:saveToLog("network.moveItemsFromTurtle(turtleName = "..turtleName..", storageToUse = "..tostring(storageToUse)..", slot = "..tostring(turtleSlot)..", slotCount = "..tostring(slotCount)..")")
  593.         network.moveItemsFromTurtle(turtleName, storageToUse, turtleSlot, slotCount)
  594.     end
  595.    
  596.     function lib.findEmptyStorage(peripheralNames, itemName, itemsPerSlot, itemCount)
  597.         T:saveToLog("lib.findEmptyStorage("..textutils.serialise(peripheralNames,{compact = true})..", itemName = "..itemName.. ", itemsPerSlot = "..itemsPerSlot)
  598.         for store = 1, #peripheralNames do
  599.             inStock, canStore, partMatch = network.checkInventory(peripheralNames[store], itemName, itemsPerSlot, "")
  600.             if canStore > itemCount then
  601.                 return peripheralNames[store]
  602.             end
  603.         end
  604.         return nil
  605.     end
  606.    
  607.     function lib.getStorageFromList(savedItems, item, sendAmount, itemsPerSlot)
  608.         if savedItems[item] == nil then                             -- no record of this item stored
  609.             T:saveToLog("lib.getStorageFromList() "..item.." not found")
  610.             local parts = T:getNames(item)                              -- eg minecraft:jungle_planks = "minecraft", "jungle", "planks"
  611.             for part = #parts, 1, -1 do                                 -- iterate "planks", "jungle", "minecraft"
  612.                 local searchTerm = parts[part]
  613.                 if searchTerm ~= "minecraft" and searchTerm ~= "mysticalagriculture" then
  614.                     for itemName, storageList in pairs(savedItems) do   -- iterate items used as keys eg minecraft:jungle_log matches jungle
  615.                         if itemName:find(searchTerm) ~= nil then        -- partial match eg "sapling" found in "minecraft:oak_sapling"
  616.                             T:saveToLog("lib.getStorageFromList() matched "..searchTerm.." with "..itemName)
  617.                             return storageList                          -- eg {"minecraft:chest_22", "minecraft:chest_23"}
  618.                         end
  619.                     end
  620.                 end
  621.             end
  622.         else
  623.             T:saveToLog("lib.getStorageFromList() ["..item.."] found")
  624.             return savedItems[item] -- list of chests with this item available
  625.         end
  626.         return nil
  627.     end
  628.    
  629.     function lib.checkCapacity(storageList, item, sendAmount, itemsPerSlot)
  630.         -- find a chest/barrel with sufficient capacity from list of storage
  631.         for store = 1, #storageList do
  632.             local inStock, canStore, partMatch = network.checkInventory(storageList[store], item, itemsPerSlot, "")
  633.             if canStore > sendAmount then
  634.                 return storageList[store]
  635.             end
  636.         end
  637.         return ""
  638.     end
  639.    
  640.     amountToSend = amountToSend or 0                        -- 0 = remove all of this item
  641.     local totalSent = 0                                     -- track quantity sent
  642.     local minSend = 0                                       -- minimum amount to send
  643.     if amountToSend > 0 then minSend = amountToSend end     -- update minimum to send
  644.     local _, turtleName, peripheralNames = network.wrapModem(R, storageType)    -- _, name of turtle, list of names of storage
  645.    
  646.     T:saveToLog("network.sendItemToNetworkStorage(R, storageType = '"..storageType.."', itemToSend = '"..itemToSend.."', amountToSend = "..amountToSend..")")
  647.     T:saveToLog("network.wrapModem(R, storageType = "..storageType..", turtleName = "..turtleName..")")
  648.     local savedItems = nil
  649.     if storageType == "barrel" then
  650.         savedItems = barrelItems
  651.     elseif storageType == "chest" then
  652.         savedItems = chestItems
  653.     end
  654.    
  655.     if itemToSend == "all" then -- empty Turtle, so item names not relevant
  656.         T:saveToLog("itemToSend = all")
  657.         repeat
  658.             local item, turtleSlot, slotCount, itemsPerSlot = "", 0, 0, 64
  659.             for slot = 1, 16 do
  660.                 item, slotCount = T:getSlotContains(slot)
  661.                 if slotCount > 0 then
  662.                     turtleSlot = slot
  663.                     T:saveToLog("for slot = 1, 16 do: item = "..item..", slotCount = "..slotCount)
  664.                     itemsPerSlot = utils.getSlotCapacity(slot)  -- most items capacity is 64 per slot
  665.                     T:saveToLog("sending'"..item.."' from slot "..slot..", quantity = "..slotCount)
  666.                     break
  667.                 end
  668.             end
  669.             if turtleSlot > 0 then
  670.                 lib.sendItem(savedItems, peripheralNames, turtleName, turtleSlot, item, slotCount, itemsPerSlot)
  671.             end
  672.         until turtleSlot == 0
  673.         return 0    -- exit function
  674.     else
  675.         local storageToUse  = ""
  676.         repeat  -- until item no longer present in inventory or requested amount has been sent
  677.             local sourceSlot, total, data = T:getItemSlot(itemToSend)   -- which slot and how much of itemToSend is in turtle?
  678.             local slotCount = data.leastCount
  679.             T:saveToLog("T:getItemSlot('"..itemToSend.."' sourceSlot = "..sourceSlot..", total = "..total..")")
  680.             if sourceSlot == 0 then
  681.                 T:saveToLog(itemToSend.." not found in turtle inventory")
  682.                 return 0    -- exit function
  683.             else
  684.                 local itemsPerSlot = utils.getSlotCapacity(sourceSlot)  -- most items capacity is 64 per slot
  685.                 itemToSend = data.leastName                             -- full name of item with lowest itemCount
  686.                 T:saveToLog("network.sendItemToNetworkStorage(R, '"..itemToSend.."', sourceSlot = "..sourceSlot..", slotCount = "..slotCount) --..", data = "..textutils.serialise(data)..")")
  687.                 if sourceSlot > 0 then                                  -- item is present in turtle inventory
  688.                     local newStore = false
  689.                     local sent = 0
  690.                     local storageList = lib.getStorageFromList(savedItems, itemToSend, slotCount, itemsPerSlot)
  691.                     if storageList == nil then
  692.                         T:saveToLog("not found in any storage, finding empty")
  693.                         storageToUse = lib.findEmptyStorage(peripheralNames, itemToSend, itemsPerSlot, total)
  694.                         T:saveToLog("new storage: "..storageToUse.." is available")
  695.                         network.addToStorageList(storageType, itemToSend, storageToUse, true)
  696.                         sent = network.moveItemsFromTurtle(turtleName, storageToUse, sourceSlot, slotCount)
  697.                     else
  698.                         storageToUse  = lib.checkCapacity(storageList, itemToSend, slotCount, itemsPerSlot)
  699.                         if storageToUse == "" then  -- no capacity in known storage list, so start a new one
  700.                             storageToUse = lib.findEmptyStorage(peripheralNames, itemToSend, itemsPerSlot, total)
  701.                             newStore = true
  702.                         end
  703.                         T:saveToLog("sent = network.moveItemsFromTurtle(turtleName = "..turtleName..", storageToUse = "..storageToUse..", sourceSlot = "..sourceSlot..", slotCount = ".. slotCount)
  704.                         sent = network.moveItemsFromTurtle(turtleName, storageToUse, sourceSlot, slotCount)
  705.                     end
  706.                     totalSent = totalSent + sent
  707.                     if minSend > 0 and totalSent >= minSend then
  708.                         return totalSent
  709.                     end
  710.                     if amountToSend > 0 then    -- sending specified amount
  711.                         amountToSend = amountToSend - sent
  712.                     end
  713.                     if newStore then
  714.                         network.addToStorageList(storageType, itemToSend, storageName, true)
  715.                     end
  716.                 end
  717.             end
  718.         until sourceSlot == 0
  719.     end
  720.    
  721.     return totalSent
  722. end
  723.  
  724. function network.sendItemsToCrafter(crafterName, fromInventoryName, fromInventorySlot, quantity, toCrafterSlot)
  725.     --[[
  726.     fromInventoryName:  The name of the inventory to move items from.
  727.     fromInventorySlot:  The slot to move from. must be pre-determined for the item required
  728.     quantity:           The amount to transfer (nil for full stack)
  729.     toCrafterSlot:      The slot to move to. (nil will use any available slot(s))
  730.     ]]
  731.     return peripheral.call(fromInventoryName, "pushItems", crafterName, fromInventorySlot, quantity, toCrafterSlot)
  732. end
  733.  
  734. function network.sendItemsToTurtle(turtleName, fromInventoryName, fromInventorySlot, quantity, toTurtleSlot)
  735.     --network.sendItemsToTurtle(turtleName, storageName, storageSlot, count, toTurtleSlot)
  736.     --[[
  737.     Move quantity of an item from one inventory to another. Turtles MUST use attachedInventory.pushItems()
  738.     eg network.sendItemsToTurtle(turtleName, chestName, chestSlot, chestCount, 16) -- move to slot 16 so must be empty
  739.     fromInventoryName:  The name of the inventory to move items from.
  740.     fromInventorySlot:  The slot to move from. must be pre-determined for the item required
  741.     quantity:           The amount to transfer (nil for full stack)
  742.     toTurtleSlot:       The slot to move to. (nil will use any available slot(s))
  743.     ]]
  744.     return peripheral.call(fromInventoryName, "pushItems", turtleName, fromInventorySlot, quantity, toTurtleSlot)
  745. end
  746.  
  747. function network.transferItem(fromInventoryName, toInventoryName, itemName, quantity, toSlot)
  748.     --[[
  749.     Move a specific number of an item from one inventory to another
  750.     fromInventoryName:  The name of the chest/barrel/dropper to search.
  751.     toInventoryName:    The name of the receiving inventory (chest/barrel/dropper/smelter)
  752.     itemName:           The name of the item to find.
  753.     toSlot:             optional. nil picks any slot
  754.     return:             boolean success Whether or not the item was successfully moved to toSlot (or already existed there)
  755.     ]]
  756.     --T:saveToLog("network.transferItem(from: "..fromInventoryName..", to: "..toInventoryName..", itemName = "..itemName..", quantity = "..tostring(quantity)..", toSlot = "..tostring(toSlot))
  757.     local list = peripheral.call(fromInventoryName, "list")
  758.     local size = peripheral.call(fromInventoryName, "size")
  759.     --T:saveToLog("network.transferItem() size = "..size..", list = \n"..textutils.serialize(list))
  760.     local count, data = network.findItemCountInInventory(list, itemName)    -- either nil or eg {{1, 64},{4, 22}}
  761.     --T:saveToLog("network.transferItem() data = "..textutils.serialize(data, {compact = true}))
  762.     local remaining = quantity          -- eg 22 items needed
  763.  
  764.     if data == nil then -- Item not found
  765.         return quantity -- return amount requested = nothing sent
  766.     end
  767.    
  768.     local fromSlot = 0
  769.     local count = 64
  770.     local available = 0
  771.     for _, v in pairs(data) do  -- eg {1, 64},{2, 64}
  772.         if v[2] < count and v[2] >= quantity then
  773.             fromSlot = v[1]
  774.             count = v[2]
  775.         else
  776.             available = available + v[2]
  777.         end
  778.     end
  779.     if fromSlot > 0 then                        -- now have slot with min required quantity
  780.         T:saveToLog("network.transferItem() from: "..fromInventoryName..", to: "..toInventoryName..", fromSlot: "..fromSlot..", toSlot: "..tostring(toSlot)..", quantity: "..tostring(quantity))
  781.         network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, quantity)
  782.         return 0
  783.     else                                    -- available must be at least 1
  784.         for i = 1, #data do                 -- itreate all slots containg at least 1 item
  785.             fromSlot = data[i][1]           -- eg slot 1
  786.             local send = data[i][2]         -- eg 10 items
  787.             if remaining - send < 0 then    -- eg 22 - 10 = 12
  788.                 send = remaining
  789.                 remaining = 0
  790.             else
  791.                 remaining = remaining - send-- eg remaining = 22 - 10 = 12
  792.             end
  793.             network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, send)
  794.             if remaining <= 0 then          -- all required items transferred
  795.                 return 0
  796.             end
  797.         end
  798.     end
  799.    
  800.     return remaining                        -- return remaining items to be found from a  different inventory
  801. end
  802.  
  803. function network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, quantity)
  804.     --[[
  805.     Move quantity of an item from one inventory to another
  806.     fromInventoryName:  The name of the inventory to move items from.
  807.     toInventoryName:    The name of the inventory to move items into.
  808.     fromSlot:           The slot to move from. must be pre-determined for the item required
  809.     toSlot:             The slot to move to. (nil will use any available slot(s))
  810.     quantity:           The amount to transfer (nil for full stack)
  811.     ]]
  812.     T:saveToLog("network.transferItems(from: "..fromInventoryName..", to: "..toInventoryName..", fromSlot: "..fromSlot..", toSlot: "..tostring(toSlot)..", quantity: "..tostring(quantity)..")")
  813.     return peripheral.call(fromInventoryName, "pushItems", toInventoryName, fromSlot, quantity, toSlot)
  814. end
  815.  
  816. function network.transferItemToTurtle(availableStorage, availableStorageKeys, turtleName, crafterData)
  817.     -- network.transferItemToTurtle(<availableStorage>, data = {{1, 64},{4, 22}}, "crafter_01", <crafterData>)
  818.     -- availableStorage.minecraft:chest_114 = {count = 86, data = {{1, 64},{4, 22}},
  819.     -- availableStorage.minecraft:chest_115 = {count = 1024, data = {{1, 64},{2, 64},{3, 64}, ... }
  820.     -- crafterData = {{2,64}, {4,64}, {6,64}, {8,64}} 64 items in each of 4 slots in the crafter
  821.     -- glitch? in crafter inventory, cannot add sequentially to existing items.
  822.     -- send to turtle slot first, then transfer
  823.     T:saveToLog("network.transferItemToTurtle(availableStorage = "..textutils.serialise(availableStorage, {compact = true})..
  824.                 "\navailableStorageKeys = "..textutils.serialise(availableStorageKeys, {compact = true})..
  825.                 "\n"..turtleName..", crafterData = "..textutils.serialise(crafterData, {compact = true}))
  826.                
  827.     local total = 0
  828.     local numSlots = 0
  829.     local sent = 0
  830.     for _, v in ipairs(crafterData) do                              -- how many items required in total?
  831.         total = total + v[2]                                        -- how many slots does it go in
  832.         numSlots = numSlots + 1
  833.     end
  834.     for _, availableStorageKey in ipairs(availableStorageKeys) do   -- eg {minecraft:chest_114, minecraft:chest_115}
  835.         local storageName = availableStorageKey                     -- eg minecraft:chest_114
  836.         local object = availableStorage[storageName]                -- availableStorage.minecraft:chest_114 = {count = 90, data = {{14,64},{15,26}}
  837.         local storageData = object.data                             -- eg data = {{14,64},{15,26}}
  838.         local storageCount = object.count                           -- eg count = 90
  839.         for _, crafterSlotData in ipairs(crafterData) do            -- eg {{2,22}, {4,22}, {6,22}, {8,22}} -> iteration 1 = {2, 22} iterate crafter slots to be filled
  840.             local toCrafterSlot = crafterSlotData[1]                -- eg slot 2 in turtle
  841.             local amountToSend = crafterSlotData[2]                 -- eg place 22 items in slot 2
  842.             T:saveToLog("storageData = "..textutils.serialise(storageData, {compact = true}))
  843.             T:saveToLog("crafterSlotData = "..textutils.serialise(crafterSlotData, {compact = true}))
  844.             for i = 1, #storageData do                              -- {{14,64},{15,26}}                   
  845.                 local slotData = storageData[i]                     -- {14,64}
  846.                 local availableToSend = slotData[2]                 -- 64
  847.                 local fromStorageSlot = slotData[1]                 -- 14
  848.                 local confirmedSent = 0
  849.                
  850.                 T:saveToLog("i = "..i..", slotData = "..textutils.serialise(slotData, {compact = true}))
  851.                 if availableToSend >= amountToSend then
  852.                     T:saveToLog("availableToSend ("..availableToSend..") >= amountToSend: ("..amountToSend.."), current value of sent = "..sent)
  853.                     T:saveToLog("?confirmedSent = peripheral.call("..storageName..", 'pushItems', "..turtleName..
  854.                                 ", from slot "..fromStorageSlot..", amountToSend = "..
  855.                                 amountToSend..", to turtle slot "..toCrafterSlot)
  856.                     confirmedSent = peripheral.call(storageName, "pushItems", turtleName, fromStorageSlot, amountToSend, toCrafterSlot)
  857.                     sent = sent + confirmedSent
  858.                     T:saveToLog("verified confirmedSent = "..confirmedSent..", sent = "..sent)
  859.                     slotData[2] = slotData[2] - confirmedSent
  860.                     crafterSlotData[2] = 0
  861.                     T:saveToLog("slotData[2] = "..slotData[2]..", crafterSlotData[2] = "..crafterSlotData[2])
  862.                 else
  863.                     T:saveToLog("availableToSend ("..availableToSend..") < amountToSend: ("..amountToSend.."), current value of sent = "..sent)
  864.                     T:saveToLog("?confirmedSent = peripheral.call("..storageName..", 'pushItems', "..turtleName..
  865.                                 ", from slot "..fromStorageSlot..", availableToSend = "..
  866.                                 availableToSend..", to turtle slot "..toCrafterSlot)
  867.                     -- taking items from multiple storage slots requires loading into turtle first
  868.                     confirmedSent = peripheral.call(storageName, "pushItems", turtleName, fromStorageSlot, availableToSend, toCrafterSlot)
  869.                     sent = sent + confirmedSent
  870.                     T:saveToLog("verified confirmedSent = "..confirmedSent..", sent = "..sent)
  871.                     amountToSend = amountToSend - confirmedSent
  872.                     slotData[2] = slotData[2] - confirmedSent
  873.                     crafterSlotData[2] = amountToSend
  874.                     T:saveToLog("slotData[2] = "..slotData[2]..", crafterSlotData[2] = "..crafterSlotData[2])
  875.                 end
  876.                
  877.                 if crafterSlotData[2] == 0 then
  878.                     T:saveToLog("crafterSlotData[2]("..crafterSlotData[2]..") == 0: breaking\n")
  879.                     break   -- already sent correct amount
  880.                 end
  881.             end
  882.         end
  883.         if sent >= total then
  884.             T:saveToLog("sent("..sent..") >= total ("..total.."): breaking\n")
  885.             break
  886.         end
  887.     end
  888.  
  889.     return sent
  890. end
  891.  
  892. function network.pullItems(fromName, fromSlot, quantity, toName, toSlot)
  893.     quantity = quantity or 1
  894.     toSlot = toSlot or nil
  895.     if type(fromName) == "table" then           -- already a wrapped peripheral
  896.         fromName = peripheral.getName(fromName)
  897.     end
  898.     if type(toName) == "string" then
  899.         toName = peripheral.wrap(toName)
  900.     end
  901.     toName.pullItems(fromName, fromSlot, quantity, toSlot)
  902. end
  903.  
  904. function network.updateList(storageType)
  905.     local output = ""
  906.     if storageType == "barrel" then
  907.         output = textutils.serialize(barrelItems)       -- serialise to json ready to write to file
  908.     elseif storageType == "chest" then
  909.         output = textutils.serialize(chestItems)        -- serialise to json ready to write to file
  910.     end
  911.     local fileName = storageType.."Items.lua"           -- barrelList.lua or chestList.lua
  912.     local outputHandle = fs.open(fileName, "w")         -- open file
  913.     outputHandle.writeLine("return")                    -- start file with return
  914.     outputHandle.write(output)                          -- add serialised table
  915.     outputHandle.close()                                -- close file
  916. end
  917.  
  918. function network.wrapModem(R, storageType)
  919.     --[[To move turtle inventory items use the target peripheral:
  920.         local modem = peripheral.wrap("front")      -- wrap modem next to turtle (beware crafting table!)
  921.         local turtleName = modem.getNameLocal()     -- get name of the turtle
  922.         local barrel = peripheral.find("barrel")    -- find barrel name you want to receive goods
  923.         barrel.pushItems(turtleName, 1, 1)          -- push items FROM turtle to barrel  pushItems(toName, fromSlot , limit , toSlot)
  924.         barrel.pullItems(turtleName, fromSlot , limit , toSlot)
  925.     ]]
  926.     local modem = peripheral.find("modem")      -- find modem
  927.     if modem == nil then
  928.         return nil, "Modem not found"
  929.     end
  930.     local turtleName = modem.getNameLocal()     -- get name of the turtle
  931.     local rawStorage = nil                      -- peripheral find can return duplicate values
  932.     if storageType:find("barrel") ~= nil then
  933.         rawStorage = {peripheral.find("minecraft:barrel")}
  934.     elseif storageType:find("chest") ~= nil then
  935.         rawStorage = {peripheral.find("minecraft:chest")}
  936.     end
  937.     local storage = {}
  938.     local names = {}
  939.     for k, value in ipairs(rawStorage) do
  940.         local name = peripheral.getName(value)
  941.         if not utils.tableContains(names, name, true) then  -- use exact match as checking peripherals
  942.             table.insert(storage, value)
  943.             table.insert(names, name)
  944.         end
  945.     end
  946.     return storage, turtleName, names
  947. end
  948.  
  949. function utils.assessFarm(R)
  950.     -- sets R.networkFarm and R.mysticalAgriculture
  951.     menu.colourPrint("Assessing farm properties...", colors.yellow)
  952.     --local storage = true
  953.     for turns = 1, 4 do
  954.         T:turnRight(1)
  955.         local itemAhead = T:getBlockType("forward")
  956.         if itemAhead:find("modem") ~= nil then
  957.             if not R.networkFarm then   -- prevents repeated text display
  958.                 R.networkFarm = true
  959.                 menu.colourPrint("Network storage in use.", colors.magenta)
  960.             end
  961.         end
  962.         if itemAhead:find("mysticalagriculture") ~= nil then
  963.             R.mysticalAgriculture = true
  964.             menu.colourPrint("Mystical Agriculture deployed.", colors.lime)
  965.         end
  966.     end
  967.     sleep(1.5)
  968.    
  969.     return R
  970. end
  971.  
  972. function utils.assessTreeFarm(R)
  973.     local lib = {}
  974.        
  975.     function lib.getSaplingType(R, blockType)
  976.         if blockType == "minecraft:mangrove_log" then
  977.             R.logType = "mangrove"
  978.             R.useBlockType ="mangrove_propagule"
  979.         else
  980.             local parts = T:getNames(blockType)
  981.             if parts[2] == "dark" then
  982.                 R.logType = "dark_oak"
  983.                 parts[2] = "dark_oak"
  984.             else
  985.                 R.logType = parts[2]                -- eg "oak"
  986.             end
  987.            
  988.             R.useBlockType = parts[2].."_sapling"   -- eg "oak_sapling"
  989.         end
  990.         utils.goBack(1)
  991.         turtle.turnLeft()
  992.        
  993.         return R
  994.     end
  995.    
  996.     local blockType = T:getBlockType("down")
  997.     if blockType:find("modem") ~= nil then
  998.         R.networkFarm = true
  999.     else
  1000.         if blockType:find("polished") == nil then
  1001.             R.message = "Not on modem or polished. Check position"
  1002.             return R
  1003.         end
  1004.     end
  1005.     if R.networkFarm then
  1006.         T:forward(1)
  1007.         blockType = T:getBlockType("down")
  1008.         T:saveToLog("T:forward(1): blockType = "..blockType)
  1009.         if blockType:find("log") ~= nil then
  1010.             R = lib.getSaplingType(R, blockType)
  1011.         elseif blockType:find("barrel") ~= nil then
  1012.             T:go("R2F2")
  1013.             blockType = T:getBlockType("down")
  1014.             if blockType:find("log") ~= nil then
  1015.                 R = lib.getSaplingType(R, blockType)
  1016.             end
  1017.         else    -- if in correct position water is 2 blocks below
  1018.             if turtle.down() then
  1019.                 blockType = T:getBlockType("down")
  1020.                 if blockType:find("water") == nil then
  1021.                     R.message = "No modem below. Check position"
  1022.                     return R
  1023.                 else
  1024.                     turtle.up()
  1025.                     utils.goBack(1)
  1026.                     T:go("R1F1")
  1027.                     blockType = T:getBlockType("down")
  1028.                     if blockType:find("log") ~= nil then
  1029.                         R = lib.getSaplingType(R, blockType)
  1030.                     else
  1031.                         R.message = "Unable to determine location. Check position"
  1032.                         return R
  1033.                     end
  1034.                 end
  1035.             else
  1036.                 R.message = "Unable to determine location. Check position"
  1037.                 return R
  1038.             end
  1039.         end
  1040.     end
  1041.    
  1042.     return R    -- sets R.networkFarm and R.useBlockType to sapling type
  1043. end
  1044.  
  1045. function utils.calculateDimensions(R)
  1046.     if R.data == "" then -- not being called from other functions
  1047.         if R.width == 0 then -- user chose auto settings
  1048.             R.length = utils.calculateDistance(R.length) -- still facing forward
  1049.             print("Calculated Length = "..R.length)
  1050.             T:turnRight(1) -- ready to check width
  1051.             R.width = utils.calculateDistance(R.width) -- now facing right
  1052.             print("Calculated width = "..R.width)
  1053.             T:go("R2F"..R.width - 1 .."L1".. "F"..R.length - 1 .."R2") -- back at start. width/length confirmed
  1054.         end
  1055.     end
  1056.     if R.height == 0 then -- use auto settings based on water detection
  1057.         R.height = 64
  1058.     end
  1059.     return R
  1060. end
  1061.  
  1062. function utils.calculateDistance(estDistamcMajorVersionnce)
  1063.     --[[
  1064.     measure length
  1065.     movement stops when either solid block in front or solid below
  1066.     called from utils.calculateDimensions
  1067.     ]]
  1068.     local moves = 1
  1069.     local nonSolidBelow = utils.clearVegetation("down")
  1070.     if estDistance == 0 then
  1071.         while nonSolidBelow and turtle.forward() do -- while able to move and air/water below
  1072.             moves = moves + 1
  1073.             nonSolidBelow = utils.clearVegetation("down")
  1074.         end
  1075.     else
  1076.         while moves < estDistance * 2 do -- loop can only run for max of double estimated distance
  1077.             if turtle.forward() then -- able to move forward
  1078.                 moves = moves + 1
  1079.             else
  1080.                 break
  1081.             end
  1082.             if not utils.clearVegetation("down") then -- solid below
  1083.                 turtle.back()
  1084.                 moves = moves - 1
  1085.                 break
  1086.             end
  1087.         end
  1088.     end
  1089.     return moves
  1090. end
  1091.  
  1092. function utils.checkFarmPosition(R)
  1093.     local discovered = ""
  1094.     local success, storage, detected = false, "", 0
  1095.     local blockType = T:getBlockType("down")
  1096.     T:saveToLog("Checking position "..blockType.. " down")
  1097.     if blockType:find("water") ~= nil then -- over water, ? facing E (crops)
  1098.         -- network: E = __modem_, N = _modem__, W = modem___, S = ___modem
  1099.         -- storage: E = _chestchest_, N = chestchest__, W = chest__chest, S = __chestchest
  1100.         -- storage: E = _barrelbarrel_, N = barrelbarrel__, W = barrel__barrel, S = __barrelbarrel
  1101.         T:saveToLog("? over water = true")
  1102.         for i = 1, 4 do
  1103.             success, storage = utils.isStorage("forward")   -- true/false, chest, barrel, modem / ""
  1104.             local itemAhead = T:getBlockType("forward")
  1105.             if success then
  1106.                 discovered = discovered .. storage
  1107.                 if storage == "modem" then
  1108.                     R.networkFarm = true
  1109.                 end
  1110.             else
  1111.                 discovered = discovered .. "_"
  1112.             end
  1113.             if itemAhead:find("mysticalagriculture") ~= nil then
  1114.                 R.mysticalAgriculture = true
  1115.             end
  1116.             T:turnRight(1)
  1117.         end
  1118.         T:saveToLog("Storage blocks found:"..discovered)
  1119.         if R.networkFarm then
  1120.             if discovered == "modemmodem__" then
  1121.                T:turnLeft(1)
  1122.             elseif discovered == "modem__modem" then
  1123.                T:turnLeft(2)
  1124.             elseif discovered == "__modemmodem" then
  1125.                T:turnRight(1)
  1126.             end
  1127.             R.ready = true
  1128.         else
  1129.             if discovered == "barrelbarrel__" or
  1130.                discovered == "barrelchest__" or
  1131.                discovered == "chestchest__" then
  1132.                T:turnLeft(1)
  1133.             elseif discovered == "barrel__barrel" or discovered == "chest__chest" then
  1134.                T:turnLeft(2)
  1135.             elseif discovered == "__barrelbarrel" or discovered == "__chestchest" then
  1136.                T:turnRight(1)
  1137.             end
  1138.             R.ready = true
  1139.         end
  1140.     end -- else not over water
  1141.        
  1142.     T:saveToLog("utils.checkFarmPosition(R) return R = "..textutils.serialise(R, {compact = true}))
  1143.     return R -- now facing crops, R.ready = true/false, R.networkFarm = true/false
  1144. end
  1145.  
  1146. function utils.checkFuelNeeded(quantity)
  1147.     local fuelNeeded = quantity - turtle.getFuelLevel() -- eg 600
  1148.     if fuelNeeded > 0 then
  1149.         if T:checkInventoryForItem({"minecraft:lava_bucket"}, {1}, false) == nil then  
  1150.             if T:checkInventoryForItem({"coal"}, {math.ceil(fuelNeeded / 60)}, false) == nil then
  1151.                 T:checkInventoryForItem({"planks"}, {math.ceil(fuelNeeded / 15)})
  1152.             end
  1153.         end
  1154.         T:refuel(quantity, true)
  1155.     end
  1156. end
  1157.  
  1158. function utils.clearVegetation(direction)
  1159.     local isAirWaterLava = true -- default true value air/water/lava presumed
  1160.     -- blockType, data
  1161.     local blockType = T:getBlockType(direction)
  1162.     if blockType ~= "" then --not air
  1163.         if T:isVegetation(blockType) then
  1164.             T:dig(direction)
  1165.         elseif blockType:find("water") == nil
  1166.                and blockType:find("lava") == nil
  1167.                and blockType:find("bubble") == nil
  1168.                and blockType:find("ice") == nil then
  1169.             -- NOT water, ice or lava
  1170.             isAirWaterLava = false -- solid block
  1171.         end
  1172.     end
  1173.    
  1174.     return isAirWaterLava --clears any grass or sea plants, returns true if air or water, bubble column or ice
  1175. end
  1176.  
  1177. function utils.convertEssence(R)
  1178.     -- R.subChoice = 1 to 5
  1179.     -- R.size = quantity
  1180.     -- 1 = inferium to prudentium
  1181.     -- 2 = prudentium to tertium
  1182.     -- 3 = Tertium to Imperium
  1183.     -- 4 = Imperium to Supremium
  1184.     -- 5 = Supremium to Insanium
  1185.     local lib = {}
  1186.    
  1187.     function lib.getCrystal()
  1188.         local turtleSlot, turtleCount = 0, 0
  1189.         if utils.isStorage("up") then
  1190.             turtle.select(2)
  1191.             turtle.suckUp()
  1192.         end
  1193.         turtleSlot = T:getItemSlot("crystal")
  1194.         if turtleSlot == 0 then
  1195.             turtleSlot, turtleCount = network.getItemFromNetwork("chest", "infusion_crystal", 1)
  1196.         end
  1197.         if turtleSlot > 0 then
  1198.             turtle.select(turtleSlot)
  1199.             turtle.transferTo(2)
  1200.             return true
  1201.         end
  1202.        
  1203.         return false
  1204.     end
  1205.        
  1206.     function lib.loadCrafter(crafterName)
  1207.         -- up to 64 essences stored in turtle slots 2, 4, 6, 8
  1208.         local slots = {2, 4, 6, 8}
  1209.         for _, slot in ipairs(slots) do     -- drop each slot contents into crafter ? slot 1
  1210.             turtle.select(slot)
  1211.             turtle.drop()
  1212.             peripheral.call(crafterName, "pushItems", crafterName, 1, nil, slot)    -- move to correct place
  1213.         end
  1214.     end
  1215.    
  1216.     function lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
  1217.         -- collect essence as above and place in minecraft:crafter slots 2, 4, 6, 8
  1218.         local crafterData = {{2, loaded}, {4, loaded}, {6, loaded}, {8, loaded}} -- eg 64 items in each of 4 slots in the crafter
  1219.         network.transferItemToTurtle(availableStorage, availableStorageKeys, turtleName, crafterData)
  1220.     end
  1221.        
  1222.     function lib.runCrafter(crafterName, count)
  1223.         -- can only craft once, then crystal + output is returned to turtle
  1224.         -- repeat process count times
  1225.         -- drop crystal into crafter, move to slot 5
  1226.         for i = 1, count do
  1227.             local slot = T:getItemSlot("crystal")
  1228.             if slot > 0 then
  1229.                 turtle.select(slot)
  1230.                 turtle.drop()
  1231.                 network.moveItem(crafterName, "crystal", 5)
  1232.                 for i = 1, 3 do
  1233.                     rs.setAnalogOutput("front",15)
  1234.                     sleep(0.1)
  1235.                     rs.setAnalogOutput("front", 0)
  1236.                 end
  1237.             end
  1238.         end
  1239.         while turtle.suck() do end
  1240.     end
  1241.    
  1242.     function lib.storeCrystal()
  1243.         if utils.isStorage("up") then
  1244.             T:dropItem("crystal", "up")
  1245.         else
  1246.             network.sendItemToNetworkStorage(R, "chest", "crystal", 0)  -- empty turtle to storage chests
  1247.         end
  1248.     end
  1249.    
  1250.     function lib.storeOutput()
  1251.         if utils.isStorage("up") then
  1252.             T:dropItem("crystal", "up")
  1253.         end
  1254.         network.sendItemToNetworkStorage(R, "chest", "all", 0)  -- empty turtle to storage chests
  1255.     end
  1256.    
  1257.     function lib.getStorageData(essence)
  1258.         local _, turtleName, storageNames = network.wrapModem(R, "chests")  -- _, turtleName, list of chest names
  1259.         if turtleName == "Modem not found" then return 0, nil, nil, turtleName end
  1260.         local availableStorage = {}
  1261.         local availableStorageKeys = {}
  1262.         local total = 0
  1263.         for _, storageName in pairs(storageNames) do
  1264.             local storageCount, storageData = network.findItemCountInInventory(storageName, essence)    -- eg 86, {{1, 64},{4, 22}}
  1265.             if storageCount > 0 then        -- eg 86: storage has some items
  1266.                 T:saveToLog("storageCount = "..storageCount)
  1267.                 availableStorage[storageName] = {}
  1268.                 availableStorage[storageName].count = storageCount
  1269.                 availableStorage[storageName].data = storageData
  1270.                 table.insert(availableStorageKeys, storageName)
  1271.                 total = total + storageCount
  1272.             end
  1273.         end
  1274.        
  1275.         return total, availableStorage, availableStorageKeys, turtleName
  1276.         --[[
  1277.             availableStorage.minecraft:chest_114 = {count = 86, data = {{1, 64},{4, 22}},
  1278.             availableStorage.minecraft:chest_115 = {count = 1024, data = {{1, 64},{2, 64},{3, 64}, ... }
  1279.         ]]
  1280.     end
  1281.    
  1282.     local essences = {"mysticalagriculture:inferium_essence",
  1283.                     "mysticalagriculture:prudentium_essence",
  1284.                     "mysticalagriculture:tertium_essence",
  1285.                     "mysticalagriculture:imperium_essence",
  1286.                     "mysticalagriculture:supremium_essence",
  1287.                     "mysticalagriculture:insanium_essence"}
  1288.    
  1289.     local message = network.loadStorageLists()
  1290.     if message ~= nil then return {message} end
  1291.     local essence = essences[R.subChoice]
  1292.     local missing = ""
  1293.     local crafter = peripheral.find("minecraft:crafter")
  1294.     local crafterName = ""
  1295.     local completed = 0
  1296.     if R.size > 0 then
  1297.         R.size = math.floor(R.size / 4) * 4
  1298.         if R.size == 0 then R.size = 4 end
  1299.     end
  1300.     if crafter == nil then
  1301.         return {"No crafter found"}
  1302.     else
  1303.         crafterName = peripheral.getName(crafter)
  1304.         T:saveToLog("utils.convertEssence started using "..essence..", quantity = "..R.size )
  1305.         while turtle.suck() do end                      -- empty crafter
  1306.         lib.storeOutput()   -- empty turtle to storage chests, (except crystal if storage above)
  1307.         if not lib.getCrystal() then
  1308.             return {"Failed: missing infusion crystal"}
  1309.         end
  1310.         lib.storeCrystal()
  1311.         local totalInStorage, availableStorage, availableStorageKeys, turtleName = lib.getStorageData(essence)
  1312.         if totalInStorage < 4 then
  1313.             return {"Only "..totalInStorage.." ".. essence:sub(20).." available"}
  1314.         else
  1315.             -- can only transfer full amount direct to crafter
  1316.             -- if a chest has 32 items in 1 slot and 32 in another Slot
  1317.             -- these have to be sent into the turtle first, dropped into crafter slot 1 and moved to correct position
  1318.             totalInStorage = math.floor(totalInStorage / 4) * 4
  1319.             if R.size == 0 then -- process all
  1320.                 T:saveToLog("initial call lib.loadTurtle("..turtleName..", "..totalInStorage.." essence")
  1321.                 local processed = 0
  1322.                 local loaded = 0
  1323.                
  1324.                 while totalInStorage > 0 do     -- use ALL stored essence
  1325.                     if totalInStorage - 256 > 0 then
  1326.                         loaded = 64
  1327.                     else
  1328.                         loaded = totalInStorage / 4
  1329.                     end
  1330.                     lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
  1331.                     lib.loadCrafter(crafterName)
  1332.                     lib.getCrystal()
  1333.                     processed = processed + loaded
  1334.                     totalInStorage = totalInStorage - loaded * 4
  1335.                     lib.runCrafter(crafterName, loaded)
  1336.                     lib.storeOutput()
  1337.                 end
  1338.             elseif R.size <= 64 then
  1339.                 local loaded = math.min(R.size, totalInStorage) -- process requested or available if less
  1340.                 if loaded > 0 then
  1341.                     lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
  1342.                     lib.loadCrafter(crafterName)
  1343.                     lib.getCrystal()
  1344.                     lib.runCrafter(crafterName, loaded)
  1345.                     lib.storeOutput()
  1346.                 end
  1347.             else    -- amount > 64
  1348.                 local processed = 0
  1349.                 local loaded = 0
  1350.                 while totalInStorage > 0 and processed < R.size do  -- stop if run out of essence, or reached target
  1351.                     if totalInStorage - 256 > 0 and R.size - processed >= 64 then
  1352.                         loaded = 64
  1353.                     elseif totalInStorage - 256 > 0 and R.size - processed > 0 then
  1354.                         loaded = R.size - processed
  1355.                     end
  1356.                     lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
  1357.                     lib.loadCrafter(crafterName)
  1358.                     lib.getCrystal()
  1359.                     processed = processed + loaded
  1360.                     totalInStorage = totalInStorage - loaded * 4
  1361.                     lib.runCrafter(crafterName, loaded)
  1362.                     lib.storeOutput()
  1363.                 end
  1364.             end
  1365.             lib.storeOutput()
  1366.         end
  1367.         return {"success"}
  1368.     end
  1369. end
  1370.  
  1371. function utils.craftItem(R)
  1372.     local message = network.loadStorageLists()  -- initialises or creates lists of where an item can be found: GLOBAL LISTS!
  1373.     if message ~= nil then return {message} end
  1374.     T:saveToLog("call network.emptyInventory(R, {'sapling', 'propagule', 'dirt', 'crafting'}, {'all'}, true)")
  1375.     network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)  -- 2 lists, one for barrels, one for chests
  1376.     T:saveToLog("\ncall network.getItemFromNetwork('barrel', 'minecraft:dirt', 169)")
  1377.     --network.getItemFromNetwork(storageType, itemRequired, countRequired, toTurtleSlot, ignoreStock)
  1378.     local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 169, nil, false)
  1379.     T:saveToLog("Get from barrel completed: turtleSlot = "..turtleSlot..", turtleCount = "..turtleCount..", ignoreStock = "..tostring(ignoreStock))
  1380.     if turtleCount < 169 then
  1381.         T:saveToLog("\ncall network.getItemFromNetwork('chest', 'minecraft:dirt', ".. 169 - turtleCount..", ignoreStock = "..tostring(ignoreStock)..")")
  1382.         turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 169 - turtleCount, nil, true)
  1383.         if turtleCount < 169 then   -- ask player for saplings
  1384.             T:checkInventoryForItem({"dirt"}, {169 - turtleCount})
  1385.         end
  1386.     end
  1387.     return {""}
  1388. end
  1389.  
  1390. function utils.createPath(R) -- 51
  1391.     --[[places a path in air/lava/water. R can also be of type int]]
  1392.     local length = 0
  1393.     local reduce = false
  1394.     local torchInterval = 8
  1395.     if type(R) == "table" then
  1396.         length = R.length
  1397.         if R.data == "reduce" then
  1398.             reduce = true
  1399.         end
  1400.         torchInterval = R.torchInterval
  1401.     else
  1402.         length = R
  1403.     end
  1404.     local numBlocks = 0
  1405.    
  1406.     if reduce then
  1407.         T:forward(1)
  1408.         local blockType = T:getBlockType("down")
  1409.         local useBlock = blockType
  1410.         while blockType == useBlock do
  1411.             T:go("x2F1")
  1412.             numBlocks = numBlocks + 1
  1413.             blockType = T:getBlockType("down")
  1414.         end
  1415.         utils.goBack(numBlocks + 1)
  1416.     else
  1417.         for i = 1, 2 do
  1418.             T:fillVoid("down", {}, false)
  1419.             T:forward(1)
  1420.             numBlocks = numBlocks + 1
  1421.         end
  1422.         local place = utils.clearVegetation("down")
  1423.         while place do -- while air, water, normal ice, bubble column or lava below
  1424.             if T:fillVoid("down", {}, false) then -- false if out of blocks
  1425.                 T:forward(1)
  1426.                 numBlocks = numBlocks + 1
  1427.                 if numBlocks % torchInterval == 1 or numBlocks == 0 then
  1428.                     if T:getItemSlot("minecraft:torch", -1) > 0 then
  1429.                         T:turnRight(2)
  1430.                         T:place("minecraft:torch", "forward", false)
  1431.                         T:turnRight(2)
  1432.                     end
  1433.                 end
  1434.             else
  1435.                 break
  1436.             end
  1437.             if length > 0 and numBlocks >= length then -- not infinite path (length = 0)
  1438.                 break
  1439.             end
  1440.             place = utils.clearVegetation("down")
  1441.         end
  1442.     end
  1443.     return {numBlocks} -- returned as a table in case called as task 51 back to main()
  1444. end
  1445.  
  1446. function utils.createStorage()
  1447.     -- start in centre, above 1st level
  1448.     T:place("modem", "down")
  1449.     utils.goBack(1)
  1450.    
  1451.     T:place("chest", "down")    -- places with handle at back of turtle
  1452.     T:go("R1F1L1")
  1453.     T:place("chest", "down")    -- 2nd of pair
  1454.     for i = 1, 3 do
  1455.         T:go("F1L1")
  1456.         T:place("chest", "down")
  1457.         T:go("R1F1L1")
  1458.         T:place("chest", "down")
  1459.     end
  1460.    
  1461.     T:go("F1L1F1")  -- end at starting position
  1462.     network.attachModem()
  1463. end
  1464.  
  1465. function utils.createWalledSpace(D)
  1466.     --[[
  1467.     D.width  = #
  1468.     D.length = #
  1469.     D.height = #
  1470.     D.ceiling = false
  1471.     D.floor = false
  1472.     D.vDirection = "U" or "D"
  1473.     D.hDirection = "LR" or "RL"
  1474.     D.goHome = true
  1475.     T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  1476.     ]]
  1477.     local turn  = "R1"
  1478.     local oTurn = "L1"
  1479.     if D.hDirection == "RL" then
  1480.         turn    = "L1"
  1481.         oTurn   = "R1"
  1482.     end
  1483.     local placeF = "C1"
  1484.  
  1485.     local lib = {}
  1486.    
  1487.     function lib.getPlace(D, start, finish)
  1488.         if start then                       -- start of build
  1489.             if D.vDirection == "U" then     -- bottom and going up
  1490.                 if D.floor then
  1491.                     return "C2"
  1492.                 end
  1493.             else                            -- D.vDirection == "D"
  1494.                 if D.ceiling then
  1495.                     return "C0"
  1496.                 end
  1497.             end
  1498.         elseif finish then                  -- end of build
  1499.             if D.vDirection == "U" then     -- bottom and going up
  1500.                 if D.ceiling then
  1501.                     return "C0"
  1502.                 end
  1503.             else
  1504.                 if D.floor then
  1505.                     return "C2"
  1506.                 end
  1507.             end
  1508.         end
  1509.  
  1510.         return ""                           -- start and finish both false
  1511.     end
  1512.    
  1513.     function lib.layer(D, start, finish)
  1514.         local outward = true
  1515.         local place = lib.getPlace(D, start, finish)
  1516.         for width = 1, D.width do
  1517.             for length = 1, D.length do
  1518.                 if start or finish then
  1519.                     T:go(place, false, 0, true)-- place floor / ceiling
  1520.                 end
  1521.                 if width == 1 then
  1522.                     T:go(oTurn..placeF..turn, false, 0, true)       -- face wall and check if block
  1523.                 elseif width == D.width then                        -- checking opposite wall
  1524.                     if outward then                                 -- travelling away from start
  1525.                         T:go(turn..placeF..oTurn, false, 0, true)   -- face wall and check if block
  1526.                     else                                            -- travelling towards start
  1527.                         T:go(oTurn..placeF..turn, false, 0, true)   -- face wall and check if block
  1528.                     end                
  1529.                 end
  1530.                 -- move forward
  1531.                 if length < D.length then
  1532.                     T:forward(1)
  1533.                 end
  1534.             end
  1535.             if width < D.width then
  1536.                 -- change direction
  1537.                 if outward then
  1538.                     T:go(placeF..turn.."F1"..oTurn..place..placeF..turn..turn, false, 0, true)
  1539.                 else
  1540.                     T:go(placeF..oTurn.."F1"..turn..place..placeF..oTurn..oTurn, false, 0, true)
  1541.                 end
  1542.                 outward = not outward
  1543.             else
  1544.                 if outward then
  1545.                     T:go(placeF..oTurn.."F"..D.width -1 ..oTurn.."F"..D.length - 1 .."C1R2", false, 0, true)
  1546.                 else
  1547.                     T:go(placeF..turn.."F"..D.width -1 ..oTurn..placeF..turn..turn, false, 0, true)
  1548.                 end
  1549.             end
  1550.         end
  1551.     end
  1552.    
  1553.     T:go("R2"..placeF.."R2", false, 0, true)            -- place block behind
  1554.     for height = 1, D.height do
  1555.         if height == 1 then
  1556.             lib.layer(D, true, false)                   -- first layer, so start = true, finish = false
  1557.         elseif height == D.height then     
  1558.             lib.layer(D, false, true)                   -- final layer, so start = false, finish = true
  1559.         else
  1560.             lib.layer(D, false, false)                  -- mid build layer, so start = false, finish = false
  1561.         end
  1562.         if height < D.height then                       -- go up or down unless finished build
  1563.             T:go(D.vDirection.."1")
  1564.         end
  1565.     end
  1566.     if D.goHome then-- ends at starting point
  1567.         if D.vDirection == "U" then
  1568.             T:down(D.height - 1)
  1569.         else
  1570.             T:up(D.height - 1)
  1571.         end
  1572.     end
  1573. end
  1574.  
  1575. function utils.createWaterSource(level)
  1576.     if level == nil then
  1577.         level = 0
  1578.     end
  1579.     if level > 0 then
  1580.         T:up(level)
  1581.     elseif level < 0 then
  1582.         T:down(math.abs(level))
  1583.     end
  1584.     -- assume on flat surface, but allow for blocks above
  1585.     T:go("x0C2F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2", false, 0, false)
  1586.     T:go("R1F1D1", false, 0, false) --move to corner and drop down
  1587.     T:go("C2F1R1 C2F1R1 C2F1R1 C2F1R1", false, 0, false)
  1588.     T:go("U1")
  1589.     for i = 1, 2 do
  1590.         T:placeWater("down")
  1591.         T:go("F1R1F1R1", false, 0, false)
  1592.     end
  1593.     -- refill water buckets
  1594.     for i = 1, 2 do
  1595.         sleep(0.5)
  1596.         T:placeWater("down")
  1597.     end
  1598.     T:go("R2F1R1F1R1")
  1599.     -- end above lower left of pond (starting point)
  1600.     return {}
  1601. end
  1602.  
  1603. function utils.drainWaterLava(R) -- 84
  1604.     local lib = {}
  1605.        
  1606.     function lib.startCorner()
  1607.         -- assume starting mid 3 high column
  1608.         T:go("D1C1R1C1 U1C1 L1C1 U1C1 R1C1 L1D1 C2C0", false, 0, true)
  1609.         -- finished on same mid 3 high column with wall in front and right completed
  1610.     end
  1611.    
  1612.     function lib.midWall()
  1613.         -- assume starting mid 3 high column
  1614.         T:go("D1R1C1 U1C1 U1C1 L1D1 C2C0", false, 0, true)
  1615.         -- finished on same mid 3 high column with wall on right completed
  1616.     end
  1617.    
  1618.     function lib.endCorner()
  1619.         -- assume starting mid 3 high column
  1620.         T:go("D1R1C1 R1C1 U1C1 L1C1 U1C1 R1C1 L2D1 C2C0", false, 0, true)
  1621.         -- finished on same mid 3 high column with wall behind and right completed
  1622.     end
  1623.    
  1624.     function lib.backTurn(offset)
  1625.         -- assume starting mid 3 high column with completed wall behind
  1626.         T:go("L1F"..offset.."L2C1 R1D1C1 U1C1 U1C1 D1")
  1627.         -- end next row along the width, facing the back, mid point
  1628.         -- wall ahead completed
  1629.     end
  1630.    
  1631.     function lib.frontTurn()
  1632.         -- assume starting mid 3 high column facing back
  1633.         -- next move is to turn toward previous wall and remove
  1634.  
  1635.         T:go("L2D1C1 U1C1 U1C1 D1R1 C2C0 F1R2C1 L1")
  1636.         -- end facing back ready to remove wall
  1637.     end
  1638.    
  1639.     function lib.placeRetainingWall(distance)
  1640.         -- assume starting above 3 block high area facing front (player)
  1641.         --T:down(1)
  1642.         for i = 1, distance do
  1643.             if i == 1 then -- start wall
  1644.                 lib.startCorner()
  1645.             else
  1646.                 if i < distance then -- mid wall
  1647.                     lib.midWall()
  1648.                 else -- end of the wall
  1649.                     lib.endCorner()
  1650.                 end
  1651.             end
  1652.             if i < distance then
  1653.                 if not turtle.back() then
  1654.                     T:go("R2F1R2")
  1655.                 end
  1656.                 T:go("C1", false, 0, true)
  1657.             end
  1658.         end
  1659.         return 1
  1660.     end
  1661.        
  1662.     function lib.placeDam(distance)
  1663.         --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  1664.         local waterPresent = false
  1665.         for i = 1, distance do
  1666.             if T:isWater("down") then
  1667.                 waterPresent = true
  1668.             end
  1669.             T:go("C0C2")
  1670.             if i < distance then
  1671.                 if not turtle.back() then
  1672.                     T:go("R2F1R2")
  1673.                 end
  1674.                 T:go("C1", false, 0, true)
  1675.             end
  1676.         end
  1677.         return waterPresent
  1678.     end
  1679.    
  1680.     function lib.removeDam(distance)
  1681.         -- facing towards back, dig wall up down and ahead
  1682.         for i = 1, distance do
  1683.             T:go("x0x2")
  1684.             if i < distance then
  1685.                 T:forward(1)
  1686.             end
  1687.         end
  1688.         T:turnRight(2)
  1689.         -- end up back to retaining wall, mid point
  1690.     end
  1691.    
  1692.     if R.data == "" then
  1693.         if turtle.detectDown() then -- on solid surface
  1694.             turtle.forward()
  1695.         end
  1696.     end
  1697.     if deletesWater then --turtle replaces source so use clearSolid()
  1698.         R.silent = true
  1699.         R.down = true
  1700.         R.up = false
  1701.         clearSolid(R)
  1702.     else -- mc 1.12.15+ turtle does NOT replace source blocks
  1703.         -- place first stone along the length of water and measure length
  1704.         R = utils.calculateDimensions(R)
  1705.         local depth = 0
  1706.         for h = 1, R.height do
  1707.             local waterPresent = false -- resets at each level
  1708.             local row = 0
  1709.             T:go("R2D2", false, 0, true)    -- at start, level 2, facing towards the front, move backards
  1710.             --lib.startCorner()
  1711.             row = row + lib.placeRetainingWall(R.length)
  1712.             lib.backTurn(1)
  1713.             if lib.placeDam(R.length) then
  1714.                 waterPresent = true
  1715.             end
  1716.             row = row + 1
  1717.             -- left side wall has been built, 2 rows of walls laid. row = 2
  1718.             while row < R.width - 1 do -- eg width=2, row=2, this will not run. width=5, row=2
  1719.                 lib.frontTurn()
  1720.                 lib.removeDam(R.length)
  1721.                 lib.backTurn(2)
  1722.                 if lib.placeDam(R.length) then
  1723.                     waterPresent = true
  1724.                 end
  1725.                 row = row + 1
  1726.             end
  1727.             -- lay right wall
  1728.             lib.frontTurn()
  1729.             lib.removeDam(R.length)
  1730.             lib.backTurn(2)
  1731.             row = row + lib.placeRetainingWall(R.length)
  1732.             lib.frontTurn()
  1733.             lib.removeDam(R.length) -- faces to front on finish
  1734.             T:go("L1F1R1")
  1735.             lib.removeDam(R.length) -- faces to front on finish
  1736.             depth = depth + 3
  1737.             T:go("L1F"..R.width - 1 .."R1D1")
  1738.             if depth == R.height or not waterPresent then -- still replacing water
  1739.                 T:up(depth - 1) -- when h == R.height will go up
  1740.                 break -- in case water dries up before loop has completed
  1741.             end
  1742.         end
  1743.     end
  1744.     return {}
  1745. end
  1746.  
  1747. function utils.dropSand()
  1748.     while not turtle.detectDown() do -- over water. will be infinite loop if out of sand
  1749.         if not T:place("sand", "down", false) then
  1750.             print("Out of sand. Add more to continue...")
  1751.             sleep(2)
  1752.         end
  1753.     end
  1754.     return true --will only get to this point if turtle.detectDown() = true
  1755. end
  1756.  
  1757. function utils.pause(R)
  1758.     --[[
  1759.     allows 2 turtles to co-operate
  1760.     When they face each other and move together
  1761.     R.side = "R" or "L"
  1762.     ]]
  1763.     local rsIn = rs.getAnalogueInput("front")
  1764.     local rsOut = 1
  1765.     local present = false
  1766.     local confirmed = false
  1767.     local timer = 0
  1768.     local endTimer = 0
  1769.     local finished = false
  1770.     T:go(R.side.."1")
  1771.     rs.setAnalogueOutput("front", 0) -- switch off output
  1772.     local blockType = T:getBlockType("forward")
  1773.     while blockType:find("turtle") == nil do
  1774.         menu.colourWrite("Waiting for other turtle "..endTimer, colors.orange, nil, nil, false, true)
  1775.         blockType = T:getBlockType("forward")
  1776.         sleep(0.1)
  1777.         timer = timer + 0.1
  1778.         if timer >= 1 then
  1779.             timer = 0
  1780.             endTimer = endTimer + 1
  1781.         end
  1782.     end
  1783.     timer = 0
  1784.     endTimer = 0
  1785.    
  1786.     while not finished do
  1787.         if endTimer == 0 then
  1788.             if present then
  1789.                 if confirmed then
  1790.                     menu.colourWrite("Turtle confirmed: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
  1791.                 else
  1792.                     menu.colourWrite("Other turtle ok: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
  1793.                 end
  1794.             else
  1795.                 menu.colourWrite("Waiting: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
  1796.             end
  1797.         end
  1798.         sleep(0.1)
  1799.         timer = timer + 1
  1800.         if endTimer > 0 then
  1801.             endTimer = endTimer + 1
  1802.         end
  1803.         if endTimer >= 10 then -- allows time for other computer to get ready
  1804.             finished = true
  1805.         end
  1806.         rs.setAnalogueOutput("front", 1) -- output 1 as a signal initially
  1807.         if present then
  1808.             rs.setAnalogueOutput("front", rsOut) -- output 1 as a signal initially
  1809.         end
  1810.         rsIn = rs.getAnalogueInput("front")
  1811.         if rsIn == 1 then
  1812.             present = true
  1813.             if not confirmed then
  1814.                 rsOut = 7
  1815.             end
  1816.         elseif rsIn == 7 then
  1817.             present = true
  1818.             confirmed = true
  1819.             rsOut = 15
  1820.         elseif rsIn == 15 or confirmed then
  1821.             menu.colourWrite("endTimer active = "..endTimer, colors.orange, nil, nil, false, true)
  1822.             endTimer = endTimer + 1 -- start endTimer
  1823.         end
  1824.     end
  1825.     T:go(R.side.."3")
  1826.    
  1827.     return rsIn -- 15
  1828. end
  1829.  
  1830. function utils.startWaterFunction(inWater, onWater, maxDescent, goIn)
  1831.     --[[
  1832.         Use with utils.getWaterStatus
  1833.         could be inWater and not onWater if on single layer of water with floor below
  1834.     ]]
  1835.     maxDescent = maxDescent or 1 -- prevents continuous down due to lack of water
  1836.     if goIn == nil then -- turtle should submerge
  1837.         goIn = true
  1838.     end
  1839.     local descent = 0 -- counter for going down
  1840.     if inWater then -- job done
  1841.         return inWater, onWater
  1842.     end
  1843.     if onWater and goIn then --inWater already returned so must be false
  1844.         if turtle.down() then
  1845.             if T:getBlockType("forward"):find("water") ~= nil or T:getBlockType("forward"):find("bubble") ~= nil then
  1846.                 inWater = true
  1847.                 return inWater, onWater
  1848.             end
  1849.         end
  1850.     end
  1851.     if not onWater then
  1852.         T:forward(1)
  1853.     end
  1854.     -- should now be above water, but may be further down so onWater still false
  1855.     while T:getBlockType("down"):find("water") == nil and T:getBlockType("down"):find("bubble") == nil do-- go down until water below
  1856.         if turtle.down() then
  1857.             descent = descent + 1
  1858.             if descent >= maxDescent then -- limit descent in case no water present
  1859.                 onWater = false
  1860.                 return inWater, onWater -- false,false
  1861.             end
  1862.         else
  1863.             onWater = false
  1864.             return inWater, onWater -- false,false
  1865.         end
  1866.     end
  1867.     -- now above water
  1868.     if goIn then
  1869.         turtle.down() -- now inside water block
  1870.         inWater = true
  1871.     end
  1872.     return inWater, onWater
  1873. end
  1874.  
  1875. function utils.fillBucket(direction)
  1876.     if T:getWater(direction)  then
  1877.         sleep(0.3)
  1878.         return true
  1879.     else
  1880.         return false
  1881.     end
  1882. end
  1883.  
  1884. function utils.getEmptyBucketCount()
  1885.     local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:bucket")
  1886.     return total
  1887. end
  1888.  
  1889. function utils.getRoofStats(R)
  1890.     local isWidthOdd = R.width % 2 == 1             -- is the width odd or even?
  1891.     local isLengthOdd = R.length % 2 == 1           -- is the length odd or even?
  1892.     if isWidthOdd then
  1893.         R.height = math.floor(R.width / 2)          -- eg 7 x 5 roof, layers = 5 / 2 = 2
  1894.     else
  1895.         R.height = R.width / 2                      -- eg 17 x 8 roof, layers = 8 / 2 = 4
  1896.     end
  1897.    
  1898.     local width = 2                                 -- assume even width with  2 block roof ridge
  1899.     local length = R.length - R.height - 1          -- assume even width with  2 block roof ridge
  1900.     if isWidthOdd then
  1901.         width = 3                                   -- adjust to allow for single width roof ridge
  1902.     end
  1903.     if isLengthOdd then
  1904.         length = R.length - R.height                -- adjust as 1 layer less
  1905.     end
  1906.    
  1907.     return R, isWidthOdd, isLengthOdd, width, length
  1908. end
  1909.  
  1910. function utils.getSlotCapacity(slot)
  1911.     return turtle.getItemSpace(slot) + turtle.getItemCount(slot)
  1912. end
  1913.  
  1914. function utils.getWater()
  1915.     if deletesWater then
  1916.         T:getWater("down") -- take water from source
  1917.         sleep(0.2)
  1918.         T:getWater("down") -- take water from source
  1919.     else
  1920.         if not turtle.detectDown() then
  1921.             T:go("C2", false, 0, false)
  1922.         end
  1923.         T:getWater("forward") -- take water from source
  1924.         sleep(0.2)
  1925.         T:getWater("forward") -- take water from source
  1926.     end
  1927. end
  1928.  
  1929. function utils.getWaterBucketCount()
  1930.     -- lastSlot, leastModifier, total, slotData  = T:getItemSlot(item)
  1931.     local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:water_bucket")
  1932.     return total
  1933. end
  1934.  
  1935. function utils.getWaterStatus()
  1936.     --[[ Usage:
  1937.     local inWater, onWater = utils.getWaterStatus() -- returns turtle position near water
  1938.     utils.startWaterFunction(onWater, inWater, 2, true) -- move INTO water max 2 blocks down
  1939.     utils.startWaterFunction(onWater, inWater, 5, false) -- move ABOVE water max 5 blocks down
  1940.     ]]
  1941.     local onWater = false
  1942.     local inWater = false
  1943.     for i = 1, 4 do
  1944.         if T:getBlockType("forward"):find("water") ~= nil  or T:getBlockType("forward"):find("bubble") ~= nil then
  1945.             inWater = true
  1946.         end
  1947.         T:turnRight(1)
  1948.     end
  1949.     if T:getBlockType("down"):find("water") ~= nil or T:getBlockType("down"):find("bubble") ~= nil then
  1950.         onWater = true
  1951.     end
  1952.     return inWater, onWater
  1953. end
  1954.  
  1955. function utils.goBack(blocks)
  1956.     blocks = blocks or 1
  1957.     local success = true
  1958.     for i = 1, blocks do
  1959.         if not turtle.back() then
  1960.             success = false
  1961.             T:go("R2F1R2")
  1962.         end
  1963.     end
  1964.    
  1965.     return success
  1966. end
  1967.  
  1968. function utils.getPrettyPrint(promptColour, menuPromptColour)
  1969.     promptColour = promptColour or colors.yellow
  1970.     menuPromptColour = menuPromptColour or colors.white
  1971.    
  1972.     local pp = {}
  1973.     pp.prompt = promptColour
  1974.     pp.itemColours = {}
  1975.     pp.menuPrompt = menuPromptColour
  1976.     pp.allowModifier = true -- can the menu return 'q' or 'h' / 'i'
  1977.    
  1978.     return pp
  1979. end
  1980.  
  1981. function utils.isStorage(direction)
  1982.     local blockType = T:getBlockType(direction)
  1983.     if blockType:find("barrel") ~= nil then
  1984.         return true, "barrel"
  1985.     elseif blockType:find("chest") ~= nil then
  1986.         return true, "chest"
  1987.     elseif blockType:find("modem") ~= nil then
  1988.         return true, "modem"
  1989.     end
  1990.    
  1991.     return false, blockType
  1992. end
  1993.  
  1994. function utils.isTableEmpty(aTable)
  1995.     if next(aTable) == nil then
  1996.         return true
  1997.     end
  1998.     return false
  1999. end
  2000.  
  2001. function utils.move(R, blocks, reverse)
  2002.     if blocks == 0 then return 0 end
  2003.     if reverse == nil then
  2004.         reverse = false
  2005.     end
  2006.     if reverse then
  2007.         --if R.subChoice == 2 then -- reverse direction
  2008.         if R.direction == "down" or R.subChoice == 2 then -- reverse direction
  2009.             T:up(blocks)
  2010.         else
  2011.             T:down(blocks)
  2012.         end
  2013.         return blocks * -1
  2014.     else
  2015.         --if R.subChoice == 1 then
  2016.         if R.direction == "up" or R.subChoice == 1 then
  2017.             T:up(blocks)
  2018.         else
  2019.             T:down(blocks)
  2020.         end
  2021.         return blocks
  2022.     end
  2023. end
  2024.  
  2025. function utils.printR(R)
  2026.     --[[
  2027.         choice = 0,
  2028.         subChoice = 0,
  2029.         size = 0,
  2030.         width = 0,
  2031.         length = 0,
  2032.         height = 0,
  2033.         depth = 0,
  2034.         up = false,
  2035.         down = false,
  2036.         silent = false,
  2037.         data = {},
  2038.         torchInterval = 0,
  2039.         useBlockType = "",
  2040.         auto = false,
  2041.         side = "",
  2042.         direction = "",
  2043.         ready = false,
  2044.         networkFarm = false,
  2045.         mysticalAgriculture = false,
  2046.         logType = "",
  2047.         treeSize = "",
  2048.         message = ""
  2049.     ]]
  2050.     T:clear()
  2051.     print("choice= ".. tostring(R.choice)..", subChoice= ".. tostring(R.subChoice))
  2052.     print("size= ".. tostring(R.size)..", width= ".. tostring(R.width))
  2053.     print("length= ".. tostring(R.length)..", height= ".. tostring(R.height)..", depth= ".. tostring(R.depth))
  2054.     print("silent= "..tostring(R.silent)..", up= ".. tostring(R.up)..", down= "..tostring(R.down))
  2055.     print("torchInterval= ".. tostring(R.torchInterval))
  2056.     print("useBlockType= "..tostring(R.useBlockType))
  2057.     print("auto= ".. tostring(R.auto)..", side= "..tostring(R.side)..", direction= "..tostring(R.direction))
  2058.     print("ready= ".. tostring(R.ready)..", networkFarm= "..tostring(R.networkFarm)..", mysticalAgriculture= "..tostring(R.mysticalAgriculture))
  2059.     print("logType= ".. tostring(R.logType)..", treeSize= "..tostring(R.treeSize)..", message= "..tostring(R.message))
  2060.     if type(R.data) == "table" then
  2061.         io.write("data= ")
  2062.         for k,v in pairs(R.data) do
  2063.             print(k ..": "..tostring(v))
  2064.         end
  2065.     else
  2066.         print("data= ".. tostring(R.data))
  2067.     end
  2068.     io.write("Enter to continue")
  2069.     read()
  2070. end
  2071.  
  2072. function utils.setStorageOptions()
  2073.     local storage = ""
  2074.     local storageBackup = ""
  2075.     if T:getItemSlot("barrel") > 0 then
  2076.         storage = "barrel"
  2077.         storageBackup = "barrel"
  2078.     end
  2079.     if T:getItemSlot("chest") > 0 then
  2080.         if storage == "" then
  2081.             storage = "chest"
  2082.         end
  2083.         storageBackup = "chest"
  2084.     end
  2085.     return storage, storageBackup
  2086. end
  2087.  
  2088. function utils.tableConcat(tbl, sep)
  2089.     local output = ""
  2090.     for i,value in pairs(tbl) do
  2091.         output = output .. tostring(value)
  2092.         if i ~= #tbl then
  2093.             output = output .. sep
  2094.         end
  2095.     end
  2096.  
  2097.     return output
  2098. end
  2099.  
  2100. function utils.tableContains(tableName, value, exactMatch)
  2101.     exactMatch = exactMatch or false
  2102.     for k, v in ipairs(tableName) do
  2103.         if exactMatch then
  2104.             if v == value then
  2105.                 return true
  2106.             end
  2107.         else
  2108.             if v:find(value) ~= nil then
  2109.                 return true
  2110.             end
  2111.         end
  2112.     end
  2113.     return false
  2114. end
  2115.  
  2116. function utils.useSticksAsFuel()
  2117.     local slot = T:getItemSlot("minecraft:stick")
  2118.     if slot > 0 then -- use any sticks to refuel
  2119.         turtle.select(slot)
  2120.         turtle.refuel()
  2121.     end
  2122.     slot = T:getItemSlot("minecraft:mangrove_roots")
  2123.     if slot > 0 then -- use any roots to refuel
  2124.         turtle.select(slot)
  2125.         turtle.refuel()
  2126.     end
  2127. end
  2128.  
  2129. function utils.waitForInput(message)
  2130.     -- debugging. Pause script and asks user to continue
  2131.     -- global dbug flag has to be set first
  2132.     if dbug then
  2133.         if message ~= nil then
  2134.             print(message)
  2135.             T:saveToLog(message, false)
  2136.         end
  2137.         menu.colourPrint("Enter to continue...", colors.lightBlue)
  2138.         --io.write("Press Enter to continue...")
  2139.         return read()
  2140.     end
  2141. end
  2142.  
  2143. function utils.writeTraceTable(description, tbl)
  2144.     local text = ""
  2145.     for key, value in pairs(tbl) do
  2146.         if type(value) == "table" then
  2147.             for k,v in pairs(value) do
  2148.                 text = text.."k = "..k..", v = "..v.."; "
  2149.             end
  2150.         else
  2151.             text = "key = "..key..", value = "..value
  2152.         end
  2153.     end
  2154.     T:saveToLog(description.."\n".. text)
  2155. end
  2156.  
  2157. local pp = utils.getPrettyPrint()
  2158.  
  2159. local function buildWall(R)
  2160.     -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  2161.     local lib = {}
  2162.    
  2163.     function lib.singleLayer(R)
  2164.         for l = 1, R.length do
  2165.             if l == R.length and R.data == "house" then
  2166.                 T:turnRight(1)
  2167.             end
  2168.             utils.goBack(1)
  2169.             T:go("C1", false, 0, false, R.useBlockType)
  2170.         end
  2171.     end
  2172.    
  2173.     function lib.doubleLayer(R)
  2174.         for l = 1, R.length do
  2175.             T:go("C2", false, 0, false, R.useBlockType)
  2176.             if l == R.length and R.data == "house" then
  2177.                 T:turnRight(1)
  2178.             end
  2179.             utils.goBack(1)
  2180.             T:go("C1", false, 0, false, R.useBlockType)
  2181.         end
  2182.     end
  2183.    
  2184.     function lib.tripleLayer(R)
  2185.         for l = 1, R.length do
  2186.             T:go("C2C0", false, 0, false, R.useBlockType)
  2187.             if l == R.length and R.data == "house" then
  2188.                 T:turnRight(1)
  2189.             end
  2190.             utils.goBack(1)
  2191.             T:go("C1", false, 0, false, R.useBlockType)
  2192.         end
  2193.     end
  2194.    
  2195.     -- R.width preset to 1
  2196.     local remaining = R.height
  2197.    
  2198.     if R.subChoice == 1 then
  2199.         T:forward(1)            -- face forward, move over first block
  2200.     end
  2201.     if R.height > 1 then
  2202.         T:up(1)                 -- go up 1 block
  2203.     end
  2204.     if R.data ~= "house" then
  2205.         T:turnRight(2)              -- rotate 180
  2206.     end
  2207.     if R.height == 1 then       -- single block: place in front
  2208.         lib.singleLayer(R)
  2209.     elseif R.height == 2 then   -- 2 blocks, go backwards, place below and ahead
  2210.         lib.doubleLayer(R)
  2211.     else
  2212.         while remaining >= 3 do
  2213.             lib.tripleLayer(R)
  2214.             remaining = remaining - 3
  2215.             if remaining == 1 then
  2216.                 T:go("U2F1R2")
  2217.             elseif remaining > 1 then
  2218.                 T:go("U3F1R2")
  2219.             end
  2220.         end
  2221.         if remaining == 1 then
  2222.             lib.singleLayer(R)
  2223.         elseif remaining == 2 then
  2224.             lib.doubleLayer(R)
  2225.         end
  2226.     end
  2227.     if not R.silent then
  2228.         while turtle.down() do end
  2229.     end
  2230.    
  2231.     return {}
  2232. end
  2233.  
  2234. local function buildStructure(R)
  2235.     local lib = {}
  2236.    
  2237.     function lib.goDown(R)
  2238.         --T:go("L1F1 R1F1 L1")  -- now on ground floor
  2239.         if R.height > 1 then
  2240.             T:down(1)
  2241.         end
  2242.     end
  2243.     local buildHeight = R.height
  2244.     local height = R.height
  2245.     local width = R.width
  2246.     local length = R.length
  2247.    
  2248.     if R.subChoice == 1 then
  2249.         T:forward(1)            -- face forward, move over first block
  2250.     end
  2251.     if R.height > 3 then
  2252.         R.height = 3
  2253.     end
  2254.     T:turnRight(2)
  2255.     R.data = "house"
  2256.     R.silent = true -- prevent return to ground after buildWall(R)
  2257.     R.subChoice = 2 -- do not move forward when building walls
  2258.     while height > 0 do
  2259.         buildWall(R)
  2260.        
  2261.         lib.goDown(R)
  2262.         R.length = width - 1
  2263.         buildWall(R)
  2264.         lib.goDown(R)
  2265.        
  2266.         R.length = length - 1
  2267.         buildWall(R)
  2268.         lib.goDown(R)
  2269.        
  2270.         R.length = width - 2
  2271.         buildWall(R)
  2272.         height = height - R.height  -- 1, 2 or 3
  2273.         if height > 0 then
  2274.             T:go("U2 R1F1 L1F1")
  2275.             R.height = height
  2276.             if height > 3 then
  2277.                 R.height = 3
  2278.             end
  2279.             R.length = length
  2280.         end
  2281.     end
  2282.    
  2283.     T:go("U2F2")
  2284.     while turtle.down() do end
  2285.     T:go("R1F1R1")
  2286.    
  2287.     return {}
  2288. end
  2289.  
  2290. local function buildGableRoof(R)
  2291.     --[[
  2292.     stairs placement:
  2293.        _|   up
  2294.      
  2295.        T L  forward
  2296.        _
  2297.         |   down
  2298.  
  2299.     ]]
  2300.     local lib = {}
  2301.    
  2302.     function lib.placeRoof(R, outward)
  2303.         for i = 1, R.length + 2 do
  2304.             if R.useBlockType:find("stairs") ~= nil then
  2305.                 T:place("stairs", "up")
  2306.             else
  2307.                 T:go("C0", false, 0, false, R.useBlockType)
  2308.             end
  2309.             if i < R.length + 2 then
  2310.                 if outward then
  2311.                     T:go("L1F1R1")
  2312.                 else
  2313.                     T:go("R1F1L1")
  2314.                 end
  2315.             end
  2316.         end
  2317.     end
  2318.    
  2319.     function lib.placeGable(R, outward)
  2320.         local width = R.width
  2321.         for h = 1, R.height do
  2322.             for w = 1, width do
  2323.                 T:go("C1")
  2324.                 if w < width then
  2325.                     if outward then
  2326.                         T:go("L1F1R1")
  2327.                     else
  2328.                         T:go("R1F1L1")
  2329.                     end
  2330.                 end
  2331.             end
  2332.             if h < R.height then
  2333.                 if outward then
  2334.                     T:go("R1F1L1U1")
  2335.                 else
  2336.                     T:go("L1F1R1U1")
  2337.                 end
  2338.             end
  2339.             width = width - 2
  2340.             outward = not outward
  2341.         end
  2342.         return outward
  2343.     end
  2344.    
  2345.     local outward = true
  2346.     -- go to centre of end wall if odd no, or half width if even
  2347.     R.height = math.floor(R.width / 2)
  2348.     local isOdd = R.width % 2 == 1
  2349.    
  2350.     utils.goBack(1)
  2351.     T:go("R1F"..R.height - 1 .."U"..R.height - 1)   -- top of roof, under top layer
  2352.     for h = 1, R.height + 1 do                      -- place tiles on left side of roof
  2353.         lib.placeRoof(R, outward)
  2354.         if h < R.height + 1 then
  2355.             utils.goBack(1)
  2356.             T:down(1)
  2357.             outward = not outward
  2358.         end
  2359.     end
  2360.     if isOdd then
  2361.         T:go("F"..R.height + 2 .."R2U"..R.height)
  2362.     else
  2363.         T:go("F"..R.height + 1 .."R2U"..R.height)
  2364.     end
  2365.     for h = 1, R.height + 1 do                      -- place tiles on right side of roof
  2366.         lib.placeRoof(R, outward)
  2367.         if h < R.height + 1 then
  2368.             utils.goBack(1)
  2369.             T:down(1)
  2370.             outward = not outward
  2371.         end
  2372.     end
  2373.     -- gable ends
  2374.     if outward then
  2375.         T:go("F1R1U1")
  2376.     else
  2377.         T:go("F1L1U1")
  2378.     end
  2379.     outward = lib.placeGable(R, outward)
  2380.     T:go("F2R2 C1R2F"..R.length - 1 .."D"..R.height - 1)
  2381.     if outward then
  2382.         T:go("R1F"..R.height - 1 .."R1")
  2383.     else
  2384.         T:go("L1F"..R.height - 1 .."L1")
  2385.     end
  2386.     outward = not outward
  2387.     outward = lib.placeGable(R, outward)
  2388.     if isOdd then
  2389.         if outward then
  2390.             T:go("L1F1R1U2F1")
  2391.         else
  2392.             T:go("R1F1L1U2F1")
  2393.         end
  2394.         for i = 1, R.length do
  2395.             T:go("C2F1", false, 0, false)
  2396.         end
  2397.         for i = 1, R.length + 2 do
  2398.             utils.goBack(1)
  2399.             T:place("slab", "forward")
  2400.         end
  2401.     end
  2402.     while turtle.down() do end
  2403.    
  2404.     return {}
  2405. end
  2406.  
  2407. local function buildPitchedRoof(R)
  2408.     --[[
  2409.     stairs placement:
  2410.        _|   up
  2411.      
  2412.        T L  forward
  2413.        _
  2414.         |   down
  2415.  
  2416.     ]]
  2417.     local lib = {}
  2418.        
  2419.     function lib.placeRoofSection(length)
  2420.         -- starts facing centre of building
  2421.         for i = 1, length do
  2422.             if i < length then
  2423.                 if R.useBlockType:find("stairs") ~= nil then
  2424.                     T:place("stairs", "up")
  2425.                 else
  2426.                     T:go("C0", false, 0, false, R.useBlockType)
  2427.                 end
  2428.                 T:go("L1F1R1")
  2429.             end
  2430.         end
  2431.         -- ends facing centre of building
  2432.     end
  2433.    
  2434.     function lib.placeRoof(R, width, length)
  2435.         lib.placeRoofSection(length)
  2436.         T:go("R1")
  2437.         lib.placeRoofSection(width)
  2438.         T:go("R1")
  2439.         lib.placeRoofSection(length)
  2440.         T:go("R1")
  2441.         lib.placeRoofSection(width)
  2442.     end
  2443.    
  2444.     function lib.placeSlabs(length)
  2445.         -- add slabs at top
  2446.         T:go("U2F1L1")
  2447.         if length > 1 then
  2448.             T:forward(length - 3)
  2449.             for i = 1, length - 3 do
  2450.                 T:place("slab", "forward")
  2451.                 utils.goBack(1)
  2452.             end
  2453.             T:place("slab", "forward")
  2454.         else
  2455.             T:place("slab", "forward")
  2456.         end
  2457.         T:go("D2R1")
  2458.         utils.goBack(1)
  2459.     end
  2460.     --[[
  2461.     Turtle MUST be placed on left corner of shortest dimension
  2462.    
  2463.     ****   or T******
  2464.     ****      *******
  2465.     ****      *******
  2466.     ****
  2467.     T***
  2468.     shortest dimension is R.width
  2469.     if width is odd, ignore top layer as is only 1 block wide
  2470.     ]]
  2471.     local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0
  2472.     R, isWidthOdd, isLengthOdd, width, length = utils.getRoofStats(R)
  2473.     T:go("F"..R.height - 1 .."R1F"..R.height - 1 .."U"..R.height - 1)       -- top of roof, under top layer
  2474.     if isWidthOdd then
  2475.         lib.placeSlabs(length)
  2476.     end
  2477.     for h = 1, R.height + 1 do                      -- place tiles on left side of roof
  2478.         lib.placeRoof(R, width, length)
  2479.         length = length + 2                         -- increase dimensions
  2480.         width = width + 2
  2481.         if h < R.height + 1 then
  2482.             utils.goBack(1)
  2483.             T:go("D1R1")
  2484.             utils.goBack(1)
  2485.         end
  2486.     end
  2487.     while turtle.down() do end
  2488.    
  2489.     return {}
  2490. end
  2491.  
  2492. local function clearAndReplantTrees() -- 25
  2493.     --[[ clear all trees in a rectangle area defined by walls, fences or non-dirt blocks
  2494.     replant with same type of sapling. If original tree 2 blocks wide, replant 4 if possible. ]]
  2495.    
  2496.     local lib = {}
  2497.    
  2498.     function lib.getSaplingFromLogType(log)
  2499.         --[[ get type of sapling to plant from log type ]]
  2500.         if log:find("oak") ~= nil then
  2501.             return "minecraft:oak_sapling"
  2502.         elseif log:find("spruce") ~= nil then
  2503.             return "minecraft:spruce_sapling"
  2504.         elseif log:find("birch") ~= nil then
  2505.             return "minecraft:birch_sapling"
  2506.         elseif log:find("jungle") ~= nil then
  2507.             return "minecraft:jungle_sapling"
  2508.         elseif log:find("acacia") ~= nil then
  2509.             return "minecraft:acacia_sapling"
  2510.         elseif log:find("dark_oak") ~= nil then
  2511.             return "minecraft:dark_oak_sapling"
  2512.         end
  2513.         return "sapling"
  2514.     end
  2515.    
  2516.     function lib.plantSapling(sapling, double)
  2517.         --[[ plant sapling(s) ]]
  2518.         if sapling == "" or sapling == nil then sapling = "sapling" end
  2519.         T:up(1)
  2520.         lib.suck()
  2521.         if double then  -- check if enough saplings
  2522.             --slotData.lastSlot, slotData.leastModifier, total, slotData = T:getItemSlot(sapling, -1)
  2523.             local a, b, total, _ = T:getItemSlot(sapling, -1)
  2524.             if total >= 4 then
  2525.                 for i = 1, 4 do
  2526.                     T:place(sapling, "down")
  2527.                     T:go("F1R1")
  2528.                 end
  2529.                 T:forward(1)        -- above pre-planted sapling
  2530.             else
  2531.                 if not T:place(sapling, "down") then
  2532.                     T:place("sapling", "down")
  2533.                 end
  2534.             end
  2535.         else
  2536.             if not T:place(sapling, "down") then
  2537.                 T:place("sapling", "down")
  2538.             end
  2539.         end
  2540.         turtle.select(1)
  2541.     end
  2542.        
  2543.     function lib.suck()
  2544.         --[[ Collect saplings, sticks and apples ]]
  2545.         turtle.select(1)
  2546.         turtle.suck()
  2547.         turtle.suckUp()
  2548.         turtle.suckDown()
  2549.     end
  2550.    
  2551.     function lib.turn(direction)
  2552.         --[[ change direction and return new value for direction ]]
  2553.         if direction == "r" then
  2554.             T:turnRight(1)
  2555.             direction = "l"
  2556.         else
  2557.             T:turnLeft(1)
  2558.             direction = "r"
  2559.         end
  2560.         return direction    -- will only change direction variable if return value is used
  2561.     end
  2562.    
  2563.     function lib.emptyInventory(blockTypeD)
  2564.         --[[ Empty all except 32 of each sapling and 1 chest ]]
  2565.         if blockTypeD == nil then
  2566.             blockTypeD = T:getBlockType("down")
  2567.         end
  2568.         if blockTypeD:find("chest") ~= nil or blockTypeD:find("barrel") ~= nil then
  2569.             -- empty logs, apples, sticks and all but 1 stack of each sapling type
  2570.             T:emptyInventorySelection("down", {"chest", "oak_sapling", "birch_sapling", "spruce_sapling", "acacia_sapling", "jungle_sapling","dark_oak_sapling"},{1, 32, 32, 32, 32, 32, 32})
  2571.             return true
  2572.         else
  2573.             return false
  2574.         end
  2575.     end
  2576.    
  2577.     function lib.moveDown(blockTypeD)
  2578.         --[[ move down until hit ground. Break leaves and continue ]]
  2579.         if blockTypeD == nil then
  2580.             blockTypeD = T:getBlockType("down")
  2581.         end
  2582.         while blockTypeD == "" or blockTypeD:find("leaves") ~= nil do   -- move down, breaking leavse
  2583.             T:down(1)
  2584.             lib.suck()
  2585.             blockTypeD = T:getBlockType("down")
  2586.         end
  2587.         return blockTypeD
  2588.     end
  2589.    
  2590.     function lib.moveForward()
  2591.         --[[ Move forward 1 block only, go down to ground while air or leaves below ]]
  2592.         local blockTypeF = T:getBlockType("forward")
  2593.         local blockTypeD = T:getBlockType("down")
  2594.         if blockTypeF == "" or blockTypeF:find("leaves") ~= nil then    -- air or leaves ahead
  2595.             T:forward(1)                                                -- move forward, breaking leaves
  2596.             T:dig("up")                                                 -- remove leaves / low branches above to allow space for player
  2597.             lib.suck()
  2598.             blockTypeD = lib.moveDown()
  2599.             if not lib.emptyInventory(blockTypeD) then                  -- check if above a corner chest / barrel
  2600.                 if lib.isBorder(blockTypeD) then                        -- not above chest so check if above border
  2601.                     return false, blockTypeD                            -- above a border block so stop
  2602.                 end
  2603.             end
  2604.             blockTypeF = T:getBlockType("forward")
  2605.             return true, blockTypeF                                     -- moved ok, could be air or block in front
  2606.         end
  2607.         return false, blockTypeF                                        -- did not move, obstacle in front NOT leaves or air
  2608.     end
  2609.    
  2610.     function lib.moveUp(blockTypeF)
  2611.         --[[ Move up until air in front (dig leaves / harvest tree) ]]
  2612.         if blockTypeF == nil then
  2613.             blockTypeF = T:getBlockType("forward")
  2614.         end
  2615.         while blockTypeF:find("dirt") ~= nil or
  2616.               blockTypeF:find("grass_block") ~= nil or
  2617.               T:isVegetation(blockTypeF) do -- go up while dirt, grass-block or any vegetation in front
  2618.             T:up(1)
  2619.             blockTypeF = T:getBlockType("forward")
  2620.             if blockTypeF:find("log") ~= nil then
  2621.                 lib.harvestTree(blockTypeF)
  2622.                 return T:getBlockType("forward")
  2623.             elseif blockTypeF:find("leaves") ~= nil then
  2624.                 T:dig("forward")
  2625.                 return ""
  2626.             end
  2627.         end
  2628.         return blockTypeF   -- should be "" (air) or any border block
  2629.     end
  2630.    
  2631.     function lib.harvestTree(blockTypeF)
  2632.         --[[ Fell tree, returns true if double size ]]
  2633.         -- clsTurtle.harvestTree(extend, craftChest, direction)
  2634.         local saplingType = lib.getSaplingFromLogType(blockTypeF)
  2635.         local double = T:harvestTree(false, false, "forward")   -- assume single tree, will auto-discover
  2636.         lib.plantSapling(saplingType, double)
  2637.     end
  2638.    
  2639.     function lib.safeMove()
  2640.         --[[ move forward until border reached. loop breaks at that point ]]
  2641.         local blockTypeF = ""
  2642.         local success = true
  2643.         while success do
  2644.             success, blockTypeF = lib.moveForward()             -- move forward 1 block, return block type ahead
  2645.             if not success then                                 -- did not move forwards, block in the way: either log, dirt/grass, border block or vegetation
  2646.                 if blockTypeF:find("log") then                  -- tree found
  2647.                     lib.harvestTree(blockTypeF)
  2648.                     success = true                              -- block (log) removed, try again
  2649.                 else
  2650.                     success = not lib.isBorder(blockTypeF)      -- Is at border?: if is at border success = false so loop stops
  2651.                     if success then                             -- Not at border. Dirt/grass vegetation in front
  2652.                         blockTypeF = lib.moveUp(blockTypeF)     -- move up until leaves/log/air
  2653.                         success = not lib.isBorder(blockTypeF)  -- Is at border?: if is at border success = false so loop stops
  2654.                         if success then                         -- keep moving forward
  2655.                             if blockTypeF:find("log") then      -- tree found
  2656.                                 lib.harvestTree(blockTypeF)
  2657.                             end
  2658.                                                                 -- else blockTypeF is air/leaves  border has been checked
  2659.                         end
  2660.                     end
  2661.                 end
  2662.             end                                                 -- else success = true, 1 block moved so continue
  2663.         end
  2664.     end
  2665.    
  2666.     function lib.isBorder(blockType)
  2667.         --[[ Is the block log, dirt, grass_block, vegetation: non-border, or other:border]]
  2668.         if blockType == nil then                    -- not passed as parameter
  2669.             blockType = T:getBlockType("forward")
  2670.         end
  2671.         if blockType == "" then                     -- air ahead: not border
  2672.             return false, ""
  2673.         else                                        -- could be border or other
  2674.             if blockType:find("dirt") ~= nil or blockType:find("grass_block") ~= nil or blockType:find("log") ~= nil then -- either dirt, grass block or log
  2675.                 return false, blockType             -- dirt, grass, log: not border
  2676.             end
  2677.             if T:isVegetation(blockType) then       -- vegetation found: not border
  2678.                 return false, blockType
  2679.             end
  2680.         end
  2681.         return true, blockType                      -- dirt, grass_block, log and vegetation eliminated:must be border
  2682.     end
  2683.    
  2684.     function lib.inPosition()
  2685.         --[[ check if in lower left corner ]]
  2686.         local inPosition = true         -- assume correct
  2687.         if not turtle.detectDown() then -- hanging in mid-air
  2688.             return false
  2689.         end
  2690.         T:turnLeft(1)
  2691.         if lib.isBorder() then
  2692.             -- so far so good
  2693.             T:turnLeft(1)
  2694.             if not lib.isBorder() then  -- not in correct place
  2695.                 inPosition = false
  2696.             end
  2697.             T:turnRight(2)              -- return to original position
  2698.         else
  2699.             inPosition = false
  2700.             T:turnRight(1)              -- return to original position
  2701.         end
  2702.         return inPosition
  2703.     end
  2704.    
  2705.     function lib.findBorder()
  2706.         --[[ assume started after reset. if log above harvest tree else return to ground. Find starting corner]]
  2707.         local blockType = T:getBlockType("up")                  -- dig any logs above, return to ground
  2708.         local log = "sapling"
  2709.         if blockType:find("log") ~= nil then                    -- originally felling a tree so complete it
  2710.             log = lib.getSaplingFromLogType(blockType)
  2711.             local double = T:harvestTree(false, false, "up")    -- assume single tree, will auto-discover
  2712.             lib.plantSapling(log, double)
  2713.         else                                                    -- no log above so go downm
  2714.             blockType = lib.moveDown()                          -- return to ground (or vegetation)
  2715.         end
  2716.         lib.safeMove()                                          -- move forward until border reached
  2717.         T:turnRight(1)
  2718.         lib.safeMove()                                          -- move forward until second border reached
  2719.         T:turnRight(1)                                          -- should now be in correct position
  2720.         lib.emptyInventory()                                    -- empty inventory if above a chest
  2721.     end
  2722.    
  2723.     local direction = "r"
  2724.     local blockTypeF = ""
  2725.     local success = false
  2726.     if not lib.inPosition() then
  2727.         lib.findBorder()
  2728.     end
  2729.     local secondBorderFound = false
  2730.     while not secondBorderFound do
  2731.         lib.safeMove()                                                      -- moves forward until reaches border forward or below
  2732.         lib.turn(direction)                                                 -- turn r or l. direction is not changed
  2733.         success, blockTypeF = lib.isBorder()                                -- no blockType passed as parameter so will return current block in new forward direction
  2734.         if success then
  2735.             secondBorderFound = true                                        -- game over
  2736.         elseif blockTypeF:find("log") ~= nil then                           -- tree in front
  2737.             lib.harvestTree(blockTypeF)
  2738.         elseif blockTypeF == "" or blockTypeF:find("leaves") ~= nil then    -- air or leaves in front
  2739.             T:forward(1)                                                    -- move forward 1 block
  2740.             lib.moveDown()                                                  -- go down if required
  2741.         elseif  blockTypeF:find("dirt") ~= nil or
  2742.                 blockTypeF:find("grass_block") ~= nil or
  2743.                 T:isVegetation(blockTypeF) then                             -- dirt, grass_block or vegetation in front
  2744.             blockTypeF = lib.moveUp(blockTypeF)                             -- move up until air or border ahead.
  2745.             if lib.isBorder(blockTypeF) then                                -- border ahead
  2746.                 secondBorderFound = true
  2747.             else                                                            -- air ahead                                   
  2748.                 T:forward(1)                                                -- move forward 1 block
  2749.             end
  2750.         end
  2751.         direction = lib.turn(direction)                                     -- turn r or l. direction is changed to opposite
  2752.     end
  2753.     lib.moveDown()                                                          -- return to ground level
  2754.     lib.emptyInventory()
  2755.     return {}
  2756. end
  2757.  
  2758. local function clearArea(R) -- 71, called from 22
  2759.     local evenWidth = false
  2760.     local evenHeight = false
  2761.     local loopWidth
  2762.     -- go(path, useTorch, torchInterval, leaveExisting)
  2763.     if R.width % 2 == 0 then
  2764.         evenWidth = true
  2765.         loopWidth = R.width / 2
  2766.     else
  2767.         loopWidth = math.ceil(R.width / 2)
  2768.     end
  2769.     if R.length % 2 == 0 then
  2770.         evenHeight = true
  2771.     end
  2772.     turtle.select(1)
  2773.     -- clear an area between 2 x 4 and 32 x 32
  2774.     -- if R.width is even no, then complete the up/down run
  2775.     -- if R.width odd no then finish at top of up run and reverse
  2776.     -- should be on flat ground, check voids below, harvest trees
  2777.     for x = 1, loopWidth do
  2778.         -- Clear first column (up)
  2779.         for y = 1, R.length do
  2780.             if R.useBlockType == "dirt" then
  2781.                 if not turtle.detectDown() then
  2782.                     T:place("minecraft:dirt", "down", true)
  2783.                 else --if not water, dirt, grass , stone then replace with dirt
  2784.                     blockType = T:getBlockType("down")
  2785.                     if blockType ~= "" then
  2786.                         if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
  2787.                             turtle.digDown()
  2788.                             T:place("minecraft:dirt", "down", true)
  2789.                         end
  2790.                     end
  2791.                 end
  2792.             end
  2793.             if y < R.length then
  2794.                 T:go("F1+1", false,0,false)
  2795.             end
  2796.         end
  2797.         -- clear second column (down)
  2798.         if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
  2799.             T:go("R1F1+1R1", false,0,false)
  2800.             for y = 1, R.length do
  2801.                 if R.useBlockType == "dirt" then
  2802.                     if not turtle.detectDown() then
  2803.                         T:place("minecraft:dirt", "down", true)
  2804.                     else
  2805.                         blockType = T:getBlockType("down")
  2806.                         if blockType ~= "" then
  2807.                             if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
  2808.                                 turtle.digDown()
  2809.                                 T:place("minecraft:dirt", "down", true)
  2810.                             end
  2811.                         end
  2812.                     end
  2813.                 end
  2814.                 if y < R.length then
  2815.                     T:go("F1+1", false, 0, false)
  2816.                 end
  2817.             end
  2818.             if x < loopWidth then
  2819.                 T:go("L1F1+1L1", false,0,false)
  2820.             else
  2821.                 T:turnRight(1)
  2822.                 T:forward(R.width - 1)
  2823.                 T:turnRight(1)
  2824.             end
  2825.         else -- equals R.width but is 1,3,5,7 etc
  2826.             T:turnLeft(2) --turn round 180
  2827.             T:forward(R.length - 1)
  2828.             T:turnRight(1)
  2829.             T:forward(R.width - 1)
  2830.             T:turnRight(1)
  2831.         end
  2832.     end
  2833.     return {}
  2834. end
  2835.  
  2836. local function clearRectangle(R) -- 72
  2837.     --local function clearRectangle(width, length, up, down)
  2838.     -- height = 0: one level, 1 = +up, 2 = +down, 3 = +up/down
  2839.     local lib = {}
  2840.     function lib.UpDown(length)
  2841.         for l = 1, length do
  2842.             --T:go("x0x2F1x0x2")
  2843.             turtle.digDown()                -- dig below
  2844.             while turtle.digUp() do end     -- dig up including gravity blocks
  2845.             while not turtle.forward() do   -- if no block in front, moves forward
  2846.                 turtle.dig()                -- block in front, so dig it
  2847.             end
  2848.             turtle.digDown()                -- now moved forward so dig down again
  2849.             while turtle.digUp() do end     -- dig up again including gravity blocks
  2850.         end
  2851.     end
  2852.    
  2853.     function lib.Up(length)
  2854.         for l = 1, length do
  2855.             --T:go("x0F1x0")
  2856.             while turtle.digUp() do end
  2857.             while not turtle.forward() do   -- if no block in front, moves forward
  2858.                 turtle.dig()                -- block in front, so dig it
  2859.             end
  2860.             while turtle.digUp() do end
  2861.         end
  2862.     end
  2863.    
  2864.     function lib.Down(length)
  2865.         for l = 1, length do
  2866.             --T:go("x2F1x2")
  2867.             turtle.digDown()
  2868.             while not turtle.forward() do   -- if no block in front, moves forward
  2869.                 turtle.dig()                -- block in front, so dig it
  2870.             end
  2871.             turtle.digDown()
  2872.         end
  2873.     end
  2874.    
  2875.     function lib.Forward(length)
  2876.         T:forward(length)
  2877.     end
  2878.    
  2879.     -- could be 1 wide x xx R.length (trench) R.up and return
  2880.     -- could be 2+ x 2+
  2881.     -- even no of runs return after last run
  2882.     -- odd no of runs forward, back, forward, reverse and return
  2883.     turtle.select(1)
  2884.     if R.width == 1 then                    -- single block trench ahead only
  2885.         if R.up and R.down then             -- single block wide trench dig R.up and R.down = 3 blocks deep
  2886.             lib.UpDown(R.length - 1)
  2887.         elseif R.up then                    -- single block wide trench dig R.up = 2 blocks deep
  2888.             lib.Up(R.length - 1)
  2889.         elseif R.down then                  -- single block wide trench dig R.down = 2 blocks deep
  2890.             lib.Down(R.length - 1)
  2891.         else                                -- single block wide = 1 block deep
  2892.             lib.Forward(R.length - 1)
  2893.         end
  2894.         T:turnRight(2)                      -- turn at the top of the run
  2895.         T:forward(R.length - 1)             -- return to start
  2896.         T:turnRight(2)                      -- turn round to original position
  2897.     else                                    -- R.width 2 or more blocks
  2898.         local iterations = 0                -- R.width = 2, 4, 6, 8 etc
  2899.         if R.width % 2 == 1 then            -- R.width = 3, 5, 7, 9 eg R.width 7
  2900.             iterations = (R.width - 1) / 2  -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
  2901.         else
  2902.             iterations = R.width / 2        -- iterations 1, 2, 3, 4 for widths 2, 4, 6, 8
  2903.         end
  2904.         for i = 1, iterations do            -- eg 3 blocks wide, iterations = 1
  2905.             if R.up and R.down then                         -- dig R.up and R.down
  2906.                 lib.UpDown(R.length - 1)
  2907.                 T:go("x0x2R1F1x0x2R1x0x2")              -- turn round
  2908.                 lib.UpDown(R.length - 1)
  2909.             elseif R.up then                                -- dig R.up
  2910.                 lib.Up(R.length - 1)
  2911.                 T:go("x0R1F1x0R1x0")
  2912.                 lib.Up(R.length - 1)
  2913.             elseif R.down then                          -- dig R.down
  2914.                 lib.Down(R.length - 1)
  2915.                 T:go("x2R1F1x2R1x2")
  2916.                 lib.Down(R.length - 1)
  2917.             else                                        -- no digging R.up or R.down
  2918.                 lib.Forward(R.length - 1)
  2919.                 T:go("R1F1R1")
  2920.                 lib.Forward(R.length - 1)
  2921.             end
  2922.             -- if 1 less than end, reposition for next run
  2923.             if i < iterations then
  2924.                 T:go("L1F1L1", false, 0, false)
  2925.             end
  2926.         end
  2927.         if R.width % 2 == 1 then  -- additional run and return to base needed
  2928.             T:go("L1F1L1", false, 0, false)
  2929.             if R.up and R.down then
  2930.                 lib.UpDown(R.length - 1)
  2931.             elseif R.up then
  2932.                 lib.Up(R.length - 1)
  2933.             elseif R.down then
  2934.                 lib.Down(R.length - 1)
  2935.             else
  2936.                 lib.Forward(R.length - 1)
  2937.             end
  2938.             T:turnRight(2)
  2939.             T:forward(R.length - 1)
  2940.         end
  2941.         T:go("R1F"..R.width - 1 .."R1", false, 0, false)
  2942.     end
  2943.     return {}
  2944. end
  2945.  
  2946. local function clearPerimeter(R) -- 74
  2947.     local lib = {}
  2948.     function lib.UpDown(length)
  2949.         for l = 1, length do
  2950.             T:go("x0x2F1x0x2")
  2951.         end
  2952.     end
  2953.    
  2954.     function lib.Up(length)
  2955.         for l = 1, length do
  2956.             T:go("x0F1x0")
  2957.         end
  2958.     end
  2959.    
  2960.     function lib.Down(length)
  2961.         for l = 1, length do
  2962.             T:go("x2F1x2")
  2963.         end
  2964.     end
  2965.    
  2966.     function lib.Forward(length)
  2967.         T:forward(length)
  2968.     end
  2969.    
  2970.     if R.up and R.down then
  2971.         for i = 1, 2 do
  2972.             lib.UpDown(R.length - 1)
  2973.             T:turnRight(1)
  2974.             lib.UpDown(R.width - 1)
  2975.             T:turnRight(1)
  2976.         end
  2977.     elseif R.up then
  2978.         for i = 1, 2 do
  2979.             lib.Up(R.length - 1)
  2980.             T:turnRight(1)
  2981.             lib.Up(R.width - 1)
  2982.             T:turnRight(1)
  2983.         end
  2984.     elseif R.down then
  2985.         for i = 1, 2 do
  2986.             lib.Down(R.length - 1)
  2987.             T:turnRight(1)
  2988.             lib.Down(R.width - 1)
  2989.             T:turnRight(1)
  2990.         end
  2991.     else
  2992.         for i = 1, 2 do
  2993.             lib.Forward(R.length - 1)
  2994.             T:turnRight(1)
  2995.             lib.Forward(R.width - 1)
  2996.             T:turnRight(1)
  2997.         end
  2998.     end
  2999.     return {}
  3000. end
  3001.  
  3002. local function clearBuilding(R) -- 75, 43
  3003.     --[[
  3004.     menu item: Clear hollow structure
  3005.     Clear the outer shell of a building, leaving inside untouched. Optional floor/ceiling removal
  3006.     if outside active area will have already moved in
  3007.     R.direction = "up" or "down" as direction of travel
  3008.     R.up = true / false to dig up as well
  3009.     R.down = true / false to dig down as well
  3010.     R.data.ceiling = true / false to remove ceiling
  3011.     R.data.floor = true / false to remove floor
  3012.     examples use a 5 x 5 x 7 cube
  3013.     ]]
  3014. --utils.printR(R)                                   -- debug values in R
  3015.     local height = 1                                -- current level of turtle
  3016.     local cleared = false
  3017.     R.silent = true
  3018.     R.up = false
  3019.     R.down = false
  3020.     -- check if floor/ceiling is to be cleared
  3021.     if R.direction == "up" then                     -- from bottom to top
  3022.         if R.data.floor then
  3023.             clearRectangle(R)
  3024.             cleared = true
  3025.         end
  3026.     else                                            -- from top to bottom
  3027.         if R.data.ceiling then
  3028.             clearRectangle(R)
  3029.             cleared = true
  3030.         end
  3031.     end
  3032.    
  3033.     if R.height == 1 and not cleared then           -- only 1 layer, perimeter only eg R.height = 7
  3034.         clearPerimeter(R)
  3035.     elseif R.height == 2 and not cleared then       -- only 2 layers, perimeter only
  3036.         if R.direction == "up" then                 -- from bottom to top
  3037.             R.up = true
  3038.         else
  3039.             R.down = true
  3040.         end
  3041.         clearPerimeter(R)
  3042.     elseif R.height >= 3 then                       -- 3 or more levels, floor/ceiling already assessed eg R.height = 7
  3043.         R.up = true
  3044.         R.down = true
  3045.         height = height + utils.move(R, 1)          -- move up/down 1 block for first layer eg height: 1 + 1 = 2
  3046.         -- height h + 3 R.height   loop
  3047.         --  2       5       5       end
  3048.         --  2       5       7       +
  3049.         --  5       8       7       end
  3050.         repeat         
  3051.             clearPerimeter(R)                       -- runs at least once, removes 3 layers: 1,2,3
  3052.             local move = 3
  3053.             --if height + 3 < R.height then         -- range with min 3(0), 4(1), 5(2), 6(3), 7(4), 8(5), 9(6) etc         
  3054.                 --height = height + utils.move(R, move) -- move up/down 3 blocks eg height 5, 8, 11, 14
  3055.             --else
  3056.                 --move = R.height - height - 1
  3057.                 --height = height + utils.move(R, move) -- move up/down 1-2 blocks eg height = 2 + 3 = 5
  3058.             --end
  3059.            
  3060.             if height + 3 >= R.height then          -- range with min 3(0), 4(1), 5(2), 6(3), 7(4), 8(5), 9(6) etc         
  3061.                 move = R.height - height
  3062.             end
  3063.             height = height + utils.move(R, move)   -- move up/down 1-2 blocks eg height = 2 + 3 = 5
  3064.         until height > R.height - 3             -- min 3 levels eg height = 2, R.height - 3 --> 7 - 3 = 4, 4 - 3 = 1
  3065.         R.up = false
  3066.         R.down = false 
  3067.         if height == R.height then                      -- already on top/bottom layer eg height = 5, R.height = 5
  3068.             if R.direction == "up" then                     -- reverse digging direction. Up = move to top and dig down
  3069.                 R.down = true
  3070.             else                                        -- reverse digging direction. Up = move to floor and dig up
  3071.                 R.up = true
  3072.             end
  3073.             clearPerimeter(R)
  3074.         else
  3075.             if R.direction == "up" then                     -- reverse digging direction. Up = move to top and dig down
  3076.                 R.down = true
  3077.             else                                        -- reverse digging direction. Up = move to floor and dig up
  3078.                 R.up = true
  3079.             end
  3080.  
  3081.             clearPerimeter(R)
  3082.         end
  3083.     end
  3084.    
  3085.     R.up = false
  3086.     R.down = false
  3087.     if R.direction == "up" then
  3088.         if R.data.ceiling then      -- from bottom to top
  3089.             clearRectangle(R)
  3090.         end
  3091.     elseif R.direction == "down" then
  3092.         if R.data.floor then    -- from top to bottom
  3093.             clearRectangle(R)
  3094.         end
  3095.     end
  3096.    
  3097.     if height > 1 then
  3098.         utils.move(R, height - 1, true) -- reverse direction
  3099.     end
  3100.    
  3101.     return {}
  3102. end
  3103.  
  3104. local function clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- 19
  3105.     local lib = {}
  3106.    
  3107.     function lib.checkCobweb(directions, inInventory)
  3108.         assert(type(directions) == "table", "directions must be a table eg {'up','down'}")
  3109.         for _, direction in ipairs(directions) do
  3110.             local blockType = T:getBlockType(direction)
  3111.             if inInventory == "minecraft:diamond_sword" then -- using a sword
  3112.                 local side = "left"
  3113.                
  3114.                 if blockType:find("cobweb") ~= nil then
  3115.                     --clsTurtle.equip(self, side, useItem, useDamage)
  3116.                     if equippedRight == "minecraft:diamond_pickaxe" then
  3117.                         side = "right"
  3118.                     end
  3119.                     T:equip(side, "minecraft:diamond_sword")
  3120.                     T:dig(direction)
  3121.                     T:equip(side, "minecraft:diamond_pickaxe")
  3122.                 elseif blockType ~= "" then
  3123.                     T:dig(direction)
  3124.                 end
  3125.             else
  3126.                 T:dig(direction)
  3127.             end
  3128.         end
  3129.     end
  3130.  
  3131.     -- check position by rotating until facing away from wall
  3132.     length = 0
  3133.     torch = 0
  3134.     turns = 0
  3135.     while not turtle.detect() do
  3136.         T:turnRight(1)
  3137.         turns = turns + 1
  3138.         if turns > 4 then
  3139.             return {"I am not facing a wall. Unable to continue"}
  3140.         end
  3141.     end
  3142.     T:turnRight(2)
  3143.     -- move forward until obstructed, digging up/down. place torches
  3144.     while not turtle.detect() do
  3145.         lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  3146.         length = length + 1
  3147.         torch = torch + 1
  3148.         if torch == R.torchInterval then
  3149.             torch = 0
  3150.             T:place("minecraft:torch", "down", false) ---(self, blockType, damageNo, direction, leaveExisting, signText)
  3151.         end
  3152.         lib.checkCobweb({"forward"}, inInventory) -- dig cobweb or any other block in front
  3153.         T:forward(1)
  3154.     end
  3155.     -- turn right, forward, right, return to start with up/down dig
  3156.     T:go("R1")
  3157.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  3158.     T:go("F1R1")
  3159.     for i = 1, length, 1 do
  3160.         lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
  3161.         T:forward(1)
  3162.     end
  3163.     -- move to other wall and repeat.
  3164.     T:go("R1")
  3165.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  3166.     T:go("F1")
  3167.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  3168.     T:go("F1R1")
  3169.     lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
  3170.     for i = 1, length, 1 do
  3171.         lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
  3172.         T:forward(1)
  3173.     end
  3174.     lib.checkCobweb({"up", "down"}, inInventory) -- dig cobweb or any other block up/down/forward
  3175.    
  3176.     return {}
  3177. end
  3178.  
  3179. local function clearMonumentLayer(R) -- 85
  3180.     R.up = true
  3181.     R.down = true
  3182.     R.silent = true
  3183.     if R.subChoice == 0 then
  3184.         R.up = false
  3185.         R.down = false
  3186.     end
  3187.     -- send turtle down until it hits bottom
  3188.     -- then clear rectangle of given size
  3189.     -- start above water, usually on cobble scaffold above monument
  3190.     if T:detect("down") then -- in case not over wall
  3191.         T:forward(1)
  3192.     end
  3193.     local height = 1
  3194.     -- go down until solid block detected
  3195.     while utils.clearVegetation("down") do
  3196.         T:down(1)
  3197.         height = height + 1
  3198.     end
  3199.     T:down(1)
  3200.     height = height + 1
  3201.     clearRectangle(R)
  3202.     T:up(height - 1)
  3203.    
  3204.     return {}
  3205. end
  3206.  
  3207. local function clearWaterPlants(R) -- 87
  3208.     local lib = {}
  3209.    
  3210.     function lib.getLength()
  3211.         local length = 1
  3212.         print("Checking water length")
  3213.         while utils.clearVegetation("forward") do
  3214.             T:forward(1)
  3215.             length = length + 1
  3216.         end
  3217.         for i = 1, length do
  3218.             turtle.back()
  3219.         end
  3220.         return length
  3221.     end
  3222.    
  3223.     function lib.clearDown(D)
  3224.         while utils.clearVegetation("down") do --clears any grass or sea plants, returns true if air or water, bubble column or ice
  3225.             T:down(1)
  3226.             D.depth = D.depth + 1
  3227.         end
  3228.         -- if slab at bottom, replace with solid block
  3229.         D.blockType = T:getBlockType("down")
  3230.         if D.blockType:find("slab") ~= nil then
  3231.             T:go("C2")
  3232.         end
  3233.         if D.depth > D.maxDepth then
  3234.             D.maxDepth = D.depth
  3235.         end
  3236.        
  3237.         return D
  3238.     end
  3239.    
  3240.     function lib.clearLength(D)
  3241.         local moves = 0
  3242.         local blockHeight = 1
  3243.         D.floorLength = 0 -- reset
  3244.         while moves < D.length - 1 do
  3245.             if utils.clearVegetation("forward") then
  3246.                 T:forward(1)
  3247.                 moves = moves + 1
  3248.                 if turtle.detectUp() then -- could be on monument going under arch, or faulty monument floor
  3249.                     if not D.monumentArchesClear then
  3250.                         D = lib.checkArches(D)
  3251.                     end
  3252.                 end
  3253.                 local temp = D.depth
  3254.                 D = lib.clearDown(D) -- go down if in water/air
  3255.                 if blockHeight == 4 and D.depth - temp == 3 then -- could be just gone over 3 block high column in ocean monument
  3256.                     if not D.monumentTopClear then
  3257.                         D = lib.checkTop(D)
  3258.                     end
  3259.                     blockHeight = 1
  3260.                 end
  3261.                 if D.useBlockType == "prismarine" then
  3262.                     if D.blockType:find("prismarine") == nil then
  3263.                         -- on monument floor so restrict forward movement to 8 blocks
  3264.                         D.floorLength = D.floorLength + 1
  3265.                         if D.floorLength == 8 then
  3266.                             D.blockType = T:getBlockType("forward")
  3267.                             while D.blockType:find("prismarine") == nil do
  3268.                                 T:up(1)
  3269.                                 D.blockType = T:getBlockType("forward")
  3270.                             end
  3271.                             D.floorLength = 0
  3272.                         end
  3273.                     end
  3274.                 end
  3275.                 if moves >= D.length - 1 then
  3276.                     D.width = D.width + 1   -- another length completed so increase width
  3277.                     return D
  3278.                 end
  3279.             else -- block in front
  3280.                 blockHeight = 1
  3281.                 local waterAbove = utils.clearVegetation("up")
  3282.                 local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
  3283.                 while not waterAhead do     -- solid block in front
  3284.                     if waterAbove then      -- move up
  3285.                         T:up(1)
  3286.                         D.depth = D.depth - 1
  3287.                         blockHeight = blockHeight + 1
  3288.                         if D.depth < 1 then
  3289.                             D.width = D.width + 1   -- another length completed so increase width
  3290.                             return D
  3291.                         end
  3292.                     else                    -- block above so go back
  3293.                         while not waterAbove do
  3294.                             utils.goBack()  --  returns true if no object behind, but moves anyway
  3295.                             waterAbove = utils.clearVegetation("up")
  3296.                             moves = moves - 1
  3297.                             if moves == 0 then
  3298.                                 T:up(1)
  3299.                                 D.depth = D.depth - 1
  3300.                                 waterAbove = utils.clearVegetation("up")
  3301.                                 while not waterAbove do
  3302.                                     T:up(1)
  3303.                                     D.depth = D.depth - 1
  3304.                                 end
  3305.                             end
  3306.                         end
  3307.                         -- go up 1 to prevent loop
  3308.                         T:up(1)
  3309.                         D.depth = D.depth - 1
  3310.                     end
  3311.                     waterAbove = utils.clearVegetation("up")
  3312.                     waterAhead = utils.clearVegetation("forward")
  3313.                 end
  3314.             end
  3315.         end
  3316.         D.width = D.width + 1   -- another length completed so increase width
  3317.         D.maxDepth = D.maxDepth + 1 -- +1 to allow for starting pos in top layer
  3318.        
  3319.         return D
  3320.     end
  3321.    
  3322.     function lib.checkArches(D)
  3323.         -- gone under a block so could be monument arch (6)
  3324.         if T:getBlockType("up"):find("prismarine") ~= nil then -- confirm on monument, not previously cleared
  3325.             local direction = ""    -- initialise direction
  3326.             T:go("B1U2F1R1")
  3327.             if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess
  3328.                 direction = "R"
  3329.             else    -- wrong direction. turn round and check other side
  3330.                 T:go("R2")
  3331.                 if T:getBlockType("forward"):find("prismarine") ~= nil then
  3332.                     direction = "L"
  3333.                 end
  3334.             end
  3335.             local path = "U1F1 U1F3 D1F1 D1R2 U2F5 D2"
  3336.             --for i = 1, 6 do
  3337.             T:go(path) -- clears arch top 1 and returns
  3338.             T:go(direction.."1F6"..direction.."1")
  3339.             T:go(path) -- clears arch top 2 and returns
  3340.             T:go(direction.."1F6"..direction.."1")
  3341.             T:go(path) -- clears arch top 3 and returns
  3342.             T:go(direction.."1F9"..direction.."1")
  3343.             T:go(path) -- clears arch top 4 and returns
  3344.             T:go(direction.."1F6"..direction.."1")
  3345.             T:go(path) -- clears arch top 5 and returns
  3346.             T:go(direction.."1F6"..direction.."1")
  3347.             T:go(path) -- clears arch top 6 and returns
  3348.            
  3349.             T:go(direction.."3F34"..direction.."2D2F1")
  3350.             D.monumentArchesClear =  true
  3351.         end
  3352.         return D
  3353.     end
  3354.    
  3355.     function lib.checkTop(D)
  3356.         -- gone over 3 block column so could be at the top of ocean monument
  3357.         if T:getBlockType("down"):find("prismarine") ~= nil then -- confirm on monument, not previously cleared
  3358.             local direction = ""    -- initialise direction
  3359.             T:go("U3R1")            -- up to top of column and try right side
  3360.             if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess
  3361.                 direction = "L"
  3362.             else    -- wrong direction. turn round and check other side
  3363.                 T:go("R2")
  3364.                 if T:getBlockType("forward"):find("prismarine") ~= nil then
  3365.                     direction = "R"
  3366.                 end
  3367.             end
  3368.             if direction ~= "" then -- facing single block on layer 2
  3369.                 T:go("U1F6"..direction.."1F5".. direction.."1F5"..direction.."1F5"..direction.."1") -- clear 4 single blocks
  3370.                 T:go("F1U1"..direction.."1F1"..direction.."3") -- on top of monument
  3371.                 T:go("F3".. direction.."1F3"..direction.."1F3"..direction.."1F3"..direction.."3") -- clear top, face return
  3372.                 T:go("F2D5"..direction.."3B1")
  3373.             end
  3374.             D.monumentTopClear = true
  3375.         end
  3376.         return D
  3377.     end
  3378.    
  3379.     function lib.findBlockTypeEnd(D)
  3380.         D.blockType = "" -- reset
  3381.         repeat
  3382.             if utils.clearVegetation("forward") then
  3383.                 T:forward(1)
  3384.                 D = lib.clearDown(D) -- go down if in water/air, D.blockType is updated with floor type
  3385.             else -- block in front
  3386.                 local waterAbove = utils.clearVegetation("up")
  3387.                 local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
  3388.                 while not waterAhead do     -- solid block in front
  3389.                     if waterAbove then      -- move up
  3390.                         T:up(1)
  3391.                     else                    -- block above so go back
  3392.                         while not waterAbove do
  3393.                             utils.goBack()  --  returns true if no object behind, but moves anyway
  3394.                             waterAbove = utils.clearVegetation("up")
  3395.                         end
  3396.                     end
  3397.                     waterAbove = utils.clearVegetation("up")
  3398.                     waterAhead = utils.clearVegetation("forward")
  3399.                 end
  3400.             end
  3401.         until D.blockType:find(D.useBlockType) == nil
  3402.         -- now above a non-prismarine block, facing away from monument
  3403.         T:turnRight(2) -- facing monument
  3404.         D.blockType = T:getBlockType("forward")
  3405.         while D.blockType:find(D.useBlockType) ~= nil do
  3406.             T:up(1)
  3407.             D.blockType = T:getBlockType("forward")
  3408.         end
  3409.         T:go("F1L1")
  3410.         D.blockType = T:getBlockType("down")
  3411.         while D.blockType:find(D.useBlockType) ~= nil do
  3412.             T:forward(1)
  3413.             D.blockType = T:getBlockType("down")
  3414.         end
  3415.         turtle.back()
  3416.         -- should now be at end of monument base
  3417.     end
  3418.    
  3419.     function lib.turn(D)
  3420.         local direction = "R"
  3421.         if not D.facingForward then
  3422.             direction = "L"
  3423.         end
  3424.         T:go(direction.. 1)
  3425.         if utils.clearVegetation("forward") then
  3426.             T:forward(1)
  3427.             --D.depth = D.depth + lib.clearDown(depth)
  3428.             D = lib.clearDown(D)
  3429.         else
  3430.             while not utils.clearVegetation("forward") do
  3431.                 T:up(1)
  3432.                 D.depth = D.depth - 1
  3433.             end
  3434.             T:forward(1)
  3435.         end
  3436.         T:go(direction.. 1)
  3437.         D.facingForward = not D.facingForward
  3438.        
  3439.         return D
  3440.     end
  3441.  
  3442.     local D = {}
  3443.     D.depth = 0
  3444.     D.maxDepth = 0
  3445.     D.blockType = ""
  3446.     D.useBlockType = R.useBlockType -- "" or "prismarine"
  3447.     D.length = 0    -- copy of R.length used in lib.clearLength
  3448.     D.width = 0     -- increased every iteration
  3449.     D.facingForward = true
  3450.     D.monumentTopClear = false
  3451.     D.monumentArchesClear = false
  3452.     D.inWater = false
  3453.     D.onWater = false
  3454.     D.inWater, D.onWater = utils.getWaterStatus()
  3455.     D.floorLength = 0 -- used on monument floor
  3456.    
  3457.     if R.data == "clearWaterPlants" then -- NOT monument corner discovery
  3458.         D.inWater, D.onWater = utils.startWaterFunction(D.onWater, D.inWater, 2, true) -- move into water
  3459.         if R.length == 0 then
  3460.             R.length = lib.getLength()
  3461.         end
  3462.         if R.width == 0 then
  3463.             T:turnRight(1)
  3464.             R.width = lib.getLength()
  3465.             T:turnLeft(1)
  3466.         end
  3467.     end
  3468.     D.length = R.length
  3469.     D = lib.clearDown(D) -- go down to floor, set depth, maxDepth, blockType
  3470.     if R.data == "clearWaterPlants" then -- NOT monument corner discovery
  3471.         if R.width == 1 then
  3472.             print("Single row clearing")
  3473.             D = lib.clearLength(D) --D.width also increased
  3474.         else
  3475.             while D.width < R.width do -- D.width starts at 0
  3476.                 -- now on floor, move along sea/river bed following contour
  3477.                 D = lib.clearLength(D) --D.width also increased
  3478.                 -- now turn and repeat
  3479.                 if D.width < R.width then  
  3480.                     D = lib.turn(D)
  3481.                     if D.depth <= 0 then
  3482.                         break
  3483.                     end
  3484.                 end
  3485.             end
  3486.         end
  3487.         -- finished so return to surface
  3488.         T:up(1) -- up 1 to check for water below
  3489.         while T:getBlockType("down"):find("water") ~= nil do
  3490.             T:up(1)
  3491.         end
  3492.         T:down(2) -- return to surface
  3493.         --[[while utils.clearVegetation("forward") do
  3494.             T:forward(1)
  3495.         end]]
  3496.     elseif R.data == "oceanMonumentColumns" then -- monument corner discovery
  3497.         -- this function used to find edge of monument base
  3498.         if D.blockType:find(D.useBlockType) ~= nil then
  3499.             lib.findBlockTypeEnd(D)
  3500.             return {""}
  3501.         else
  3502.             T:up(D.depth)
  3503.             return {"Prismarine not found on ocean floor"}
  3504.         end
  3505.     end
  3506.     if R.silent then
  3507.         return {D.maxDepth, R.length}
  3508.     else
  3509.         return {""}
  3510.     end
  3511. end
  3512.  
  3513. local function clearMountainSide(R) -- 78
  3514.     --[[
  3515.     First row              outward  l  s  f  mid    (length, start, finish, midPoint)
  3516.  
  3517.           >|*|*|           true                     lib.clearRow() moves: 7-5=2, midPoint starts at 2
  3518.           +|*|*|
  3519.           +|*|*|
  3520.           ^|*|*|        <  false    7  5  6  2      lib.clearRow() moves: 9-2=7, midPoint starts at -4 -1 = -5
  3521.            |*|*|*|      +
  3522.          |*|*|*|*|*|    +
  3523.       >  |*|*|*|*|*|    ^  true     9  2  6  -4     lib.getStartingLength(). Ends 1 block after block finish
  3524.       ^|*|*|*|*|*|*|*|*|                            starts here, moves up 1
  3525.         1 2 3 4 5 6 7 8                             block index
  3526.          
  3527.     Second row                outward l  s  f  mid
  3528.                  <            false
  3529.                  +
  3530.           |*|*|  +
  3531.        >|*|*|*|*|^            true
  3532.        +|*|*|*|*|
  3533.        +|*|*|*|*|
  3534.        ^|*|*|*|*|          <  false   6  5  6  2
  3535.         |*|*|*|*|*|*|      +
  3536.       |*|*|*|*|*|*|*|*|    +
  3537.       |*|*|*|>|*|*|*|*|    ^  true    7+5   5 -7    lib.getHalf(R); goBack(7)
  3538.     |*|*|*|*|*|*|*|*|*|*|*|                           starts at midPoint of previous row eg block 4
  3539.      0 1 2 3 4 5 6 7 8 9 10
  3540.     ]]
  3541.    
  3542.     -- variables declared before lib for them to be used within lib as is then in scope
  3543.     local turn = "R"
  3544.     local oTurn = "L"
  3545.     if R.subChoice == 1 then    -- remove left side
  3546.         turn = "L"
  3547.         oTurn = "R"
  3548.     end
  3549.     local outward = true        -- direction flag
  3550.    
  3551.     local lib = {}
  3552.    
  3553.     function lib.isAnyAbove(above)
  3554.         T:saveToLog("lib.isAnyAbove: "..utils.tableConcat(above, ", "), false)
  3555.         for k,v in ipairs(above) do
  3556.             if v then
  3557.                 T:saveToLog("lib.isAnyAbove Found: "..k , false)
  3558.                 return true
  3559.             end
  3560.         end
  3561.         return false
  3562.     end
  3563.        
  3564.     function lib.clearLevel(R, above)   -- eg 9, 2, 6, -4 from lib.getStartingLength OR 7, 5, 6, 3 from previous
  3565.         -- clearLevel always follows either lib.getStartingLength or a previous lib.clearLevel
  3566.         -- midPoint should be adjusted as turtle moves to reflect current row length
  3567.         if #above == 0 then return above, 1 end
  3568.         --local index = 0
  3569.         local minMoves = math.floor(#above / 2)
  3570.         local up, forward, down = lib.getDetect()
  3571.         if outward then                                     -- follow table indexes
  3572.             for x = 1, minMoves do                          -- clear first half
  3573.                 above[x] = up                               -- reset this with new value
  3574.                 T:go("x0x2F1")                              -- clear and move forward
  3575.                 up, forward, down = lib.getDetect()
  3576.                 --index = index + 1
  3577.             end
  3578.             for x = minMoves + 1, #above do                 -- check remaing half and clear
  3579.                 T:go("x0x2")                                -- clear above / below
  3580.                 if above[x] then                            -- is a block recorded as present?(now below)
  3581.                     above[x] = up                           -- reset this with new value
  3582.                     T:forward(1)                            -- move forward
  3583.                     up, forward, down = lib.getDetect()
  3584.                     --index = index + 1
  3585.                 else
  3586.                     break
  3587.                 end
  3588.             end
  3589.         else                                                -- iterate table in reverse
  3590.             --index = #above
  3591.             for x = #above, minMoves, -1 do                 -- clear first half
  3592.                 above[x] = up                               -- reset this with new value
  3593.                 T:go("x0x2F1")                              -- clear and move forward
  3594.                 up, forward, down = lib.getDetect()
  3595.                 --index = index - 1
  3596.             end
  3597.             for x = minMoves - 1, 1, -1 do                  -- check remaing half and clear
  3598.                 T:go("x0x2")                                -- clear up / down
  3599.                 if above[x] then                            -- is a block recorded as present?(now below)
  3600.                     above[x] = up                           -- reset this with new value
  3601.                     T:forward(1)                            -- move forward
  3602.                     up, forward, down = lib.getDetect()
  3603.                     --index = index - 1
  3604.                 else
  3605.                     break
  3606.                 end
  3607.             end
  3608.         end
  3609.         T:go("x0x2 F1R2 x0x2 F1")                           -- face opposite direction, delete blocks above and below
  3610.         outward = not outward                               -- switch direction flag
  3611.         return above                                        -- eg {false, true, true, true, false}
  3612.     end
  3613.    
  3614.     function lib.getDetect()
  3615.         return turtle.detectUp(),  turtle.detect(),  turtle.detectDown()
  3616.     end
  3617.    
  3618.     function lib.getStartingLength(R)
  3619.         --[[
  3620.             length of column by excavating blocks above, ahead or below
  3621.             Rotate 180 at end of run ready to return
  3622.             already 1 block above ground
  3623.         ]]
  3624.         local above = {}                                    -- empty table of boolean values
  3625.         local length = 0                                    -- used as counter                         
  3626.         T:forward(1)                                        -- start check 1 block ahead
  3627.         local up, forward, down = lib.getDetect()           -- check if anything around current block
  3628.         if up or forward or down then                       -- block found nearby: continue
  3629.             while up or forward or down do                  -- while blocks ahead / up / down move forward
  3630.                 table.insert(above, up)
  3631.                 T:go("x0x2F1")
  3632.                 up, forward, down = lib.getDetect()         -- check if anything around current block
  3633.                 length = length + 1
  3634.                 if length >= R.length then                  -- check if going out of range
  3635.                     T:saveToLog("lib.getStartingLength(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
  3636.                     break
  3637.                 end
  3638.             end
  3639.             T:go("R2x0x2")                                  -- Rotate 180 and clear blocks above/below
  3640.         else                                                -- no blocks nearby: exit
  3641.             T:go("R2F1")                                    -- return to start position rotated 180
  3642.         end
  3643.         outward = not outward
  3644.  
  3645.         return above                                        -- above = {false, true, true, true, true, false, false}
  3646.     end
  3647.    
  3648.     function lib.firstRow(R)
  3649.         local height = 1                                    -- starts at ground level, but forced up 1
  3650.         T:up(1)
  3651.         local above = lib.getStartingLength(R)              -- clear the ground level and 1 above eg 9, 2, 5, 4
  3652.         if T:saveToLog("startLength: "..#above, true) then
  3653.             T:saveToLog(utils.tableConcat(above, ", "), false)
  3654.             utils.waitForInput()
  3655.         end                                                 -- at end of first row as already turned 180, outward set to false in getStartingLength
  3656.         while lib.isAnyAbove(above) do
  3657.             T:go("U3")  -- go up 3
  3658.             height = height + 3
  3659.             above = lib.clearLevel(R, above)    -- returns start and finish of blocks above, rotates 180
  3660.             if T:saveToLog("checking level: "..height, true) then
  3661.                 T:saveToLog(utils.tableConcat(above, ", "), false)
  3662.                 utils.waitForInput()
  3663.             end
  3664.         end                                                 -- first row all levels completed.
  3665.         T:down(height)                                      -- now on ground + 1, facing last column cleared.
  3666.        
  3667.         return above
  3668.     end
  3669.        
  3670.     function lib.deepCopy(tbl)
  3671.         local copy = {}
  3672.         for key, value in ipairs(tbl) do
  3673.             table.insert(copy, value)
  3674.         end
  3675.         return copy
  3676.     end
  3677.    
  3678.     function lib.getHalf(R, above)
  3679.         -- already 1 block above ground
  3680.         local maxLength = R.length
  3681.         local temp = {}
  3682.         local retValue = {}
  3683.         if #above > 0 then                              -- not empty table, so must be second half
  3684.             temp = lib.deepCopy(above)                  -- copy existing table
  3685.             above = {}                                  -- initialise above
  3686.         end
  3687.         local up, forward, down = lib.getDetect()
  3688.        
  3689.         while up or forward or down do                  -- while blocks ahead / up / down move forward
  3690.             T:go("x0x2F1")
  3691.             table.insert(above, up)
  3692.             up, forward, down = lib.getDetect()         -- check if anything around current block
  3693.            
  3694.             if #above >= math.floor(maxLength / 2) then -- check if going out of range
  3695.                 T:saveToLog("lib.getHalf(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
  3696.                 T:go("x0x2")
  3697.                 break
  3698.             end
  3699.         end
  3700.         T:turnRight(2)                                  -- ready for next half or return
  3701.         outward = not outward
  3702.         if #temp > 0 then                               -- completing a second half measurement
  3703.             for i = #above, 1, -1 do
  3704.                 table.insert(retValue, above[i])        -- combine 2 tables into 1
  3705.             end
  3706.             for i = 1, #temp do
  3707.                 table.insert(retValue, temp[i])
  3708.             end
  3709.         else
  3710.             retValue = above
  3711.         end
  3712.         return retValue
  3713.     end
  3714.    
  3715.     function lib.nextRow(R)
  3716.         local height = 1
  3717.         T:saveToLog("lib.nextRow(R)", false)
  3718.         T:up(1)
  3719.         local pattern = turn.."1F1"..turn.."1"
  3720.         if not outward then
  3721.             pattern = oTurn.."1F1"..oTurn.."1"
  3722.         end
  3723.         T:go(pattern)
  3724.         T:saveToLog("    T:go("..pattern..")", false)
  3725.         outward = not outward -- reverse direction flag
  3726.         -- now in next vertical row
  3727.         local above = lib.getHalf(R, {})
  3728.         local index = 0
  3729.         if T:saveToLog("\t  first half Length: "..#above.." Enter", true) then
  3730.             T:saveToLog(utils.tableConcat(above, ", "), false)
  3731.             utils.waitForInput()
  3732.         end
  3733.         lib.returnToMidPoint(#above)                    -- return to starting point
  3734.         T:forward(1)       
  3735.         above = lib.getHalf(R, above)                   -- returns length - 1 eg 5, 4
  3736.         if T:saveToLog("\t  total length: "..#above.." Enter", true) then
  3737.             T:saveToLog(utils.tableConcat(above, ", "), false)
  3738.             utils.waitForInput()
  3739.         end
  3740.        
  3741.         while lib.isAnyAbove(above) do
  3742.             T:go("U3")              -- go up 3
  3743.             height = height + 3     -- increment height
  3744.             T:saveToLog("\tClear height loop: height = "..height, false)
  3745.             above = lib.clearLevel(R, above)    -- returns start and finish of blocks above
  3746.         end
  3747.         T:down(height)  -- now on ground + 1
  3748.         lib.returnToMidPoint(above)
  3749.     end
  3750.    
  3751.     function lib.returnToMidPoint(above)
  3752.         --[[ value can be integer or table]]
  3753.         if type(above) == "table" then
  3754.             T:saveToLog("lib.returnToMidPoint("..#above..")", false)
  3755.             if #above > 0 then
  3756.                 local midPoint = math.floor(#above / 2)
  3757.                 if #above % 2 == 1 and  not outward then -- length is odd no
  3758.                     midPoint = math.ceil(#above / 2)
  3759.                     T:saveToLog("    midPoint adjusted "..midPoint..")", false)
  3760.                 end
  3761.                 T:saveToLog("    T:forward("..midPoint..")", false)
  3762.                 T:forward(midPoint)
  3763.             end
  3764.         else
  3765.             T:saveToLog("lib.returnToMidPoint("..above..")", false)
  3766.             if above > 0 then
  3767.                 T:saveToLog("    T:forward("..above..")", false)
  3768.                 T:forward(above)
  3769.             end
  3770.         end
  3771.         -- now back at starting point
  3772.     end
  3773.    
  3774.     -- Start here
  3775.     -- if "tk log d.." typed instead of "tk" will start logfile and display comments. read() will be activated for debugging
  3776.     T:saveToLog("Starting function clearMountainSide", false)
  3777.     local above = lib.firstRow(R)           -- outward depends on height eg 1-2 = false, 3-5 = true, 6-8 = false
  3778.     lib.returnToMidPoint(above)             -- return to mid first row of blocks
  3779.     for row = 1, R.width -1 do
  3780.         lib.nextRow(R)
  3781.     end
  3782.    
  3783.     return {}
  3784. end
  3785.  
  3786. local function clearSandWall(R) -- 81
  3787.     --dig down while on top of sand/red_sand/soul_sand
  3788.     local lib = {}
  3789.    
  3790.     function lib.checkAbove(height)
  3791.         if turtle.detectUp() then -- moved under a ledge
  3792.             T:go("B1U1")
  3793.             height = height - 1
  3794.         end
  3795.         return height
  3796.     end
  3797.    
  3798.     function lib.moveDown(height)
  3799.         blockType = T:getBlockType("down")
  3800.         while blockType:find("sand") ~= nil do
  3801.             T:down(1)
  3802.             height = height + 1
  3803.             blockType = T:getBlockType("down")
  3804.         end
  3805.         return height
  3806.     end
  3807.    
  3808.     function lib.moveForward(length)
  3809.         lib.digForward()
  3810.         T:forward(1)
  3811.         length = length + 1
  3812.         local blockType = T:getBlockType("forward")
  3813.         return length, blockType
  3814.     end
  3815.    
  3816.     function lib.digForward()
  3817.         while T:dig("forward") do
  3818.             while T:suck("forward") do end
  3819.             while T:suck("up") do end
  3820.         end
  3821.     end
  3822.    
  3823.     local moves  = 0
  3824.     local height = 0
  3825.     local length = 0
  3826.     local search = 0
  3827.     local reverse = false
  3828.     local blockType = T:getBlockType("down")
  3829.     if R.length == 0 then
  3830.         R.length = 64
  3831.     end
  3832.    
  3833.     print("Checking for sand below")
  3834.     while blockType:find("sand") == nil do --move forward until sand detected or 3 moves
  3835.         T:forward(1)
  3836.         search = search + 1
  3837.         blockType = T:getBlockType("down")
  3838.         if search > 3 then
  3839.             T:go("B"..search)
  3840.             return {"Unable to locate sand"}
  3841.         end
  3842.     end
  3843.     -- must be sand below
  3844.     height = lib.moveDown(height)   -- go down if sand below
  3845.     -- repeat until height == 0
  3846.     repeat -- starts at bottom of sand wall
  3847.         blockType = T:getBlockType("forward")
  3848.         if blockType:find("sand") ~= nil then -- sand in front
  3849.             length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
  3850.             if blockType == "" or  blockType:find("sand") ~= nil then -- sand or nothing in front
  3851.                 height = lib.moveDown(height)   -- go down if sand below
  3852.             end
  3853.         else -- solid block, air or water, not sand so move up
  3854.             if turtle.detect() then -- block in front
  3855.                 blockType = T:getBlockType("down")
  3856.                 if blockType:find("sand") ~= nil then -- sand below
  3857.                     T:dig("down")
  3858.                 end
  3859.                 T:up(1)
  3860.                 height = height - 1
  3861.             else -- air/water in front so move forward
  3862.                 if length < 60 then -- in case missing wall and in open ocean
  3863.                     length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
  3864.                     height = lib.checkAbove(height)
  3865.                 else -- already > monument length of 56
  3866.                     T:up(1)
  3867.                     height = height - 1
  3868.                 end
  3869.             end
  3870.         end
  3871.     until height == 0 or length == R.length
  3872.     blockType = T:getBlockType("down")
  3873.     if blockType:find("sand") ~= nil then -- sand below
  3874.         T:dig("down")
  3875.     end
  3876.     if height > 0 then -- finished as length ran out
  3877.         T:up(height)
  3878.     end
  3879.     -- stay at end of cleared wall unless user chose to return
  3880.     if R.data == "return" then
  3881.         T:go("R2F"..length.."R2")
  3882.     end
  3883.    
  3884.     return {}
  3885. end
  3886.  
  3887. local function clearSolid(R) -- 76
  3888.     --[[ direction = R.direction "up" or "down" ]]
  3889.     local height = 1
  3890.     local remaining = R.height
  3891.     local lib = {}
  3892.    
  3893.     function lib.singleLayer(R)
  3894.         R.up = false
  3895.         R.down = false
  3896.         clearRectangle(R)
  3897.     end
  3898.    
  3899.     function lib.doubleLayer(R)
  3900.         R.up = false
  3901.         R.down = false
  3902.         if R.direction == "up" then
  3903.             R.up = true
  3904.         else
  3905.             R.down = true
  3906.         end
  3907.         clearRectangle(R)
  3908.     end
  3909.        
  3910.     function lib.tripleLayer(R)
  3911.         -- turtle in centre layer
  3912.         R.up = true
  3913.         R.down = true
  3914.         clearRectangle(R)
  3915.     end
  3916.  
  3917.     R.silent = true
  3918.     if R.height < 3 then                            --1-3 layers only
  3919.         if R.height == 1 then                       --one layer only
  3920.             lib.singleLayer(R)
  3921.         elseif R.height == 2 then                   --2 layers only current + dig up/down
  3922.             lib.doubleLayer(R)
  3923.         end
  3924.     else -- 3 or more levels
  3925.         height = height + utils.move(R, 1)          -- move up/down 1 block for first layer
  3926.         while remaining >= 3 do                     -- min 3 levels
  3927.             lib.tripleLayer(R)
  3928.             remaining = remaining - 3
  3929.             if remaining == 0 then                  -- all finished
  3930.                 break
  3931.             elseif remaining == 1 then
  3932.                 height = height + utils.move(R, 2)  -- move up/down 2 blocks
  3933.                 lib.singleLayer(R)
  3934.             elseif remaining == 2 then
  3935.                 height = height + utils.move(R, 2)  -- move up/down 2 blocks
  3936.                 lib.doubleLayer(R)
  3937.             else
  3938.                 height = height + utils.move(R, 3)  -- move up/down 3 blocks
  3939.                 if remaining == 3 then
  3940.                     finish = true
  3941.                 end
  3942.             end
  3943.         end
  3944.     end
  3945.    
  3946.     if height > 1 then
  3947.         utils.move(R, height - 1, true) -- reverse direction
  3948.     end
  3949.    
  3950.     return {}
  3951. end
  3952.  
  3953. local function clearSandCube(R) -- 81
  3954.     R.data = ""
  3955.     for w = 1, R.width do
  3956.         clearSandWall(R)
  3957.         if w < R.width then
  3958.             if w % 2 == 1 then
  3959.                 T:go("R1F1R1")
  3960.             else
  3961.                 T:go("L1F1L1")
  3962.             end
  3963.         end
  3964.     end
  3965.    
  3966.     return {}
  3967. end
  3968.  
  3969. local function clearWall(R) -- 73
  3970.     local lib = {}
  3971.    
  3972.     function lib.move(direction, blocks, reverse)
  3973.         --[[ Move up or down by blocks count ]]
  3974.         if reverse == nil then
  3975.             reverse = false
  3976.         end
  3977.         if reverse then
  3978.             if direction == "down" then -- reverse direction
  3979.                 T:up(blocks)
  3980.             else
  3981.                 T:down(blocks)
  3982.             end
  3983.         else
  3984.             if direction == "up" then
  3985.                 T:up(blocks)
  3986.             else
  3987.                 T:down(blocks)
  3988.             end
  3989.         end
  3990.         return blocks
  3991.     end
  3992.    
  3993.     function lib.singleLayer(length)
  3994.         T:go("F"..length - 1)
  3995.     end
  3996.    
  3997.     function lib.doubleLayer(modifier, length)
  3998.         for i = 1, length do
  3999.             if i < length then
  4000.                 T:go("x"..modifier.."F1")
  4001.             else
  4002.                 T:go("x"..modifier)
  4003.             end
  4004.         end
  4005.     end
  4006.    
  4007.     function lib.tripleLayer(direction, length)
  4008.         for i = 1, length do
  4009.             if i < length then
  4010.                 T:go("x0x2F1")
  4011.             else
  4012.                 T:go("x0x2")
  4013.             end
  4014.         end
  4015.     end
  4016.    
  4017.    
  4018.     -- R.width preset to 1
  4019.     -- R.subChoice = 1 up / 2 down
  4020.     if R.height < 3 then
  4021.         R.silent = true
  4022.     end
  4023.     -- dig along and up/down for specified R.length
  4024.     local modifier = "0"
  4025.     local direction = "U"
  4026.     local outbound = true
  4027.     local height = 0
  4028.     if R.subChoice == 2 then
  4029.          modifier = "2"
  4030.          direction = "D"
  4031.     end
  4032.     if R.height == 1 then               -- single block so dig and return
  4033.         lib.singleLayer(R.length)
  4034.     elseif R.height == 2 then
  4035.         lib.doubleLayer(modifier, R.length)
  4036.     else                                -- 4 blocks or more. start with bulk 3 blocks
  4037.         local remaining = R.height
  4038.         T:go(direction.."1")            -- up 1 or down 1
  4039.         height = 1
  4040.         while remaining >= 3 do
  4041.             lib.tripleLayer(direction, R.length)
  4042.             remaining = remaining - 3
  4043.            
  4044.             if remaining == 0 then      -- no more, return home, already in position
  4045.                
  4046.             elseif remaining == 1 or remaining == 2 then
  4047.                 T:go(direction.."2")
  4048.                 height = height + 2
  4049.             else
  4050.                 T:go(direction.."3")
  4051.                 height = height + 3
  4052.                 if remaining >= 3 then -- another iteration
  4053.                     T:go("R2")
  4054.                     outbound = not outbound
  4055.                 end
  4056.             end
  4057.         end
  4058.         -- 0, 1 or 2 layers left
  4059.         if remaining > 0 then
  4060.             T:go("R2")
  4061.             outbound = not outbound
  4062.             if remaining == 1 then
  4063.                 lib.singleLayer(R.length)
  4064.             elseif remaining == 2 then
  4065.                 lib.doubleLayer(modifier, R.length)
  4066.             end
  4067.         end
  4068.     end
  4069.     if outbound then
  4070.         T:go("R2F"..R.length)
  4071.     else
  4072.         T:forward(1)
  4073.     end
  4074.     direction = "D" -- reverse direction
  4075.     if R.subChoice == 2 then
  4076.          direction = "U"
  4077.     end
  4078.     if height > 0 then
  4079.         T:go(direction..height.."R2")
  4080.     else
  4081.         T:go("R2")
  4082.     end
  4083.     return {}
  4084. end
  4085.  
  4086. local function convertWater(R) -- 88
  4087.     --[[
  4088.     if dry need enough buckets to place along (width + length - 1) / 2
  4089.     use 12 buckets
  4090.     start on floor + 1
  4091.     place slab down and water up along 2 edges. stay on this level
  4092.     return round same 2 edges removing slabs and and placing them 1 above
  4093.     placeUp water onto slabs on both edges
  4094.     repeat recover slabs, place 1 above , placeUp water
  4095.    
  4096.     for sloping water, place full area with slabs
  4097.     place sloping water on top of slabs
  4098.     remove slabs
  4099.    
  4100.     ]]
  4101.     local lib = {}
  4102.    
  4103.     function lib.checkStartPosition()
  4104.         --[[
  4105.         0 T             -- T=turtle, W=wall, S=source, F=flowing
  4106.         1 W|S|F|F|F|F|F -- sloping flowing water
  4107.         2 W|F|F|F|F|F|F -- blocks removed after placing flowing water above
  4108.         3 W|S|S|S|S|S|S -- original sources
  4109.         4 W|?|?|?|?|?|? -- may be sources
  4110.         ]]
  4111.         -- need to be on floor or R.height if specified
  4112.         local depth = 0
  4113.         local blockType = T:getBlockType("down")
  4114.         local isWaterUp, isSourceUp = T:isWater("up")
  4115.         local isWaterForward, isSourceForward = T:isWater("forward")
  4116.         local isWaterDown, isSourceDown = T:isWater("down")
  4117.         print("Block below is "..blockType)
  4118.         print("Water above is "..tostring(isWaterUp))
  4119.         print("Water forward is "..tostring(isWaterForward))
  4120.         print("Water below is "..tostring(isWaterDown))
  4121.         if blockType:find("water") == nil then -- on at least level 0
  4122.             print("Moving forward in 2 seconds...")
  4123.             sleep(2)
  4124.             T:forward(1)
  4125.             blockType = T:getBlockType("down")
  4126.             if blockType:find("water") ~= nil then
  4127.                 print("Water found. Going down to floor")
  4128.                 depth = -1
  4129.             else
  4130.                 T:down(1)
  4131.                 blockType = T:getBlockType("down")
  4132.                 if blockType:find("water") ~= nil then
  4133.                     depth = -2
  4134.                 else
  4135.                     return 0, "Not close to water. Aborting..."
  4136.                 end
  4137.             end
  4138.         end
  4139.         while turtle.down() do
  4140.             depth = depth + 1
  4141.         end
  4142.         local emptyBuckets = utils.getEmptyBucketCount()
  4143.         for i = depth, 0, -1 do
  4144.             if emptyBuckets > 0 then
  4145.                 lib.fillBuckets()
  4146.                 emptyBuckets = utils.getEmptyBucketCount()
  4147.             end
  4148.             turtle.up()
  4149.         end
  4150.        
  4151.         return depth, ""
  4152.     end
  4153.    
  4154.     function lib.fillBuckets()
  4155.         local emptyBuckets = utils.getEmptyBucketCount()
  4156.         local direction = "forward"-- start with forward
  4157.         local isWater, isSource, isIce = T:isWater(direction)
  4158.         if emptyBuckets > 0 then
  4159.             if not isSource then
  4160.                 direction = "down"
  4161.                 isWater, isSource, isIce = T:isWater(direction)
  4162.                 if not isSource then
  4163.                     direction = "up"
  4164.                     isWater, isSource, isIce = T:isWater(direction)
  4165.                     if not isSource then
  4166.                         direction = ""
  4167.                     end
  4168.                 end
  4169.             end
  4170.             if direction == "" then
  4171.                 print("Unable to locate water source")
  4172.             else
  4173.                 for i = 1, emptyBuckets do
  4174.                     if utils.fillBucket(direction) then
  4175.                         print("Bucket filled "..direction)
  4176.                         sleep(0.3)
  4177.                     else
  4178.                         print("Unable to fill bucket ".. i .." / "..emptyBuckets)
  4179.                     end
  4180.                 end
  4181.             end
  4182.         end
  4183.         return utils.getWaterBucketCount()
  4184.     end
  4185.    
  4186.     function lib.placeSlabs(length)
  4187.         for i = 1, length do
  4188.             T:place("slab", "down", false)
  4189.             if i < length then
  4190.                 T:forward(1)
  4191.             end
  4192.         end
  4193.     end
  4194.    
  4195.     function lib.placeSources(length, place)
  4196.         local moves = 1
  4197.         local waterBuckets = utils.getWaterBucketCount()
  4198.         -- place sources alternate positions + start and finish
  4199.         while moves < length do
  4200.             if place then
  4201.                 if T:placeWater("up") then
  4202.                     print("Placed source up")
  4203.                     waterBuckets = waterBuckets - 1
  4204.                 end
  4205.             end
  4206.             place = not place
  4207.             if moves < length then
  4208.                 T:forward(1)
  4209.                 moves = moves + 1
  4210.             end
  4211.             if waterBuckets == 0 then
  4212.                 T:down(1) -- break the slab below
  4213.                 waterBuckets = lib.fillBuckets()
  4214.                 T:up(1)
  4215.                 T:place("slab", "down", false)
  4216.             end
  4217.         end
  4218.         if T:placeWater("up") then -- end of length
  4219.             print("Placed final source up")
  4220.         end
  4221.         return place
  4222.     end
  4223.    
  4224.     function lib.moveSlabs(length)
  4225.         for i = 1, length do
  4226.             T:dig("down")
  4227.             T:up(1)
  4228.             T:place("slab", "down", true)
  4229.             if i < length then
  4230.                 T:forward(1)
  4231.                 T:down(1)
  4232.             end
  4233.         end
  4234.     end
  4235.    
  4236.     function lib.recoverSlabs(length)
  4237.         for i = 1, length do
  4238.             T:dig("down")
  4239.             if i < length then
  4240.                 T:forward(1)
  4241.             end
  4242.         end
  4243.     end
  4244.    
  4245.     local depth, message = lib.checkStartPosition()
  4246.     if message ~= "" then
  4247.         return {message}
  4248.     end
  4249.     local maxDepth = R.height
  4250.     local buckets = utils.getWaterBucketCount()
  4251.     R = utils.calculateDimensions(R) -- if R.width or R.length == 0
  4252.     T:down(depth)
  4253.     lib.placeSlabs(R.length)
  4254.     T:go("R1")
  4255.     lib.placeSlabs(R.width)
  4256.     T:go("R2")
  4257.    
  4258.     while depth > 0 do
  4259.         local place = true
  4260.         lib.fillBuckets()
  4261.         place = lib.placeSources(R.width, place)
  4262.         T:go("L1")
  4263.         place = lib.placeSources(R.length, place)
  4264.         lib.fillBuckets()
  4265.         T:go("R2")
  4266.         lib.moveSlabs(R.length) -- dig slab from below, move up and replace below
  4267.         T:go("R1F1D1")
  4268.         lib.moveSlabs(R.width - 1)
  4269.         T:go("R2") -- now moved up 1 layer
  4270.         depth = depth - 1
  4271.         if depth == 0 then
  4272.             place = lib.placeSources(R.width, true)
  4273.             T:go("L1")
  4274.             place = lib.placeSources(R.length, place)
  4275.             T:go("R2")
  4276.             lib.recoverSlabs(R.length)
  4277.             T:go("R1")
  4278.             lib.recoverSlabs(R.width)
  4279.         end
  4280.     end
  4281.    
  4282.     return {}
  4283. end
  4284.  
  4285. local function createBoatLift(R) -- 59 state:0=new, size:1=extend, side:0=left, 1=right
  4286.     -- build stepped lift with fencing gates and soul sand
  4287.     local lib = {}
  4288.    
  4289.     function lib.getWater(backToWater, downToWater)
  4290.         if backToWater > 0 then
  4291.             utils.goBack(backToWater)
  4292.         end
  4293.         if downToWater > 0 then
  4294.             T:down(downToWater)
  4295.         end
  4296.         T:getWater("down") -- take water from source
  4297.         sleep(0.2)
  4298.         T:getWater("down") -- take water from source
  4299.         if downToWater > 0 then
  4300.             T:up(downToWater)
  4301.         end
  4302.         if backToWater > 0 then
  4303.             T:forward(backToWater)
  4304.         end
  4305.     end
  4306.    
  4307.     --T:place(blockType, direction, leaveExisting, signText)
  4308.    
  4309.     local backToWater = 0
  4310.     local downToWater = 0
  4311.    
  4312.     T:go("R1F1L1")                                      -- over canal facing forward
  4313.     for h = 1, R.height do
  4314.         lib.getWater(backToWater, downToWater)          -- check water supplies, return to starting position
  4315.         T:go("L1C1 R1D1 L1C1 R1", false, 0, false)      -- place towpath, forward, down, place towpath, face forward
  4316.         T:place("soul", "down", false)              -- place soulsand down
  4317.         T:place("soul", "forward", false)           -- place soulsand forward
  4318.         T:go("R1F1C1L1", false, 0, false)               -- place right towpath face forward
  4319.         T:place("soul", "down", false)              -- place soulsand down
  4320.         T:place("soul", "forward", false)           -- place soulsand forward
  4321.         T:go("U1 R1C1 L1")                              -- place towpath, face forward
  4322.         T:placeWater("down")                            -- place water down
  4323.         utils.goBack(1)
  4324.         T:place("gate", "forward", false)           -- place fence gate
  4325.         T:go("R1C1 U1C1 D1 L2F1 C1R1 F1 L1C1R1")        -- over left soul sand
  4326.         T:placeWater("down")                            -- place water down
  4327.         utils.goBack(1)
  4328.         T:place("gate", "forward", false)           -- place fence gate
  4329.         T:go("U1 L1C1 R1F1 L1C1 R1x1")                  -- facing forward first unit complete
  4330.         T:go("R1F1 L1x1 R1C1")
  4331.         utils.goBack(1)
  4332.         T:go("L1F1")
  4333.         if backToWater == 0 then
  4334.             backToWater = 1
  4335.         end
  4336.         backToWater = backToWater + 1
  4337.         downToWater = downToWater + 1
  4338.     end
  4339.    
  4340.     -- now finish the canal
  4341.     lib.getWater(backToWater, downToWater)
  4342.     T:go("D1 L1C1 U1C1")                    -- build left towpath, facing towpath, above water level
  4343.     T:go("R1F1 L1C1 D1C1")                  -- move forward, build towpath, facing towpath ground level
  4344.     T:go("R1C1 R1F1 L1C1 R1C1 U1C1")        -- build right towpath, facing towpath, above water level
  4345.     T:go("R1F1 L1C1 D1C1 U1")               -- build right towpath next to gate, facing towpath, above water level
  4346.     T:placeWater("down")
  4347.     utils.goBack(1)
  4348.     T:go("L1F1")
  4349.     T:placeWater("down")  
  4350.    
  4351.     return {}
  4352. end
  4353.  
  4354. local function createBorehole(R)
  4355.     --[[go down to bedrock and return. Chart all blocks dug/ passed through]]
  4356.     local diary = {}
  4357.     local lib = {}
  4358.     local depth = R.height  -- eg 63 start position
  4359.     local moves = 0
  4360.     --R.height = current level
  4361.    
  4362.     function lib.addBlock(depth, blockType, diary)
  4363.         if blockType == "" then
  4364.             blockType = "air"
  4365.         end
  4366.         table.insert(diary, blockType)
  4367.        
  4368.        
  4369.         --[[if blockType ~= "" then
  4370.             local add = true
  4371.             for k,v in pairs(diary) do
  4372.                 if blockType == v then
  4373.                     add = false
  4374.                     break
  4375.                 end
  4376.             end
  4377.             if add then
  4378.                 diary[depth] = blockType
  4379.             end
  4380.         end]]
  4381.        
  4382.         return diary
  4383.     end
  4384.    
  4385.     function lib.processItem(item)
  4386.         if item:find("minecraft") ~= nil then
  4387.             return item:sub(11)
  4388.         end
  4389.         return item
  4390.     end
  4391.    
  4392.     function lib.writeReport(R, diary)
  4393.         local numLevels = #diary                        -- eg 125 levels
  4394.         local levelsPerCol = math.ceil(numLevels / 4)   -- eg 31.25 -> 32
  4395.         local lines = {}
  4396.         for l = 1, levelsPerCol do                      -- add 32 empty strings
  4397.             table.insert(lines, "")
  4398.         end
  4399.         local lineNo = 1
  4400.         for k, v in ipairs(diary) do
  4401.             local level = R.height - k                  -- eg 63 range 63 to -59
  4402.             local lev = "      "
  4403.             local item = lib.processItem(v)
  4404.             if level < -9 then
  4405.                 lev = tostring(level).."   "            -- "-10   " to "-59   "
  4406.             elseif level < 0 then              
  4407.                 lev = "-0"..math.abs(level).."   "      -- "-09   " to "-01   "
  4408.             elseif level < 10 then
  4409.                 lev = " 0"..level.."   "                -- " 01   " to " 09   "
  4410.             elseif level < 100 then
  4411.                 lev = " "..level.."   "                 -- " 10   " to " 99   "
  4412.             else
  4413.                 lev = " "..level.."  "                  -- " 100  " to " 319  "
  4414.             end
  4415.             local output = lev..item                    -- eg "-10   grass_block"
  4416.             if #output > 20 then                        -- eg "-10   some_long_block_name"  
  4417.                 output = output:sub(1, 20)              -- eg "-10   some_long_block_"
  4418.             else
  4419.                 output = menu.padRight(output, 20, " ") -- eg "-10   grass_block     "
  4420.             end
  4421.             lines[lineNo] = lines[lineNo]..output       -- add new entry to this line
  4422.             lineNo = lineNo + 1                         -- increase line no
  4423.             if lineNo > levelsPerCol then               -- past last line number
  4424.                 lineNo = 1                              -- reset to 1
  4425.             end
  4426.         end
  4427.        
  4428.         local fileName = "borehole"..os.getComputerID()..".txt"
  4429.         local handle = fs.open(fileName, "w")       --create file eg "borehole0.txt"
  4430.         handle.writeLine("Level Block         Level Block         Level Block         Level Block")
  4431.         for k,v in ipairs(lines) do
  4432.             handle.writeLine(v)
  4433.         end
  4434.        
  4435.         handle.close()
  4436.        
  4437.         return fileName
  4438.     end
  4439.    
  4440.     local blockType = T:getBlockType("down")
  4441.     while T:down(1) do
  4442.         depth = depth - 1
  4443.         moves = moves + 1
  4444.         if depth == R.depth then
  4445.             break
  4446.         end
  4447.         diary = lib.addBlock(depth, blockType, diary)
  4448.         blockType = T:getBlockType("down")
  4449.     end
  4450.     local fileName = lib.writeReport(R, diary)
  4451.     T:up(moves)
  4452.    
  4453.     return {"File '"..fileName.."' written"}
  4454. end
  4455.  
  4456. local function createBubbleLift(R) -- 15
  4457.     local lib = {}
  4458.    
  4459.     function lib.addLayer()
  4460.         T:go("F2 L1C1 R1C1 R1C1 L1", false, 0, true)
  4461.         turtle.back()
  4462.         T:dig("up") -- clear block above so completed lift can be found
  4463.         T:placeWater("forward")
  4464.         turtle.back()
  4465.         T:go("C1x0")       
  4466.     end
  4467.    
  4468.     function lib.addSign()
  4469.         turtle.back()
  4470.         T:placeWater("forward")
  4471.         T:go("L1B1")
  4472.         T:place("sign", "forward")
  4473.     end
  4474.    
  4475.     function lib.buildLift(toHeight)
  4476.         local built = lib.goToWater()       -- returns lift blocks already placed, total height of drop from starting point
  4477.         local toBuild = toHeight - built    -- no of blocks remaining to increase lift size
  4478.         local water = 0
  4479.         while toBuild > 0 do                -- at least 1 block height remaining
  4480.             water = lib.fillBuckets(toBuild, false) -- no of water buckets onboard (could be more than required)
  4481.             if water > toBuild then         -- more water than required
  4482.                 water = toBuild             -- reduce to correct amount
  4483.             end
  4484.             T:up(built)                     -- climb to top of existing lift
  4485.             while water > 0 and toBuild > 0 do
  4486.                 lib.addLayer()
  4487.                 water = water - 1
  4488.                 T:up(1)
  4489.                 toBuild = toBuild - 1
  4490.             end
  4491.             -- may still be some height to complete, but needs refill
  4492.             if toBuild > 0 then
  4493.                 built = lib.goToWater() --return to source
  4494.                 toBuild = toHeight - built
  4495.                 --lib.fillBuckets(toBuild)
  4496.             end
  4497.         end
  4498.     end
  4499.    
  4500.     function lib.cleanUp(fromHeight)
  4501.         local plug = false
  4502.         T:turnRight(2)
  4503.         for i = 1, fromHeight do
  4504.             plug = false
  4505.             if turtle.detect() then
  4506.                 plug = true
  4507.             end
  4508.             turtle.down()
  4509.             if plug then
  4510.                 T:place("stone", "up")
  4511.             end
  4512.         end
  4513.         T:go("D1 C1R1x1 R1C1 R1F1 R1x1 L2x1 L1C1 x1") -- delete water sources
  4514.         T:go("D1 C1R1x1 R1")
  4515.         local blockType = T:getBlockType("forward")
  4516.         if blockType:find("dirt") == nil and blockType:find("soul") == nil then -- not dirt or soul sand in front
  4517.             T:go("C1")
  4518.         end
  4519.         T:go("R1F1 R1x1 L2x1 L1C1 x1")
  4520.     end
  4521.    
  4522.     function lib.fillBuckets(toBuild, withSort)
  4523.         local emptySlots, water = lib.stackBuckets(withSort)-- gets no of empty slots + no of water buckets
  4524.         if water < toBuild then                     -- no of water buckets onboard less than required quantity
  4525.             for i = 1, toBuild do                   -- fill required no of buckets up to max space in inventory
  4526.                 if emptySlots == 0 then             -- inventory full
  4527.                     break
  4528.                 else
  4529.                     if T:getWater("down") then
  4530.                         water = water + 1
  4531.                         sleep(0.5)
  4532.                     end
  4533.                 end
  4534.                 emptySlots = lib.getEmptySlots()
  4535.             end
  4536.         end
  4537.        
  4538.         return water
  4539.     end
  4540.    
  4541.     function lib.getEmptySlots()
  4542.         local empty = 0
  4543.         for i = 1, 16 do
  4544.             if turtle.getItemCount(i) == 0 then
  4545.                 empty = empty + 1
  4546.             end
  4547.         end
  4548.         return empty
  4549.     end
  4550.    
  4551.     function lib.goToWater()
  4552.         local built = 0 -- measures completed lift height
  4553.         while turtle.down() do -- takes turtle to bottom of water source
  4554.             if turtle.detect() then
  4555.                 built = built + 1
  4556.             end
  4557.         end
  4558.         T:up(1) -- above watersource ready to fill buckets
  4559.         -- height = height - 1
  4560.         -- built = built - 1 not required as next block is water source: not detected
  4561.         return built -- , height
  4562.     end
  4563.    
  4564.     function lib.stackBuckets(withSort)
  4565.         if withSort == nil then withSort = false end
  4566.         local data = {}
  4567.         local bucketSlot = 0
  4568.         local emptySlots = 0
  4569.         local water = 0
  4570.         if withSort then
  4571.             T:sortInventory()
  4572.         end
  4573.         for i = 1, 16 do
  4574.             -- find first empty bucket
  4575.             if turtle.getItemCount(i) > 0 then
  4576.                 data = turtle.getItemDetail(i)
  4577.                 if data.name == "minecraft:bucket" then
  4578.                     if bucketSlot == 0 then
  4579.                         bucketSlot = i
  4580.                     else
  4581.                         turtle.select(i)
  4582.                         turtle.transferTo(bucketSlot)
  4583.                     end
  4584.                 elseif data.name == "minecraft:water_bucket" then
  4585.                     water = water + 1
  4586.                 end
  4587.             else
  4588.                 emptySlots = emptySlots + 1
  4589.             end
  4590.         end
  4591.         return emptySlots, water
  4592.     end
  4593.    
  4594.    
  4595.     T:go("C1R1")                                                -- place block next to ladder support block, turn right to check ladder
  4596.     local blockType = T:getBlockType("forward")                 -- Is there a ladder to the right?
  4597.     if blockType:find("ladder") == nil then
  4598.         T:go("C1L2")                                            -- Place block as ladder not present
  4599.     else                                                        -- ladder present
  4600.         T:go("L2")                                              -- ready to check other side
  4601.     end
  4602.     blockType = T:getBlockType("forward")
  4603.     if blockType:find("ladder") == nil then
  4604.         T:go("C1R1")
  4605.     else
  4606.         T:go("R1")
  4607.     end
  4608.     blockType = T:getBlockType("down")
  4609.     local dirt = "minecraft:dirt"
  4610.     if T:getItemSlot("minecraft:soul_sand") > 0 then
  4611.         dirt = "minecraft:soul_sand"
  4612.     end
  4613.     if blockType:find("bedrock") ~= nil then
  4614.         utils.goBack(1)
  4615.         T:place(dirt, "forward", false)                     -- placed at end of potential water source, next to ladder
  4616.     else
  4617.         T:place(dirt, "down", false)                        -- placed in ground, next to ladder
  4618.         utils.goBack(1)
  4619.         T:placeWater("forward")                             -- place extra water source
  4620.     end
  4621.     T:go("R1C1 R2C1 L1F1C2 R1C1 L2C1 R1F1C2 R1C1 L1C1 L1C1 L1F1", false, 0, true)
  4622.     -- ready for water sources to be placed
  4623.     T:placeWater("forward")                                 -- place front water source
  4624.     T:turnRight(2)                                          -- facing backward
  4625.     T:placeWater("forward")                                 -- place back water source
  4626.     T:go("R2U1")                                            -- facing forward, U1, above centre of water source
  4627.     lib.fillBuckets(R.height, true)                         -- fill as many buckets as required or until inventory full, sort inventory as well
  4628.     local nextToLadder = false
  4629.     --T:go("F2R1")
  4630.     T:go("x0F1 x0F1C1 R1")                                  -- move forward 2 taking out blocks above, plug behind soul sand
  4631.     if T:getBlockType("forward"):find("ladder") == nil then -- no ladder here
  4632.         T:turnLeft(2)
  4633.         if T:getBlockType("forward"):find("ladder") ~= nil then -- ladder here
  4634.             nextToLadder = true
  4635.         end
  4636.         T:turnRight(1)
  4637.     else
  4638.         nextToLadder = true
  4639.         T:turnLeft(1)
  4640.     end
  4641.     -- now above soul sand, facing forward
  4642.     if nextToLadder then                                -- if nextToLadder, no need for signs
  4643.         utils.goBack(2)                                 -- return to source centre
  4644.     else
  4645.         T:go("F2 L1C1R1C1R1C1L1", false, 0, true)       -- prepare layer 1
  4646.         lib.addSign()
  4647.         T:go("U1F1R1F1 L1C1R1C1R1C1L1", false, 0, true) -- prepare layer 2
  4648.         lib.addSign()
  4649.         T:go("L1F1 R1F1R1", false, 0, true)             -- above source, level 2
  4650.     end
  4651.     -- ready to build lift
  4652.     lib.buildLift(R.height - 1)
  4653.     lib.cleanUp(R.height - 1)
  4654.    
  4655.     return {"Bubble lift created", "Check correct operation", "Check exit before using" }
  4656. end
  4657.  
  4658. local function createBubbleTrap(R) -- 34
  4659.     --[[
  4660.     Replace floor of existing volume of water with soulsand
  4661.     Used in river biome for squid farm. Area should be enclosed
  4662.     with solid walls surface to floor.
  4663.     Usually 7 blocks wide
  4664.     ]]
  4665.     local lib = {}
  4666.    
  4667.     function lib.clearDown(depth)
  4668.         while utils.clearVegetation("down") do
  4669.             T:down(1)
  4670.             depth = depth + 1
  4671.         end
  4672.         T:place("soul_sand", "down", false)
  4673.         return depth
  4674.     end
  4675.    
  4676.     function lib.clearLength(length, depth)
  4677.         local moves = 0
  4678.         while moves < length - 1 do
  4679.             if utils.clearVegetation("forward") then
  4680.                 T:forward(1)
  4681.                 moves = moves + 1
  4682.                 depth = lib.clearDown(depth) -- go down if in water/air
  4683.                 if moves >= length - 1 then
  4684.                     return depth
  4685.                 end
  4686.             else -- block in front
  4687.                 local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
  4688.                 while not waterAhead do     -- solid block in front
  4689.                     T:up(1)
  4690.                     depth = depth - 1
  4691.                     if depth < 1 then
  4692.                         return 0
  4693.                     end
  4694.                     waterAhead = utils.clearVegetation("forward")
  4695.                 end
  4696.             end
  4697.         end
  4698.  
  4699.         return depth
  4700.     end
  4701.    
  4702.     function lib.turn(facingForward, depth)
  4703.         local direction = "R"
  4704.         if not facingForward then
  4705.             direction = "L"
  4706.         end
  4707.         T:go(direction.. 1)
  4708.         if utils.clearVegetation("forward") then
  4709.             T:forward(1)
  4710.             depth = depth + lib.clearDown(depth)
  4711.         else
  4712.             while not utils.clearVegetation("forward") do
  4713.                 T:up(1)
  4714.                 depth = depth - 1
  4715.             end
  4716.         end
  4717.         T:go(direction.. 1)
  4718.        
  4719.         return depth
  4720.     end
  4721.    
  4722.     local depth = 0
  4723.     local length = 0
  4724.     local width = 0
  4725.     local outbound = true
  4726.     local facingForward = true
  4727.     local inWater, onWater = utils.getWaterStatus()
  4728.     inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,true) -- move into water, max descent 2
  4729.     if R.length == 0 then
  4730.         R.length = lib.getLength()
  4731.     end
  4732.     if R.width == 0 then
  4733.         T:turnRight(1)
  4734.         R.width = lib.getLength()
  4735.         T:turnLeft(1)
  4736.     end
  4737.     -- go down to floor
  4738.     depth = lib.clearDown(depth)
  4739.     while width < R.width do
  4740.         -- now on floor, move along sea/river bed following contour
  4741.         depth = lib.clearLength(R.length, depth)
  4742.         width = width + 1
  4743.         -- now turn and repeat
  4744.         if width < R.width then
  4745.             depth = lib.turn(facingForward, depth)
  4746.             facingForward = not facingForward
  4747.         end
  4748.     end
  4749.     -- finished so return to surface
  4750.     T:up(1) -- up 1 to check for water below
  4751.     while T:isWater("down") do
  4752.         T:up(1)
  4753.     end
  4754.    
  4755.     return {}
  4756. end
  4757.  
  4758. local function createCorridor(R) -- 52
  4759.     --[[create a corridoor 2 blocks high, with floor and ceiling guaranteed
  4760.     T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)]]
  4761.     local lib = {}
  4762.    
  4763.     function lib.continue(R, currentSteps, totalSteps)
  4764.         if not R.silent then
  4765.             if currentSteps >= 64 and R.length == 0 then
  4766.                 -- request permission to continue if infinite
  4767.                 T:clear()
  4768.                 print("Completed "..totalSteps..". Ready for 64 more")
  4769.                 print("Do you want to continue? (y/n)")
  4770.                 response = read()
  4771.                 if response:lower() ~= "y" then
  4772.                     return true, 0
  4773.                 else
  4774.                     return false, currentSteps
  4775.                 end
  4776.             end
  4777.         end
  4778.         return true, currentSteps
  4779.     end
  4780.    
  4781.     function lib.seal()
  4782.         local blockType = T:getBlockType("forward")
  4783.         if blockType:find("water") ~= nil then
  4784.             T:place("stone", "forward", false)
  4785.             return "water"  -- water found
  4786.         elseif blockType:find("lava") ~= nil then
  4787.             T:place("stone", "forward", false)
  4788.             return "lava"   -- lava found
  4789.         end
  4790.         return ""   -- no water or lava
  4791.     end
  4792.    
  4793.     function lib.checkSeal(R)
  4794.         local fluidType = ""
  4795.         if R.data == "seal" then        -- check for lava/water at the sides
  4796.             T:turnRight(1)
  4797.             fluidType = lib.seal()      -- could be "", "water", "lava"
  4798.             T:turnLeft(2)
  4799.             local blockType = lib.seal()
  4800.             if fluidType == "" then     -- no water / lava so far
  4801.                 fluidType = blockType   -- could be "", "water", "lava"
  4802.             end
  4803.             T:turnRight(1)
  4804.         end
  4805.         return fluidType                -- could be "", "water", "lava"
  4806.     end
  4807.    
  4808.     function lib.placeTorch(R, torchSpaces, totalSteps)
  4809.         if R.torchInterval > 0 then -- torches onboard
  4810.             if torchSpaces == R.torchInterval then -- time to place another torch
  4811.                 if totalSteps < R.length then -- not at end of run
  4812.                     if T:getItemSlot("minecraft:torch") > 0 then
  4813.                         T:place("minecraft:torch", "down")
  4814.                     end
  4815.                     torchSpaces = 1
  4816.                 end
  4817.             end
  4818.         end
  4819.         return torchSpaces -- original value or 1
  4820.     end
  4821.    
  4822.     local currentSteps = 0                  -- counter for infinite length. pause every 64 blocks
  4823.     local totalSteps = 0                    -- counter for all steps so far
  4824.     local torchSpaces = R.torchInterval     -- if torches present, counter to place with 8 blocks between
  4825.     local fluidType = ""
  4826.     local damLength = 0
  4827.     local damStarted = false
  4828.     local doContinue = true
  4829.     if T:getItemSlot("minecraft:torch") == 0 then
  4830.         R.torchInterval = 0 -- set to default 9 in getTask()
  4831.     end
  4832.     for steps = 1, R.length do
  4833.         -- starts on floor of tunnel
  4834.         doContinue, currentSteps = lib.continue(R, currentSteps, totalSteps) -- continue tunnelling?
  4835.         if not doContinue then
  4836.             break
  4837.         end
  4838.         T:go("C2U1C0", false, 0, true)      -- place floor, up 1, place ceiling
  4839.         fluidType = lib.checkSeal(R)        -- if R.data == "seal", check for water/lava at ceiling level
  4840.         if fluidType == "" then -- either R.data ~= "seal" or no fluid found
  4841.             torchSpaces = lib.placeTorch(R, torchSpaces, totalSteps) -- original value or 1 if torch placed
  4842.             T:go("F1D1")
  4843.         elseif fluidType == "water" then
  4844.             T:go("F1R2 C1D1 C1L2", false, 0, true)
  4845.             damStarted = true
  4846.             damLength = damLength + 1
  4847.         else    --lava
  4848.             T:go("F1D1")
  4849.         end
  4850.         blockType = lib.checkSeal(R)
  4851.         if blockType ~= "" then
  4852.             fluidType = blockType
  4853.         end
  4854.         currentSteps = currentSteps + 1
  4855.         totalSteps = totalSteps + 1
  4856.         torchSpaces = torchSpaces + 1
  4857.         if damStarted and fluidType == "" then -- was in water, but no more
  4858.             T:go("R2 F"..damLength + 1 .."U1L2F"..damLength + 1 .."D1")
  4859.             damStarted = false
  4860.         end
  4861.     end
  4862.     if fluidType ~= "" then -- water or lava found while tunnelling
  4863.         T:go("U1C0", false, 0, true)
  4864.         lib.checkSeal(R)
  4865.         T:go("C1", false, 0, true)
  4866.         T:down(1)
  4867.     end
  4868.     return {}
  4869. end
  4870.  
  4871. local function createDragonTrap() -- 49
  4872.     local lib = {}
  4873.    
  4874.     function lib.attack()
  4875.         local totalHitsF = 0
  4876.         local totalHitsU = 0
  4877.         local totalHitsD = 0
  4878.         while true do
  4879.             local hitF = false
  4880.             local hitU = false
  4881.             local hitD = false
  4882.             if turtle.attackUp() then
  4883.                 hitU = true
  4884.                 totalHitsU = totalHitsU + 1
  4885.             end
  4886.             if turtle.attackDown() then
  4887.                 hitD = true
  4888.                 totalHitsD = totalHitsD + 1
  4889.             end
  4890.             if turtle.attack() then
  4891.                 hitF = true
  4892.                 totalHitsF = totalHitsF + 1
  4893.             end
  4894.             if hitF or hitU or hitD then
  4895.                 print("hits forward: "..totalHitsF..", up: "..totalHitsU..", down: "..totalHitsD)
  4896.             end
  4897.         end
  4898.     end
  4899.     -- build up 145 blocks with ladders
  4900.     T:clear()
  4901.     menu.colourPrint("Press Enter to start 1 minute delay\n", colors.red)
  4902.     menu.colourPrint("Run to island centre across the bridge\n", colors.orange)
  4903.     menu.colourPrint("You have already made the bridge?...", colors.lime)
  4904.     read()
  4905.     for t = 60, 1, -1 do
  4906.         sleep(1)
  4907.         T:clear()
  4908.         io.write("Starting in "..t.. " seconds ")
  4909.     end
  4910.     for i = 1, 145 do
  4911.         T:go("U1C2")
  4912.         turtle.back()
  4913.         T:place("minecraft:ladder", "down")
  4914.         turtle.forward()
  4915.     end
  4916.     T:go("R2F1C1 L1C1 L2C1 R1")
  4917.     for i = 1, 100 do
  4918.         T:go("F1C2U1C0D1")
  4919.     end
  4920.     T:forward(1)
  4921.     T:place("minecraft:obsidian", "down")
  4922.     T:go("R2F1x2R2")
  4923.     T:placeWater("forward")
  4924.     T:go("R2F6R2")
  4925.     lib.attack()
  4926.    
  4927.     return {}
  4928. end
  4929.    
  4930. local function createEnderTower(stage) -- 66
  4931.     --[[ lower base = stage 1, upper base = 2, tower = 3 ]]
  4932.     local lib = {}
  4933.     --[[ go(path, useTorch, torchInterval, leaveExisting, preferredBlock) ]]
  4934.     function lib.getEmptySlots()
  4935.         local empty = 0
  4936.         for i = 1, 16 do
  4937.             if turtle.getItemCount(i) == 0 then
  4938.                 empty = empty + 1
  4939.             end
  4940.         end
  4941.         return empty
  4942.     end
  4943.  
  4944.     function lib.getStone(direction, stacks)
  4945.         --[[ get block user wants to use ]]
  4946.         local suck = turtle.suck   
  4947.         if direction == "down" then
  4948.             suck = turtle.suckDown
  4949.         end
  4950.         if T:getBlockType(direction) == "minecraft:chest" then
  4951.             T:sortInventory()
  4952.             local slot = T:getFirstEmptySlot() --find spare slot
  4953.             if slot > 0 then --empty slot found
  4954.                 turtle.select(1)
  4955.                 if stacks == 0 then
  4956.                     while suck() do end
  4957.                 else
  4958.                     for i = 1, stacks do -- get # stacks of stone from chest
  4959.                         suck()
  4960.                     end
  4961.                 end
  4962.                 if T:getSlotContains(slot) == "" then
  4963.                     return T:getMostItem()              -- empty chest
  4964.                 else
  4965.                     return T:getSlotContains(slot)      -- use this as default building block
  4966.                 end
  4967.             else
  4968.                 return T:getMostItem()              -- full inventory
  4969.             end
  4970.         else
  4971.             return T:getMostItem()              -- no chest
  4972.         end
  4973.     end
  4974.    
  4975.     function lib.stackBuckets()
  4976.         local data = {}
  4977.         local bucketSlot = 0
  4978.         local emptySlots = 0
  4979.         local water = 0
  4980.         T:sortInventory()
  4981.         for i = 1, 16 do
  4982.             -- find first empty bucket
  4983.             if turtle.getItemCount(i) > 0 then
  4984.                 data = turtle.getItemDetail(i)
  4985.                 if data.name == "minecraft:bucket" then
  4986.                     if bucketSlot == 0 then
  4987.                         bucketSlot = i
  4988.                     else
  4989.                         turtle.select(i)
  4990.                         turtle.transferTo(bucketSlot)
  4991.                     end
  4992.                 elseif data.name == "minecraft:water_bucket" then
  4993.                     water = water + 1
  4994.                 end
  4995.             else
  4996.                 emptySlots = emptySlots + 1
  4997.             end
  4998.         end
  4999.         return emptySlots, water
  5000.     end
  5001.    
  5002.     function lib.countWaterBuckets()
  5003.         local data = {}
  5004.         local buckets = 0
  5005.         for i = 1, 16 do
  5006.             data = turtle.getItemDetail(i)
  5007.             if data.name == "minecraft:water_bucket" then
  5008.                 buckets = buckets + 1
  5009.             end
  5010.         end
  5011.         return buckets
  5012.     end
  5013.    
  5014.     function lib.baseRun(preferredBlock, count, turn)
  5015.         for i = 1, count do
  5016.             T:go("C2F1", false, 0, false, preferredBlock)
  5017.         end
  5018.         T:go("C2"..turn, false, 0, false, preferredBlock)
  5019.     end
  5020.    
  5021.     function lib.outsideRun(preferredBlock)
  5022.         T:place("fence", "down", false)
  5023.         T:forward(1)
  5024.         T:place(preferredBlock, "down", false)
  5025.         T:forward(1)
  5026.         T:place(preferredBlock, "down", false)
  5027.         T:forward(2)
  5028.         T:place(preferredBlock, "down", false)
  5029.     end
  5030.    
  5031.     function lib.signRun(preferredBlock ,message)
  5032.         T:place(preferredBlock, "down", false)
  5033.         T:forward(4)
  5034.         T:place(preferredBlock, "down", false)
  5035.         turtle.back()
  5036.         turtle.back()
  5037.         T:down(1)
  5038.         T:place("sign", "forward", false, message)
  5039.         T:go("U1F2")
  5040.     end
  5041.    
  5042.     function lib.goToWater(height)
  5043.         local built = 0 -- measures completed lift height
  5044.         while turtle.down() do -- takes turtle to bottom of water source
  5045.             height = height + 1
  5046.             if turtle.detect() then
  5047.                 built = built + 1
  5048.             end
  5049.         end
  5050.         T:up(1) -- above watersource assuming it is 1-1.5 blocks deep
  5051.         height = height - 1
  5052.         -- built = built - 1 not required as next block is water source: not detected
  5053.         return built, height
  5054.     end
  5055.    
  5056.     function lib.fillBuckets(toBuild)
  5057.         local emptySlots, water = lib.stackBuckets() -- gets no of empty slots + no of water buckets
  5058.         if water < toBuild then -- no of water buckets onboard less than required quantity
  5059.             for i = 1, toBuild do -- fill required no of buckets up to max space in inventory
  5060.                 emptySlots = lib.getEmptySlots()
  5061.                 if emptySlots == 0 then -- inventory full
  5062.                     break
  5063.                 else
  5064.                     if T:getWater("down") then
  5065.                         water = water + 1
  5066.                         sleep(0.5)
  5067.                     end
  5068.                 end
  5069.             end
  5070.         end
  5071.        
  5072.         return water
  5073.     end
  5074.    
  5075.     function lib.buildLift(preferredBlock)
  5076.         local built = 0 -- measures completed lift height
  5077.         local height = 0 -- measures total height from starting position
  5078.         built, height = lib.goToWater(height) -- returns lift blocks already placed, total height of drop from starting point
  5079.         local toBuild = height - built -- no of blocks to increase lift size
  5080.         while toBuild > 0 do -- at least 1 block height remaining
  5081.             local water = lib.fillBuckets(toBuild) -- no of water buckets onboard (could be more than required)
  5082.             if water > toBuild then
  5083.                 water = toBuild
  5084.             end
  5085.             while turtle.detect() do -- climb to top of existing lift
  5086.                 turtle.up()
  5087.                 height = height - 1
  5088.             end
  5089.             T:forward(1)
  5090.             for i = 1, water do -- build lift by no of water buckets
  5091.                 if T:placeWater("forward")  then
  5092.                     T:up(1)
  5093.                     height = height - 1
  5094.                     toBuild = toBuild - 1
  5095.                     T:place(preferredBlock, "down", false)
  5096.                 end
  5097.             end
  5098.             turtle.back()
  5099.             -- may still be some height to complete, but needs refill
  5100.             if toBuild > 0 then
  5101.                 lib.goToWater(0) --return to source
  5102.                 lib.fillBuckets(toBuild)
  5103.             end
  5104.         end
  5105.         if height > 0 then -- if any remaining distance
  5106.             T:up(height)
  5107.         end
  5108.        
  5109.     end
  5110.    
  5111.     function lib.buildSection(preferredBlock, solid)
  5112.         -- builds a section without any blocks in the centre
  5113.         -- second layer of each section end walls have fence posts
  5114.         T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- first side solid row
  5115.         if solid then -- first layer of each section
  5116.             T:go("F1C2 F1R1", false, 0, false, preferredBlock) -- top side solid row
  5117.         else
  5118.             T:go("F1") -- top side solid row
  5119.             if not T:place("fence", "down", false) then-- first side
  5120.                 T:place(preferredBlock, "down", false)
  5121.             end
  5122.             T:go("F1R1") -- top side solid row
  5123.         end
  5124.         T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- far side solid row
  5125.         T:go("F1C2 F1R1U1", false, 0, false, preferredBlock) -- bottom side solid row
  5126.     end
  5127.     --[[
  5128.         clsTurtle methods:
  5129.         clsTurtle.place(self, blockType, damageNo, direction, leaveExisting)
  5130.         clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
  5131.     ]]
  5132.     -- remove 1 stack stone from chest
  5133.     local preferredBlock = lib.getStone("down", 1) -- use this as default building block
  5134.     if stage == 1 then
  5135.         -- build base floor
  5136.         --T:go("R2F2R1F3R1", false, 0, false, preferredBlock)
  5137.         T:go("R2F1C2R1F1C2F1C2F1C2R1", false, 0, false, preferredBlock)
  5138.         for i = 1, 2 do
  5139.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  5140.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  5141.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  5142.         end
  5143.         -- move back to centre, build water source, with soul sand at base of first source
  5144.         --T:go("R1F3L1C2F1C2F2D1", false, 0, false, preferredBlock) --just behind chest, 1 below ground level
  5145.         T:go("R1F3L1F2C2F1D1", false, 0, false, preferredBlock) --1 block behind chest, 1 below ground level
  5146.         T:place("minecraft:soul_sand", "down", false) -- over block 1 of water source
  5147.         T:go("F1C2F1C2", false, 0, false, preferredBlock) -- over block 2 of water source
  5148.         T:go("F1C2U1C2", false, 0, false, preferredBlock) -- over block 4 of water source
  5149.         T:go("F1C2F1C2R2F5R2", false, 0, false, preferredBlock) -- over block 1 of water source
  5150.         T:placeWater("down")
  5151.         T:forward(2) -- over block 3 of water source
  5152.         T:placeWater("down")
  5153.         turtle.back() -- over block 2 of water source
  5154.         T:getWater("down")
  5155.         T:go("F2D1R2C2") -- over block 4 of water source
  5156.         T:go("U1", false, 0, false, preferredBlock)
  5157.         T:placeWater("down")
  5158.         T:forward(4)
  5159.         lib.stackBuckets() -- put all buckets in same slot
  5160.         T:dropItem("minecraft:dirt", "up", 0) -- drop dirt up:  clsTurtle.dropItem(self, item, direction, keepAmount)
  5161.         preferredBlock = lib.getStone("down", 6)
  5162.         T:go("R1F2R1U1") -- move to start position
  5163.         for i = 1, 2 do
  5164.             -- build first level of tower: 2 x outside run, 2 x sign run
  5165.             lib.outsideRun(preferredBlock)
  5166.             if i == 1 then -- place door
  5167.                 T:go("L1F1L1F1L1D1")
  5168.                 T:place("door", "forward", false)
  5169.                 T:go("U1L1F1R1F1L1")
  5170.             end
  5171.             T:go("R1F1R1")
  5172.             lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
  5173.             T:go("L1F1L1C2", false, 0, false, preferredBlock)
  5174.             T:forward(4) -- miss out centre block
  5175.             T:place(preferredBlock, "down", false)
  5176.             T:go("R1F1R1")
  5177.             lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
  5178.             T:go("L1F1L1")
  5179.             lib.outsideRun(preferredBlock)
  5180.             if i == 1 then -- layer 1
  5181.                 T:go("R1F1R1F1R1D1") -- place door
  5182.                 T:place("door", "forward", false)
  5183.                 T:go("U1 R1F1 L1F5 L1U1 F2D1  F2R2 U1") -- go over door
  5184.             else -- layer 2
  5185.                 T:go("L1F5L1F6R2U1") -- over corner of lower platform
  5186.             end
  5187.         end
  5188.         for i = 1, 2 do -- build both sides of platform, leave centre missing
  5189.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  5190.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  5191.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  5192.         end
  5193.         T:go("R1F3L1C2F1C2F1C2F4C2F1C2F1C2", false, 0, false, preferredBlock) --fill in centre row
  5194.         --T:go("R2F6R1F1R1U1") -- go to start of tower base
  5195.         T:go("R2F7R2D3") -- go to start on top of chest
  5196.         T:sortInventory()
  5197.     elseif stage == 2 then
  5198.         -- start on top of chest, should have sufficient stone in inventory
  5199.         T:go("U3L1F1R1F1U1") -- go to start of tower base
  5200.         for i = 1, 7 do -- build 14 block high tower
  5201.             lib.buildSection(preferredBlock, false)
  5202.             lib.buildSection(preferredBlock, true)
  5203.         end
  5204.         T:go("R2F4R1F4R1", false, 0, false, preferredBlock) -- build upper platform (154 blocks remaining)
  5205.         for i = 1, 2 do -- build both sides of upper platform, leave centre missing
  5206.             lib.baseRun(preferredBlock, 12, "R1F1R1")
  5207.             lib.baseRun(preferredBlock, 12, "L1F1L1")
  5208.             lib.baseRun(preferredBlock, 12, "R1F1R1")
  5209.             lib.baseRun(preferredBlock, 12, "L1F1L1")
  5210.             lib.baseRun(preferredBlock, 12, "R1F6R1")
  5211.         end
  5212.         T:go("R1F5 L1C2 F1C2 F1C2 F1C2 F1C2 F4C2 F1C2 F1C2 F1C2 F1C2 ", false, 0, false, preferredBlock) --fill in centre row
  5213.         T:go("R2F5") -- return to drop area
  5214.         lib.buildLift(preferredBlock) -- build bubble lift
  5215.         T:go("F3R1F1R1U1") -- go to start of tower base
  5216.         T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock)      -- left side layer 21
  5217.         T:go("F2C2 F2C2 L1F1L1", false, 0, false, preferredBlock)   -- centre layer 21
  5218.         T:go("C2F4 C2R2U1", false, 0, false, preferredBlock)        -- right side layer 21
  5219.         T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock)      -- right side layer 22
  5220.         T:place("fence", "down", false)                         -- fence centre of bottom side layer 22
  5221.         T:go("F2C2 F2L1F1L1", false, 0, false, preferredBlock)      -- centre layer 22
  5222.         T:go("C2F4 C2R2F2L1F1R2D2", false, 0, false, preferredBlock) --ready to place ladder
  5223.         T:place("ladder", "forward", false)
  5224.         T:up(1)
  5225.         T:place("ladder", "forward", false)
  5226.         --T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
  5227.         T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
  5228.         for i = 1, 2 do -- build both sides of platform, leave centre missing
  5229.             lib.baseRun(preferredBlock, 8, "R1F1R1")
  5230.             lib.baseRun(preferredBlock, 8, "L1F1L1")
  5231.             lib.baseRun(preferredBlock, 8, "R1F4R1")
  5232.         end
  5233.         T:go("R1F3 L1C2 F1C2 F1C2 F1", false, 0, false, preferredBlock) --fill in centre row
  5234.         T:place("minecraft:soul_sand", "down", false)
  5235.         T:go("F1C2 F2C2 F1C2 F1C2", false, 0, false, preferredBlock)
  5236.         T:go("R2F6R1F1R1U1") -- go to start of tower base
  5237.         -- build 2 levels, finish signs and ladders
  5238.         T:go("C2F2 R1D2 U1", false, 0, false, preferredBlock)
  5239.         T:place("ladder", "down", false)
  5240.         T:turnRight(1)
  5241.         T:place("sign", "forward", false, "UP\n^\n|\n|")
  5242.         T:go("U1R2F2C2 R1F2C2 R1", false, 0, false, preferredBlock) --top right corner
  5243.         T:go("F4C2B2D1", false, 0, false, preferredBlock)
  5244.         T:place("sign", "forward", false, "UP\n^\n|\n|")
  5245.         T:go("U1F2R1F1C2F1R1U1", false, 0, false, preferredBlock) --ready for second level
  5246.         T:go("C2F2 R2D1", false, 0, false, preferredBlock)
  5247.         T:place("sign", "forward", false, "UP\n^\n|\n|")
  5248.         T:go("U1R2F2C2R1", false, 0, false, preferredBlock) --top left corner
  5249.         T:go("F1R1C2F4C2", false, 0, false, preferredBlock) --mid bottom row
  5250.         T:go("L1F1L1C2", false, 0, false, preferredBlock) -- bottom right corner
  5251.         T:go("F2R2D1", false, 0, false, preferredBlock)
  5252.         T:place("sign", "forward", false, "UP\n^\n|\n|")
  5253.         T:go("U1R2F2C2", false, 0, false, preferredBlock) -- top right corner
  5254.         -- return to chest
  5255.         T:go("L1F1L1 F5D23R2", false, 0, false, preferredBlock) -- return to chest
  5256.         T:sortInventory()
  5257.     elseif stage == 3 then
  5258.         --[[ move to top of structure
  5259.         | 4 |
  5260.         |3 5|
  5261.         | X |
  5262.         |2 6|
  5263.         | 1 |
  5264.         ]]
  5265.         local towerHeight = 128 -- even no only suggest 128
  5266.         while turtle.detect() do
  5267.             turtle.up()
  5268.         end
  5269.         T:go("F1U1", false, 0, false, preferredBlock) -- return to finish tower
  5270.         for i = 1, towerHeight do -- 1
  5271.             T:go("C2U1", false, 0, false, preferredBlock)
  5272.         end
  5273.         T:go("F1L1F1R1D2")
  5274.         while turtle.down() do -- 2
  5275.             T:fillVoid("up", {preferredBlock})
  5276.         end
  5277.         T:go("F1R2C1R2F1D1", false, 0, false, preferredBlock)
  5278.         for i = 1, towerHeight / 2 do -- 3
  5279.             T:go("U2C2", false, 0, false, preferredBlock)
  5280.         end
  5281.         T:go("U1F1R1F1R1D1", false, 0, false, preferredBlock) -- back of tower facing front
  5282.         local deviate = false
  5283.         while turtle.down() do -- 4
  5284.             T:place("fence", "up", false)
  5285.             if turtle.down() then
  5286.                 T:fillVoid("up", {preferredBlock})
  5287.             else
  5288.                 T:go("F1R2C1R1F1R1D1", false, 0, false, preferredBlock)
  5289.                 deviate = true
  5290.                 break
  5291.             end
  5292.         end
  5293.         if not deviate then
  5294.             T:go("F1L1F1R1D1", false, 0, false, preferredBlock)
  5295.         end
  5296.         for i = 1, towerHeight / 2 do -- 5
  5297.             T:go("U2C2", false, 0, false, preferredBlock)
  5298.         end
  5299.         T:go("F2R2", false, 0, false, preferredBlock) -- facing back of tower
  5300.         while turtle.down() do -- 6
  5301.             T:fillVoid("up", {preferredBlock}) --layer 129
  5302.         end
  5303.         T:go("F1L2C1U"..towerHeight)
  5304.         T:go("F4R1F3R1U1", false, 0, false, preferredBlock)
  5305.         -- add small platform at the top
  5306.         lib.baseRun(preferredBlock, 8, "R1F1R1")
  5307.         lib.baseRun(preferredBlock, 8, "L1F3L1")
  5308.         lib.baseRun(preferredBlock, 8, "L1F1L1")
  5309.         lib.baseRun(preferredBlock, 8, "R1F1R1")
  5310.         T:go("C2 F1C2 F1C2 F4C2 F1C2 F1C2 R2F3", false, 0, false, preferredBlock) --fill in centre row
  5311.         lib.buildLift(preferredBlock) -- build bubble lift
  5312.     end
  5313.     return {}
  5314. end
  5315.  
  5316. local function createFarmNetworkStorage(R, withStorage, removeLegacy)
  5317.     removeLegacy = removeLegacy or false
  5318.     -- new or converted farm will have:
  5319.     -- 2 modems, 1 barrel per plot
  5320.     -- primary plot and storage needs 1 modem, 1 barrel, 8 chests
  5321.     local lib = {}
  5322.    
  5323.     function lib.createBasement(R, up, down, width, length)
  5324.         -- start facing lower left
  5325.         R.up = up
  5326.         R.down = down
  5327.         R.width = width
  5328.         R.length = length
  5329.         clearRectangle(R)   -- dig 10 x 10 x 2 area, return to starting position
  5330.         -- add network cable, modems and chests
  5331.     end
  5332.    
  5333.     function lib.placeNetwork(count, pattern)
  5334.         for i = 1, count do
  5335.             T:place("computercraft:cable", "up", true)
  5336.             if i < count then
  5337.                 T:go(pattern)
  5338.             end
  5339.         end
  5340.     end
  5341.    
  5342.     -- called when starting at lower left side of plot, facing crops
  5343.     if removeLegacy then
  5344.         T:go("L1F1")
  5345.         while turtle.suckDown() do end
  5346.         --T:dig("down", false)  -- do not bypass chests
  5347.         turtle.digDown()
  5348.         T:place("dirt", "down")
  5349.         T:go("R2F1")
  5350.         while turtle.suck() do end
  5351.         T:go("F1L1 F1U1 R2")    -- remove barrel/wall or double chest. face tree
  5352.         T:place("stone", "down")
  5353.         T:forward(1)
  5354.         T:place("modem", "down")
  5355.         -- could be tree/sapling in front
  5356.         T:forward(1)
  5357.         if T:getBlockType("down") == "minecraft:dirt" then
  5358.             T:place("barrel", "down")
  5359.             T:go("U1x0")
  5360.             T:place("dirt", "up")
  5361.             T:go("B1U2")
  5362.             if T:getBlockType("forward"):find("log") ~= nil then
  5363.                 T:place("sapling", "forward")
  5364.             end
  5365.             T:go("D3F1 R1F1")
  5366.         else
  5367.             T:place("barrel", "down")
  5368.             T:go("R1F1")
  5369.         end
  5370.         while turtle.suckDown() do end
  5371.         T:place("modem", "down")
  5372.         network.attachModem()
  5373.         T:go("F1x2 R2C2 F1L1 F1D1")
  5374.     end
  5375.     T:go("L1D3") -- move below crop field, face N
  5376.     lib.createBasement(R, true, true, 10, 10)   -- ends facing N below water source
  5377.     T:go("U1 F9R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8") -- facing W below water source
  5378.     T:go("F1 R2C1 R1 F1L1 x0x2")    -- move to corner, face along front edge
  5379.     for c = 1, 4 do
  5380.         if c == 1 then
  5381.             lib.placeNetwork(12, "F1x0x2")
  5382.         else
  5383.             lib.placeNetwork(11, "F1x0x2")
  5384.         end
  5385.         if c < 4 then
  5386.             T:go("L1F1 x0x2 L1C1R1")
  5387.         end
  5388.     end
  5389.     -- now in bottom left facing S
  5390.     T:go("L2F1R1")  -- under modem/netwok cable facing in
  5391.     for i = 1, 3 do
  5392.         T:go("L1C1 R1C1 R1C1 L1D1")
  5393.         T:place("computercraft:cable", "up", true)
  5394.     end
  5395.     T:go("C1L1 C1L1 C1L1 C1L1 D1L1")-- ready for clearing rectangle up/down
  5396.     T:place("computercraft:cable", "up", true)
  5397.     T:down(1)
  5398.     T:place("computercraft:cable", "up", true)
  5399.     lib.createBasement(R, true, true, 11, 11)
  5400.     T:turnRight(1)
  5401.     lib.placeNetwork(11, "F1")
  5402.     T:go("R2F4 R1")
  5403.     lib.placeNetwork(11, "F1")
  5404.     T:go("L1F5 L1F9 R1D1 C1")   -- ready to make ladder column
  5405.     for i = 1, 5 do
  5406.         if i < 5 then
  5407.             T:go("U1C1")
  5408.         else
  5409.             T:up(1)
  5410.         end
  5411.         T:place("ladder", "down")
  5412.     end
  5413.     if withStorage then
  5414.         T:go("R1F4 R1F3 D1x2")
  5415.         T:place("computercraft:cable", "down", true) --ready to build chest storage area
  5416.         T:up(1)
  5417.         utils.createStorage()
  5418.         T:go("U1R1 F5R1 F5U1 C2U1 R2")  -- end on plot starting position, facing crops
  5419.     else
  5420.         T:go("U1F2 L1F1 U1C2 U1L1") -- end on plot starting position, facing crops
  5421.     end
  5422.    
  5423.     return "Farm converted to network storage"
  5424. end
  5425.  
  5426. local function createFarm(R, extend) -- 31
  5427.     -- if extend ~= nil then this has been called from createFarmExtension()
  5428.     -- extend "right" or "forward". only adds a single new farm.
  5429.  
  5430.     if extend == nil then
  5431.         extend = ""
  5432.     end
  5433.    
  5434.     local lib = {}
  5435.  
  5436.     function lib.addWaterSource(R, pattern, storage)
  5437.         -- pattern = {"d","c","c","d"} t = place crafting  instead of dirt
  5438.         -- place(self, blockType, damageNo, direction, leaveExisting, signText)
  5439.         T:go("D1x2C2", false, 0, false, R.useBlockType)
  5440.         for i = 1, 4 do
  5441.             T:dig("forward")
  5442.             if pattern[i] == "d" then
  5443.                 T:place("dirt", "forward", false)
  5444.             elseif pattern[i] == "t" then
  5445.                 --if not T:place("minecraft:crafting_table", "forward", false) then
  5446.                 if T:place(storage, "forward", false) then
  5447.                     if T:dropItem("crafting", "forward", 0) then
  5448.                         print("Crafting table -> buried storage")
  5449.                     end
  5450.                 else
  5451.                     T:place("dirt", "forward", false) -- dirt if no storage available
  5452.                 end
  5453.             else
  5454.                 T:place(R.useBlockType, "forward", false)
  5455.             end
  5456.             T:turnRight(1)
  5457.         end
  5458.         T:up(1)
  5459.         T:placeWater("down")    -- ends facing same direction as started, over water source
  5460.     end
  5461.    
  5462.     function lib.placeDirt(count, atCurrent)
  5463.         if atCurrent then
  5464.             local blockType = T:getBlockType("down")
  5465.             if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
  5466.                 T:place("dirt", "down", false)
  5467.             end
  5468.         end
  5469.         for  i = 1, count do
  5470.             T:forward(1)
  5471.             T:dig("up")
  5472.             local blockType = T:getBlockType("down")
  5473.             if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
  5474.                 T:place("dirt", "down", false)
  5475.             end
  5476.         end
  5477.     end
  5478.  
  5479.     function lib.placeStorage(storage, storageBackup)
  5480.         T:dig("down")
  5481.         if not T:place(storage, "down", false) then-- place barrel/chest below
  5482.             T:place(storageBackup, "down", false) -- place chest below
  5483.         end
  5484.     end
  5485.    
  5486.     local blockType = ""
  5487.     -- current position if extend == nil is on ground/farm level facing N
  5488.     -- if extend = "right", "front" above water source facing crops
  5489.     local numPlots = 0
  5490.     local storage, storageBackup = utils.setStorageOptions()
  5491.     if extend == "right" then
  5492.         T:up(1)
  5493.         utils.goBack(1)
  5494.         repeat
  5495.             T:forward(11)
  5496.             numPlots = numPlots + 1
  5497.         until not utils.isStorage("down") -- on top of chest, barrel or modem
  5498.         T:go("R1F1R2")  -- move to front right corner of last plot on right side
  5499.         --T:go("R1U1 F1L1 F10L1") -- move to front right corner
  5500.     elseif extend == "forward" then
  5501.         T:go("L1U1")
  5502.         utils.goBack(1)
  5503.         repeat
  5504.             T:forward(11)
  5505.             numPlots = numPlots + 1
  5506.         until not utils.isStorage("down") -- on top of chest, barrel or modem
  5507.         T:go("L1F1 R1x2")   -- could dig tree or sapling + block below
  5508.         --T:go("L2U1 F1R1 F10")
  5509.     elseif extend == "convertWithStorage" then
  5510.         -- convert normal (storage) primary plot farm to networked storage
  5511.         --T:turnLeft(1) -- over water source, facing N
  5512.         local response = createFarmNetworkStorage(R, true, true)
  5513.         return {response}
  5514.     elseif extend == "convert" or extend == "convertWithStorage" then
  5515.         -- convert normal (storage) extended farm to networked storage
  5516.         --T:turnLeft(1) -- over water source, facing N
  5517.         createFarmNetworkStorage(R, false, true)
  5518.         return {"Farm converted to network storage"}
  5519.     else -- new farm.
  5520.         T:up(1) -- assume on the ground, go up 1
  5521.     end
  5522.    
  5523.     -- design change: sapling placed 2 blocks above corner for ease of walking round
  5524.     if R.networkFarm then   -- barrel on corner of plot, modems on each side N/E
  5525.         T:place("barrel", "down", false)
  5526.     else
  5527.         T:place(R.useBlockType, "down", false)
  5528.     end
  5529.     -- stage 2 place sapling
  5530.     T:up(3)
  5531.     T:place("dirt", "down")
  5532.     T:up(1)
  5533.     T:place("sapling", "down") -- plant sapling
  5534.     T:go("F1D4")
  5535.     if R.networkFarm then
  5536.         T:place("modem", "down", false)
  5537.         network.attachModem()
  5538.         T:forward(1)
  5539.         T:place(R.useBlockType, "down", false)
  5540.     else
  5541.         -- stage 2 place double barrel/chest
  5542.         T:go("L1")
  5543.         lib.placeStorage(storage, storageBackup)
  5544.         T:go("R1F1L1")
  5545.         lib.placeStorage(storage, storageBackup)
  5546.         T:turnRight(1)
  5547.     end
  5548.     if extend == "right" then -- cobble wall exists so go forward to its end
  5549.         T:forward(9)
  5550.     else -- new farm or extend forward
  5551.         for i = 1, 9 do -- complete left wall to end of farm
  5552.             T:go("F1 x0x2C 2", false, 0, false, R.useBlockType)
  5553.         end
  5554.     end
  5555.     T:go("R1F1 R1x0 x2C2 F1D1", false, 0, false, R.useBlockType)-- turn round ready for first dirt col
  5556.     lib.addWaterSource(R, {"d","c","c","d"}, storage) -- water at top of farm
  5557.     lib.placeDirt(9, false)     -- place dirt back to start
  5558.     if R.networkFarm then   -- water source next to modem
  5559.         lib.addWaterSource(R, {"c","c","d","d"}, storage)
  5560.         -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock
  5561.         T:go("U1F1L1")
  5562.         T:place("modem", "down", false)
  5563.         T:go("F1C2 L1F1 D1", false, 0, false, R.useBlockType)
  5564.     else
  5565.         lib.addWaterSource(R, {"c","c","t","d"}, storage)  -- put barrel / chest in floor
  5566.         T:go("U1F1R2")
  5567.         if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
  5568.             lib.placeStorage(storage, storageBackup)
  5569.         end
  5570.         T:go("R1F1L1")
  5571.         if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
  5572.             lib.placeStorage(storage, storageBackup)
  5573.         end
  5574.         T:go("F1D1")
  5575.     end
  5576.     lib.placeDirt(9, true)
  5577.     local turn = "R"
  5578.     for i = 1, 7 do
  5579.         T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0 x2C2 F1D1", false, 0, false, R.useBlockType)
  5580.         lib.placeDirt(9, true)
  5581.         if turn == "R" then
  5582.             turn = "L"
  5583.         else
  5584.             turn = "R"
  5585.         end
  5586.     end
  5587.     T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
  5588.     lib.addWaterSource(R, {"d","c","c","d"}, storage)   -- bottom right
  5589.     lib.placeDirt(9, false)
  5590.     lib.addWaterSource(R, {"c","c","d","d"}, storage)   -- top right, facing away from plot
  5591.     T:go("F1U1 R1C2 x0F1 x0x2 C2R1", false, 0, false, R.useBlockType)
  5592.     for i = 1, 11 do    -- build right wall from top of plot to bottom
  5593.         T:go("F1x0x2C2", false, 0, false, R.useBlockType)
  5594.     end
  5595.     T:go("R1F10")               -- ends on top of front storage/ modem facing tree
  5596.     if R.networkFarm then       -- network storage
  5597.         network.attachModem()
  5598.         T:go("R1F1D1R1")    -- over water source, facing E (crops)
  5599.         if extend == "" then    -- primary plot
  5600.             createFarmNetworkStorage(R, true)
  5601.         else
  5602.             createFarmNetworkStorage(R, false)
  5603.         end
  5604.     end
  5605.     if extend == "right" then
  5606.         T:up(1)
  5607.         utils.goBack(numPlots * 11)
  5608.         T:down(1)
  5609.     elseif extend == "forward" then
  5610.         T:go("R1U1F".. numPlots * 11 .."D1L1")
  5611.     end
  5612.     return {"Modular farm completed"}
  5613. end
  5614.  
  5615. local function createFarmExtension(R) -- 32
  5616.     -- assume inventory contains 4 chests, 64 cobble, 128 dirt, 4 water, 1 sapling
  5617.     -- check position by rotating to face tree/sapling
  5618.    
  5619.     --T:setUseLog(true, "farmCreateLog.txt", true)
  5620.     --dbug = true   -- set dbug flag
  5621.     --utils.waitForInput("Logging and debugging enabled")   --utils.waitForInput(message)
  5622.    
  5623.     local extend = "right" -- default
  5624.     if R.subChoice == 1 then
  5625.         extend = "forward"
  5626.     end
  5627.    
  5628.     R = utils.checkFarmPosition(R)
  5629.    
  5630.     if not R.ready then
  5631.         return {"Unable to determine starting position"}
  5632.     end
  5633.    
  5634.     createFarm(R, extend)
  5635.     return {"Modular crop farm extended"}
  5636. end
  5637.  
  5638. local function createFloorCeiling(R) -- 79 size integer 1 to 4
  5639.     --[[
  5640.     R.up = true for ceiling
  5641.     R.down = true for floor
  5642.     R.height = 0 for normal
  5643.     R.height combined with R.up/R.down used for remote access
  5644.     R.data == "random" for random floor placement
  5645.     ]]
  5646.    
  5647.     local lib = {}
  5648.    
  5649.     function lib.goToRemote(R)
  5650.         R.silent = true
  5651.         local depth = 0
  5652.         if R.down then -- floor could be under water
  5653.             while turtle.down() do
  5654.                 depth = depth + 1
  5655.             end
  5656.         elseif R.up then
  5657.             while turtle.up() do
  5658.                 depth = depth + 1
  5659.                 if depth > R.height + 3 then
  5660.                     break
  5661.                 end
  5662.             end
  5663.         end
  5664.         if not(R.height - depth <= 2 or depth - R.height <= 2) then
  5665.             T:up(depth)
  5666.             return "Measured depth/height of "..depth.." > setting: "..R.height
  5667.         end
  5668.         -- not returned so depth acceptable
  5669.         return ""
  5670.     end
  5671.    
  5672.     function lib.checkPosition(R)
  5673.         -- check if block above/below
  5674.         local blockBelow = turtle.detectDown()
  5675.         local blockAbove = turtle.detectUp()
  5676.         if R.subChoice == 2 then -- New floor over existing
  5677.             -- if no block below, assume in correct position and continue
  5678.             -- else move up 1 and continue
  5679.             if blockBelow then T:up(1) end
  5680.         elseif R.subChoice == 4 then -- New ceiling under existing
  5681.             -- if no block above, assume in correct position and continue
  5682.             -- else move down 1 and continue
  5683.             if blockAbove then T:down(1) end
  5684.         end
  5685.     end
  5686.    
  5687.     function lib.placeRow(R, direction, waterPresent)
  5688.         for y = 1, R.length do
  5689.             local blockType = T:getBlockType("forward")
  5690.             if not waterPresent then
  5691.                 if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then
  5692.                     waterPresent = true
  5693.                 end
  5694.             end
  5695.             R = lib.getRandomBlock(R)   -- changes block randomly ONLY if R.data == "random"
  5696.             R = lib.changeCheckered(R)  -- changes to next block type ONLY if R.data == "checked"
  5697.             -- ONLY if R.data == "striped" has already been changed for whole row
  5698.             T:place(R.inventory.useBlock, direction, false) -- leaveExisting = false
  5699.             if y < R.length then
  5700.                 T:forward(1)
  5701.             end
  5702.         end
  5703.         return waterPresent, R
  5704.     end
  5705.    
  5706.     function lib.getRandomBlock(R)
  5707.         if R.data == "random" then
  5708.             local index = math.random(1, #R.inventory.names)    -- random index between 1 and no of block types
  5709.             local success = false
  5710.             for i = index, R.inventory.blockTypeCount do        -- iterate from index upwards
  5711.                 if R.inventory.quantities[i] > 0 then           -- at least 1 block left
  5712.                     R.inventory.useBlock = R.inventory.names[i]
  5713.                     R.inventory.quantities[i] = R.inventory.quantities[i] - 1
  5714.                     R.inventory.blockCount = R.inventory.blockCount - 1
  5715.                     success = true
  5716.                     break
  5717.                 end
  5718.             end
  5719.            
  5720.             if not success then                             -- no blocks left in the range of index -> no of block types
  5721.                 for i = index, 1, -1 do                     -- go backwards from index to 1
  5722.                     if R.inventory.quantities[i] > 0 then       -- at least 1 block left
  5723.                         R.inventory.useBlock = R.inventory.names[i]
  5724.                         R.inventory.quantities[i] = R.inventory.quantities[i] - 1
  5725.                         R.inventory.blockCount = R.inventory.blockCount - 1
  5726.                         success = true
  5727.                         break
  5728.                     end
  5729.                 end
  5730.             end
  5731.         end
  5732.        
  5733.         return R
  5734.     end
  5735.    
  5736.     function lib.changeStripe(R)
  5737.         if R.data == "striped" then
  5738.             R.size = R.size + 1
  5739.             if R.size > R.inventory.blockTypeCount then
  5740.                 R.size = 1
  5741.             end
  5742.             R.inventory.useBlock = R.inventory.names[R.size]
  5743.         end
  5744.         return R
  5745.     end
  5746.    
  5747.     function lib.changeCheckered(R)
  5748.         --swap between 2 block types
  5749.         if R.data == "checked" then
  5750.             if R.inventory.useBlock == R.inventory.names[1] then
  5751.                 R.inventory.useBlock = R.inventory.names[2]
  5752.             else
  5753.                 R.inventory.useBlock = R.inventory.names[1]
  5754.             end
  5755.         end
  5756.         return R
  5757.     end
  5758.    
  5759.     local waterPresent = false
  5760.    
  5761.     if R.data == "random" then
  5762.         math.randomseed(R.inventory.blockCount)
  5763.         print("Using random blocks")
  5764.     elseif R.data == "striped" then
  5765.         print("Using striped pattern")
  5766.     elseif R.data == "checked" then
  5767.         print("Using checkered pattern")
  5768.     end
  5769.     local direction = "down"
  5770.     if R.up then
  5771.         direction = "up"
  5772.     end
  5773.    
  5774.     if R.height > 0 then -- remote placing. go up/down R.height first
  5775.         local message = lib.goToRemote(R)
  5776.         if message ~= "" then   -- error encountered
  5777.             return {message}
  5778.         end
  5779.     end
  5780.    
  5781.     lib.checkPosition(R)
  5782.     -- based on clearRectangle code
  5783.     if R.width == 1 then                    -- single block ahead only
  5784.         waterPresent, R = lib.placeRow(R, direction, waterPresent)
  5785.         T:turnRight(2)                      -- turn at the top of the run
  5786.         T:forward(R.length - 1)             -- return to start
  5787.         T:turnRight(2)                      -- turn round to original position
  5788.     else
  5789.         local iterations = 0                -- R.width = 2, 4, 6, 8 etc
  5790.         if R.width % 2 == 1 then            -- R.width = 3, 5, 7, 9 eg R.width 7
  5791.             iterations = (R.width - 1) / 2  -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
  5792.         else
  5793.             iterations = R.width / 2        -- iterations 1, 2, 3, 4 for widths 2, 4, 6, 8
  5794.         end
  5795.         R = lib.changeStripe(R)
  5796.         R = lib.changeCheckered(R)
  5797.         for i = 1, iterations do            -- eg 3 blocks wide, iterations = 1
  5798.             waterPresent, R = lib.placeRow(R, direction, waterPresent)
  5799.             T:go("R1F1R1")
  5800.             R = lib.changeStripe(R)
  5801.             --R = lib.changeCheckered(R)
  5802.             waterPresent, R = lib.placeRow(R, direction, waterPresent)
  5803.             -- if 1 less than end, reposition for next run
  5804.             if i < iterations then
  5805.                 T:go("L1F1L1", false, 0, false)
  5806.                 R = lib.changeStripe(R)
  5807.             end
  5808.         end
  5809.         if R.width % 2 == 1 then  -- additional run and return to base needed
  5810.             T:go("L1F1L1", false, 0, false)
  5811.             R = lib.changeStripe(R)
  5812.             waterPresent, R = lib.placeRow(R, direction, waterPresent)
  5813.             T:turnRight(2)
  5814.             T:forward(R.length - 1)
  5815.         end
  5816.         T:go("R1F"..R.width - 1 .."R1", false, 0, false)
  5817.     end
  5818.  
  5819.     if waterPresent then
  5820.         return {"water or lava found"}
  5821.     end
  5822.    
  5823.     return {""}
  5824. end
  5825.  
  5826. local function createIceCanal(R) -- 55
  5827.     --[[
  5828.         R.subChoice =
  5829.         1: move right into canal, build left towpath
  5830.         2: build left towpath
  5831.         3: build right towpath
  5832.         4: move left into canal, build right towpath
  5833.         5/8: clear path 3 blocks high, place slabs/torches
  5834.         6/7: build alternating ice road / create 3 block high air gap (2 over water)
  5835.     ]]
  5836.     local oTurn = "R"
  5837.     if R.side == "R" then
  5838.         oTurn = "L"
  5839.     end
  5840.     local lib = {}
  5841.    
  5842.     function lib.convertTowpath(R)
  5843.         -- only used to convert existing water canal, so assume towpath already present
  5844.         -- starting position 1 block above existing towpath
  5845.         for i = 1, R.length do
  5846.             if turtle.detectDown() then                         -- eg existing torch
  5847.                 T:dig("down")
  5848.             end
  5849.             local placeSlab = true
  5850.             if R.torchInterval > 0 then                         -- place torches
  5851.                 if i == 1 or i % R.torchInterval == 0 then      -- ready to place torch
  5852.                     --go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  5853.                     T:go("C2x0", false, 0, false, R.useBlockType)-- place solid block below
  5854.                     T:go("F1R2x0")
  5855.                     T:place("torch", "forward")             -- place torch, move forward
  5856.                     T:turnRight(2)                              -- turn round
  5857.                     placeSlab = false
  5858.                 end
  5859.             end
  5860.             if placeSlab then
  5861.                 T:dig("up")
  5862.                 if not T:place("slab", "down") then         -- break if out of slabs
  5863.                     break
  5864.                 end
  5865.                 if i < R.length then
  5866.                     T:forward(1)                                -- move forward
  5867.                 end
  5868.             end
  5869.         end
  5870.     end
  5871.    
  5872.     function lib.iceCanalTowpath(R)
  5873.         -- move forward placing slabs along the way. If existing water canal, ceiling will be raised by 1 block
  5874.         local torchInterval = 0
  5875.         local placeIce = true
  5876.         for i = 1, R.length do
  5877.             local addTorch = false
  5878.             if R.torchInterval > 0 then
  5879.                 if i == 1 then addTorch = true end
  5880.                 if torchInterval >= R.torchInterval then
  5881.                     addTorch = true
  5882.                     torchInterval = 0
  5883.                 end
  5884.             end
  5885.             lib.iceCanalEdge(R, addTorch, i, placeIce)
  5886.             torchInterval = torchInterval + 1
  5887.             placeIce = not placeIce
  5888.         end
  5889.         T:go(oTurn.."1")
  5890.     end
  5891.    
  5892.     function lib.iceCanalEdge(R, addTorch, numBlocks, placeIce)
  5893.         -- starting position facing canal side
  5894.         local blockType = T:getBlockType("forward")         -- ? air / slab / other
  5895.         local isWater, isSource, isIce = T:isWater("down")  -- water / ice below
  5896.         if blockType:find("slab") == nil then               -- add slab
  5897.             if addTorch then                                -- check if torch needed
  5898.                 -- T:place(blockType, direction, leaveExisting, signText)
  5899.                 if not T:place("stone", "forward", false) then
  5900.                     T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
  5901.                 end
  5902.                 T:go("U1x1 U1x1 D1")                    -- water level to 2 above water level
  5903.                 if T:getItemSlot("minecraft:torch") > 0 then
  5904.                     T:place("torch", "forward", false)
  5905.                 end
  5906.                 T:down(1)                               -- back to above water level
  5907.                 if not isIce then                       -- break block below if NOT ice
  5908.                     T:dig("down")
  5909.                 end
  5910.             else
  5911.                 if not T:place("slab", "forward", false) then
  5912.                     T:checkInventoryForItem({"slab"}, {R.length - numBlocks}, true)
  5913.                 end
  5914.                 if not isSource then                    -- NOT on water, so dig above
  5915.                     T:go("U1x1 U1x1 D2")
  5916.                 end
  5917.                 if not isIce and not isSource then
  5918.                     T:dig("down")
  5919.                 end
  5920.             end
  5921.         else -- slab already on side
  5922.             if addTorch then                            -- check if torch needed
  5923.                 T:dig("forward")
  5924.                 if not T:place("stone", "forward", false) then
  5925.                     T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
  5926.                 end
  5927.                 T:go("U1x1 U1x1 D1")                    -- water level to 2 above water level
  5928.                 if T:getItemSlot("minecraft:torch") > 0 then
  5929.                     T:place("torch", "forward", false)
  5930.                 end
  5931.                 T:down(1)                               -- back to above water level
  5932.                 if not isIce then                       -- break block below if NOT ice
  5933.                     T:dig("down")
  5934.                 end
  5935.             end
  5936.         end
  5937.         if R.data == "ice" and placeIce and not isIce then -- R.data = "ice", placeIce = true, not already ice present
  5938.             T:place("ice", "down", true)
  5939.         end
  5940.         if numBlocks < R.length then
  5941.             T:go(oTurn.."1F1"..R.side.."1")
  5942.         end
  5943.     end
  5944.    
  5945.     function lib.convertIcepath(length)
  5946.         -- use only for placing ice to convert a water canal
  5947.         -- place ice on alternate blocks until length reached or run out of ice
  5948.         local placeIce = true
  5949.         for i = 1, length do
  5950.             if T:getBlockType("down"):find("ice") == nil then -- no ice below
  5951.                 T:dig("down") -- remove any existing block
  5952.                 if placeIce then
  5953.                     if not T:place("ice", "down", true) then -- out of ice
  5954.                         break
  5955.                     end
  5956.                     if i == length - 1 then
  5957.                         break
  5958.                     end
  5959.                 end
  5960.             else -- ice already below
  5961.                 placeIce = true
  5962.             end
  5963.             T:go("U1x0 D1F1")
  5964.             placeIce = not placeIce -- reverse action
  5965.         end
  5966.     end
  5967.    
  5968.     function lib.convertToAir(length)
  5969.         -- use only for converting a water canal. start at ground level
  5970.         -- dig up/down/forward to clear space
  5971.         for i = 1, length + 1 do
  5972.             T:go("U1x0D1")
  5973.             if i < length + 1 then
  5974.                 T:go("x2F1")
  5975.             else
  5976.                 T:dig("down")
  5977.             end
  5978.         end
  5979.     end
  5980.    
  5981.     function lib.initialise(R)
  5982.         if R.subChoice == 1 or R.subChoice == 4 then       
  5983.             local blockType = T:getBlockType("down")        -- ? at ground/water level or on top of existing slab
  5984.             if blockType:find("slab") ~= nil then           -- slab already present
  5985.                 T:go(oTurn.."1F1D1"..R.side.."2")           -- move right/left forward, down onto ice canal top, face canal wall
  5986.             elseif blockType:find("torch") ~= nil then
  5987.                 T:go(oTurn.."1F1D2"..R.side.."2")           -- move right/left forward, down onto ice canal top, face canal wall
  5988.             else                                            -- assume on ground / water level
  5989.                 T:go(oTurn.."1F1"..R.side.."2")             -- move right/left forward onto ice canal top, face canal wall
  5990.             end
  5991.         else
  5992.             if T:isWater("forward") then                    -- player put turtle inside canal water
  5993.                 T:up(1)
  5994.             end
  5995.             T:go(R.side.."1")                               -- face canal wall
  5996.         end
  5997.     end
  5998.    
  5999.     if R.length == 0 then R.length = 1024 end
  6000.  
  6001.     if R.subChoice <= 4  then                               -- towpath 1,2,3,4
  6002.         lib.initialise(R)                                   -- reposition
  6003.         lib.iceCanalTowpath(R)                              -- build towpath
  6004.     elseif R.subChoice == 5 or R.subChoice == 8 then        -- assume placed on towpath
  6005.         if T:getBlockType("down"):find("slab") ~= nil then  -- slab already present
  6006.             T:go("F1")
  6007.         else
  6008.             T:up(1)
  6009.         end
  6010.         lib.convertTowpath(R)
  6011.     elseif R.subChoice == 6 or R.subChoice == 7 then   
  6012.         if R.data == "ice" then                         -- assume placed on existing ice or initial ice position
  6013.             lib.convertIcepath(R.length)-- place ice
  6014.         else                                            -- assume placed on empty path
  6015.             lib.convertToAir(R.length)                  -- clear 3 high area
  6016.         end
  6017.     end
  6018.    
  6019.     return {}
  6020. end
  6021.  
  6022. local function createLadder(R) -- 12
  6023.     -- createLadder(R.data ="bedrock", R.height = 70, R.depth = -48)
  6024.     -- go(path, useTorch, torchInterval, leaveExisting)
  6025.     -- place(blockType, damageNo, direction, leaveExisting)
  6026.     local lib = {}
  6027.    
  6028.     function lib.placeLadder(direction, ledge, i, height)
  6029.         -- 1 check both sides and behind
  6030.         local fluid = false
  6031.         local block = T:isWaterOrLava("forward", ledge)
  6032.         if block:find("water") ~= nil or block:find("lava") ~= nil then
  6033.             --[[ surround 2 block shaft with blocks ]]
  6034.             T:go("R1C1 R1C1 R1C1 R1F1 L1C1 R1C1 R1C1 R1C1F1 R2C1 x1")
  6035.         else
  6036.             --[[ no water/lava so prepare ladder site]]
  6037.             T:go("F1 L1C1 R1C1 R1C1 L1B1", false, 0, true)
  6038.         end
  6039.         if not T:place("ladder", "forward", false) then
  6040.             T:checkInventoryForItem({"ladder"}, {height - i}, false)
  6041.         end
  6042.         -- 3 check if ledge, torch
  6043.         if ledge == 0 and i > 1 then -- place block above unless new ladder
  6044.             T:place("common", direction, false) -- any common block
  6045.         elseif ledge == 1 then
  6046.             T:place("minecraft:torch", direction, false)
  6047.         elseif ledge == 2 then
  6048.             ledge = -1
  6049.         end
  6050.        
  6051.         return ledge
  6052.     end
  6053.    
  6054.     local retValue = {}
  6055.     local ledge = 0
  6056.     local height = math.abs(R.depth - R.height) --height of ladder
  6057.     local blockType = T:getBlockType("forward")
  6058.     if R.up then -- create ladder from current level to height specified
  6059.         for i = 1, height do -- go up, place ladder as you go
  6060.             ledge = lib.placeLadder("down", ledge, i, height) -- ladder placed forward, stone ledge for torch placed down
  6061.             if i <  height then
  6062.                 T:up(1)
  6063.                 ledge = ledge + 1
  6064.             end
  6065.         end    
  6066.     else -- R.down = true: ladder towards bedrock      
  6067.         local success = true
  6068.         local numBlocks, errorMsg = 0, ""
  6069.         T:down(1)
  6070.         for i = 1, height do -- go down, place ladder as you go
  6071.             ledge = lib.placeLadder("up", ledge, i, heigt) -- ladder placed forward, stone torch placed up
  6072.             --success, blocksMoved, errorMsg, blockType = clsTurtle.down(self, steps, getBlockType)
  6073.             if i < height then
  6074.                 success, numBlocks, errorMsg, blockType = T:down(1, true) -- true = return blockType
  6075.                 ledge = ledge + 1
  6076.             end
  6077.             -- if looking for stronghold then check for stone_bricks
  6078.             if blockType:find("stone_bricks") ~= nil then
  6079.                 table.insert(retValue, "Stronghold discovered")
  6080.                 break -- stop descent at stronghold
  6081.             end
  6082.         end
  6083.         -- if user requested shelter create chamber at this level
  6084.         if R.data == "chamber" then -- user has chosen to build a chamber
  6085.             table.insert(retValue, "Shelter constucted at level".. R.depth)
  6086.             if blockType:find("bedrock") ~= nil then
  6087.                 T:findBedrockTop(0) -- test to check if on safe level immediately above tallest bedrock
  6088.             end
  6089.             -- In shaft, facing start direction, on lowest safe level
  6090.             -- create a square space round shaft base, end facing original shaft, 1 space back
  6091.             T:go("L1n1 R1n3 R1n2 R1n3 R1n1", false, 0, true)
  6092.             T:go("U1Q1 R1Q3 R1Q2 R1Q3 R1Q1 R1D1", false, 0, true)
  6093.         end
  6094.     end
  6095.    
  6096.     return retValue
  6097. end
  6098.  
  6099. local function createLadderToWater(R) -- 86
  6100.     -- go down to water/lava with alternaate solid/open layers
  6101.     -- create a working area at the base
  6102.     -- Return to surface facing towards player placing ladders
  6103.     local inAir = true
  6104.     local numBlocks, errorMsg = 0, ""
  6105.     local height = 2
  6106.     local blockType = T:getBlockType("down")
  6107.     if blockType ~= "" then -- not over air
  6108.         T:forward(1)
  6109.     end
  6110.     T:go("R2D1") -- face player, go down 2
  6111.     while inAir do --success = false when hits water/lava
  6112.         blockType = T:isWaterOrLava("down")
  6113.         if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
  6114.             inAir = false
  6115.         end
  6116.         T:go("C1R1 C1R2 C1R1", false, 0, false) -- surround front  and sides with cobble
  6117.         if inAir then
  6118.             T:down(1)
  6119.             height = height + 1
  6120.         end
  6121.         T:place("ladder", "up")
  6122.     end
  6123.     -- In shaft, facing opposite start direction, on water/lava, ladders above
  6124.     T:go("C2", false, 0, false)
  6125.     utils.goBack(1)
  6126.     T:place("ladder", "forward")
  6127.     T:up(3)
  6128.     height = height - 3
  6129.     for i = 1, height do
  6130.         if i < height then
  6131.             T:go("C2U1", false, 0, false)
  6132.         else
  6133.             T:go("C2", false, 0, false)
  6134.         end
  6135.     end
  6136.  
  6137.     return {}
  6138. end
  6139.  
  6140. local function createMine() -- 11
  6141.     -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  6142.     T:clear()  
  6143.     T:go("m32U1R2M16", true, 8, true) -- mine ground level, go up, reverse and mine ceiling to mid-point
  6144.     T:go("U2D2") -- create space for chest
  6145.     T:place("minecraft:chest", "up", false)
  6146.     T:emptyTrash("up")
  6147.     T:go("D1R1m16U1R2M16", true, 8, true) -- mine floor/ceiling of right side branch
  6148.     T:emptyTrash("up")
  6149.     T:go("D1m16U1R2M16", true, 8, true) -- mine floor/ceiling of left side branch
  6150.     T:emptyTrash("up")
  6151.     T:go("L1M15F1R1D1", true, 8, true) -- mine ceiling of entry corridor, turn right
  6152.     T:go("F1x0 F1x0 n14 R1n32 R1n32 R1n32 R1n14 F1x0 F1U1", true, 8, true)-- mine floor of 36 x 36 square corridor
  6153.     T:go("R1F16R2") --return to centre
  6154.     T:emptyTrash("up")
  6155.     T:go("F16R1") --return to entry shaft
  6156.     T:go("F2Q14R1Q32R1Q32R1Q32R1Q14F2R1", true, 8, true) --mine ceiling of 36x36 square corridor. return to entry shaft + 1
  6157.     T:go("F16R2") --return to centre
  6158.     T:emptyTrash("up")
  6159.     -- get rid of any remaining torches
  6160.     while T:getItemSlot("minecraft:torch") > 0 do
  6161.         turtle.select(T:getItemSlot("minecraft:torch"))
  6162.         turtle.dropUp()
  6163.     end
  6164.     T:go("F16R1F1R1") --return to shaft + 1
  6165.     for i = 1, 8 do
  6166.         T:go("N32L1F1L1", true, 8, true)
  6167.         T:go("N16L1F"..(i * 2).."R2", true, 8, true)
  6168.         T:emptyTrash("up")
  6169.         if i < 8 then
  6170.             T:go("F"..(i * 2).."L1N16R1F1R1", true, 8, true)
  6171.         else
  6172.             T:go("F"..(i * 2).."L1N16L1", true, 8, true)
  6173.         end
  6174.     end
  6175.     T:go("F17L1") -- close gap in wall, return to ladder + 1
  6176.     for i = 1, 8 do
  6177.         T:go("N32R1F1R1", true, 8, true)
  6178.         T:go("N16R1F"..(i * 2).."R2", true, 8, true)
  6179.         T:emptyTrash("up")
  6180.         if i < 8 then
  6181.             T:go("F"..(i * 2).."R1N16L1F1L1", true, 8, true)
  6182.         else
  6183.             T:go("F"..(i * 2).."R1N16R1", true, 8, true)
  6184.         end
  6185.     end
  6186.     T:go("F16R1")
  6187.     T:clear()
  6188.     return{"Mining operation complete"}
  6189. end
  6190.  
  6191. local function createMobFarmCube(R) -- 61, 62
  6192.     --[[
  6193.     Part 1 / 3 Mob Spawner Farm
  6194.     blaze = true: blaze spawner in nether
  6195.         R.subChoice is set to:
  6196.         1 = on top of spawner
  6197.         2 = line of sight
  6198.         3 = room below
  6199.     blaze = false: overworld mob spawner
  6200.         R.subChoice is set to:
  6201.         1 = on top of spawner
  6202.         2 = bottom left corner
  6203.         3 = top left corner
  6204.         4 = bottom right, corner
  6205.         5 = top right corner
  6206.         R.width / R.length set by player (external size)
  6207.     ]]
  6208.     local blaze = true
  6209.     if R.data == "spawner" or R.data == "chest" then
  6210.         blaze = false
  6211.     end
  6212.     local continue = false
  6213.     if R.data == "restart" then
  6214.         continue = true
  6215.     end
  6216.     R.direction = "clock"       -- starting on right side
  6217.     if not blaze then
  6218.         print("R.width: "..tostring(R.width))
  6219.         R.width = R.width - 2       -- internal width
  6220.         R.length = R.length - 2     -- internal length
  6221.        
  6222.         if R.subChoice == 2 or R.subChoice == 3 then
  6223.             R.direction = "anticlock"
  6224.         end
  6225.     end
  6226.     -- R.data allows for 2-part operation "blaze" = main cube, "restart" = killzone
  6227.     T:clear()
  6228.     local lib = {}
  6229.    
  6230.     function lib.floorSection(length)
  6231.         for i = 1, length do        -- starts on top left corner
  6232.             T:go("C2")
  6233.             if i < length then
  6234.                 T:forward(1)
  6235.             else
  6236.                 T:go("R1F1")
  6237.             end
  6238.         end
  6239.     end
  6240.    
  6241.     function lib.wallSection(blaze)
  6242.         blaze = blaze or false
  6243.         for i = 1, 4 do
  6244.             for j = 1, 11 do
  6245.                 if blaze then
  6246.                     T:place("slab", "up", false)
  6247.                     T:go("C2", false, 0, false)
  6248.                 else
  6249.                     T:go("C0C2", false, 0, false)
  6250.                 end
  6251.                 if j < 11 then
  6252.                     T:forward(1)
  6253.                     T:go("R2C1L2", false, 0, false)
  6254.                 else
  6255.                     T:turnRight(1)
  6256.                 end
  6257.             end
  6258.         end
  6259.     end
  6260.    
  6261.     function lib.ceiling(blaze)
  6262.         -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  6263.         -- all outer walls complete, now for remaining 9x9 ceiling
  6264.         blaze = blaze or false
  6265.         for i = 1, 9 do
  6266.             for j = 1, 9 do
  6267.                 if blaze then
  6268.                     T:place("slab", "up", false)
  6269.                     T:dig("down")
  6270.                 else
  6271.                     T:go("C0x2", false, 0, true)
  6272.                 end
  6273.                 if j < 9 then
  6274.                     T:forward(1)
  6275.                 else    -- end of length
  6276.                     local place = false
  6277.                     if i%2 == 1 then -- odd numbers 1,3,5,7,9
  6278.                         if i < 9 then
  6279.                             place = true
  6280.                             T:go("R1F1 R1")
  6281.                         end
  6282.                     else
  6283.                         place = true
  6284.                         T:go("L1F1 L1")
  6285.                     end
  6286.                     if place then
  6287.                         if blaze then
  6288.                             T:place("slab", "up", false)
  6289.                             T:dig("down")
  6290.                         else
  6291.                             T:go("C0x2", false, 0, true)
  6292.                         end
  6293.                     end
  6294.                 end
  6295.             end
  6296.         end
  6297.     end
  6298.    
  6299.     function lib.clearWall(length)
  6300.         for i = 1, 4 do
  6301.             for j = 1, length do
  6302.                 if j < length then
  6303.                     T:go("x0x2F1")
  6304.                 else
  6305.                     T:go("x0x2R1")
  6306.                 end
  6307.             end
  6308.         end
  6309.     end
  6310.    
  6311.     function lib.isSpawner()
  6312.         local blockType = T:getBlockType("down")
  6313.         if blockType:find("spawner") ~= nil then
  6314.             return true, "top"
  6315.         end
  6316.         blockType = T:getBlockType("up")
  6317.         if blockType:find("spawner") ~= nil then
  6318.             return true, "bottom"
  6319.         end
  6320.         blockType = T:getBlockType("forward")
  6321.         if blockType:find("spawner") ~= nil then
  6322.             return true, "forward"
  6323.         end
  6324.         return false, ""
  6325.     end
  6326.    
  6327.     function lib.placeFloor(width, length, blockType)
  6328.         -- T:place(blockType, direction, leaveExisting, signText)
  6329.         for i = 1, width do            
  6330.             for j = 1, length do
  6331.                 T:place(blockType, "down", false)
  6332.                 if j < length then
  6333.                     T:forward(1)
  6334.                 else
  6335.                     if i%2 == 1 then -- odd numbers 1,3,5,7,9
  6336.                         if i < width then
  6337.                             T:go("R1F1R1", false, 0, true)
  6338.                         end
  6339.                     else
  6340.                         T:go("L1F1L1", false, 0, true)
  6341.                     end
  6342.                 end
  6343.             end
  6344.         end
  6345.     end
  6346.    
  6347.     function lib.searchStrip(distance)
  6348.         --go forward until hit either a wall or a chest
  6349.         local blocks = 1
  6350.         print("Searching strip, distance = "..distance)
  6351.         while blocks < distance do --max travel is external width/length
  6352.             if turtle.forward() then
  6353.                 blocks = blocks + 1
  6354.             else
  6355.                 print("Checking for chest")
  6356.                 if lib.isChest("forward") then
  6357.                     if turtle.forward() then
  6358.                         blocks = blocks + 1
  6359.                     end
  6360.                 else
  6361.                     break
  6362.                 end
  6363.             end
  6364.         end
  6365.     end
  6366.    
  6367.     function lib.findChests(R)
  6368.         for i = 1, 4 do
  6369.             print("Searching wall "..i)
  6370.             if i == 1 or i == 3 then
  6371.                 lib.searchStrip(R.width)    -- find and empty chests along width
  6372.             else
  6373.                 lib.searchStrip(R.length)   -- find and empty chests along length
  6374.             end
  6375.             if R.direction == "clock" then
  6376.                 T:turnRight(1)
  6377.             else
  6378.                 T:turnLeft(1)
  6379.             end
  6380.         end
  6381.  
  6382.         -- checked all walls
  6383.         T:go("F".. math.floor(R.width / 2)) -- now at mid-dungeon, next to wall
  6384.         if T:getItemSlot("chest") > 0 then
  6385.             if R.direction == "clock" then
  6386.                 T:turnLeft(1)
  6387.             else
  6388.                 T:turnRight(1)
  6389.             end
  6390.             -- now at mid-dungeon, facing wall
  6391.             -- deposit chest outside the dungeon
  6392.             while turtle.back() do end -- backing spawner
  6393.             T:go("x0 F1x0 F1x0 F1x0 F1x0 F1x0 F1x0 x1x2")
  6394.             -- place(self, blockType, damageNo, direction, leaveExisting, signText)
  6395.             T:place("chest", "forward", false)
  6396.             -- empty out all except stone and slab
  6397.             T:emptyInventorySelection("forward", {"cobble", "tuff", "slab", "granite", "andesite", "diorite" }, {0,0,0,0,0,0})
  6398.             T:turnLeft(2)
  6399.             T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements")
  6400.             while turtle.forward() do end -- facing spawner
  6401.         else
  6402.             if R.direction == "clock" then
  6403.                 T:turnRight(1)
  6404.             else
  6405.                 T:turnLeft(1)
  6406.             end
  6407.         end -- now at mid-dungeon, facing spawner
  6408.     end
  6409.    
  6410.     function lib.enterDungeon(R)
  6411.         --[[ find and empty any chests, return to dungeon wall ]]
  6412.         print("Entering dungeon")
  6413.         local blockType = T:getBlockType("forward")
  6414.         if blockType == "" then -- nothing in front.Error
  6415.             return false, "No block in front: Check position."
  6416.         else -- attempt entry into dungeon wall
  6417.             if R.subChoice == 2 then        -- bottom left
  6418.                 T:go("R1F1 L1U2 F2R1")
  6419.             elseif R.subChoice == 3 then    -- top left
  6420.                 T:go("R1F1 L1D1 F2R1")
  6421.             elseif R.subChoice == 4 then    -- bottom right
  6422.                 T:go("L1F1 R1U2 F2L1")
  6423.             elseif R.subChoice == 5 then    -- top right
  6424.                 T:go("L1F1 R1D1 F2L1")
  6425.             end
  6426.             while turtle.down() do end -- either on floor or chest
  6427.             if lib.isChest("down") then
  6428.                 turtle.down()
  6429.             end
  6430.             print("Searching for chests")
  6431.             lib.findChests(R)   -- go round inside walls  emptying chests. Finish mid-wall
  6432.         end
  6433.         return true, ""-- success, message
  6434.     end
  6435.    
  6436.     function lib.isChest(direction)
  6437.         direction = direction or "forward"
  6438.         local blockType = T:getBlockType(direction)
  6439.         if blockType:find("chest") ~= nil then -- chest found. early stages so empty and break it
  6440.             print("Chest found")
  6441.             while T:suck(direction) do end
  6442.             T:dig(direction, false) -- false prevents checking for chests
  6443.             return true
  6444.         elseif blockType:find("torch") ~= nil then
  6445.             print("Torch found")
  6446.             T:dig(direction, false) -- false prevents checking for chests
  6447.             return true
  6448.         end
  6449.         return false
  6450.     end
  6451.        
  6452.     function lib.findSpawner(blaze)
  6453.         local moves  = 0
  6454.         local quit = false
  6455.         -- assume turtle placed on centre of inside spawner wall in front of spawner
  6456.         -- or as close as possible in Nether
  6457.         print("Checking if next to spawner")
  6458.         local found, position = lib.isSpawner() -- true/false, top/bottom/nil
  6459.         if not found then -- move forward towards spawner
  6460.             print("Not close to spawner")
  6461.             while turtle.forward() and not quit do
  6462.                 moves = moves + 1
  6463.                 if moves > 16 then
  6464.                     quit = true
  6465.                 end
  6466.             end
  6467.             found, position = lib.isSpawner() -- true/false, top/bottom/nil
  6468.             if not found then
  6469.                 if blaze then -- could be behind a wall
  6470.                     print("Assuming blaze spawner behind a wall")
  6471.                     T:forward(1)
  6472.                     moves = moves + 1
  6473.                     while turtle.forward() and not quit do
  6474.                         moves = moves + 1
  6475.                         if moves > 16 then
  6476.                             quit = true
  6477.                         end
  6478.                     end
  6479.                     found, position = lib.isSpawner() -- true/false, top/bottom/nil
  6480.                     if not found then
  6481.                         T:go("R2F"..moves + 2 .."R2")
  6482.                     end
  6483.                 end
  6484.             end
  6485.         end
  6486.        
  6487.         return found, position
  6488.     end
  6489.    
  6490.    
  6491.     if not continue then -- new mob cube either dungeon or blaze
  6492.         -- clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
  6493.         -- determine spawner position level 4, move to top of spawner (level 6)
  6494.         print("Checking if already at spawner")
  6495.         local found, position = lib.isSpawner() -- already on spawner?
  6496.         if blaze then
  6497.             if not found then -- away from spawner
  6498.                 if R.subChoice == 3 then
  6499.                     T:go("U5")
  6500.                 end
  6501.                 found, position = lib.findSpawner(blaze)
  6502.             end
  6503.         else -- go to bottom of dungeon and empty chests
  6504.             if not found then --outside dungeon
  6505.                 local success, message = lib.enterDungeon(R)
  6506.                 if not success then
  6507.                     return {message}
  6508.                 end
  6509.                 found, position = lib.findSpawner(blaze) -- is spawner in front / above / below?
  6510.             end
  6511.         end
  6512.        
  6513.         if found then -- true: move to correct starting position
  6514.             --[[
  6515.             1 |c|c|c|c|c|c|c|c|c|c|c|
  6516.             2 |w| | | | | | | | | |w|
  6517.             3 |w| | | | | | | | | |w|
  6518.             4 |w| | | | | | | | | |w|
  6519.             5 |w| | | | | | | | | |w|
  6520.             6 |w| | | | |s| | | | |w|
  6521.             7 |w| | | | | | | | | |w|
  6522.             8 |w| | | | | | | | | |w|
  6523.             9 |w| | | | | | | | | |w|
  6524.            10 |w| | | | | | | | | |w| exit level for overworld
  6525.            11 |f|f|f|f|f|f|f|f|f|f|f|
  6526.            12 |f|f|f|f|f|f|f|f|f|f|f| sub floor for overworld
  6527.                1 2 3 4 5 6 7 8 9 1 1
  6528.                                  0 1
  6529.             ]]
  6530.             -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  6531.             if position == "bottom" then
  6532.                 T:go("B1U2F1")
  6533.             elseif position == "forward" then
  6534.                 T:go("U1F1")
  6535.             end
  6536.            
  6537.             T:up(1)
  6538.             T:place("slab", "down", true)               -- place slab on top T:place(blockType, direction, leaveExisting)
  6539.             -- go up 2 blocks, forward 5, right, forward 5, right
  6540.             T:go("U2F5 R1F5 R1")                            -- Level 2: now placed 1 below ceiling inside wall, top right corner of new dungeon
  6541.             lib.wallSection(blaze)                          -- fix layers 1, 2, 3 including ceiling margin turtle at Level 2           
  6542.             T:go("F1R2 C1L1 F1R2 C1R1", false, 0, false)    -- exit wall, repair behind, still Level 2
  6543.             lib.ceiling(blaze)                              -- fix ceiling, end opposite corner to start
  6544.             T:go("R2D3")                                    -- clear the inner walls inside original dungeon
  6545.             lib.clearWall(9)                                -- clear the 9 x 9 area around the spawner
  6546.             T:go("F1R1F1L1")
  6547.             lib.clearWall(7)                                -- clear the 7 x 7 area around the spawner
  6548.             T:go("F1R1F1L1")
  6549.             lib.clearWall(5)                                -- clear the 5 x 5 area around the spawner. Also needed for cave spiders
  6550.             T:go("R2F1R1F1R1")
  6551.             T:go("F7R1 F8L1F1R2", false, 0, false)          -- return from ceiling, enter wall below previous section: Level 5
  6552.             lib.wallSection()                               -- deal with areas from spawner level up (4,5,6). walls only   
  6553.             T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8
  6554.             clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 7,8,9
  6555.             T:go("L1F1 L1F1L2", false, 0, false)            -- go inside wall sectio, ready for next wall section
  6556.             lib.wallSection()                               -- deal with walls on levels 7,8,9
  6557.             T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 4 below original floor: Level 11
  6558.             --print("Check: about to clear 3 floors 3 below spawner") read()
  6559.             clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 10,11,12
  6560.            
  6561.             if blaze then
  6562.                 T:go("L1F1 L1F1L2", false, 0, false)            -- ready for next wall section
  6563.                 lib.wallSection()                               -- wall on layers 10,11,12
  6564.                 T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8
  6565.                 clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 13, 14, 15
  6566.             end
  6567.            
  6568.             T:go("L1F1L1F1L2", false, 0, false) -- ready for next wall section
  6569.             --print("Check: level 11, 5 north, 5 east")
  6570.             --read()
  6571.             lib.wallSection()   -- wall on layers 10,11,12 or 12,13,14 if blaze
  6572.             T:go("F1R1 F1R2 C1R1 U1", false, 0, false) -- exit wall, repair behind: Level 10, facing entry point top right corner
  6573.             T:down(1)
  6574.             if blaze then
  6575.                 lib.placeFloor(9, 9, brick)             -- place brick floor on level 14
  6576.                 T:go("L1F4 R1F2 U4")                    -- ends facing out to lower chamber ?below staircase
  6577.                 -- now needs to build killzone
  6578.             else
  6579.                 lib.placeFloor(9, 9, "stone")           -- ends facing wall on entrance side
  6580.                 T:go("U1R2")
  6581.                 lib.placeFloor(9, 9, "stone")           -- ends facing wall on opposite side
  6582.                 -- return to mid-point front
  6583.                 T:go("R2F8 R1F4 L1F2")                  -- exit at bottom of dungeon
  6584.                 T:go("x1U1 x1U1 x1U1 x1D3 R2")          -- rise to chest, then return ready for next stage 
  6585.                 -- ends with turtle facing spawner, in front of exit hole              
  6586.             end
  6587.         else
  6588.             return
  6589.             {
  6590.                 "Spawner not found. Place me on top,",
  6591.                 "immediately below, or facing it.",
  6592.                 "\nEnter to quit"
  6593.             }
  6594.         end
  6595.     end
  6596.     if continue then
  6597.         T:clear()
  6598.         local text =
  6599. [[~yellow~Items required to continue:
  6600.  
  6601. ~lightGray~slabs            81
  6602. ~orange~nether bricks    88
  6603. ~yellow~lava buckets     4
  6604. ~brown~chest / barrel   1
  6605. ~gray~hopper           1      
  6606.  
  6607. ~red~WARNING ~yellow~Inventory ejects items if you
  6608. continue! ~orange~(Choose at next menu.)
  6609.  
  6610. ~white~Next -> Enter]]
  6611.         menu.colourText(nil, text, true)
  6612.         read()
  6613.         pp.itemColours = {colors.red, colors.lime}
  6614.         local choice = menu.new("Choose your option", {"Continue with build", "Re-start later"}, pp, "Type number + Enter") -- 1 = continue, 2= quit
  6615.         if choice == 1 then
  6616.             choice = menu.new("Choose your option", {"Turtle is above me", "Turtle is below or next to me"}, pp, "Type number + Enter") -- 1 = up, 2= down
  6617.             if choice == 1 then
  6618.                 T:emptyInventory("down")
  6619.             else
  6620.                 T:emptyInventory("up")
  6621.             end
  6622.         else
  6623.             return {"Blaze spawner partial build halted"}
  6624.         end
  6625.        
  6626.         --clsTurtle.getItemSlot(self, item, useDamage): return slotData.lastSlot, slotData.leastModifier, total, slotData
  6627.         T:checkInventoryForItem({brick}, {88})
  6628.         T:checkInventoryForItem({"slab"}, {81})
  6629.         T:checkInventoryForItem({"lava"}, {4})
  6630.         T:checkInventoryForItem({"sign"}, {1})
  6631.         T:checkInventoryForItem({"hopper"}, {1})
  6632.         T:checkInventoryForItem({"chest", "barrel"}, {1, 1})
  6633.         print("Stand clear. Starting in 2 secs")
  6634.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  6635.         -- place upper floor and slabs under it
  6636.         T:go("R2D4F2 L1F4 R1U4")   
  6637.         lib.placeFloor(9, 9, brick)             -- place brick floor on level 10
  6638.         T:down(2)
  6639.         T:place(brick, "up")
  6640.         T:go("D1R2")
  6641.         lib.ceiling(true)                       -- true uses slabs
  6642.        
  6643.         -- place lava
  6644.         T:go("L1F4 L1F4 U4")                    -- through hole in ceiling
  6645.         T:go("F4 L1F4 R2")
  6646.         for i = 1, 4 do
  6647.             T:place("lava", "down")
  6648.             T:go("F8 R1")
  6649.         end
  6650.         T:go("F4 R1F4 D2 F1 R2")
  6651.         -- place sign and repair above
  6652.         T:dig("forward")
  6653.         T:place("sign", true, "")
  6654.         T:down(1)
  6655.         T:place(brick, "up")
  6656.         T:forward(1)
  6657.         -- place blocks under exit hole
  6658.         for i = 1, 4 do
  6659.             T:place(brick, "forward")
  6660.             T:turnRight(1)
  6661.         end
  6662.         -- place chest and hopper
  6663.        
  6664.         T:go("D2x2")
  6665.         if not T:place("chest", "down") then
  6666.             T:place("barrel", "down")
  6667.         end
  6668.         T:up(1)
  6669.         T:place("hopper", "down")
  6670.         utils.goBack(1)
  6671.         T:place("slab", "forward")
  6672.         T:go("R2F5U3")-- return to starting point and create entrance
  6673.     end
  6674.     return {}
  6675. end
  6676.  
  6677. local function floodMobFarm(R) -- 63
  6678.     --[[Part 2 / 3 Mob Spawner Farm turtle on floor, pointing towards water source wall, single hole]]
  6679.     local lib ={}
  6680.    
  6681.     function lib.setPosition(addWater)
  6682.         local width = 0
  6683.         while turtle.forward() do end                   -- move forward until hit wall
  6684.         T:go("U1L1")
  6685.         while turtle.forward() do end                   -- move forward until hit left wall
  6686.         if addWater then
  6687.             T:placeWater("down")                        -- place water down
  6688.         end
  6689.         T:turnLeft(2)                                   -- turn round
  6690.         while turtle.forward() do
  6691.             width = width + 1
  6692.         end         -- go forward 7
  6693.         if addWater then                                -- back 1
  6694.             T:placeWater("down")                        -- place water                 
  6695.         end
  6696.         T:go("L2F".. math.floor(width / 2) .."L1")      -- turn round, go forward 3 (centre of wall), turn left
  6697.     end
  6698.  
  6699.     function lib.digFloor()
  6700.         T:go("x2F1 x2")                                 -- first block, move forward
  6701.        
  6702.         T:turnLeft(1)                                   -- left turn, go back into right side, facing left
  6703.         utils.goBack(1)
  6704.         T:go("x2 F1x2 F1x2 R1F1")                       -- go right to left dig 3 blocks, forward on left side
  6705.        
  6706.         T:turnRight(1)                                  -- right turn, go back into left side, facing right
  6707.         utils.goBack(1)
  6708.         T:go("x2 F1x2 F1x2 F1x2 F1x2 L1F1")             -- go left to right dig 5 blocks, forward on right side
  6709.        
  6710.         T:turnLeft(1)                                   -- left turn, go back into right side, facing left
  6711.         utils.goBack(1)
  6712.         T:go("x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 R1F1")   -- go right to left dig 7 blocks, forward on left side
  6713.        
  6714.         T:turnRight(1)                                  -- right turn, go back into left side, facing right
  6715.         utils.goBack(1)
  6716.         T:go("x2 F1x2 F1x2 F1x2 F1x2 F1x2  F1x2  F1x2  F1x2 L1")    -- go left to right dig 5 blocks, face forward on right side
  6717.     end
  6718.    
  6719.     lib.setPosition(false)                  -- move to back of cube and verify position
  6720.     if R.subChoice == 1 then
  6721.         T:forward(3)                        -- forward 4 (centre of chamber)
  6722.     else
  6723.         T:forward(2)                        -- forward 3
  6724.     end
  6725.     T:down(1)
  6726.     lib.digFloor()
  6727.     if R.subChoice == 1 then       
  6728.         T:go("D1F1 L1F8")
  6729.         utils.goBack(4)
  6730.         T:go("L1U1")
  6731.         lib.setPosition(true)               -- place water sources
  6732.         T:go("F8D2")
  6733.         -- go down 2, check floor, up 1, place fence
  6734.         T:go("D2C2U1", false, 0, true)
  6735.         T:place("fence", "down", false)
  6736.         T:go("F1D1C2U1", false, 0, true)
  6737.         T:place("fence", "down", false)
  6738.         T:go("F1U1R2", false, 0, true)
  6739.         T:go("F1R1U1")
  6740.         T:place("sign", "down", false)
  6741.         T:go("U1C0D1")
  6742.         T:place("slab", "up", false)
  6743.         T:go("R2F1R2")
  6744.         T:place("sign", "forward", false)
  6745.         T:go("R1F1R2C1R1F1D1L1") --sitting on soul sand/dirt facing spawner
  6746.         if not T:place("minecraft:soul_sand", "down", false) then
  6747.             T:place("minecraft:dirt", "down", false)
  6748.         end
  6749.     else
  6750.         T:go("D1F1 L1F8")
  6751.         T:go("R1F1 R1F8")
  6752.         utils.goBack(4)
  6753.         T:go("R1U1")
  6754.         lib.setPosition(true)       -- place water sources
  6755.         T:go("F8D2 F1C2C0 F1")      -- exit leaving single hole in wall, facing away from spawner
  6756.     end
  6757.    
  6758.     return {}
  6759. end
  6760.  
  6761. local function createMobBubbleLift(R) -- 64
  6762.     -- Part 3 / 3 Mob Spawner Farm
  6763.     -- R.subChoice = 1 or 2 (left/right)
  6764.     local lib = {}
  6765.    
  6766.     function lib.initialise()
  6767.         local blockType = T:getBlockType("down")
  6768.         if blockType ~= "minecraft:soul_sand" then
  6769.             T:dig("down")
  6770.             if not T:place("minecraft:soul_sand", "down", false) then
  6771.                 return {"Unable to find or place soulsand."}
  6772.             end
  6773.         end
  6774.         -- check facing sign, rotate if not
  6775.         blockType = T:getBlockType("forward")
  6776.         local turns = 0
  6777.         while blockType:find("sign") == nil do
  6778.             T:turnRight(1)
  6779.             turns = turns + 1
  6780.             if turns == 4 then
  6781.                 return {"Unable to find sign."}
  6782.             end
  6783.             blockType = T:getBlockType("forward")
  6784.         end
  6785.         return {""}
  6786.     end
  6787.    
  6788.     function lib.createWaterSource(oTurn)
  6789.         T:go(oTurn.."1")            -- turn to opposite side of dropzone
  6790.         T:go("F1x0D1")
  6791.         for i = 1, 3 do
  6792.             T:go("C2 L1C1 R2C1 L1")
  6793.             if i < 3 then
  6794.                 T:go("F1x0")
  6795.             end
  6796.         end
  6797.         T:go("R2F1")                -- face column move to middle
  6798.         T:placeWater("forward")
  6799.         T:go("R2")                  -- face away
  6800.         T:placeWater("forward")
  6801.         T:go("U1x0 R2F1x0 F1x0"..oTurn.."1")    -- face column, return to soul sand, face spawner
  6802.     end
  6803.    
  6804.     function lib.goToWater(moves)
  6805.         T:down(moves)
  6806.         T:getWater("down")
  6807.         sleep(0.1)
  6808.         T:getWater("down")
  6809.     end
  6810.    
  6811.     function lib.placeCollector(turn, oTurn)
  6812.         local hopperSlot = T:getItemSlot("hopper")
  6813.         local chestSlot = T:getItemSlot("chest")
  6814.         if hopperSlot > 0 and chestSlot > 0 then
  6815.             T:dig("down")
  6816.             T:place("chest", "down")
  6817.             T:go(turn.."1F1"..oTurn.."1")
  6818.             T:dig("down")
  6819.             T:place("chest", "down")
  6820.             T:go(turn.."1")
  6821.             utils.goBack(3)
  6822.             T:go("D1x1")
  6823.             T:place("hopper", "forward")
  6824.             T:go("U1C2F2"..oTurn.."1")
  6825.         end
  6826.     end
  6827.    
  6828.     function lib.up()
  6829.         local moves = 0
  6830.         while turtle.detect() do
  6831.             turtle.up()
  6832.             moves = moves + 1
  6833.         end
  6834.  
  6835.         return moves
  6836.     end
  6837.    
  6838.     function lib.createChamber()
  6839.         local D = {}
  6840.         D.width  = 4
  6841.         D.length = 7
  6842.         D.height = 4
  6843.         D.ceiling = true
  6844.         D.floor = true
  6845.         D.vDirection = "D"
  6846.         D.hDirection = "RL"
  6847.         D.goHome = true
  6848.  
  6849.         utils.createWalledSpace(D)
  6850.     end
  6851.    
  6852.     function lib.mobTransporter()
  6853.         for i = 1, 9 do -- fill in a solid block bar from bubble column for 8 spaces
  6854.             T:go("F1C0C2 R1C1 R1C1 R1C1 R1C1")
  6855.         end
  6856.         T:go("D1C2C1 R1C1 R2C1 L1 C0x0") -- move down column
  6857.         for i = 1, 8 do -- go under solid block bar
  6858.             T:go("F1C2 R1C1 L2C1 R1x0")
  6859.         end
  6860.     end
  6861.    
  6862.     local turn = "R"
  6863.     local oTurn = "L"
  6864.     if R.subChoice == 1 then
  6865.         turn = "L"
  6866.         oTurn = "R"
  6867.     end
  6868.    
  6869.     local data = lib.initialise()           -- check if in the right position
  6870.     if data[1] ~= "" then
  6871.         return data                         -- eg {"Unable to find sign."}
  6872.     end
  6873.     lib.createWaterSource(oTurn)            -- everything in place, build a water source, facing spawner
  6874.     for i = 1, 3 do     -- fill in back and one side, go up
  6875.         T:go(turn.."1C1"..turn.."1C1"..turn.."1x1"..turn.."1U1", false, 0, true)
  6876.     end
  6877.     -- dungeon wall, above mob exit, facing spawner
  6878.     local colHeight = 19
  6879.     for i = 1, colHeight do     -- tunnel up, filling 3 sides
  6880.         T:go(turn.."1C1"..turn.."1C1"..turn.."1x1"..turn.."1C1 U1", false, 0, true)
  6881.     end
  6882.     -- facing spawner 20 blocks up. move either left/right 8 blocks, repairing ceiling and sides
  6883.     T:go("C0"..turn.."2C1"..turn.."1F1 C0C1"..turn.."1C1"..turn.."2C1"..oTurn.."1", false, 0, true) -- fill top of column
  6884.    
  6885.     lib.mobTransporter()
  6886.     T:go("x2x0 F1x2x0 F1x2x0 R2") -- over water source
  6887.     -- now create bubble column
  6888.     T:down(colHeight + 2)
  6889.     local moves = 0
  6890.     repeat
  6891.         lib.goToWater(moves)    -- get water
  6892.         moves = lib.up()
  6893.         T:go("F1")
  6894.         T:placeWater("forward")
  6895.         T:go("U1C2")
  6896.         T:placeWater("forward")
  6897.         utils.goBack(1)
  6898.         T:go("C1")
  6899.         moves = moves + 1
  6900.     until moves >= colHeight + 1
  6901.     lib.goToWater(moves)    -- get water for last time
  6902.     lib.up()                -- finishes above lower part of the transport bar
  6903.     T:go("F2R2C1D1")        -- seal off bubble column
  6904.     utils.goBack(1)
  6905.     T:placeWater("forward") -- place source on top of bubble column
  6906.     utils.goBack(7)         -- over down shaft
  6907.     T:down(1)               -- start shaft, facing bubble column
  6908.     for i = 1, 17 do
  6909.         -- tunnel down, filling all 4 sides
  6910.         T:go("R1C1 R1C1 R1C1 R1C1 D1", false, 0, true)
  6911.     end
  6912.     lib.createChamber()
  6913.     T:go("x0")
  6914.     T:go(oTurn.."1C1".. turn.."1D1C2"..oTurn.."1C1"..turn.."1F1".. oTurn.."1F1"..oTurn.."1") -- facing end wall ready to place slabs
  6915.     for i = 1, 6 do
  6916.         T:place("slab", "down")
  6917.         if i == 6 then
  6918.             T:go(oTurn.."1")
  6919.         end
  6920.         utils.goBack(1)
  6921.         T:go("C1")
  6922.     end
  6923.    
  6924.     T:go("D2F2"..turn.."1F5")
  6925.     T:placeWater("forward")
  6926.     T:go(turn.."1F1"..oTurn.."1") -- facing down mob channel floor
  6927.     for i = 1, 5 do
  6928.         T:go("C1")
  6929.         utils.goBack(1)
  6930.     end
  6931.     T:go("C1"..turn.."1F1"..turn.."1F1")
  6932.     for i = 1, 7 do
  6933.         T:go("C2x0")
  6934.         if i < 7 then
  6935.             T:forward(1)
  6936.         end
  6937.     end
  6938.     T:go("U3R2")
  6939.     for i = 1, 7 do
  6940.         T:go("F1x2")
  6941.     end
  6942.     T:go("D3")
  6943.    
  6944.     lib.placeCollector(turn, oTurn) -- if hopper / chests present
  6945.    
  6946.     return {}
  6947. end
  6948.  
  6949. local function createPlatform(R) -- 56
  6950.     -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  6951.     local forward = true
  6952.     for w = 1, R.width do
  6953.         for l = 1, R.length do
  6954.             T:go("x2C2", false, 0, false, R.useBlockType)
  6955.             if R.up then
  6956.                 T:dig("up")
  6957.             end
  6958.             if l < R.length then
  6959.                 T:forward(1)
  6960.             end
  6961.         end
  6962.         if w < R.width then
  6963.             if forward then
  6964.                 if R.up then
  6965.                     T:go("R1F1 x0R1")
  6966.                 else
  6967.                     T:go("R1F1 R1")
  6968.                 end
  6969.             else
  6970.                 if R.up then
  6971.                     T:go("L1F1 x0L1")
  6972.                 else
  6973.                     T:go("L1F1 L1")
  6974.                 end
  6975.             end
  6976.         end
  6977.         forward = not forward
  6978.     end
  6979.     return {}
  6980. end
  6981.  
  6982. local function createPortal(R) -- 42
  6983.     --[[
  6984.     R.length = length of portal NOT width default 4
  6985.     R.height = height of portal default 5
  6986.     R.width = thickness of portal default 1
  6987.     R.data = "bury" to embed bottom into ground
  6988.     R.subChoice 1 = facing portal, 2 = aligned
  6989.     ]]
  6990.     local lib = {}
  6991.    
  6992.     function lib.buildBase()
  6993.         --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  6994.         T:go("C2", false, 0, false, R.useBlockType)
  6995.         T:forward(1)
  6996.         for i = 1, R.length - 2 do -- R.length = 4: place when i=1,2
  6997.             T:place("minecraft:obsidian", "down", false)
  6998.             T:forward(1)
  6999.         end
  7000.         T:go("C2", false, 0, false, R.useBlockType)
  7001.     end
  7002.    
  7003.     function lib.buildLayer()
  7004.         T:place("minecraft:obsidian", "down", false)
  7005.         for i = 1, R.length - 1 do -- R.length = 4: forward when i=1,2,3
  7006.             T:forward(1)
  7007.         end
  7008.         T:place("minecraft:obsidian", "down", false)
  7009.     end
  7010.    
  7011.     if R.data ~= "bury" then
  7012.         T:up(1)
  7013.     end
  7014.     if R.subChoice == 1 then
  7015.         T:go("F1R1")
  7016.     end
  7017.     local out = true
  7018.     for width = 1, R.width do
  7019.         lib.buildBase()
  7020.         for i = 1, R.height - 2 do
  7021.             T:go("R2U1")
  7022.             out = not out
  7023.             lib.buildLayer()
  7024.         end
  7025.         T:go("R2U1")
  7026.         out = not out
  7027.         lib.buildBase()
  7028.         if out then
  7029.             T:go("R2F"..R.length - 1)
  7030.         end
  7031.         if width < R.width then
  7032.             T:go("R1F1D"..R.height.."R1")
  7033.             out = true
  7034.         else
  7035.             T:go("L1F"..R.width.."D"..R.height - 1 .."R2")
  7036.             if R.data ~= "bury" then
  7037.                 T:down(1)
  7038.             end
  7039.         end
  7040.     end
  7041.    
  7042.     return {}
  7043. end
  7044.  
  7045. local function createPortalPlatform() -- 48
  7046.     --[[ Used in End World to use a trapdoor to push player through portal ]]
  7047.     local lib ={}
  7048.    
  7049.     function lib.findPortal()
  7050.         local found = false
  7051.         local onSide = false
  7052.         for i = 1, 64 do
  7053.             if not turtle.up() then -- hit block above
  7054.                 found = true
  7055.                 break
  7056.             end
  7057.         end
  7058.         if found then
  7059.             -- are we under the centre block, or one of the sides?
  7060.             if turtle.detect() then -- under a side
  7061.                 onSide = true
  7062.             else    -- nothing in front, probably under centre, or facing wrong direction so check
  7063.                 for i = 1, 4 do
  7064.                     turtle.turnRight()
  7065.                     if turtle.detect() then
  7066.                         onSide = true
  7067.                         break
  7068.                     end
  7069.                 end
  7070.             end
  7071.             if onSide then-- move to centre
  7072.                 T:go("D1F1")
  7073.             end
  7074.         end
  7075.         local height = 3 -- allows for 2 bedrock + starting space
  7076.         while turtle.down() do
  7077.             height = height + 1
  7078.         end
  7079.         return found, height
  7080.     end
  7081.    
  7082.     function lib.addFloor(length)
  7083.         for i = 1, length do
  7084.             if i < length then
  7085.                 T:go("C2F1", false, 0, true)
  7086.             else
  7087.                 T:go("C2", false, 0, true)
  7088.             end
  7089.         end
  7090.     end
  7091.    
  7092.     function lib.buildLadder(height)
  7093.         for i = 1, height do
  7094.             --T:go("F1C1 R1C1 L2C1 L1F1L2", false, 0, true)
  7095.             T:go("F1C1 R1C1 L2C1 R1", false, 0, true)
  7096.             utils.goBack(1)
  7097.             if i > 3 then
  7098.                 T:go("C2")
  7099.             end
  7100.             T:place("minecraft:ladder", "forward", true)
  7101.             T:up(1)
  7102.         end
  7103.     end
  7104.    
  7105.     local found, height = lib.findPortal()
  7106.     if found then   -- position under centre of beacon
  7107.         -- build ladder up and create platform
  7108.         T:go("L1F1L1F2L2")
  7109.         T:checkInventoryForItem({"minecraft:ladder"},{height})
  7110.         T:checkInventoryForItem({"stone"},{height * 4 + 18})
  7111.         T:checkInventoryForItem({"trapdoor"},{1})
  7112.         lib.buildLadder(height) -- ends facing ladder, 1 block above
  7113.        
  7114.         T:go("R1")
  7115.         utils.goBack(1)
  7116.         T:go("C2F1 C2F1 C2F1 C2")
  7117.         T:go("R1F1R1")
  7118.         T:go("C2F1 C2F1 C2F1 C2")
  7119.         utils.goBack(2)
  7120.         T:go("R1F1")            -- facing portal entrance
  7121.         T:place("trapdoor", "up", false)
  7122.     else
  7123.         return {"Portal not found. Move me under","the centre if possible.", "wait for purple beacon."}
  7124.     end
  7125.     return {}
  7126. end
  7127.  
  7128. local function createRailway(R) -- 93
  7129.     -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  7130.     --[[
  7131.         Build steps up or down ready for railtrack
  7132.         R.depth = headroom, default 2
  7133.     ]]
  7134.     if R.down then
  7135.         if R.height == 0 then
  7136.             local blockType = ""
  7137.             while blockType == "" do
  7138.                 T:go("F1D1", false, 0, true)
  7139.                 blockType = T:getBlockType("down")
  7140.                 if blockType == "" then
  7141.                     T:go("C2", false, 0, true)
  7142.                 end
  7143.             end
  7144.         else
  7145.             for i = 1, R.height - 1 do
  7146.                 --T:go("U1x0 D1x1 F1x0x1 D1x1 C2", false, 0, false)
  7147.                 T:go("U"..R.depth - 1 .."x0 D"..R.depth - 1 .."x1 F1x0x1 D1x1 C2", false, 0, false)
  7148.             end
  7149.         end
  7150.     elseif R.up then
  7151.         for i = 1, R.height do
  7152.             --T:go("C1U2 x0D1F1", false, 0, false) --put stone in front, up 2 excavate 1, down 1, forward 1
  7153.             T:go("C1U"..R.depth.." x0D"..R.depth.."F1", false, 0, false) --put stone in front, up 2 (or headroom) excavate 1, down 1, forward 1
  7154.         end
  7155.     end
  7156.     return {}
  7157. end
  7158.  
  7159. local function createRectanglePath(R) -- 710, 83 direct commands
  7160.     -- allow user to control length / width of each path
  7161.     -- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  7162.     --local pp = utils.getPrettyPrint()
  7163.     local lib = {}
  7164.    
  7165.     function lib.forward(R)
  7166.         if R.subChoice == 1 then
  7167.             for i = 1, R.length do
  7168.                 T:go("F1x0C2", false, 0, true)
  7169.             end
  7170.         else
  7171.             for i = 1, R.length do
  7172.                 T:go("F1U1C0D1C2", false, 0, true)
  7173.             end
  7174.         end
  7175.     end
  7176.    
  7177.     function lib.back(R)
  7178.         for i = 1, R.length do
  7179.             turtle.back()
  7180.         end
  7181.     end
  7182.    
  7183.     function lib.left(R)
  7184.         T:turnLeft(R.length)
  7185.     end
  7186.    
  7187.     function lib.right(R)
  7188.         T:turnRight(R.length)
  7189.     end
  7190.    
  7191.     function lib.up(R)
  7192.         if R.subChoice == 1 then
  7193.             T:go("U2R2 x1R2 D1C2", false, 0, true)
  7194.         else
  7195.             T:go("U2R2 x1R2C0 D1C2", false, 0, true)
  7196.         end
  7197.     end
  7198.    
  7199.     function lib.down()
  7200.         T:go("D1C2", false, 0, true)
  7201.     end
  7202.    
  7203.     if R.data == "menu" then
  7204.         -- mimics direct commands using f.lua, r.lua etc with space between commands and number
  7205.         local width = 0
  7206.         local length = 0
  7207.         local choices =
  7208.         {
  7209.             "Forward 1 block",
  7210.             "Forward # blocks",
  7211.             "Back 1 block",
  7212.             "Back # blocks",
  7213.             "Turn Right",
  7214.             "Turn Left",
  7215.             "Up 1 block",
  7216.             "Down 1 block",
  7217.             "Quit"
  7218.         }
  7219.         local choice, modifier
  7220.         pp.itemColours = {colors.lime, colors.lime, colors.green, colors.green, colors.orange, colors.orange, colors.cyan, colors.cyan, colors.gray}
  7221.         while choice ~= 9 do
  7222.             choice, modifier = menu.menu("Choose next step", choices, pp, "Type number + Enter ")
  7223.             if choice == 1 then
  7224.                 R.length = 1
  7225.                 lib.forward(R)
  7226.             elseif choice == 2 then
  7227.                 -- getInteger(prompt, minValue, maxValue, row, fg, bg, default)
  7228.                 R.length = menu.getInteger("Move forward how many blocks?", 1, 250, nil, colors.lime)
  7229.                 lib.forward(R)
  7230.             elseif choice == 3 then
  7231.                 R.length = 1
  7232.                 lib.back(R)
  7233.             elseif choice == 4 then
  7234.                 R.length = menu.getInteger("Move back how many blocks?", 1, 250, nil, colors.green)
  7235.                 lib.back(R)
  7236.             elseif choice == 5 then
  7237.                 R.length = 1
  7238.                 lib.right(R)
  7239.             elseif choice == 6 then
  7240.                 R.length = 1
  7241.                 lib.left(R)
  7242.             elseif choice == 7 then
  7243.                 lib.up(R)
  7244.             elseif choice == 8 then
  7245.                 lib.down()
  7246.             end
  7247.         end
  7248.     else
  7249.         local instructions =
  7250. [[~lightGray~Commands:
  7251.  
  7252. direction + ~blue~number ~yellow~eg ~white~f2 ~yellow~= forward ~blue~2
  7253. ~lightGray~direction without number = ~blue~1
  7254.  
  7255. ~yellow~f = forward  ~orange~b = backward
  7256. ~lime~l = left     ~red~r = right
  7257. ~lightGray~u = up       ~cyan~d = down
  7258.  
  7259. ~red~q = quit
  7260.  
  7261. ]] -- Direct control
  7262.         local cmd = ""
  7263.         while cmd ~= "q" do
  7264.             local line = menu.clear()
  7265.             line = menu.colourText(line, instructions)
  7266.             -- menu.getString(prompt, withTitle, minValue, maxValue, row, fg, bg, default)
  7267.             input = menu.getString("command ", false, 1, 5, line, colors.yellow, colors.black):lower()
  7268.             -- remove spaces
  7269.             input = input:gsub( " ", "")
  7270.             cmd = input:sub(1,1)
  7271.             R.length = 1
  7272.             if #input > 1 then
  7273.                 R.length = tonumber(input:sub(2))
  7274.             end
  7275.             if cmd == "q" then
  7276.                 return{"User has quit application"}
  7277.             end
  7278.             if cmd == "f" then
  7279.                 lib.forward(R)
  7280.             elseif cmd == "b" then
  7281.                 lib.back(R)
  7282.             elseif cmd == "l" then
  7283.                 lib.left(R)
  7284.             elseif cmd == "r" then
  7285.                 lib.right(R)
  7286.             elseif cmd == "u" then
  7287.                 lib.up(R)
  7288.             elseif cmd == "d" then
  7289.                 lib.down()
  7290.             end
  7291.         end
  7292.     end
  7293.     return {}
  7294. end
  7295.  
  7296. local function createRetainingWall(R) -- 34, 82
  7297.     -- facing direction wall will take
  7298.     -- will need to rotate 180 to build
  7299.     -- if R.height > 0 then build to specified depth
  7300.     local lib = {}
  7301.        
  7302.     function lib.checkFloor()
  7303.         local newDepth = 0
  7304.         place = utils.clearVegetation("down") -- in case col in front is deeper
  7305.         while place do -- loop will be entered at least once
  7306.             T:down(1)
  7307.             newDepth = newDepth + 1
  7308.             place = utils.clearVegetation("down")
  7309.         end
  7310.         if newDepth > 0 then
  7311.             for j = 1, newDepth do  -- go up until column base is met
  7312.                 T:go("U1C2")
  7313.             end
  7314.         end
  7315.     end
  7316.    
  7317.     function lib.patchMissingBlock()
  7318.         if turtle.back() then
  7319.             T:go("C1")
  7320.         else
  7321.             T:go("B1C1")
  7322.         end
  7323.     end
  7324.    
  7325.     function lib.placeSingle(height)
  7326.         local y = 0
  7327.         if height > 0 then
  7328.             T:go("D"..height)
  7329.             y = height
  7330.         else
  7331.             local place = utils.clearVegetation("down")
  7332.             while place do -- loop will be entered at least once
  7333.                 place = utils.clearVegetation("down")
  7334.                 if place then
  7335.                     T:down(1)
  7336.                     y = y + 1
  7337.                 end
  7338.             end
  7339.         end
  7340.         -- return to surface, placing below
  7341.         for i = 1, y do
  7342.             T:go("U1C2", false, 0, true)
  7343.         end
  7344.     end
  7345.    
  7346.     function lib.placeDouble(height)
  7347.         --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  7348.         local y = 0
  7349.         if not turtle.back() then
  7350.             T:go("B1")
  7351.         end
  7352.         if height > 0 then
  7353.             for i = 1, height do
  7354.                 T:go("C1D1", false, 0, true)
  7355.             end
  7356.             T:go("C1", false, 0, true)
  7357.             y = height
  7358.         else
  7359.             local place = utils.clearVegetation("down")
  7360.             -- build back column
  7361.             while place do -- loop will be entered at least once
  7362.                 place = utils.clearVegetation("down")
  7363.                 if place then
  7364.                     T:go("C1D1", false, 0, true)
  7365.                     y = y + 1
  7366.                 end
  7367.             end
  7368.             -- reached bottom. floor in front could drop down
  7369.             T:go("F1") -- move under first column
  7370.             lib.checkFloor()
  7371.             turtle.back() -- back at starting point
  7372.             T:go("C1", false, 0, true)
  7373.         end
  7374.         -- return to surface, placing below
  7375.         for i = 1, y do
  7376.             T:go("U1C2", false, 0, true)
  7377.         end
  7378.     end
  7379.        
  7380.     function lib.placeTriple(height)
  7381.         --T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  7382.         local y = 0
  7383.         if turtle.back() then
  7384.             T:go("C1")
  7385.         else
  7386.             T:go("B1C1")
  7387.         end
  7388.         if height > 0 then
  7389.             for i = 1, height do
  7390.                 T:go("C1D1", false, 0, true)
  7391.             end
  7392.             for i = 1, height do
  7393.                 T:go("C1D1", false, 0, true)
  7394.             end
  7395.             T:go("C1R2C1", false, 0, true) --fill last block, then turn 180 to build opposite side
  7396.             y = height
  7397.         else
  7398.             local place = utils.clearVegetation("down")
  7399.             -- build back column
  7400.             while place do -- loop will be entered at least once
  7401.                 place = utils.clearVegetation("down")
  7402.                 if place then
  7403.                     T:go("C1D1", false, 0, true)
  7404.                     y = y + 1
  7405.                 end
  7406.             end
  7407.             -- reached bottom. floor in front could drop down
  7408.             T:go("F1") -- move under first column
  7409.             lib.checkFloor()
  7410.             T:go("B1C1R2F1", false, 0, true)
  7411.             lib.checkFloor()
  7412.             T:go("B1C1")
  7413.             -- return to surface , placing below and to front
  7414.         end
  7415.         for i = 1, y do
  7416.             T:go("C1U1C2", false, 0, true)
  7417.         end
  7418.         T:go("F1R2C1", false, 0, true)
  7419.         -- facing back again inside edge of col 3
  7420.         return y -- depth of this run
  7421.     end
  7422.    
  7423.     local topInPlace = false -- topInPlace = true already a path across the water eg monument rectangle
  7424.     if R.data == "withPath" then
  7425.         topInPlace = true
  7426.     end
  7427.     local place = false
  7428.     local inWater = false
  7429.     local onWater = false
  7430.     if not topInPlace then
  7431.         if R.length > 1 then
  7432.             inWater, onWater = utils.getWaterStatus() -- returns whether above water, or immersed
  7433.         end
  7434.     end
  7435.    
  7436.     local maxDepth = 5 --initial estimated value
  7437.     -- start at surface, move back 1 block
  7438.     -- each iteration completes 3 columns
  7439.     local numBlocks = T:getSolidBlockCount()
  7440.     print("Solid blocks in inventory: "..numBlocks)
  7441.    
  7442.     if R.length == 1 then -- single column down to water bed
  7443.         lib.placeSingle(R.height)
  7444.     elseif R.length == 2 then--down then up: 2 cols
  7445.         inWater, onWater = utils.startWaterFunction(onWater, inWater, 2, true) -- move into water
  7446.         T:go("R2") -- move to face player
  7447.         lib.placeDouble(R.height)
  7448.         if not inWater then
  7449.             T:go("U1C2", false, 0, true)
  7450.         end
  7451.     else -- R.length 3 or more
  7452.         if topInPlace then
  7453.             T:down(1) -- break through top
  7454.         else
  7455.             inWater, onWater = utils.startWaterFunction(onWater, inWater, 2, true) -- move into water
  7456.         end
  7457.         T:go("R2") -- move to face player
  7458.         -- now at water surface
  7459.         local remain = R.length
  7460.         while remain >= 3 do
  7461.             numBlocks = T:getSolidBlockCount()
  7462.             print("Inventory blocks: "..numBlocks.." depth: "..maxDepth)
  7463.             if numBlocks < maxDepth * 3 then
  7464.                 --ask player for more
  7465.                 T:checkInventoryForItem({"stone"}, {maxDepth * remain}, false)
  7466.             end
  7467.             local y = lib.placeTriple(R.height) -- moves back, places col in front, centre and behind. R.height = 0 for auto depth
  7468.             if y > maxDepth then
  7469.                 maxDepth = y
  7470.             end
  7471.             remain = remain - 3
  7472.             if remain > 1 then
  7473.                 lib.patchMissingBlock()
  7474.             end
  7475.         end
  7476.         if remain == 1 then -- 1 more column
  7477.             lib.patchMissingBlock()
  7478.             lib.placeSingle(R.height)
  7479.         elseif remain == 2 then -- 2 cols
  7480.             lib.placeDouble(R.height)
  7481.         end
  7482.         T:go("U1C2") -- above surface
  7483.     end
  7484.     return {}
  7485. end
  7486.  
  7487. local function createSafeDrop(R) -- 14
  7488.     -- dig down height blocks, checking for blocks on all sides
  7489.     local drop = 0
  7490.     local isBedrock = false
  7491.     T:down(2)
  7492.     drop = 2
  7493.     for i = 1, R.height - 1 do
  7494.         for j = 1, 4 do
  7495.             -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  7496.             T:go("C1R1", false, 0, true)
  7497.         end
  7498.         if T:down(1) then
  7499.              drop = drop + 1
  7500.         else
  7501.             isBedrock = true
  7502.             break
  7503.         end
  7504.         if T:isWaterOrLava("up") ~= "" then
  7505.             T:go("C0x0", false, 0, false) -- delete water/ lava block
  7506.         end
  7507.     end
  7508.     if not isBedrock then -- not sitting on bedrock, so break foot level exit block
  7509.         T:go("U1R2x1")
  7510.     end
  7511.     T:placeWater("down")
  7512.     if isBedrock then
  7513.         T:go("U1x1 U1x1")
  7514.     else
  7515.         T:go("U1x1")
  7516.     end
  7517.     T:up(drop - 2)
  7518.    
  7519.     return {"Safe drop completed "..drop .. " blocks"}
  7520. end
  7521.  
  7522. local function createSlopingWater(R) -- 34, 89
  7523.     --[[
  7524.     creates a sloping water area above existing lake/river/ocean
  7525.     R.width is usually 7 with an existing wall on 8th row
  7526.     R.length  is user choice, limited to bucket/slab quantities
  7527.     Places slabs into existing surface, places row of sources
  7528.     Removes slabs
  7529.     ]]
  7530.     local lib = {}
  7531.    
  7532.     function lib.fillBuckets()
  7533.         local emptyBuckets = utils.getEmptyBucketCount()
  7534.         for i = 1, emptyBuckets do
  7535.             if utils.fillBucket("down") then
  7536.                 print("Bucket filled down")
  7537.                 sleep(0.3)
  7538.             else
  7539.                 print("Unable to fill bucket ".. i .." / "..emptyBuckets)
  7540.             end
  7541.         end
  7542.         return utils.getWaterBucketCount()
  7543.     end
  7544.    
  7545.     local outbound = true
  7546.     local inWater, onWater = utils.getWaterStatus()
  7547.     inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,false) -- move above water, max descent 2
  7548.     local waterBuckets = lib.fillBuckets()
  7549.     for w = 1, R.width do
  7550.         for l = 1, R.length do
  7551.             T:place("slab", "down", false)
  7552.             if l < R.length then
  7553.                 T:forward(1)
  7554.             end
  7555.         end
  7556.         if w < R.width then
  7557.             if outbound then
  7558.                 T:go("R1F1R1")
  7559.             else
  7560.                 T:go("L1F1L1")
  7561.             end
  7562.             outbound = not outbound
  7563.         end
  7564.     end
  7565.     if outbound then
  7566.         T:go("L1F"..R.width - 1 .."L1")
  7567.     else
  7568.         T:go("R1F"..R.width - 1 .."R1")
  7569.     end
  7570.     T:placeWater("up")  -- place in corner
  7571.     local move = true
  7572.     while move do
  7573.         move = turtle.forward()
  7574.         move = turtle.forward() -- false if at end of run
  7575.         T:placeWater("up")  -- alternate positions + end of run
  7576.     end
  7577.     T:go("R2D1")
  7578.     T:sortInventory() -- get all buckets into 1 slot
  7579.     for w = 1, R.width do
  7580.         for l = 1, R.length do
  7581.             if l < R.length then
  7582.                 T:forward(1)
  7583.             end
  7584.         end
  7585.         if w < R.width then
  7586.             if outbound then
  7587.                 T:go("R1F1R1")
  7588.             else
  7589.                 T:go("L1F1L1")
  7590.             end
  7591.             outbound = not outbound
  7592.         end
  7593.     end
  7594.     if outbound then
  7595.         T:go("L1F"..R.width - 1 .."L1")
  7596.     else
  7597.         T:go("R1F"..R.width - 1 .."R1")
  7598.     end
  7599.     T:go("U2")
  7600.    
  7601.     return {}
  7602. end
  7603.  
  7604. local function createSquidFarmBase(R) -- 34
  7605.     -- dig down to y=45. assume starting at water level (64)
  7606.     local depth = 0
  7607.     local message =
  7608. [[Place the turtle under the grid
  7609. left corner above current pit
  7610. opening.
  7611. It will descend to the base and
  7612. continue to level y=45.
  7613.  
  7614. Enter to continue...
  7615. ]]
  7616.     read()
  7617.     while turtle.down()do
  7618.         depth = depth + 1
  7619.     end
  7620.     T:down(1)
  7621.     R.height = 21 - depth
  7622.     R.width = 15
  7623.     R.length = 15
  7624.     R.silent = true
  7625.     R.data = "down"
  7626.     clearSolid(R)
  7627.     T:up(depth + 4)
  7628.     return {}
  7629. end
  7630.  
  7631. local function createSandWall(R) -- 81
  7632.     local success = true
  7633.     --move above water
  7634.     local maxMove = 2
  7635.     while turtle.detectDown() and maxMove > 0 do
  7636.         T:forward(1)
  7637.         maxMove = maxMove - 1
  7638.     end
  7639.     if R.length > 0 then
  7640.         for i = 1, R.length - 1 do
  7641.             success = utils.dropSand()
  7642.             T:forward(1, false)
  7643.         end
  7644.         success = utils.dropSand()
  7645.     else
  7646.         while not turtle.detectDown() do -- over water
  7647.             while not turtle.detectDown() do -- nested to allow forward movement
  7648.                 success = utils.dropSand() -- drops sand and checks supplies
  7649.             end
  7650.             if success then
  7651.                 T:forward(1, false)
  7652.             else -- out of sand
  7653.                 break
  7654.             end
  7655.         end
  7656.     end
  7657.     return {}
  7658. end
  7659.  
  7660. local function createSinkingPlatform(R) -- 58
  7661.     local lib = {}
  7662.    
  7663.     function lib.stage1a(R)                         -- build side wall left side
  7664.         for l = 1, R.length do                      --            | |*| |
  7665.             T:go("L1C1 R1C2", false, 0, false)      -- |*|>| | to |*|>| | place left wall
  7666.             if l == 1 then                          -- first iteration
  7667.                 T:go("U1C2 D1 F1C2", false, 0, false)-- |*|>| | to |*|*|>| up/down block to delete source at corner
  7668.             elseif l < R.length then                -- mid run
  7669.                 T:go("F1C2", false, 0, false)       -- |*|>| | to |*|*|>| move forward
  7670.             else                                    -- end of run
  7671.                 T:go("C1U1 C2D1", false, 0, false)  -- |*|>| | to |*|>|*| place end wall
  7672.             end
  7673.         end
  7674.     end
  7675.    
  7676.     function lib.stage1b(R)                         -- same as stage1a on right side
  7677.         for l = 1, R.length do
  7678.             T:go("R1C1 L1C2", false, 0, false)
  7679.             if l == 1 then
  7680.                 T:go("U1C2 D1 F1C2", false, 0, false)
  7681.             elseif l < R.length then
  7682.                 T:go("F1C2", false, 0, false)
  7683.             else
  7684.                 T:go("C1U1 C2D1", false, 0, false)
  7685.             end
  7686.         end
  7687.     end
  7688.    
  7689.     function lib.stage2(forward)
  7690.         if forward then
  7691.             T:go("C1R1 F1L1 C1R2", false, 0, false)
  7692.         else
  7693.             T:go("C1L1 F1R1 C1L2", false, 0, false)
  7694.         end
  7695.     end
  7696.        
  7697.     local forward = true
  7698.     local goingRight = true
  7699.     local blockType = T:getBlockType("down")
  7700.     if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
  7701.         T:up(1)
  7702.     end
  7703.     for h = 1, R.height do                      -- repeatedly create a platform, move down and repeat
  7704.         T:down(1)                               -- move down into existing platform
  7705.         if goingRight then                      -- first side
  7706.             if forward then                     -- complete left side
  7707.                 T:go("R2C1 L2", false, 0, false) -- | |>| | to |*|<| | to |*|>| |
  7708.                 lib.stage1a(R)                  -- build left wall
  7709.                 T:go("R1F1 L1C1 R2C2", false, 0, false)         -- turn ready for next side
  7710.             else
  7711.                 T:go("L2C1 R2", false, 0, false) -- block 1, 1
  7712.                 lib.stage1b(R)                  -- turn ready for next side
  7713.                 T:go("L1F1 R1C1 L2C2", false, 0, false)
  7714.             end
  7715.         else                                    -- on right side so different approach
  7716.             if forward then
  7717.                 T:go("L2C1 R2", false, 0, false) -- | |<| | to | |>|* | to | |<|*|
  7718.                 lib.stage1b(R)                 
  7719.                 T:go("C1L1 F1R1 C1L2 C2", false, 0, false)      -- turn ready for next side
  7720.             else                                -- complete left side
  7721.                 T:go("R2C1 L2", false, 0, false) -- block 1, 1
  7722.                 lib.stage1a(R)                  -- turn ready for next side
  7723.                 T:go("C1R1 F1L1 C1R2 C2", false, 0, false)
  7724.             end
  7725.         end
  7726.         forward = not forward                   -- continue strips across until at far edge
  7727.         for w = 1, R.width - 2 do
  7728.             for l = 1, R.length do
  7729.                 if l < R.length then
  7730.                     T:go("C2F1", false, 0, false)
  7731.                 else
  7732.                     T:go("C2", false, 0, false)
  7733.                 end
  7734.             end
  7735.             if goingRight then
  7736.                 lib.stage2(forward)
  7737.             else
  7738.                 lib.stage2(not forward)
  7739.             end
  7740.             forward = not forward
  7741.         end                                     -- far side
  7742.         if goingRight then
  7743.             if forward then
  7744.                 lib.stage1b(R)
  7745.             else
  7746.                 lib.stage1a(R)
  7747.             end
  7748.         else
  7749.             if forward then
  7750.                 lib.stage1a(R)
  7751.             else
  7752.                 lib.stage1b(R)
  7753.             end
  7754.         end
  7755.         goingRight = not goingRight
  7756.         T:turnRight(2)
  7757.         forward = not forward
  7758.     end
  7759.     return {}
  7760. end
  7761.  
  7762. local function createStaircase(R) -- 13
  7763.     -- R# L# F# B# U# D# +0 -0 = Right, Left, Forward, Back, Up, Down, up while detect and return, down while not detect
  7764.     -- dig:           x0,x1,x2 (up/fwd/down)
  7765.     -- suck:          s0,s1,s2
  7766.     -- place chest:   H0,H1,H2
  7767.     -- place sapling: S0,S1,S2
  7768.     -- place Torch:   T0,T1,T2
  7769.     -- place Hopper:  P0,P1,P2
  7770.     -- mine floor:    m# = mine # blocks above and below, checking for valuable items below, and filling space with cobble or dirt
  7771.     -- mine ceiling:  M# = mine # blocks, checking for valuable items above, and filling space with cobble or dirt
  7772.     -- mine ceiling:  N# same as M but not mining block below unless valuable
  7773.     -- place:         C,H,r,S,T,P,^ = Cobble / cHest / DIrT / Sapling / Torch / hoPper /stair in direction 0/1/2 (up/fwd/down) eg C2 = place cobble down
  7774.    
  7775.     -- 3| |B| |
  7776.     --   - - -
  7777.     -- 2|A| |C|
  7778.     --   - - -
  7779.     -- 1|^|D| |
  7780.     --   - - -
  7781.     --   1 2 3
  7782.     local lib = {}
  7783.    
  7784.     function lib.checkFluids()
  7785.         local isFluid = false
  7786.         -- check if water or lava present
  7787.         for i = 1, 4 do
  7788.             blockType = T:isWaterOrLava("forward")
  7789.             if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then
  7790.                 isFluid = true
  7791.             end
  7792.         end
  7793.         return isFluid
  7794.     end
  7795.    
  7796.     function lib.createStaircaseSection(onGround, levels, level)
  7797.         -- start 1,1,1, n
  7798.         -- stage A
  7799.         local isFluid = lib.checkFluids()
  7800.         local blockType = ""
  7801.         local data = T:getStock("stairs")
  7802.         if data.total == 0 then
  7803.             T:craft('stairs', 4)
  7804.         end
  7805.         if onGround and isFluid then
  7806.             -- add right side and block entrance
  7807.             T:go("R1C1R1C1R2")
  7808.         end
  7809.         if isFluid then
  7810.             T:go("L1C1 R1F1C2 L1C1 R1x1 R1C1 L1C2B1 C1x1 ^1C2", false, 0, true) --start:1,1,1,n stairs A on level 1, going back to 1,1,1,n
  7811.         else
  7812.             T:go("F1x1 R1C1 L1C2B1 ^1C2", false, 0, true)
  7813.         end
  7814.         if not onGround then
  7815.             -- stage A1
  7816.             T:go("L2C1L2", false, 0, true) -- start 1,1,1,n fix corner on level 1 end: 1,1,1,n
  7817.         end
  7818.         -- stage B
  7819.         T:go("U1L1", false, 0, true) -- end  1,1,1,w layer 2
  7820.         level = level + 1
  7821.         isFluid = lib.checkFluids()
  7822.         if isFluid then
  7823.             T:go("C1", false, 0, true) -- end  1,1,1,w layer 2
  7824.         end
  7825.         if not onGround then
  7826.             if isFluid then
  7827.                 T:go("L1C1R1", false, 0, true) -- end  1,1,1,w layer 2
  7828.             end
  7829.         end
  7830.         -- stage C1
  7831.         if isFluid then
  7832.             T:go("R1C1F1C1x1 L1C1 R2C1 L1B1", false, 0, true)
  7833.         else
  7834.             T:go("R1F1 R1C1 L1B1", false, 0, true)
  7835.         end
  7836.         --level = level + 1
  7837.         --if level == levels then
  7838.             --return false, level
  7839.         --end
  7840.         -- stage C2
  7841.         T:go("U1")
  7842.         level = level + 1
  7843.         --if level == levels then
  7844.             --return true, level
  7845.         --end
  7846.         isFluid = lib.checkFluids()
  7847.         if isFluid then
  7848.             T:go("L1C1L1 C1L2 C1F1L1 C1R2 C1L1 B1C2 D1", false, 0, true) -- end 1,1,2,n
  7849.         else
  7850.             T:go("F1R1 C1L1 B1D1", false, 0, true) -- end 1,1,2,n
  7851.         end
  7852.         level = level - 1 -- went down in branch above
  7853.         --if level == levels then
  7854.             --return false, level
  7855.         --end
  7856.         -- stage D
  7857.         isFluid = lib.checkFluids()
  7858.         if isFluid then
  7859.             T:go("C1F1C1F1C1x1L1 C1R1 C1R1", false, 0, true) -- 3,1,2,e
  7860.         else
  7861.             T:go("F2 C1R1", false, 0, true) -- 3,1,2,e
  7862.         end
  7863.        
  7864.         return false, level
  7865.     end
  7866.  
  7867.     --local height = currentLevel -- eg 64 at top or 5 at bedrock
  7868.     local data = T:getStock("stairs")
  7869.     --{rt.total, rt.mostSlot, rt.leastSlot, rt.mostCount, rt.leastCount}
  7870.     local numStairs = data.total
  7871.     local levels = math.abs(R.depth - R.height) --height of stairs
  7872.     local numStairsNeeded = levels
  7873.     numStairsNeeded = numStairsNeeded - numStairs
  7874.     if numStairsNeeded > 40 then
  7875.         print('crafting '..numStairsNeeded..' : '..numStairs.. ' in stock')
  7876.         if T:craft('stairs', 40) then   -- max 40 so repeat
  7877.             data = T:getStock("stairs")
  7878.             if data.total == 0 then
  7879.                 data = T:getStock("stairs")
  7880.             end
  7881.             numStairs = data.total
  7882.             numStairsNeeded = numStairsNeeded - numStairs
  7883.         else
  7884.             return {"Unable to craft stairs"}
  7885.         end
  7886.     end
  7887.     if numStairsNeeded > 0 then
  7888.         T:craft('stairs', numStairsNeeded)
  7889.     end
  7890.     local level = 0
  7891.     if R.down then -- go down towards bedrock
  7892.         local atBedrock = false
  7893.         for i = 1, levels do
  7894.             level = level - 1
  7895.             if not T:down() then
  7896.                 atBedrock = true
  7897.                 break
  7898.             end
  7899.         end
  7900.         if atBedrock then -- hit bedrock so get to level 5 / -59
  7901.             level = T:findBedrockTop(level)
  7902.             T:go("R1F1R1", false, 0, true)
  7903.         end
  7904.     end
  7905.     local onGround = true
  7906.     level = 0
  7907.     while level < levels do
  7908.         onGround, level = lib.createStaircaseSection(onGround, levels, level)
  7909.     end
  7910.     if not turtle.detectDown() then
  7911.         T:go("C2")
  7912.     end
  7913.    
  7914.     return{"Staircase completed"}
  7915. end
  7916.  
  7917. local function createStripMine(R)
  7918.     --[[
  7919.     R.length should be a multiple of 16
  7920.     mine a corridoor repairing floor and ceiling
  7921.     check sides, remove valuable items
  7922.     plug if lava present
  7923.     Every 16 blocks dig a side passage 1 block deep 2 blocks long
  7924.     ]]
  7925.     local lib = {}
  7926.    
  7927.     function lib.seal(R)   
  7928.         if T:isValuable("forward") then -- valuable block in front. If debris then refuse already dumped
  7929.             T:dig("forward")
  7930.         end
  7931.         local blockType = T:getBlockType("forward")
  7932.         if blockType:find("lava") ~= nil then
  7933.             --T:place("stone", "forward", false) -- place does not allow for specific blocktype
  7934.             T:go("C1", false, 0, false, R.useBlockType)
  7935.             return true
  7936.         end
  7937.        
  7938.         return false
  7939.     end
  7940.    
  7941.     function lib.checkSeal(R)
  7942.         local retValue = false
  7943.         T:turnRight(1)
  7944.         if lib.seal(R) then
  7945.             retValue = true
  7946.         end
  7947.         T:turnLeft(2)
  7948.         if lib.seal(R) then
  7949.             retValue = true
  7950.         end
  7951.         T:turnRight(1)
  7952.         return retValue
  7953.     end
  7954.        
  7955.     function lib.alcove(R)
  7956.         -- right side, starting at ceiling
  7957.         T:go("R1F1 C0", false, 0, false, R.useBlockType)-- stone ceiling, facing alcove wall (upper)
  7958.         lib.seal(R)                                     -- seal alcove wall (upper)
  7959.         T:go("D1C2", false, 0, false, "cobble")         -- cobble floor, facing alcove wall (lower)
  7960.         lib.seal(R)                                     -- seal alcove wall (lower)    
  7961.         T:go("L2 F1")                                   -- down 1, turn round, return to corridoor.
  7962.         -- left side   
  7963.         T:go("F1 C2", false, 0, false, "cobble")        -- cobble floor, facing alcove wall (lower)
  7964.         lib.seal(R)                                     -- seal alcove wall (lower)
  7965.         T:go("U1 C0", false, 0, false, R.useBlockType)  -- stone ceiling, still facing alcove wall
  7966.         lib.seal(R)                                     -- seal alcove wall (upper)                    
  7967.         T:go("L2F1L1")                                  -- return to corridoor at ceiling position
  7968.         lib.placeTorch(R)                              
  7969.     end
  7970.    
  7971.     function lib.placeTorch(R)
  7972.         if R.torchInterval > 0 then                     -- torches onboard
  7973.             if T:getItemSlot("minecraft:torch") > 0 then
  7974.                 T:place("minecraft:torch", "down")
  7975.             end
  7976.         end
  7977.     end
  7978.    
  7979.     local seal = false
  7980.     if T:getItemSlot("minecraft:torch") == 0 then
  7981.         R.torchInterval = 0 -- set to default 16 above
  7982.     end
  7983.     for steps = 1, R.length do
  7984.         -- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  7985.         T:go("C2U1C0", false, 0, true, R.useBlockType)      -- check and repair floor / ceiling
  7986.         if steps % 16 == 0 or steps % 16 == 1 then
  7987.             lib.alcove(R) -- enter and exit at ceiling position
  7988.         else
  7989.             seal = lib.checkSeal(R)
  7990.         end
  7991.         T:go("F1D1", false, 0, true)
  7992.         seal = lib.checkSeal(R)
  7993.     end
  7994.     if seal then -- water or lava found while tunnelling
  7995.         T:go("U1C0", false, 0, true, R.useBlockType)
  7996.         lib.checkSeal(R)
  7997.         T:go("C1", false, 0, true, R.useBlockType)
  7998.         T:down(1)
  7999.     end
  8000.     return {}
  8001. end
  8002.  
  8003. local function createTreefarm(R) -- 22
  8004.     local lib = {}
  8005.     --go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
  8006.     function lib.buildWallSection(section, useBlockType)
  8007.         -- build a layer 1 block high below turtle
  8008.         for i = 1, #section do
  8009.             local block = section:sub(i, i)
  8010.             if block == "l" then
  8011.                 T:place("log", "down")
  8012.             elseif block == "m" then
  8013.                 T:place("modem", "down")
  8014.             elseif block == "b" then
  8015.                 T:place("barrel", "down")
  8016.             elseif block == "c" then
  8017.                 T:place("cable", "down")
  8018.             else
  8019.                 T:place(useBlockType, "down")
  8020.             end
  8021.             if i < #section then
  8022.                 T:forward(1)
  8023.             end
  8024.         end
  8025.     end
  8026.    
  8027.     function lib.placeFloor(length, useBlockType)
  8028.         for i = 1, length do
  8029.             while turtle.digUp() do end
  8030.             turtle.digDown()
  8031.             T:place(useBlockType, "down")
  8032.             --T:go("x0C2", false, 0, false, useBlockType)
  8033.             if i < length then
  8034.                 while not turtle.forward() do
  8035.                     turtle.dig()
  8036.                 end
  8037.                 --T:forward(1)
  8038.             end
  8039.         end
  8040.     end
  8041.    
  8042.     function lib.placeWater(length)
  8043.         T:placeWater("down")
  8044.         T:go("F"..length.."R1")
  8045.     end
  8046.    
  8047.     function lib.placeCorners(length, numBlocks, useBlockType)
  8048.         for i = 1, numBlocks do
  8049.             T:go("C2F1", false, 0, false, useBlockType)
  8050.         end
  8051.         -- now at 5th space
  8052.         T:forward(length - (numBlocks * 2))
  8053.         for i = 1, numBlocks do
  8054.             T:go("C2", false, 0, false, useBlockType)
  8055.             if i < numBlocks then
  8056.                 T:forward(1)
  8057.             end
  8058.         end
  8059.     end
  8060.    
  8061.     function lib.turn(outward)
  8062.         if outward then
  8063.             T:go("R1F1R1")
  8064.         else
  8065.             T:go("L1F1L1")
  8066.         end
  8067.         return not outward
  8068.     end
  8069.    
  8070.     function lib.findLegacyStart()
  8071.         T:turnRight(1)
  8072.         local block = T:getBlockType("down")
  8073.         if block:find("polished") ~= nil then
  8074.             return ""   -- in correct position, facing centre of front wall
  8075.         end
  8076.         -- assume on left corner
  8077.         T:forward (1)
  8078.         local couint = 0
  8079.         while (T:getBlockType("down")):find("polished") == nil do
  8080.             T:forward(1)
  8081.             count = count + 1
  8082.             if count > 10 then
  8083.                 return "Unable to locate polished block"
  8084.             end
  8085.         end
  8086.         return ""
  8087.     end
  8088.    
  8089.     function lib.floodFarm(R)
  8090.         local outward = true
  8091.         T:sortInventory(false)
  8092.         for i = 1, R.width - 2 do
  8093.             lib.placeFloor(R.length - 2, R.useBlockType)
  8094.             if i < R.width - 2 then
  8095.                 outward = lib.turn(outward)
  8096.             end
  8097.         end
  8098.         T:go("U1R2") -- over 13 x 13 internal area opposite corner
  8099.         -- now add corners
  8100.         lib.placeCorners(R.length - 2, 4, R.useBlockType)
  8101.         outward = lib.turn(outward)
  8102.         lib.placeCorners(R.length - 2, 3, R.useBlockType)
  8103.         outward = lib.turn(outward)
  8104.         lib.placeCorners(R.length - 2, 2, R.useBlockType)
  8105.         outward = lib.turn(outward)
  8106.         lib.placeCorners(R.length - 2, 1, R.useBlockType)
  8107.         if outward then
  8108.             T:go("R1F"..R.width - 9 .."R1")
  8109.         else
  8110.             T:go("L1F"..R.width - 9 .."L1")
  8111.         end
  8112.         outward = not outward
  8113.         lib.placeCorners(R.length - 2, 1, R.useBlockType)
  8114.         outward = lib.turn(outward)
  8115.         lib.placeCorners(R.length - 2, 2, R.useBlockType)
  8116.         outward = lib.turn(outward)
  8117.         lib.placeCorners(R.length - 2, 3, R.useBlockType)
  8118.         outward = lib.turn(outward)
  8119.         lib.placeCorners(R.length - 2, 4, R.useBlockType) -- should be back in starting corner facing front
  8120.        
  8121.         T:go("U1R1")
  8122.         lib.placeWater(R.length - 3) -- place water down then move forward, turn right
  8123.         lib.placeWater(R.width - 3)
  8124.         lib.placeWater(R.length - 3)
  8125.         lib.placeWater(R.width - 3)
  8126.         T:go("F".. math.floor((R.length - 2) / 2).."R1F".. math.floor((R.width - 2) / 2)) -- should be in centre
  8127.        
  8128.         --T:go("D6x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 R1F7 R1U1")
  8129.         T:go("D6F7 R1F7 R1U1") -- end facing back at left corner, 1 block above floor/1 below ceiling
  8130.     end
  8131.    
  8132.     function lib.clearBasement()
  8133.         T:sortInventory(false)
  8134.         T:dropItem("seeds", "forward")
  8135.         T:dropItem("flint", "forward")
  8136.         clearRectangle({width = 15, length = 15, up = true, down = true})
  8137.         -- area has been cleared. starts facing back, 1 block above ground, 1 block below ceiling
  8138.         T:go("R1U1")
  8139.         for i = 1, 14 do    -- place cable into gutter beneath front of farm
  8140.             T:place("cable", "up")
  8141.             if i < 14 then
  8142.                 T:forward(1)
  8143.             end
  8144.         end
  8145.         -- ends right side facing right, just below ceiling
  8146.     end
  8147.    
  8148.     local blockType
  8149.     local blockModifier
  8150.    
  8151.     -- R.data = "new", "left", "right" or "back" to extend tree farm
  8152.     -- R.up = true if clear area
  8153.     -- R.networkFarm to create storage area
  8154.     if R.up then
  8155.         clearArea(R)
  8156.     end
  8157.     -- R.data = "new", "left", "right", "back", "convertStorage", "convert"
  8158.     if R.data == "new" then -- new treeFarm, Start at current position
  8159.         -- build 4 wall sections in 2 passes
  8160.         T:down(1)
  8161.         lib.buildWallSection("---------------", R.useBlockType)     -- left wall (15 blocks)
  8162.         T:go("R1F1")
  8163.         for i = 1, 2 do
  8164.             lib.buildWallSection("--------------", R.useBlockType)  -- back/ right wall (14 blocks)
  8165.             T:go("R1F1")
  8166.         end
  8167.         lib.buildWallSection("------c------", R.useBlockType)       -- front wall (14 blocks) c = network cable
  8168.         T:go("U1F1R1")
  8169.         lib.buildWallSection("---------------", R.useBlockType)     -- left wall top (15 blocks)
  8170.         T:go("R1F1")
  8171.         for i = 1, 2 do
  8172.             lib.buildWallSection("--------------", R.useBlockType)  --back/right wall (14 blocks)
  8173.             T:go("R1F1")
  8174.         end
  8175.         --lib.buildWallSection("-----lmb-----", R.useBlockType) --front wall (14 blocks) log/modem/barrel
  8176.         lib.buildWallSection("-----lmb", R.useBlockType)
  8177.         utils.goBack(1)
  8178.         network.attachModem()
  8179.         T:forward(2)
  8180.         lib.buildWallSection("-----", R.useBlockType)  
  8181.         T:go("R1F1 D2") -- over 13 x 13 internal area
  8182.     elseif R.data == "left" or R.data == "right" or R.data == "back" then
  8183.         -- build 3 wall sections in 2 passes
  8184.         if R.data == "left" then                                        -- should be on left corner of existing
  8185.             T:go("L1F1 D1")                                             -- move left 1 blocks, down 1: <-
  8186.             lib.buildWallSection("------c-------", R.useBlockType)      -- front wall (14 blocks) c = network cable <-
  8187.             T:go("R1F1")
  8188.             lib.buildWallSection("--------------", R.useBlockType)      -- left wall (14 blocks) ^
  8189.             T:go("R1F1")
  8190.             lib.buildWallSection("-------------", R.useBlockType)       -- back wall (13 blocks) ->
  8191.             T:go("U1R2")                                                -- turn round ready to add next layer <-
  8192.             lib.buildWallSection("--------------", R.useBlockType)      -- back wall top (14 blocks) <-
  8193.             T:go("L1F1")
  8194.             lib.buildWallSection("--------------", R.useBlockType)      -- left wall top (14 blocks) v
  8195.             T:go("L1F1")
  8196.             lib.buildWallSection("-----bm", R.useBlockType)             -- front wall (7 blocks) barrel/modem ->
  8197.             network.attachModem()
  8198.             T:forward(1)
  8199.             lib.buildWallSection("l-----", R.useBlockType)              -- front wall (5 blocks) log ->
  8200.             T:go("R2F12 R1F1 D2")                                       -- over 13 x 13 internal area lower left side
  8201.         elseif R.data == "right" then                                   -- should be on right corner of existing
  8202.             T:go("R1F1 D1")                                             -- move right, forward, down 1
  8203.             lib.buildWallSection("------c-------", R.useBlockType)      -- front wall (14 blocks) c = network cable
  8204.             T:go("L1F1")
  8205.             lib.buildWallSection("--------------", R.useBlockType)      -- right wall (14 blocks)
  8206.             T:go("L1F1")
  8207.             lib.buildWallSection("-------------", R.useBlockType)       -- back wall (13 blocks)
  8208.             T:go("U1R2")                                                -- turn round ready to add next layer
  8209.             lib.buildWallSection("--------------", R.useBlockType)      -- back wall top (14 blocks)
  8210.             T:go("R1F1")
  8211.             lib.buildWallSection("--------------", R.useBlockType)      -- left wall top (14 blocks)
  8212.             T:go("R1F1")
  8213.             lib.buildWallSection("-----lmb", R.useBlockType)
  8214.             utils.goBack(1)
  8215.             network.attachModem()
  8216.             T:forward(2)
  8217.             lib.buildWallSection("-----", R.useBlockType)  
  8218.             T:go("R1F1 D2")                                             -- over 13 x 13 internal area
  8219.         elseif R.data == "back" then                                    -- should be on left front corner of existing
  8220.             T:go("R2F1 D4R2 F1")                                        -- move forward 14 blocks, down 1
  8221.             for i = 1, 15 do
  8222.                 T:place("cable", "up")
  8223.                 T:forward(1)
  8224.             end
  8225.             T:up(1)
  8226.             if T:getBlockType("up") == R.useBlockType then              -- already a farm on left side
  8227.                 T:go("U2C2 U1C2 F13R1 F1D1", false, 0, false, R.useBlockType)
  8228.                 lib.buildWallSection("--------------", R.useBlockType)  -- back wall (14 blocks)
  8229.                 T:go("R1F1")
  8230.             else
  8231.                 T:up(2)
  8232.                 lib.buildWallSection("--------------", R.useBlockType)  -- left wall (14 blocks)
  8233.                 T:go("R1F1")
  8234.                 lib.buildWallSection("--------------", R.useBlockType)  -- back wall (14 blocks)
  8235.                 T:go("R1F1")
  8236.             end
  8237.  
  8238.             lib.buildWallSection("-------------", R.useBlockType)       --right wall (13 blocks) no special blocks
  8239.             T:go("U1R2")    -- turn round ready to add next layer
  8240.             for i = 1, 2 do
  8241.                 lib.buildWallSection("--------------", R.useBlockType)  --right wall top (14 blocks) no special blocks
  8242.                 T:go("L1F1")
  8243.             end
  8244.             lib.buildWallSection("-------------", R.useBlockType)       -- left wall top (13 blocks) no special blocks
  8245.             T:go("F1L1 F7x2")
  8246.             T:go("D1x2")
  8247.             T:place("cable", "down")
  8248.             T:up(1)
  8249.             T:place("modem", "down")
  8250.             T:go("F1R2x2")
  8251.             T:place("log", "down")
  8252.             T:go("F2x2")
  8253.             T:place("barrel", "down")
  8254.             utils.goBack(1)
  8255.             network.attachModem()
  8256.             T:go("F6R1 F1D2")
  8257.         end
  8258.     else -- convertStorage or convert
  8259.         -- legacy farm had polished block on positions 4 / (10) from left corner
  8260.          local message = lib.findLegacyStart()
  8261.          if message ~= "" then
  8262.             return {message}
  8263.          end
  8264.          -- now on top of polished block, 4 from left corner, facing Centre
  8265.          T:forward(2)
  8266.          T:place("barrel", "down")
  8267.          T:go("F1D1")
  8268.          T:place("cable", "down")
  8269.          T:up(1)
  8270.          T:place("modem", "down")
  8271.          network.attachModem()
  8272.          T:forward(1)
  8273.          T:place("log", "down")
  8274.          T:go("R1F1 R1F1 D5R1 F1L1 F7R1")-- left corner, facing back ready to clear basement
  8275.     end
  8276.     if (R.data):find("convert") == nil then
  8277.         lib.floodFarm(R)
  8278.     end
  8279.     lib.clearBasement() -- area has been cleared. ends right side facing right, just below ceiling
  8280.  
  8281.     if R.data == "back" then
  8282.         T:go("R2F6 R1D1")
  8283.     else
  8284.         T:go("R2F6 L1F1 U4D5 R2F1") -- make exit for player. end mid floor/ceiling height, facing back, in centre
  8285.     end
  8286.     if R.data == "new" or R.data == "convertStorage" then   -- put storage in this farm
  8287.         for i = 1, 3 do
  8288.             T:place("cable", "up")
  8289.             T:forward(1)
  8290.         end
  8291.         T:place("cable", "up")
  8292.         --T:down(1)
  8293.         utils.createStorage()   -- creates on ground, 1 below current
  8294.         T:go("F1R2")
  8295.         T:place("cable", "forward")
  8296.         T:go("R2")
  8297.         for i = 1, 2 do
  8298.             T:place("cable", "up")
  8299.             T:forward(1)
  8300.         end
  8301.     else
  8302.         for i = 1, 6 do
  8303.             T:place("cable", "up")
  8304.             T:forward(1)
  8305.         end
  8306.     end
  8307.     T:place("modem", "up")
  8308.     T:go("F1R2U2")
  8309.     T:place("barrel", "down")
  8310.     T:drop("down", "dirt", 64)-- override 'slot' with item string
  8311.     T:up(1)
  8312.     T:place("hopper", "down")
  8313.     T:go("F1D1")
  8314.     network.attachModem()
  8315.     T:go("U1C2 U2F6 R2")
  8316.     --network.attachModem()
  8317.  
  8318.     return {"Tree farm ready for planting"}
  8319. end
  8320.  
  8321. local function createWallOrFence(R)
  8322.     local lib = {}
  8323.    
  8324.     function lib.placeBarrel(R)
  8325.         if R.data == "barrel" then
  8326.             utils.goBack(1)
  8327.             T:go("L1F1")
  8328.             T:place("barrel", "down", false)
  8329.             utils.goBack(1)
  8330.             T:go("R1")
  8331.             T:forward(1)
  8332.         end
  8333.     end
  8334.    
  8335.     function lib.placeTorch(R)
  8336.         T:up(1)
  8337.         local up = 1
  8338.         local blockType = T:getBlockType("forward")
  8339.         while blockType:find(R.useBlockType) ~= nil and blockType ~= "" do -- prevent continuous upward travel
  8340.             T:up(1)
  8341.             up = up + 1
  8342.             blockType = T:getBlockType("forward")
  8343.         end
  8344.         T:place("torch", "forward", true)
  8345.         T:down(up)
  8346.     end
  8347.    
  8348.     function lib.buildWall(R, length)
  8349.         -- T:place(blockType, direction, leaveExisting, signText)
  8350.         local blockType = ""
  8351.         local blocks = 0
  8352.         lib.placeBarrel(R)
  8353.         while blocks < length do
  8354.             if turtle.back() then
  8355.                 T:place(R.useBlockType, "forward", true)
  8356.                 if R.torchInterval > 0 then
  8357.                     if blocks == 0 or blocks % R.torchInterval == 0 then
  8358.                         lib.placeTorch(R)
  8359.                     end
  8360.                 end
  8361.                 blocks = blocks + 1 -- still facing start position
  8362.                 while turtle.down() do
  8363.                     T:place(R.useBlockType, "up", true)
  8364.                 end
  8365.             else -- obstruction
  8366.                 T:turnRight(2) -- facing away from start
  8367.                 blockType = T:getBlockType("forward")
  8368.                 if blockType:find("torch") ~= nil then
  8369.                     T:go("F1R2")
  8370.                     T:place(R.useBlockType, "forward")
  8371.                     blocks = blocks + 1 -- facing start
  8372.                 elseif blockType:find("log") ~= nil then
  8373.                     T:harvestTree()
  8374.                     T:turnRight(2)
  8375.                     T:place(R.useBlockType, "forward")
  8376.                     blocks = blocks + 1 -- facing start
  8377.                 elseif T:isVegetation(blockType) then
  8378.                     T:go("F1R2")
  8379.                     T:place(R.useBlockType, "forward")
  8380.                     blocks = blocks + 1 -- facing start
  8381.                 else -- cant go forward, go up instead
  8382.                     while turtle.detect() and blockType:find("torch") == nil and blockType:find("log") == nil and not T:isVegetation(blockType) do -- block ahead, but not torch or tree
  8383.                         while turtle.detectUp() do -- will only run if block above
  8384.                             utils.goBack(1)
  8385.                             blocks = blocks - 1
  8386.                         end
  8387.                         turtle.up()
  8388.                         T:place(R.useBlockType, "down", true)
  8389.                         blockType = T:getBlockType("forward")
  8390.                     end
  8391.                     T:turnRight(2) -- facing start
  8392.                 end
  8393.             end
  8394.         end
  8395.     end
  8396.    
  8397.     T:turnRight(2) --facing start position
  8398.     if R.width == 0 then -- single fence
  8399.         lib.buildWall(R, R.length)
  8400.     else   
  8401.         lib.buildWall(R, R.length - 1)
  8402.         T:go("R1") -- facing start so left turn = turnRight
  8403.         lib.buildWall(R, R.width - 1)
  8404.         T:go("R1")
  8405.         lib.buildWall(R, R.length - 1)
  8406.         T:go("R1")
  8407.         lib.buildWall(R, R.width - 2)
  8408.         T:go("U1")
  8409.         T:place(R.useBlockType, "down", true)
  8410.     end
  8411.    
  8412.     return {"Wall or fence completed"}
  8413. end
  8414.  
  8415. local function createWaterCanal(R) -- 53
  8416.     --[[
  8417.     designed for 4 turtles, but can be done with 2 as well
  8418.     R.data = 1 (2 turtles) or 2 (4 turtles)
  8419.     R.height = 0 (in water/ on canal floor) or 1 (at ground level)
  8420.     R.side = "R" or "L"
  8421.     R.subChoice =
  8422.         1 = left side, ground level (on towpath)
  8423.         2 = left side above canal water (new canal only)
  8424.         3 = right side above canal water (new canal only)
  8425.         4 = right side, ground level (on towpath)
  8426.         5 = left side in canal water (if present)
  8427.         6 = right side in canal water (if present)
  8428.    
  8429.     if R.height = 0 then already at correct height on canal floor
  8430.         check block below, block to left and block above, move forward tunnelling
  8431.         if entering water then move up, onto canal wall and continue pathway
  8432.         if tunnelling then flood canal
  8433.     else R.height = 1 then above water and on path across
  8434.         move forward, checking for water below
  8435.         if water finishes, move into canal, drop down and continue tunnelling
  8436.     ]]
  8437.     local lib = {}
  8438.    
  8439.     function lib.newCanalSide(oTurn)
  8440.         T:go("C1 U1x1 U1x1 D2"..oTurn.."1", false, 0, false)
  8441.     end
  8442.    
  8443.     function lib.newCanalBase(R)
  8444.         local oTurn = "R"                               -- assume R.side = "L"
  8445.         if R.side == "R" then
  8446.             oTurn = "L"
  8447.         end
  8448.         if not turtle.detectDown() then                 -- air / water below: fill floor
  8449.             T:go(oTurn.."1D1")                          -- *|>| | | to *|V| | | turn towards canal centre, go down ready to repair neighbouring canal base
  8450.             if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position
  8451.                 if R.side == "L" then                   -- only left side repairs, so wait 1 second
  8452.                     sleep(1)
  8453.                     T:go("C1")                          -- repair neighbouring canal base
  8454.                 end
  8455.             else
  8456.                 T:go("C1")                              -- repair neighbouring canal base
  8457.             end
  8458.             T:go(R.side.."1")                           -- *|V| | | to *|>| | | turn to face start
  8459.             T:up(1)                                     -- *|>| | | return to canal floor
  8460.         end
  8461.         T:go("C2", false, 0, false)
  8462.     end
  8463.    
  8464.     function lib.newCanal(R)
  8465.         --  no source in front as this function called                                              -- *|<| | |  facing end wall ready for new canal canal base level
  8466.         local oTurn = "R"                                   -- assume R.side = "L"
  8467.         if R.side == "R" then
  8468.             oTurn = "L"
  8469.         end
  8470.         lib.newCanalSide(oTurn)                             -- *|<| | | wall fixed. to -- *|^| | |
  8471.         lib.newCanalSide(oTurn)                             -- *|^| | | wall fixed. to -- *|>| | |
  8472.         lib.newCanalBase(R)                                 -- *|>| | | base fixed
  8473.         T:go("F1"..R.side.."1")                             -- *|>| | | to *| |>| | to *| |^| |
  8474.         lib.newCanalSide(oTurn)                             -- *| |^| | to *| |>| |
  8475.         lib.newCanalBase(R)                                 -- *| |>| | base fixed
  8476.         T:go("F1"..R.side.."1")                             -- *| |>| | to *| | |>| to *| | |^|
  8477.         lib.newCanalSide(oTurn)                             -- *| | |^| to *| | |>|
  8478.         lib.newCanalBase(R)                                 -- *| | |>| base fixed
  8479.         T:go(R.side.."2")                                   -- *| | |>| to *| | |<|facing existing / back wall
  8480.         T:forward(1)                                        -- *| |<| |
  8481.         T:placeWater("forward")                             -- *|W|<| | placed against start wall  
  8482.         T:go("L2")                                          -- *|W|>| |
  8483.         T:placeWater("forward")                             -- *|W|>|W| placed direction of travel
  8484.         T:go("R2")                                          -- *|W|<|W| rotate
  8485.         if deletesWater then
  8486.             T:up(1)
  8487.         else
  8488.             sleep(0.2)
  8489.         end
  8490.         utils.getWater()                                    -- *|W|<|W|
  8491.         T:go(oTurn.."2F1")                                  -- *|W|<|W|  to *|W|W|>|  ready to go  
  8492.     end
  8493.    
  8494.     function lib.towpathOnly(R)
  8495.         --[[single turtle on towpath only using 4 turtles. Starts at ground level]]
  8496.         for i = 1, R.length do
  8497.             if turtle.detectDown() then                     -- eg dirt, stone
  8498.                 T:dig("down")                               -- remove block below
  8499.             end
  8500.             local placeOnly = true
  8501.             if R.torchInterval > 0 then                     -- place torches
  8502.                 if i == 1 or i % R.torchInterval == 0 then  -- ready to place torch
  8503.                     T:go("C2U1")                            -- place solid block below, up 1
  8504.                     T:place("torch", "down")                -- place torch, move forward
  8505.                     T:go("F1D1")                            -- move forward, down
  8506.                     placeOnly = false      
  8507.                 end
  8508.             end
  8509.             if placeOnly then
  8510.                 T:dig("up")                                 -- clear blocks above
  8511.                 if not T:place("stone", "down") then        -- place stone below
  8512.                     break
  8513.                 end
  8514.                 if i < R.length then
  8515.                     T:forward(1)                            -- move forward
  8516.                 end                        
  8517.             end
  8518.         end
  8519.     end
  8520.    
  8521.     function lib.initialiseCanal(R)
  8522.         --[[ move turtle to correct position. return moves]]
  8523.         local moves = 1
  8524.         local oTurn = "R"
  8525.         if R.side == "R" then
  8526.             oTurn = "L"
  8527.         end
  8528.         local newCanal, isWater, isSource = false, false, false
  8529.         if R.data == 1 then -- use 2 turtles only
  8530.             if R.subChoice == 1 or R.subChoice == 4 then    -- left / right side on towpath- move into canal space
  8531.                 if deletesWater then
  8532.                     T:go(oTurn.."1F1")                      -- turn to face canal centre, go forward over water
  8533.                     isWater, isSource = T:isWater("down")
  8534.                     if isSource then                        -- canal already exists
  8535.                         T:go(oTurn.."1")                    -- stay above water, face existing canal
  8536.                     else                                    -- NOT above source
  8537.                         T:go("D1"..oTurn.."1")              -- go to canal floor, face existing
  8538.                         newCanal = true                     -- flag create 6 water source blocks
  8539.                     end
  8540.                 else                                        -- NOT deletesWater
  8541.                     T:go(oTurn.."1F1D1"..oTurn.."1")        -- move into canal, face back along any existing canal
  8542.                     isWater, isSource = T:isWater("forward")
  8543.                     if isSource then
  8544.                         T:go(R.side.."2")                   -- face forward for new canal
  8545.                     else
  8546.                         newCanal = true
  8547.                     end
  8548.                 end
  8549.             elseif R.subChoice == 2 or R.subChoice == 3 then-- left / right side above canal finishing pos if deletesWater
  8550.                 if deletesWater then
  8551.                     isWater, isSource = T:isWater("down")
  8552.                     if isSource then
  8553.                         T:go(R.side.."2")                   -- face towards existing canal
  8554.                     else
  8555.                         T:go("D1"..R.side.."2")             -- go down and face existing canal                      -- no water ahead
  8556.                         newCanal = true                     -- already in newCanal starting position
  8557.                     end
  8558.                 else                                        -- NOT deletesWater
  8559.                     T:go("D1"..R.side.."2")                 -- facing existing on canal floor
  8560.                     isWater, isSource = T:isWater("forward")
  8561.                     if isSource then                        -- water ahead
  8562.                         T:go(R.side.."2")                   -- face forward for new canal
  8563.                     else                                   
  8564.                         newCanal = true
  8565.                     end
  8566.                 end
  8567.             elseif R.subChoice == 5 or R.subChoice == 6 then -- left / right  side in canal base. Assume NOT deletesWater
  8568.                 T:go(R.side.."2")                           -- check if water behind   
  8569.                 isWater, isSource = T:isWater("forward")
  8570.                 if isSource then
  8571.                     T:go(oTurn.."2")    
  8572.                 else
  8573.                     newCanal = true
  8574.                 end
  8575.             end
  8576.         else    -- use 4 turtles
  8577.             if R.subChoice == 1 or R.subChoice == 4 then    -- left / right side on towpath stays in place for 4 part canal
  8578.            
  8579.             elseif R.subChoice == 2 or R.subChoice == 3 then-- left / right side above canal finishing pos if deletesWater
  8580.            
  8581.             elseif R.subChoice == 5 or R.subChoice == 6 then -- left / right  side in canal base. Assume NOT deletesWater
  8582.            
  8583.             end
  8584.         end
  8585.         if newCanal then                                -- no water ahead, facing start wall of new canal *|<| | |
  8586.             lib.newCanal(R)                             -- start new canal, finish facing new canal 6 block water sources
  8587.             moves = 2
  8588.         end
  8589.        
  8590.         return moves                                    -- facing forward ready for new canal *|>| | |
  8591.     end
  8592.    
  8593.     function lib.side(R, maxLength)
  8594.         -- Already in position facing new canal, 2 water buckets
  8595.         local torch = R.length - maxLength                  -- start torch count at 1-2 depending on lib.initialise()
  8596.         local sourceCount = 0                               -- allow for 1 iteration of placing source blocks when changing from solid to water
  8597.         local numBlocks = 0                                 -- distance travelled
  8598.         local _, isSource = nil, false                      -- initialise variables
  8599.         local oTurn = "R"                                   -- assume R.side == "L" -> oTurn = "R"
  8600.         if R.side == "R" then                               -- R.side = "R"
  8601.             oTurn = "L"                                     -- oTurn = "L"
  8602.         end
  8603.        
  8604.         while numBlocks < maxLength do                      -- loop from here. Facing forwards to extend canal
  8605.             torch = torch + 1                               -- increase torch spacing interval
  8606.             numBlocks = numBlocks + 1                       -- inrease block count
  8607.             if deletesWater then                            -- up to and including mc 1.12.2
  8608.                 T:forward(1)                                -- move forward to extend canal  | |>|
  8609.                 _, isSource = T:isWater("down")             -- check if source water below
  8610.                 if isSource then
  8611.                     sourceCount = sourceCount + 1           -- count source blocks
  8612.                 else                                       
  8613.                     T:down(1)                               -- down to canal floor
  8614.                     sourceCount = 0                         -- reset
  8615.                     T:go("C2", false, 0, false)             -- place block below
  8616.                     T:up(1)                                 -- up to water level
  8617.                 end                                         -- still facing away from canal
  8618.                 T:go(R.side.."1F1C2", false, 0, false)      -- go above towpath, place stone down, facing out
  8619.                 if turtle.detectUp() then                   -- ? block above
  8620.                     T:go(R.side.."2U1F1D1"..R.side.."2")    -- rotate to face canal, up 1 forward over canal, back down to water level, face towpath
  8621.                 else
  8622.                     utils.goBack(1)                         -- face towpath
  8623.                 end
  8624.                 -- facing towpath
  8625.                 if R.torchInterval > 0 then                 -- Are torches required?
  8626.                     if torch == R.torchInterval  or numBlocks == 0 then     -- check if ready to place
  8627.                         torch = 0                           -- reset interval counter
  8628.                         T:go("U1F1")
  8629.                         T:place("torch", "down")        -- place torch
  8630.                         utils.goBack(1)
  8631.                         T:down(1)
  8632.                     end
  8633.                 end                                         -- facing towpath, above water
  8634.                 -- facing towpath
  8635.                 if isSource and scoreCount > 0 then
  8636.                     T:go(oTurn.."1x0")                      -- face new canal direction
  8637.                 else                                        -- not source below, or first time found, ensures continous canal
  8638.                     T:go(R.side.."1x0")                     -- face back to existing canal
  8639.                     T:placeWater("down")                    -- place water
  8640.                     T:forward(1)                            -- forward 1
  8641.                     T:placeWater("down")                    -- place water
  8642.                     utils.getWater()                            -- collects water from below
  8643.                     utils.goBack(1)                         -- back 1
  8644.                     T:go(oTurn.."1x0")                      -- face new canal
  8645.                 end
  8646.             else
  8647.                 T:forward(1)                                -- move forward to extend canal
  8648.                 _, isSource = T:isWater("forward")          -- check if source water ahead
  8649.                 if isSource then                            -- ? source ahead
  8650.                     sourceCount = sourceCount + 1
  8651.                 else
  8652.                     sourceCount = 0
  8653.                     if not turtle.detectDown() then         -- air / water below, but no source in front, so fill it
  8654.                         T:go(oTurn.."1D1")                  -- ready to repair neighbouring canal base
  8655.                         if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position
  8656.                             if R.side == "L" then           -- only left side repairs, so wait 1 second
  8657.                                 sleep(1)
  8658.                                 T:go("C1")                  -- repair neighbouring canal base
  8659.                             end
  8660.                             T:go(R.side.."1")               -- face forward
  8661.                         else
  8662.                             T:go("C1"..R.side.."1")         -- repair neighbouring canal base if air
  8663.                         end
  8664.                         T:up(1)
  8665.                     end
  8666.                     T:go("C2", false, 0, false)             -- place block below if not already source
  8667.                 end
  8668.                 T:go(R.side.."1C1", false, 0, false)        -- face canal wall, replace with stone
  8669.                
  8670.                 local placeTorch = false
  8671.                 if R.torchInterval > 0 then                 -- Are torches required?
  8672.                     if torch == R.torchInterval  or numBlocks == 0 then     -- check if ready to place
  8673.                         torch = 0                           -- reset interval counter
  8674.                         placeTorch = true
  8675.                     end
  8676.                 end
  8677.                 if (isSource and placeTorch) or not isSource then
  8678.                     T:go("U1x1 U1x1")                       -- up 2 and excavate blocks above tow path
  8679.                     if placeTorch then                      -- torch required
  8680.                         T:forward(1)                        -- move over towpath
  8681.                         T:place("torch", "down")        -- place torch
  8682.                         utils.goBack(1)                     -- move back
  8683.                     end
  8684.                     T:down(2)                               -- return to canal base
  8685.                 end
  8686.                 if isSource and sourceCount > 1 then        -- source ahead found at least once
  8687.                     T:go(oTurn.."1")                        -- face newcanal as no water refill required
  8688.                 else                                        -- not source in front, or first time found, ensures continous canal
  8689.                     T:go(oTurn.."1C1")                      -- *| | | |>| face along new canal and block entrance
  8690.                     utils.goBack(1)                         -- *| | |>| | back 1
  8691.                     T:placeWater("forward")                 -- *| | |>|W| place water
  8692.                     T:go(oTurn.."2")                        -- *| | |<|W| face existing canal
  8693.                     _, isSource = T:isWater("forward")      -- *| |?|<|W| check if source water ahead
  8694.                     if not isSource then
  8695.                         if not T:placeWater("forward") then -- place water again *| |W|<|W|
  8696.                             while not T:getWater("forward") do -- wait for other turtle
  8697.                                 print("Out of water buckets")
  8698.                                 sleep(1)
  8699.                             end
  8700.                             sleep(0.2)
  8701.                             T:getWater("forward")
  8702.                         end
  8703.                     end
  8704.                     utils.getWater()                            -- collects water *| |W|<|W|
  8705.                     T:go(R.side.."2F1")                         -- face along new canal *| |W|>|W| to *| |W|W|>|
  8706.                 end
  8707.             end
  8708.         end
  8709.     end
  8710.        
  8711.     function lib.waterOnly(R, maxLength)
  8712.         -- Already in position facing new canal, 2 water buckets
  8713.         local torch = R.length - maxLength                  -- start torch count at 1-2 depending on lib.initialise()
  8714.         local sourceCount = 0                               -- allow for 1 iteration of placing source blocks when changing from solid to water
  8715.         local numBlocks = 0                                 -- distance travelled
  8716.         local _, isSource = nil, false                      -- initialise variables
  8717.         local oTurn = "R"                                   -- assume R.side == "L" -> oTurn = "R"
  8718.         if R.side == "R" then                               -- R.side = "R"
  8719.             oTurn = "L"                                     -- oTurn = "L"
  8720.         end
  8721.        
  8722.         while numBlocks < maxLength do                      -- loop from here. Facing forwards to extend canal
  8723.             torch = torch + 1                               -- increase torch spacing interval
  8724.             numBlocks = numBlocks + 1                       -- inrease block count
  8725.             if deletesWater then                            -- up to and including mc 1.12.2
  8726.                 T:forward(1)                                -- move forward to extend canal  | |>|
  8727.                 _, isSource = T:isWater("down")             -- check if source water below
  8728.                 if isSource then
  8729.                     sourceCount = sourceCount + 1           -- count source blocks
  8730.                 else                                       
  8731.                     T:down(1)                               -- down to canal floor
  8732.                     sourceCount = 0                         -- reset
  8733.                     T:go("C2", false, 0, false)             -- place block below
  8734.                     T:up(1)                                 -- up to water level
  8735.                 end                                         -- still facing away from canal
  8736.                 if turtle.detectUp() then                   -- ? block above
  8737.                     T:go("U1x0")                            -- break block above
  8738.                 end
  8739.                 if not isSource or scoreCount == 0 then     -- not source below, or first time found, ensures continous canal
  8740.                     T:go(R.side.."2x0")                     -- face back to existing canal
  8741.                     T:placeWater("down")                    -- place water
  8742.                     T:forward(1)                            -- forward 1
  8743.                     T:placeWater("down")                    -- place water
  8744.                     utils.getWater()                        -- collects water from below
  8745.                     utils.goBack(1)                         -- back 1
  8746.                     T:go(R.side.."2")                       -- face new canal
  8747.                 end
  8748.             else
  8749.                 T:forward(1)                                -- move forward to extend canal
  8750.                 _, isSource = T:isWater("forward")          -- check if source water ahead
  8751.                 if isSource then                            -- ? source ahead
  8752.                     sourceCount = sourceCount + 1
  8753.                 else
  8754.                     sourceCount = 0
  8755.                     if not turtle.detectDown() then         -- air / water below, but no source in front, so fill it
  8756.                         T:go(oTurn.."1D1")                  -- ready to repair neighbouring canal base
  8757.                         if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position
  8758.                             if R.side == "L" then           -- only left side repairs, so wait 1 second
  8759.                                 sleep(1)
  8760.                                 T:go("C1", false, 0, true)  -- repair neighbouring canal base
  8761.                             end
  8762.                             T:go(R.side.."1")               -- face forward
  8763.                         else
  8764.                             T:go("C1"..R.side.."1",false, 0, true)  -- repair neighbouring canal base if air
  8765.                         end
  8766.                         T:up(1)
  8767.                     end
  8768.                     T:go("C2", false, 0, false)             -- place block below if not already source
  8769.                 end
  8770.                 if not isSource then
  8771.                     T:go("U1x0D1")                          -- up 1 and excavate blocks above canal. return to canal base
  8772.                 end
  8773.                 T:go(R.side.."1C1"..oTurn.."1", false, 0, true) -- face canal wall, replace with stone if empty, face forward                                      
  8774.                 if not isSource and sourceCount == 0 then   -- not source in front, or first time found, ensures continous canal                   
  8775.                     T:go("C1", false, 0, true)              -- *| | | |>| face along new canal and block entrance
  8776.                     utils.goBack(1)                         -- *| | |>| | back 1
  8777.                     T:placeWater("forward")                 -- *| | |>|W| place water
  8778.                     T:go(oTurn.."2")                        -- *| | |<|W| face existing canal
  8779.                     _, isSource = T:isWater("forward")      -- *| |?|<|W| check if source water ahead
  8780.                     if not isSource then
  8781.                         if not T:placeWater("forward") then -- place water again *| |W|<|W|
  8782.                             while not T:getWater("forward") do -- wait for other turtle
  8783.                                 print("Out of water buckets")
  8784.                                 sleep(1)
  8785.                             end
  8786.                             sleep(0.2)
  8787.                             T:placeWater("forward")
  8788.                         end
  8789.                     end
  8790.                     utils.getWater()                            -- collects 2 water *| |W|<|W|
  8791.                     T:go(R.side.."2F1")                         -- face along new canal *| |W|>|W| to *| |W|W|>|
  8792.                 end
  8793.             end
  8794.         end
  8795.     end
  8796.        
  8797.     local maxLength = 512
  8798.     if R.length ~= 0 then
  8799.         maxLength = R.length
  8800.     end
  8801.     menu.clear()
  8802.     menu.colourWrite("Building canal "..R.side.." side", colors.yellow, nil, nil, false, true)
  8803.     local moves = lib.initialiseCanal(R) -- move to correct position and/or start new canal
  8804.     if R.data == 1 then -- 2 turtles
  8805.         lib.side(R, maxLength - moves) 
  8806.     else -- 4 turtles
  8807.         if R.subChoice == 1 or R.subChoice == 4 then -- towpath
  8808.             lib.towpathOnly(R)
  8809.             --lib.waterCanalTowpath(R, maxLength - moves)
  8810.         else -- main canal only
  8811.             lib.waterOnly(R, maxLength - moves)
  8812.         end
  8813.     end
  8814.    
  8815.     return {}
  8816. end
  8817.  
  8818. local function createMobGrinder(R)
  8819.     -- go down 5 and create a cavity 9 wide, 5 long, 8 high
  8820.     -- assume facing out from spawner cube at base of exit (6 blocks above ground
  8821.     -- R.subChoice = 1 or 2 (sticky or normal pistons)
  8822.    
  8823.     local lib = {}
  8824.    
  8825.     function lib.getInventory(R)
  8826.         T:clear()
  8827.         menu.colourPrint("All blocks to be ejected. Ready? Enter", colors.red)
  8828.         read()
  8829.         T:emptyInventory("up")
  8830.         T:checkInventoryForItem({"stone"}, {20}, true, "Match existing walls?")
  8831.         if R.subChoice == 1 then -- sticky pistons
  8832.             T:checkInventoryForItem({"computercraft:computer_normal"}, {1})
  8833.             T:checkInventoryForItem({"minecraft:sticky_piston"}, {2})
  8834.         else
  8835.             T:checkInventoryForItem({"computercraft:computer_normal"}, {2})
  8836.             T:checkInventoryForItem({"minecraft:piston"}, {4})
  8837.             T:checkInventoryForItem({"computercraft:cable"}, {6})
  8838.             T:checkInventoryForItem({"computercraft:wired_modem"}, {2})
  8839.         end
  8840.         T:checkInventoryForItem({"polished"}, {23}, true, "Any polished block")
  8841.         T:checkInventoryForItem({"wall"}, {2}, true, "Any wall block ? match")
  8842.         T:checkInventoryForItem({"slab"}, {7}, true, "Any stone slab. ? polished / match")
  8843.         T:checkInventoryForItem({"minecraft:glass"}, {2})
  8844.         T:checkInventoryForItem({"minecraft:stone_pressure_plate"}, {1})
  8845.         T:checkInventoryForItem({"minecraft:dispenser"}, {1})
  8846.         T:checkInventoryForItem({"hopper"}, {1})
  8847.         T:checkInventoryForItem({"chest"}, {2})
  8848.         T:checkInventoryForItem({"minecraft:redstone"}, {9})
  8849.         T:checkInventoryForItem({"lava"}, {1})
  8850.         R.useBlockType = T:getPolishedItem("")
  8851.         if R.useBlockType == "" then
  8852.             R.useBlockType = T:getMostItem("", true)
  8853.         end
  8854.     end
  8855.    
  8856.     function lib.placeRedstone()
  8857.         T:go("D2U2")                                -- in left corner facing right
  8858.         T:place("slab", "down")                 -- place slab layer 1
  8859.         T:up(2)
  8860.         T:place("slab", "down")                 -- place slab layer 2
  8861.         T:up(1)
  8862.         T:place("redstone", "down")
  8863.         T:go("F1D4 C2L1C1 L1U1", false, 0, false)   -- facing ground level slab
  8864.         T:place("redstone", "forward")          -- redstone on ground level slab
  8865.         T:up(1)
  8866.         T:place("slab", "down")                 -- slab on layer 1
  8867.         T:up(2)
  8868.         T:place("slab", "down")                 -- slab on layer 3
  8869.         T:up(1)
  8870.         T:place("redstone", "down")             -- redstone on layer 3 slab
  8871.         utils.goBack(1)
  8872.         T:down(3)                                   -- facing layer 1 slab
  8873.         T:place("redstone", "forward")          -- redstone on layer 1 slab
  8874.         T:go("D2C2", false, 0, false)               -- under end of chest position
  8875.         T:place("redstone", "forward")          -- redstone on level 0 floor
  8876.         T:go("R1C1R1", false, 0, false)             -- face right, repair back wall
  8877.         T:go("F1C2 L1C1 R1", false, 0, false)       -- under chest start
  8878.         T:go("F1C2 L1C1 R1", false, 0, false)       -- under hopper
  8879.         T:go("F1C2 L1C1 R1", false, 0, false)       -- under right side wall block
  8880.         T:go("U1L2")                                -- ready for redstone
  8881.         for i = 1, 4 do
  8882.             T:place("redstone", "down")         -- redstone under chest etc
  8883.             if i < 4 then
  8884.                 T:forward(1)
  8885.             end
  8886.         end
  8887.         -- finishes facing slab at ground level, redstone below
  8888.     end
  8889.    
  8890.     function lib.placeStorage()
  8891.         -- starts facing slab at ground level, redstone below
  8892.         T:go("L1F1L2")                              -- up and out ready for chest placement
  8893.         T:place("chest", "forward")             -- end chest
  8894.         T:go("R1F1 L1F1 R1U2")                      -- at above start chest position facing right
  8895.         T:place("slab", "down")                 -- slab above chest
  8896.         T:turnLeft(1)
  8897.         utils.goBack(1)                            
  8898.         T:down(2)                                   -- in front of start chest position
  8899.         T:place("chest", "forward")             -- start chest
  8900.         T:go("R1F2L2")                              -- at pressure plate position facing left
  8901.         T:place("wall", "forward")              -- place wall
  8902.         T:up(1)
  8903.         T:place("pressure", "down")             -- place pressure plate
  8904.         T:go("R1F1 L1D1")                           -- at second wall position
  8905.         T:place("hopper", "forward")                -- place hopper into chest
  8906.         utils.goBack(1)
  8907.         T:place("wall", "forward")              -- place second wall
  8908.         -- finishes on level 1 (ground) facing right side wall block
  8909.     end
  8910.    
  8911.     function lib.placePistons(R)
  8912.         -- starts on level 1 (ground) facing right side wall block
  8913.         T:go("U1F2 R1")                                 -- go over wall block, facing back wall layer 2
  8914.         T:place(R.useBlockType, "forward", false)   -- replace back wall with polished block layer 2
  8915.         T:up(1)                                         -- layer 3
  8916.         T:place(R.useBlockType, "forward", false)   -- replace back wall with polished block layer 3
  8917.         T:turnRight(1)                                  -- face right side
  8918.         if R.subChoice == 1 then                        -- use sticky pistons x 2
  8919.             T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 3
  8920.             T:go("R2F1")                                -- ready to place lower piston (works ok as slab already in place behind it)
  8921.         else
  8922.             T:go("F2R2")                                -- move forward 2 and face left
  8923.             T:place("piston", "forward")                -- lower replacer piston placed
  8924.             T:go("U1F2D1F1")                            -- go up and over piston forward 1 ready for other piston
  8925.         end
  8926.         T:place("piston", "forward")                    -- lower piston placed
  8927.         utils.goBack(1)
  8928.         T:go("U1R1")                                    -- layer 4
  8929.         T:place(R.useBlockType, "forward", false)   -- polished block back wall layer 4
  8930.         T:go("L1F2R2")                                  -- head left ready for dispenser
  8931.         T:place("dispenser", "forward")             -- dispenser placed
  8932.         T:dropItem("lava", "forward")                   -- drop lava bucket into dispenser
  8933.         T:go("U1F2 D1")                                 -- up and over dispenser, facing right side
  8934.         T:place("slab", "down")                     -- lower piston slab placed
  8935.         if R.subChoice == 1 then
  8936.             T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 4
  8937.             T:turnLeft(1)                               -- facing back wall
  8938.         else
  8939.             T:go("F1L1")                                -- at second computer position, facing back wall
  8940.             utils.goBack(1)                             -- ready to place computer
  8941.             T:place("computercraft:computer_normal", "forward", false)  -- place computer
  8942.             T:go("L1F1R1F1")                            -- facing back wall in mob drop, level 4
  8943.         end
  8944.         T:place(R.useBlockType, "forward", false)   -- polished block back wall layer 4
  8945.         T:turnLeft(1)
  8946.         T:go("U1F3R2")                                  -- level 5 ready for upper piston
  8947.         T:place("piston", "forward")                    -- upper piston placed
  8948.         T:go("U1F3D1R2")                                -- up and over piston, facing left, level 5
  8949.         T:turnRight(1)                                  -- at mob drop, facing wall, level 5
  8950.         T:place(R.useBlockType, "forward", false)   -- polished block back wall layer 5
  8951.         T:turnRight(1)                                  -- facing right side
  8952.         if R.subChoice == 1 then
  8953.             T:place(R.useBlockType, "forward", false)-- right side polished block layer 5, facing right side, in mob drop                           -- layer 5 facing left side, in mob drop       
  8954.         else
  8955.             T:go("F1C1")                                -- move forward, place temporary block
  8956.             utils.goBack(1)
  8957.             T:place("piston", "forward")                -- upper replacer piston placed            
  8958.         end
  8959.         T:turnRight(2) 
  8960.         T:place("slab", "forward")                  -- upper piston slab placed
  8961.         T:turnLeft(1)                                   -- facing away from back wall
  8962.     end
  8963.    
  8964.     function lib.placeComputer(R)
  8965.         -- starts facing away from back wall, layer 5, in mob drop         
  8966.         T:go("F1R1 F2R1 D1")                            -- move to left computerposition, facing back wall, layer 4
  8967.         T:place("computercraft:computer_normal", "forward", false)      -- place computer in gap, layer 4
  8968.     end
  8969.    
  8970.     function lib.placeColumnSection(direction)
  8971.         T:place(R.useBlockType, "forward", false)
  8972.         T:go(direction.."1")
  8973.         T:place(R.useBlockType, "forward", false)
  8974.         T:go(direction.."1")
  8975.         T:place(R.useBlockType, "forward", false)   -- facing right
  8976.     end
  8977.    
  8978.     function lib.placeColumns(R)
  8979.         -- starts facing left computer, layer 4
  8980.         T:go("R1F2 L1")                                 -- facing mob drop level 4
  8981.         T:place("glass", "down", false)
  8982.         T:up(1)                                         -- facing mob drop level 5
  8983.         T:place("glass", "down", false)             -- on top of glass facing back wall at dungeon base level 5
  8984.         T:up(1)
  8985.         T:place(R.useBlockType, "down", false)      -- level 6 dungeon exit
  8986.         T:go("F1L1")
  8987.         lib.placeColumnSection("L")                     -- facing right
  8988.         T:up(1)
  8989.         lib.placeColumnSection("R")                     -- facing left
  8990.         T:up(1)
  8991.         lib.placeColumnSection("L")                     -- facing right
  8992.         T:up(1)
  8993.         lib.placeColumnSection("R")                     -- facing left
  8994.         T:up(1)
  8995.         T:place(R.useBlockType, "forward", false)
  8996.         T:turnLeft(2)
  8997.         T:place(R.useBlockType, "forward", false)   -- facing right
  8998.         T:turnLeft(1)                                   -- at top of column
  8999.         T:go("x1D1 x1D1 x1U2")                          -- open exit for mobs
  9000.         utils.goBack(2)
  9001.         T:place(R.useBlockType, "forward", false)
  9002.         T:down(9)
  9003.     end
  9004.    
  9005.     function lib.placeNetwork()
  9006.         T:go("R1F2L1 F3U3 F1L1F1 L1x1")                             -- go behind second computer and remove block
  9007.         T:place("computercraft:wired_modem", "forward", false)  -- place modem
  9008.         utils.goBack(1)
  9009.         T:place("computercraft:cable", "forward", false)            -- place network cable
  9010.         T:place("computercraft:cable", "forward", false)            -- place network cable (no need to move)
  9011.         T:go("R1F1 x2L1")                                           -- move forward, face back wall
  9012.         T:place("computercraft:cable", "forward", false)
  9013.         T:go("R1F1 x2L1")
  9014.         T:place("computercraft:cable", "forward", false)
  9015.         T:go("R1F1 x2L1F1 x1x2")                                    -- come behind left computer and expose back
  9016.         T:place("computercraft:wired_modem", "forward", false)  -- place modem
  9017.         utils.goBack(1)
  9018.         T:place("computercraft:cable", "forward", false)
  9019.         T:place("computercraft:cable", "forward", false)
  9020.         T:go("L1D3 F4R1 F3U4 D4")                                   -- removes temporary block
  9021.     end
  9022.    
  9023.     local tempSubChoice = R.subChoice   -- store for later use
  9024.     R.width = 4                         -- settings for createFloorCeiling()
  9025.     R.length = 9
  9026.     R.height = 0
  9027.     R.up = true
  9028.     T:turnRight(2)
  9029.     local isWater, isSource, isIce, level, isAir = T:isWater("forward")
  9030.     if not isWater then
  9031.         T:turnRight(2)
  9032.         return{"Not in correct position. Must be water behind"}
  9033.     end
  9034.     --T:go("U1x1 U1L1 F4R2")                    -- go up to starting point
  9035.     T:go("U2L1 F4R2")                   -- go up to starting point
  9036.     local data = createFloorCeiling(R)[1]   -- place ceiling, returns to starting position. if water or lava present is returned as "water or lava found"
  9037.     if data == "water or lava found" then
  9038.         R.height = 10
  9039.         R.silent = true
  9040.         T:up(1)
  9041.         createSinkingPlatform(R)
  9042.         T:go("F4L1 U5x1 U1x1 U3R1 F4C0 R1F3C0 R1F8C0 R1F3C0 R1D9")          -- re-open exit hole, return to floor level
  9043.     else -- no water or lava found so empty out area
  9044.         R.height = 10
  9045.         R.subChoice = 2
  9046.         clearSolid(R) -- 76
  9047.         T:down(R.height - 1)
  9048.         R.width = 4                         -- settings for createFloorCeiling()
  9049.         R.length = 9
  9050.         R.height = 0
  9051.         R.down = true
  9052.         R.up = false
  9053.         R.subChoice = 1                     -- replace existing floor
  9054.         createFloorCeiling(R)
  9055.     end
  9056.    
  9057.     R.subChoice = tempSubChoice
  9058.     lib.getInventory(R)
  9059.     lib.placeRedstone()
  9060.     lib.placeStorage()
  9061.     lib.placePistons(R)
  9062.     lib.placeComputer(R)        -- ends facing computer
  9063.     lib.placeColumns(R)
  9064.     if R.subChoice == 2 then
  9065.         lib.placeNetwork()
  9066.     end
  9067.    
  9068.     return {}
  9069. end
  9070.  
  9071. local function createTrialCover(R)
  9072.     local lib = {}
  9073.    
  9074.     function lib.isSpawner()
  9075.         local blockType = T:getBlockType("down")
  9076.         if blockType:find("spawner") ~= nil then
  9077.             return true, "top"
  9078.         end
  9079.         blockType = T:getBlockType("up")
  9080.         if blockType:find("spawner") ~= nil then
  9081.             return true, "bottom"
  9082.         end
  9083.         blockType = T:getBlockType("forward")
  9084.         if blockType:find("spawner") ~= nil then
  9085.             return true, "forward"
  9086.         end
  9087.         return false, ""
  9088.     end
  9089.    
  9090.     function lib.findSpawner()
  9091.         local moves  = 0
  9092.         local quit = false
  9093.         -- assume turtle placed facing trial spawner
  9094.         print("Checking if next to spawner")
  9095.         local found, position = lib.isSpawner() -- true/false, top/bottom/nil
  9096.         if not found then -- move forward towards spawner
  9097.             print("Not close to spawner")
  9098.             while turtle.forward() and not quit do
  9099.                 moves = moves + 1
  9100.                 if moves > 32 then
  9101.                     quit = true
  9102.                 end
  9103.             end
  9104.             found, position = lib.isSpawner() -- true/false, top/bottom/nil
  9105.             if not found then   -- could be behind a wall
  9106.                 print("Assuming spawner behind a wall")
  9107.                 T:forward(1)
  9108.                 moves = moves + 1
  9109.                 while turtle.forward() and not quit do
  9110.                     moves = moves + 1
  9111.                     if moves > 32 then
  9112.                         quit = true
  9113.                     end
  9114.                 end
  9115.                 found, position = lib.isSpawner() -- true/false, top/bottom/nil
  9116.                 if not found then
  9117.                     T:go("R2F"..moves + 2 .."R2")
  9118.                 end
  9119.             end
  9120.         end
  9121.        
  9122.         return found, position
  9123.     end
  9124.    
  9125.     function lib.attack()
  9126.         local totalHitsF = 0
  9127.         local totalHitsU = 0
  9128.         local totalHitsD = 0
  9129.         while true do
  9130.             local hitF = false
  9131.             local hitU = false
  9132.             local hitD = false
  9133.             if turtle.attackUp() then
  9134.                 hitU = true
  9135.                 totalHitsU = totalHitsU + 1
  9136.             end
  9137.             if turtle.attackDown() then
  9138.                 hitD = true
  9139.                 totalHitsD = totalHitsD + 1
  9140.             end
  9141.             if turtle.attack() then
  9142.                 hitF = true
  9143.                 totalHitsF = totalHitsF + 1
  9144.             end
  9145.             if hitF or hitU or hitD then
  9146.                 print("hits forward: "..totalHitsF..", up: "..totalHitsU..", down: "..totalHitsD)
  9147.             end
  9148.         end
  9149.     end
  9150.    
  9151.     local found, position = lib.findSpawner() -- move forwards until meet Spawner, go through wall if present
  9152.     if not found then --outside dungeon
  9153.         return {"Trial spawner not found"}
  9154.     end
  9155.     if position == "top" then
  9156.         T:go("B2D1")
  9157.     elseif position == "forward" then
  9158.         T:go("B1")
  9159.     else
  9160.         T:go("B2U1")
  9161.     end
  9162.     T:go("R1F2R2")  --on lower right corner
  9163.     -- starts with wall across spawner
  9164.     buildStructure(R)
  9165.     T:go("U3F1 R1F1 L1U1 F1")
  9166.     R.height = 0
  9167.     R.width = 3
  9168.     R.length = 3
  9169.     R.down = true
  9170.     createFloorCeiling(R)
  9171.     T:go("F1R1 B1D1 B1D2 F1")
  9172.     lib.attack()
  9173.     return {}
  9174. end
  9175.  
  9176. local function sandFillArea(R) -- 81
  9177.     --clearRectangle with sand drop
  9178.     -- could be 1 wide x xx length (trench) up and return
  9179.     -- could be 2+ x 2+
  9180.     -- even no of runs return after last run
  9181.     -- odd no of runs forward, back, forward, reverse and return
  9182.     local success
  9183.     local directReturn = true
  9184.     if R.width % 2 == 1 then
  9185.         directReturn = false
  9186.     end
  9187.     if R.width == 1 then -- trench ahead, so fill then return
  9188.         for i = 1, R.length - 1 do
  9189.             success = utils.dropSand()
  9190.             T:forward(1, false)
  9191.         end
  9192.         success = utils.dropSand()
  9193.         T:go("R2F"..(R.length - 1).."R2", false, 0, false)
  9194.     else --2 or more columns
  9195.         if directReturn then -- R.width = 2,4,6,8 etc
  9196.             for i = 1, R.width, 2 do -- i = 1,3,5,7 etc
  9197.                 -- move along R.length, dropping sand
  9198.                 for j = 1, R.length - 1 do
  9199.                     success = utils.dropSand()
  9200.                     T:forward(1, false)
  9201.                 end
  9202.                 success = utils.dropSand()
  9203.                 T:go("R1F1R1") --turn right and return on next column
  9204.                 for j = 1, R.length - 1 do
  9205.                     success = utils.dropSand()
  9206.                     T:forward(1, false)
  9207.                 end
  9208.                 success = utils.dropSand()
  9209.                 if i < R.width - 2 then -- eg R.width = 8, i compares with 6: 1, 3, 5, 7
  9210.                     T:go("L1F1L1")
  9211.                 end
  9212.             end
  9213.             T:go("R1F"..R.width - 1 .."R1") --return home
  9214.         else
  9215.             for i = 1, R.width, 2 do -- i = 1,3,5,7 etc
  9216.                 -- move along R.length, dropping sand
  9217.                 for j = 1, R.length - 1 do
  9218.                     success = utils.dropSand()
  9219.                     T:forward(1, false)
  9220.                 end
  9221.                 success = utils.dropSand()
  9222.                 T:go("R1F1R1") --turn right and return on next column
  9223.                 for j = 1, R.length - 1 do
  9224.                     success = utils.dropSand()
  9225.                     T:forward(1, false)
  9226.                 end
  9227.                 success = utils.dropSand()
  9228.                 T:go("L1F1L1")
  9229.             end
  9230.             -- one more run then return
  9231.             for j = 1, R.length - 1 do
  9232.                 success = utils.dropSand()
  9233.                 T:forward(1, false)
  9234.             end
  9235.             success = utils.dropSand()
  9236.             T:go("R2F"..R.length.."R1F"..R.width - 1 .."R1")
  9237.         end
  9238.     end
  9239.     return {}
  9240. end
  9241.  
  9242. local function deactivateDragonTower() -- 45
  9243.     -- go up centre of tower to bedrock
  9244.     local height = 0
  9245.     --numBlocksMoved, errorMsg = clsTurtle.doMoves(self, numBlocksRequested, direction)
  9246.     local numBlocks, message = T:doMoves(1, "up")
  9247.     while message == nil do
  9248.         numBlocks, message = T:doMoves(1, "up")
  9249.         height = height + 1
  9250.     end
  9251.     -- go round bedrock and destroy crystal
  9252.     T:go("F1R2U2x1U1x1")
  9253.     -- return to start
  9254.     T:down(height + 5)
  9255.     return {}
  9256. end
  9257.  
  9258. local function undermineDragonTowers() -- 44
  9259.     --[[
  9260.             -13, -40....12, -40                     NNW (4)     NNE (5)
  9261.            
  9262.         -34, -25............33, -25             NWW (2)             NEE (9)
  9263.        
  9264.     -42, -1....................42, 0        W (1)                       E (8)
  9265.    
  9266.          -34, 24............33,24               SWW (3)             SEE (10)
  9267.          
  9268.               -13,39....12, 39                      SSW (7)     SSE (6)
  9269.    
  9270.     North towers centres 25 blocks apart, 40 blocks north of axis
  9271.     Mid-North towers 67 blocks apart, 25 blocks north of axis
  9272.     W-E centres 84 blocks apart, on 0 axis
  9273.     Mid-south towers 67 blocks apart, 24 blocks south of axis
  9274.     South towers centres 25 blocks apart, 39 blocks south of axis
  9275.     ]]
  9276.    
  9277.     local lib = {}
  9278.     function lib.findNextTower(maxDistance, withMarker)
  9279.         local distance = 0
  9280.         local blockTypeF = T:getBlockType("forward")
  9281.         local blockTypeD = T:getBlockType("down")
  9282.         for i = 1, maxDistance do
  9283.             if blockTypeF ~= "minecraft:obsidian" and blockTypeD ~= "minecraft:obsidian" then -- not in a tower
  9284.                 if withMarker and blockTypeD ~= "minecraft:obsidian" then -- used to mark 0 coordinate
  9285.                     T:place("cobble", "down", false) -- place cobblestone or cobbled deepslate to mark zero coordinate
  9286.                 end
  9287.             else    -- obsidian found, could still be in an earlier tower
  9288.                 if i > 10 then
  9289.                     break
  9290.                 end
  9291.             end
  9292.             T:go("F1x0")
  9293.             distance = distance + 1
  9294.             blockTypeF = T:getBlockType("forward")
  9295.             blockTypeD = T:getBlockType("down")
  9296.         end
  9297.         if distance == maxDistance then -- obsidian not found ? wrong place/ direction
  9298.             print("Obsidian not found")
  9299.             error()
  9300.         end
  9301.         -- will now be at side of a tower
  9302.         lib.findCentre() -- move into tower to find the other side
  9303.         return distance
  9304.     end
  9305.    
  9306.     function lib.findCentre()
  9307.         local width = 0
  9308.         -- while obsidian in front or below (previously entered tower) measure width and return to centre
  9309.         local blockTypeF = T:getBlockType("forward")
  9310.         local blockTypeD = T:getBlockType("down")
  9311.         while blockTypeF == "minecraft:obsidian" or blockTypeD == "minecraft:obsidian" do
  9312.             T:go("F1x0")
  9313.             width = width + 1
  9314.             blockTypeF = T:getBlockType("forward")
  9315.             blockTypeD = T:getBlockType("down")
  9316.         end
  9317.         -- will always go outside the tower 1 block. width of 5 block tower = 6
  9318.         T:go("R2F"..math.ceil(width / 2)) --return to centre of tower
  9319.         T:turnLeft(1) -- now find another edge of the tower, dig forward until out of obsidian
  9320.         for i = 1, math.ceil(width) do  -- give additional loops if missed centre
  9321.             blockTypeF = T:getBlockType("forward")
  9322.             blockTypeD = T:getBlockType("down")
  9323.             if blockTypeF == "minecraft:obsidian" or blockTypeD == "minecraft:obsidian" then
  9324.                 T:go("F1x0")
  9325.             else
  9326.                 break
  9327.             end
  9328.         end
  9329.         -- now outside different edge of the tower
  9330.         -- reverse and move width/2, dig up + 1 to mark centre, face original direction
  9331.         T:go("L2F"..math.ceil(width / 2).."R1U2x1")
  9332.         T:place("minecraft:end_stone", "forward", false) -- place endstone to mark facing direction
  9333.         T:down(2)
  9334.     end
  9335.    
  9336.     function lib.findPath(maxLength)
  9337.         local blockTypeD = T:getBlockType("down")
  9338.         local distance = 0
  9339.         while blockTypeD:find("cobble") == nil and distance < maxLength do
  9340.             T:go("F1x0")                            -- return to 0 axis,
  9341.             distance = distance + 1
  9342.             blockTypeD = T:getBlockType("down")
  9343.         end
  9344.         return distance
  9345.     end
  9346.    
  9347.     -- start at 0,y,0, facing West
  9348.     T:dig("up")                                 -- in case not already done
  9349.     local maxLength = 0
  9350.     local blockTypeD
  9351.     local distance = lib.findNextTower(45, true)-- find W tower (1) and mark trail with cobble
  9352.     T:turnRight(2)                     
  9353.     for i = 1, 8 do                             -- head back East 8 blocks, turn left (facing north)
  9354.         T:go("F1x0")                            -- this path may be off-axis, so dig double height
  9355.     end
  9356.     T:turnLeft(1)
  9357.     lib.findNextTower(30)                       -- find NWW tower (2)
  9358.     T:turnRight(2)
  9359.     distance = lib.findPath(30)
  9360.     distance = distance + lib.findNextTower(30) -- find SWW tower (3)
  9361.     T:turnRight(2)
  9362.     distance = lib.findPath(30)
  9363.     T:turnRight(1)                              -- should be on cobble path
  9364.     for i = 1, 21 do                            -- move East 21 blocks, turn left facing North
  9365.         T:go("F1x0")
  9366.     end
  9367.     T:turnLeft(1)
  9368.    
  9369.     distance = lib.findNextTower(45)        -- find NNW tower (4)
  9370.     T:turnRight(1)                         
  9371.     distance = lib.findNextTower(30)        -- find NNE tower (5)
  9372.     T:turnRight(1)
  9373.     distance = lib.findNextTower(85)        -- find SSE tower (6)
  9374.     T:turnRight(1)
  9375.  
  9376.     distance = lib.findNextTower(30)        -- find SSW tower (7)
  9377.     T:turnRight(1)
  9378.     distance = lib.findPath(40)             -- head North to 0 axis
  9379.     T:go("R1F13")                           -- return to 0,0 facing East
  9380.     distance = lib.findNextTower(45, true)  -- find E tower (8)
  9381.    
  9382.     T:turnRight(2)                     
  9383.     for i = 1, 9 do
  9384.         T:go("F1x0")                        -- this path may be off-axis, so dig double height
  9385.     end
  9386.     T:turnRight(1)
  9387.    
  9388.     distance = lib.findNextTower(30)        -- find NEE tower (9)
  9389.     T:turnRight(2)
  9390.     distance = lib.findPath(30) -- return to 0 axis
  9391.     distance = lib.findNextTower(30)        -- find SEE tower (10)
  9392.     T:turnRight(2)
  9393.     distance = lib.findPath(30)             -- return to 0 axis
  9394.     T:go("L1F33")                           -- return to 0, 0
  9395.    
  9396.     return {}
  9397. end
  9398.  
  9399. local function demolishPortal(R) -- 43
  9400.     --[[
  9401.     R.length = length of portal NOT width default 4
  9402.     R.height = height of portal default 5
  9403.     R.width = thickness of portal default 1
  9404.     R.data = "bury" to embed bottom into ground
  9405.     R.subChoice 1 = facing portal, 2 = aligned
  9406.     ]]
  9407.     local data = R.data
  9408.     if R.subChoice == 1 then -- facing portal
  9409.         T:go("F"..R.width.."R1")
  9410.     else
  9411.         T:forward(1)
  9412.     end
  9413.     if R.data == "bury" then
  9414.         T:down(1)
  9415.     end
  9416.  
  9417.     R.data = "up"
  9418.     R.silent = true
  9419.     if R.width == 1 then
  9420.         clearWall(R)
  9421.     else
  9422.         clearBuilding(R, true, true)
  9423.     end
  9424.     if data == "bury" then
  9425.         T:up(1)
  9426.     end
  9427.     if R.subChoice == 1 then -- facing portal
  9428.         T:go("R1F1L1F1L1")
  9429.     end
  9430.    
  9431.     return {}
  9432. end
  9433.  
  9434. local function digTrench(R) -- 77
  9435.     local blockType
  9436.     -- go down R.height, move forward
  9437.     if R.length == 0 then
  9438.         R.length = 4096 -- will go out of loaded chunks and stop or max 4096 on a server
  9439.     end
  9440.     for i = 1, R.length do
  9441.         local count = 0
  9442.         for down = 1, R.height do
  9443.             blockType = T:isWaterOrLava("down")
  9444.             -- go down only if no water or lava below
  9445.             if blockType:find("water") == nil and blockType:find("lava") == nil then
  9446.                 T:down(1)
  9447.                 count = count + 1
  9448.             end
  9449.         end
  9450.         T:go("C2", false, 0, true)              -- if empty below fill void
  9451.         T:go("U"..count)                        -- return to surface, continue if block above
  9452.         while turtle.detect() do                -- go up while block in front
  9453.             blockType = T:getBlockType("forward")
  9454.             if T:isVegetation(blockType) then
  9455.                 T:dig("forward")
  9456.                 break
  9457.             elseif blockType:find("log") ~= nil then
  9458.                 T:harvestTree("forward", false)
  9459.             else
  9460.                 T:up(1)
  9461.             end
  9462.         end
  9463.         T:forward(1)                            -- move forward
  9464.         while not turtle.detectDown() do        -- go down until block detected
  9465.             blockType = T:isWaterOrLava("down")
  9466.             if blockType:find("water") == nil and blockType:find("lava") == nil then
  9467.                 T:down(1)
  9468.             else
  9469.                 break
  9470.             end
  9471.         end
  9472.     end
  9473.    
  9474.     return {}
  9475. end
  9476.  
  9477. local function harvestTreeFarm(R) -- 24
  9478.     local lib = {}
  9479.    
  9480.     function lib.getLogCount()
  9481.         local count = 0
  9482.         for i = 1,16 do
  9483.             local item, itemCount = T:getSlotContains(i)
  9484.             if item:find("log") ~= nil then
  9485.                 count = count + itemCount
  9486.             end
  9487.         end
  9488.        
  9489.         return count
  9490.     end
  9491.    
  9492.     function lib.initialise(R)
  9493.         -- assumes legacy tree farm with turtle on polished block 4 blocks from corner
  9494.         local message  = ""
  9495.         R.treeSize = "single"
  9496.         local blockType = T:getBlockType("forward")
  9497.         --local logType = ""
  9498.         --local startHeight = 0
  9499.         local range = 0
  9500.         if blockType == "" then
  9501.             while turtle.forward() do
  9502.                 range = range + 1
  9503.                 if range == 3 then
  9504.                     break
  9505.                 end
  9506.             end
  9507.         end
  9508.         blockType = T:getBlockType("forward")
  9509.         if blockType:find("dirt") ~= nil then   -- dirt found
  9510.             T:go("R1F1L1")
  9511.             blockType = T:getBlockType("forward")
  9512.             if blockType:find("dirt") ~= nil then
  9513.                 R.treeSize = "double"
  9514.             end
  9515.             T:go("L1F1 R1")
  9516.         else    -- dirt NOT found where expected
  9517.             message = "Unable to determine position"
  9518.         end
  9519.         T:up(1)
  9520.         blockType = T:getBlockType("forward")   -- 1 block above dirt
  9521.         if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil or blockType:find("propagule") ~= nil then
  9522.             local parts = T:getNames(blockType)
  9523.             if parts[2] == "dark" then
  9524.                 R.logType = "dark_oak"
  9525.             else
  9526.                 R.logType = parts[2]                -- eg "oak"
  9527.             end
  9528.             if R.logType == "mangrove" then
  9529.                 R.useBlockType = "mangrove_propagule"
  9530.             else
  9531.                 R.useBlockType = parts[2].."_sapling"   -- eg "oak_sapling"
  9532.             end
  9533.         end
  9534.         T:down(1)   -- facing dirt
  9535.        
  9536.         return R, message
  9537.     end
  9538.    
  9539.     function lib.waitForGrowth(R)
  9540.         local pattern = R.treeSize  --"single","double"
  9541.         local elapsed = 0
  9542.         local facing = "left"
  9543.         local ready = {}
  9544.         ready.left = false
  9545.         ready.top = false
  9546.         ready.right = false
  9547.         ready.bottom = false
  9548.         if R.logType == "mangrove" then
  9549.             pattern = "mangrove"
  9550.             local facings = {"left", "top", "right", "bottom"}
  9551.             T:up(1) -- go up from dirt to sapling level
  9552.             while not ready.left or not ready.right or not ready.top or not ready.bottom do
  9553.                 for i = 1, 4 do
  9554.                     local blockType = T:getBlockType("forward")
  9555.                     if blockType:find("propagule") ==  nil then -- either grown or deleted by roots
  9556.                         ready[facings[i]] = true
  9557.                     end
  9558.                     T:turnRight(1)
  9559.                 end
  9560.                 if ready.left and ready.right and ready.top and ready.bottom then
  9561.                     break
  9562.                 else
  9563.                     sleep(15)
  9564.                     elapsed = elapsed + 15
  9565.                     if  elapsed / 60 > 15 then  -- max 15 mins real time before farm is harvested
  9566.                         break
  9567.                     end
  9568.                 end
  9569.                 print("Waiting for mangrove growth "..elapsed / 60 .." minutes")
  9570.                 print("Left = "..tostring(ready.left)..
  9571.                       ", top = "..tostring(ready.top)..
  9572.                       ", right = "..tostring(ready.right)..
  9573.                       ", bottom = "..tostring(ready.bottom))
  9574.                
  9575.             end
  9576.             --T:go("L1D1")
  9577.             T:turnLeft(1)   -- face front
  9578.         else
  9579.             while not ready.left or not ready.right do
  9580.                 T:up(1) -- go up from dirt to sapling level
  9581.                 local blockType = T:getBlockType("forward")
  9582.                 if blockType:find("log") ~=  nil then
  9583.                     ready[facing] = true
  9584.                 end
  9585.                 if pattern == "single" then
  9586.                     --alternate between 2 trees, starts facing left
  9587.                     T:turnRight(2)
  9588.                     if facing == "left" then
  9589.                         facing = "right"
  9590.                     elseif facing == "right" then
  9591.                         facing = "left"
  9592.                     end
  9593.                     blockType = T:getBlockType("forward")
  9594.                     if blockType:find("log") ~=  nil then
  9595.                         ready[facing] = true
  9596.                     end
  9597.                     T:down(1)   -- drop below sapling to dirt level
  9598.                 elseif pattern == "double" then
  9599.                     if ready.left and facing == "left" then-- tree on left now grown. check right
  9600.                         T:go("R2F2")
  9601.                         facing = "right"
  9602.                     end
  9603.                     blockType = T:getBlockType("forward")
  9604.                     if blockType:find("log") ~=  nil then
  9605.                         ready[facing] = true
  9606.                     end
  9607.                     T:down(1)   -- drop below sapling to dirt level
  9608.                 end
  9609.                 T:clear()
  9610.                 print("Farm type: "..pattern)
  9611.                 print("Waiting for tree growth "..elapsed / 60 .." minutes")
  9612.                 print("Left grown = "..tostring(ready.left)..", right grown = "..tostring(ready.right))
  9613.                 if not ready.left or not ready.right then
  9614.                     sleep(15)
  9615.                     elapsed = elapsed + 15
  9616.                     if pattern == "single" and elapsed / 60 > 10 then   -- max 10 mins real time before farm is harvested
  9617.                         break
  9618.                     elseif pattern == "double" and elapsed / 60 > 15 then   -- max 15 mins real time before farm is harvested
  9619.                         break
  9620.                     end
  9621.                 end
  9622.             end
  9623.         end
  9624.         -- growth complete
  9625.         if pattern == "single" then
  9626.             if facing == "right" then
  9627.                 T:turnRight(1)
  9628.             else
  9629.                 T:turnLeft(1)
  9630.             end
  9631.             --T:go("F1R1 F3R1")         -- facing first dirt
  9632.             T:go("F1R1 F1R1")           -- facing first dirt
  9633.         elseif pattern == "double" then -- assume on right side
  9634.             if facing == "right" then
  9635.                 T:go("R1F1 R1F4 R1")
  9636.             else
  9637.                 T:go("L1F1 R1F2 R1")
  9638.             end
  9639.         elseif pattern == "mangrove" then
  9640.             T:go("D2F6 U1F1 R1F6 R1F1 U1")
  9641.         end
  9642.         -- ends facing dirt at base of first tree
  9643.         -- no return needed, function exit so trees are grown
  9644.     end
  9645.    
  9646.     function lib.watchFarm(R)
  9647.         -- rotate to check if dirt on both sides
  9648.         -- R.subChoice == 1: 16 single trees, 2 = 4 doubles
  9649.         if R.logType ~= "mangrove" then
  9650.             R.treeSize = "single"
  9651.             T:turnRight(2)  -- if no dirt then on 4 x doubles
  9652.             if T:getBlockType("forward") == "" then
  9653.                 R.treeSize = "double"
  9654.             end
  9655.             T:saveToLog("lib.watchFarm: R.treeSize set to '"..R.treeSize.."'")
  9656.             T:turnLeft(2)   -- face lower left double dirt
  9657.         end
  9658.         lib.waitForGrowth(R)
  9659.        
  9660.         return R
  9661.     end
  9662.    
  9663.     function lib.harvestSingle(direction, moves)
  9664.         -- if direction == "up": starting inside tree on dirt at dirt level
  9665.         T:saveToLog("lib.harvestSingle('"..direction.."', moves = "..moves)
  9666.         if direction == "up" then
  9667.             while turtle.detectUp() do
  9668.                 T:up(1)
  9669.                 moves = moves + 1
  9670.             end
  9671.         else    -- direction = "down", but could be mid-tree
  9672.             local movesUp = 0
  9673.             while turtle.detectUp() do
  9674.                 T:up(1)
  9675.                 movesUp = movesUp + 1
  9676.             end
  9677.             T:down(movesUp)
  9678.             T:down(moves)
  9679.         end
  9680.         return moves
  9681.     end
  9682.    
  9683.     function lib.harvestSingleRow()
  9684.         -- start next to tree/dirt
  9685.         T:go("F1")
  9686.         local moves = lib.harvestSingle("up", 0)
  9687.         T:go("F2")
  9688.         lib.harvestSingle("down", moves)
  9689.         T:go("F2")
  9690.         moves = lib.harvestSingle("up", 0)
  9691.         T:go("F2")
  9692.         lib.harvestSingle("down", moves)
  9693.     end
  9694.    
  9695.     function lib.harvestDouble()
  9696.         T:forward(1)    -- dig dirt, move into left (S) corner
  9697.         local moves = 0
  9698.         while turtle.detectUp() do
  9699.             turtle.dig()
  9700.             turtle.digUp()
  9701.             turtle.up()
  9702.             moves = moves + 1
  9703.         end
  9704.         turtle.dig()
  9705.         T:go("R1F1L1")  -- move to right corner
  9706.         for i = 1, moves do
  9707.             turtle.dig()
  9708.             turtle.digDown()
  9709.             turtle.down()
  9710.         end
  9711.         turtle.dig()
  9712.         T:go("F1L1F1R1") -- move to left corner (N)
  9713.     end
  9714.        
  9715.     --T:setUseLog(true, "treeFarmLog.txt", true)    -- T:setUseLog(use, filename, delete)
  9716.     --dbug = true                               -- set dbug flag
  9717.    
  9718.     R.silent = true
  9719.     -- if on modem, R.networkFarm has already been set
  9720.     T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm))
  9721.  
  9722.     if R.networkFarm then
  9723.         local message = network.loadStorageLists()  -- initialises or creates lists of where an item can be found: GLOBAL LISTS!
  9724.         if message ~= nil then return {message} end
  9725.         network.emptyInventory(R, {"sapling", "propagule", "dirt"}, {"all"}, true)
  9726.     end
  9727.    
  9728.     if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then
  9729.         local turtleSlot, turtleCount = network.getItemFromNetwork("chest", "log", 16)
  9730.         if turtleSlot > 0 then
  9731.             if turtle.craft() then
  9732.                 turtle.refuel()
  9733.                 T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm))
  9734.             end
  9735.         end
  9736.     end
  9737.    
  9738.     if R.networkFarm then           -- monitor trees for growth
  9739.         if R.logType == "mangrove" then
  9740.             T:go("F1D1")
  9741.             T:place("dirt", "up")
  9742.             T:go("F6x2U1L1")    -- move under dirt covering, clear roots from hopper, move level with dirt, face left
  9743.         else
  9744.             T:go("F4R1")                -- either in between 2 trees or in gap between double trees at dirt level
  9745.             if turtle.detect() then     -- single trees, move between 1st and 2nd rows
  9746.                 T:go("R1F1 R1F2 R1F1 L1")
  9747.             else    -- using double trees
  9748.                 T:go("R2F1")
  9749.                 if not turtle.detect() then
  9750.                     return {"Unable to determine position"}
  9751.                 end
  9752.             end
  9753.         end
  9754.         R = lib.watchFarm(R)    -- wait for trees to grow, then start harvest
  9755.     else
  9756.         --logType, startHeight, R = lib.initialise(R) -- possible ID tree type + move to correct position 1 above dirt
  9757.         R, message = lib.initialise(R)      -- possible ID tree type + move to correct position next to first dirt
  9758.         if message ~= "" then
  9759.             return{message}
  9760.         end
  9761.     end
  9762.     T:saveToLog("R.networkFarm = "..tostring(R.networkFarm)..", logType = "..R.logType..", treeSize = "..R.treeSize)
  9763.     -- different clearing for different trees:
  9764.     -- double spruce and jungle: staight up/down or small
  9765.     if R.logType == "mangrove" then
  9766.         clearRectangle({width = 13, length = 13, up = true, down = true })
  9767.         T:go("U2F2 R1F2L1")
  9768.         clearSolid({width = 9, length = 9, height = 18, direction ="up"})
  9769.         T:go("D3R1 F4R1 F3R2")
  9770.         network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
  9771.     elseif R.logType == "birch" or R.logType == "spruce" or R.logType == "jungle" then  -- use column harvest
  9772.         if R.treeSize == "single" then
  9773.             lib.harvestSingleRow()
  9774.             T:go("F1R1F2R1")
  9775.             lib.harvestSingleRow()
  9776.             T:go("F1L1F2L1")
  9777.             lib.harvestSingleRow()
  9778.             T:go("F1R1F2R1")
  9779.             lib.harvestSingleRow()
  9780.             if R.networkFarm then
  9781.                 T:go("F1R1 F3L1 F3R2")
  9782.                 network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
  9783.             else
  9784.                 T:go("F1R1 F6L1 F3R2")
  9785.             end
  9786.         else
  9787.             lib.harvestDouble()
  9788.             T:go("F3")
  9789.             lib.harvestDouble()
  9790.             T:go("R1F4")
  9791.             lib.harvestDouble()
  9792.             T:go("R1F4")
  9793.             lib.harvestDouble()
  9794.             if R.networkFarm then
  9795.                 T:go("F1R1 F3L1 F3R2")
  9796.                 network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
  9797.             else
  9798.                 T:go("F1R1 F6L1 F3R2")
  9799.             end
  9800.         end
  9801.     else    -- use cube harvest, including mangrove
  9802.         local size = 10
  9803.         local start = "L1F1 L1F1 R2"
  9804.         local finish = "R1F1 R1F3 R2"
  9805.         if R.logType == "acacia" then
  9806.             size = 12
  9807.             start = "L1F2 L1F2 R2"
  9808.             finish = "R1F2 R1F2 R2"
  9809.         elseif R.logType == "cherry" then
  9810.             size = 14
  9811.             start = "L1F3 L1F3 R2"
  9812.             finish = "R1F3 R1F1 R2"
  9813.         end
  9814.         T:go("U1F1")    -- into first log at base of tree
  9815.         clearRectangle({width = 7, length = 7, up = true, down = true})
  9816.         --T:go("L1F2 L1F2 R2")  -- rect size 12
  9817.         --T:go("L1F1 L1F1 R2")  -- rect size 10
  9818.         T:go(start)
  9819.         local height = 0
  9820.         local pastLogCount = -1
  9821.         local currentLogCount = lib.getLogCount()
  9822.         --while currentLogCount ~= pastLogCount do
  9823.         while currentLogCount - pastLogCount > 5 do -- ony continue if at least 5 logs harvested last round
  9824.             T:up(3)
  9825.             height = height + 3
  9826.             pastLogCount = currentLogCount -- 0 when loop starts
  9827.             --clearRectangle({width = 12, length = 12, up = true, down = true})
  9828.             clearRectangle({width = size, length = size, up = true, down = true})
  9829.             currentLogCount = lib.getLogCount() -- eg 20 logs from first round
  9830.         end
  9831.         T:down(height + 1)
  9832.         --T:go("R1F2 R1F2 R2")      -- on polished stone rect size 12
  9833.         --T:go("R1F1 R1F3 R2")      -- on polished stone rect size 10
  9834.         T:go(finish)
  9835.         if R.networkFarm then
  9836.             T:go("R1F3 L1")         -- on modem
  9837.             network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
  9838.         end
  9839.     end
  9840.    
  9841.     return {}   -- if player initiated, stops here. If R.auto then returns to plantTreeFarm()
  9842. end
  9843.  
  9844. local function harvestObsidian(R) -- 41
  9845.     local lib = {}
  9846.    
  9847.     function lib.forward(move)
  9848.         T:isWaterOrLava("forward")  -- automatically use lava ahead to refuel
  9849.         T:isWaterOrLava("down")     -- automatically use lava down to refuel
  9850.         T:go("C2", false, 0, false) -- place / replace block below
  9851.         if move then
  9852.             T:forward(1)
  9853.         end
  9854.     end
  9855.    
  9856.     function lib.home(outward)
  9857.         if outward then
  9858.             T:go("L1F"..R.width - 1 .."L1F"..R.length - 1)
  9859.         else   
  9860.             T:go("R1F"..R.width - 1 .."R1")
  9861.         end
  9862.     end
  9863.    
  9864.     function lib.start()
  9865.         local lavaSlot = T:getItemSlot("lava")
  9866.         if lavaSlot > 0 then
  9867.             turtle.select(slot)
  9868.             turtle.refuel()
  9869.         end
  9870.         T:down(1)
  9871.     end
  9872.    
  9873.     local outward = true
  9874.    
  9875.     lib.start()                     -- use lava bucket if placed, move down into block below
  9876.     for w = 1, R.width do
  9877.         for l = 1, R.length do
  9878.             if l < R.length then
  9879.                 lib.forward(true)
  9880.             else
  9881.                 lib.forward(false)
  9882.             end
  9883.         end
  9884.         if w < R.width then
  9885.             if outward then
  9886.                 T:go("R1F1R1")
  9887.             else
  9888.                 T:go("L1F1L1")
  9889.             end
  9890.             outward = not outward
  9891.         end
  9892.     end
  9893.    
  9894.     lib.home(outward)
  9895.    
  9896.     return {}
  9897. end
  9898.  
  9899. local function harvestShulkers(R)
  9900.     local lib = {}
  9901.    
  9902.     function lib.attackAll()
  9903.         return turtle.attack(), turtle.attackUp(), turtle.attackDown()
  9904.     end
  9905.  
  9906.     function lib.attack()
  9907.         local forward, up, down = lib.attackAll()
  9908.         while forward or up or down do
  9909.             forward, up, down = lib.attackAll()
  9910.             sleep(0.2)
  9911.         end
  9912.     end
  9913.    
  9914.     function lib.approach(direction, limit, dig)
  9915.         -- move forward until stopped by shulker
  9916.         limit = limit or 64
  9917.         dig = dig or false
  9918.         local count = 0
  9919.         local solidDown = false
  9920.         move = turtle.forward
  9921.         if direction == "up" then
  9922.             move = turtle.up
  9923.         elseif direction == "down" then
  9924.             move = turtle.down
  9925.         end
  9926.         local forward, up, down = lib.attackAll()
  9927.         if forward or up or down then -- attacks suceeded
  9928.             return true, 0, solidDown
  9929.         else
  9930.             while move() do
  9931.                 count = count + 1
  9932.                 if turtle.detectDown() then
  9933.                     solidDown = true
  9934.                 end
  9935.                 if count >= limit then
  9936.                     return false, count, solidDown
  9937.                 end
  9938.                 forward, up, down = lib.attackAll()
  9939.                 if forward or up or down then
  9940.                     return true, count, solidDown
  9941.                 else
  9942.                     if dig then
  9943.                         T:dig("forward")
  9944.                     end
  9945.                 end
  9946.             end
  9947.             return false, count, solidDown
  9948.         end
  9949.     end
  9950.    
  9951.     function lib.home(direction, moves)
  9952.         local move = turtle.back
  9953.         if direction == "up" then
  9954.             move = turtle.down
  9955.         elseif direction == "down" then
  9956.             move = turtle.up
  9957.         end
  9958.         for i = 1, moves do
  9959.             move()
  9960.         end
  9961.     end
  9962.    
  9963.     function lib.checkPosition()
  9964.         if T:detect("forward") then         -- wall in front
  9965.             T:turnRight(1)
  9966.             if T:detect("forward") then     -- wall to right
  9967.                 T:turnLeft(1)
  9968.                 return true                 -- position corrected
  9969.             else
  9970.                 T:turnLeft(2)
  9971.                 if T:detect("forward") then -- wall in front. position correct
  9972.                     return true
  9973.                 end
  9974.             end
  9975.         end
  9976.         return false
  9977.     end
  9978.    
  9979.     function lib.getLength()
  9980.         local count = 0
  9981.         while turtle.detectDown() do
  9982.             count = count + 1
  9983.             T:forward(1)
  9984.         end
  9985.         utils.goBack(1)
  9986.         return count
  9987.     end
  9988.    
  9989.     function lib.clearWall()
  9990.         local distance = 0
  9991.         while distance < 9 do   -- smallest external walls are 8 x 8
  9992.             local success, count = lib.approach("forward", 8 - distance)
  9993.             if success then
  9994.                 lib.attack()
  9995.             end
  9996.             distance = distance + count
  9997.         end
  9998.         T:turnLeft(1)
  9999.         if T:detect("forward") then -- larger than 8 blocks
  10000.             T:turnRight(1)
  10001.             while distance < 14 do  -- larger builds are 14 x 14
  10002.                 local success, count = lib.approach("forward", 13 - distance)
  10003.                 if success then
  10004.                     lib.attack()
  10005.                 end
  10006.                 distance = distance + count
  10007.             end
  10008.             T:go("L1x2")
  10009.         end
  10010.     end
  10011.    
  10012.     function lib.roof()
  10013.         -- check position
  10014.         local doContinue = lib.checkPosition()
  10015.        
  10016.         if doContinue then
  10017.             T:go("U2F3 R1F3 R1")
  10018.             local length = lib.getLength()
  10019.             local width = 1
  10020.             local outward = lib.turnRound(true)
  10021.             local success, count, onRoof = false, 0, true  
  10022.             while onRoof do
  10023.                 local distance = 0
  10024.                 while distance < length - 1 do
  10025.                     success, count, onRoof = lib.approach("forward", length - 1 - distance)
  10026.                     if success then
  10027.                         lib.attack()
  10028.                     end
  10029.                     if count == 0 then
  10030.                         turtle.dig()
  10031.                     end
  10032.                     distance = distance + count
  10033.                 end
  10034.                 width = width + 1
  10035.                 outward = lib.turnRound(outward)
  10036.             end
  10037.             if outward then
  10038.                 T:go("F".. 3 .."L1F"..width - 3 .."D2L1")
  10039.             else
  10040.                 T:go("F".. length - 3 .."R1F"..width - 3 .."D2L1")
  10041.             end
  10042.             return {}
  10043.         else
  10044.             return {"Turtle not in front of a wall"}
  10045.         end
  10046.     end
  10047.    
  10048.     function lib.turnRound(outward)
  10049.         if outward then
  10050.             T:go("R1F1R1")
  10051.         else
  10052.             T:go("L1F1L1")
  10053.         end
  10054.         return not outward
  10055.     end
  10056.  
  10057.     function lib.upAndOver()
  10058.         local start, height, forward = 0, 0, 0
  10059.         while turtle.detect() do
  10060.             turtle.up()
  10061.             start = start + 1
  10062.         end
  10063.         while turtle.forward() do
  10064.             forward = forward + 1
  10065.         end
  10066.         turtle.turnRight()
  10067.         while not turtle.detectUp() do
  10068.             local success, count = lib.approach("up", 64, true)
  10069.             if success then
  10070.                 lib.attack()
  10071.             end
  10072.             height = height + count
  10073.         end
  10074.         T:turnRight(2)
  10075.         while not turtle.detectDown() do
  10076.             if lib.approach("down", 64, true) then
  10077.                 lib.attack()
  10078.             end
  10079.         end
  10080.         T:turnLeft(1)
  10081.         for i = 1, forward do
  10082.             turtle.forward()
  10083.         end
  10084.         for i = 1, start do
  10085.             turtle.down()
  10086.         end
  10087.         T:turnRight(2)
  10088.     end
  10089.    
  10090.     function lib.walls()
  10091.         local doContinue = lib.checkPosition()
  10092.         if doContinue then
  10093.             T:go("F2R1 F2R2 D1x2")      -- on corner outside middle of wall, facing along its length, dig light rod
  10094.             for i = 1, 4 do
  10095.                 lib.clearWall()
  10096.             end
  10097.             T:go("F2L1 U1F2 R2")
  10098.         else
  10099.             return {"Turtle not in front of a wall"}
  10100.         end
  10101.     end
  10102.        
  10103.     local direction = "forward"
  10104.     local doContinue = false
  10105.    
  10106.     if R.subChoice == 1 then        -- Shulker is above
  10107.         direction = "up"
  10108.         doContinue = true
  10109.     elseif R.subChoice == 2 then    -- Shulker is ahead
  10110.         doContinue = true
  10111.     elseif R.subChoice == 3 then    -- Shulker is below
  10112.         direction = "down"
  10113.         doContinue = true
  10114.     else
  10115.         if R.subChoice == 4 then    -- Climb tower wall
  10116.             lib.upAndOver()
  10117.         elseif R.subChoice == 5 then    -- Clear roof above
  10118.             return lib.roof()
  10119.         elseif R.subChoice == 6 then    -- Clear outside walls
  10120.             lib.walls()
  10121.         end
  10122.    
  10123.     end
  10124.     if doContinue then
  10125.         local success, moves = lib.approach(direction, 64)
  10126.         if success then
  10127.             lib.attack()
  10128.         end
  10129.         lib.home(direction, moves)
  10130.     end
  10131.    
  10132.     return {}
  10133. end
  10134.  
  10135. local function upgradeFarmland(R)
  10136.     local essences = {":inferium", ":prudentium", ":tertium", ":imperium", ":supremium", ":awakened" , ":insanium"}
  10137.    
  10138.     local lib = {}
  10139.    
  10140.     function lib.isHigherTeir(essence, farmLand)
  10141.         -- eg "ma:prudentium_essence", "mc:farmland"
  10142.         local teir = 0
  10143.         for index = 1, #essences do
  10144.             if farmLand:find(essences[index]) ~= nil then
  10145.                 teir = index    -- 0 if vanilla, else eg 2 for prudentium
  10146.                 break
  10147.             end
  10148.         end
  10149.         for index = 1, #essences do
  10150.             if essence:find(essences[index]) ~= nil then
  10151.                 if index > teir then
  10152.                     return true
  10153.                 end
  10154.             end
  10155.         end
  10156.         return false
  10157.     end
  10158.    
  10159.     function lib.upgrade(essence, slot)
  10160.         -- essence is the slot no of any essence
  10161.         turtle.select(slot)
  10162.         local blockType = T:getBlockType("up")
  10163.         if blockType:find("farmland") ~= nil then           -- farmland found (vanilla or modded)
  10164.             if lib.isHigherTeir(essence, blockType) then    -- eg "ma:inferium", mc:farmland"
  10165.                 turtle.placeUp()
  10166.             end
  10167.         end
  10168.     end
  10169.     -- check if any essence still onboard
  10170.     T:checkInventoryForItem({"essence"}, {95}, false)
  10171.     -- return slotData.lastSlot, total, slotData -- integer, integer, table
  10172.     local name = ""
  10173.     local slot, amount, data = T:getItemSlot("essence")
  10174.     name = data.mostName or ""
  10175.     local empty = T:getFirstEmptySlot()
  10176.    
  10177.     if slot > 0 then
  10178.         T:go("D2")
  10179.         local outward = true
  10180.         for w = 1, 10 do
  10181.             for i = 1, 9 do
  10182.                 if turtle.getItemCount(slot) == 0 then
  10183.                     slot, amount, data = T:getItemSlot("essence")
  10184.                     name = data.mostName or ""
  10185.                     if slot == 0 then
  10186.                         slot = empty
  10187.                     end
  10188.                 end
  10189.                 lib.upgrade(name, slot)
  10190.                 if w == 1 and i == 1 then
  10191.                     T:go("F1R2 C1R2")
  10192.                 elseif w == 10 and i == 1 then
  10193.                    
  10194.                 else
  10195.                     T:forward(1)
  10196.                 end
  10197.             end
  10198.             if outward then
  10199.                 lib.upgrade(name, slot)
  10200.                 if w == 1 then
  10201.                     T:go("L1F1 L2C1 R1")
  10202.                 elseif w == 9 then
  10203.                     T:go("L1F1 L1F1 L2C1 L2")
  10204.                 else
  10205.                     T:go("L1F1L1")
  10206.                 end
  10207.             else
  10208.                 if w < 10 then
  10209.                     lib.upgrade(name, slot)
  10210.                     T:go("R1F1R1")
  10211.                 else
  10212.                     T:go("L1F1 L2C1 R2F8 L1U1 C2U2") -- 1 above normal position
  10213.                 end
  10214.             end
  10215.             outward = not outward
  10216.         end
  10217.         -- sometimes original essence pops out of the ground when upgraded, so rescue it
  10218.         for w = 1, 10 do
  10219.             for i = 1, 9 do
  10220.                 turtle.suckDown()
  10221.                 turtle.suck()
  10222.                 T:forward(1)
  10223.             end
  10224.             if outward then
  10225.                 turtle.suckDown()
  10226.                 turtle.suck()
  10227.                 T:go("L1F1L1")
  10228.             else
  10229.                 if w < 10 then
  10230.                     turtle.suckDown()
  10231.                     turtle.suck()
  10232.                     T:go("R1F1R1")
  10233.                 else
  10234.                     T:go("L1F9 L1D1") -- normal position
  10235.                 end
  10236.             end
  10237.             outward = not outward
  10238.         end
  10239.     end
  10240.     return ({"Farmland Upgraded"})
  10241. end
  10242.  
  10243. local function manageFarm(R)
  10244.     local lib = {}
  10245.        
  10246.     function lib.askPlayerForCrops()
  10247.         local seed  = ""
  10248.         pp.itemColours = {colors.lightGray, colors.red, colors.orange, colors.brown, colors.magenta, colors.yellow}
  10249.         crops = {"minecraft:wheat_seeds", "minecraft:beetroot_seeds", "minecraft:carrots", "minecraft:potatoes", "mysticalagriculture", "none"}
  10250.         choices = {"wheat (seeds)", "beetroot (seeds)", "carrot", "potato", "Mystical Agriculture", "Till soil only"}
  10251.         choice = menu.menu("Choose preferred crop", choices, pp, "Type number of your choice")
  10252.         crop = crops[choice]
  10253.         if crop == "none" then
  10254.             return "", ""
  10255.         elseif crop == "mysticalagriculture" then
  10256.             T:checkInventoryForItem({"seeds"}, {95}, true, "Add one type of M. Agriculture seeds")
  10257.         else
  10258.             T:checkInventoryForItem({crop}, {95}, true, "Do not mix! add as many as you want")
  10259.         end
  10260.         crop = T:getMostItem("", false)     -- not searching for any specific item, not checking stone only
  10261.         -- crop could be wheat/beetroot seeds, carrots, potatoes or mystical agriculture seeds
  10262.         seed, crop = lib.getCropSeed(crop)  -- seed type or "", crop type
  10263.         return seed, crop  
  10264.     end
  10265.        
  10266.     function lib.assessPlot(R)
  10267.         local crop = T:getBlockType("forward")  -- convert ma:inferium_crop to ma:inferium_seeds
  10268.         local seed = lib.getCropSeed(crop)
  10269.         turtle.down()                                   -- into water source
  10270.         local soil = T:getBlockType("forward")
  10271.         turtle.up()                                     -- at crop level
  10272.         return crop, seed, soil
  10273.     end
  10274.    
  10275.     function lib.checkEquipment(R, itemRequired)
  10276.         -- Check if item is equipped and return it to slot
  10277.         T:clear()
  10278.         print("Checking equipment. Please wait...")
  10279.         local equipped, slot = T:getEquipped("right", false)    -- see what is equipped and replace it
  10280.         if equipped == itemRequired then
  10281.             equipped, slot = T:getEquipped("right", true)       -- remove item and return slot
  10282.             return slot
  10283.         end
  10284.  
  10285.         return 0    -- not found
  10286.     end
  10287.        
  10288.     function lib.crossFarm(R)
  10289.         -- used with goHome to find starting point
  10290.         local blockType = ""
  10291.         local isReady, cropType, seed, status
  10292.         isReady, cropType, seed, status, R = lib.isCropReady(R,"down")
  10293.         -- will go forward until chest, barrel, modem or cobble detected below
  10294.         -- if detected within 1 move, this is ignored
  10295.         local numMoves = 0
  10296.         local endOfPath = false
  10297.         while not endOfPath do
  10298.             blockType = T:getBlockType("down")
  10299.             if blockType == "" or cropType ~= "" then --crops or nothing below
  10300.                 turtle.forward()
  10301.             elseif  blockType:find("barrel") ~= nil or
  10302.                     blockType:find("chest") ~= nil or
  10303.                     blockType:find("modem") ~= nil or
  10304.                     blockType:find("cobble") ~= nil then
  10305.                 endOfPath = true
  10306.             end
  10307.             numMoves = numMoves + 1
  10308.         end
  10309.         return R, blockType -- either barrel, chest, modem or cobble
  10310.     end
  10311.    
  10312.     function lib.farmAll(R, isFarmToRight, isFarmToFront)
  10313.         local plotCountR = 0        -- plot a1 harvested
  10314.         local plotCountF = 0        -- plot a1 harvested
  10315.         if isFarmToRight then
  10316.             while isFarmToRight do  -- do all plots on this axis
  10317.                 R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin
  10318.                 plotCountR = plotCountR + 1
  10319.             end
  10320.             lib.goToLeft(R, plotCountR)
  10321.         end
  10322.         if isFarmToFront then
  10323.             while isFarmToFront do  -- do all plots on this axis
  10324.                 plotCountR = 0              -- reset
  10325.                 R, isFarmToRight, isFarmToFront = lib.farmInFront(R)
  10326.                 if isFarmToRight then
  10327.                     while isFarmToRight do  -- do all plots on this axis
  10328.                         R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin
  10329.                         plotCountR = plotCountR + 1
  10330.                     end
  10331.                     lib.goToLeft(R, plotCountR) -- return home and continue with front
  10332.                 end
  10333.                 plotCountF = plotCountF + 1
  10334.             end
  10335.             lib.goToFront(R, plotCountF)
  10336.         end
  10337.     end
  10338.    
  10339.     function lib.farmInFront(R)
  10340.         --[[ facing crops on first farm. move to next farm in front ]]
  10341.         T:go("U1L1 F11D1 R1")                       -- on next farm, facing crops
  10342.         local seed, crop = lib.manageTree(R)        -- refuel, gather seeds or other crops
  10343.         local isFarmToRight = false
  10344.         R, isFarmToRight = lib.harvest(R, seed, crop)       -- harvest field, store crops
  10345.         return R, isFarmToRight
  10346.     end
  10347.    
  10348.     function lib.farmToRight(R)
  10349.         --[[ facing crops on first farm. move to next farm on right side ]]
  10350.         T:go("U1F11 D1")                                -- on next farm, facing crops
  10351.         local seed, crop = lib.manageTree(R)                    -- refuel, gather seeds and other crops
  10352.         R, isFarmToRight = lib.harvest(R, seed, crop)       -- harvest field, store crops
  10353.         -- now at starting position of current plot
  10354.         return R, isFarmToRight
  10355.     end
  10356.    
  10357.     function lib.getCropSeed(crop)
  10358.         -- change growing crops into equivalent seed names
  10359.         -- crop could be seeds, so return equivalent crop
  10360.         local start = crop:find("_crop")
  10361.         if start ~= nil then    -- only modded seeds have "crop"
  10362.             return crop:sub(1, start).."seeds", crop
  10363.         end
  10364.         if crop:find("seeds") ~= nil then   -- asked to return crop from seed type
  10365.             if crop:find("wheat") ~= nil then
  10366.                 return "minecraft:wheat_seeds", "minecraft:wheat"
  10367.             end
  10368.             if crop:find("beetroot") ~= nil then
  10369.                 return "minecraft:beetroot_seeds", "minecraft:beetroot"
  10370.             end
  10371.         end
  10372.         if crop:find("wheat") ~= nil then
  10373.             return "minecraft:wheat_seeds", "minecraft:wheat"
  10374.         end
  10375.         if crop:find("beetroot") ~= nil then
  10376.             return "minecraft:beetroot_seeds", "minecraft:beetroot"
  10377.         end
  10378.         if crop:find("carrot") ~= nil then
  10379.             return "", "minecraft:carrot"
  10380.         end
  10381.         if crop:find("potato") ~= nil then
  10382.             return "", "minecraft:potato"
  10383.         end
  10384.         -- planted crops are plural, harvested singular: carrots / carrot, pototoes/ potato
  10385.         return "", crop -- no seed for carrot / potato
  10386.     end
  10387.    
  10388.     function lib.getHoe()
  10389.         local message = ""
  10390.         if R.networkFarm then   -- get hoe from storage
  10391.             hoeSlot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1)
  10392.             if hoeSlot == 0 then
  10393.                 if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then
  10394.                     hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
  10395.                 end
  10396.             end
  10397.         else    -- put crafting table into barrel in floor
  10398.             T:go("L1F1")        -- over barrel
  10399.             local isStorage, storageType = utils.isStorage("down")
  10400.             if not isStorage then
  10401.                 message =
  10402. [["Farm upgrade required:
  10403. Previous designs had a crafting table
  10404. next to the water source.
  10405.  
  10406. 1. Place a barrel or chest under the turtle
  10407.     instead.
  10408.    
  10409. 2. Restart"
  10410. ]]
  10411.                 return 0, message
  10412.             end
  10413.             -- must be storage below to get this far
  10414.             T:suck("down")      -- if hoe already in storage get it out
  10415.             hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
  10416.             if hoeSlot == 0 then
  10417.                 if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then
  10418.                     hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
  10419.                 end
  10420.             end
  10421.         end
  10422.         return hoeSlot, ""
  10423.     end
  10424.                
  10425.     function lib.getSaplings(R, direction)
  10426.         --[[ get a single sapling from the chest ]]
  10427.         if direction == nil then
  10428.             direction = "forward"
  10429.         end
  10430.         if R.networkFarm then
  10431.             network.getItemFromNetwork("barrel", "sapling", 1)
  10432.             --lib.getItemFromNetworkBarrels(R, "sapling", 1)
  10433.         else
  10434.             while T:suck(direction, 1) do end -- remove saplings/ seeds
  10435.             T:dropItem("sapling", direction, 1) -- drop all but 1 saplings
  10436.             if not T:dropItem("seeds", direction, 0) then-- drop all seeds
  10437.                 T:dropItem("seeds", "up", 0)
  10438.             end
  10439.         end
  10440.        
  10441.         return T:getItemSlot("sapling")
  10442.     end
  10443.    
  10444.     function lib.getSeeds(R, direction, seed)
  10445.         --[[
  10446.             seed = name of growing crops seed or ""
  10447.             turtle facing crops on networked, else facing storage
  10448.             allow for other seeds from mods eg MysticalAgriculture
  10449.             get 1 stack of seeds of whatever type is being farmed
  10450.         ]]
  10451.         if seed == "" then
  10452.             return "", 0
  10453.         end
  10454.         local inventorySlot, seedCount = 0, 0
  10455.         T:saveToLog("Collecting seeds from storage")
  10456.         if R.networkFarm then
  10457.             inventorySlot, seedCount = network.getItemFromNetwork("chest", seed, 64)
  10458.         else
  10459.             while T:suck(direction, 1) do end -- remove saplings/ seeds
  10460.             T:dropItem("sapling", direction, 0) -- drop all saplings
  10461.             T:dropItem("seeds", direction, 64)  -- drop all but 64 of any seed type
  10462.             seedCount = T:getItemCount(seed)   
  10463.         end
  10464.         if seedCount > 0 then
  10465.             T:saveToLog("planting " ..seed)
  10466.         end
  10467.         return seed, seedCount  -- could be: "", 0 or "minecraft:wheat_seeds", 64
  10468.     end
  10469.        
  10470.     function lib.getVeg(R, direction, crop)
  10471.         -- assume only one type of crop per field
  10472.         -- local item, itemName, shortName, slot = "", "","", 0
  10473.         local inventorySlot, cropCount = 0, 0
  10474.        
  10475.         if R.networkFarm then
  10476.             inventorySlot, cropCount = network.getItemFromNetwork("chest", crop, 64)
  10477.         else
  10478.             if not R.mysticalAgriculture then
  10479.                 print("Collecting root crops from storage")
  10480.                 direction = direction or "forward"
  10481.                 while T:suck(direction, 1) do end           -- remove carrots / potatoes / wheat / beetroot / essence
  10482.                 --item, itemName, shortName, slot = T:getFirstItem()
  10483.                 local found = false
  10484.                 if T:getItemSlot("potato") > 0 then
  10485.                     T:dropItem("potato", direction, 64)     -- drop all but 65 potato
  10486.                     found = true
  10487.                     crop = "minecraft:potato"
  10488.                 end
  10489.                 if T:getItemSlot("carrot") > 0 then
  10490.                     T:dropItem("carrot", direction, 64)     -- drop all but 64 carrots
  10491.                     found = true
  10492.                     crop = "minecraft:carrot"
  10493.                 end
  10494.                 if not found then
  10495.                     T:dropAll(direction)                    -- drop everything back
  10496.                 end
  10497.             end
  10498.             cropCount = T:getItemCount(crop)
  10499.         end
  10500.        
  10501.         if cropCount > 0 then
  10502.             print("planting " ..crop)
  10503.         end
  10504.         return crop, cropCount -- could be: "", 0 or "minecraft:potato", 64
  10505.     end
  10506.    
  10507.     function lib.goHome(R)
  10508.         -- after a re-boot go to start
  10509.         local onTree = false
  10510.         -- is tree above or in front
  10511.         -- check if log in front
  10512.         if T:getBlockType("forward"):find("log") ~= nil then -- about to harvest tree
  10513.             lib.harvestTree(R, "forward")       -- will only harvest if fuel below half of limit
  10514.             onTree = true                   -- end on dirt
  10515.         elseif T:getBlockType("up"):find("log") ~= nil then -- harvesting tree
  10516.             lib.harvestTree(R, "up")            -- end on dirt
  10517.             onTree = true
  10518.         elseif T:getItemSlot("log") > 0 then-- tree just harvested
  10519.             onTree = true
  10520.             turtle.up()
  10521.             if T:getBlockType("up"):find("log") ~= nil then -- harvesting tree
  10522.                 lib.harvestTree(R, "up")        -- end on dirt
  10523.             else
  10524.                 while turtle.down() do end  -- end on dirt
  10525.             end
  10526.         end
  10527.        
  10528.         if onTree then
  10529.             local success, storage = false, ""
  10530.             -- tree harvested, sitting on dirt, but direction unknown
  10531.             T:down(1)               -- dig dirt, go down
  10532.             -- if storage type farm chest/barrel will give position
  10533.             for turns = 1, 4 do
  10534.                 T:turnRight(1)
  10535.                 success, storage = utils.isStorage("forward")
  10536.                 if success then
  10537.                     T:go("L2U1")
  10538.                     T:place("dirt", "down")
  10539.                     T:go("B1R1 F1D1R1")
  10540.                     R.ready = true
  10541.                     return R
  10542.                 end
  10543.             end
  10544.             -- if networked will be in air 2 blocks above barrel or stone
  10545.             T:down(1)
  10546.             T:place("dirt", "up")
  10547.             T:down(1)    --should be on corner
  10548.             for turns = 1, 4 do
  10549.                 T:forward(1)
  10550.                 success, storage = utils.isStorage("down")
  10551.                 if storage == "modem" then
  10552.                     T:go("R1F1D1")
  10553.                     R.ready = true
  10554.                     return R
  10555.                 end
  10556.                 T:go("B1R1")
  10557.             end
  10558.         else
  10559.             while turtle.down() do end -- no tree around, no logs onboard
  10560.         end
  10561.            
  10562.         return R    -- R.ready == false
  10563.     end
  10564.    
  10565.     function lib.goToLeft(R, plotCountR)
  10566.         T:go("U1R2 F"..plotCountR * 11 .."D1R2")    -- return home and continue with front
  10567.         if R.config ~= nil then
  10568.             local coord = R.config.currentPlot
  10569.             for i = 1, plotCountR do
  10570.                 coord = lib.configUpdateCoords(R, coord, "left")
  10571.             end
  10572.             R.config.currentPlot = coord
  10573.         end
  10574.     end
  10575.    
  10576.     function lib.goToFront(R, plotCountF)
  10577.         T:go("U1R1F"..plotCountF * 11 .."D1L1")
  10578.         if R.config ~= nil then
  10579.             local coord = R.config.currentPlot
  10580.             for i = 1, plotCountF do
  10581.                 coord = lib.configUpdateCoords(R, coord, "back")
  10582.             end
  10583.             R.config.currentPlot = coord
  10584.         end
  10585.     end
  10586.    
  10587.     function lib.gotoTree(R)
  10588.         -- assume facing crops
  10589.         if not R.networkFarm then
  10590.             T:turnRight(1)                          -- face storage
  10591.         end
  10592.         T:saveToLog("Extracting saplings from storage")
  10593.         lib.getSaplings(R, "forward")               -- gets one sapling only (if present)
  10594.         T:saveToLog("Moving to tree position")
  10595.         if R.networkFarm then
  10596.             T:turnRight(1)                          -- face wall next to corner barrel
  10597.         end
  10598.         T:go("U1F1R1")                              -- move on top of wall/storage. face tree direction
  10599.  
  10600.         -- check if tree or dirt ahead
  10601.         if turtle.forward() then                    -- No tree or sapling ahead. assume tree is missing or 2 blocks above
  10602.             if T:getBlockType("down") == "minecraft:dirt" then
  10603.                 turtle.back()                       -- older design, return
  10604.             else
  10605.                 T:up(1)
  10606.                 if turtle.detectUp() then           -- dirt above = new tree layout
  10607.                     if T:getBlockType("up") == "minecraft:dirt" then
  10608.                         T:go("B1U2")                -- check tree in elevated position
  10609.                     else
  10610.                         turtle.back()               -- not dirt above ? removed or lost
  10611.                     end
  10612.                 end
  10613.             end
  10614.         end
  10615.         lib.harvestTree(R, "forward")               -- fell tree or plant sapling, ends facing tree / dirt / sapling. sticks already used for fuel. excess saplings placed
  10616.         T:go("R1F1D1R1")                            -- return to base, facing crops
  10617.         if R.networkFarm then
  10618.             network.sendItemToNetworkStorage(R, "barrel", "sapling", 64) --move saplings to any attached barrel
  10619.         else
  10620.             T:turnRight(1)                          -- facing plot storage
  10621.             T:saveToLog("Dropping saplings into storage")
  10622.             T:dropItem("sapling", "forward", 0) -- drop all saplings forward into chest/barrel
  10623.             T:turnLeft(1)
  10624.         end
  10625.         -- ends in field facing crops
  10626.     end
  10627.    
  10628.     function lib.harvest(R, seed, crop)
  10629.         --[[
  10630.         cover the field in a set pattern.
  10631.         harvest crop if ripe
  10632.         till soil and plant new ones
  10633.         place seeds / harvest in chests
  10634.         return farm(s) to right / front
  10635.         crop is full name. if mixed seeds only one type returned
  10636.         ]]
  10637.         T:go("U1") --ready to farm field
  10638.         local isFarmToRight = false
  10639.         local isFarmToFront = false
  10640.         local width = 9
  10641.         local length = 10
  10642.         local toRight = true
  10643.         for l = 1, length do
  10644.             for w = 1, width do
  10645.                 lib.replant(R, seed, crop)  -- check and replant crop below
  10646.                 T:forward(1)
  10647.                 if l == 1 and w == width then -- last block of first row at front of farm
  10648.                     T:forward(1)
  10649.                     if utils.isStorage("down") then -- chest, barrel or modem
  10650.                         isFarmToRight = true
  10651.                     end
  10652.                     turtle.back()
  10653.                 end
  10654.             end
  10655.             -- end of the row: change direction
  10656.             if l < length then -- do not turn at final row
  10657.                 lib.replant(R, seed, crop)  -- check and replant crop below
  10658.                 if toRight then
  10659.                     T:go("L1F1L1")
  10660.                 else
  10661.                     T:go("R1F1R1")
  10662.                 end
  10663.                 lib.replant(R, seed, crop)
  10664.             end
  10665.             toRight = not toRight
  10666.         end
  10667.         T:go("R1F1") -- goes over chest/cobble on top wall
  10668.         if utils.isStorage("down") then
  10669.             isFarmToFront = true
  10670.         end
  10671.         T:go("R2F"..length.."D1L1") -- go straight across to seed chest 10 blocks, facing crops
  10672.         lib.storeCrops(R) -- rotates from start to deposit seeds and crops, ends facing crops
  10673.         return R, isFarmToRight, isFarmToFront
  10674.     end
  10675.    
  10676.     function lib.harvestTree(R, direction)
  10677.         --[[
  10678.             start in front of / during tree harvest
  10679.             Check if sapling present
  10680.             Harvest tree if present, replant sapling
  10681.             Dispose of apples. Use sticks as fuel
  10682.             Return to top of storage
  10683.         ]]
  10684.  
  10685.         direction = direction or "forward"
  10686.         local inFront = T:getBlockType("forward")
  10687.         print("Checking tree")
  10688.         if inFront == "" then -- no tree or sapling
  10689.             print("No sapling: planting sapling")
  10690.             T:place("sapling", "forward")
  10691.         elseif inFront:find("log") ~= nil or direction == "up" then -- tree above or in front
  10692.             -- clsTurtle.harvestTree(self, extend, craftChest, direction)
  10693.             print("Harvesting tree")
  10694.             T:harvestTree(false, false, direction) --do not investigate side branches in case chunk unloaded
  10695.             T:back(1) -- face dirt
  10696.             -- place(self, blockType, direction, leaveExisting, signText)
  10697.             T:place("sapling", "forward")
  10698.         end
  10699.         print("Disposing of apples")
  10700.         T:dropItem("apple", "up", 0) -- drop any apples
  10701.         utils.useSticksAsFuel()
  10702.        
  10703.         while turtle.down() do end  -- ends facing tree, on top of plot storage
  10704.     end
  10705.    
  10706.     function lib.manageTree(R)
  10707.         --[[ starting position facing crops ]]
  10708.         local isReady, crop, seed, status, R = lib.isCropReady(R, "forward")
  10709.         if crop == "" and not R.auto then           -- only ask player if not running via startup
  10710.             seed, crop = lib.askPlayerForCrops()    -- "" or  specific seed type,
  10711.         end
  10712.         local logSlot = T:getItemSlot("stick")
  10713.        
  10714.         if logSlot > 0 then
  10715.             turtle.select(logSlot)
  10716.             turtle.refuel()
  10717.         end
  10718.         logSlot = T:getItemSlot("log")
  10719.         local needsFuel = false
  10720.    
  10721.         if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then
  10722.             needsFuel = true
  10723.         end
  10724.         if needsFuel then
  10725.             T:saveToLog("Running Tree Manager")
  10726.             lib.gotoTree(R)                     -- check for sapling or harvest tree, retuns to facing crops
  10727.         end
  10728.        
  10729.         logSlot = T:getItemSlot("log")
  10730.         if logSlot > 0 then                     --logs onboard, need to equip crafting table
  10731.             if R.networkFarm then
  10732.                 lib.refuelWithLogs(R, logSlot)  -- use any logs for fuel
  10733.             else
  10734.                 T:go("L1F1")                    -- move to buried storage chest/barrel
  10735.                 lib.refuelWithLogs(R, logSlot)  -- use any logs for fuel
  10736.                 T:go("R2F1")                    -- facing seed chest/barrel
  10737.             end
  10738.         else
  10739.             if not R.networkFarm then
  10740.                 T:turnRight(1)
  10741.             end
  10742.         end
  10743.         -- get seeds or veg based on what is growing
  10744.         if seed ~= "" then
  10745.             local seedType, seedCount = lib.getSeeds(R, "forward", seed)    -- table: get 95 of beetroot / wheat / mysticalagriculture seeds
  10746.             if seedCount == 0 then
  10747.                 T:saveToLog("No seeds available.")
  10748.             end
  10749.         else    -- seed  = ""
  10750.             local veg, vegCount = "", 0
  10751.             if R.networkFarm then
  10752.                 veg, vegCount = lib.getVeg(R, "forward", crop)  -- gets any carrots / potatoes
  10753.             else
  10754.                 T:turnRight(1)                  -- face crop chests
  10755.                 veg, vegCount = lib.getVeg(R, "forward", crop)  -- gets any carrots / potatoes
  10756.                 T:turnRight(2)                  -- face crops
  10757.             end
  10758.             if veg ~= "" then
  10759.                 crop = veg
  10760.             end
  10761.         end
  10762.        
  10763.         return seed, crop   -- name of seed / "",  crop / ""
  10764.     end
  10765.    
  10766.     function lib.isCropReady(R, direction)
  10767.         local isReady = false
  10768.         local status = ""
  10769.         local success = false
  10770.         local crop, seed = "", ""
  10771.         local data = {}
  10772.  
  10773.         direction = direction or "forward"
  10774.  
  10775.         if direction == "down" then
  10776.             success, data = turtle.inspectDown()
  10777.         else
  10778.             success, data = turtle.inspect()
  10779.         end
  10780.         --T:saveToLog("lib.isCropReady(R,".. direction..")")
  10781.         if success then         -- inspect() success
  10782.             crop = data.name    -- name of growing plant
  10783.             if crop:find("flower") ~= nil then
  10784.                 T:saveToLog("Flower "..crop.." found")
  10785.                 return true, crop, "open"   -- eg torchflower
  10786.             else
  10787.                 if data.name:find("beetroot") ~= nil then
  10788.                     status = data.state.age.." / 3"
  10789.                     if data.state.age == 3 then
  10790.                         isReady = true
  10791.                     end
  10792.                 else            -- all other crops inc Mystical Agriculture
  10793.                     status = data.state.age.." / 7"
  10794.                     if data.state.age == 7 then
  10795.                         isReady = true
  10796.                     end
  10797.                 end
  10798.             end
  10799.             seed, crop = lib.getCropSeed(crop)
  10800.         end
  10801.         --T:saveToLog("return isReady = "..tostring(isReady)..", crop = "..crop..", seed = "..seed..", status = "..status)
  10802.         -- crop: "", "minecraft:carrots", "minecraft:beetroot", "minecraft:potatoes", "minecraft:wheat", "mysticalagriculture:*_crop"
  10803.         return isReady, crop, seed, status, R   -- eg true, "minecraft:carrots", "7 / 7" or false, "mysticalagriculture:inferium_crop", "1 / 7"
  10804.     end
  10805.    
  10806.     function lib.locateFarm(R)
  10807.         T:saveToLog("? over water = false")
  10808.         for i = 1, 4 do
  10809.             if turtle.detect() then
  10810.                 detected = i
  10811.             end
  10812.             T:turnRight(1)
  10813.         end
  10814.         T:saveToLog("Neighbouring blocks detected at: "..detected)
  10815.         -- check if on corner
  10816.         if detected > 0 then
  10817.             --assume tree / sapling on corner on older farm type
  10818.             T:saveToLog("Assuming next to tree / sapling. Moving..")
  10819.             T:go("R"..detected .."F1D1R1")
  10820.         else    -- no surrounding blocks
  10821.             for i = 1, 4 do
  10822.                 T:forward(1)
  10823.                 success, storage = utils.isStorage("down")
  10824.                 T:saveToLog("i = "..i..",success = "..tostring(success)..". storage = "..storage)
  10825.                 if success then
  10826.                     discovered = discovered .. storage
  10827.                     if storage == "modem" then
  10828.                         R.networkFarm = true
  10829.                     end
  10830.                 else
  10831.                     if storage == "" then
  10832.                         discovered = discovered .. "_"
  10833.                     else
  10834.                         discovered = discovered .. "wall"
  10835.                     end
  10836.                 end
  10837.                 utils.goBack(1)
  10838.                 T:turnRight(1)
  10839.             end
  10840.             T:saveToLog("Neighbouring blocks found:"..discovered)
  10841.         end
  10842.         -- check discovered for patterns eg {_wall_barrel}
  10843.         -- |W|*|B| * = turtle on wall
  10844.         -- | | |M|
  10845.         if R.networkFarm then
  10846.             -- E = wall_barrel_, N = _barrel_wall, W = wall_barrel_, S = _wall_barrel
  10847.             if discovered == "_wall_barrel" then
  10848.                 T:go("F1D1R1")
  10849.             elseif discovered == "barrel_wall_" then
  10850.                 T:go("R1F1D1R1")
  10851.             elseif discovered == "_barrel_wall" then
  10852.                 T:go("R2F1D1R1")
  10853.             elseif discovered == "wall_barrel_" then
  10854.                 T:go("L1F1D1R1")
  10855.             end
  10856.         else    -- normal storage farm
  10857.             if discovered == "_chest_chest" then
  10858.                 T:go("F1D1R1")
  10859.             elseif discovered == "chest__chest" then
  10860.                 T:go("R1F1D1R1")
  10861.             elseif discovered == "_chest_chest" then
  10862.                 T:go("R2F1D1R1")
  10863.             elseif discovered == "chest_chest_" then
  10864.                 T:go("L1F1D1R1")
  10865.             end
  10866.         end
  10867.         blockType = T:getBlockType("down")
  10868.         if blockType:find("water") ~= nil then
  10869.             for i = 1, 4 do
  10870.                 success, storage = utils.isStorage("forward")   -- true/false, chest, barrel, modem / ""
  10871.                 if success and storage == "modem" then
  10872.                     R.networkFarm = true
  10873.                 end
  10874.                 T:turnRight(1)
  10875.             end
  10876.             R.ready = true
  10877.         end
  10878.     end
  10879.    
  10880.     function lib.plantCrop(R, seed, crop, direction)
  10881.         --turtle.digDown("left") -- harvest existing
  10882.         --turtle.digDown("right") -- till soil
  10883.         if crop:find("potato") ~= nil then
  10884.             T:dropItem("poison", "up", 0)
  10885.         end
  10886.         --T:saveToLog("lib.plantCrop(R, seed = "..seed..", crop = "..crop)
  10887.         local success = false
  10888.         -- place(blockType, direction, leaveExisting, signText, doNotAttack)
  10889.         if seed == "" then  -- must be a crop
  10890.             success = T:place(crop, direction, true, "", true)
  10891.             --success = T:place(crop, direction, false, "", true)
  10892.             --T:saveToLog("Seed = "..seed..". Placing "..crop..": success = "..tostring(success))
  10893.         else
  10894.             success = T:place(seed, direction, true, "", true)  -- eg "mysticalagriculture:air_seeds"
  10895.             --success = T:place(seed, direction, false, "", true)   -- eg "mysticalagriculture:air_seeds"
  10896.             --T:saveToLog("Placing "..seed..": success = "..tostring(success))
  10897.         end
  10898.         if not success then
  10899.             success = T:place("seed", direction, true, "", true)            -- failsafe
  10900.             --success = T:place("seed", direction, false, "", true)         -- failsafe
  10901.             --T:saveToLog("Placing generic 'seeds' : success = "..tostring(success))
  10902.         end
  10903.         return success
  10904.     end
  10905.        
  10906.     function lib.replant(R, seed, crop)
  10907.         -- check crop below. If ripe, dig and replant seed
  10908.         local isReady, cropType, seedType, status
  10909.         isReady, cropType, seedType, status, R = lib.isCropReady(R, "down") -- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
  10910.         if cropType == "" then                  -- no crop below (above water, storage or dirt)
  10911.             turtle.digDown("right")             -- use hoe
  10912.             lib.plantCrop(R, seed, crop, "down")-- plant crop
  10913.         elseif isReady then                     -- crop below is ready
  10914.             turtle.digDown("left")              -- use pickaxe
  10915.             lib.plantCrop(R, seedType, cropType, "down")    -- plant crop
  10916.         end
  10917.  
  10918.         return R
  10919.     end
  10920.    
  10921.     function lib.refuelWithLogs(R, logSlot)
  10922.         -- saplings already dropped, apples dumped, sticks used as fuel
  10923.         -- assume positioned in front of crops if networked, or over buried storage
  10924.         -- earlier versions used crafting table buried in the ground
  10925.         -- newer versions have a barrel or chest embedded in the ground, containing the crafting table
  10926.         -- networked version uses remote storage, turtle faces crops and has modem at back
  10927.         local slot, count = 0, 0
  10928.         T:saveToLog("Sorting Inventory")    -- make sure all items collected together
  10929.         T:sortInventory(true)
  10930.         T:saveToLog("Logs present: collecting crafting table")
  10931.         if R.networkFarm then
  10932.             slot, count = network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
  10933.             --slot = lib.getItemFromNetworkBarrels(R, "minecraft:crafting_table", 1)
  10934.         else
  10935.             while T:suck("down") do end                 -- empty out barrel/chest to find crafting table
  10936.         end
  10937.         if T:getItemSlot("crafting") == 0 then
  10938.             T:checkInventoryForItem({"crafting"}, {1}, true, "Crafting table required for logs->planks")
  10939.         end
  10940.         if T:equip("right", "minecraft:crafting_table") then -- swap equipment on right side
  10941.             if R.networkFarm then
  10942.                 network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1)
  10943.             end
  10944.             for i = 1, 16 do                        -- drop anything except logs down into barrel/chest/pit
  10945.                 if T:getSlotContains(i):find("log") == nil then
  10946.                     T:drop("down", i)   -- into water if networked, buried chest otherwise
  10947.                 else
  10948.                     logSlot = i
  10949.                 end
  10950.             end
  10951.             turtle.select(logSlot)
  10952.             turtle.transferTo(1)
  10953.             turtle.craft()                          -- craft logs to planks
  10954.             logSlot = T:getItemSlot("planks")
  10955.             while logSlot > 0 and turtle.getFuelLevel() < turtle.getFuelLimit() do
  10956.                 turtle.select(logSlot)
  10957.                 turtle.refuel()                     -- refuel using planks
  10958.                 logSlot = T:getItemSlot("planks")              
  10959.             end
  10960.             while T:suck("down") do end         -- recover items from water / storage below
  10961.             --T:unequip("right")
  10962.             if R.networkFarm then
  10963.                 slot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1)
  10964.             end
  10965.             if not T:equip("right", "minecraft:diamond_hoe") then       -- re-equip hoe/remove crafting table
  10966.                 T:equip("right", "minecraft:diamond_pickaxe")          
  10967.             end
  10968.             if R.networkFarm then
  10969.                 network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1)
  10970.             else
  10971.                 T:dropItem("minecraft:crafting_table", "down")
  10972.             end
  10973.         else
  10974.             print("Unable to equip crafting table.\n\nCheck turtle inventory and chest or barrel below")
  10975.             error()
  10976.         end
  10977.     end
  10978.                
  10979.     function lib.storeCrops(R)
  10980.         -- place crops and seeds into chests. starts facing crops
  10981.         T:dropItem("apple", "up", 0) -- drop all apples
  10982.         T:dropItem("poison", "up", 0) -- drop all poison potatoes
  10983.         if R.networkFarm then
  10984.             network.emptyInventory(R, {"sapling", "diamond_hoe", "crafting"}, {"all"}, true)
  10985.         else
  10986.             T:turnRight(1)  -- face seed storage
  10987.             lib.storeSeeds(R, "forward")
  10988.             T:turnRight(1)
  10989.             if utils.isStorage(direction) then
  10990.                 T:dropAll(direction) -- drops everything including essences
  10991.             end
  10992.             T:turnRight(2) -- facing crops again
  10993.         end
  10994.     end
  10995.        
  10996.     function lib.storeSeeds(R, direction)
  10997.         direction = direction or "forward"
  10998.         if utils.isStorage(direction) then -- chest exists
  10999.             if not R.networkFarm then
  11000.                 if T:getItemSlot("minecraft:wheat_seeds") > 0 then
  11001.                     if not T:dropItem("minecraft:wheat_seeds", direction, 0) then
  11002.                         T:dropItem("minecraft:wheat_seeds", "up", 0)
  11003.                     end -- drop all wheat seeds
  11004.                 elseif T:getItemSlot("minecraft:beetroot_seeds") > 0 then
  11005.                     if not T:dropItem("minecraft:beetroot_seeds", direction, 0) then-- drop all beetroot seeds
  11006.                         T:dropItem("minecraft:beetroot_seeds", "up", 0)
  11007.                     end
  11008.                 elseif T:getItemSlot("seeds") > 0 then
  11009.                     if not T:dropItem("seeds", direction, 0) then   -- drop all other seeds as chest is full
  11010.                         T:dropItem("seeds", "up", 0)
  11011.                         -- or could print a message and wait for player to empty storage
  11012.                     end
  11013.                 end
  11014.             end
  11015.         end
  11016.     end
  11017.    
  11018.     function lib.watchFarm(R)
  11019.         --[[
  11020.         check status of crops in front of turtle.
  11021.         call lib.harvest when ripe
  11022.         return farm(s) found in front or to the right
  11023.         ]]
  11024.         local isReady, crop, seed, status   -- bool, string, string, integer
  11025.         isReady, crop, seed, status, R = lib.isCropReady(R, "forward")      -- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
  11026.         -- check state of crop in front. Harvest if ripe       
  11027.         repeat
  11028.             if not isReady then
  11029.                 if crop == "" then
  11030.                     print("No crops found in front")
  11031.                     print("Plant seeds, carrots, potatoes")
  11032.                     error()
  11033.                 else
  11034.                     print("Waiting for "..crop.." status: "..status)
  11035.                     if crop:find("mysticalagriculture") ~= nil then
  11036.                         R.mysticalAgriculture = true
  11037.                     end
  11038.                 end
  11039.                 sleep(60)
  11040.                 isReady, crop, seed, status, R = lib.isCropReady(R, "forward")          -- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
  11041.             end
  11042.         until isReady
  11043.         T:saveToLog("Local crops ripe", true)
  11044.         seed, crop = lib.manageTree(R) -- "", "" or name of seed, crop
  11045.         return seed, crop
  11046.     end
  11047.    
  11048.     --[[
  11049.         ENTRY POINT**********************************************
  11050.         called from args on start, or from user choice
  11051.         farm already built, needs planting and/or harvesting
  11052.         needs both pickaxe and hoe
  11053.         may start in any position if chunk unloaded while running
  11054.     ]]
  11055.    
  11056.    
  11057.     --T:setUseLog(true, "farmLog.txt", true)    -- T:setUseLog(use, filename, delete)
  11058.     --dbug = true                               -- set dbug flag
  11059.     --if not R.auto then                        -- not running from startup.lua
  11060.         --utils.waitForInput("Logging and debugging enabled")   --utils.waitForInput(message)
  11061.     --end
  11062.    
  11063.     R = utils.checkFarmPosition(R)  -- should be facing crops, placed above water source. R.ready, R.networkFarm is true/false
  11064.     if R.networkFarm then
  11065.         local message = network.loadStorageLists()  -- initialises or creates lists of where an item can be found: GLOBAL LISTS!
  11066.         if message ~= nil then return {message} end
  11067.     end
  11068.     if not R.ready then     -- not in correct starting place
  11069.         R = lib.goHome(R)
  11070.         if not R.ready then -- try to find home
  11071.             return
  11072.             {
  11073.                 "Unable to determine my position.\n",
  11074.                 "Place me in the lower left corner",
  11075.                 "over water, facing the crops with",
  11076.                 "barrel or chest to my right and behind",
  11077.                 "(or modem behind if networked farm)"
  11078.             }
  11079.         end
  11080.     end
  11081.     if not T:isEmpty() then     -- items in turtle inventory
  11082.         local logSlot = T:getItemSlot("log")
  11083.         if logSlot > 0 then
  11084.             if R.networkFarm then
  11085.                 lib.refuelWithLogs(R, logSlot)  -- use any logs for fuel
  11086.             else
  11087.                 T:go("L1F1")                    -- move to buried storage chest/barrel
  11088.                 lib.refuelWithLogs(R, logSlot)  -- use any logs for fuel
  11089.                 T:go("R2F1")                    -- facing seed chest/barrel
  11090.             end
  11091.         end
  11092.         if not T:isEmpty() then                 -- still items in turtle inventory
  11093.             lib.storeCrops(R)
  11094.         end
  11095.     end
  11096.     -- in correct position. Check equipment first, harvest tree, re-equip then harvest crops
  11097.     local hoeSlot = lib.checkEquipment(R, "minecraft:diamond_hoe")  -- returns slot  or 0
  11098.    
  11099.     if hoeSlot == 0 then        -- hoe not in inventory
  11100.         local message
  11101.         hoeSlot, message = lib.getHoe()
  11102.         if message ~= "" then
  11103.             return {message}
  11104.         end
  11105.     end
  11106.     -- hoe present or user cancelled request for hoe. Turtle is ready to exchange items
  11107.     if hoeSlot > 0 then
  11108.         T:equip("right", "minecraft:diamond_hoe", 0) -- equip hoe and put crafting chest into barrel
  11109.         if R.networkFarm then   -- drop crafting table into storage
  11110.             network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1)
  11111.         else    -- put crafting table into barrel in floor
  11112.             T:dropItem("crafting", "down")
  11113.             T:go("B1R1")
  11114.         end
  11115.     else    -- hoe not present: return to start and exit
  11116.         if not R.networkFarm then
  11117.             T:go("B1R1")
  11118.         end
  11119.         return {"Unable to equip hoe."}
  11120.     end
  11121.     -- check if crops already planted
  11122.    
  11123.     local isFarmToRight, isFarmToFront = false, false
  11124.     local isReady, crop, seed, status
  11125.     isReady, crop, seed, status, R = lib.isCropReady(R, "forward")
  11126.     local watch = true  -- assume watching farm already planted
  11127.     local init = false
  11128.     if crop == "" then  -- nothing has been planted
  11129.         seed, crop = lib.askPlayerForCrops()
  11130.         if crop ~= "" or seed  ~= "" then   -- something has been chosen
  11131.             T:saveToLog("Initial planting of "..crop, true)
  11132.             R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop)    -- harvest plot a1 plots to right / front recorded 
  11133.             init = true
  11134.         else
  11135.             watch = false   -- not watching, continue with planting
  11136.         end
  11137.     end
  11138.     while true do -- start infinite loop of watching crops, farming all modules
  11139.         if watch and not init then -- init true when farm first planted
  11140.             seed, crop = lib.watchFarm(R) -- waits if required, returns seed / crop
  11141.             init = false
  11142.         end
  11143.         T:saveToLog("Beginning "..crop.. " management", true)
  11144.         R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop)    -- harvest plot a1 plots to right / front recorded
  11145.         lib.farmAll(R, isFarmToRight, isFarmToFront)
  11146.         if not R.auto then -- not started from startup.lua
  11147.             if R.networkFarm then
  11148.                 T:unequip("right")  -- unequip hoe
  11149.                 network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
  11150.                 network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1)
  11151.                 T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table
  11152.             else
  11153.                 T:go("L1F1")
  11154.                 while T:suck("down") do end                     -- recover items from storagebelow
  11155.                 T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table
  11156.                 T:dropItem("minecraft:diamond_hoe", "down")                 -- drop hoe into storage
  11157.                 T:dropItem("crafting", "down")                  -- in case spare one picked by mistake
  11158.                 utils.goBack(1)
  11159.                 T:turnRight(1)
  11160.             end
  11161.             return {"Crop management of all modules completed"}
  11162.         end
  11163.     end
  11164.     return {}
  11165. end
  11166.  
  11167. local function manageFarmSetup(R) -- 33
  11168.     local lib = {}
  11169.    
  11170.     function lib.disableAutostart()
  11171.         if fs.exists("start.txt") then
  11172.             fs.delete("start.txt")
  11173.         end
  11174.         if fs.exists("startup.lua") then
  11175.             fs.delete("startup.lua")
  11176.         end
  11177.     end
  11178.    
  11179.     function lib.enableAutostart()
  11180.         if not fs.exists("startup.lua") then
  11181.             local h = fs.open("startup.lua", "w")
  11182.             h.writeLine('function main()')
  11183.             h.writeLine('   if fs.exists("start.txt") then')
  11184.             h.writeLine('       local handle = fs.open("start.txt", "r")')
  11185.             h.writeLine('       local cmd = handle.readLine()')
  11186.             h.writeLine('       handle.close()')
  11187.             h.writeLine('       shell.run("tk.lua "..cmd)')
  11188.             h.writeLine('   end')
  11189.             h.writeLine('end')
  11190.             h.writeLine('main()')
  11191.             h.close()
  11192.         end
  11193.         local h = fs.open("start.txt", "w")
  11194.         if R.data == "farm" then
  11195.             h.writeLine('farm')
  11196.         end
  11197.         h.close()
  11198.         print("Startup files written")
  11199.     end
  11200.    
  11201.     T:clear()
  11202.     --local pp = utils.getPrettyPrint()
  11203.     local choices = {"Plant or harvest this farm complex"}  -- 1.
  11204.     local isManaged = fs.exists("start.txt")
  11205.  
  11206.     if isManaged then
  11207.         table.insert(choices, "Disable automatic farm management") -- 2.
  11208.     else
  11209.         table.insert(choices, "Enable automatic farm management") -- 2.
  11210.     end
  11211.     pp.itemColours = {colors.lime, colors.lightGray}
  11212.     if not R.networkFarm then
  11213.         table.insert(choices, "Convert to Network Storage")     -- 3.
  11214.         table.insert(pp.itemColours, colors.magenta)
  11215.     end
  11216.     if R.mysticalAgriculture then
  11217.         --table.insert(choices, "Convert to Mystical Agriculture")
  11218.         table.insert(choices, "Upgrade Mystical Agriculture soil")  --3/4
  11219.         table.insert(pp.itemColours, colors.green)
  11220.     end
  11221.    
  11222.     local userChoice, modifier = menu.menu("Choose your option", choices, pp) -- 1 to 2
  11223.     if modifier == "q" then -- quit chosen
  11224.         return {"Player has quit"}
  11225.     end
  11226.     R.subChoice = userChoice
  11227.     if R.subChoice == 1 then -- harvest now
  11228.         R.silent = false
  11229.         R.data = "farm"
  11230.         R.auto = false
  11231.         return manageFarm(R)
  11232.     elseif R.subChoice == 2 then -- enable/disable auto farm
  11233.         local line = menu.clear()
  11234.         if isManaged then
  11235.             local message = ( "This turtle has been configured to"..
  11236.                               "start automatically and run the farm"..
  11237.                               "management program.\n")
  11238.             line = menu.colourText(line, message, true, true)
  11239.             if menu.getBoolean("Do you want to disable this? (y/n)", line, colors.yellow, colors.black) then
  11240.                 lib.disableAutostart()
  11241.             end
  11242.             return {"Autostart disabled. Reboot to activate"}
  11243.         else -- not managed
  11244.             local message = ( "~yellow~This turtle can be configured to be\n"..
  11245.                               "a dedicated farm manager.\n\n"..
  11246.                               "~lightGray~It will then start automatically and\n"..
  11247.                               "monitor the farm complex:\n\n"..
  11248.                               "~green~harvesting~yellow~ and ~lime~replanting ~yellow~continuously.\n")
  11249.             line = menu.colourText(line, message, true, true)
  11250.             if menu.getBoolean("Do you want to enable this? (y/n)", line + 2, colors.orange, colors.black) then
  11251.                 lib.enableAutostart()
  11252.             else
  11253.                 return {"Player cancelled operation"}
  11254.             end
  11255.             return {"Autostart enabled. Reboot to activate"}
  11256.         end
  11257.     --elseif R.subChoice == 3 and #choices == 4 then -- convert normal farm to network storage
  11258.     elseif R.subChoice == 3 then -- convert normal farm to network storage
  11259.         local isMain = false
  11260.         local line = menu.clear()
  11261.         local message = ("~yellow~You have chosen to convert this farm "..
  11262.                          "to ~magenta~network storage ~yellow~with modems."..
  11263.                          "All ~brown~chests and barrels ~red~will be removed.\n")
  11264.         line = menu.colourText(line, message, true, true)
  11265.         if menu.getBoolean("Is this the main or only plot? (y/n)", line + 3, colors.orange, colors.black) then
  11266.             isMain = true
  11267.         end
  11268.         T:checkInventoryForItem({"stone"}, {16})
  11269.         T:checkInventoryForItem({"dirt"}, {2})
  11270.         T:checkInventoryForItem({"sapling"}, {1})
  11271.         T:checkInventoryForItem({"barrel"}, {1})
  11272.         T:checkInventoryForItem({"ladder"}, {5})
  11273.         if isMain then
  11274.             T:checkInventoryForItem({"chest"}, {8})
  11275.             T:checkInventoryForItem({"wired_modem_full"}, {3})
  11276.             T:checkInventoryForItem({"computercraft:cable"}, {70})
  11277.             return createFarm(R, "convertWithStorage")
  11278.         else
  11279.             T:checkInventoryForItem({"wired_modem_full"}, {2})
  11280.             T:checkInventoryForItem({"computercraft:cable"}, {57})
  11281.             return createFarm(R, "convert")
  11282.         end
  11283.     --elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present)
  11284.     --elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present)
  11285.         --return upgradeFarmland(R)
  11286.     elseif R.subChoice == 4 then -- upgrade farmland with essence
  11287.         return upgradeFarmland(R)
  11288.     end
  11289.    
  11290.     return {}
  11291. end
  11292.  
  11293. local function measure(R) -- 101
  11294.     -- measure height/ depth / length
  11295.     local lib = {}
  11296.    
  11297.     function lib.checkBlocks(R, blocks)
  11298.         local dimension = "height"
  11299.         local message = ""
  11300.         local measure = ""
  11301.         local doContinue = true
  11302.         if R.choice == 102 then
  11303.             dimension = "depth"
  11304.         elseif R.choice == 103 then
  11305.             dimension = "length"
  11306.         end
  11307.         blocks = blocks + 1
  11308.         if blocks > R.size then
  11309.             message = "Max "..dimension.." of "..R.size.." stopped measurement"
  11310.             measure = ""
  11311.             doContinue = false
  11312.         else
  11313.             measure = dimension.." measured: "..blocks.." blocks"
  11314.         end
  11315.         return doContinue, blocks, measure, message
  11316.     end
  11317.    
  11318.     local blocks = 1
  11319.     local method = ""
  11320.     local measure = ""
  11321.     local message = ""
  11322.     local doContinue = true
  11323.     if R.choice == 101 then             -- height
  11324.         if R.subChoice == 1 then        -- obstruction above
  11325.             method = "Method: Until obstruction above"
  11326.             while turtle.up() and doContinue do
  11327.                 doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11328.             end
  11329.         elseif R.subChoice == 2 then    -- end of blocks in front of turtle eg cliff, wall
  11330.             method = "Method: Until no block detected in front"
  11331.             while turtle.detect() and doContinue do
  11332.                 if turtle.up() then
  11333.                     doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11334.                 else
  11335.                     message = "Obstruction above stopped measurement"
  11336.                     measure = ""
  11337.                     doContinue = false
  11338.                 end
  11339.             end
  11340.         elseif R.subChoice == 3 then    -- search for specific block min 3 characters
  11341.             method = "Method:Until search: '"..R.data.."' met"
  11342.             while turtle.detect() and doContinue do
  11343.                 if turtle.up() then
  11344.                     doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11345.                     if doContinue then
  11346.                         local blockType = T:getBlockType("forward")
  11347.                         if blockType:find(R.data) ~= nil then
  11348.                             measure = "Height measured: "..blocks.." blocks"
  11349.                             message = "Found "..blockType
  11350.                             doContinue = false
  11351.                         end
  11352.                     end
  11353.                 else
  11354.                     message = "Obstruction above stopped measurement"
  11355.                     measure = ""
  11356.                     doContinue = false
  11357.                 end
  11358.             end
  11359.         elseif R.subChoice == 4 then    -- When block above changes eg dragon tower height
  11360.             local blockType = T:getBlockType("up")
  11361.             local compare = blockType
  11362.             method = "Method: Until "..blockType.." changes"
  11363.             while blockType == compare and doContinue do
  11364.                 T:up(1)
  11365.                 doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11366.                 if doContinue then
  11367.                     blockType = T:getBlockType("up")
  11368.                 end
  11369.             end
  11370.             measure = "Height measured: "..blocks.." blocks"
  11371.             message = "Found "..blockType
  11372.         end
  11373.        
  11374.         for i = 1, blocks do
  11375.             turtle.down()
  11376.         end
  11377.     elseif R.choice == 102 then -- depth
  11378.         T:go("F1R2D1") -- go off the edge and face cliff/pit wall
  11379.         blocks = blocks + 1
  11380.         if R.subChoice == 1 then        -- obstruction water / lava below
  11381.             local move = true
  11382.             while move do
  11383.                 local blockType = T:getBlockType("down")
  11384.                 if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
  11385.                     message1 = blockType.." found at "..blocks
  11386.                     move = false
  11387.                 else
  11388.                     move = turtle.down()
  11389.                     if move then
  11390.                         blocks = blocks + 1
  11391.                     else
  11392.                         measure = "Depth measured: "..blocks.." blocks"
  11393.                     end
  11394.                 end
  11395.             end
  11396.             method = "Method: Until obstruction below"
  11397.         elseif R.subChoice == 2 then    -- end of wall in front`
  11398.             while turtle.detect() do
  11399.                 if turtle.down() then
  11400.                     blocks = blocks + 1
  11401.                     measure = "Depth measured: "..blocks.." blocks"
  11402.                 else
  11403.                     message1 = "Obstruction below stopped measurement"
  11404.                     break
  11405.                 end
  11406.             end
  11407.             method = "Method: Until no block detected ahead"
  11408.         elseif R.subChoice == 3 then    -- specific block detected ahead
  11409.             method = "Method:Until search: '"..R.data.."' met"
  11410.             while turtle.detect() do
  11411.                 if turtle.down() then
  11412.                     blocks = blocks + 1
  11413.                     local blockType = T:getBlockType("forward")
  11414.                     if blockType:find(R.data) ~= nil then
  11415.                         measure = "Depth measured: "..blocks.." blocks"
  11416.                         message = "Found "..blockType
  11417.                         break
  11418.                     end
  11419.                 else
  11420.                     message = "Obstruction below stopped measurement"
  11421.                     break
  11422.                 end
  11423.             end
  11424.         end
  11425.         for i = 1, blocks do
  11426.             turtle.up()
  11427.         end
  11428.         T:go("F1R2")
  11429.     elseif R.choice == 103 then -- length
  11430.         if R.subChoice == 1 then        -- obstruction ahead
  11431.             method = "Method: Until obstruction ahead"
  11432.             while turtle.forward() and doContinue  do
  11433.                 doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11434.             end
  11435.         elseif R.subChoice == 2 then    -- end of ceiling above
  11436.             method = "Method: Until no block detected above"
  11437.             while turtle.detectUp() and doContinue do
  11438.                 if turtle.forward() then
  11439.                     doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11440.                 else
  11441.                     message = "Obstruction ahead stopped measurement"
  11442.                     measure = ""
  11443.                     doContinue = false
  11444.                 end
  11445.             end
  11446.         elseif R.subChoice == 3 then    -- end of floor below
  11447.             method = "Method: Until no block detected below"
  11448.             while turtle.detectDown() and doContinue do
  11449.                 if turtle.forward() then
  11450.                     doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11451.                 else
  11452.                     message = "Obstruction ahead stopped measurement"
  11453.                     measure = ""
  11454.                     doContinue = false
  11455.                 end
  11456.             end
  11457.         elseif R.subChoice == 4 then    -- search for specific block up min 3 characters
  11458.             method = "Method:Until search: '"..R.data.."' above met"
  11459.             while turtle.detectUp() and doContinue do
  11460.                 if turtle.forward() then
  11461.                     doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11462.                     if doContinue then
  11463.                         local blockType = T:getBlockType("up")
  11464.                         if blockType:find(R.data) ~= nil then
  11465.                             message = "Found "..blockType
  11466.                             measure = "Length measured: "..blocks.." blocks"
  11467.                             doContinue = false
  11468.                         end
  11469.                     end
  11470.                 else
  11471.                     message = "Obstruction ahead stopped measurement"
  11472.                     measure = ""
  11473.                     doContinue = false
  11474.                 end
  11475.             end
  11476.         elseif R.subChoice == 5 then    -- search for specific block down min 3 characters
  11477.             method = "Method:Until search: '"..R.data.."' below met"
  11478.             --while turtle.detectDown() and doContinue do
  11479.             while doContinue do
  11480.                 if turtle.forward() then
  11481.                     doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
  11482.                     if doContinue then
  11483.                         local blockType = T:getBlockType("down")
  11484.                         if blockType:find(R.data) ~= nil then
  11485.                             message = "Found "..blockType
  11486.                             measure = "Length measured: "..blocks.." blocks"
  11487.                             doContinue = false
  11488.                         end
  11489.                     end
  11490.                 else
  11491.                     message = "Obstruction ahead stopped measurement"
  11492.                     measure = ""
  11493.                     doContinue = false
  11494.                 end
  11495.             end
  11496.         end
  11497.         T:turnRight(2)  -- head home
  11498.         for i = 1, blocks do
  11499.             turtle.forward()
  11500.         end
  11501.         T:turnRight(2)
  11502.     elseif R.choice == 104 then -- depth of stretch of water
  11503.         --R.length = 0 to auto calculate
  11504.         R.width = 1
  11505.         R.silent = true
  11506.         R.useBlockType = ""
  11507.         R.data = "clearWaterPlants"
  11508.         local data = clearWaterPlants(R)
  11509.         R.height = data[1]
  11510.         local length = data[2]
  11511.         T:go ("R2F"..length - 1 .."R2U1")
  11512.         return {"Greatest depth measured: ".. R.height,"Width of water: "..R.length}
  11513.     end
  11514.     if message == "" then
  11515.         return{method, measure}
  11516.     else
  11517.         return{method, measure, message}
  11518.     end
  11519. end
  11520.  
  11521. local function mineBedrockArea(R) -- 19
  11522.     --[[
  11523.     Assume on level 5 or -59
  11524.     for 1, width do
  11525.         for 1, length do
  11526.             go down until bedrock, digging/replacing all directions
  11527.             return to 5 / -59
  11528.             move forward 1 blocks
  11529.         end
  11530.         turn right/ forward 2 turn right
  11531.     end
  11532.     ]] 
  11533.     local lib = {}
  11534.    
  11535.     function lib.clearColumn(R)
  11536.         local level = 0
  11537.         --T:go("L1x1R2x1L1")
  11538.         local success = T:down(1)
  11539.         while success do
  11540.             level = level + 1
  11541.             if R.data == "leaveExposed" then
  11542.                 T:go("R1x1R1x1R1x1R1x1", false, 0, true)
  11543.             else
  11544.                 T:go("R1C1R1C1R1C1R1C1", false, 0, true)
  11545.             end
  11546.             success = T:down(1)
  11547.         end
  11548.         if R.data == "leaveExposed" then
  11549.             T:go("U"..level)
  11550.         else
  11551.             T:go("U"..level.."C2")
  11552.         end
  11553.     end
  11554.    
  11555.     local goRight = true
  11556.     for i = 1, R.width do
  11557.         for j = 1, R.length do
  11558.             lib.clearColumn(R)
  11559.             T:forward(1)
  11560.         end
  11561.         if goRight then
  11562.             T:go("R1F1R1")
  11563.         else
  11564.             T:go("L1F1L1")
  11565.         end
  11566.         goRight = not goRight
  11567.     end
  11568.     return {}
  11569. end
  11570.  
  11571. local function oceanMonumentColumns(R)
  11572.     -- utility to find corners and build columns to surface
  11573.     local lib = {}
  11574.    
  11575.     function lib.buildColumn()
  11576.         local depth = 0
  11577.         while T:isWater("forward") do
  11578.             T:go("U1C2")
  11579.             depth = depth + 1
  11580.         end
  11581.         return depth
  11582.     end
  11583.    
  11584.     function lib.buildTower()
  11585.         T:go("F1C2 F1C2 F1C2")
  11586.         T:go("L1F1 L1C2 F1C2 F1C2 F1C2")
  11587.         T:go("R1F1 R1C2 F1C2 F1C2 F1C2")
  11588.         T:go("L1F1 L1C2 F1C2 F1C2 F1C2")
  11589.        
  11590.         T:go("R2")
  11591.         for i = 1, 4 do
  11592.             T:go("U1C2")
  11593.             for j = 1, 4 do
  11594.                 T:go("F1C2 F1C2 F1C2 R1")
  11595.             end
  11596.         end
  11597.     end
  11598.    
  11599.     R.silent = true
  11600.     local blockType = T:getBlockType("down")
  11601.     while blockType:find("water") == nil do
  11602.         T:down(1) -- if on a platform will break through
  11603.         blockType = T:getBlockType("down")
  11604.     end
  11605.     --R.useBlockType = "prismarine", R.data = "oceanMonumentColumns" from getTask
  11606.     --local tempData = R.data
  11607.     --R.data = "clearWaterPlants"
  11608.     local result = clearWaterPlants(R)[1]
  11609.     if result ~= "" then
  11610.         return {result}
  11611.     else
  11612.         --on corner of monument, facing out to ocean
  11613.         local depth = lib.buildColumn()
  11614.         -- now above surface, block below at surface level
  11615.         for i = 1, 4 do
  11616.             T:turnRight(1)
  11617.             R.length = 57
  11618.             utils.createPath(R) -- roughly at next corner
  11619.             if i < 4 then
  11620.                 T:down(depth-2) -- roughly at correct depth
  11621.                 local waterBelow = utils.clearVegetation("down")
  11622.                 while waterBelow do
  11623.                     T:down(1)
  11624.                     waterBelow = utils.clearVegetation("down")
  11625.                 end
  11626.                 blockType = T:getBlockType("down")
  11627.                 while blockType:find("prismarine") ~= nil do
  11628.                     T:forward(1)
  11629.                     blockType = T:getBlockType("down")
  11630.                 end
  11631.                 turtle.back()
  11632.                 depth = lib.buildColumn()
  11633.             end
  11634.         end
  11635.         -- completed retaining paths. Build small tower for easy access
  11636.         lib.buildTower()
  11637.     end
  11638.    
  11639.     return {}
  11640. end
  11641.  
  11642. local function placeRedstoneTorch(R) -- 91, 92
  11643.     local moves = 2
  11644.     local blockType = T:getBlockType("down")
  11645.     if R.data == "level" then
  11646.         T:turnLeft(1)
  11647.         utils.goBack(1)
  11648.         if blockType:find("rail") ~= nil then
  11649.              moves = 3
  11650.         end
  11651.         T:down(moves)
  11652.         T:go("F1R1")
  11653.         --clsTurtle.place(self, blockType, damageNo, direction, leaveExisting)
  11654.         T:place(R.useBlockType, "forward", false)
  11655.         utils.goBack(1)
  11656.         T:place("minecraft:redstone_torch", "forward", true)
  11657.         T:turnLeft(1)
  11658.         utils.goBack(1)
  11659.         T:up(moves)
  11660.         T:go("F1R1F1")
  11661.     elseif R.data == "up" then -- sloping rail up/down is relative to dirtection facing
  11662.         moves = 3
  11663.         T:turnLeft(1)
  11664.         utils.goBack(1)
  11665.         if blockType:find("rail") ~= nil then
  11666.              moves = 4
  11667.         end
  11668.         T:down(moves)
  11669.         T:go("F1L1")
  11670.         T:place("minecraft:redstone_torch", "up", false)
  11671.        
  11672.         T:turnRight(1)
  11673.         utils.goBack(1)
  11674.         T:up(moves)
  11675.         T:go("F1R1")
  11676.     end
  11677.     return {}
  11678. end
  11679.  
  11680. local function plantTreefarm(R) -- 23
  11681.     -- already known R.networkFarm, R.subChoice (1 = singe, 2 = double, 3 = mangrove)
  11682.     --T:place(blockType, damageNo, leaveExisting, signText)
  11683.     local lib = {}
  11684.    
  11685.     function lib.checkSaplings(firstChoice, secondChoice)
  11686.         local saplingSlot, sapling, count = T:getSaplingSlot(firstChoice)
  11687.         if count < 4  and secondChoice ~= "" then
  11688.             saplingSlot, sapling, count = T:getSaplingSlot(secondChoice)
  11689.         end
  11690.         if count == 0 then
  11691.             sapling = ""
  11692.         end
  11693.        
  11694.         return sapling, count
  11695.     end
  11696.    
  11697.     function lib.emptyInventory(R)
  11698.         if not T:isEmpty() then
  11699.             utils.useSticksAsFuel()
  11700.             network.sendItemToNetworkStorage(R, "barrel", "sapling", 64)
  11701.             network.sendItemToNetworkStorage(R, "barrel", "propagule", 64)
  11702.             network.sendItemToNetworkStorage(R, "barrel", "apple", 64)
  11703.             network.sendItemToNetworkStorage(R, "barrel", "dirt", 64)
  11704.             network.sendItemToNetworkStorage(R, "chest", "all", 0)
  11705.         end
  11706.     end
  11707.    
  11708.     function lib.getSaplingInventory(R)
  11709.         local saplings = {}
  11710.         saplings.oak_sapling = 0
  11711.         saplings.spruce_sapling = 0
  11712.         saplings.birch_sapling = 0
  11713.         saplings.jungle_sapling = 0
  11714.         saplings.acacia_sapling = 0
  11715.         saplings.dark_oak_sapling = 0
  11716.         saplings.cherry_sapling = 0
  11717.         saplings.mangrove_propagule = 0
  11718.  
  11719.         local firstChoice = ""
  11720.         local firstCount = 0
  11721.         local secondChoice  = ""
  11722.         local secondCount = 0
  11723.         if T:getItemSlot("sapling") > 0 then
  11724.             for i = 1, 16 do
  11725.                 if turtle.getItemCount(i) > 0 then
  11726.                     local data = turtle.getItemDetail(i)
  11727.                     if data.name:find("sapling") ~= nil then
  11728.                         local name = data.name:sub(11) -- removes "minecraft:"
  11729.                         saplings[name] = saplings[name] + data.count
  11730.                     end
  11731.                 end
  11732.             end
  11733.         elseif T:getItemSlot("propagule") > 0 then
  11734.             saplings.mangrove_propagule = turtle.getItemCount(T:getItemSlot("propagule"))
  11735.         else    -- no saplings onBoard: ? automated networked farm
  11736.             if R.networkFarm then
  11737.                 -- networked farms use 1 type of sapling indicated by log embedded to right of modem
  11738.                 -- discovered from utils.assessTreeFarm() on manual Startup
  11739.                 if R.auto then  -- called here as NOT manual startup
  11740.                     R = utils.assessTreeFarm(R)
  11741.                     if R.message ~= "" then
  11742.                         return {R.message}  -- location of turtle error
  11743.                     end
  11744.                 end
  11745.                 local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", R.useBlockType, 16)
  11746.                 if turtleCount == 0 then    -- ask player for saplings
  11747.                     T:checkInventoryForItem({R.useBlockType}, {16}, true, "Saplings required for tree farm")
  11748.                 end
  11749.                 saplings[R.useBlockType] = saplings[R.useBlockType] + turtleCount
  11750.                 turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 16)
  11751.                 if turtleCount == 0 then
  11752.                     turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 16)
  11753.                 end
  11754.                 if turtleCount == 0 then    -- ask player
  11755.                     T:checkInventoryForItem({"minecraft:dirt"}, {16}, true, "Dirt required for tree farm")
  11756.                 end
  11757.                 return saplings, R.useBlockType, R.useBlockType
  11758.             end
  11759.         end
  11760.         for sapling, count in pairs(saplings) do
  11761.             if count > firstCount then
  11762.                 firstCount = count
  11763.                 firstChoice = sapling
  11764.             else
  11765.                 if count > secondCount then
  11766.                     secondCount = count
  11767.                     secondChoice = sapling
  11768.                 end
  11769.             end
  11770.         end
  11771.         return saplings, firstChoice, secondChoice -- table, "oak_sapling", "dark_oak_sapling"
  11772.     end
  11773.    
  11774.     function lib.createIsland(sapling, count, exit)
  11775.         -- place 4 dirt with saplings on all 4 unless jungle
  11776.         -- sapling count/type already checked
  11777.         T:forward(2) -- assume starting outside planting area
  11778.         for i = 1, 4 do
  11779.             T:go("R1F1")
  11780.             T:place("dirt", "down", false, "", true)
  11781.         end
  11782.         T:up(1)
  11783.         if count >= 4 then
  11784.             for i = 1, 4 do
  11785.                 T:go("R1F1")
  11786.                 T:place(sapling, "down", false, "", true)
  11787.             end
  11788.         else
  11789.             if sapling:find("dark") == nil and sapling ~= "" then
  11790.                 T:place(sapling, "down", false, "", true)
  11791.             end
  11792.         end
  11793.         if exit == "forward" then
  11794.             T:go("F1D1")
  11795.         elseif exit == "right" then
  11796.             T:go("R1F2D1")
  11797.         elseif exit == "left" then
  11798.             T:go("L1F1D1")
  11799.         elseif exit == "back" then
  11800.             T:go("R2F2D1")
  11801.         end
  11802.     end
  11803.    
  11804.     function lib.createSingle(sapling, exit)
  11805.         -- place single dirt with sapling on top
  11806.         -- sapling count/type already checked
  11807.         T:place("dirt", "down", false, "", true)
  11808.         T:up(1)
  11809.         if not T:place(sapling, "down", false, "", true) then -- try specific sapling
  11810.             T:place("sapling", "down", false, "", true)     -- any available sapling
  11811.         end
  11812.         if exit == "forward" then
  11813.             T:go("F1D1")
  11814.         elseif exit == "right" then
  11815.             T:go("R1F1D1")
  11816.         elseif exit == "left" then
  11817.             T:go("L1F1D1")
  11818.         elseif exit == "back" then
  11819.             T:go("R2F1D1")
  11820.         end
  11821.     end
  11822.    
  11823.     function lib.getMangroveSupplies()
  11824.         local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 169)
  11825.         if turtleCount < 169 then
  11826.             turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 169 - turtleCount)
  11827.             if turtleCount < 169 then   -- ask player for saplings
  11828.                 T:checkInventoryForItem({"dirt"}, {169 - turtleCount})
  11829.             end
  11830.         end
  11831.         turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:mangrove_propagule", 25)
  11832.         if turtleCount == 0 then    -- ask player for saplings
  11833.             T:checkInventoryForItem({"mangrove_propagule"}, {25}, true, "Mangrove propagules required")
  11834.         end
  11835.     end
  11836.    
  11837.     function lib.plantMangrove()
  11838.         T:go("L1F6 R1F1 U1")
  11839.         createFloorCeiling({width = 13, length = 13, up = false, down = true,
  11840.                             height = 0, subChoice = 0, useBlockType = "minecraft:dirt",
  11841.                             inventory = T:getInventory()})
  11842.        
  11843.         --T:go("U1F5 R1F5 L1")          -- lower left of planting area, facing Back
  11844.         T:go("U1F4 R1F4 L1")            -- lower left of planting area, facing Back
  11845.         for x = 1, 5 do
  11846.             for i = 1, 5 do
  11847.                 T:place("propagule", "down")    -- left 1
  11848.                 if i < 5 then
  11849.                     T:forward(1)
  11850.                 end
  11851.             end
  11852.             if x % 2 == 1 then
  11853.                 if x < 5 then
  11854.                     T:go("R1F1R1")
  11855.                 end
  11856.             else
  11857.                 T:go("L1F1L1")
  11858.             end
  11859.         end
  11860.         T:go("L1F2 L1F2 D2U2 F7R2 D2")
  11861.         --[[
  11862.         T:place("propagule", "down")    -- left 1
  11863.         T:forward(1)
  11864.         T:place("propagule", "down")    -- left 2
  11865.         T:forward(1)
  11866.         T:place("propagule", "down")    -- left 3/top 1
  11867.  
  11868.         T:go("R1F1")
  11869.         T:place("propagule", "down")    -- top 2
  11870.         T:forward(1)
  11871.         T:place("propagule", "down")    -- top 3/right 1
  11872.         T:go("R1F1")
  11873.        
  11874.         T:place("propagule", "down")    -- right 2
  11875.         T:forward(1)
  11876.         T:place("propagule", "down")    -- right 3/bottom 1
  11877.         T:go("R1F1")
  11878.         T:place("propagule", "down")    -- bottom 2]]
  11879.        
  11880.         --T:go("R1F1R2 D2U2 F7R2 D2")
  11881.     end
  11882.    
  11883.     function lib.plantSingle(R)
  11884.         local sapling, count = lib.checkSaplings(firstChoice, secondChoice)
  11885.         if count >= 1 then
  11886.             if R.networkFarm then
  11887.                 T:go("U1L1 F3R1 F4") -- outside first area
  11888.             else
  11889.                 T:go("U1F4") -- outside first area
  11890.             end
  11891.             for i = 1, 3 do -- column 1/4
  11892.                 lib.createSingle(sapling, "forward")
  11893.                 T:forward(1)
  11894.             end
  11895.             for i = 1, 2 do
  11896.                 lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
  11897.                 T:forward(1)
  11898.             end
  11899.             for i = 1, 2 do -- column 2/4
  11900.                 lib.createSingle(sapling, "forward")
  11901.                 T:forward(1)
  11902.             end
  11903.             for i = 1, 2 do
  11904.                 lib.createSingle(sapling, "left") -- place 4th dirt/saling and exit to right
  11905.                 T:forward(1)
  11906.             end
  11907.             for i = 1, 2 do -- column 3/4
  11908.                 lib.createSingle(sapling, "forward")
  11909.                 T:forward(1)
  11910.             end
  11911.             for i = 1, 2 do
  11912.                 lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
  11913.                 T:forward(1)
  11914.             end
  11915.             for i = 1, 3 do -- column 4/4
  11916.                 lib.createSingle(sapling, "forward")
  11917.                 T:forward(1)
  11918.             end
  11919.             if R.networkFarm then
  11920.                 T:go("R1F3 R1F2L1") -- in-between 2 trees
  11921.                 if R.auto then
  11922.                     harvestTreeFarm(R)
  11923.                 else
  11924.                     T:go("L1F4R2D1")
  11925.                 end
  11926.             else
  11927.                 T:go("R1F6 L1F2 R2D1")
  11928.             end
  11929.         else
  11930.             return "No saplings to plant"
  11931.         end
  11932.        
  11933.         return ""
  11934.     end
  11935.    
  11936.     function lib.plantDouble(R)
  11937.         -- assume placed 4 blocks from start
  11938.         local sapling, count = lib.checkSaplings(saplings, firstChoice, secondChoice)
  11939.        
  11940.         if count >= 4 then
  11941.             if R.networkFarm then
  11942.                 T:go("U1L1 F3R1 F3") -- outside first area
  11943.             else
  11944.                 T:go("U1F3") -- outside first area
  11945.             end
  11946.             lib.createIsland(sapling, count, "forward")
  11947.             sapling, count = lib.checkSaplings(firstChoice, secondChoice)
  11948.             T:go("F2")
  11949.             lib.createIsland(sapling, count, "right")
  11950.             sapling, count = lib.checkSaplings(firstChoice, secondChoice)
  11951.             T:go("F2")
  11952.             lib.createIsland(sapling, count,  "right")
  11953.             sapling, count = lib.checkSaplings(firstChoice, secondChoice)
  11954.             T:go("F2")
  11955.             lib.createIsland(sapling, count, "forward")
  11956.            
  11957.             if R.networkFarm then
  11958.                 T:go("R1F4 R1F1 L1")            -- on left side of double tree
  11959.                 if R.auto then
  11960.                     harvestTreeFarm(R)
  11961.                 else
  11962.                     T:go("L1F4 L1F1 L1D1")  -- back to start
  11963.                 end
  11964.             else
  11965.                 T:go("R1D1 F6L1 F3R2") -- outside first area
  11966.             end
  11967.         else
  11968.             return "Insufficient saplings to plant"
  11969.         end
  11970.         return ""
  11971.     end
  11972.    
  11973.     if R.networkFarm then
  11974.         local message = network.loadStorageLists()  -- initialises or creates lists of where an item can be found: GLOBAL LISTS!
  11975.         if message ~= nil then return {message} end
  11976.         lib.emptyInventory(R)
  11977.     end
  11978.     if R.subChoice == 3 then    -- mangrove, R.networkFarm only
  11979.         lib.getMangroveSupplies()
  11980.         lib.plantMangrove()
  11981.     else
  11982.         local saplings, firstChoice, secondChoice = lib.getSaplingInventory(R)
  11983.         if firstChoice ~= "" then
  11984.             print("first sapling: "..firstChoice .. " ("..saplings[firstChoice]..")")
  11985.         end
  11986.         if secondChoice ~= "" then
  11987.             print("second sapling: "..secondChoice .. " ("..saplings[secondChoice]..")")
  11988.         end
  11989.    
  11990.         -- check type/size of farm
  11991.         local message = ""
  11992.         if R.subChoice == 1 then            -- 16 single trees
  11993.             message = lib.plantSingle(R)    -- always ""
  11994.         elseif R.subChoice == 2 then        -- 4 double trees (4 saplings)
  11995.             message = lib.plantDouble(R)    -- "" or error about numbers
  11996.         end
  11997.     end
  11998.     if R.networkFarm then
  11999.         lib.emptyInventory(R)
  12000.     end
  12001.     return {message}
  12002. end
  12003.  
  12004. local function quickMine(R) -- 17
  12005.     --[[
  12006.     mine valuable blocks from specified area
  12007.     if R.up set or lava/water found, ceiling is formed
  12008.     if R.down is set, or lava/water found layer is kept 1 block high
  12009.     R.subChoice
  12010.     1 At mine area start, on the floor
  12011.     2 At mine area start, on the ceiling
  12012.     3 On floor, start 1 block ahead
  12013.     4 On ceiling, start 1 block ahead
  12014.     5 On floor diagonally to left"
  12015.     ]]
  12016.     local lib = {}
  12017.    
  12018.     function lib.refuel(direction)
  12019.         if T:getWater(direction)  then
  12020.             T:refuel(1000, false)
  12021.         end
  12022.     end
  12023.    
  12024.     function lib.mine(R)
  12025.         -- starts on ceiling
  12026.         local isValuable, blockType
  12027.         for i = 1, R.length do
  12028.             local fillUp = R.up
  12029.             local fillDown = R.down
  12030.             isValuable, blockType = T:isValuable("down")
  12031.             if isValuable then
  12032.                 T:dig("down")
  12033.             elseif blockType:find("water") ~= nil then
  12034.                 fillDown = true
  12035.             elseif blockType:find("lava") ~= nil then
  12036.                 lib.refuel("down")
  12037.                 fillDown = true
  12038.             end
  12039.             isValuable, blockType = T:isValuable("up")
  12040.             if isValuable then
  12041.                 T:dig("up")
  12042.             elseif blockType:find("water") ~= nil then
  12043.                 fillUp = true
  12044.             elseif blockType:find("lava") ~= nil then
  12045.                 lib.refuel("up")
  12046.                 fillUp = true
  12047.             end
  12048.             --if not turtle.detectUp() and fillUp then
  12049.             if fillUp then
  12050.                 T:fillVoid("up")
  12051.             end
  12052.             --if not turtle.detectDown() and fillDown then
  12053.             if fillDown then
  12054.                 T:fillVoid("down")
  12055.             end
  12056.             if i < R.length then
  12057.                 T:forward(1)
  12058.             end
  12059.         end
  12060.     end
  12061.    
  12062.     local outbound = true
  12063.    
  12064.     if R.subChoice == 1 then
  12065.         T:up(1)
  12066.     elseif R.subChoice == 3 then
  12067.         T:go("U1F1")
  12068.     elseif R.subChoice == 4 then
  12069.         T:go("F1")
  12070.     elseif R.subChoice == 5 then
  12071.         T:go("U1R1 F1L1 F1")
  12072.     end
  12073.    
  12074.     for w = 1, R.width do
  12075.         lib.mine(R)
  12076.         if w < R.width then
  12077.             if outbound then
  12078.                 T:go("R1F1R1")
  12079.             else
  12080.                 T:go("L1F1L1")
  12081.             end
  12082.             outbound = not outbound
  12083.         end
  12084.         if T:getFirstEmptySlot() == 0 then
  12085.             T:dumpRefuse("forward", 1)
  12086.         end
  12087.     end
  12088.     if outbound then
  12089.         T:go("L1F"..R.width - 1 .."L1F"..R.length - 1)
  12090.     else
  12091.         T:go("R1F"..R.width - 1 .."R1")
  12092.     end
  12093.    
  12094.     return {}
  12095. end
  12096.  
  12097. local function quickMineCorridor(R) -- 16
  12098.     --[[
  12099.     R.subChoice
  12100.     1: At corridor start, on the floor
  12101.     2: At corridor start, on the ceiling
  12102.     3: On floor, start 1 block ahead
  12103.     4: On ceiling, start 1 block ahead
  12104.     ]]
  12105.     if R.subChoice == 2 then
  12106.         T:down(1)
  12107.     elseif R.subChoice == 3 then
  12108.         T:forward(1)
  12109.     elseif R.subChoice == 4 then
  12110.         T:go("D1F1")
  12111.     end
  12112.     local width = R.width - 1
  12113.     local length = R.length - 1
  12114.     R.silent = true
  12115.     R.length = length
  12116.     createCorridor(R, true) -- put floor and ceiling for R.length, place torch at start
  12117.     T:turnRight(1)
  12118.     R.length = width
  12119.     createCorridor(R, true)
  12120.     T:turnRight(1)
  12121.     R.length = length
  12122.     createCorridor(R, true)
  12123.     T:turnRight(1)
  12124.     R.length = width
  12125.     createCorridor(R, true)
  12126.     T:turnRight(1)
  12127.    
  12128.     return {}
  12129. end
  12130.  
  12131. local function repairWall(startAt, height, width, replaceWith)
  12132.     -- go up to startAt
  12133.    
  12134.     -- if width = 1
  12135.    
  12136.         -- for h = startAt, height, 1 do
  12137.        
  12138.             -- replace block with replaceWith ("" = any)
  12139.            
  12140.             -- move up
  12141.            
  12142.         --end
  12143.        
  12144.         -- move back to beginning
  12145.        
  12146.     -- else
  12147.    
  12148.         -- remain = height % 2
  12149.        
  12150.         -- for w = 1, width - remain do
  12151.        
  12152.             -- for h = startAt, height, 1 do
  12153.            
  12154.                 -- replace block with replaceWith ("" = any)
  12155.                
  12156.                 -- move up
  12157.                
  12158.             --end
  12159.            
  12160.             -- move to the right 1 block
  12161.            
  12162.             -- for i = height, startAt, -1 do
  12163.            
  12164.                 -- replace block with replaceWith ("" = any)
  12165.                
  12166.                 -- move down
  12167.                
  12168.             --end
  12169.            
  12170.         -- end
  12171.        
  12172.     -- end
  12173.    
  12174. end
  12175.  
  12176. local function getTaskItemsList()
  12177.     -- list of items required for each task
  12178.     local text = {}
  12179.     --MINING
  12180.     text[11] = {"1 ladder for each level","levels / 4 torch (optional)","levels * 4 stone"}             -- ladder to bedrock
  12181.     text[12] = {"2 stairs for each level", "6 * levels stone", "1 chest"}                               -- stairs up/down
  12182.     text[13] = {"24 torch (optional)", "1 bucket (optional)", "64 stone", "1 chest"}                    -- mine at this level
  12183.     text[14] = {"levels * 4 stone","water_bucket"}                                                      -- safe drop to water block
  12184.     text[15] = {"levels * 4 stone", "1 soul sand", "1 water bucket"}                                    -- single column bubble lift
  12185.     text[16] = {"1 bucket (optional)", "64 stone"}                                                      -- quick corridor
  12186.     text[17] = {"1 bucket (optional)", "64 stone"}                                                      -- quick mine
  12187.     text[18] = {"1 bucket (optional)"}                                                                  -- mine to bedrock
  12188.     text[19] = {"1 UNUSED diamond sword (optional)"}                                                    -- rob mineshaft
  12189.  
  12190.     -- FORESTRY
  12191.     text[21] = {"1 chest (optional)"}                                                                   -- Fell Tree
  12192.     text[22] = {"320 stone", "4 polished stone"}                                                        -- Create treefarm
  12193.     text[23] = {"min 4 saplings", "16 dirt"}                                                            -- plant treefarm
  12194.     text[24] = {"No items required"}                                                                    -- Harvest treefarm
  12195.     text[25] = {"width * length * 2 walls or fences", "torches (optional)", "4 barrels (optional)"}     -- fence or wall a forest
  12196.     text[26] = {"1 chest", " any saplings"}                                                             -- harvest and replant walled rectangle of natural forest
  12197.                
  12198.     -- FARMING         
  12199.     text[31] = {"64 stone","128 dirt (optional)", "4 water buckets","4 chests / barrels","1 sapling"}   -- Create modular crop farm
  12200.     text[32] = {"64 stone","128 dirt (optional)", "4 water buckets","5 chests/ barrels","1 sapling"}    -- extend modular farm
  12201.     text[33] = {"No items required"}                                                                    -- Manual harvest and auto setup
  12202.     text[34] = {"Walls or Fences", "Torches (optional)"}                                                -- Build a wall or fence
  12203.     text[35] = text[34]                                                                                 -- Wall or fence enclosed area
  12204.  
  12205.     -- OBSIDIAN
  12206.     text[41] = {"stone to cover area of obsidian"}                                                      -- Harvest obsidian
  12207.     text[42] = {"2 x height + width obsidian", "4 stone"}                                               -- build Nether portal
  12208.     text[43] = {"No items required"}                                                                    -- demolish Nether portal
  12209.     text[44] = {"length * 4 stone/netherrack, bucket"}                                                  -- Netherite stripping
  12210.     text[45] = {"84 stone"}                                                                             -- undermine dragon towers
  12211.     text[46] = {"No items required"}                                                                    -- deactivate dragon tower
  12212.     text[47] = {"448 stone, 145 ladders, 1 obsidian, 1 water bucket"}                                   -- dragon water trap
  12213.     text[48] = {"height * 4 stone","height * ladders", "1 trapdoor"}                                    -- build end portal platform
  12214.                
  12215.     --CANALS BRIDGES WALKWAYS
  12216.     text[51] = {"dirt or stone * length","torch (optional)"}                                            -- single path
  12217.     text[52] = {"dirt or stone 2 * length","torch (optional)"}                                          -- covered path / tunnel
  12218.     text[53] = {"2 * length stone or dirt","2 water buckets","torches (optional)"}                      -- water canal
  12219.     text[54] = {"0.5 * length Packed or blue ice","length * slabs","stone","torches (optional)"}        -- Ice canal
  12220.     text[55] = {"width * length stone"}                                                                 -- platform
  12221.     text[56] = {"width + 1 * length + 1 stone"}                                                         -- sinking platform
  12222.     text[57] = {"height * 10 stone","height * 4 + 2 soul sand, 2 water buckets"}                        -- Boat bubble lift
  12223.    
  12224.     -- MOB FARM
  12225.     text[61] = {"512 stone","1 slab"}                                                                   -- 9x9 cube round spawner
  12226.     text[62] = {"640 stone","37 slab","8 powered rail","64 rail","2 redstone torch",
  12227.                 "1 hopper minecart","1 stone button"}                                                   -- 9x9 cube round blaze spawner
  12228.     text[63] = {"2 water buckets","If using bubble lift","2 fence","2 signs","1 slab",
  12229.                 "1 soul sand (or dirt as placeholder)"}                                                 -- flood spawner chamber   
  12230.     text[64] = {"128 stone","2 water buckets","1 soul sand"}                                            --Build bubble tower kill zone
  12231.     text[65] = {"1-2 computer","2 sticky or 4 normal pistons","6 network cable + 2 wired modems",
  12232.                 "23 polished stone + 7 slabs","2 glass","1 stone pressure plate","1 dispenser",
  12233.                 "1 hopper + 2 chest", "9 redstone", "1 lava bucket"}                                    --Computercraft mob grinder
  12234.     text[66] = {"1856 stone, diorite etc (inc polished)","1 chest","10 empty buckets",
  12235.                 "2 water buckets","192 fence","8 signs","3 ladder","2 soul sand"}                       -- build endermen observation tower
  12236.     text[67] = {"24 blocks of any type"}                                                                -- Cover Trial spawners to prevent mobs escaping
  12237.    
  12238.     -- AREA CARVING
  12239.     text[71] = {"width * length dirt"}                                                                  -- Clear field
  12240.     text[72] = {"No items required"}                                                                    -- Clear rectangle width, length
  12241.     text[73] = {"No items required"}                                                                    -- Clear wall height, length
  12242.     text[74] = {"No items required"}                                                                    -- Clear rectangle perimeter only width, length
  12243.     text[75] = {"No items required"}                                                                    -- Clear structure floor/walls/ceiling
  12244.     text[76] = {"No items required"}                                                                    -- clear solid
  12245.     text[77] = {"No items required"}                                                                    -- Dig a trench
  12246.     text[78] = {"No items required"}                                                                    -- carve mountain
  12247.     text[79] = {"width * height Any material floor / ceiling"}                                          -- floor or ceiling
  12248.     text[710] = {"Blocks to add 'floor as you go'"}                                                     -- Direct control of movement
  12249.                
  12250.     -- LAVA WATER
  12251.     text[81] = {"Enough sand or gravel to fill volume"}                                                 -- sand based utilities
  12252.     text[82] = {"length * depth stone"}                                                                 -- vertical wall from surface
  12253.     text[83] = {"Blocks to add 'floor as you go'"}                                                      -- player driven path construction
  12254.     text[84] = {"width * length + extra stone"}                                                         -- water clearing by repeated block deletion
  12255.     text[85] = text[84]                                                                                 -- sinking platform
  12256.     text[86] = {"Full inventories of sand or stone"}                                                    -- Ocean monument utilities
  12257.     text[87] = {"ladder to height","stone, dirt netherrack 4 X height"}                                 -- ladder to water/lava
  12258.     text[88] = {"No items required"}                                                                    -- clear water plants
  12259.     text[89] = {"water buckets / buckets"}                                                              -- convert flowing water to source
  12260.     text[810] = {"6 buckets","slabs to cover area"}                                                     -- create sloping water
  12261.                
  12262.     -- BUILDING and MINECART
  12263.     text[91] = {"length * height stone"}                                                                -- Build a wall
  12264.     text[92] = {"length * height * 4 stone"}                                                            -- build a walled area
  12265.     text[93] = {"length * width * height stairs", "length * slabs"}                                     -- build a gable roof
  12266.     text[94] = {"length * width * height stairs", "length * slabs"}                                     -- Build a pitched roof
  12267.     text[95] = {"1 block of choice","1 redstone torch"}                                                 -- place redstone torch under current block
  12268.     text[96] = {"1 block of choice","1 redstone torch"}                                                 -- place redstone torch on upward slope
  12269.     text[97] = {"height x block of choice","height/3 x redstone torch"}                                 -- build downward slope
  12270.     text[98] = text[97]                                                                                 -- build upward slope
  12271.     return text
  12272. end
  12273.  
  12274. local function getTaskHelp(menuLevel, menuItem, noMenu, getInteger)
  12275.     -- display help about selected task
  12276.     -- terminal size = 39 x 13
  12277. --[[This line of text = 39 characters]]
  12278.     noMenu = noMenu or false
  12279.     getInteger = getInteger or false
  12280.     info = {}
  12281.     info.main = {}
  12282.     info.sub = {}
  12283.     table.insert(info.main,
  12284.     [[                ~lightGray~MINING:~white~
  12285. Can be used in over-world or nether.~brown~
  12286. Ladders and ~lightGray~stairs up/down    
  12287. Create a pre-formatted 33 x 33 blocks  
  12288. mine at chosen level.
  12289. ~blue~Bubble lift and ~cyan~safe drop to water.~magenta~  
  12290. Faster version of ~white~33x33 mine pattern  
  12291. using ~magenta~corridor and ~pink~rectangle functions.~brown~
  12292. Mine bottom layer to bedrock (not worth
  12293. the fuel and time)
  12294. ~brown~Strip resources from abandoned mines.
  12295. ]])
  12296.     table.insert(info.main,
  12297.     [[               ~lime~FORESTRY:~brown~
  12298. Fell Tree can be used in Nether as well
  12299. for cutting any size tree / branches~lime~
  12300. Create a simple 16 single tree farm
  12301. or 4 double size (Dark oak or any type)
  12302. suitable for turtle harvesting.
  12303. ~brown~ fence or wall a rectangle keeping
  12304. to contours.
  12305. ~green~Forest can be harvested and replanted.
  12306. (Must be walled off)
  12307.  
  12308. ]])
  12309.     table.insert(info.main,
  12310.     [[                ~green~FARMING:~yellow~
  12311. Farm modules can be built to fixed size
  12312. and placed next to each other in linear
  12313. or rectangular pattern.~lime~
  12314. Whole farm is managed by a dedicated
  12315. turtle, which must be equipped with a
  12316. diamond hoe as well as pickaxe.
  12317. Fuel obtained from a tree placed in the
  12318. corner of each module.
  12319. Double chests store produce and seeds.
  12320. ]])
  12321.     table.insert(info.main,
  12322.     [[               ~red~OBSIDIAN:~lightGray~
  12323. The turtle can extract obsidian from
  12324. lava areas safely.~pink~
  12325. Nether portals can be built or removed
  12326. without needing diamond pickaxes.~orange~
  12327. End World dragon towers can be
  12328. undermined ready for deactivating.
  12329. End world towers can have the crystals
  12330. destroyed.~red~
  12331. Water trapped dragon attacked from above~brown~
  12332. Minecart end portal stations built.
  12333. ]])
  12334.     table.insert(info.main,
  12335.     [[        ~brown~PATHS, BRIDGES, CANALS:~white~
  12336. Can be used in Nether and End.~lightGray~
  12337. Build pathways over air, water or lava
  12338. Optional roofed pathway for Nether use.
  12339. Tunnel through rock and place a floor
  12340. at the same time.~blue~
  12341. Build a water canal with towpath.~cyan~
  12342. Build a super-fast ice canal.~brown~
  12343. Platform for use over air, water, lava
  12344. Sinking version is removed and replaced
  12345. 1 block lower each time
  12346. ]])
  12347.     table.insert(info.main,
  12348.     [[             ~lightGray~SPAWNER FARMS:~brown~
  12349. Tools to create mob farms round
  12350. existing spawners. ~red~
  12351. Special version for Blaze farms
  12352. uses rail collection.~cyan~
  12353. Choice of bubble lift mob dropper
  12354. or ~brown~simple deep trench.~gray~
  12355. Enderman observation tower can be
  12356. built >128 above ground: is ~red~expensive.~gray~
  12357. Re-spawns new mobs when used.~red~
  12358. Suggest build only the base.
  12359. ]])
  12360.     table.insert(info.main,
  12361.     [[    ~orange~AREA CLEARING AND REFORMING:~lime~
  12362. Tools to clear a field including trees~magenta~
  12363. Clear rectangles.~pink~
  12364. Clear single walls.~brown~
  12365. Clear hollow and~orange~solid structures.~brown~
  12366. Dig a trench.~gray~
  12367. Carve away side of a mountain.~lightBlue~
  12368. Place or replace floors and ceilings
  12369.  
  12370.  
  12371.  
  12372. ]])
  12373.     table.insert(info.main,
  12374.     [[      ~blue~WATER AND LAVA TOOLS:~white~
  12375. Used to drain ocean monuments and
  12376. shipwrecks. Can also be used to make
  12377. underwater base. ~blue~Water is cleared using
  12378. sand dropping and recycling~cyan~
  12379. Destructive draining uses solid block
  12380. placing and recycling.~green~
  12381. Water plants can be removed without
  12382. damaging structures.~lightBlue~
  12383. Tools to manipulate water areas:
  12384. (convert to source, sloping water)
  12385. ]])
  12386.     table.insert(info.main,
  12387.     [[         ~cyan~BUILDING, MINECART TOOLS:~lightGray~
  12388. Build simple walls, buildings and ~gray~roofs
  12389.  
  12390. ~orange~Used to build diagonal uphill slope~brown~
  12391. and downhill slope for placing
  12392. 45 degree rail tracks.~red~
  12393. Placing Redstone torches under powered
  12394. rails when above ground level (viaduct)
  12395.  
  12396.  
  12397.  
  12398. ]])
  12399.     table.insert(info.main,
  12400.     [[           ~yellow~MEASURING TOOLS:
  12401. Used to measure
  12402.     ~red~Height
  12403.     ~purple~Depth
  12404.     ~magenta~Length~pink~
  12405.    
  12406.     Greatest depth of water
  12407.  
  12408.  
  12409.  
  12410.  
  12411. ]])
  12412.  
  12413.     info.sub[11] =
  12414. [[~yellow~Place me on the ground at ~red~^~yellow~
  12415. The ~brown~ladder ~yellow~will start at this level
  12416. and go up or down.
  12417.  
  12418. ~lightGray~| | | | | |
  12419. ~lightGray~| | |*| | | * = Ladder support block
  12420. | | |~brown~L~lightGray~| | | ~brown~L = Ladder
  12421. ~lightGray~| | |~red~^~lightGray~| | | ~red~^ = Turtle
  12422. ~lightGray~| | | | | |
  12423. | | | | | |
  12424.  
  12425. ]]-- Ladder up/down
  12426.     info.sub[12] =
  12427. [[~lightGray~Place me on the ground at ~red~^
  12428.  
  12429. ~lightGray~| | | | | | | | * = Solid block
  12430. ~lightGray~| |*|*|*|*|*| | ~cyan~^ = Stairs to back
  12431. ~lightGray~| |*|-|~cyan~>~lightGray~|-|*| | ~cyan~> = Stairs to right
  12432. ~lightGray~| |*|~cyan~^|~lightGray~*|~cyan~V~lightGray~|*| | ~cyan~V = Stairs to front
  12433. ~lightGray~| |*|-|~cyan~<~lightGray~|-|*| | ~cyan~< = Stairs to left
  12434. ~lightGray~| |*|~red~^~lightGray~|*|*|*| | - = Corner tread
  12435. ~lightGray~| | | | | | | | ~red~^ = Turtle
  12436.  
  12437. ~lightGray~Going ~blue~down~lightGray~ -> digs down then stairs up
  12438. ]] -- Stairs up/down
  12439.         info.sub[13] =
  12440. [[~yellow~Press F3 to check Y level.
  12441.  
  12442. ~lightGray~| |~red~^~lightGray~| | | ~red~^ = Turtle behind ladder
  12443. ~lightGray~| |~gray~s~lightGray~| | | ~gray~s = 1 block space
  12444. ~lightGray~| |*| | | * = Ladder support block
  12445. ~lightGray~| |~brown~L~lightGray~| | | ~brown~L = Ladder
  12446. ~lightGray~| |~brown~s~lightGray~| | | ~brown~s~gray~ = 2 spaces (inc. ladder)
  12447. ~lightGray~| |~red~V~lightGray~| | | ~red~V = Turtle ahead of ladder~yellow~
  12448.  
  12449. ]]
  12450.     if bedrock == 0 then    --pre 1.18
  12451.         info.sub[13] = info.sub[13].."Place at Y = 5, 8, 11 ~red~(11 nether)" -- Create mine at this level
  12452.     else
  12453.         info.sub[13] = info.sub[13].."Place at Y = -59, -56, -53 (11 nether)" -- Create mine at this level
  12454.     end
  12455.     info.sub[14] =
  12456. [[~yellow~Turtle goes ~blue~DOWN ~yellow~to chosen level
  12457. enclosing all sides of the column.
  12458. Water placed at bottom. Returns here.
  12459. If next to a ladder, place as below:
  12460.  
  12461. ~lightGray~| | | | | |
  12462. ~lightGray~| | |*| | | * = Ladder support block
  12463. | |~red~^~brown~|L|~red~^~lightGray~| | ~brown~L = ladder
  12464. ~lightGray~| | | | | | ~red~^ = Turtle facing forward
  12465. ~lightGray~| | | | | |
  12466.            
  12467. ]] -- safe drop
  12468.     info.sub[15] =
  12469. [[~magenta~Direction of travel = UP!
  12470. ~yellow~Place me on the ground. I will build a
  12471. 3 x 1 ~blue~water ~yellow~source and a single column
  12472. bubble lift to the chosen height.
  12473. If near a ladder, place left or right:
  12474.  
  12475. ~lightGray~| | | | | |
  12476. ~lightGray~| | |*| | | * = Ladder support block
  12477. | |~blue~^~brown~|L|~blue~^~lightGray~| | ~brown~L = ladder
  12478. ~lightGray~| | | | | | ~blue~^ = Turtle facing forward
  12479. ~lightGray~| | | | | | ~blue~^ = Bubble column above
  12480.  
  12481. ]] -- single column bubble lift
  12482.     info.sub[16] =
  12483. [[~yellow~Place me as below:
  12484.  1. On ~blue~floor   ~yellow~(feet height)
  12485.  2. On ~lime~ceiling ~yellow~(eye height)
  12486.  
  12487. ~lightGray~B|B|B|B|B|B|B    ~yellow~W I D T H
  12488. ~lightGray~B| | | | | |B               ~orange~L
  12489. ~lightGray~B| |B|B|B| |B               ~orange~E
  12490. ~lightGray~B| |B|B|B| |B               ~orange~N
  12491. ~lightGray~B| |B|B|B| |B               ~orange~G
  12492. ~lightGray~B|~red~^~lightGray~| | | | |B  ~red~^~lightGray~ = Turtle   ~orange~T
  12493. ~lightGray~B|~cyan~P~lightGray~|B|B|B|B|B  ~cyan~P~lightGray~ = Player   ~orange~H
  12494. ]] -- quick corridor system
  12495.     info.sub[17] =
  12496. [[~yellow~~yellow~Place me as below:
  12497.  1. On ~blue~floor   ~yellow~(feet height)
  12498.  2. On ~lime~ceiling ~yellow~(eye height)
  12499. ~lightGray~B|B|B|B|B|B|B
  12500. B| | | | | |B
  12501. B| |B|B|B| |B
  12502. B| |B|B|B| |B
  12503. B| |~lime~^~lightGray~|B|B| |B
  12504. B|~red~^~lightGray~|~magenta~^~lightGray~| | | |B ~white~^~lightGray~ = turtle
  12505. B|~cyan~P~lightGray~|B|B|B|B|B ~cyan~P~lightGray~ = Player
  12506. ~yellow~Note colour of ~white~^~yellow~ matches next screen->
  12507. ]] -- quick mine
  12508.         info.sub[18] =
  12509. [[~yellow~Place me level -59 / 5 on the floor to
  12510. expose bedrock ~red~(slow and inefficient)
  12511.  
  12512. ~lightGray~| | | |B| |B|     ~yellow~W I D T H
  12513. ~lightGray~|B| | | | | |B               ~orange~L
  12514. ~lightGray~| | | |B|B| |                ~orange~E
  12515. ~lightGray~| | |B| | |B|                ~orange~N
  12516. ~lightGray~|B| | | |B| |                ~orange~G
  12517. ~lightGray~| | | | | | |B               ~orange~T
  12518. ~lightGray~|~red~^~lightGray~| | | |B| |B  ~red~^~lightGray~ = Turtle   ~orange~H
  12519. ]] -- mine all blocks to bedrock pre 1.12
  12520.         info.sub[19] =
  12521. [[~yellow~Place me on the end wall of a disused
  12522. mine in the centre block, 1 block above
  12523. the floor.
  12524. Provide a ~cyan~diamond ~yellow~sword for
  12525. harvesting string from spider webs~lightGray~
  12526.  
  12527. ~gray~-------   - = Ceiling
  12528. ~lightGray~| | | |
  12529. | |~red~T~lightGray~| |  ~red~T = Turtle (facing wall)
  12530. ~lightGray~| | | |
  12531. ~gray~-------  - = Floor
  12532. ]] -- salvage mineshaft
  12533.     info.sub[21] =
  12534. [[~yellow~Place me as below.
  12535. ~brown~Chest ~yellow~ONLY required if ~blue~0 ~yellow~fuel
  12536.  
  12537. Plan view:
  12538.  
  12539. ~green~   | | | |
  12540. ~green~   | |~lime~T~green~| |  ~lime~T = Tree
  12541. ~green~   | |~red~^~green~| |  ~red~^ = Turtle
  12542. ~green~   | | | |
  12543.  
  12544.  
  12545.  
  12546. ]] -- Fell Tree
  12547.     info.sub[22] =
  12548. [[~yellow~New, extend left/back=~red~^ ~orange~Extend Right=^
  12549. ~lightGray~|*|~blue~ | | | | | | ~brown~|D| |D| ~blue~| | ~lightGray~|*|
  12550. ~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | | | | | | | ~lightGray~|*|
  12551. ~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | ~brown~|D| |D| ~blue~| | ~lightGray~|*|
  12552. ~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
  12553. ~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
  12554. ~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
  12555. ~lightGray~|~red~^~lightGray~|*|*|*|*|*|*~magenta~|M|~lightGray~*|*|*|*|*|*|~orange~^|
  12556. ~lime~4 ~brown~double trees~green~ or 16 ~brown~single trees
  12557. ~brown~D = Dirt, ~magenta~M = Modem
  12558. ~red~^~yellow~ = Turtle ~red~(new/left/back) ~orange~^ on right
  12559. ]] -- Create treefarm
  12560.     info.sub[23] =
  12561. [[~yellow~Place me on ground as below ~lightGray~^ ~magenta~^
  12562. ~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| |
  12563. ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | | | | | |
  12564. ~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | ~brown~|D| |D| |
  12565. ~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | |
  12566. ~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | |
  12567. ~lime~|*|*|*|*|~lightGray~^~lime~|*| ~magenta~|^| ~green~or |*|*|*|*|~lightGray~^~green~|*|*~magenta~|^|
  12568. ~lime~ 4 ~brown~double trees~green~   or  16 ~brown~single trees
  12569. ~brown~D = dirt
  12570. ~lightGray~^ = Turtle on marker (Legacy storage)
  12571. ~magenta~^ = Turtle on Modem (Network storage)
  12572. ]] -- Plant treefarm / Harvest treefarm
  12573.     info.sub[24] = info.sub[23]
  12574.     info.sub[25] =
  12575. [[~yellow~Place me at ~red~^
  12576.  
  12577. ~lightGray~|F|F|F|F|F|F|F| F = Fence or Wall
  12578. ~lightGray~|F|~brown~B~lime~| | | |~brown~B~lightGray~|F| ~brown~B = Barrel (corners)
  12579. ~lightGray~|F|~lime~ | | | | ~lightGray~|F|
  12580. ~lightGray~|F|~lime~ | | | |~cyan~T~lightGray~|F| ~cyan~T = Tree
  12581. ~lightGray~|F|~lime~ |~cyan~T~lime~| | | ~lightGray~|F|
  12582. ~lightGray~|F|~lime~ | | | | ~lightGray~|F|
  12583. ~lightGray~|F|~brown~B~lime~| |~cyan~T~lime~| |~brown~B~lightGray~|F|
  12584. ~lightGray~|~red~^~lightGray~|F|F|F|F|F|F| ~red~^ = Turtle
  12585. ~yellow~Fence/Wall follows land contours
  12586. ]] --
  12587.     info.sub[26] =
  12588. [[~yellow~A rectangular walled area of forest:
  12589. Place me at ~red~^
  12590.  
  12591. ~lightGray~|F|F|F|F|F|F|F| F = Fence or wall
  12592. ~lightGray~|F|~brown~B~lime~| | | |~brown~B~lightGray~|F| ~brown~B = Barrel (corners)
  12593. ~lightGray~|F|~lime~ | | | | ~lightGray~|F|
  12594. ~lightGray~|F|~lime~ | | | |~cyan~T~lightGray~|F| ~cyan~T = Tree
  12595. ~lightGray~|F|~lime~ |~cyan~T~lime~| | | ~lightGray~|F|
  12596. ~lightGray~|F|~lime~ | | | | ~lightGray~|F|
  12597. ~lightGray~|F|~red~^~lime~| |~cyan~T~lime~| |~brown~B~lightGray~|F| ~red~^ = Turtle ~brown~(on Barrel)
  12598. ~lightGray~|F|F|F|F|F|F|F|
  12599.  
  12600. ]] -- manage walled forest
  12601.     info.sub[31] =
  12602. [[~yellow~Place me on the ground as below ~red~^
  12603.  
  12604. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
  12605. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
  12606. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
  12607. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
  12608. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
  12609. ~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~brown~B = Barrel or Chest
  12610. ~brown~|B|~blue~W~green~| | |~lightGray~or ~magenta~|M|~blue~W~green~| | ~blue~W = Water
  12611. ~lime~|~red~^~lime~|~brown~B|B|~lightGray~*|or ~brown~|~red~^~brown~|~magenta~M|~lightGray~*| ~red~^ = Turtle
  12612. ~brown~Legacy   ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12
  12613. ]] -- Create modular crop farm
  12614.     info.sub[32] =
  12615. [[~yellow~Place on any ~brown~T ~blue~T ~magenta~T~yellow~ facing < > ^ v
  12616.  
  12617. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
  12618. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
  12619. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
  12620. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
  12621. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest
  12622. ~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~blue~W = Water
  12623. ~brown~|B~blue~|T| ~green~| |~lightGray~or ~magenta~|M|~blue~T~green~| | ~orange~S = Sapling or Tree
  12624. ~orange~|S|~brown~T|B|~lightGray~*|or ~brown~|B~magenta~|T|~lightGray~*| ~brown~T ~lightGray~= Turtle (~blue~T ~magenta~T~lightGray~)
  12625. ~brown~Legacy   ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12
  12626. ]] -- Extend farm
  12627.     info.sub[33] =
  12628. [[~yellow~Place as below ~blue~T~yellow~ facing < > ^ v
  12629.  
  12630. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
  12631. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
  12632. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
  12633. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
  12634. ~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest
  12635. ~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | C = Crop (first)
  12636. ~brown~|B|~blue~T~green~|C| |~lightGray~or ~magenta~|M|~blue~T~green~|C| ~orange~S = Sapling or Tree
  12637. ~orange~|S|~brown~B|B|~lightGray~*|or ~magenta~|M|~brown~B|~lightGray~*| ~blue~T = Turtle on Water
  12638. ~yellow~Options to harvest or manage to follow.
  12639. ]] -- Manual harvest and auto setup
  12640.     info.sub[34] =
  12641. [[~yellow~Build a ~brown~fence ~yellow~or ~lightGray~wall ~yellow~to chosen length.
  12642.  
  12643. Turtle goes ~orange~BACKWARDS ~yellow~when started.
  12644.  
  12645. Start: length = 6, Turtle facing right
  12646.  
  12647. ~lightGray~| |~red~>~lightGray~| | | | | | | ~red~> = Turtle
  12648.  
  12649. Finish:
  12650.  
  12651. ~lightGray~| |F|F|F|F|F|F| | F = Fence or Wall
  12652. ]] -- build fence or wall
  12653.     info.sub[35] =
  12654. [[~yellow~Build a ~brown~fence ~yellow~or ~lightGray~wall ~yellow~
  12655. rectangular area.
  12656.  
  12657. ~lightGray~| | | | | | | | ~brown~F = Fence or Wall
  12658. ~lightGray~| ~brown~|F|F|F|F|F~lightGray~| |
  12659. ~lightGray~| ~brown~|F| | | |F~lightGray~| |
  12660. ~lightGray~| ~brown~|F| | | |F~lightGray~| |
  12661. ~lightGray~| ~brown~|F| | | |F~lightGray~| |
  12662. ~lightGray~| |~red~^~brown~|F|F|F|F| | ~red~^ = Turtle
  12663. ~lightGray~| | | | | | | |
  12664.  
  12665. ]] -- build rectangular fence or wall
  12666.     info.sub[41] =
  12667. [[~yellow~Place me on any block on the left
  12668. side facing the obsidian field.
  12669.  
  12670. ~gray~|O|O|O|O|O| O = Obsidian
  12671. |O|O|O|O|O|
  12672. |O|O|O|O|O|
  12673. |O|O|O|O|O|
  12674. |~red~^~gray~|O|O|O|O| ~red~^ = Turtle
  12675. |~red~^~gray~| | | | |
  12676.  
  12677. ]] -- Harvest obsidian
  12678.     info.sub[42] =
  12679. [[~yellow~Place me on the ground as below ~red~> ~pink~^
  12680. ~yellow~Start ~red~> ~yellow~(facing right) or ~pink~^ ~yellow~ahead
  12681.  
  12682. ~lightGray~| |~red~>~lightGray~|O|O|*| | |    |*|O|O|*| face view            
  12683.    ~pink~^~lightGray~               |O|~purple~+ +~lightGray~|O|
  12684.                    |O|~purple~+ +~lightGray~|O|
  12685. ~yellow~Result (plan)      ~lightGray~|O|~purple~+ +~lightGray~|O|
  12686. ~lightGray~| |O|O|O|O| | |    |*|O|O|*|
  12687.                    ~green~--------- ground
  12688. ~yellow~width=4, ~orange~height=5 ~red~(frame size)
  12689. ]] -- build Nether portal
  12690.     info.sub[43] = info.sub[42] -- Demolish Nether portal
  12691.     info.sub[44] =
  12692. [[~yellow~Press F3+G for chunk boundaries
  12693. Netherite stripmine plan view
  12694.                
  12695. ~lightGray~|*|*|*~lime~N~lightGray~*|*|*|
  12696. ~lightGray~|*|*|*~lime~|~lightGray~*|*|*| ~lime~-| = Chunk Boundaries
  12697. ~lightGray~|*|~red~^~lightGray~|*~lime~|~lightGray~*|~red~^~lightGray~|*|  ~red~^ = Turtle
  12698. ~lime~W*-*-*~blue~+~lime~*-*-*E  ~blue~+ = Boundaries junction
  12699. ~lightGray~|*|*|*~lime~|~lightGray~*|*|*|
  12700. ~lightGray~|*|*|*~lime~|~lightGray~*|*|*|  ~yellow~North of WE
  12701. ~lightGray~|*|*|*~lime~S~lightGray~*|*|*|  ~yellow~1 block from NS
  12702. Most generate close to chunk boundaries
  12703. ]] -- Netherite stripping
  12704.     info.sub[45] =
  12705. [[~yellow~Place me on the ground ~red~<~yellow~ facing ~red~West.
  12706.  
  12707. ~lime~x
  12708.                  ~lightGray~N
  12709. ~lime~a~lightGray~   -1        | | | |  
  12710. ~lime~x~lightGray~    0       ~red~W~lightGray~| |~red~<~lightGray~| |E  ~red~< = Turtle
  12711. ~lime~i~lightGray~    1        | | | |  
  12712. ~lime~s~lightGray~                S
  12713.     ~green~z axis    ~lightGray~-1 0 1
  12714.  
  12715. Centre of the dragon arena ~lime~X = 0, ~green~Z = 0
  12716. ~yellow~                           facing ~red~West
  12717. ]] -- Find dragon tower centres
  12718.     info.sub[46] =
  12719. [[~yellow~Place turtle in ceiling facing endstone
  12720.  
  12721. Plan view    Side view
  12722. ~gray~             |*|*|*|*|*|
  12723.     |*|      |*|*|*|*|*|
  12724.   |*|*|*|    |*|*|*|*|*|
  12725. |*|*|*|*|*|  |*|*|*|*|*|  * ~lightGray~= Obsidian
  12726. ~gray~|*|*|~yellow~E~gray~|*|*|  |*|*|*|*|*|  ~yellow~E ~lightGray~= Endstone
  12727. ~gray~  |*|~red~^~gray~|*|    |*|*|~red~T~gray~|*|*|~red~ ^T ~lightGray~= Turtle
  12728. ~gray~    |*|      |*|*| |*|*|
  12729.              |*|*| |*|*|
  12730. ]] -- deactivate dragon tower
  12731.     info.sub[47] =
  12732. [[~yellow~Place turtle on the ground at 100,49,0
  12733.  
  12734. |*|*|*|*|*|*|*|*|*|   ~lightGray~= Dragon Island
  12735.  
  12736.  
  12737. ~yellow~    Facing WEST
  12738. ~gray~    |*|*|*|*|*|     * ~lightGray~= Obsidian plate
  12739. ~gray~    |*|*|*|*|*|
  12740. ~yellow~  S ~gray~|*|*|~red~T~gray~|*|*| ~yellow~N   ~red~T ~lightGray~= Turtle
  12741. ~gray~    |*|*|*|*|*|
  12742.     |*|*|*|*|*|
  12743. ~yellow~         E]] -- build dragon water trap
  12744.     info.sub[48] =
  12745. [[~yellow~Place turtle under end world portal
  12746.  
  12747. ~gray~        |B|     B ~lightGray~= Bedrock
  12748. ~gray~      |B|B|B|
  12749.         ~purple~|P|     P ~lightGray~= Portal
  12750. ~gray~      |B|B|B|
  12751.         |B|
  12752.          ~green~|      
  12753.          ~green~|      ~lime~Height measured first     
  12754.          ~green~|      
  12755. ~red~         T      T ~lightGray~= Turtle 
  12756. ~yellow~  |*|*|*|*|*|*| ~red~Inventory AFTER height
  12757. ]] -- build end portal minecart
  12758.    
  12759.     info.sub[491] =
  12760. [[~yellow~Place turtle <64 blocks from shulker
  12761. Directly below or 1 block in front
  12762. ~lightGray~|*|*|*|*|*|*|*|
  12763.      ~gray~> ~lime~S ~gray~<       > T < = kill positions
  12764.        ~gray~T
  12765.  
  12766.  
  12767.  
  12768.      ~red~> T <       Attacks ahead / above
  12769. ~lightGray~|*|*|*|*|*|*|*|
  12770.  
  12771. ~red~> T <~lightGray~ = Turtle   ~lime~S~lightGray~ = Shulker]] -- Shulker is above
  12772.  
  12773.     info.sub[492] =
  12774. [[~yellow~Place turtle <64 blocks from shulker
  12775. Same level, or 1 block above/below
  12776. Plan view:
  12777.    ~red~>~lightGray~ | | | | | |~lime~S~lightGray~|
  12778.  
  12779. ~yellow~Side view:
  12780.    ~red~T~lightGray~ | | | | | |~gray~T~lightGray~|
  12781.    ~red~T~lightGray~ | | | | |~gray~T~lightGray~|~lime~S~lightGray~|   ~gray~T = kill positions
  12782.    ~red~T~lightGray~ | | | | | |~gray~T~lightGray~|
  12783.    
  12784.  ~red~> T~lightGray~ = Turtle   ~lime~S~lightGray~ = Shulker]] -- Shulker is ahead
  12785.    
  12786.     info.sub[493] =
  12787. [[~yellow~Place turtle <64 blocks from shulker
  12788. Directly above or 1 block in front
  12789. ~lightGray~|*|*|*|*|*|*|*|
  12790.      ~red~> T <       Attacks ahead / below
  12791.  
  12792.  
  12793.  
  12794.        ~gray~T
  12795.      ~gray~> ~lime~S ~gray~<       > T < = kill positions
  12796. ~lightGray~|*|*|*|*|*|*|*|
  12797.  
  12798. ~red~> T <~lightGray~ = Turtle   ~lime~S~lightGray~ = Shulker]] -- Shulker is below
  12799.  
  12800.     info.sub[494] =
  12801. [[~yellow~Place turtle in entry pit centre wall
  12802.  
  12803. ~lightGray~|*|~orange~+~lightGray~| | |~red~+~lightGray~| | |~lime~S~lightGray~|*| ~lime~S~lightGray~ = Shulker
  12804. ~lightGray~|*|~orange~+~lightGray~| |~lime~S|~red~+~lightGray~| | |~blue~+~lightGray~|*| T = turtle places
  12805. ~lightGray~|*|~orange~+~lightGray~| | |~red~+~lightGray~| | |~blue~+~lightGray~|*|
  12806. ~lightGray~|*|~orange~+~lightGray~| | |~red~+~lightGray~| | |~blue~+~lightGray~|*|     ~yellow~Plan view
  12807. ~lightGray~|*|~orange~+|+|+|~red~+|~blue~+|+|+~lightGray~|*|    |*|*|*|*|*|
  12808. ~lightGray~|*|*|*|~orange~+|~red~+|~blue~+~lightGray~|*|*|*|    |*| |~red~T~lightGray~| |*|
  12809. ~lightGray~|*|*|*|~orange~T|~red~T|~blue~T~lightGray~|*|*|*|    |*|~orange~T~lightGray~| |~blue~T~lightGray~|*|
  12810. ~lightGray~|*|*|*| | | |*|*|*|    |*| |~red~T~lightGray~| |*|
  12811.                        |*|*|*|*|*|]] -- Climb tower wall
  12812.  
  12813.     info.sub[495] =
  12814. [[~yellow~Place turtle in corner against ceiling
  12815. Face ~red~direction ~yellow~shown. It will exit up,
  12816. clear the roof above and return
  12817.  
  12818. ~lightGray~|*|*|*|*|*|*|*|*|*|*|  ~yellow~Clears 15x15
  12819. ~lightGray~|*|~red~<~lightGray~| | | | | | |~red~^~lightGray~|*|  ~yellow~area regardless
  12820. ~lightGray~|*| | | | | | | | |*|  ~yellow~of actual size
  12821.  
  12822. ~lightGray~|*| | | | | | | | |*|
  12823. ~lightGray~|*|~red~V~lightGray~| | | | | | |~red~>~lightGray~|*|
  12824. ~lightGray~|*|*|*|*|*|*|*|*|*|*|]] -- Clear roof above
  12825.  
  12826.     info.sub[496] =
  12827. [[~yellow~Place turtle in corner against ceiling
  12828. Face ~red~direction ~yellow~shown. It will exit out,
  12829. clear 4 outside walls and return.
  12830.  
  12831. ~lightGray~|*|*|*|*|*|*|*|*|*|*|  ~yellow~Size calculated
  12832. ~lightGray~|*|~red~<~lightGray~| | | | | | |~red~^~lightGray~|*|  ~yellow~automatically.
  12833. ~lightGray~|*| | | | | | | | |*|
  12834.  
  12835. ~lightGray~|*| | | | | | | | |*|
  12836. ~lightGray~|*|~red~V~lightGray~| | | | | | |~red~>~lightGray~|*|
  12837. ~lightGray~|*|*|*|*|*|*|*|*|*|*|]] -- Clear outside wall
  12838.  
  12839.     info.sub[51] =
  12840. [[~yellow~Place me on the ground as below ~red~^
  12841.  
  12842. ~yellow~Start:~blue~  |-|-|-|    - = air/water
  12843. ~orange~        |-|-|-|    - = lava
  12844. ~blue~        |-|-|-|
  12845. ~lightGray~        |*|~red~^~lightGray~|*|    ~red~^ = Turtle
  12846.  
  12847. ~yellow~Result:~blue~ |-|~lightGray~*|~blue~-|    - = air/water
  12848. ~orange~        |-|~lightGray~*|~orange~-|    - = lava
  12849. ~blue~        |-|~lightGray~*|~blue~-|
  12850. ~lightGray~        |*|*|*|    * = Solid block
  12851. ]] -- Single path
  12852.     info.sub[52] =
  12853. [[~yellow~Place ~red~^ T~yellow~ at start of path or tunnel
  12854.  
  12855. ~yellow~Plan view    Face view
  12856.  
  12857. ~lightGray~|*|~green~*~lightGray~|*|      *|*|*|*|*   ~green~* = new block
  12858. ~lightGray~|*|~green~*~lightGray~|*|      *|*|~green~*~lightGray~|*|*
  12859. ~lightGray~|*|~green~*~lightGray~|*|      *|*| |*|*
  12860. ~lightGray~|*|~green~*~lightGray~|*|      *|*|~red~T~lightGray~|*|*   ~red~^ T = Turtle
  12861.    ~red~^~lightGray~         ~green~- - * - -   ground
  12862.  
  12863. ~green~Floor + ceiling ~yellow~placed for your safety!
  12864. ]] -- Covered walkway / tunnel
  12865.     info.sub[53] =
  12866. [[~yellow~plan view
  12867.  
  12868. ~lightGray~|*|~blue~-|-~lightGray~|*|
  12869. ~lightGray~|*|~blue~-|-~lightGray~|*|    ~yellow~Cross section view
  12870. ~lightGray~|*|~blue~-|-~lightGray~|*|     ~lime~1 ~orange~2 ~brown~3 ~green~4  ~lightGray~= on ground
  12871. ~lightGray~|~lime~^~lightGray~|~blue~^~lightGray~|~cyan~^~lightGray~|~green~^~lightGray~|    |*|~blue~5~lightGray~|~cyan~6~lightGray~|*| ~lightGray~= in water
  12872.  
  12873. ~yellow~New canal       ~lime~1 ~orange~2 ~brown~3 ~green~4 ~yellow~ground level-63
  12874. ~yellow~Extend existing ~lime~1     ~green~4 ~yellow~ground level-63
  12875. ~yellow~Extend existing   ~blue~5 ~cyan~6   ~yellow~water  level-62
  12876. ]] -- new/existing canal
  12877.     info.sub[54] =
  12878. [[~lime~New ~yellow~ice canal or ~lightBlue~convert ~yellow~existing water
  12879.  
  12880. ~lightGray~ |*| | |*|    * = Slab
  12881. ~lightGray~ |~orange~T~lightGray~|~blue~I~lightGray~| |*|    ~blue~I = Ice (packed or blue)
  12882. ~lightGray~ |*| | |*|   | | = Air (empty block)
  12883. ~lightGray~ |*|~blue~I~lightGray~| |~orange~T~lightGray~|   ~orange~T = Torch (optional)
  12884. ~lime~  1 2 3 4    New ice canal
  12885. ~lightBlue~  5 6 7 8    Convert water canal
  12886.  
  12887. ~red~All turtles placed at ground level!
  12888. ~lime~1-4 ~lightGray~for ~lime~new ~lightGray~canal ~lightBlue~5-8 ~lightGray~to ~lightBlue~convert ~lightGray~water
  12889. ]] -- ice canal
  12890.     info.sub[55] =
  12891. [[~yellow~Place ~red~^~yellow~ any level air, water or lava.~lightGray~
  12892.  
  12893. | | | | | | | |
  12894. | |*|*|*|*|*| |  * = Block
  12895. | |*|*|*|*|*| |
  12896. | |*|*|*|*|*| |
  12897. | |*|*|*|*|*| |
  12898. | |~red~^~lightGray~|*|*|*|*| |  ~red~^ = Turtle~lightGray~
  12899. | | | | | | | |
  12900.  
  12901. Blocks placed under the turtle
  12902. ]] -- Platform
  12903.     info.sub[56] =
  12904. [[~yellow~Place ~red~^~yellow~ above water.~lightGray~
  12905. Existing platform replaced below
  12906.  
  12907. | |*|*|*|*|*| |  * = Block
  12908. | |*|*|*|*|*| |
  12909. | |*|*|*|*|*| |
  12910. | |*|*|*|*|*| |
  12911. | |~red~^~lightGray~|*|*|*|*| |  ~red~^ = Turtle~lightGray~
  12912. | | | | | | | |
  12913.  
  12914. Blocks placed under the turtle
  12915. ]] -- Sinking platform
  12916.     info.sub[57] =
  12917. [[~yellow~Boat Lift (Ice or Water)
  12918. Place turtle left side. ~blue~Source~yellow~ to right
  12919.  
  12920. Start~lightGray~        |*|~blue~ | ~lightGray~|*| ~yellow~Finish
  12921. ~lightGray~             |*|~blue~ | ~lightGray~|*|
  12922.              |*|~cyan~S|S|~lightGray~*| ~cyan~S ~lightGray~= Soul sand
  12923. |*|*|*|*|    |*|~brown~S|S~lightGray~|*| ~brown~S = ~lightGray~Sand + gate
  12924. |~red~^~lightGray~|~blue~W|W~lightGray~|*|    |*~blue~|W|W|~lightGray~*| ~red~^ ~lightGray~= Turtle
  12925. |*|~blue~W|W~lightGray~|*|    |*|~blue~W|W~lightGray~|*|
  12926. |*|~blue~ | ~lightGray~|*|    |*|~blue~ | ~lightGray~|*| ~yellow~Ice canal needs
  12927. ~lightGray~|*|~blue~ | ~lightGray~|*|    |*|~blue~ | ~lightGray~|*| ~yellow~2x2 water source
  12928. ]] -- boat bubble lift
  12929.     info.sub[61] =
  12930. [[~red~NOT ~yellow~for Blaze spawners!
  12931. Plan view          Side view~lightGray~
  12932.     T       T      T = Outside dungeon
  12933.  |*|*|*|*|*|*|*|   |*|~brown~1~lightGray~|*|*|*|~yellow~2~lightGray~|*| Top
  12934. T|*| | | | | |*|T  |*| | | | | |*|
  12935.  |*| | |~magenta~5~lightGray~| | |*|   |*| | |~magenta~5~lightGray~| | |*|
  12936.  |*| |~magenta~5~lightGray~|~orange~S~lightGray~|~magenta~5~lightGray~| |*|   |*|~lime~3~lightGray~|~magenta~5|~orange~S~lightGray~|~magenta~5|~green~4~lightGray~|*| Base
  12937.  |*| | |~magenta~5~lightGray~| | |*|
  12938. T|*| | | | | |*|T  * = Dungeon Wall
  12939.  |*|*|*|*|*|*|*|   ~orange~S = Spawner
  12940. ~lightGray~    T       T      T = Turtle ~brown~1 ~yellow~2 ~lime~3 ~green~4
  12941. ~magenta~5~lightGray~ = On top or adjacent (0 chests only)
  12942. ]] -- 9x9 cube round spawner
  12943.     info.sub[62] =
  12944. [[~yellow~Place turtle as indicated:
  12945. Plan view          Side view
  12946.  
  12947. ~lightGray~|*|*|*|*|*|*|*|*|  ~lime~> T = Continue build
  12948. ~lightGray~|*| | | | | | | |  ~red~< T = New build
  12949. ~lightGray~|*| | | | | | | |
  12950. |*| | | |~purple~S~lightGray~| | | |~lime~>~red~<          T
  12951. ~lightGray~|*| | | | | | | |   |*| | | |~purple~S~lightGray~| | | |~red~T
  12952. ~lightGray~|*| | | | | | | |   |*| | | | | | | |
  12953. ~lightGray~|*| | | | | | | |   |*| | | | | | | |
  12954. ~lightGray~|*|*|*|*|*|*|*|*|   |*| | | | | | | |~lime~T
  12955.                                      ~red~T]] -- 9x9 cube round blaze spawner
  12956.     info.sub[63] =
  12957. [[~yellow~ Plan view (truncated)    Side view
  12958.  
  12959. ~lightGray~ |*| | | | | | | | | |*|  |*| | | | | |
  12960. ~red~>~lightGray~|*| | | | |~purple~S~lightGray~| | | | |*|~red~<~lightGray~ |*| | | | |~purple~S~lightGray~|
  12961.  |*| | | | | | | | | |*|  |*| | | | | |
  12962.  |*| | | | | | | | | |*|  |*| | | | | |
  12963.  |*| | | | | | | | | |*|  |*| | | | | |
  12964.  |*| | | | | | | | | |*|  |*| | | | | |
  12965.  |*|*|*|*|*|*|*|*|*|*|*| ~red~T~lightGray~|*|*|*|*|*|*|
  12966.             ~red~^
  12967. ~purple~S ~lightGray~= Spawner ~red~<> ^ T ~lightGray~= Turtle
  12968. ]] -- Flood spawner chamber
  12969.     info.sub[64] =
  12970. [[~yellow~Bubble lift: Plan view at start~lightGray~
  12971.  |*| | | | | | | | | |*|
  12972.  |*| | | | |~brown~F~lightGray~| | | | |*|
  12973.  |*|*|*|*|*|~brown~F~lightGray~|*|*|*|*|*|  ~brown~F ~lightGray~= Fence
  12974.            ~brown~|~red~^~brown~|~lightGray~= Turtle on ~brown~Soul Sand
  12975.            
  12976. ~yellow~Plan view completed~lightGray~         
  12977.  |*| | | | |~brown~F~lightGray~| | | | |*|
  12978.  |*|*|*|*|*|~brown~F~lightGray~|*|*|*|*|*|  ~brown~F ~lightGray~= Fence
  12979. ~yellow~kill zone~lightGray~|*|~blue~S~lightGray~|*|~yellow~kill zone ~lightGray~Left / Right
  12980.            ~lightGray~|*|        ~blue~S ~lightGray~= Bubble lift
  12981. ]] -- Build bubble tower kill zone
  12982.     info.sub[65] =
  12983. [[~yellow~Computercraft mob grinder
  12984.  
  12985. Plan view~lightGray~ |*~blue~| | | | | | | | | |~lightGray~*|
  12986.           |*~blue~| | | | | | | | | |~lightGray~*|
  12987.           |*|*|*|*|*~blue~| |~lightGray~*|*|*|*|*| Front
  12988. ~red~T~yellow~urtle facing out    ~red~V~lightGray~              
  12989.                          
  12990. ~yellow~Side view ~lightGray~|*|*|*|*|*|*|*|*|*|*|*|
  12991.           |*|*|*|*|*|*|*|*|*|*|*|
  12992.           |*|*|*|*|*|*|*|*|*|*|*|
  12993. ~red~E~yellow~xit hole ~lightGray~|*|*|*|*|*|~red~T~lightGray~|*|*|*|*|*|
  12994.           ~gray~|*|*|*|*|*|*|*|*|*|*|*| Base
  12995. ]] -- Computercraft mob grinder
  12996.     info.sub[66] =
  12997. [[This is a 3 stage process:
  12998. 1.New tower lower base: place me on
  12999. flat ground in open plain.
  13000.  
  13001. 2.Upper base: place me in front of
  13002. the existing chest at tower base.
  13003.  
  13004. 3.Main tower, only needed to respawn
  13005. mobs. Expensive, not recommended.
  13006. Place me in front of chest in ground.
  13007. ]] -- Build endermen observation tower
  13008.     info.sub[67] =
  13009. [[Turtle moves toward spawner
  13010. Place at spawner level.
  13011.  
  13012. Can be behind a wall for protection
  13013. of player.
  13014.  
  13015. Embeds in wall with attack working
  13016.  
  13017. Needs 24 blocks
  13018.  
  13019. ]] -- Build 3*3*3 wall around trial spawner
  13020.  
  13021.     info.sub[71] =
  13022. [[~yellow~Clear field
  13023.  
  13024. ~lightGray~| | | | | |  Remove ~lime~trees ~lightGray~and ~pink~flowers
  13025. ~lightGray~| | | | | |  Fill ~gray~holes
  13026. ~lightGray~| | | | | |  Remove blocks > ground
  13027. | | | | | |
  13028. | | | | | |
  13029. |~red~^~lightGray~| | | | |  ~red~^ ~lightGray~= Turtle position
  13030.  
  13031. ~yellow~Optional use ~brown~dirt ~yellow~as surface
  13032.  
  13033. ]] -- Clear field
  13034.     info.sub[72] =
  13035. [[~yellow~Clear rectangle
  13036.  
  13037. ~lightGray~| | | | | |  Remove all blocks
  13038. ~lightGray~| | | | | |  Optional dig ~lime~up
  13039. ~lightGray~| | | | | |  Optional dig ~blue~down
  13040. ~lightGray~| | | | | |
  13041. | | | | | |
  13042. |~red~^~lightGray~| | | | |  ~red~^ ~lightGray~= Turtle position
  13043.  ~red~^
  13044.  
  13045. ~yellow~Can be used to clear 3 layers at a time
  13046.  
  13047. ]] -- Clear rectangle
  13048.  
  13049.     info.sub[73] =
  13050. [[~yellow~Clear wall
  13051. Plan view         Side view
  13052.                   ~gray~T ~lightBlue~T
  13053. ~red~>~lightGray~|~orange~>~lightGray~|*|*|*|*|*|    ~cyan~T~lightGray~|~blue~T~lightGray~|*|*|*|*|*| Top
  13054. ~lightGray~                   |*|*|*|*|*|*|
  13055.                    |*|*|*|*|*|*|
  13056.                    |*|*|*|*|*|*|
  13057.                    |*|*|*|*|*|*|
  13058.                   ~lime~T~lightGray~|~green~T~lightGray~|*|*|*|*|*| Base
  13059.                  
  13060. T = Turtle top / bottom/ inside / out
  13061. ~yellow~Bottom to top or top to bottom
  13062. ]] -- Clear wall
  13063.     info.sub[74] =
  13064. [[~yellow~Clear rectangle ~red~perimeter only
  13065.  
  13066. ~yellow~Plan view
  13067. ~lightGray~| | | | | |  Remove all blocks
  13068. ~lightGray~| |*|*|*| |  Optional dig ~lime~up
  13069. ~lightGray~| |*|*|*| |  Optional dig ~blue~down
  13070. ~lightGray~| |*|*|*| |
  13071. | |*|*|*| |
  13072. |~red~^~lightGray~| | | | |  ~red~^ ~lightGray~= Turtle position
  13073. ~red~ ^
  13074. ~yellow~Can be used to clear 3 layers at a time
  13075.  
  13076. ]] -- Clear rectangle (perimeter only)
  13077.     info.sub[75] =
  13078. [[~yellow~Demolish cube structure
  13079. Plan view        Side view
  13080.                ~gray~T ~lightBlue~T
  13081. ~lightGray~|*|*|*|*|*|*|  ~cyan~T~lightGray~|~blue~T~lightGray~|*|*|*|*|*|
  13082. |*|*|*|*|*|*|   |*|*|*|*|*|*|
  13083. |*|*|*|*|*|*|   |*|*|*|*|*|*|
  13084. |*|*|*|*|*|*|   |*|*|*|*|*|*|
  13085. |*|*|*|*|*|*|   |*|*|*|*|*|*|
  13086. |~lime~^~lightGray~|*|*|*|*|*|  ~lime~T~lightGray~|~green~T~lightGray~|*|*|*|*|*|
  13087.  ~green~^
  13088. ~lightGray~^ T = Turtle (top/base in/out)
  13089. ]] -- Clear structure floor/walls/ceiling hollow and solid
  13090.     info.sub[76] = info.sub[75]
  13091.     info.sub[77] =
  13092. [[~yellow~Dig a trench (Plan view)
  13093.  
  13094. ~lightGray~      |~red~>~lightGray~| | | | | | |
  13095.  
  13096. | |    ~red~>~lightGray~ = Turtle
  13097. | |    
  13098. | |
  13099. | |
  13100. | |    
  13101. |~red~^~lightGray~|    ~red~^~lightGray~ = Turtle
  13102. ]] -- Dig a trench
  13103.     info.sub[78] =
  13104. [[~yellow~Mountain carving     ~red~T ^ = Turtle
  13105. ~yellow~Side view            Plan view
  13106.  
  13107. ~lightGray~        |*|              |*|*|      ~yellow~L
  13108. ~gray~      |*~lightGray~|*|            ~gray~|*~lightGray~|*|*|*|    ~yellow~E
  13109. ~gray~      |*~lightGray~|*|*|*|      ~gray~|*|*~lightGray~|*|*|*|*|  ~yellow~N
  13110. ~gray~      |*~lightGray~|*|*|*|      ~gray~|*|*~lightGray~|*|*|*|*|  ~yellow~G
  13111. ~gray~      |*~lightGray~|*|*|*|       ~red~^~gray~|*~lightGray~|*|*|*|    ~yellow~T
  13112. ~gray~    |*|*~lightGray~|*|*|*|*|        |*|*|      ~yellow~H
  13113.    ~red~T~gray~|*|*~lightGray~|*|*|*|*|
  13114.     ~yellow~<--> no. of rows <-->
  13115. ]] -- Carve mountain
  13116.     info.sub[79] =
  13117. [[~yellow~Place / Replace floor or ceiling
  13118.  
  13119. Plan view      Side view
  13120. ~lightGray~| | | | | |    |*|*|*|*|*|
  13121. | | | | | |     T          Ceiling
  13122. | | | | | |
  13123. | | | | | |
  13124. | | | | | |     T          Floor
  13125. |~red~^~lightGray~| | | | |    |*|*|*|*|*|
  13126.  
  13127. ~red~^ ~lightGray~T = Turtle position
  13128.  
  13129. ]] -- (Re)place floor or ceiling
  13130.     info.sub[710] =
  13131. [[~yellow~Place me anywhere!
  13132. Menu or direct command interface.
  13133.  
  13134. ~lightGray~Commands:
  13135.  
  13136. direction + ~blue~number ~yellow~eg ~white~f2 ~yellow~= forward ~blue~2
  13137.  
  13138. ~yellow~f = forward  ~orange~b = backward
  13139. ~lime~l = left     ~red~r = right
  13140. ~lightGray~u = up       ~cyan~d = down
  13141.  
  13142. ]] -- Direct control
  13143.     info.sub[81] =
  13144. [[~blue~1.Drop sand or gravel wall
  13145.   ~yellow~Place me on water/lava surface
  13146.  
  13147. ~lightBlue~2.Fill area with sand
  13148.   ~yellow~Place  on left corner of area
  13149.  
  13150. ~yellow~3.Clear ~blue~(1) sand wall
  13151.   ~yellow~Place me on the surface of sand.
  13152.  
  13153. ~yellow~4.Clear ~lightBlue~(2) sand filled area
  13154.   ~yellow~Place on left corner of sand field
  13155. ]] -- Sand based utilities
  13156.     info.sub[82] =
  13157. [[~yellow~Turtle position ~red~> T ~gray~(~red~V ~gray~to enclose)
  13158. ~yellow~Plan view                      ~gray~Start:~red~V
  13159. ~blue~|~red~>~blue~| | | | | | ~yellow~to ~lightGray~|*|*|*|*|*|~red~V~lightGray~|~gray~ enclose
  13160.                             ~gray~*  area
  13161. ~yellow~Side view
  13162.  ~red~T
  13163. ~blue~| | | | | | | ~yellow~to ~lightGray~|*|*|*|*|*|*|
  13164. ~blue~| | | | | | |    ~lightGray~|*|*|*|*|*|*|
  13165. ~blue~| | | | | | |    ~lightGray~|*|*|*|*|*|*|
  13166. ~yellow~|S|~blue~ | | |~yellow~S|S|    |S|~lightGray~*|*|*|~yellow~S|S|
  13167. ~yellow~|S|S|S|S|S|S|    |S|S|S|S|S|S|
  13168. ]] -- build wall from water or lava surface downwards  
  13169.     info.sub[83] =
  13170. [[~yellow~Build a walled rectangle
  13171.  
  13172.  
  13173. ~yellow~L ~lightGray~|*|*|*|*|*|*|
  13174. ~yellow~e ~lightGray~|*| | | | |*|
  13175. ~yellow~n ~lightGray~|*| | | | |*|
  13176. ~yellow~g ~lightGray~|*| | | | |*|
  13177. ~yellow~t ~lightGray~|*|*|*|*|*|*|
  13178. ~yellow~h  ~red~^
  13179. ~yellow~   W i d t h      ~red~^ ~lightGray~= Turtle
  13180.  
  13181.  
  13182. ]] -- Create enclosed area
  13183.     info.sub[84] =
  13184. [[~yellow~Clear volume of water
  13185.  
  13186. Plan view
  13187. ~lightGray~|*|*|*|*|*|*|*|*|  * = Stone
  13188. |*|*~blue~| | |~lightGray~*|*~blue~| |~lightGray~*|  ~blue~| ~lightGray~= Water
  13189. |*~blue~| | | | | | |~lightGray~*|
  13190. |*~blue~| | | | | | |~lightGray~*|
  13191. |*~blue~| | | | | | |~lightGray~*|
  13192. |*~blue~| | | | | |~lightGray~*|*|
  13193. |*|~red~^~lightGray~|*~blue~| | | | |~lightGray~*|  ~red~^ ~lightGray~= Turtle
  13194. |*|*|*|*|*|*|*|*|  ~yellow~Width~blue~: ~yellow~6, ~orange~length~blue~:~orange~ 6
  13195.  
  13196. ]] -- Clear volume of water
  13197.     info.sub[85] = info.sub[56] -- Sinking platform
  13198.     info.sub[861] =
  13199. [[~yellow~Turtle placement  ~red~V~lime~ < ^ > ~yellow~over monument
  13200.  
  13201. ~red~******    ******  * ~lightGray~= Avoid this area
  13202. ~red~******    ******  V do not face front
  13203. ******    ******  ~lime~< ^ > ~lightGray~Ideal facing~lightGray~
  13204. ******    ******
  13205. ~green~******~lime~++++~green~******  ~lime~+ ~lightGray~= Ideal position~green~
  13206. ******~lime~++++~green~******  ~green~* ~lightGray~= Good position
  13207. ~green~****************
  13208. ****************  Or any corner < 12
  13209. ****************  blocks from edge
  13210. ]]-- Ocean monument 85 subChoice 1: 4 corner pillars
  13211.  
  13212.     info.sub[862] =
  13213. [[~yellow~Turtle positions ~red~> ^ < V
  13214.  
  13215. ~lightGray~|*|~red~>~lightGray~|*|*|*|*|*|~red~<~lightGray~|*|  ~red~NOT ~lightGray~corner blocks!
  13216. |~red~V~lightGray~|             |~red~V~lightGray~|
  13217. |*|             |*|
  13218. |*|             |*|
  13219. |*|             |*|
  13220. |*|             |*|
  13221. |*|             |*|  ~yellow~Fill inventory~lightGray~
  13222. |~red~^~lightGray~|             |~red~^~lightGray~|  ~yellow~with stone.~lightGray~
  13223. |*|~red~>~lightGray~|*|*|*|*|*|~red~<~lightGray~|*|  ~yellow~Add when asked
  13224. ]] -- Ocean monument build retaining walls
  13225.  
  13226.     info.sub[863] =
  13227. [[~yellow~Turtle ~red~> < ~yellow~on side walls only
  13228.  
  13229. ~lightGray~|*|*|*|*|*|*|*|*|*|*|
  13230. ~lightGray~|~red~>~cyan~| *****   ***** |~red~<~lightGray~|
  13231. ~lightGray~|~red~>~cyan~| *****   ***** |~red~<~lightGray~|
  13232. ~lightGray~|~red~>~cyan~| *****   ***** |~red~<~lightGray~|
  13233. ~lightGray~|~red~>~cyan~| *****+++***** |~red~<~lightGray~|
  13234. ~lightGray~|~red~>~cyan~| *****+++***** |~red~<~lightGray~|
  13235. ~lightGray~|~red~>~cyan~| ************* |~red~<~lightGray~|
  13236. ~lightGray~|~red~>~cyan~| ************* |~red~<~lightGray~|
  13237. |*|*|*|*|*|*|*|*|*|*|
  13238. ]] -- clear plants before sand draining
  13239.     info.sub[864] = info.sub[863]
  13240.     info.sub[865] = info.sub[863]
  13241.     info.sub[866] = info.sub[56]
  13242.     info.sub[867] =
  13243. [[~yellow~Turtle positions ~red~> ^ < V
  13244. ~green~|*|*|*|*|*~brown~|*|*|*|~red~V~brown~|*|
  13245. ~green~|~red~>~green~|- - - - ~brown~- - - -|*|
  13246. ~green~|*|- - - - ~brown~- - - -|*| ~lightGray~1 Turtle removes
  13247. ~green~|*|- - - - ~brown~- - - -|*| ~lightGray~1 coloured area
  13248. ~green~|*|- - - - ~brown~- - - -|*|
  13249. ~orange~|*|- - - - ~lime~- - - -|*| ~lightGray~6 chests / area
  13250. ~orange~|*|- - - - ~lime~- - - -|*| ~lightGray~Follow turtle
  13251. ~orange~|*|- - - - ~lime~- - - -|*|
  13252. ~orange~|*|- - - - ~lime~- - - -|~red~<~lime~| ~lightGray~30,000 fuel each!
  13253. ~orange~|*|~red~^~orange~|*|*|*~lime~|*|*|*|*|*| ~lightGray~3,000 stone each!
  13254. ]] -- Ocean monument drain and remove 1 of 4 quarters
  13255.     info.sub[87] =
  13256. [[~yellow~Ladder to water / lava: Plan view
  13257.  
  13258.  ~blue~- ~red~- ~blue~- ~red~- ~blue~- ~red~- ~blue~-    ~blue~- ~red~- ~blue~- ~red~- ~blue~- ~red~- ~blue~-
  13259.  ~red~- ~blue~- ~red~- ~blue~- ~red~- ~blue~- ~red~-    ~red~- ~blue~- ~red~-~lightGray~|*|- ~blue~- ~red~-
  13260.  ~blue~- ~red~- ~blue~- ~red~- ~blue~- ~red~- ~blue~-    ~blue~- ~red~-~lightGray~|*|~brown~L~lightGray~|*|~red~- ~blue~- ~~lightGray~
  13261. |*|*|*|~red~^~lightGray~|*|*|*|  |*|*|*|*|*|*|*|
  13262. |*|*|*|*|*|*|*|  |*|*|*|*|*|*|*|
  13263. |*|*|*|*|*|*|*|  |*|*|*|*|*|*|*|
  13264.  
  13265. ~red~^ ~lightGray~= Turtle facing water / lava
  13266. ~brown~L ~lightGray~= Ladder
  13267.  
  13268. ]] -- Ladder to water/lava 
  13269.     info.sub[88] =
  13270. [[~yellow~Place ~red~T~yellow~urtle at water edge.
  13271. Returns max ~blue~d~yellow~epth. ~yellow~Water ~green~p~yellow~lants~yellow~ removed
  13272.  
  13273.    ~red~T                       T
  13274. ~lightGray~|*|*| ~blue~| | | | | | | | | | ~lightGray~|*|
  13275. |*|*| ~blue~| | | | | | | | | ~lightGray~|*|*|
  13276. |*|*| ~blue~| | | | | | | ~lightGray~|*|*|*|*|
  13277. |*|*|*| ~blue~| | |~green~p~blue~| | ~lightGray~|*|*|*|*|*|
  13278. |*|*|*| ~blue~| | |~green~p~lightGray~|*|*|*|*|*|*|*|
  13279. |*|*|*|*~blue~|d~lightGray~|*|*|*|*|*|*|*|*|*|
  13280. |*|*|*|*|*|*|*|*|*|*|*|*|*|*|
  13281. ]] -- Clear water plants from enclosed area
  13282.     info.sub[89] =
  13283. [[Place me on the left corner of the top
  13284. of retaining wall facing water
  13285. ]] -- Convert all water to source
  13286.     info.sub[810] =
  13287. [[Place me on the left corner of the top
  13288. of retaining wall facing water.
  13289. The source blocks are placed ahead to
  13290. selected length
  13291. ]] -- Create sloping water
  13292.  
  13293. -- Building and railway
  13294.     info.sub[91] =
  13295. [[~yellow~Build a wall
  13296.  
  13297. Plan view        Side view
  13298.  
  13299. ~red~>~lightGray~| | | | | | |   |*|*|*|*|*|*|
  13300.                  |*|*|*|*|*|*|
  13301.                  |*|*|*|*|*|*|
  13302.                  |*|*|*|*|*|*|
  13303.                 ~red~T~lightGray~|~red~T~lightGray~|*|*|*|*|*|
  13304.  
  13305. ~red~> T~lightGray~ = Turtle
  13306.                  
  13307. ]] -- Build a wall
  13308.     info.sub[92] =
  13309. [[~yellow~Build a walled rectangle / house
  13310.  
  13311. Plan view         Side view
  13312.  
  13313. ~yellow~L ~lightGray~|*|*|*|*|*|*|   |*|*|*|*|*|*|
  13314. ~yellow~e ~lightGray~|*| | | | |*|   |*|*|*|*|*|*|
  13315. ~yellow~n ~lightGray~|*| | | | |*|   |*|*|*|*|*|*|
  13316. ~yellow~g ~lightGray~|*| | | | |*|   |*|*|*|*|*|*|
  13317. ~yellow~t ~lightGray~|~red~^~lightGray~|*|*|*|*|*|  ~red~T~lightGray~|~red~T~lightGray~|*|*|*|*|*|
  13318. ~yellow~h  ~red~^
  13319. ~yellow~   W i d t h      ~red~^ T ~lightGray~= Turtle
  13320.  
  13321. ]] -- Build a rectangular structure
  13322.     info.sub[93] =
  13323. [[~yellow~Build a gable roof
  13324. Gable built on right side of turtle
  13325. Plan view       End view (width)
  13326.                      ~gray~+      gable top
  13327. ~yellow~L ~lightGray~|*|*|*|*|*|      ~gray~+ + +    gable end
  13328. ~yellow~e ~lightGray~|*| | | |*|    ~red~T~gray~ + + + +  gable end
  13329. ~yellow~n ~lightGray~|*| | | |*|   |*|*|*|*|*| top of wall
  13330. ~yellow~g ~lightGray~|*| | | |*|   |*|*|*|*|*|
  13331. ~yellow~t ~lightGray~|*| | | |*|   |*|*|*|*|*|
  13332. ~yellow~h ~lightGray~|~red~^~lightGray~|*|*|*|*|   |*|*|*|*|*|
  13333. ~yellow~  W i d t h     W i d t h   ~red~^T ~lightGray~= Turtle
  13334. ]] -- Build a gable end roof
  13335.     info.sub[94] =
  13336. [[~yellow~Build a pitched roof
  13337. Width ~red~MUST ~yellow~be ~red~<= ~yellow~Length eg ~red~4~yellow~ x 6
  13338. Plan view        End view (width)
  13339.  
  13340.                   ~red~T ~lightGray~on top of building
  13341. ~yellow~L ~lightGray~|*|*|*|*|      |*|*|*|*|
  13342. ~yellow~e ~lightGray~|*| | |*|      |*|*|*|*|
  13343. ~yellow~n ~lightGray~|*| | |*|      |*|*|*|*|
  13344. ~yellow~g ~lightGray~|*| | |*|      |*|*|*|*|
  13345. ~yellow~t ~lightGray~|*| | |*|
  13346. ~yellow~h ~lightGray~|~red~^~lightGray~|*|*|*|
  13347. ~yellow~  W i d t h     ~red~^ T ~lightGray~= Turtle
  13348. ]]-- Build a pitched roof
  13349.     info.sub[95] =
  13350. [[~yellow~Place me on suspended railway stone
  13351. Redstone torch will go below me
  13352.  
  13353. ~lightGray~_____
  13354. ~lightGray~|*|*|\                           ~red~>~lightGray~|*|
  13355.     |*|~red~<                       ~lightGray~/|*|
  13356.       ~lightGray~|*|______~red~T~lightGray~_________    /~lightGray~|*|~red~!
  13357.        ~red~!~lightGray~|*|*|*|*|*|*|*|*|\ /|*|
  13358.                ~red~!        ~lightGray~|*|*|
  13359.  
  13360. ~red~T < > ~lightGray~= Turtle ~red~! ~lightGray~= Redstone Torch
  13361. On block or above rail, face up slope
  13362. ]] -- Place redstone torch under block
  13363.     info.sub[96] = info.sub[95]
  13364.     info.sub[97] =
  13365. [[~yellow~Place me on last block before up/down
  13366.  
  13367. Build down            Build up~lightGray~
  13368.  
  13369. _____~red~T~lightGray~                        ___
  13370. |*|*|*|_                     _|*|
  13371.       |*|_                 _|*|
  13372.         |*|_             _|*|
  13373.           |*|__________~red~T~lightGray~|*|
  13374.             |*|*|*|*|*|*|      
  13375. ~red~T~lightGray~ = Turtle on block, not above rail
  13376. ]] -- build down
  13377.     info.sub[98] =  info.sub[97]
  13378.  
  13379. --Measurement tools
  13380.     info.sub[101] =
  13381. [[~yellow~Place me on floor.~lightGray~
  13382.             Measured Height:
  13383. |~lightBlue~*~lightGray~|*|*|*|   ~lightBlue~7. Overhead obstruction
  13384.             ~cyan~7. ~red~NOT ~cyan~detect() ~gray~7. Change~lightGray~
  13385.   |*|*|*|
  13386.   |*|*|*|
  13387.   |~lime~S~lightGray~|*|*|   ~lime~4. Specific block found~lightGray~
  13388.   |*|*|*|
  13389.   |*|*|*|
  13390.   |*|*|*|
  13391.  ~red~T~lightGray~|*|*|~red~T~lightGray~|   ~red~T~lightGray~ = Turtle
  13392. ]] -- measure height
  13393.     info.sub[102] =
  13394. [[~yellow~Depth measurement
  13395. Place me on the floor above pit / edge
  13396.  
  13397.     ~red~T~lightGray~
  13398. 1|*|*|
  13399. 2|*|*|
  13400. 3|*|*|
  13401. 4|*|*|         Measured depth:
  13402. 5|*|~lime~S~lightGray~|         ~lime~5. Specific block found
  13403. ~lightGray~6              ~cyan~6. ~red~NOT ~cyan~turtle.detect()~lightGray~
  13404. 7|*|*|~lightBlue~*~lightGray~|*| |   ~lightBlue~6. Obstruction below
  13405. ]] -- measure depth
  13406.     info.sub[103] =
  13407. [[~yellow~Length measurement
  13408.  
  13409. ~lightGray~1 2 3 4 ~lime~5~lightGray~ 6 ~lime~7 ~cyan~8 ~lightBlue~9~lightGray~ 10
  13410.                       ~cyan~8. No block up
  13411. ~lightGray~*|*|*|*|*|*|~lime~S~lightGray~| |*|*|  ~lime~7. Search block
  13412. ~red~T~lightGray~                |*|  ~lightBlue~9. Obstruction
  13413. ~lightGray~*|*|*|*|~lime~S~lightGray~|*|*| |*|*|  ~lime~5. Search block
  13414.                       ~cyan~8. No block down
  13415.  
  13416. ~red~T ~lightGray~= Turtle
  13417.  
  13418. ]] -- measure length
  13419.     info.sub[104] = info.sub[88] -- measure deepest section of water
  13420.     info.sub[105] =
  13421. [[~yellow~Place turtle anywhere:
  13422.  
  13423.  1. make a ~blue~borehole~yellow~ to chosen level.
  13424.  
  13425.  2. Write a report called:
  13426.  
  13427.  3. ~lime~borehole~blue~X~lime~.txt ~yellow~( ~blue~X ~yellow~= computer ID )
  13428.  
  13429.  4. ~orange~Return home
  13430.  
  13431. ]] -- Borehole: Analyse blocks below
  13432.     info.sub[110] =
  13433. [[~yellow~How many turtles?:
  13434.  
  13435. ~yellow~1.~lightGray~ Alternative positions for ~lime~2 ~lightGray~turtles
  13436. ~lightGray~| |~lime~1~lightGray~|~lime~2~lightGray~| |  |~lime~1~lightGray~| | |~lime~2~lightGray~| | | | | | ground 2
  13437. ~lightGray~|*|~blue~W|W~lightGray~|*|  |*|~blue~W|W~lightGray~|*| |*|~blue~1~lightGray~|~blue~2~lightGray~|*| water  2
  13438.  
  13439. ~yellow~2.~lightGray~ Alternative positions for ~orange~4 ~lightGray~turtles
  13440. ~lightGray~|~orange~1~lightGray~|~orange~2~lightGray~|~orange~3~lightGray~|~orange~4~lightGray~|                      ground 4
  13441. ~lightGray~|*|~blue~W|W~lightGray~|*|                      water  0
  13442.  
  13443. ~yellow~Enter 1 to use ~lime~2 ~yellow~turtles or 2 to use ~orange~4]]  -- initial menu for water canal
  13444.     local line = menu.clear()
  13445.     if menuLevel == 1 then -- general help
  13446.         line = menu.colourText(line, info.main[menuItem], true, true)
  13447.         term.write("Enter to continue ")
  13448.         read()
  13449.         return ""
  13450.     else -- item specific help
  13451.         if info.sub[menuItem] ~= nil then -- help file exists
  13452.             line = menu.colourText(line, info.sub[menuItem], true, true)
  13453.             if noMenu then
  13454.                
  13455.  
  13456.                 if getInteger then
  13457.                     return line -- ready for further input
  13458.                 else
  13459.                     term.setCursorPos(1, 13)
  13460.                     menu.enterToContinue()
  13461.                 end
  13462.             else
  13463.                 term.setCursorPos(1, 13)
  13464.                 term.write("Enter=exit, Any key + Enter=more ")
  13465.                 return read()
  13466.             end
  13467.         end
  13468.     end
  13469. end
  13470.  
  13471. local function getTaskOptions()
  13472.     local options = {}
  13473.     options.main =
  13474.     {
  13475.         "Mining (includes Nether)",
  13476.         "Forestry",
  13477.         "Farming",
  13478.         "Obsidian, Nether & End",
  13479.         "Canal, bridge and walkway",
  13480.         "Spawner farm tools",
  13481.         "Area shaping and clearing",
  13482.         "Lava and Water",
  13483.         "Building and minecart",
  13484.         "Measuring tools",
  13485.         "Network Tools"
  13486.     }
  13487.     table.insert(options,
  13488.     {
  13489.         "Ladder up or down",
  13490.         "Stairs up or down",
  13491.         "Create mine at this level",
  13492.         "Safe drop to water block",
  13493.         "Single column bubble lift",
  13494.         "QuickMine corridor system",
  13495.         "QuickMine rectangle",
  13496.         "Mine bedrock level",
  13497.         "Rob disused mineshaft"
  13498.     })
  13499.     table.insert(options,
  13500.     {
  13501.         "Fell Tree",
  13502.         "Create extend or convert tree farm",
  13503.         "Plant tree farm",
  13504.         "Harvest tree farm",
  13505.         "Fence or wall a forest",
  13506.         "Harvest and replant forest"
  13507.     })
  13508.     table.insert(options,
  13509.     {
  13510.         "Create modular crop farm",
  13511.         "Extend modular crop farm",
  13512.         "Manage farm:plant,harvest,convert",
  13513.         "Build a wall or fence",
  13514.         "Fence or wall an enclosure"
  13515.     }) 
  13516.     table.insert(options,                  
  13517.     {
  13518.         "Dig obsidian field",
  13519.         "Build Nether Portal",
  13520.         "Demolish Nether Portal",
  13521.         "Stripmine Netherite",
  13522.         "Undermine Dragon Towers",
  13523.         "Deactivate Dragon Tower",
  13524.         "Build dragon water trap",
  13525.         "Build portal ladder & platform",
  13526.         "Shulker harvester"
  13527.     })
  13528.     table.insert(options,
  13529.     {
  13530.         "Simple path on air, water or lava",
  13531.         "Covered path or tunnel",
  13532.         "Water canal (mulitple options)",
  13533.         "Ice canal (multiple options)",
  13534.         "Platform",
  13535.         "Sinking platform",
  13536.         "Boat bubble lift",
  13537.     })
  13538.     table.insert(options,
  13539.     {
  13540.         "Cube around spawner (NOT blaze)",
  13541.         "Cube around Blaze spawner",
  13542.         "Flood mob farm floor",
  13543.         "Create mob bubble lift",
  13544.         "Computercraft mob grinder",
  13545.         "Build Endermen observation tower",
  13546.         "Surround trial spawner"
  13547.     })
  13548.     table.insert(options,
  13549.     {
  13550.         "Clear field (inc trees)",
  13551.         "Clear a rectangle (+ u/d opt)",
  13552.         "Clear single wall up/down",
  13553.         "Clear rectangular wall section",
  13554.         "Clear hollow structure up/down",
  13555.         "Clear solid structure up/down",
  13556.         "Dig a trench",
  13557.         "Carve mountain side",
  13558.         "Place a floor or ceiling",
  13559.         "Direct control of movement"
  13560.     })
  13561.     table.insert(options,
  13562.     {
  13563.         "Sand based utilities",
  13564.         "Vertical wall from surface",
  13565.         "Create enclosed area",
  13566.         "Clear volume of water",
  13567.         "Sinking platform",
  13568.         "Ocean monument utilities",
  13569.         "Ladder down to water/lava",
  13570.         "Clear water plants",
  13571.         "Convert all water to source",
  13572.         "Create sloping water"
  13573.     })
  13574.     table.insert(options,
  13575.     {
  13576.         "Build a wall",
  13577.         "Build a walled area / house",
  13578.         "Build a gable end roof",
  13579.         "Build a pitched roof",
  13580.         "Place Redstone:torch level track",
  13581.         "Place Redstone:torch upward track",
  13582.         "Build downward track",
  13583.         "Build upward track"
  13584.     })
  13585.     table.insert(options,
  13586.     {
  13587.         "Measure height",
  13588.         "Measure depth",
  13589.         "Measure length",
  13590.         "Measure greatest depth",
  13591.         "Borehole: Analyse blocks below"
  13592.     })
  13593.     table.insert(options,
  13594.     {
  13595.         "Craft an item",
  13596.         "Mystical Agriculture Essence tools"
  13597.     })
  13598.    
  13599.     return options
  13600. end
  13601.  
  13602. local function getTaskColours()
  13603.     local options = {}
  13604.     options.main =
  13605.     {
  13606.         colors.lightGray,   -- Mining (includes Nether)
  13607.         colors.lime,        -- Forestry
  13608.         colors.green,       -- Farming
  13609.         colors.red,         -- Obsidian, Nether & End Portal
  13610.         colors.brown,       -- Canal, bridge and walkway
  13611.         colors.lightGray,   -- Mob farm tools
  13612.         colors.orange,      -- Area shaping and clearing
  13613.         colors.blue,        -- Lava and Water
  13614.         colors.cyan,        -- Railway
  13615.         colors.purple,      -- Measuring tools
  13616.         colors.pink         -- Network tools
  13617.     }
  13618.     table.insert(options,
  13619.     {
  13620.         colors.brown,       -- Ladder up or down
  13621.         colors.lightGray,   -- Stairs up or down
  13622.         colors.lightGray,   -- Create mine at this level
  13623.         colors.blue,        -- Safe drop to water block
  13624.         colors.blue,        -- Single column bubble lift
  13625.         colors.magenta,     -- QuickMine corridor system
  13626.         colors.pink,        -- QuickMine rectangle
  13627.         colors.gray,        -- Mine bedrock level
  13628.         colors.brown        -- Rob disused mineshaft
  13629.     })
  13630.     table.insert(options,
  13631.     {
  13632.         colors.brown,       -- Fell Tree
  13633.         colors.lightGray,   -- Create tree farm
  13634.         colors.lime,        -- Plant tree farm
  13635.         colors.green,       -- Harvest tree farm
  13636.         colors.brown,       -- Fence or wall an enclosure
  13637.         colors.lime         -- Harvest and replant forest
  13638.     })
  13639.     table.insert(options,
  13640.     {
  13641.         colors.yellow,      -- Create modular crop farm
  13642.         colors.green,       -- Extend modular crop farm
  13643.         colors.lime,        -- Manage modular crop farm
  13644.         colors.brown,       -- Build wall or fence
  13645.         colors.brown        -- Build rectangle wall or fence
  13646.     }) 
  13647.     table.insert(options,                  
  13648.     {
  13649.         colors.lightGray,   -- Dig obsidian field
  13650.         colors.purple,      -- Build Nether Portal
  13651.         colors.gray,        -- Demolish Nether Portal
  13652.         colors.red,         -- Netherite stripping
  13653.         colors.orange,      -- Undermine Dragon Towers
  13654.         colors.orange,      -- Deactivate Dragon Tower
  13655.         colors.blue,        -- Build dragon water trap
  13656.         colors.lightGray,   -- Build portal minecart station
  13657.         colors.red          -- Shulker harvesting
  13658.     })
  13659.     table.insert(options,
  13660.     {
  13661.         colors.lightGray,   -- Continuous path
  13662.         colors.gray,        -- Covered walkway / tunnel
  13663.         colors.blue,        -- Water canal
  13664.         colors.lightBlue,   -- Ice canal (4 options)
  13665.         colors.brown,       -- Platform
  13666.         colors.blue,        -- Sinking platform for oceans
  13667.         colors.cyan         -- Boat bubble lift
  13668.     })
  13669.     table.insert(options,
  13670.     {
  13671.         colors.brown,       -- Cube around spawner (NOT blaze)
  13672.         colors.red,         -- Cube around Blaze spawner
  13673.         colors.cyan,        -- Flood mob farm floor
  13674.         colors.blue,        -- Create mob bubble lift
  13675.         colors.brown,       -- Dig mob drop trench
  13676.         colors.gray,        -- Build Endermen observation tower
  13677.         colors.orange       -- Surround trial spawner
  13678.     })
  13679.     table.insert(options,
  13680.     {
  13681.         colors.lime,        -- Clear field (inc trees)
  13682.         colors.magenta,     -- Clear a rectangle (+ u/d opt)
  13683.         colors.pink,        -- Clear single wall up/down
  13684.         colors.purple,      -- Clear rectangular wall section
  13685.         colors.brown,       -- Clear hollow structure up/down
  13686.         colors.orange,      -- Clear solid structure up/down
  13687.         colors.brown,       -- Dig a trench
  13688.         colors.gray,        -- Carve mountain side
  13689.         colors.lightBlue,   -- Place a floor or ceiling
  13690.         colors.red          -- Direct control of movement
  13691.     })
  13692.     table.insert(options,
  13693.     {
  13694.         colors.yellow,      -- Sand based utilities
  13695.         colors.blue,        -- Vertical wall from surface
  13696.         colors.blue,        -- Create enclosed area
  13697.         colors.cyan,        -- Clear volume of water
  13698.         colors.lightGray,   -- Sinking platform
  13699.         colors.orange,      -- Ocean monument utilities
  13700.         colors.brown,       -- Ladder down to water/lava
  13701.         colors.green,       -- Clear water plants
  13702.         colors.lightBlue,   -- Convert all water to source
  13703.         colors.blue         -- Create sloping water
  13704.     })
  13705.     table.insert(options,
  13706.     {
  13707.         colors.yellow,      -- build a wall
  13708.         colors.orange,      -- build rectangular structure
  13709.         colors.lightGray,   -- gable end roof
  13710.         colors.gray,        -- pitched roof
  13711.         colors.red,         -- Place Redstone:torch level track
  13712.         colors.red,         -- Place Redstone:torch upward track
  13713.         colors.orange,      -- Build downward track
  13714.         colors.brown        -- Build upward track
  13715.     })
  13716.     table.insert(options,
  13717.     {
  13718.         colors.red,         -- Measure height
  13719.         colors.purple,      -- Measure depth
  13720.         colors.magenta,     -- Measure length
  13721.         colors.pink,        -- Measure greatest depth
  13722.         colors.lightBlue    -- Borehole: Analyse blocks below
  13723.     })
  13724.     table.insert(options,
  13725.     {
  13726.         colors.red,         -- Craft item
  13727.         colors.magenta,     -- MysticalAgriculture
  13728.     })
  13729.     return options
  13730. end
  13731.  
  13732. local function chooseTask(R)
  13733. --[[
  13734.     called from main()
  13735.     R = chooseTask(R)
  13736.     coloured menu: 
  13737.     local pp =
  13738.     {
  13739.         prompt = colors.green,
  13740.         itemColours = {colors.white, colors.red, ... one for each item},
  13741.         menuPrompt = colors.yellow
  13742.     }
  13743.     choice, modifier = menu.menu or menu.new("Choose your option", options, pp)
  13744.     ]]
  13745.     local lib = {}
  13746.    
  13747.     function lib.getHelp(choice, itemsRequired, pp)
  13748.         local listOfItems = itemsRequired[choice]
  13749.         local result = getTaskHelp(2, choice)
  13750.         if result ~= "" then -- any key + enter = more
  13751.             lib.showItems(listOfItems)
  13752.         end
  13753.         T:clear()
  13754.         pp.itemColours = {colors.green, colors.yellow, colors.orange, colors.red}
  13755.         local options ={"Continue with selected task", "return to menu", "Return to main menu","Quit application"}
  13756.         local option = menu.menu("Choose your option", options, pp, "Type number + Enter ")
  13757.         if option == 2 then
  13758.             choice = -2 -- return to subMenu
  13759.         elseif option == 3 then
  13760.             choice = 0 -- return to main menu
  13761.         elseif option == 4 then
  13762.             choice = -1 -- quit
  13763.         -- else return original value of choice
  13764.         end
  13765.        
  13766.         return choice -- if R.choice reset to 0, then re-starts, -1 == quit
  13767.     end
  13768.    
  13769.     function lib.showItems(listOfItems)
  13770.         T:clear()
  13771.         if next(listOfItems) ~= nil then
  13772.             menu.colourPrint("Items required:", colors.lime)
  13773.             for k,v in pairs(listOfItems) do
  13774.                 menu.colourPrint("  "..v, colors.lightGray)
  13775.             end
  13776.         else
  13777.             menu.colourPrint("No items required", colors.lime)
  13778.         end
  13779.         menu.colourWrite("Enter to continue", colors.yellow, colors.black, nil, true)
  13780.         read()
  13781.     end
  13782.    
  13783.     function lib.getItemList(subChoice, itemsRequired)
  13784.         local listOfItems = itemsRequired[subChoice]
  13785.         lib.showItems(listOfItems)
  13786.     end
  13787.    
  13788.     function lib.getChoice(choice, subChoice)
  13789.         if subChoice > 9 then -- need more than 9 sub-options
  13790.             choice = subChoice + (choice * 100) -- 10 = 10 + 1000 = 1100
  13791.         else -- eg main option 1 (mining), sub-option 1 (create mine) = 1 + 10 = 11
  13792.             choice = subChoice + (choice * 10) -- 9 = 9 + 9 * 10 = 99, 1 + 10*10 = 101
  13793.         end
  13794.         return choice
  13795.     end
  13796.    
  13797.     local modifier = ""
  13798.     local subChoice = 0
  13799.     local prompt = "Choose an option"
  13800.     local mainPrompt = "Choose option (+h = help eg 3h):"
  13801.     local subPrompt = "Choose (+h = help +i = items eg 3h):"
  13802.     local options = getTaskOptions()
  13803.     local menuColours = getTaskColours()
  13804.     local itemsRequired = getTaskItemsList()
  13805.     local menuState = 0 -- use main menu
  13806.     -- local pp = utils.getPrettyPrint(colors.cyan, colors.magenta) -- specify menu title and prompt colours
  13807.     --local pp = utils.getPrettyPrint()-- uses default colours
  13808.    
  13809.     while menuState >= 0 do -- menuState has to be -1 to exit loop
  13810.         --[[
  13811.         menu returns choice=nil if user enters just q or h
  13812.         menu returns choice=2, modifier = "h" if 2h entered
  13813.         Mining (includes Nether)        white
  13814.         Forestry                        lime
  13815.         Farming                         lime
  13816.         Obsidian, Nether & End Portal   brown
  13817.         Canal, bridge and walkway       pink   
  13818.         Mob farm tools                  gray
  13819.         Area shaping and clearing       purple 
  13820.         Lava and Water                  blue
  13821.         Railway                         magenta
  13822.         Measuring tools                 cyan       
  13823.         ]]
  13824.        
  13825.         if menuState == 0 then
  13826.             pp.itemColours = menuColours.main
  13827.             local mainChoice, modifier = menu.menu(mainPrompt, options.main, pp) -- open main menu options
  13828.             if modifier == "q" then
  13829.                 R.choice = -1
  13830.                 return R -- quit application
  13831.             elseif modifier == "h" then -- get help on main menu items
  13832.                 getTaskHelp(1, mainChoice) -- "" or any return string for more
  13833.                 R.choice = 0
  13834.                 return R -- quit task system so it re-starts as help menu chosen R.choice = 0
  13835.             else
  13836.                 menuState = 1 -- next level so use sub-menu
  13837.                 R.choice = mainChoice -- 1-11
  13838.             end
  13839.         else
  13840.             pp.prompt = colors.yellow
  13841.             pp.itemColours = menuColours[R.choice]
  13842.             subChoice, modifier = menu.menu(subPrompt, options[R.choice], pp, "Back = 'q' or number + Enter: ") -- open submenu options
  13843.             if modifier == "q" then
  13844.                 R.choice = 0    -- return to root menu. change this to -1 if quit application preferred
  13845.                 return R -- quit task system so it re-starts first menu
  13846.             elseif modifier == "i" then -- get list of items
  13847.                 local index = lib.getChoice(R.choice, subChoice)
  13848.                 lib.getItemList(index, itemsRequired) -- list of items shown
  13849.                 subChoice = nil -- allow menu to continue
  13850.             elseif modifier == "h" then -- get help on main menu items
  13851.                 local index = lib.getChoice(R.choice, subChoice)
  13852.                 index = lib.getHelp(index, itemsRequired, pp)
  13853.                 --R = lib.getHelp(R, itemsRequired, pp) -- if R.choice reset to 0 then will continue
  13854.                 if index == -2 then -- redraw sub-menu
  13855.                     subChoice = nil -- allow menu to continue
  13856.                 elseif index == -1 then -- if R.choice reset to 0 then will continue
  13857.                     R.choice = -1
  13858.                     return R
  13859.                 elseif index == 0 then
  13860.                     R.choice = 0
  13861.                     menuState = 0 -- if R.choice reset to 0 then back to main menu
  13862.                 end
  13863.             end
  13864.             if subChoice ~= nil then
  13865.                 R.choice = lib.getChoice(R.choice, subChoice)
  13866.                 return R -- exit loop
  13867.             end
  13868.         end
  13869.     end
  13870.     return R
  13871. end
  13872.  
  13873. local function getTask(R)
  13874.     --[[
  13875.     Called from main(): R = getTask(R)
  13876.     local R =
  13877.         {
  13878.             choice = 0,
  13879.             subChoice = 0,
  13880.             size = 0,
  13881.             width = 0,
  13882.             length = 0,
  13883.             height = 0,
  13884.             depth = 0,
  13885.             up = false,
  13886.             down = false,
  13887.             silent = false,
  13888.             data = {},
  13889.             torchInterval = 0,
  13890.             useBlockType = "",
  13891.             auto = false,
  13892.             side = "",
  13893.             direction = "",
  13894.             mysticalAgriculture = false
  13895.         }
  13896.     ]]
  13897.     local lib = {}
  13898.    
  13899.     function lib.isAutoHelp(choice, noAutoHelp)
  13900.         for _, v in ipairs(noAutoHelp) do
  13901.             if choice == v then
  13902.                 return true
  13903.             end
  13904.         end
  13905.         return false
  13906.     end
  13907.    
  13908.     function lib.isMysticalAgriculture(R)
  13909.         if menu.getBoolean("Mystical Agriculture modded? (y/n)", nil, colors.brown) then
  13910.             R.mysticalAgriculture = true
  13911.         end
  13912.         return R
  13913.     end
  13914.    
  13915.     local prompt = "Choose an option"
  13916.     local noAutoHelp = {23, 24, 47, 49, 53, 54, 81, 85}
  13917.     if not lib.isAutoHelp(R.choice, noAutoHelp) then -- exclude Water canal, ice canal, sand utilities, monument utilities, dragon trap
  13918.         getTaskHelp(2, R.choice, true)
  13919.         menu.clear()
  13920.     end
  13921. -- 01. MINING
  13922.     if R.choice >= 11 and  R.choice <= 13 then  -- createLadder, createStaircase, createMine)
  13923.         --getTaskHelp(2, R.choice, true)
  13924.         --menu.clear()
  13925.     elseif R.choice == 14 then  -- safe drop to water
  13926.         local currentLevel = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.lightGray)
  13927.         local destLevel = menu.getInteger("Go down to level? ("..currentLevel - 2 .." to "..bedrock + 5 ..")", bedrock + 5 , currentLevel - 2, nil, colors.blue, nil, bedrock + 5)
  13928.         R.height    = math.abs(destLevel - currentLevel)
  13929.     elseif R.choice == 15 then  -- bubble lift
  13930.         local currentLevel = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5 , ceiling, nil, colors.blue, nil, bedrock + 5)
  13931.         local destLevel = menu.getInteger("Go up to level? ("..currentLevel + 2 .." to "..ceiling ..") ", currentLevel + 2, ceiling, nil, colors.lightGray)
  13932.         --[[if currentLevel <= bedrock + 5 then
  13933.             if menu.getBoolean("Confirm close to bedrock (y / n) ", nil, colors.yellow, colors.black) then
  13934.                 R.data = "bedrock"
  13935.             end
  13936.         end]]
  13937.         R.height    = math.abs(destLevel - currentLevel)
  13938.     elseif R.choice == 16 then -- create mining corridor system default: square 17 x 17
  13939.         local choices = {"At corridor start, on the floor",
  13940.                          "At corridor start, on the ceiling",
  13941.                          "On floor, move forward to start",
  13942.                          "On ceiling, move forward to start"}
  13943.         pp.itemColours = {colors.lime, colors.green, colors.magenta, colors.pink}
  13944.         local userChoice, modifier = menu.menu("Starting position?", choices, pp, "Type number + Enter ") -- 1 to 4
  13945.         if modifier == "q" then -- quit chosen
  13946.             R.data = "quit"
  13947.             return R
  13948.         end
  13949.         R.width     = menu.getInteger("Width (2-64 default 17) ", 2, 64, nil, colors.yellow, nil, 17)
  13950.         R.length    = menu.getInteger("Length (2-64 default 17) ", 2, 64, nil, colors.orange, nil, 17)
  13951.         R.torchInterval = 9 -- 8 spaces between torches
  13952.         if mcMajorVersion >= 1.18 then
  13953.             R.torchInterval = 17 -- 16 spaces between torches
  13954.         end
  13955.         R.subChoice = userChoice
  13956.     elseif R.choice == 17 then -- clear a rectangle, fill empty spaces above
  13957.         local choices = {"At mine area start, on the floor",
  13958.                          "At mine area start, on the ceiling",
  13959.                          "On floor, move forward to start",
  13960.                          "On ceiling, move forward to start",
  13961.                          "On floor diagonally to left"} -- just finished corridor
  13962.         pp.itemColours = {colors.lime, colors.green, colors.magenta, colors.pink, colors.red}
  13963.         local userChoice, modifier = menu.menu("Starting position?", choices, pp, "Type number + Enter ") -- 1 to 4
  13964.         if modifier == "q" then -- quit chosen
  13965.             R.data = "quit"
  13966.             return R
  13967.         end
  13968.         R.width     = menu.getInteger("Width (2-64 default 15) ", 2, 64, nil, colors.yellow, nil, 15)
  13969.         R.length    = menu.getInteger("Length (2-64 default 15) ", 2, 64, nil, colors.orange, nil, 15)
  13970.         R.subChoice = userChoice
  13971.     elseif R.choice == 18 then -- Mine bedrock area
  13972.         --getTaskHelp(2, R.choice, true)
  13973.         --menu.clear()
  13974.         R.width     = menu.getInteger("Width (2-64 default 17) ", 2, 64, nil, colors.yellow, nil,  17)
  13975.         R.length    = menu.getInteger("Length (2-64 default 17) ", 2, 64, nil, colors.orange, nil,  17)
  13976.         if menu.getBoolean("Leave bedrock exposed? (y/n) ", nil, colors.yellow) then
  13977.             R.data = "leaveExposed"
  13978.         end
  13979.     elseif R.choice == 19 then -- salvage mine shaft
  13980.         R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
  13981. -- 02. FORESTRY
  13982.     elseif R.choice == 22 then --Create treefarm
  13983.         R.width = 15
  13984.         R.length = 15
  13985.         pp.itemColours = {colors.lightGray, colors.green, colors.orange, colors.yellow, colors.gray, colors.lightGray}
  13986.         choices = {"New tree farm. Starting here", "On left side of existing farm <-",
  13987.                     "On right side of existing farm ->", "On back left of existing farm ^",
  13988.                     "Convert legacy with storage", "Convert Legacy without storage"}
  13989.         local choice = menu.menu(prompt, choices, pp, "Type number + Enter ")
  13990.         if choice == 1 then
  13991.             R.data = "new"
  13992.         elseif choice == 2 then
  13993.             R.data = "left"
  13994.         elseif choice == 3 then
  13995.             R.data = "right"
  13996.         elseif choice == 4 then
  13997.             R.data = "back"
  13998.         elseif choice == 5 then
  13999.             R.data = "convertStorage"
  14000.         elseif choice == 6 then
  14001.             R.data = "convert"
  14002.         end
  14003.         R.networkFarm = true
  14004.         --R.networkFarm =  menu.getBoolean({"Automate this farm with network","storage and modem? (y/n)"}, nil, {colors.yellow, colors.orange}, colors.black)
  14005.         if R.data ~= "convert" and R.data ~= "convertStorage" then
  14006.             R.up = menu.getBoolean({"Any blocks/trees above current level","in a 15 x 15 block area (y/n) "}, nil, {colors.yellow, colors.orange}, colors.black)
  14007.         end
  14008.     elseif R.choice == 23 then -- plant treefarm
  14009.         R = utils.assessTreeFarm(R) -- sets network and sapling type
  14010.         if R.message ~= "" then
  14011.             return {R.message}  -- location error
  14012.         end
  14013.         if R.networkFarm then
  14014.             if R.logType == "mangrove" then
  14015.                 R.subChoice = 3 -- mangrove
  14016.             elseif R.logType == "spruce" or R.logType == "dark_oak" then
  14017.                 R.subChoice = 2 -- double trees
  14018.             else
  14019.                 R.subChoice = 1 -- single trees
  14020.             end
  14021.         else
  14022.             local choices   = {"16 x oak, birch, acacia, cherry", "4 double spruce, dark oak, jungle"}
  14023.             pp.itemColours = {colors.lime, colors.green}
  14024.             R.subChoice = menu.menu(prompt, choices, pp, "Type number + Enter ")
  14025.         end
  14026.     elseif R.choice == 24 then -- Harvest treefarm
  14027.         R = utils.assessTreeFarm(R) -- sets network and sapling type
  14028.         if R.message ~= "" then
  14029.             return {R.message}  -- location error
  14030.         end
  14031.     elseif R.choice == 25 then -- Build wall or fence
  14032.         R.width     = menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow)
  14033.         R.length    = menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange)
  14034.         R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
  14035.         if menu.getBoolean("Storage barrels in corners? (y/n)", nil, colors.brown) then
  14036.             R.data = "barrel"
  14037.         end
  14038.     elseif R.choice == 26 then -- Harvest and replant natural forest
  14039.  
  14040.        
  14041. -- 03. FARMING
  14042.     elseif R.choice == 31 then -- new crop farm
  14043.         --R = lib.isMysticalAgriculture(R)
  14044.         local choices   = {"Use local storage", "Use modem network storage"}
  14045.         pp.itemColours = {colors.lime, colors.green}
  14046.         local choice = menu.menu(prompt, choices, pp, "Type number + Enter ")
  14047.         if choice == 2 then
  14048.             R.networkFarm = true
  14049.         end
  14050.     elseif R.choice == 32 then -- extend crop farm
  14051.         R = utils.assessFarm(R)-- sets R.networkFarm and R.mysticalAgriculture
  14052.         local choices   = {"Add a farm at the back", "Add a farm to the right"}
  14053.         pp.itemColours = {colors.lime, colors.green}
  14054.         R.subChoice = menu.menu(prompt, choices, pp, "Type number + Enter ")
  14055.     elseif R.choice == 33 then -- manage crop farm
  14056.         R = utils.checkFarmPosition(R)
  14057.         --R = utils.assessFarm(R)-- sets R.networkFarm and R.mysticalAgriculture
  14058.     elseif R.choice == 34 then -- fence or wall
  14059.         R.length    = menu.getInteger("Length of wall / fence (1-256)", 1, 256, nil, colors.orange)
  14060.         R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
  14061.     elseif R.choice == 35 then -- rectangle fence or wall
  14062.         R.width     = menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow)
  14063.         R.length    = menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange)
  14064.         R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
  14065.    
  14066. -- 04. OBSIDIAN
  14067.     elseif R.choice == 41 then  -- Harvest obsidian
  14068.         R.width     = menu.getInteger("Width of the area (1-64) ", 1, 64, nil, colors.yellow)
  14069.         R.length    = menu.getInteger("Length of the area (1-64) ", 1, 64, nil, colors.orange)
  14070.     elseif R.choice == 42 or R.choice == 43 then -- build Nether portal / demolish Nether portal
  14071.         local choices = {"Facing portal: forward, turn right",
  14072.                          "Aligned with portal: start ahead"}
  14073.         pp.itemColours = {colors.pink, colors.red}
  14074.         local userChoice, modifier = menu.menu("Starting position?", choices, pp, "Type number + Enter ") -- 1 to 2
  14075.         R.subChoice = userChoice
  14076.         if modifier == "q" then -- quit chosen
  14077.             R.data = "quit"
  14078.             return R
  14079.         end
  14080.         R.length    = menu.getInteger("Portal width", 1, 64, nil, colors.yellow, nil, 4)
  14081.         R.height    = menu.getInteger("Portal height (inc. buried base)", 1, 64, nil, colors.lightGray, nil, 5)
  14082.         R.width     = menu.getInteger("Thickness (Usually 1) Enter = 1)", 1, 64, nil, colors.red, nil, 1)
  14083.         if menu.getBoolean("Base below surface (y/n)", nil, colors.orange) then
  14084.             R.data = "bury"
  14085.         end
  14086.     elseif R.choice == 44 then -- Netherite stripping
  14087.         R.width     = 1
  14088.         while R.length == 0 or R.length % 16 > 0 do
  14089.             R.length = menu.getInteger("Strip length (divisible by 16) ", 16, 512, 1, colors.orange)
  14090.             if R.length % 16 > 0 then
  14091.                 menu.colourText(1, "~red~Must be multiple of 16")
  14092.             end
  14093.         end
  14094.         R.torchInterval = 16
  14095.         R.data = "seal"
  14096.     elseif R.choice == 45 then -- undermine dragon towers
  14097.  
  14098.     elseif R.choice == 46 then -- deactivate dragon tower
  14099.    
  14100.     elseif R.choice == 47 then -- build dragon water trap
  14101.         local text =
  14102. [[~yellow~You ~red~MUST ~yellow~have already constructed a
  14103. bridge / tunnel into the dragon island
  14104. to allow for safe construction of the
  14105. dragon trap.
  14106.  
  14107. If not use toolkit:
  14108.   ~brown~5.~gray~2 Covered path or tunnel~yellow~ length 100
  14109.  
  14110. start centre of obsidian platform:
  14111.   100,49,0 facing west]]
  14112.         menu.colourText(1, text)
  14113.         if menu.getBoolean("Bridge already made? (y/n)", 12, colors.orange) then
  14114.             getTaskHelp(2, R.choice, true)
  14115.             menu.clear()
  14116.         else
  14117.             R.data = "quit"
  14118.             return R
  14119.         end
  14120.     elseif R.choice == 48 then -- build end portal minecart station
  14121.     elseif R.choice == 49 then -- Shulker harvesting
  14122.         local items =
  14123.         {
  14124.             "Shulker is above",
  14125.             "Shulker is ahead",
  14126.             "Shulker is below",
  14127.             "Climb tower wall",
  14128.             "Clear roof above",
  14129.             "Clear outside walls"
  14130.         }
  14131.         pp.itemColours = {colors.lightGray, colors.brown, colors.blue, colors.yellow, colors.orange, colors.lightGray}
  14132.         R.subChoice = menu.menu("Which utility? ", items, pp)
  14133.         getTaskHelp(2, R.choice * 10 + R.subChoice, true)  -- eg 490 + 1 = 491
  14134.         menu.clear()   
  14135.        
  14136. -- 05. CANAL BRIDGE
  14137.     elseif R.choice == 51 then  --single path
  14138.         if menu.getBoolean("Shorten an existing path? (y/n)", nil, colors.brown) then
  14139.             R.data = "reduce"
  14140.         end
  14141.         if R.data == "reduce" then
  14142.             R.length = menu.getInteger("Reduce by? 0 = here to end", 0, 1024, nil, colors.orange, nil, 64)
  14143.         else
  14144.             R.length = menu.getInteger("Path length? 0 = continuous ", 0, 1024, nil, colors.orange, nil, 64)
  14145.             R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
  14146.         end
  14147.     elseif R.choice == 52 then  -- 2 block corridor / covered walkway
  14148.         R.length    = menu.getInteger("Corridor length?", 1, 1024, nil, colors.orange, nil, 64)
  14149.         R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
  14150.         if menu.getBoolean("Seal off water or lava? (y/n)", nil, colors.brown) then
  14151.             R.data = "seal"
  14152.         end
  14153.     elseif R.choice == 53 then  --left/right side of new/existing canal
  14154.         local line = getTaskHelp(2, 110, true, true) -- request line no of help display if needed for getInteger
  14155.         R.data = menu.getInteger("Choose method 1 or 2", 1, 2, line + 1, colors.white)  -- 2 or 4 turtles
  14156.         menu.clear()
  14157.         line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger
  14158.         R.subChoice = menu.getInteger("Type position of this turtle", 1, 6, line + 1, colors.white)
  14159.         local position = "on ground"
  14160.         local side = "left"
  14161.         local colour = colors.lime
  14162.         if R.subChoice == 1 then
  14163.             R.side = "L"
  14164.             R.height = 1
  14165.             position = "on ground"
  14166.             colour = colors.lime
  14167.         elseif R.subChoice == 2 then
  14168.             R.side = "L"
  14169.             R.height = 1
  14170.             position = "above canal"
  14171.             colour = colors.orange
  14172.         elseif R.subChoice == 3 then
  14173.             R.side = "R"
  14174.             side = "right"
  14175.             R.height = 1
  14176.             position = "above canal"
  14177.             colour = colors.brown
  14178.         elseif R.subChoice == 4 then
  14179.             R.side = "R"
  14180.             side = "right"
  14181.             R.height = 1
  14182.             colour = colors.green
  14183.         elseif R.subChoice == 5 then
  14184.             R.side = "L"
  14185.             R.height = 0
  14186.             position = "on canal base"
  14187.             colour = colors.blue
  14188.         elseif R.subChoice == 6 then
  14189.             R.side = "R"
  14190.             side = "right"
  14191.             R.height = 0
  14192.             position = "on canal base"
  14193.             colour = colors.cyan
  14194.         end
  14195.         line = menu.clear()
  14196.         if R.data == 1 or (R.data == 2 and (R.subChoice == 1 or R.subChoice == 4)) then
  14197.             R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
  14198.         end
  14199.         -- menu.colourPrint(text, fg, bg, width)
  14200.         -- menu.colourText(row, text, reset)
  14201.         menu.colourPrint("Turtle placed "..side.." "..position, colour)
  14202.         R.length    = menu.getInteger("Canal length? 0 = continuous ", 0, 512, line + 2, colors.orange, nil, 64)
  14203.     elseif R.choice == 54 then  --ice canal 4 sections: edge+torch, edge, centre+ice, centre no ice
  14204.         local line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger
  14205.         R.subChoice = menu.getInteger("Type turtle position", 1, 8, line, colors.white)
  14206.         R.side = "L"
  14207.         local position = "on towpath"
  14208.         local side = "left"
  14209.         local colour = colors.lime
  14210.         line = menu.clear()
  14211.         --[[
  14212.             new canal
  14213.             1 = left towpath- move to centre left
  14214.             2 = centre left ice or hollow
  14215.             3 = centre right ice or hollow
  14216.             4 = right side - move to centre right
  14217.             convert water canal
  14218.             5 = left towpath
  14219.             6 = centre left ice or air
  14220.             7 = centre right ice or air
  14221.             8 = right towpath
  14222.         ]]
  14223.         if R.subChoice == 1 or R.subChoice == 4 or R.subChoice == 5 or R.subChoice == 8 then
  14224.             -- on towpath r/l
  14225.             R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
  14226.             if R.subChoice == 4 or R.subChoice == 8 then
  14227.                 side = "right"
  14228.                 R.side = "R"
  14229.             end
  14230.             if R.subChoice <= 4 then -- 1 or 4 only
  14231.                 if menu.getBoolean("Place Ice as well? (y/n)", line + 1, colors.blue) then
  14232.                     R.data = "ice"
  14233.                 end
  14234.             end
  14235.         else -- on canal centre r/l
  14236.             if R.subChoice == 3 or R.subChoice == 7 then
  14237.                 side = "right"
  14238.                 R.side = "R"
  14239.             end
  14240.             if R.subChoice == 2 or R.subChoice == 3 then -- new canal
  14241.                 R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
  14242.                 position = "above air/ice"
  14243.             end
  14244.             if menu.getBoolean("Place Ice as well? (y/n)", line + 1, colors.blue) then
  14245.                 R.data = "ice"
  14246.                 if R.subChoice == 6 or R.subChoice == 7 then   
  14247.                     position = "alternate air/ice"
  14248.                     colour = colors.lightBlue
  14249.                 end
  14250.             else
  14251.                 if R.subChoice == 6 or R.subChoice == 7 then   
  14252.                     position = "on air spaces"
  14253.                     colour = colors.lighGray
  14254.                     if R.subChoice == 7 then
  14255.                         side = "right"
  14256.                         R.side = "R"
  14257.                     end
  14258.                 end
  14259.             end
  14260.         end
  14261.         R.length    = menu.getInteger("Canal length? 0 = continuous ", 0, 1024, line + 2, colors.orange, nil, 64)
  14262.         menu.colourPrint("Turtle on "..side.." side "..position, colour)
  14263.         sleep(2)
  14264.     elseif R.choice == 55 then  --platform
  14265.         R.width     = menu.getInteger("Platform width", 1, 256, 1, colors.yellow)
  14266.         R.length    = menu.getInteger("Platform length", 1, 256, 2, colors.orange)
  14267.         if menu.getBoolean("Remove blocks above? (y/n)",3, colours.red) then
  14268.             R.up = true
  14269.         end
  14270.        
  14271.     elseif R.choice == 56 then  --sinking platform
  14272.         R.width     = menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow)
  14273.         R.length    = menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange)
  14274.         R.height    = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue)
  14275.     elseif R.choice == 57 then  --boat bubble lift
  14276.         R.height    = menu.getInteger("Levels to go up?", 1, ceiling - 2, nil, colors.lightBlue)
  14277.        
  14278. -- 06. MOB SPAWNER TOOLS
  14279.     elseif R.choice == 61 then -- create cube round mob spawner
  14280.         local text =
  14281. [[~yellow~Turtle placement options:
  14282.  
  14283. ~lime~1. On top or in front of the spawner
  14284.    ~green~(cave spider OR no chests around)
  14285. ~lightGray~2. Outside the dungeon at floor or
  14286.    ceiling level ~red~1 block from corner
  14287. ~yellow~Make sure you have access to the block
  14288. facing the spawner, as any chests
  14289. found inside will be placed outside
  14290. the new dungeon wall at this height
  14291.  
  14292. ~white~Enter to continue
  14293. ]]
  14294.         menu.colourText(nil, text, true)
  14295.         read()
  14296.         menu.clear()
  14297.         R.data = "spawner"
  14298.         if menu.getBoolean("Any chests around spawner? (y/n)",1, colours.red) then
  14299.             R.data = "chest"
  14300.         end
  14301.         local choices = {"Turtle on spawner (no chests)",
  14302.                          "Outside wall: left side, floor",
  14303.                          "Outside wall: left side, ceiling",
  14304.                          "Outside wall: right side, floor",
  14305.                          "Outside wall: right side, ceiling"}
  14306.         pp.itemColours = {colors.red, colors.lime, colors.orange, colors.green, colors.yellow}
  14307.         local userChoice, modifier = menu.new("Select turtle position", choices, pp) -- 1 to 5
  14308.        
  14309.         if modifier == "q" then -- quit chosen
  14310.             R.data = "quit"
  14311.             return R
  14312.         end
  14313.         R.subChoice     = userChoice
  14314.         if R.subChoice > 1 then -- get dungeon wall dimensions
  14315.             R.width     = menu.getInteger("Dungeon external width ", 0, 11, nil, colors.yellow, nil, 11)
  14316.             R.length    = menu.getInteger("Dungeon external length ", 0, 11, nil, colors.orange, nil, 11)
  14317.         end
  14318.        
  14319.     elseif R.choice == 62 then -- Blaze spawner
  14320.         local text =
  14321. [[~yellow~Turtle placement options:
  14322.  
  14323. ~red~1a On top of the spawner
  14324.  
  14325. ~red~1b ~orange~At the same level in direct line of
  14326. spawner.~yellow~ (can be behind a safety wall)
  14327.  
  14328. ~red~1c~lightGray~ Room below spawner (via stairs)
  14329.  
  14330. ~lime~2 Finish build: In brick floor outside
  14331.   existing cube. (facing player)
  14332.  
  14333. ~white~Enter to continue]]
  14334.         menu.colourText(nil, text, true)
  14335.         read()
  14336.         pp.itemColours = {colors.red, colors.lime}
  14337.         R.subChoice = menu.new("Choose your option", {"New Blaze spawner", "Complete part build (killzone)"}, pp, "Type number + Enter") -- 1 = new, 2= continue
  14338.         R.data = "blaze"            -- default
  14339.         if R.subChoice == 1 then    -- new blaze spawner
  14340.             text =
  14341. [[~yellow~Turtle placement options:
  14342. ~red~1. On top of the spawner
  14343. ~orange~2. In direct sight (safety wall ok)
  14344. ~lightGray~3. Room below spawner (via stairs)
  14345.    |*|*|*|*|*|   Ceiling
  14346.    |*|*|~red~T~lightGray~|*|*|   Turtle under ceiling
  14347.    |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*|   Top of fence
  14348.    |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*|
  14349.    |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*|   Bottom of fence
  14350.    |*|*|*|*|*|   Floor level]]
  14351.             --R.subChoice = menu.new("Choose your position", {"On top of spawner", "In direct sight (safety wall ok)", "Room below spawner"}, pp, "Type number + Enter")
  14352.             --getInteger(prompt, minValue, maxValue, row, fg, bg, default)
  14353.             T:clear()
  14354.             menu.colourText(nil, text, true)
  14355.             R.subChoice = menu.getInteger("Enter position number", 1, 3, 12, colors.white)
  14356.         else
  14357.             R.data = "restart"      -- complete part build
  14358.         end
  14359.     elseif R.choice == 63 then -- flood spawner cube
  14360.         local choices = {"Bubble lift", "Computercraft mob softener"}
  14361.         pp.itemColours = {colors.lime, colors.orange}
  14362.         local userChoice = menu.menu("Flood for Mob grinder type?", choices, pp, "Type number + Enter ")
  14363.         R.subChoice = userChoice -- 1 bubble, 2 computercraft
  14364.     elseif R.choice == 64 then -- create bubble lift at mob spawner
  14365.         local choices = {"Dropzone on left", "Dropzone on right"}
  14366.         pp.itemColours = {colors.lime, colors.orange}
  14367.         local userChoice = menu.menu("Which side do you want the mobs?", choices, pp, "Type number + Enter")
  14368.         R.subChoice = userChoice -- 1 left, 2 right
  14369.     elseif R.choice == 65 then -- Computercraft mob grinder
  14370.         local choices = {"Use Sticky pistons", "Use non-sticky pistons"}
  14371.         pp.itemColours = {colors.lime, colors.orange}
  14372.         local userChoice = menu.menu("Which type of pistons?", choices, pp, "Type number + Enter ")
  14373.         R.subChoice = userChoice -- 1 sticky, 2 normal
  14374.    
  14375. -- 07. AREA CARVING
  14376.     elseif R.choice == 71 then --Clear field
  14377.         R.width     = menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow)
  14378.         R.length    = menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange)
  14379.         if menu.getBoolean("Dirt on the surface (y/n)", nil, colors.brown) then
  14380.             R.useBlockType = "dirt"
  14381.         end
  14382.     elseif R.choice == 72 then -- Clear solid rectangle R.width, R.length
  14383.         R.width     = menu.getInteger("Rectangle width (1-256)", 1, 256, nil, colors.yellow)
  14384.         R.length    = menu.getInteger("Rectangle length (1-256)", 1, 256, nil, colors.orange)
  14385.         R.up        = menu.getBoolean("Remove blocks above?", nil, colors.yellow)
  14386.         R.down      = menu.getBoolean("Remove blocks below?", nil, colors.orange)
  14387.         if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then
  14388.             T:forward(1)
  14389.         end
  14390.     elseif R.choice == 73 then -- Clear wall
  14391.         R.width     = 1
  14392.         R.length    = menu.getInteger("Length of wall (1-256) ", 1, 256, nil, colors.orange)
  14393.         R.height    = menu.getInteger("Height of wall (1-50) ", 1, 50, nil, colors.lightGray)
  14394.         pp.itemColours = {colors.lime, colors.orange}
  14395.         R.subChoice = menu.menu("Which direction?", {"Bottom -> Top", "Top -> Bottom"}, pp, "Type number + Enter ") -- open direction menu options
  14396.         if R.subChoice == 1 then
  14397.             if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then
  14398.                 T:forward(1)
  14399.             end
  14400.         else
  14401.             pp.itemColours = {colors.lightBlue, colors.cyan, colors.blue, colors.gray}
  14402.             local choice = menu.menu("Exact position?", {"On top of clearing zone", "In front of clearing zone", "Inside clearing zone","Above AND outside"}, pp, "Type number + Enter ")
  14403.             if choice == 1 then
  14404.                 T:down(1)
  14405.             elseif choice == 2 then
  14406.                 T:forward(1)
  14407.             elseif choice == 4 then
  14408.                 T:go("D1F1")
  14409.             end
  14410.         end
  14411.     elseif R.choice == 74 then -- Clear rectangle perimeter only R.width, R.length
  14412.         R.width     = menu.getInteger("Perimeter width (1-256) ", 1, 256, nil, colors.yellow)
  14413.         R.length    = menu.getInteger("Perimeter length (1-256) ", 1, 256, nil, colors.orange)
  14414.         R.height    = 1
  14415.         if menu.getBoolean("Remove blocks above? (y/n)", 3, colours.red) then
  14416.             R.up = true
  14417.         end
  14418.         if menu.getBoolean("Remove blocks below? (y/n)", 4, colours.red) then
  14419.             R.down = true
  14420.         end
  14421.         if menu.getBoolean("Am I outside clearing zone (y/n)?", 5, colors.yellow) then
  14422.             T:forward(1)
  14423.         end
  14424.     elseif R.choice == 75 or R.choice == 76 then -- Clear hollow building floor/walls/ceiling OR clear solid object
  14425.         R.width     = menu.getInteger("Structure width (1-256)", 1, 256, nil, colors.yellow)
  14426.         R.length    = menu.getInteger("Structure length (1-256)", 1, 256, nil, colors.orange)
  14427.         R.height    = menu.getInteger("Depth/Height (1-256)", 1, 256, nil, colors.lightGray)
  14428.         if R.choice == 75 then -- hollow building so need to check if floors/ceilings to be removed
  14429.             R.data = {}
  14430.             R.data.ceiling = false
  14431.             R.data.floor = false
  14432.             if menu.getBoolean("Remove ceiling? (y/n)", nil, colors.yellow, colors.black) then
  14433.                 R.data.ceiling = true
  14434.             end
  14435.             if menu.getBoolean("Remove floor? (y/n)", nil, colors.orange, colors.black) then
  14436.                 R.data.floor = true
  14437.             end
  14438.         end
  14439.         pp.itemColours = {colors.lime, colors.orange}
  14440.         local direction = menu.menu("Which direction?", {"Bottom -> Top", "Top -> Bottom"}, pp, "Type number + Enter ") -- open direction menu options
  14441.         if direction == 1 then
  14442.             R.direction = "up"
  14443.             if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then
  14444.                 T:forward(1)
  14445.             end
  14446.         else
  14447.             R.direction = "down"
  14448.             pp.itemColours = {colors.lightBlue, colors.cyan, colors.blue, colors.gray}
  14449.             local choice = menu.menu("Exact position?", {"On top of clearing zone", "Outside clearing zone", "Inside clearing zone","Above AND outside"}, pp, "Type number + Enter ")
  14450.             if choice == 1 then
  14451.                 T:down(1)
  14452.             elseif choice == 2 then
  14453.                 T:forward(1)
  14454.             elseif choice == 4 then
  14455.                 T:go("D1F1")
  14456.             end
  14457.         end
  14458.     elseif R.choice == 77 then  -- Dig a trench
  14459.         R.height    = menu.getInteger("Depth of the trench (1-64) ", 1, 64, nil, colors.blue)
  14460.         R.length    = menu.getInteger("Trench length? 0 = continuous ", 0, 1024, nil, colors.orange)
  14461.     elseif R.choice == 78 then  -- Carve side of mountain
  14462.         pp.itemColours = {colors.lime, colors.orange}
  14463.         R.subChoice = menu.menu("Remove blocks on which side?", {"Left", "Right"}, pp, "Type number + Enter ") -- open direction menu options
  14464.         R.width     = menu.getInteger("Remove how many vertical rows? ", 1, 1024, nil, colors.yellow)
  14465.         R.length    = menu.getInteger({"Max length of each row?"," - Prevents cutting too wide","1 to 255 default 64"}, 1, 255, nil, {colors.orange, colors.red, colors.white}, colors.black, 64)
  14466.     elseif R.choice == 79 then  -- Place a floor or ceiling
  14467.         local items = { "Replacing current floor",
  14468.                         "New floor over existing",
  14469.                         "Replacing current ceiling",
  14470.                         "New ceiling under existing"}
  14471.         pp.itemColours = {colors.lime, colors.orange, colors.green, colors.yellow}
  14472.         R.subChoice = menu.menu("Laying what?", items, pp, "Type number + Enter ")
  14473.         R.height = menu.getInteger({"Enter 0 for on-site placement",
  14474.                                     "If in deep water or above reach",
  14475.                                     "Enter approx depth/height"}, 0, 64, nil, {colors.yellow, colors.blue, colors.cyan} )
  14476.         if R.subChoice < 3 then
  14477.             R.down = true
  14478.             R.width     = menu.getInteger("Width of floor (1-64) ", 1, 64, nil, colors.yellow)
  14479.             R.length    = menu.getInteger("Length of floor (1-64) ", 1, 64, nil, colors.orange)
  14480.         else
  14481.             R.up = true
  14482.             R.width     = menu.getInteger("Width of ceiling (1-64) ", 1, 64, nil, colors.yellow)
  14483.             R.length    = menu.getInteger("Length of ceiling (1-64) ", 1, 64, nil, colors.orange)
  14484.         end
  14485.     elseif R.choice == 710 or R.choice == 83 then -- Direct movement
  14486.         local choices = {"Simple path", "Covered 2 block high path"}
  14487.         pp.itemColours = {colors.lime, colors.orange}
  14488.         local userChoice = menu.menu("Choose your path option", choices, pp, "Type number + Enter ")
  14489.         R.subChoice = userChoice -- 1 open, 2 covered
  14490.         choices = {"Command driven", "Menu driven"}
  14491.         userChoice = menu.menu("Choose your preference", choices, pp, "Type number + Enter ")
  14492.         if userChoice == 1 then
  14493.             R.data = "cmd"
  14494.         else
  14495.             R.data = "menu"
  14496.         end
  14497.        
  14498. -- 08. WATER LAVA
  14499.     elseif R.choice == 81 then -- Sand based utilities
  14500.         local line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger
  14501.         R.subChoice = menu.getInteger("Type number of choice", 1, 4, line, colors.white)
  14502.         T:clear()
  14503.         if R.subChoice == 1 then -- drop sand into water or lava surface until solid ground reached
  14504.             R.width   = 1
  14505.             R.length  = menu.getInteger("Length of sand wall (0=to block) ", 0, 60, nil, colors.orange)
  14506.         elseif R.subChoice == 2 then    -- clear rectangle on top of building and fill with sand
  14507.             R.width   = menu.getInteger("Width of area (<=30) ", 1, 30, nil, colors.yellow)
  14508.             R.length  = menu.getInteger("Length of of area (<=30) ", 1, 30, nil, colors.orange)
  14509.         elseif R.subChoice == 3 then    -- clear sand wall or harvest sand
  14510.             R.width   = 1
  14511.             R.length  = menu.getInteger("Length of sand (0=auto-detect)", 0, 60, nil, colors.orange)
  14512.             choices = {"Stay at end of wall", "Return home"}
  14513.             pp.itemColours = {colors.lime, colors.orange}
  14514.             userChoice = menu.menu("Choose your preference", choices, pp, "Type number + Enter ")
  14515.             if userChoice == 2 then
  14516.                 R.data = "return"
  14517.             end
  14518.         elseif R.subChoice == 4 then    -- remove sand from cube. start at top
  14519.             R.width   = menu.getInteger("Width of sand (<=30) ", 1, 30, nil, colors.yellow)
  14520.             R.length  = menu.getInteger("Length of of sand (<=30) ", 1, 30, nil, colors.orange)
  14521.             R.height  = 0
  14522.             R.data = "down" -- always starts at the top
  14523.         end
  14524.         if menu.getBoolean("Am I outside the active zone (y/n)?", nil, colors.yellow) then
  14525.             T:forward(1)
  14526.         end
  14527.     elseif R.choice == 82 then -- build wall from water or lava surface downwards
  14528.         R.width     = 1
  14529.         if menu.getBoolean("Going 90 deg. from existing? (y/n)", nil, colors.yellow, colors.black) then
  14530.             getTaskHelp(2, 852, true)
  14531.             menu.clear()   
  14532.             R.length = 56
  14533.             R.data = "withPath" -- ensures turtle will break through path
  14534.             R.length = menu.getInteger({"Wall length minus corners","(Ocean monument default 56)","Number -> Enter or Enter only (56)"},
  14535.                                         1, 64, nil, {colors.yellow, colors.orange, colors.green}, colors.black, 56)
  14536.         else
  14537.             R.length    = menu.getInteger("Length of the wall (1-60) ", 1, 60, nil, colors.yellow)
  14538.             R.height    = menu.getInteger("Fixed depth or 0 = to floor ", 0, 60, nil, colors.yellow)
  14539.         end
  14540.     -- for 83 see 710
  14541.     elseif R.choice == 84 then -- Clear area of water bounded by blocks
  14542.         R.width     = menu.getInteger("Width of water (0=autodetect) ", 0, 64, nil, colors.yellow)
  14543.         if R.width > 0 then
  14544.             R.length = menu.getInteger("Length of water", 1, 64, nil, colors.orange)
  14545.         end
  14546.         R.height    = menu.getInteger("Depth of water (0=autodetect)", 0, 64, nil, colors.blue)
  14547.     elseif R.choice == 85 then -- Sinking platform
  14548.         R.width     = menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow)
  14549.         R.length    = menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange)
  14550.         R.height    = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue)
  14551.     elseif R.choice == 86 then -- ocean monument utilities
  14552.         local items =
  14553.         {
  14554.             "Build 4 corner marker columns",
  14555.             "Retaining wall beween 2 columns",
  14556.             "Clear plants pre sand draining",
  14557.             "Drop sand wall",
  14558.             "Recover sand wall",
  14559.             "Sinking platform",
  14560.             "Drain and remove structure"   
  14561.         }
  14562.         pp.itemColours = {colors.lightGray, colors.brown, colors.blue, colors.yellow, colors.orange, colors.lightGray, colors.gray}
  14563.         R.subChoice = menu.menu("Which utility? ", items, pp)
  14564.         if R.subChoice ~= nil then
  14565.             getTaskHelp(2, R.choice * 10 + R.subChoice, true)
  14566.         end
  14567.         menu.clear()   
  14568.         if R.subChoice == 1 then -- Build 4 corner marker columns          
  14569.             R.useBlockType = "prismarine"
  14570.             R.data = "oceanMonumentColumns"
  14571.         elseif R.subChoice == 2 then -- Retaining wall beween 2 columns
  14572.             R.length = 56
  14573.             R.data = "withPath" -- ensures turtle will break through path
  14574.             T:clear()
  14575.             R.length = menu.getInteger({"Wall length minus corners","(Ocean monument default 56)","Number -> Enter or Enter only (56)"},
  14576.                                          1, 64, nil, {colors.yellow, colors.orange, colors.green}, colors.black, 56)
  14577.         elseif R.subChoice == 3 then -- Clear plants pre sand draining
  14578.             R.useBlockType = "prismarine"
  14579.             R.data = "clearWaterPlants"
  14580.             R.silent = true
  14581.             R.width     = menu.getInteger("water width (0=auto detect) ", 0, 64, nil, colors.yellow)
  14582.             R.length    = menu.getInteger("water length (0=auto detect) ", 0, 64, nil, colors.orange)
  14583.         elseif R.subChoice == 4 then -- Drain using sand utilities
  14584.             R.width   = 1
  14585.             R.length  = 0
  14586.         elseif R.subChoice == 5 then -- remove sand wall using sand utilities
  14587.             R.width   = 1
  14588.             R.length  = 0
  14589.         elseif R.subChoice == 6 then -- sinking platform
  14590.             R.width = menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow)
  14591.             R.length = menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange)
  14592.             R.height = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue)
  14593.         elseif R.subChoice == 7 then -- Drain and remove structure
  14594.             R.width = 28
  14595.             R.length = 28
  14596.             R.height = menu.getInteger("Go down how far from current", 1, 64, nil, colors.blue)
  14597.         end
  14598.     elseif R.choice == 87 then -- Ladder to water/lava 
  14599.         R.height    = menu.getInteger("est. height above (?F3) ", 1, 256, nil, colors.blue)
  14600.     elseif R.choice == 88 then -- Clear water plants from enclosed area
  14601.         R.data      = "clearWaterPlants"
  14602.         R.width     = menu.getInteger("water width (0=auto detect) ", 0, 64, nil, colors.yellow)
  14603.         R.length    = menu.getInteger("water length (0=auto detect) ", 0, 64, nil, colors.orange)
  14604.     elseif R.choice == 89 then -- convert flowing water to source
  14605.         R.width     = menu.getInteger("water width  (0=auto detect) ", 0, 64, nil, colors.yellow)
  14606.         if R.width > 0 then
  14607.             R.length = menu.getInteger("water length (0=auto detect) ", 0, 64, nil, colors.orange)
  14608.         end
  14609.         R.height    = menu.getInteger("water depth (0=auto detect) ", 0, 64, nil, colors.blue)
  14610.     elseif R.choice == 810 then -- create sloping water
  14611.         R.width     = menu.getInteger("water slope width (usually 7/8) ", 1, 8, nil, colors.yellow)
  14612.         R.length    = menu.getInteger("water slope length ", 1, 64, nil, colors.orange)
  14613.    
  14614. -- 09. BUILDING & RAILWAY
  14615.     elseif R.choice == 91 then -- Build wall
  14616.         R.width     = 1
  14617.         R.length    = menu.getInteger("Length of wall (1-256) ", 1, 256, nil, colors.orange)
  14618.         R.height    = menu.getInteger("Height of wall (1-50) ", 1, 50, nil, colors.lightGray)
  14619.         pp.itemColours = {colors.lime, colors.magenta}
  14620.         R.subChoice = menu.menu("What is my current position?", {"End of wall: Start ahead","Within the wall: start here"}, pp, "Type number + Enter")
  14621.     elseif R.choice == 92 then -- Build rectangular structure
  14622.         R.width     = menu.getInteger("Building width (1-256)", 1, 256, nil, colors.yellow)
  14623.         R.length    = menu.getInteger("Building length (1-256) ", 1, 256, nil, colors.orange)
  14624.         R.height    = menu.getInteger("Building Height(1-50) ", 1, 50, nil, colors.lightGray)
  14625.         pp.itemColours = {colors.lime, colors.magenta}
  14626.         R.subChoice = menu.menu("What is my current position?", {"Outside building: Start ahead","Within the walls: start here"}, pp, "Type number + Enter")
  14627.     elseif R.choice == 93 or R.choice == 94 then -- Build gable roof / pitched roof
  14628.         R.width     = menu.getInteger("Building width (1-256)", 1, 256, nil, colors.yellow)
  14629.         R.length    = menu.getInteger("Building length (1-256) ", 1, 256, nil, colors.orange)
  14630.     elseif R.choice == 97 then -- build downward slope
  14631.     --getInteger(prompt, minValue, maxValue, row, fg, bg, default)
  14632.         R.height    = menu.getInteger("How many blocks down (0=to ground)?", 0, 256, nil, colors.blue)
  14633.         R.depth     = menu.getInteger("How much headroom (default 2)?", 0, 5, nil, colors.cyan, colors.black, 2)
  14634.         R.down = true
  14635.     elseif R.choice == 98 then -- build upward slope
  14636.         R.height    = menu.getInteger("Go up by how many blocks?", 1, 256, nil, colors.lightGray)
  14637.         R.depth     = menu.getInteger("How much headroom (default 2)?", 0, 5, nil, colors.cyan, colors.black, 2)
  14638.         R.up = true
  14639.        
  14640. -- 10. MEASURING TOOLS
  14641.     elseif R.choice == 101 then -- measure height
  14642.         pp.itemColours = {colors.lightBlue, colors.cyan, colors.lime, colors.gray}
  14643.         R.subChoice = menu.menu("Measure using?", {"Obstruction above", "No further blocks in front", "Detect specific block in front", "Until block above changes" }, pp, "Type number + Enter ") -- open direction menu options
  14644.         if R.subChoice == 3 then
  14645.             R.data = menu.getString({"Search for? eg 'ore', 'obsidian'",">"}, false, 3, 20, nil, {colors.lime, colors.yellow})
  14646.         end
  14647.         R.size = menu.getInteger("Max distance before abort?", 1, 1024, nil, colors.red, nil, 64)
  14648.     elseif R.choice == 102 then -- measure depth
  14649.         pp.itemColours = {colors.lime, colors.orange, colors.green}
  14650.         R.subChoice = menu.menu("Measure using?", {"Water/Lava/Obstruction below", "No further blocks ahead", "Detect specific block ahead"}, pp, "Type number + Enter") -- open direction menu options
  14651.         if R.subChoice == 3 then
  14652.             R.data = menu.getString({"Search for? eg 'ore', 'obsidian'",">"}, false, 3, 20, nil, {colors.lime, colors.yellow})
  14653.         end
  14654.     elseif R.choice == 103 then -- measure length
  14655.         pp.itemColours = {colors.gray, colors.lime, colors.green, colors.blue, colors.cyan}
  14656.         R.subChoice = menu.menu("Measure using?", {"Obstruction ahead",
  14657.                                                     "No further blocks above",
  14658.                                                     "No further blocks below",
  14659.                                                     "Detect specific block above",
  14660.                                                     "Detect specific block below"}, pp, "Type number + Enter") -- open direction menu options
  14661.         if R.subChoice == 4 or R.subChoice == 5 then
  14662.             R.data = menu.getString({"Search for? eg 'ore', 'obsidian'",">"}, false, 3, 20, nil, {colors.lime, colors.yellow})
  14663.         end
  14664.         R.size = menu.getInteger("Max distance before abort?", 1, 1024, nil, colors.red, nil, 64)
  14665.     elseif R.choice == 104 then -- measure greatest depth of water body
  14666.         pp.itemColours = {colors.lime, colors.orange}
  14667.         R.subChoice = menu.menu("Measure using?", {"Player entered", "No further water below"}, pp, "Type number + Enter ") -- open direction menu options
  14668.         -- 1 = player entry, 2 = water length
  14669.         if R.subChoice == 1 then
  14670.             R.length = menu.getInteger("water length (0=auto detect) ", 0, 256)
  14671.         end
  14672.     elseif R.choice == 105 then -- drill borehole and write borhole.txt to file
  14673.         R.height = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.lightGray)
  14674.         R.depth = menu.getInteger("Go down to level? ("..R.height - 2 .." to "..bedrock + 5 ..")", bedrock + 5 ,R.height - 2, nil, colors.blue, nil, bedrock + 5)
  14675.    
  14676. -- 11 Network tools
  14677.     elseif R.choice == 111 then -- craft an item
  14678.         local modem = peripheral.find("modem")      -- find modem
  14679.         if modem == nil then
  14680.             menu.colourText(1, "~yellow~I need to be placed close to an\n"..
  14681.                   "~red~activated ~brown~computercraft:modem_full~yellow~ to use "..
  14682.                   "~magenta~networked resources ~yellow~for crafting"..
  14683.                   "\n\n~blue~(Right-click modem to activate)\n")
  14684.                 error()
  14685.         end
  14686.     elseif R.choice == 112 then -- mystical Agriculture essence tools
  14687.         if T:getBlockType("forward") ~= "minecraft:crafter" then
  14688.             menu.colourText(1, "~yellow~I need to be placed in front of a\n"..
  14689.                   "~red~minecraft:crafter ~yellow~(mc 1.21.1) as \n"..
  14690.                   "currently turtle.craft() with a\n"..
  14691.                   "~lime~mystical agriculture crystal\n~red~destroys the crystal!\n")
  14692.                 error()
  14693.         end
  14694.         pp.itemColours = {colors.green, colors.lime, colors.orange, colors.blue, colors.red}
  14695.         R.subChoice = menu.menu("Process Essences:", {"Inferium to Prudentium",
  14696.                                                     "Prudentium to Tertium",
  14697.                                                     "Tertium to Imperium",
  14698.                                                     "Imperium to Supremium",
  14699.                                                     "Supremium to Insanium"}, pp, "Type number + Enter") -- open essence menu options
  14700.         R.size = menu.getInteger("Quantity? 0 = all)", 0, 1024, nil, colors.orange, nil, 64)
  14701.     end
  14702.  
  14703.     return R
  14704. end
  14705.  
  14706. local function getTaskInventoryTo30(R)
  14707.     local retValue = {}
  14708.     local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n"
  14709.     --local pp = utils.getPrettyPrint()
  14710.    
  14711.     if R.choice == 0 then --Missing pickaxe
  14712.         T:checkInventoryForItem({"minecraft:diamond_pickaxe"}, {1})
  14713.         print("Diamond Pickaxe being tested...")
  14714.         T:setEquipment()
  14715.     elseif R.choice == 1 then --Missing crafting table
  14716.         T:checkInventoryForItem({"minecraft:crafting_table"}, {1}) -- 0 if not present
  14717.         print("Crafting table being tested...")
  14718.         T:setEquipment()
  14719.     elseif R.choice == 2 then --Missing chest
  14720.         T:checkInventoryForItem({"minecraft:chest"}, {1}) -- 0 if not present
  14721.         sleep(1.5)
  14722.        
  14723.     -- MINING
  14724.    
  14725.     elseif R.choice == 11 or R.choice == 12 then            -- ladder down / up / stairs down / stairs up
  14726.         local description = "Creating ladder going down"    -- default action description
  14727.         pp.itemColours = {colors.blue, colors.lightGray}
  14728.         pp.allowModifier = false -- only allow numbers to be returned
  14729.         local inAir = false
  14730.         local inNether = menu.getBoolean("Are you in the nether? (y/n) ", nil, colors.yellow, colors.black)
  14731.        
  14732.         if inNether then
  14733.             bedrock = 0
  14734.             inAir = true
  14735.         end
  14736.         local option = menu.menu("Which direction?", {"Going down","Going up"}, pp)
  14737.         if option == 1 then
  14738.             R.down = true
  14739.             R.height = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.lightGray)
  14740.             R.depth = menu.getInteger("Go down to level? ("..R.height - 2 .." to "..bedrock + 5 ..") ", bedrock + 5 , R.height - 2, nil, colors.blue)
  14741.             if R.choice == 11 then
  14742.                 if menu.getBoolean("Build a shelter at base? (y/n) ", nil, colors.yellow, colors.black) then
  14743.                     R.data = "chamber"
  14744.                 end
  14745.             end
  14746.             if R.choice == 13 then
  14747.                 description = "Creating stairs going down"
  14748.             end
  14749.         else
  14750.             R.up = true
  14751.             --R.depth = utils.getSize(true,"Current level (F3->Y coord)? ", bedrock + 5, ceiling)
  14752.             --R.height = utils.getSize(true, "Go up to level? ("..R.depth + 2 .." to "..ceiling ..")", R.depth + 2, ceiling)
  14753.             R.depth = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.blue)
  14754.             R.height = menu.getInteger("Go up to level? ("..R.depth + 2 .." to "..ceiling ..") ", R.depth + 2, ceiling, nil, colors.lightGray)
  14755.             if R.choice == 11 then
  14756.                 description = "Creating ladder going up"
  14757.             else
  14758.                 description = "Creating stairs going up"
  14759.             end
  14760.         end
  14761.         local range = math.abs(R.height - R.depth)
  14762.        
  14763.         if not inAir then
  14764.             inAir = menu.getBoolean("Are you in air (add blocks)? (y/n) ", nil, colors.yellow, colors.black)
  14765.         end
  14766.         --[[
  14767.         range examples
  14768.         -50 to -59 = -59 -(-50) = -9   down
  14769.         -59 to -50 = -50 -(-59) = 9    up
  14770.          70 to -48 = -48 -   70 = -118 down
  14771.           5 to  64 =  64 -   5  = 59   up
  14772.         ]]
  14773.         T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
  14774.         if R.choice == 11 then -- ladders
  14775.             utils.checkFuelNeeded(range * 2)
  14776.             T:checkInventoryForItem({"minecraft:ladder"}, {range})
  14777.             T:checkInventoryForItem({"minecraft:torch"}, {math.floor(range / 3)}, false)
  14778.             if inAir then
  14779.                 range = range * 4 -- more blocks needed
  14780.             end
  14781.             T:checkInventoryForItem({"stone"}, {range})
  14782.         else -- stairs
  14783.             utils.checkFuelNeeded(range * 10) -- stairs: each layer needs 10 moves
  14784.             local numStairsNeeded = range
  14785.             local data = T:getStock("stairs")
  14786.             local numStairs = data.total
  14787.             local cobbleNeeded = math.min(range * 6, 256)
  14788.             if inAir then
  14789.                 cobbleNeeded = range * 6 -- 5 blocks / layer unless in water or lava
  14790.             end
  14791.             if numStairs < numStairsNeeded then
  14792.                 cobbleNeeded = cobbleNeeded + (math.floor((2 * (numStairsNeeded - numStairs)) / 3))
  14793.             end
  14794.             T:checkInventoryForItem({"stairs"}, {numStairsNeeded}, false)
  14795.             T:checkInventoryForItem({"stone"}, {cobbleNeeded})
  14796.             T:checkInventoryForItem({"minecraft:chest"}, {1})   -- needed for crafting
  14797.         end
  14798.         menu.colourPrint(description, colors.lightBlue)
  14799.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  14800.         if R.choice == 11 then
  14801.             retValue = createLadder(R) -- "bedrock", 70, -48
  14802.         else
  14803.             retValue = createStaircase(R)
  14804.         end
  14805.     elseif R.choice == 13 then --Create Mine at this level
  14806.         utils.checkFuelNeeded(960)
  14807.         T:checkInventoryForItem({"minecraft:torch"}, {24}, false)
  14808.         T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
  14809.         T:checkInventoryForItem({"stone"}, {64})
  14810.         T:checkInventoryForItem({"minecraft:chest"}, {1})
  14811.         menu.colourPrint("CreateMine starting", colors.lightBlue)
  14812.         sleep(2)
  14813.         retValue = createMine()
  14814.     elseif R.choice == 14 then  -- safe drop to water
  14815.         utils.checkFuelNeeded(R.height * 2)
  14816.         T:checkInventoryForItem({"minecraft:water_bucket"}, {1})
  14817.         T:checkInventoryForItem({"stone"}, {R.height * 2}, false) -- estimate only partial cloaking needed
  14818.         menu.colourPrint("Creating safe drop ".. R.height.. " blocks deep", colors.lightBlue)
  14819.         menu.colourPrint("Wait for my return!", colors.yellow)
  14820.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  14821.         retValue = createSafeDrop(R)
  14822.     elseif R.choice == 15 then  -- single column bubble lift
  14823.         local needSigns = true
  14824.         utils.checkFuelNeeded(R.height * 6)
  14825.         --print(text, fg, bg, width)
  14826.         menu.colourPrint("Checking if near ladder", colors.red)
  14827.         T:turnRight(1)
  14828.         local blockType = T:getBlockType("forward")
  14829.         if blockType:find("ladder") == nil then
  14830.             T:turnLeft(2)
  14831.             blockType = T:getBlockType("forward")
  14832.             if blockType:find("ladder") == nil then
  14833.                 needSigns = false
  14834.             end
  14835.             T:turnRight(1)
  14836.         else
  14837.             needSigns = false
  14838.             T:turnLeft(1)
  14839.         end
  14840.         sleep(1)
  14841.         if needSigns then
  14842.             T:checkInventoryForItem({"sign"}, {2}, true, "Ladder not found")
  14843.         else
  14844.             menu.colourPrint("Ladder found, signs not required", colors.orange)
  14845.             sleep(1)
  14846.         end
  14847.         if T:getBlockType("down"):find("bedrock") == nil then -- NOT bedrock below
  14848.             T:checkInventoryForItem({"minecraft:water_bucket"}, {3})
  14849.         else
  14850.             T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
  14851.         end
  14852.         T:checkInventoryForItem({"minecraft:soul_sand", "minecraft:dirt"}, {1, 1}, true, "? use dirt as soul sand placeholder")
  14853.         T:checkInventoryForItem({"stone"}, {R.height * 2}, false) -- estimate only partial cloaking needed
  14854.         local _, slots = T:getFirstEmptySlot() -- returns first empty slot, no of empty slots
  14855.         T:checkInventoryForItem({"minecraft:bucket"}, {slots}, false, "Add empty buckets for speed!")
  14856.         menu.colourPrint("Creating bubble lift ".. R.height.. " blocks high", colors.lime)
  14857.         if not needSigns then -- ladder present as signs not required
  14858.             menu.colourPrint("Wait at the top via ladder...", colors.orange)
  14859.         end
  14860.         menu.colourPrint("\nSTAND ON THE LADDER FOR SAFETY!", colors.red)
  14861.         menu.colourPrint("\nEnter to continue", colors.yellow)
  14862.         read()
  14863.         retValue = createBubbleLift(R)
  14864.     elseif R.choice == 16 then --QuickMine corridor
  14865.         utils.checkFuelNeeded((R.width * 2 + R.length * 2) * 2)
  14866.         T:checkInventoryForItem({"stone"}, {R.width * 2 + R.length * 2}, false)
  14867.         T:checkInventoryForItem({"minecraft:torch"}, {math.floor((R.width * 2 + R.length * 2) / R.torchInterval)}, false)
  14868.         T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
  14869.         menu.colourPrint("QuickMine corridor: R.subChoice "..R.width.. " x "..R.length, colors.lightBlue)
  14870.         retValue = quickMineCorridor(R)
  14871.     elseif R.choice == 17 then --QuickMine
  14872.         utils.checkFuelNeeded(R.width * R.length)
  14873.         T:checkInventoryForItem({"stone"}, {64})
  14874.         T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
  14875.         menu.colourPrint("QuickMine rectangle: R.subChoice "..R.width.. " x "..R.length, colors.lightBlue)
  14876.         retValue = quickMine(R)
  14877.     elseif R.choice == 18 then --Mine bedrock area
  14878.         utils.checkFuelNeeded(R.width * R.length)
  14879.         T:checkInventoryForItem({"stone"}, {64})
  14880.         T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
  14881.         retValue = mineBedrockArea(R) -- R.data = "leaveExposed" or ""
  14882.     elseif R.choice == 19 then  -- salvage mineshaft
  14883.         local equippedRight, equippedLeft, inInventory = T:setEquipment() -- check for crafting table, sword, pickaxe, Put sword in spare slot
  14884.         if equippedLeft ~= "minecraft:diamond_pickaxe" and equippedRight ~= "minecraft:diamond_pickaxe" then
  14885.             T:checkInventoryForItem({"minecraft:diamond_pickaxe"}, {1}, true)
  14886.             equippedRight, equippedLeft, inInventory = T:setEquipment() -- check for crafting table, sword, pickaxe, Put sword in spare slot
  14887.         end
  14888.         if inInventory ~= "minecraft:diamond_sword" then
  14889.             T:checkInventoryForItem({"minecraft:diamond_sword"}, {1}, false, "To harvest spider webs\nyou need a diamond sword.") --checkInventoryForItem(self, items, quantities, required, message, name)
  14890.         end
  14891.         if T:getItemSlot("minecraft:diamond_sword") > 0 then
  14892.             inInventory = "minecraft:diamond_sword"
  14893.         end
  14894.         T:checkInventoryForItem({"minecraft:torch"}, {R.torchInterval}, false)
  14895.         if inInventory == "minecraft:diamond_sword" then
  14896.             menu.colourPrint("Clearing Mineshaft and cobwebs", colors.orange)
  14897.         else
  14898.             menu.colourPrint("Clearing Mineshaft", colors.yellow)
  14899.         end
  14900.         retValue = clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- pass whether the sword is present
  14901.        
  14902.     -- FORESTRY
  14903.     elseif R.choice == 21 then  -- Fell tree
  14904.         if T:isLog("forward") then
  14905.             if turtle.getFuelLevel() < 30 then
  14906.                 T:checkInventoryForItem({"minecraft:chest"}, {1}, false,"Fuel level critical: "..turtle.getFuelLevel())
  14907.                 turtle.select(1)
  14908.                 T:dig("forward")
  14909.                 T:craft("planks", 4)
  14910.                 T:refuel()
  14911.                 T:forward(1)
  14912.                 T:up(2)
  14913.                 T:craft("chest", 1)
  14914.             else
  14915.                 T:forward(1)
  14916.             end
  14917.             menu.colourPrint("Felling tree", colors.lime)
  14918.             os.sleep(2)    -- pause for 2 secs to allow time to press esc
  14919.             T:harvestWholeTree("up")
  14920.             while turtle.down() do end
  14921.             retValue = {"Tree Harvested"}
  14922.         else
  14923.             retValue =
  14924.             {
  14925.                 "No log in front..",
  14926.                 "Move me in front of a tree!"
  14927.             }
  14928.         end
  14929.     elseif R.choice == 22 then --Create treefarm
  14930.         utils.checkFuelNeeded(900)
  14931.         if R.data == "convertStorage" or R.data == "convert" then
  14932.             T:checkInventoryForItem({"log"}, {1}, true, "Use log to indicate sapling type")
  14933.             T:checkInventoryForItem({"barrel"}, {2})
  14934.             T:checkInventoryForItem({"minecraft:hopper"}, {1})
  14935.             if R.data == "convertStorage" then
  14936.                 T:checkInventoryForItem({"chest"}, {8})
  14937.                 T:checkInventoryForItem({"wired_modem_full"}, {3})
  14938.                 T:checkInventoryForItem({"computercraft:cable"}, {24})
  14939.             else
  14940.                 T:checkInventoryForItem({"wired_modem_full"}, {2})
  14941.                 T:checkInventoryForItem({"computercraft:cable"}, {22})
  14942.             end
  14943.         else
  14944.             T:checkInventoryForItem({"stone"}, {320})
  14945.             T:checkInventoryForItem({"minecraft:water_bucket"}, {4})
  14946.             T:checkInventoryForItem({"minecraft:hopper"}, {1})
  14947.             T:checkInventoryForItem({"log"}, {1}, true, "Use log to indicate sapling type")
  14948.             R.useBlockType = T:getMostItem("", true)
  14949.             T:checkInventoryForItem({"barrel"}, {2})
  14950.             if R.data == "new" then
  14951.                 T:checkInventoryForItem({"chest"}, {8})
  14952.                 T:checkInventoryForItem({"wired_modem_full"}, {3})
  14953.                 T:checkInventoryForItem({"computercraft:cable"}, {24})
  14954.             else
  14955.                 T:checkInventoryForItem({"wired_modem_full"}, {2})
  14956.                 if R.data == "back" then
  14957.                     T:checkInventoryForItem({"computercraft:cable"}, {34})
  14958.                 else
  14959.                     T:checkInventoryForItem({"computercraft:cable"}, {22})
  14960.                 end
  14961.             end
  14962.             menu.colourPrint("Creating Tree Farm with "..R.useBlockType, colors.lime)
  14963.         end
  14964.         retValue = createTreefarm(R)
  14965.     elseif R.choice == 23 then -- Plant treefarm
  14966.         if not R.networkFarm then
  14967.             if R.subChoice == 1 then
  14968.                 utils.checkFuelNeeded(180)
  14969.                 T:checkInventoryForItem({"dirt"}, {16})
  14970.                 T:checkInventoryForItem({"sapling"}, {16}, false, "Max 16. NOT dark oak")
  14971.             elseif R.subChoice == 2 then
  14972.                 utils.checkFuelNeeded(180)
  14973.                 T:checkInventoryForItem({"dirt"}, {16})
  14974.                 T:checkInventoryForItem({"sapling"}, {16}, false, "Max 16. 4 saplings / tree")
  14975.             end
  14976.         end
  14977.         menu.colourPrint("plantTreefarm starting: size "..R.subChoice, colors.lime)
  14978.         retValue = plantTreefarm(R)
  14979.     elseif R.choice == 24 then  -- Harvest treefarm
  14980.         menu.colourPrint("Harvesting treefarm starting", colors.lime)
  14981.         retValue = harvestTreeFarm(R)
  14982.     elseif R.choice == 25 then  -- Build wall / fence
  14983.         utils.checkFuelNeeded(R.width * R.length * 2)
  14984.         local quantity = math.ceil((R.width + R.length) * 2.3)
  14985.         T:checkInventoryForItem({"wall", "fence"}, {quantity, quantity})
  14986.         if R.torchInterval > 0 then
  14987.             T:checkInventoryForItem({"minecraft:torch"}, {math.floor(quantity / R.torchInterval)}, false)
  14988.         end
  14989.         if R.data == "barrel" then
  14990.             T:checkInventoryForItem({"barrel"}, {4}, false)
  14991.         end
  14992.         R.useBlockType = T:getMostItem("", false) -- no excluded blocks, any block type
  14993.         menu.colourPrint("Creating "..R.width.." x "..R.length.." walled enclosure", colors.yellow)
  14994.         menu.colourPrint("Using: "..R.useBlockType, colors.orange)
  14995.         retValue = createWallOrFence(R)
  14996.     elseif R.choice == 26 then  -- clear natural forest
  14997.         T:checkInventoryForItem({"minecraft:chest"}, {1})
  14998.         T:checkInventoryForItem({"sapling"}, {64}, false)
  14999.         menu.colourPrint("Clearing and replanting trees", colors.lime)
  15000.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15001.         retValue = clearAndReplantTrees()
  15002.     end
  15003.     return retValue
  15004. end
  15005.  
  15006. local function getTaskInventoryTo70(R)
  15007.     local retValue = {}
  15008.     local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n"
  15009.     -- FARMING
  15010.     if R.choice == 31 then  -- Create modular farm
  15011.         utils.checkFuelNeeded(300)
  15012.         T:checkInventoryForItem({"stone"}, {64})
  15013.         T:checkInventoryForItem({"dirt"}, {128}, false)
  15014.         T:checkInventoryForItem({"water_bucket"}, {4})
  15015.         if R.networkFarm then  
  15016.             T:checkInventoryForItem({"barrel"}, {1})
  15017.             T:checkInventoryForItem({"chest",}, {8})
  15018.             T:checkInventoryForItem({"ladder",}, {5})
  15019.             T:checkInventoryForItem({"wired_modem_full"}, {3})
  15020.             T:checkInventoryForItem({"computercraft:cable"}, {70})
  15021.         else    -- conventional storage farm
  15022.             T:checkInventoryForItem({"chest", "barrel"}, {5,5})
  15023.         end
  15024.         T:checkInventoryForItem({"sapling"}, {1})
  15025.         R.useBlockType = T:getMostItem("dirt", true) -- exclude dirt from count
  15026.         print(thanks)
  15027.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15028.         print("Creating modular farm with "..R.useBlockType)
  15029.         retValue = createFarm(R, "")
  15030.     elseif R.choice == 32 then  -- Extend modular farm
  15031.         utils.checkFuelNeeded(300)
  15032.         T:checkInventoryForItem({"sapling"}, {1})
  15033.         T:checkInventoryForItem({"stone"}, {64})
  15034.         T:checkInventoryForItem({"dirt"}, {128}, false)
  15035.         T:checkInventoryForItem({"water_bucket"}, {4})
  15036.         if R.networkFarm then  
  15037.             T:checkInventoryForItem({"barrel"}, {1})
  15038.             T:checkInventoryForItem({"ladder",}, {5})
  15039.             T:checkInventoryForItem({"wired_modem_full"}, {2})
  15040.             T:checkInventoryForItem({"computercraft:cable"}, {57})
  15041.         else    -- conventional storage farm
  15042.             T:checkInventoryForItem({"chest", "barrel"}, {5,5})
  15043.         end
  15044.         R.useBlockType = T:getMostItem("dirt", true) -- exclude dirt from count
  15045.         menu.colourPrint("Checking position...\n", colors.green)
  15046.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15047.         retValue = createFarmExtension(R) -- subChoice: 1 = ahead, 2 = to the right
  15048.     elseif R.choice == 33 then  -- manage modular farm
  15049.         -- inventory checked in function depending on option taken
  15050.         R.data = "farm"
  15051.         retValue = manageFarmSetup(R)
  15052.     elseif R.choice == 34 then  -- build single fence
  15053.         utils.checkFuelNeeded(R.length)
  15054.         T:checkInventoryForItem({"wall", "fence"}, {R.length, R.length})
  15055.         if R.torchInterval > 0 then
  15056.             T:checkInventoryForItem({"minecraft:torch"}, {math.ceil(R.length / R.torchInterval)}, false)
  15057.         end
  15058.         R.useBlockType = T:getMostItem("minecraft:torch") -- exclude torch
  15059.         menu.colourPrint("Creating "..R.length.." wall or fence", colors.green)
  15060.         menu.colourPrint("Using: "..R.useBlockType, colors.orange)
  15061.         retValue = createWallOrFence(R) -- barrels not included in R.data, R.width = 0 so only single length
  15062.     elseif R.choice == 35 then  -- build fence
  15063.         utils.checkFuelNeeded(R.width * R.length * 2)
  15064.         local quantity = math.ceil((R.width + R.length) * 2.3)
  15065.         T:checkInventoryForItem({"wall", "fence"}, {quantity, quantity})
  15066.         if R.torchInterval > 0 then
  15067.             T:checkInventoryForItem({"minecraft:torch"}, {math.floor(quantity / R.torchInterval)}, false)
  15068.         end
  15069.         R.useBlockType = T:getMostItem("minecraft:torch") -- exclude torch
  15070.         menu.colourPrint("Creating "..R.width.." x "..R.length.." walled enclosure", colors.green)
  15071.         menu.colourPrint("Using: "..R.useBlockType, colors.orange)
  15072.         retValue = createWallOrFence(R) -- barrels not included in R.data
  15073.     -- OBSIDIAN
  15074.     elseif R.choice == 41 then --harvest obsidian
  15075.         utils.checkFuelNeeded(R.width * R.length * 3)
  15076.         T:checkInventoryForItem({"stone"}, {R.width * R.length})
  15077.         T:checkInventoryForItem({"minecraft:bucket", "minecraft:lava_bucket"}, {1, 1}, false, "Get extra fuel as well!")
  15078.         menu.colourPrint("Harvesting obsidian area: size "..R.width.. " x "..R.length, colors.orange)
  15079.         sleep(2)
  15080.         retValue = harvestObsidian(R)
  15081.     elseif R.choice == 42 then --build nether portal
  15082.         utils.checkFuelNeeded(R.length * R.height * R.width)    -- length = width when facing standard = 5 high 4 length 1 width
  15083.         T:checkInventoryForItem({"minecraft:obsidian"}, {((R.length - 2 + R.height - 2) * R.width * 2)})
  15084.         T:checkInventoryForItem({"stone"}, {R.width * 4})
  15085.         R.useBlockType = T:getMostItem("obsidian", true) -- exclude obsidian from count
  15086.         menu.colourPrint("Building Nether portal", colors.orange)
  15087.         sleep(2)
  15088.         retValue = createPortal(R)
  15089.     elseif R.choice == 43 then --demolish nether portal
  15090.         utils.checkFuelNeeded(20)
  15091.         print("Demolishing Nether portal")
  15092.         retValue = demolishPortal(R)
  15093.     elseif R.choice == 44 then -- Strip mine Netherite
  15094.         utils.checkFuelNeeded(R.length * 2)
  15095.         T:checkInventoryForItem({"stone"}, {R.length * 4})
  15096.         R.useBlockType = T:getMostItem("", true) -- exclude none, use stone only/netherrack
  15097.         T:checkInventoryForItem({"cobble"}, {math.floor(R.length / 16) * 4}, true, "For marking Chunk boundaries")
  15098.         T:checkInventoryForItem({"minecraft:bucket", "minecraft:lava_bucket"}, {1, 1})
  15099.         T:checkInventoryForItem({"minecraft:torch"}, {math.floor(R.length / 16)}, false)
  15100.         retValue = createStripMine(R)
  15101.     elseif R.choice == 45 then --undermine dragon towers
  15102.         utils.checkFuelNeeded(500)
  15103.         T:checkInventoryForItem({"minecraft:cobblestone", "minecraft:cobbled_deepslate"}, {84, 84})
  15104.         print("Undermining dragon towers")
  15105.         retValue = undermineDragonTowers()
  15106.     elseif R.choice == 46 then --deactivate dragon tower
  15107.         utils.checkFuelNeeded(50)
  15108.         print("Deactivating dragon tower")
  15109.         retValue = deactivateDragonTower()
  15110.     elseif R.choice == 47 then --build dragon water trap
  15111.         utils.checkFuelNeeded(256)
  15112.         T:checkInventoryForItem({"stone"}, {356})
  15113.         T:checkInventoryForItem({"minecraft:obsidian"}, {1})
  15114.         T:checkInventoryForItem({"minecraft:ladder"}, {145})
  15115.         T:checkInventoryForItem({"minecraft:water_bucket"}, {1})
  15116.         print("Building dragon water trap")
  15117.         retValue = createDragonTrap()
  15118.     elseif R.choice == 48 then --build portal minecart station
  15119.         utils.checkFuelNeeded(200)
  15120.         menu.colourPrint("Inventory after height measurement", colors.red)
  15121.         menu.colourPrint("Enter to start measurement.", colors.lime)
  15122.         read()
  15123.         print("Building portal platform")
  15124.         retValue = createPortalPlatform()
  15125.     elseif R.choice == 49 then -- shulker harvesting
  15126.         retValue = harvestShulkers(R)
  15127.        
  15128.     -- CANAL BRIDGE
  15129.     elseif R.choice == 51 then  -- continuous path over void/water/lava
  15130.         utils.checkFuelNeeded(R.length) -- allow for R.length
  15131.         if R.data ~= "reduce" then
  15132.             T:checkInventoryForItem({"stone"}, {R.length}, false)
  15133.             if R.torchInterval > 0 then
  15134.                 T:checkInventoryForItem({"minecraft:torch"}, {math.floor(R.length/R.torchInterval)}, false)
  15135.             end
  15136.             print("Building continuous path")
  15137.         end
  15138.         retValue = utils.createPath(R) -- returns {numBlocks}
  15139.     elseif R.choice == 52 then  -- simple 2 block corridor
  15140.         utils.checkFuelNeeded(R.length)
  15141.         T:checkInventoryForItem({"stone"}, {R.length * 2}, false)
  15142.         if R.torchInterval > 0 then
  15143.             T:checkInventoryForItem({"minecraft:torch"}, {math.ceil(R.length / R.torchInterval)}, false)
  15144.         end
  15145.         print(thanks)
  15146.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15147.         print("Building simple corridor")
  15148.         retValue = createCorridor(R)
  15149.     elseif R.choice == 53 then  -- canal management
  15150.         local torches = 0
  15151.         local length = R.length
  15152.         if length > 0 then
  15153.             utils.checkFuelNeeded(length * 4) -- allow for 1024 R.length
  15154.             if R.torchInterval > 0 then
  15155.                 torches = math.floor(length / R.torchInterval)
  15156.             end
  15157.         else
  15158.             utils.checkFuelNeeded(2048) -- allow for 1024 R.length
  15159.             length = 256
  15160.         end
  15161.         T:checkInventoryForItem({"stone"}, {length})
  15162.         R.useBlockType = T:getMostItem("", true)
  15163.         if R.data == 1 or (R.data == 2 and (R.subChoice == 2 or R.subChoice == 3 or R.subChoice == 5 or R.subChoice == 6)) then
  15164.             T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
  15165.         end
  15166.         if torches > 0 then
  15167.             T:checkInventoryForItem({"minecraft:torch"}, {torches}, false)
  15168.         end
  15169.         retValue = createWaterCanal(R)
  15170.     elseif R.choice == 54 then  -- ice canal
  15171.         local default = R.length
  15172.         if R.length > 0 then
  15173.             utils.checkFuelNeeded(R.length)
  15174.         else
  15175.             default = 64
  15176.             utils.checkFuelNeeded(default * 2) -- allow for 128 min R.length
  15177.         end
  15178.         --[[
  15179.             new canal
  15180.             1 = left towpath- move to centre left
  15181.             2 = centre left ice or hollow
  15182.             3 = centre right ice or hollow
  15183.             4 = right side - move to centre right
  15184.             convert water canal
  15185.             5 = left towpath
  15186.             6 = centre left ice or air
  15187.             7 = centre right ice or air
  15188.             8 = right towpath
  15189.         ]]
  15190.         if R.subChoice <= 5 or R.subChoice == 8 then    -- towpath
  15191.             T:checkInventoryForItem({"slab"}, {default}, true, "Add slabs to length required")
  15192.         end
  15193.         if R.torchInterval > 0 then
  15194.             --checkInventoryForItem(items, quantities, required, message)
  15195.             T:checkInventoryForItem({"stone"}, {math.ceil(default / R.torchInterval)}, true, "NOT bricks!")
  15196.             R.useBlockType = T:getMostItem("", true)
  15197.             T:checkInventoryForItem({"torch"}, {math.ceil(default / R.torchInterval)}, false)
  15198.         end
  15199.         if R.data == "ice" then -- ice canal with 2 spaces above
  15200.             T:checkInventoryForItem({"minecraft:packed_ice", "minecraft:blue_ice"}, {math.ceil(R.length / 2), math.ceil(R.length / 2)}, false)
  15201.         end
  15202.         print(thanks)
  15203.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15204.         print("Building ice canal")
  15205.         retValue = createIceCanal(R)
  15206.     elseif R.choice == 55 then -- platform
  15207.         local volume = R.width * R.length
  15208.         utils.checkFuelNeeded(volume)
  15209.         T:checkInventoryForItem({"stone", "dirt"}, {volume, volume})
  15210.         R.useBlockType = T:getMostItem("", true)
  15211.         print(thanks)
  15212.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15213.         print("Building platform")
  15214.         retValue = createPlatform(R)
  15215.     elseif R.choice == 56 then -- sinking platform
  15216.         local volume = (R.width + 1) * (R.length + 1)
  15217.         utils.checkFuelNeeded(volume * (R.height + 1))
  15218.         T:checkInventoryForItem({"stone"}, {volume + ((R.length * 2) + (R.width * 2) * R.height) + 1})
  15219.         print(thanks)
  15220.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15221.         print("Building sinking platform")
  15222.         retValue = createSinkingPlatform(R)
  15223.     elseif R.choice == 57 then -- boat bubble lift
  15224.         utils.checkFuelNeeded(R.height * 20)
  15225.         T:checkInventoryForItem({"minecraft:bucket","minecraft:water_bucket"}, {2, 2})
  15226.         T:checkInventoryForItem({"stone"}, {R.height * 10})
  15227.         T:checkInventoryForItem({"gate"}, {R.height * 2})
  15228.         T:checkInventoryForItem({"minecraft:soul_sand"}, {R.height * 2 + 2})
  15229.         print(thanks)
  15230.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15231.         print("Building boat bubble lift")
  15232.         retValue = createBoatLift(R)
  15233.         --retValue = createBoatLift(R) -- R.subChoice:0=new, R.subChoice:1=extend, R.length:0=left, 1=right
  15234.        
  15235.     -- MOB SPAWNER
  15236.     elseif R.choice == 61 then  --  9x9 hollow cube cobble lined
  15237.         utils.checkFuelNeeded(600) -- allow for 600 moves
  15238.         T:checkInventoryForItem({"slab","stone"}, {1, 3}, true, "Slab can be crafted from 3 stone")
  15239.         if T:getItemSlot("stone") > 0 and T:getItemSlot("slab") == 0 then -- no slabs, but is stone
  15240.             local craftOK, message = T:craft("slab")
  15241.         end
  15242.         if R.data == "chest" then
  15243.             menu.colourText(nil, "~yellow~Chest(s) will be emptied first\nWait for me to exit and request\n~orange~around 700 stone!\n\n~lightGray~Enter to continue", true)
  15244.             read()
  15245.         else
  15246.             T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements")
  15247.         end
  15248.         print(thanks)
  15249.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15250.         retValue = createMobFarmCube(R) -- R.data = "spawner" or "chest": not blaze
  15251.     elseif R.choice == 62 then  -- Blaze spawner
  15252.         utils.checkFuelNeeded(2500) -- allow for 2500 moves
  15253.         if R.data == "blaze" then
  15254.             T:checkInventoryForItem({"slab"}, {122}, true)
  15255.             T:checkInventoryForItem({"stone"}, {576})
  15256.             print("You will be asked for more assets later")
  15257.             print("Enter to continue")
  15258.             read()
  15259.         end  -- else R.data == "restart"
  15260.         retValue = createMobFarmCube(R) --R.data = "blaze" or R.data = "restart"
  15261.     elseif R.choice == 63 then  --  flood mob spawner
  15262.         utils.checkFuelNeeded(60) -- allow for 60 moves
  15263.         T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
  15264.         if R.subChoice == 1 then
  15265.             T:checkInventoryForItem({"fence"}, {2})
  15266.             T:checkInventoryForItem({"sign"}, {2})
  15267.             T:checkInventoryForItem({"slab"}, {1})
  15268.             T:checkInventoryForItem({"minecraft:soul_sand", "minecraft:dirt"}, {1, 1}, true)
  15269.         end
  15270.         print(thanks)
  15271.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15272.         retValue = floodMobFarm(R)
  15273.     elseif R.choice == 64 then -- build bubble lift on top of soul sand
  15274.         utils.checkFuelNeeded(200) -- allow for 200 moves
  15275.         T:checkInventoryForItem({"slab","stone"}, {6, 3}, true, "Slabs can be crafted from 3 stone")
  15276.         if T:getItemSlot("stone") > 0 and T:getItemSlot("slab") == 0 then -- no slabs, but is stone
  15277.             local craftOK, message = T:craft("slab")
  15278.         end
  15279.         T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
  15280.         T:checkInventoryForItem({"stone"}, {256})
  15281.         if T:getBlockType("down") ~= "minecraft:soul_sand" then
  15282.             T:checkInventoryForItem({"minecraft:soul_sand"}, {1})
  15283.         end
  15284.         T:checkInventoryForItem({"hopper"}, {1}, false)
  15285.         if T:getItemSlot("hopper") > 0 then
  15286.             T:checkInventoryForItem({"chest"}, {2})
  15287.         end
  15288.         print(thanks)
  15289.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15290.         retValue = createMobBubbleLift(R)
  15291.     elseif R.choice == 65 then -- computercraft mob grinder
  15292.         utils.checkFuelNeeded(1000) -- allow for 1000 moves
  15293.         T:checkInventoryForItem({"stone"}, {256}) -- for ceiling, walls and floor of area
  15294.         R.useBlockType = T:getMostItem("", true) -- stone only, no exclusions
  15295.         print(thanks)
  15296.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15297.         retValue = createMobGrinder(R)
  15298.     elseif R.choice == 66 then -- build endermen tower
  15299.         -- build in 3 sections, base, tower, top
  15300.         getTaskHelp(2, 66) -- compulsory help display
  15301.         read() -- pause until user ready
  15302.         local numFuel = 700
  15303.         local choices =
  15304.         {
  15305.             "New tower lower base",
  15306.             "Add tower upper base + killzone",
  15307.             "128 block tower to existing base"
  15308.         }
  15309.         pp.itemColours = {colors.lime, colors.orange, colors.green}
  15310.         local option, modifier = menu.menu("Select build stage:", choices, pp)
  15311.         if option == 1 then --lower base
  15312.             T:checkInventoryForItem({"minecraft:chest"}, {1})
  15313.             T:place("chest", "down", false)
  15314.             T:emptyInventory("up")
  15315.             utils.checkFuelNeeded(320) -- allow for 320 moves
  15316.             T:checkInventoryForItem({"stone"}, {144}) -- <3 stacks
  15317.             T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
  15318.             T:checkInventoryForItem({"fence"}, {4})
  15319.             T:checkInventoryForItem({"sign"}, {4})
  15320.             T:checkInventoryForItem({"door"}, {2})
  15321.             T:checkInventoryForItem({"minecraft:soul_sand"}, {1})
  15322.         elseif option == 2 then -- upper base
  15323.             utils.checkFuelNeeded(710) -- allow for 703 moves
  15324.             T:checkInventoryForItem({"stone"}, {384}) -- 6 stacks
  15325.             T:checkInventoryForItem({"minecraft:bucket"}, {4})
  15326.             T:checkInventoryForItem({"fence"}, {15})
  15327.             T:checkInventoryForItem({"sign"}, {4})
  15328.             T:checkInventoryForItem({"ladder"}, {3})
  15329.             T:checkInventoryForItem({"minecraft:soul_sand"}, {1})
  15330.         else -- main tower
  15331.             utils.checkFuelNeeded(3000) -- allow for 3000 moves
  15332.             if T:getBlockType("down") ~= "minecraft:chest" then
  15333.                 T:checkInventoryForItem({"minecraft:chest"}, {1})
  15334.                 T:place("chest", "down", false)
  15335.             end
  15336.             T:checkInventoryForItem({"stone"}, {768}) -- 12 stacks
  15337.             T:checkInventoryForItem({"minecraft:bucket"}, {10})
  15338.             T:checkInventoryForItem({"fence"}, {64})    -- 1 stacks    
  15339.         end
  15340.         print(thanks)
  15341.         os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15342.         retValue = createEnderTower(option) -- 1, 2, or 3
  15343.     elseif R.choice == 67 then -- surround Trial spawner
  15344.         utils.checkFuelNeeded(200) -- allow for 1000 moves
  15345.         T:checkInventoryForItem({"stone"}, {57}) -- for covering spawner
  15346.         R.useBlockType = T:getMostItem("", false) -- use whatever block type available
  15347.         R.height = 3
  15348.         R.width = 5
  15349.         R.length = 5
  15350.         retValue = createTrialCover(R)
  15351.     end
  15352.     return retValue
  15353. end
  15354.  
  15355. local function getTaskInventory(R)
  15356.     -- run this loop 2x per second to check if player has put anything in the inventory
  15357.     -- fuel 1 coal = 60 = 4 planks. 64 planks = 16 coal = 960 units
  15358.     local retValue = {}
  15359.     local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n"
  15360.    
  15361.     if R.choice < 31 then
  15362.         return getTaskInventoryTo30(R) -- Mining, Forestry
  15363.     elseif R.choice < 71 then
  15364.         return getTaskInventoryTo70(R) -- Farming, Obsidian, Canal / Bridge
  15365.     elseif R.choice > 500 and R.choice < 700 then
  15366.         return getTaskInventoryTo70(R)
  15367.     else -- Area carving, Lava/Water, Railway
  15368.         -- AREA CARVING
  15369.         if R.choice == 71 then--Clear area
  15370.             utils.checkFuelNeeded(R.width * R.length * 3)
  15371.             if R.useBlockType == "dirt" then
  15372.                 T:checkInventoryForItem({"minecraft:dirt"}, {R.width * R.length})
  15373.             end
  15374.             print(thanks)
  15375.             sleep(2)
  15376.             print("Clearing area: size "..R.width.. " x "..R.length)
  15377.             retValue = clearArea(R)
  15378.         elseif R.choice == 72 then --Clear rectangle
  15379.             -- R.choice, R.width(R.subChoice), R.length(R.width), up(R.length), down(R.height) from getTask()
  15380.             utils.checkFuelNeeded(R.width * R.length)
  15381.             print("Clearing rectangle: size "..R.width.. " x "..R.length)
  15382.             retValue = clearRectangle(R)
  15383.         elseif R.choice == 73 then --Clear wall
  15384.             utils.checkFuelNeeded(R.length * R.height)
  15385.             print("Removing wall "..R.length.." long x "..R.height.." high")
  15386.             retValue = clearWall(R)
  15387.         elseif R.choice == 74 then --Clear single R.height perimeter wall
  15388.             utils.checkFuelNeeded((R.width + R.length) * 2)
  15389.             print("Recycling wall section "..R.width.." x "..R.length)
  15390.             retValue = clearPerimeter(R)
  15391.         elseif R.choice == 75 then --Clear hollow structure
  15392.             utils.checkFuelNeeded((R.width * R.length) + ((R.width + R.length) * R.height))
  15393.             print("Recycling hollow object "..R.width.." x "..R.length.." height: "..R.height)
  15394.             retValue = clearBuilding(R)
  15395.         elseif R.choice == 76 then --Clear solid structure / extend water pool
  15396.             utils.checkFuelNeeded((R.width * R.length) + ((R.width + R.length) * R.height))
  15397.             print("Recycling solid object w:"..R.width..", l:"..R.length..", h:"..R.height)
  15398.             retValue = clearSolid(R)
  15399.         elseif R.choice == 77 then  -- Dig trench
  15400.             utils.checkFuelNeeded(R.height * R.length * 2)
  15401.             print(thanks)
  15402.             os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15403.             if R.length == 0 then
  15404.                 print("Digging continuous trench "..R.height.." blocks deep")
  15405.             else
  15406.                 print("Digging trench "..R.length.." blocks long, "..R.height.." blocks deep")
  15407.             end
  15408.             retValue = digTrench(R)
  15409.         elseif R.choice == 78 then --Carve mountain
  15410.             utils.checkFuelNeeded(R.length * R.width * 10)
  15411.             print("Carving mountain side "..R.width.." x "..R.length)
  15412.             retValue = clearMountainSide(R)
  15413.         elseif R.choice == 79 then -- Place floor or Ceiling
  15414.             local blocks = R.width * R.length
  15415.             utils.checkFuelNeeded(blocks)
  15416.             T:clear()
  15417.             local inventory = T:getInventory()
  15418.             repeat
  15419.                 T:clear()
  15420.                 --colourText(row, text, reset)
  15421.                 menu.colourText(1, "~yellow~Add floor/ceiling blocks to inventory", false)
  15422.                 menu.colourText(2, "~orange~Multiple types will allow patterns", false)
  15423.                 if blocks - inventory.blockCount > 0 then
  15424.                     menu.colourText(3, "~lime~Add ~red~"..blocks - inventory.blockCount .." ~lime~blocks", false)
  15425.                 else
  15426.                     menu.colourText(3, "~lime~Minimum number of blocks recieved ~red~("..blocks..")", false)
  15427.                     menu.colourText(5, "~yellow~Add more or press ~red~'Enter'~yellow~ to start", true)
  15428.                 end
  15429.                
  15430.                 inventory = T:updateInventory() -- returns inventory or nil if key pressed
  15431.             until inventory == nil
  15432.             --T:checkInventoryForItem({"stone", "log", "planks"}, {blocks, blocks, blocks}, false)
  15433.             R.inventory = T:getInventory()
  15434.             --[[
  15435.                 {
  15436.                 inventory["minecraft:cobblestone"] = 128
  15437.                 inventory["minecraft:stone"] = 64
  15438.                 inventory.names = {minecraft:cobblestone, minecraft:stone}
  15439.                 inventory.quantities = {128, 64}
  15440.                 inventory.blockTypeCount = 2,
  15441.                 inventory.blockCount = 196,
  15442.                 inventory.useBlock = "minecraft:cobblestone"
  15443.                 inventory.mostBlock = "minecraft:cobblestone"
  15444.                 inventory.mostCount = 128
  15445.                 }
  15446.             ]]
  15447.             R.useBlockType = R.inventory.useBlock
  15448.             -- check if > 1 type of material, then use R.data == "random"
  15449.             T:clear()
  15450.             if R.inventory.blockTypeCount > 1 then
  15451.                 local choice, modifier
  15452.                 local choices = {"Random block placement", "Striped pattern"}
  15453.                 pp.itemColours = {colors.lime, colors.orange}
  15454.                 if R.inventory.blockTypeCount == 2 then
  15455.                     table.insert(choices, "Checkerboard pattern")
  15456.                     table.insert(pp.itemColours, colors.green)
  15457.                 end
  15458.                 choice, modifier = menu.menu("Layout pattern?", choices, pp, "Type number + Enter ")
  15459.                 if choice == 1 then
  15460.                     R.data = "random"
  15461.                 elseif choice == 2 then
  15462.                     R.data = "striped"
  15463.                 else
  15464.                     R.data = "checked"
  15465.                 end
  15466.             end
  15467.             retValue = createFloorCeiling(R) -- R.subChoice integer 1 to 4
  15468.         elseif R.choice == 710 then -- direct commands
  15469.             utils.checkFuelNeeded(200)
  15470.             createRectanglePath(R)
  15471.            
  15472. -- LAVA WATER
  15473.         elseif R.choice == 81 then -- Sand based utilities
  15474.             if R.subChoice == 1 then    -- Drop sand or gravel wall
  15475.                 utils.checkFuelNeeded(100)
  15476.                 T:checkInventoryForItem({"sand", "gravel"}, {1024, 1024}, false)
  15477.                 if R.length == 0 then
  15478.                     print("Building sand wall. Auto length: ")
  15479.                 else
  15480.                     print("Building sand wall. length: "..R.length)
  15481.                 end
  15482.                 retValue = createSandWall(R)
  15483.             elseif R.subChoice == 2 then    -- Fill area with sand
  15484.                 utils.checkFuelNeeded(R.length * R.width)
  15485.                 T:checkInventoryForItem({"sand"}, {1024}, false)
  15486.                 print("Filling area with sand. length: "..R.length.." width: "..R.width)
  15487.                 retValue = sandFillArea(R)
  15488.             elseif R.subChoice == 3 then -- Clear sand wall
  15489.                 utils.checkFuelNeeded(200)
  15490.                 if R.length == 0 then
  15491.                     print("Digging sand. Auto length")
  15492.                 else
  15493.                     print("Digging sand. length: "..R.length)
  15494.                 end
  15495.                 retValue = clearSandWall(R)
  15496.             elseif R.subChoice == 4 then    -- Clear sand filled area
  15497.                 utils.checkFuelNeeded(R.length * R.width * 4)
  15498.                 print("Removing sand cube. length: "..R.length.." width: "..R.width)
  15499.                 retValue = clearSandCube(R)
  15500.             end
  15501.        
  15502.         elseif R.choice == 82 then --build containing wall in water or lava
  15503.             utils.checkFuelNeeded(R.length * R.length)
  15504.             local depth = R.height
  15505.             if depth == 0 then
  15506.                 depth = 20
  15507.             end
  15508.             T:checkInventoryForItem({"stone"}, {R.length * depth}, false)
  15509.             print("Building retaining wall in lava/water. length "..R.length)
  15510.             retValue = createRetainingWall(R)          
  15511.         elseif R.choice == 83 then -- create a rectangle path in water/lava
  15512.             utils.checkFuelNeeded(200)
  15513.             createRectanglePath(R)
  15514.         elseif  R.choice == 84 then -- Delete water/lava
  15515.             if R.width == 0 then
  15516.                 utils.checkFuelNeeded(2000)
  15517.                 T:checkInventoryForItem({"stone"}, {256}, false)
  15518.                 print("Deleting water using auto-detection")
  15519.             else
  15520.                 if R.height == 0 then
  15521.                     utils.checkFuelNeeded(2000)
  15522.                     T:checkInventoryForItem({"stone"}, {256}, false)
  15523.                 else
  15524.                     utils.checkFuelNeeded(R.width * R.length * R.height)
  15525.                     T:checkInventoryForItem({"stone"}, {math.max(R.length, R.width) * 2}, false)
  15526.                 end
  15527.                 print("Deleting enclosed water "..R.width.." x "..R.length.." x ".. R.height)
  15528.             end
  15529.             retValue = utils.drainWaterLava(R)
  15530.         elseif  R.choice == 85 then -- Sinking platform
  15531.             local volume = (R.width + 1) * (R.length + 1)
  15532.             utils.checkFuelNeeded(volume * (R.height + 1))
  15533.             T:checkInventoryForItem({"stone"}, {volume + ((R.length * 2) + (R.width * 2) * R.height) + 1})
  15534.             print(thanks)
  15535.             os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15536.             print("Building sinking platform")
  15537.             retValue = createSinkingPlatform(R)
  15538.         elseif R.choice == 86 then -- ocean monument utilities
  15539.             if R.subChoice == 1 then    -- Build 4 corner marker columns
  15540.                 --R.useBlockType = "prismarine", R.data = "oceanMonumentColumns"
  15541.                 T:checkInventoryForItem({"stone"}, {448})
  15542.                 retValue = oceanMonumentColumns(R)
  15543.             elseif R.subChoice == 2 then    -- Retaining wall beween 2 columns
  15544.                 T:checkInventoryForItem({"stone"}, {1024})
  15545.                 retValue = createRetainingWall(R)
  15546.             elseif R.subChoice == 3 then    -- Clear plants pre sand draining
  15547.                 retValue = clearWaterPlants(R)
  15548.             elseif R.subChoice == 4 then    -- Use sand draining
  15549.                 utils.checkFuelNeeded(100)
  15550.                 T:checkInventoryForItem({"sand", "gravel"}, {1024, 1024}, false)
  15551.                 if R.length == 0 then
  15552.                     print("Building sand wall. Auto length: ")
  15553.                 else
  15554.                     print("Building sand wall. length: "..R.length)
  15555.                 end
  15556.                 retValue = createSandWall(R)
  15557.             elseif R.subChoice == 5 then    -- remove sand wall
  15558.                 utils.checkFuelNeeded(200)
  15559.                 print("Digging sand from ocean monument")
  15560.                 retValue = clearSandWall(R)
  15561.             elseif R.subChoice == 6 then    -- Drain and remove structure
  15562.                 T:checkInventoryForItem({"stone"}, {1024})
  15563.                 retValue = utils.drainWaterLava(R)
  15564.             end
  15565.         elseif R.choice == 87 then --ladder to water/lava
  15566.             utils.checkFuelNeeded(R.height * 2)
  15567.             T:checkInventoryForItem({"minecraft:ladder"}, {R.height}, true, "Add more to be safe!")
  15568.             local cobble = R.height * 3 + 10
  15569.             T:checkInventoryForItem({"stone"}, {cobble})
  15570.             print(thanks)
  15571.             os.sleep(2)    -- pause for 2 secs to allow time to press esc
  15572.             print("Creating ladder to bedrock")
  15573.             retValue = createLadderToWater()
  15574.         elseif R.choice == 88 then --remove plants
  15575.             utils.checkFuelNeeded(R.length * R.width * 4)
  15576.             T:checkInventoryForItem({"sand", "stone"}, {64, 64})
  15577.             local width = R.width
  15578.             local length = R.length
  15579.             if width == 0 then
  15580.                 width = "auto"
  15581.             end
  15582.             if length == 0 then
  15583.                 length = "auto"
  15584.             end
  15585.             print("Removing water plants. length: "..length.." width: "..width)
  15586.             retValue = clearWaterPlants(R)
  15587.         elseif R.choice == 89 then -- convert flowing water to source
  15588.             --utils.checkFuelNeeded(R.length * R.width * 4) -- unknown as size not calculated
  15589.             T:checkInventoryForItem({"water_bucket", "bucket"}, {12, 12})
  15590.             T:checkInventoryForItem({"slab"}, {128})
  15591.             print("Converting water to source "..R.width.." x "..R.length.." x ".. R.height)
  15592.             retValue = convertWater(R)
  15593.         elseif R.choice == 810 then -- create sloping water
  15594.             utils.checkFuelNeeded(R.length * R.width * 3)
  15595.             local buckets = math.floor(R.length / 2) + 1
  15596.             T:checkInventoryForItem({"water_bucket", "bucket"}, {buckets, buckets})
  15597.             T:checkInventoryForItem({"slab"}, {R.length * R.width})
  15598.             print("Creating sloping water field "..R.width.." x "..R.length.." x ".. R.height)
  15599.             retValue = createSlopingWater(R)
  15600.         -- BUILDING & RAILWAY
  15601.         elseif R.choice == 91 then -- Build a wall
  15602.             local blocks = R.height * R.length
  15603.             utils.checkFuelNeeded(blocks)
  15604.             T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks})
  15605.             R.useBlockType = T:getMostItem()
  15606.             print("Building a wall using "..R.useBlockType)
  15607.             sleep(2)
  15608.             retValue = buildWall(R)
  15609.         elseif R.choice == 92 then -- Build a rectangular structure
  15610.             local blocks = (R.height * R.length * 2) + (R.height * R.width * 2)
  15611.             utils.checkFuelNeeded(blocks)
  15612.             T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks})
  15613.             R.useBlockType = T:getMostItem()
  15614.             print("Building a house using "..R.useBlockType)
  15615.             sleep(2)
  15616.             retValue = buildStructure(R)
  15617.         elseif R.choice == 93 or R.choice == 94 then -- Build a gable end roof / pitched roof
  15618.             local blocks = ((R.width + 2) * (R.length + 2))
  15619.             utils.checkFuelNeeded(blocks)
  15620.             if menu.getBoolean("Using stairs / planks for roof (y/n)", nil, colors.yellow) then
  15621.                 T:checkInventoryForItem({"planks", "stairs"}, {blocks, blocks})
  15622.             else
  15623.                 T:checkInventoryForItem({"stone"}, {blocks})
  15624.             end
  15625.            
  15626.             R.useBlockType = T:getMostItem()
  15627.             if R.choice == 93 then              -- Build a gableroof
  15628.                 if R.width % 2 == 1 then
  15629.                     T:checkInventoryForItem({"slab"}, {R.length + 2}, false, "Match slabs with roof blocks")
  15630.                 end
  15631.                 blocks = (R.width * 6)
  15632.                 T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks}, true, "Match gable with existing building")
  15633.             else
  15634.                 local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0
  15635.                 R, isWidthOdd, isLengthOdd, width, length = utils.getRoofStats(R)
  15636.                 if isWidthOdd then
  15637.                     T:checkInventoryForItem({"slab"}, {length - 2}, false, "Match slabs with roof blocks")
  15638.                 end
  15639.             end
  15640.             print("Building a roof using "..R.useBlockType)
  15641.             sleep(2)
  15642.             if R.choice == 93 then              -- Build a gableroof
  15643.                 retValue = buildGableRoof(R)
  15644.             else                                -- Build a pitched roof
  15645.                 retValue = buildPitchedRoof(R)
  15646.             end
  15647.         elseif R.choice == 95 or R.choice == 96 then --place redstone torch level or downward slope
  15648.             utils.checkFuelNeeded(10)
  15649.             if R.choice == 95 then
  15650.                 R.data = "level"
  15651.             else
  15652.                 R.data = "up"
  15653.             end
  15654.             T:checkInventoryForItem({"stone"}, {1})
  15655.             R.useBlockType = T:getMostItem("", true)
  15656.             T:checkInventoryForItem({"minecraft:redstone_torch"}, {1})
  15657.             print("Placing redstone torch on ".. R.useBlockType)
  15658.             retValue = placeRedstoneTorch(R)
  15659.         elseif R.choice == 97 or R.choice == 98 then --build downward/upward slope
  15660.             local blocks = R.height * 2
  15661.             if R.height == 0 then
  15662.                 blocks = 64
  15663.             end
  15664.             utils.checkFuelNeeded(blocks)
  15665.             T:checkInventoryForItem({"stone"}, {blocks})
  15666.             print("Building slope")
  15667.             sleep(2)
  15668.             retValue = createRailway(R)
  15669.         elseif R.choice == 101 or R.choice == 102 or R.choice == 103 or R.choice == 104 then -- measure height/depth/length
  15670.             retValue = measure(R)
  15671.         elseif R.choice == 105 then--Borehole
  15672.             retValue = createBorehole(R)
  15673.         elseif R.choice == 111 then --craft an item
  15674.             retValue = utils.craftItem(R)
  15675.         elseif R.choice == 112 then --MysticalAgriculture essence conversion
  15676.             retValue = utils.convertEssence(R)
  15677.         end
  15678.     end
  15679.     return retValue
  15680. end
  15681.  
  15682. local function test(R)
  15683.     local lib = {}
  15684.    
  15685.     function lib.dig(direction, bypass, slot)
  15686.         direction = direction or "forward"
  15687.         slot = slot or 1
  15688.         bypass = bypass or true
  15689.        
  15690.         print("direction: "..direction)
  15691.         print("bypass: "..tostring(bypass))
  15692.         print("slot: "..slot)
  15693.        
  15694.     end
  15695.     lib.dig("down")
  15696.     read()
  15697. end
  15698.  
  15699. local function main()
  15700.     local lib = {}
  15701.    
  15702.     function lib.checkLabel()
  15703.         if os.getComputerLabel() == nil then
  15704.             os.setComputerLabel("toolkit")
  15705.             print("Computer label set to "..os.getComputerLabel())
  15706.         end
  15707.     end
  15708.    
  15709.     function lib.checkLibs(libDir, filename)
  15710.         local fileExists = false
  15711.         if fs.exists(libDir) then
  15712.             if not fs.isDir(libDir) then
  15713.                 fs.move(libDir, libDir.."Renamed")
  15714.                 fs.makeDir(libDir)
  15715.             end
  15716.         else
  15717.             fs.makeDir(libDir)
  15718.         end
  15719.         if fs.exists(fs.combine(libDir, filename)) or fs.exists(fs.combine(libDir, filename..".lua")) then
  15720.             fileExists = true
  15721.         end
  15722.         return fileExists
  15723.     end
  15724.    
  15725.     local doContinue = true
  15726.     lib.checkLabel() -- make sure turtle label is set
  15727.     --check if lib folder exists
  15728.     if not lib.checkLibs("lib", "clsTurtle") then
  15729.         -- use pastebin get to download clsTurtle to libs folder
  15730.         print("Missing clsTurtle.lua in libs directory")
  15731.         print("Attempting to obtain from Pastebin...")
  15732.         if shell.run("pastebin","get","tvfj90gK","lib/clsTurtle.lua") then
  15733.             print("clsTurtle.lua installed from Pastebin")
  15734.         else
  15735.             print("failed to install clsTurtle.lua from Pastebin")
  15736.             doContinue = false
  15737.         end
  15738.     end
  15739.     if not lib.checkLibs("lib", "menu") then
  15740.         -- use pastebin get to download menu.lua to libs folder
  15741.         print("Missing menu.lua in libs directory")
  15742.         print("Attempting to obtain from Pastebin...")
  15743.         if shell.run("pastebin","get","BhjbYsw4","lib/menu.lua") then
  15744.             print("menu.lua installed from Pastebin")
  15745.         else
  15746.             print("failed to install menu.lua from Pastebin")
  15747.             doContinue = false
  15748.         end
  15749.     end
  15750.     if doContinue then
  15751.         local result = {}
  15752.         local R =
  15753.         {
  15754.             choice = 0,
  15755.             subChoice = 0,
  15756.             size = 0,
  15757.             width = 0,
  15758.             length = 0,
  15759.             height = 0,
  15760.             depth = 0,
  15761.             up = false,
  15762.             down = false,
  15763.             silent = false,
  15764.             data = {},
  15765.             torchInterval = 0,
  15766.             useBlockType = "",
  15767.             auto = false,
  15768.             side = "",
  15769.             direction = "",
  15770.             ready = false,
  15771.             networkFarm = false,
  15772.             mysticalAgriculture = false,
  15773.             logType = "",
  15774.             treeSize = "",
  15775.             message = "",
  15776.             inventory = {}
  15777.         }
  15778.         menu = require("lib.menu")
  15779.         T = require("lib.clsTurtle").new(false) -- true enables logfile to log.txt note dot NOT colon
  15780.         T:clear()
  15781.         doContinue = false  -- reset
  15782.         if args[1] ~= nil then
  15783.             if args[1]:sub(1,1) == "h" then
  15784.                 local help =
  15785. [[... = any following characters
  15786.  
  15787. tk v...     = mc/ccTweaked versions
  15788. tk log      = enable logging
  15789. tk log d... = enable logging + debug
  15790. tk find     = writes locate.txt
  15791. tk test     = runs test(R)
  15792. tk farm     = runs manageFarm(R)
  15793.  
  15794.  
  15795.  
  15796. Enter to exit]]
  15797.                 menu.colourPrint(help, colours.yellow)
  15798.                 read()
  15799.             elseif args[1] == "log" then
  15800.                 if args[2] ~= nil then
  15801.                     if args[2]:sub(1,1) == "d" then
  15802.                         dbug = true -- set dbug flag
  15803.                         menu.colourPrint("Logging and debugging enabled", colors.lime)
  15804.                     end
  15805.                 else
  15806.                     menu.colourPrint("Logging enabled", colors.lime)
  15807.                 end
  15808.                 if T:getLogExists() then
  15809.                     if menu.getBoolean("Delete existing log file? (y/n)", 3, colors.orange) then
  15810.                         T:deleteLog()
  15811.                         menu.colourPrint("Log file deleted", colors.yellow)
  15812.                     end
  15813.                 end
  15814.                 T:setUseLog(true)
  15815.                 doContinue = true
  15816.                 utils.waitForInput()
  15817.                 --if dbug then
  15818.                     --menu.colourPrint("Enter to continue...", colors.lightBlue)
  15819.                     --read()
  15820.                 --end
  15821.             elseif args[1] == "farm" then
  15822.                 R.silent = true
  15823.                 R.data = "farm"
  15824.                 R.auto = true
  15825.                 manageFarm(R)
  15826.             --elseif args[1] == "tree" then
  15827.                 --R.silent = true
  15828.                 --R.data = "treefarm"
  15829.                 --R.auto = true
  15830.                 --manageTreeFarm(R) -- use file to read status
  15831.             elseif args[1] == "find" then
  15832.                 -- missing turtle: player used 'tk find'
  15833.                 T:setUseLog(true)
  15834.                 T:setLogFileName("locate.txt")
  15835.                 T:appendLine("Booting succeeded")
  15836.                 T:appendLine("Block ahead: "..T:getBlockType("forward"))
  15837.                 T:appendLine("Block above: "..T:getBlockType("up"))
  15838.                 T:appendLine("Block below: "..T:getBlockType("down"))
  15839.             elseif args[1] == "test" then
  15840.                 test(R)
  15841.             elseif args[1]:find("v") ~= nil then
  15842.                 print("_HOST:")
  15843.                 print()
  15844.                 print(_HOST)
  15845.                 print()
  15846.                 print("Minecraft major version: "..mcMajorVersion)
  15847.                 print("Minecraft minor version: "..mcMinorVersion)
  15848.                 print("ccTweaked major version: "..ccMajorVersion)
  15849.                 print("ccTweaked minor version: "..ccMinorVersion)
  15850.                 print("tk version:              "..tkVersion)
  15851.                 print("clsTurtle version:       "..version)
  15852.                 print("\nEnter to exit")
  15853.                 read()
  15854.             end
  15855.         else
  15856.             doContinue = true
  15857.         end
  15858.         if doContinue then
  15859.             print("Minecraft major version: "..mcMajorVersion)
  15860.             print("Bedrock level: "..bedrock)
  15861. -- T:setUseLog(use, filename, delete)
  15862. --T:setUseLog(true, "log.txt", true)
  15863.             if T:getUseLog() then
  15864.                 if T:saveToLog("Started with logging enabled", true) then
  15865.                     menu.colourPrint("\nEnter to continue...", colors.lightBlue)
  15866.                     read()
  15867.                 end
  15868.             else
  15869.                 print("Logging disabled")
  15870.             end
  15871.             sleep(1)
  15872.             while R.choice == 0 do
  15873.                 R = chooseTask(R)
  15874.             end
  15875.             if R.choice > 0 then
  15876.                 R = getTask(R)
  15877.                 if R.data ~= "quit" then
  15878.                     result = getTaskInventory(R) -- table of comments
  15879.                 end
  15880.             end
  15881.         end
  15882.         T:clear()
  15883.         table.insert(result, "Thank you for using 'survival toolkit'")
  15884.         local clr = {colors.yellow, colors.orange, colors.green, colors.lightBlue}
  15885.         local count = 1
  15886.         for _, value in ipairs(result) do
  15887.             --print(value)
  15888.             --.print(text, fg, bg, width)
  15889.             menu.colourPrint(tostring(value), clr[count])
  15890.             count = count + 1
  15891.             if count > #clr then
  15892.                 count = 1
  15893.             end
  15894.         end
  15895.     else
  15896.         print("Add missing files and restart")
  15897.     end
  15898. end
  15899.  
  15900. main()
Add Comment
Please, Sign In to add comment