View difference between Paste ID: C1nGR1dA and UFvjc1bw
SHOW: | | - or go back to the newest paste.
1-
version = 20241122.1730
1+
version = 20231005.1900
2
3
local tkVersion = version -- otherwise over-written by clsTurtle when loaded
4
--[[
5
	**********Toolkit v2**********
6
	https://pastebin.com/UFvjc1bw
7
	Last edited: see version YYYYMMDD.HHMM
8
	if NOT online:
9
		Make sure you create a folder 'lib' and place menu.lua and clsTurtle.lua into it
10
	else
11
		lib folder will be created and files obtained automatically!
12
	end
13
]]
14
15
args = {...} -- eg "farm", "tree"
16
17
local menu, T
18
--[[
19
Computercraft started with mc version 1.7.10 and went to 1.8.9
20-
ccTweaked started around mc 1.12.2 and currently at 1.21.1
20+
ccTweaked started around mc 1.12.2 and currently at 1.18
21-
mc 1.18 onwards has new blocks and bedrock at -64, so needs to be taken into account.
21+
mc 1.18 has new blocks and bedrock at -64, so needs to be taken into account.
22
_HOST = The ComputerCraft and Minecraft version of the current computer environment.
23
For example, ComputerCraft 1.93.0 (Minecraft 1.15.2).
24
]]
25
local dbug = false -- debug is reserved word
26
local bedrock = 0
27
local netherBedrock = 0
28
local ceiling = 255
29
local deletesWater = false
30
local brick = "minecraft:nether_brick" -- pre 1.16+ name
31
local ccMajorVersion = _HOST:sub(15, _HOST:find("Minecraft") - 2) --eg ComputerCraft 1.93.0 (Minecraft 1.15.2)
32
local ccMinorVersion = 0
33-
local barrelItems = nil	-- list of items and the barrels where they are usually found
33+
34-
local chestItems = nil	-- list of items and the chests where they are usually found
34+
35
Chunk borders F3+G or:
36
math.floor(x / 16) * 16 add 16 for each border. same for z
37
]]
38
function string:split(sSeparator, nMax, bRegexp, noEmpty)
39
	--[[return a table split with sSeparator. noEmpty removes empty elements
40
		use: tblSplit = SplitTest:split('~',[nil], [nil], false) or tblSplit = string.split(SplitTest, '~')]]   
41
	assert(sSeparator ~= '','separator must not be empty string')
42
	assert(nMax == nil or nMax >= 1, 'nMax must be >= 1 and not nil')
43
	if noEmpty == nil then noEmpty = true end
44
45
	local aRecord = {}
46
	local newRecord = {}
47
	-- self refers to the 'string' being split
48
	if self:len() > 0 then
49
		local bPlain = not bRegexp
50
		nMax = nMax or -1
51
52
		local nField, nStart = 1, 1
53
		local nFirst,nLast = self:find(sSeparator, nStart, bPlain)
54
		while nFirst and nMax ~= 0 do
55
			aRecord[nField] = self:sub(nStart, nFirst-1)
56
			nField = nField+1
57
			nStart = nLast+1
58
			nFirst,nLast = self:find(sSeparator, nStart, bPlain)
59
			nMax = nMax-1
60
		end
61
		aRecord[nField] = self:sub(nStart)
62
		
63
		if noEmpty then --split on newline preserves empty values
64
			for i = 1, #aRecord do
65
				if aRecord[i] ~= "" then
66
					table.insert(newRecord, aRecord[i])
67
				end
68
			end
69
		else
70
			newRecord = aRecord
71
		end
72
	end
73
	
74
	return newRecord
75
end
76
77
if tonumber(ccMajorVersion) == nil then -- 1.93.0 NAN
78
	--ccMajorVersion = ccMajorVersion:sub(1, ccMajorVersion:find(".", 3, true) - 1)
79
	local parts = ccMajorVersion:split(".")
80
	ccMajorVersion = parts[1]
81
	if parts[2] ~= nil then
82
		ccMajorVersion = ccMajorVersion.."."..parts[2]
83
	end
84
	ccMajorVersion = tonumber(ccMajorVersion)
85
	if parts[3] ~= nil then
86
		ccMinorVersion = tonumber(parts[3])
87
	end
88
end
89
90
local mcMajorVersion = _HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 1) -- eg 1.18 or 1.20 -> 1.18, 1.20
91
local mcMinorVersion = 0
92
if tonumber(mcMajorVersion) == nil then -- 1.18.3 NAN
93
	--mcMajorVersion = tonumber(_HOST:sub(_HOST:find("Minecraft") + 10, _HOST:find("\)") - 3)) -- eg 1.19.4 -> 1.19
94
	local parts = mcMajorVersion:split(".")
95
	mcMajorVersion = parts[1]
96
	if parts[2] ~= nil then
97
		mcMajorVersion = mcMajorVersion.."."..parts[2]
98
	end
99
	mcMajorVersion = tonumber(mcMajorVersion)
100
	if parts[3] ~= nil then
101
		mcMinorVersion = tonumber(parts[3])
102
	end
103
end
104
105
if mcMajorVersion < 1.7  and mcMajorVersion >= 1.18 then -- 1.12 to 1.??
106
	bedrock = -64
107
	ceiling = 319
108
end
109
if mcMajorVersion < 1.7  and mcMajorVersion >= 1.16 then -- 1.12 to 1.??
110
	brick = "minecraft:nether_bricks"
111
end
112
if mcMajorVersion < 1.7  and mcMajorVersion <= 1.12 then --- turtle in source deletes it. 1.7.10 to 1.12
113
	deletesWater = true
114
end
115
116
local utils = {}
117
118
function utils.tableConcat(tbl, sep)
119-
local network = {}
119+
120
    for i,value in pairs(tbl) do
121-
function network.addToStorageList(storageType, itemKey, storageName, writeToFile)
121+
122-
	-- itemKey is a table, so is passed byRef. No need to return a value
122+
123-
	-- eg itemKey: [ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96"}
123+
124-
	-- storageName = "minecraft:barrel_99"
124+
125-
	local itemTable = {}
125+
126-
	if storageType == "chest" then
126+
127-
		itemTable = chestItems[itemKey]	-- eg [ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96"}
127+
128
end
129-
		itemTable = barrelItems[itemKey]
129+
130
function utils.calculateDimensions(R)
131-
	if itemTable == nil then				-- key does not match. This item not previously stored
131+
132-
		if storageType == "chest" then
132+
133-
			chestItems[itemKey] = {storageName}	-- eg U.chestItems[minecraft:diorite] = {chest_105}
133+
134
			print("Calculated Length = "..R.length)
135-
			barrelItems[itemKey] = {storageName}
135+
136
			R.width = utils.calculateDistance(R.width) -- now facing right
137
			print("Calculated width = "..R.width)
138-
		for _, storage in ipairs(itemTable) do	-- is "minecraft:barrel_99" already in the list?
138+
139-
			if storage == storageName then
139+
140-
				return	-- exit function
140+
141
	if R.height == 0 then -- use auto settings based on water detection
142
		R.height = 64
143-
		-- not found so add to table. return not required as funcion is ended
143+
144-
		table.insert(itemTable, storageName)	-- add to table eg table[ "minecraft:dark_oak_sapling" ] = {"minecraft:barrel_94", "minecraft:barrel_96",, "minecraft:barrel_99"}
144+
145
end
146-
	if writeToFile then
146+
147-
		network.updateList(storageType)
147+
148
	--[[
149
	measure length
150
	movement stops when either solid block in front or solid below
151-
function network.attachModem()
151+
152-
	-- modem cannot be "attached". Has to be player right-click!
152+
153-
	-- place on  top or next to a modem and ask player to right-click
153+
154
	local nonSolidBelow = utils.clearVegetation("down")
155-
	menu.colourPrint("Please right-click on the modem(s) I am next to or above/below"..
155+
156-
					"\nThe centre square should be lit red.\n"..
156+
157-
					"If embedded use narrow gap at side\n", colors.red)
157+
158-
	local event, side = os.pullEvent("peripheral")
158+
159-
	for timer = 5, 0, -1 do
159+
160-
		-- text, fg, bg, width, isInput, cr
160+
161-
		menu.colourWrite("Thanks. continuing in ".. timer.." seconds", colors.lime, colors.black, 0, false, true)
161+
162
			if turtle.forward() then -- able to move forward
163
				moves = moves + 1
164
			else
165
				break
166-
function network.checkInventory(inventory, itemName, itemsPerSlot, matchPart)
166+
167
			if not utils.clearVegetation("down") then -- solid below
168-
	Find an item already in an inventory
168+
169-
	inventory = The wrapped inventory or it's name
169+
170-
	itemName = The name of the item to find.
170+
171-
	return no of items already present, and storage space for additional
171+
172
		end
173-
	itemsPerSlot = itemsPerSlot or 64
173+
174-
	matchPart = matchPart or ""
174+
175-
	local contents = nil
175+
176-
	local numSlots = 0
176+
177-
	if type(inventory) == "string" then
177+
178-
		contents = peripheral.call(inventory, "list")
178+
    local quantity = tonumber(quantity)
179-
		numSlots = peripheral.call(inventory, "size")
179+
	local fuelNeeded = quantity - tonumber(turtle.getFuelLevel()) -- eg 600
180-
		--assert(contents ~= nil, "Nil contents from inventory "..tostring(inventory))
180+
181-
		T:saveToLog("network.checkInventory('"..inventory.."', itemName = "..itemName..", itemsPerSlot = "..itemsPerSlot..", matchPart = "..tostring(matchPart))
181+
182
			if T:checkInventoryForItem({"coal"}, {math.ceil(fuelNeeded / 60)}, false) == nil then
183-
		contents = inventory.list()
183+
184-
		numSlots = inventory.size()
184+
185
		end
186-
	local inStock = 0
186+
187-
	local partMatch = false
187+
188-
	local canStore = 0
188+
189-
	if contents ~= nil then
189+
190-
		T:saveToLog("#slots in use = "..#contents)
190+
191-
		canStore = (numSlots - #contents) * itemsPerSlot 	-- capacity of empty slots
191+
192-
		for slot, item in pairs(contents) do
192+
	-- blockType, blockModifier, data
193-
			if item.name == itemName then
193+
	local blockType, blockModifier = T:getBlockType(direction)
194-
				inStock = inStock  + item.count
194+
195-
				canStore = canStore + itemsPerSlot - item.count
195+
196
			T:dig(direction)
197-
				if matchPart ~= "" then	-- eg check for "cobblestone" or "slab"
197+
198-
					if item.name:find(matchPart) ~= nil then
198+
199-
						partMatch = true
199+
200
			   and blockType:find("ice") == nil then
201
			-- NOT water, ice or lava 
202
			isAirWaterLava = false -- solid block
203
		end
204
	end
205-
	T:saveToLog("network.checkInventory return inStock = "..inStock..", canStore = "..canStore..", partMatch = "..tostring(partMatch))
205+
206-
	return inStock, canStore, partMatch -- eg 1, 3647, false if contains only 1 matching item in otherwise empty chest
206+
207
end
208
209-
function network.emptyInventory(R, barrels, chests, sticksAsFuel)
209+
210-
	--[[network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)]]
210+
211-
	if not T:isEmpty() then
211+
212-
		if sticksAsFuel then
212+
213-
			utils.useSticksAsFuel()
213+
214
	if type(R) == "table" then
215-
		for _, item in ipairs(barrels) do
215+
216-
			network.sendItemToNetworkStorage(R, "barrel", item, 0)
216+
217
			reduce = true
218-
		for _, item in ipairs(chests) do
218+
219-
			network.sendItemToNetworkStorage(R, "chest", item, 0)
219+
220
	else
221
		length = R
222
	end
223
	local numBlocks = 0
224-
function network.loadStorageLists()
224+
225
	if reduce then
226
		T:forward(1)
227-
	function lib.createList(storageType)
227+
228-
		local storage, turtleName, storageNames = network.wrapModem(R, storageType)	-- list of barrel/chest peripherals, name of turtle, names of barrels / chests
228+
229-
		local total = 0
229+
230-
		local locations = {}
230+
231-
		for _, store in pairs(storageNames) do					-- eg "minecraft:chest_1"
231+
232-
			T:clear()				
232+
233-
			T:saveToLog("Checking "..store.. " contents")		-- eg "checking minecraft:chest_1 contents"
233+
234-
			local contents = peripheral.call(store, "list")		-- list of items / slots for this chest
234+
235-
			for slot, item in pairs(contents) do				-- for each item check if this storage is listed
235+
236-
				if locations[item.name] == nil then				-- this item not yet found
236+
237-
					locations[item.name] = {store}				-- add to table eg locations["minecraft:cobblestone"] = {"minecraft:chest_1"}
237+
238-
				else											-- already has at least 1 location
238+
239-
					network.addToStorageList(storageType, locations[item.name], store, false)
239+
240
		end
241
		local place = utils.clearVegetation("down")
242-
			total = total + 1
242+
243
			if T:fillVoid("down", {}, false) then -- false if out of blocks
244-
		T:saveToLog("found ".. total.." "..storageType)
244+
245-
		local output = textutils.serialize(locations)		-- serialise to json ready to write to file
245+
246-
		local fileName = storageType.."Items.lua"			-- barrelList.lua or chestList.lua
246+
247-
		local outputHandle = fs.open(fileName, "w")			-- open file
247+
248-
		outputHandle.writeLine("return")					-- start file with return
248+
249-
		outputHandle.write(output)							-- add serialised table
249+
						T:place("minecraft:torch", -1, "forward", false)
250-
		outputHandle.close()								-- close file
250+
251
					end
252-
		return locations
252+
253
			else
254
				break
255-
	function lib.listNeedUpdating(storageType, list)
255+
256-
		-- see if named chest/barrel in list is found in fresh peripheral.find
256+
257-
		-- turtle may have moved to a different network
257+
258-
		-- list = eg [ "minecraft:stick" ] = {"minecraft:barrel_91","minecraft:barrel_114"}
258+
259-
		local rawStorage = {peripheral.find(storageType)}
259+
260-
		if not utils.isTableEmpty(rawStorage) then		-- chests / barrels are attached see if they match
260+
261-
			for item, storeList in pairs(list) do		-- existing storage names can be found here
261+
262-
				local found = false
262+
263-
				for key, value in ipairs(rawStorage) do	-- look in the fresh list of storage names to see if there are missing entries
263+
264-
					local name = peripheral.getName(value)				
264+
265-
					for _, storageName in ipairs(storeList) do 	-- check each storage name found
265+
266-
						if storageName == name then 	-- recorded name matches, check next one
266+
267-
							found = true
267+
268-
							break
268+
269
	D.height = #
270
	D.ceiling = false
271-
					if found then break end
271+
272
	D.vDirection = "U" or "D"
273-
				if not found then
273+
274-
					-- no match in existing list for this storage: list needs updating
274+
275-
					return true-- list does not match
275+
276
	]]
277
	local turn  = "R1"
278
	local oTurn = "L1"
279-
		return false	-- list is ok
279+
280
		turn    = "L1"
281
		oTurn   = "R1"
282-
	local _, turtleName, storageNames = network.wrapModem(R, "chest")	-- _, name of turtle, list of names of storage
282+
283-
	if turtleName == "Modem not found" then return turtleName end
283+
284-
	local redo = false
284+
285-
	if barrelItems == nil then	-- not yet loaded
285+
286-
		T:saveToLog("barrelItems == nil")
286+
287-
		if fs.exists("barrelItems.lua") then
287+
288-
			T:saveToLog("require('barrelItems')")
288+
289-
			barrelItems = require("barrelItems")	-- global variable
289+
290-
			redo = lib.listNeedUpdating("barrel", barrelItems)
290+
291
					return "C2"
292-
			T:saveToLog("lib.createList('barrel'")
292+
293-
			barrelItems = lib.createList("barrel")
293+
294
				if D.ceiling then
295
					return "C0"
296-
	if chestItems == nil then	-- not yet loaded
296+
297-
		T:saveToLog("chestItems == nil")
297+
298-
		if fs.exists("chestItems.lua") then
298+
299-
			T:saveToLog("require('chestItems')")
299+
300-
			chestItems = require("chestItems")	-- global variable
300+
301-
			redo = lib.listNeedUpdating("chest", barrelItems)
301+
302
				end
303-
			T:saveToLog("lib.createList('chest'")
303+
304-
			chestItems = lib.createList("chest")
304+
305-
		end	
305+
306
				end
307-
	if redo then
307+
308-
		barrelItems = lib.createList("barrel")
308+
309-
		chestItems = lib.createList("chest")
309+
310
		return ""							-- start and finish both false
311
	end
312
	
313-
function network.findEmptySlot(list, size)
313+
314-
	--[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
314+
315-
	Find the first empty slot in a chest.
315+
316-
	list = list of items in the chest/barrel/dropper
316+
317-
	size = The size of the inventory
317+
318-
	return integer? slot The slot number of the first empty slot, or nil if none are empty.
318+
319
					T:go(place, false, 0, true)-- place floor / ceiling
320-
	for slot = 1, size do
320+
321-
		if not list[slot] then
321+
322-
			return slot
322+
323
				elseif width == D.width then						-- checking opposite wall
324
					if outward then									-- travelling away from start
325
						T:go(turn..placeF..oTurn, false, 0, true)	-- face wall and check if block
326-
	return nil
326+
327
						T:go(oTurn..placeF..turn, false, 0, true)	-- face wall and check if block 
328
					end					
329-
function network.findItemCountInInventory(list, itemName, exactMatch)
329+
330
				-- move forward
331-
	Find an item in an inventory
331+
332-
	list = The list of items in the inventory
332+
333-
	itemName = The name of the item to find.
333+
334-
	return integer? The slot number of the item, or nil if not found.
334+
335
			if width < D.width then
336-
	exactMatch = exactMatch or false
336+
337-
	if type(list) == "string" then
337+
338-
		list = peripheral.call(list, "list")
338+
339
				else
340-
	local retValue = nil
340+
341-
	local count = 0
341+
342-
	for slot, item in pairs(list) do
342+
343
			else
344-
		if exactMatch then
344+
345-
			if item.name == itemName then found = true end
345+
346
				else
347-
			if item.name:find(itemName) ~= nil then found = true end
347+
348
				end
349
			end
350-
			if retValue == nil then
350+
351-
				retValue = {}
351+
352
	
353-
			table.insert(retValue,{slot, item.count}) -- eg {1, 64}
353+
354-
			count = count + item.count
354+
355
		if height == 1 then
356
			lib.layer(D, true, false)					-- first layer, so start = true, finish = false
357-
	return count, retValue -- either nil or eg {{1, 64},{4, 22}}
357+
358
			lib.layer(D, false, true)					-- final layer, so start = false, finish = true
359
		else
360-
function network.findItemInInventory(inventory, itemName, exactMatch)
360+
361-
	--[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
361+
362-
	Find an item in an inventory
362+
363-
	inventory = name of inventory or wrapped peripheral
363+
364-
	itemName = The name of the item to find.
364+
365-
	return integer?, integer? The slot number and count of the item, or nil if not found.
365+
366
	if D.goHome then-- ends at starting point
367-
	exactMatch = exactMatch or false
367+
368-
	if type(inventory) == "string" then
368+
369-
		T:saveToLog("network.findItemInInventory("..inventory..", "..itemName..", exactMatch = "..tostring(exactMatch)..")", true)
369+
370-
		contents = peripheral.call(inventory, "list")
370+
371-
	else	-- should be supplied with .list() already
371+
372-
		T:saveToLog("network.findItemInInventory(<inventory>, "..itemName..", exactMatch = "..tostring(exactMatch)..")", true)
372+
373-
		contents = inventory
373+
374
375-
	--T:saveToLog("contents = "..table.concat(contents, ", "))
375+
376-
	--utils.writeTraceTable("contents = ", contents)
376+
377-
	if contents ~= nil then
377+
378-
		for slot, item in pairs(contents) do
378+
379-
			--T:saveToLog("item.name = "..item.name..", item.count = "..item.count)
379+
380-
			if exactMatch then
380+
381-
				if item.name == itemName then
381+
382-
					T:saveToLog("Item found in "..slot..", quantity = "..item.count)
382+
383-
					return slot, item.count
383+
384
	-- assume on flat surface, but allow for blocks above
385
	T:go("x0C2F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2F1 x0C2R1 F1 x0C2F1 x0C2", false, 0, false)
386-
				if (item.name):find(itemName) ~= nil then
386+
387-
					T:saveToLog("Matching Item found in "..slot..", quantity = "..item.count)
387+
388-
					return slot, item.count
388+
389
	for i = 1, 2 do
390
		T:placeWater("down")
391
		T:go("F1R1F1R1", false, 0, false)
392
	end
393-
	T:saveToLog("Item not found")
393+
394-
	return 0,0
394+
395
		sleep(0.5)
396
		T:placeWater("down")
397-
function network.getItemFromNetwork(storageType, itemRequired, countRequired, toTurtleSlot, ignoreStock)
397+
398
	T:go("R2F1R1F1R1")
399
	-- end above lower left of pond (starting point)
400-
	function lib.getItem(storageTable, turtleName, itemRequired, countRequired, toTurtleSlot, sent)
400+
401-
		local exit = false
401+
402-
		for k, storageName in pairs(storageTable) do 	-- eg {"minecraft:barrel_17", "minecraft:barrel_18"...}
402+
403-
			local available, data = network.findItemCountInInventory(storageName, itemRequired, false)		-- either nil or eg {{1, 64},{4, 22}}
403+
404-
			T:saveToLog("network.findItemCountInInventory("..storageName..", "..itemRequired..", false")
404+
405-
			if data ~= nil then
405+
406-
				for i = 1, #data do 
406+
407-
					local request = countRequired
407+
408-
					if countRequired > 64 then
408+
409-
						request = 64
409+
410
	end
411-
					local received = network.sendItemsToTurtle(turtleName, storageName, data[i][1], request, toTurtleSlot)	-- request items, returns number sent
411+
412-
					if received == nil then received = 0 end
412+
413-
					sent = sent + received
413+
414-
					T:saveToLog("received = "..received..", request = "..request.." from "..storageName..", sent = "..sent)
414+
415-
					if sent >= countRequired then
415+
416-
						exit = true
416+
417-
						break 
417+
418-
					end			-- job done, no need to check remaining slots
418+
419-
					countRequired = countRequired - sent			-- this line not reached if sent >= count
419+
420
		T:go("D1R1C1 R1C1 U1C1 L1C1 U1C1 R1C1 L2D1 C2C0", false, 0, true)
421
		-- finished on same mid 3 high column with wall behind and right completed
422-
			--if sent >= countRequired then break end				-- no need to check other storage
422+
423-
			--if countRequired <= 0 then break end
423+
424-
			if exit then
424+
425-
				return sent, countRequired
425+
426
		T:go("L1F"..offset.."L2C1 R1D1C1 U1C1 U1C1 D1")
427
		-- end next row along the width, facing the back, mid point
428
		-- wall ahead completed
429-
		return sent, countRequired
429+
430
	
431
	function lib.frontTurn()
432-
	-- eg slot, count = network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
432+
433-
	-- storageType either "chest" or "barrel"
433+
434-
	if countRequired == nil then return 0,0 end
434+
435-
	--if toTurtleSlot not specified then nil = use any slot
435+
436-
	ignoreStock = ignoreStock or false	-- return only no of items obtained from storage
436+
437-
	T:saveToLog("network.getItemFromNetwork(storageType = "..storageType..", itemRequired = ".. itemRequired..
437+
438-
				", countRequired = ".. countRequired..", toTurtleSlot = "..tostring(toTurtleSlot)..", ignoreStock = "..tostring(ignoreStock))
438+
439-
	-- Must be next to a modem: MUST remove crafting table if modem on that side. Other tools ok
439+
440-
	local sent = 0
440+
441-
	local turtleSlot, turtleCount = T:getItemSlot(itemRequired)	-- check local stock
441+
442-
	if not ignoreStock then	-- take account of existing items and reduce count accordingly
442+
443-
		countRequired = countRequired - turtleCount
443+
444
				lib.startCorner()
445-
	local savedItems = nil
445+
446-
	if storageType == "barrel" then
446+
447-
		savedItems = barrelItems
447+
448-
	elseif storageType == "chest" then
448+
449-
		savedItems = chestItems
449+
450
				end
451-
	local storage, turtleName, storageNames = network.wrapModem(R, storageType)	-- list of chest/barrel peripherals, name of turtle, list of storage names
451+
452-
	--if turtleName == "Modem not found" then return 0, nil, nil, turtleName end
452+
453-
	if countRequired > 0 then 						-- not enough in stock, or ignore current stock
453+
454-
		-- check if item in storageLists
454+
455-
		local testStores = nil
455+
456-
		if savedItems[itemRequired] ~= nil then	-- only works with full item names
456+
457-
			T:saveToLog("savedItems key in list: "..textutils.serialise(savedItems[itemRequired], {compact = true}))
457+
458-
			testStores = savedItems[itemRequired]
458+
459
		return 1
460-
			for key, value in pairs(savedItems) do 
460+
461-
				if key:find(itemRequired)~= nil then
461+
462-
					T:saveToLog("savedItems found in list: "..textutils.serialise(value, {compact = true}))
462+
463-
					testStores = value
463+
464
		local waterPresent = false
465
		for i = 1, distance do
466
			if T:isWater("down") then
467
				waterPresent = true
468-
		if testStores == nil then	-- no match in storage lists
468+
469-
			T:saveToLog("Unable to find recorded storage, using all "..storageType.."s")
469+
470-
			sent, countRequired = lib.getItem(storageNames, turtleName, itemRequired, countRequired, toTurtleSlot, sent)
470+
471-
		else -- match found, list of storage availble -- eg {"minecraft:barrel_17", "minecraft:barrel_18"...}
471+
472-
			T:saveToLog("Using recorded list alias 'testStores'")
472+
473-
			sent, countRequired = lib.getItem(testStores, turtleName, itemRequired, countRequired, toTurtleSlot, sent)
473+
474
				T:go("C1", false, 0, true)
475
			end
476-
		-- slotData.lastSlot, total, slotData -- integer, integer, table
476+
477-
	local data = {}
477+
478-
	turtleSlot, turtleCount, data = T:getItemSlot(itemRequired)
478+
479-
	T:saveToLog("turtleSlot = "..turtleSlot..", turtleCount = "..turtleCount..", sent = "..sent) --..", data = "..textutils.serialise(data))
479+
480-
	if ignoreStock then
480+
481-
		return turtleSlot, sent	-- 0 -> count
481+
482
		for i = 1, distance do
483-
		return turtleSlot, turtleCount	-- 0 -> count
483+
484
			if i < distance then
485
				T:forward(1)
486
			end
487-
function network.getSlotContains(inventoryName, inSlot)
487+
488-
	local list = peripheral.call(inventoryName, "list")
488+
489-
	for slot, item in pairs(list) do
489+
490-
		if inSlot == slot then
490+
491-
			return item.name
491+
492
	if R.data == "" then
493
		if turtle.detectDown() then -- on solid surface
494-
	return ""
494+
495
		end
496
	end
497-
function network.moveItem(inventoryName, itemName, toSlot)
497+
498-
	--[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
498+
499-
	Move a specific item to specific slot eg 1, moving other items out of the way if needed.
499+
500-
	inventoryName = The name of the chest/barrel/dropper to search.
500+
501-
	itemName = The name of the item to find.
501+
502-
	toSlot optional. default is slot 1
502+
503-
	return boolean success Whether or not the item was successfully moved to toSlot (or already existed there)
503+
504
		R = utils.calculateDimensions(R)
505-
	toSlot = toSlot or 1
505+
506-
	local list = peripheral.call(inventoryName, "list")
506+
507-
	local size = peripheral.call(inventoryName, "size")
507+
508-
	local slot = network.findItemInInventory(list, itemName)
508+
509
			T:go("R2D2", false, 0, true)	-- at start, level 2, facing towards the front, move backards
510-
  -- If the item didn't exist, or is already in the first slot, we're done.
510+
511-
	if not slot then
511+
512-
		T:saveToLog("network.moveItem(): Item not found")
512+
513
			if lib.placeDam(R.length) then
514
				waterPresent = true
515-
	if slot == toSlot then
515+
516
			row = row + 1
517
			-- left side wall has been built, 2 rows of walls laid. row = 2
518
			while row < R.width - 1 do -- eg width=2, row=2, this will not run. width=5, row=2
519-
	-- If an item is blocking the first slot (we already know it's not the one we want), we need to move it.
519+
520-
	if list[toSlot] then
520+
521-
		T:saveToLog("network.moveItem() Slot "..toSlot.." occupied, moving..")
521+
522-
		local emptySlot = network.findEmptySlot(list, size)
522+
523
					waterPresent = true
524-
		-- If there are no empty slots, we can't move the item.
524+
525-
		if not emptySlot then
525+
526-
			T:saveToLog("network.moveItem(): No empty slots")
526+
527
			-- lay right wall
528
			lib.frontTurn()
529
			lib.removeDam(R.length)
530-
		-- Move the item to the first empty slot.
530+
531
			row = row + lib.placeRetainingWall(R.length)
532-
		if not network.moveItemStack(inventoryName, toSlot, emptySlot) then
532+
533-
			T:saveToLog("network.moveItem(): Failed to move item to slot " .. emptySlot)
533+
534
			T:go("L1F1R1")
535
			lib.removeDam(R.length) -- faces to front on finish
536
			depth = depth + 3
537-
		T:saveToLog("network.moveItem(): Moved item to slot " .. emptySlot)
537+
538
			if depth == R.height or not waterPresent then -- still replacing water
539
				T:up(depth - 1) -- when h == R.height will go up
540-
	-- Move the item to slot 1.
540+
541-
	if not network.moveItemStack(inventoryName, slot, toSlot) then
541+
542-
		T:saveToLog("network.moveItem(): Failed to move item to slot "..toSlot)
542+
543
	end
544
	return {}
545
end
546-
	T:saveToLog("network.moveItem(): Moved item to slot "..toSlot)
546+
547-
	return true
547+
548
	while not turtle.detectDown() do -- over water. will be infinite loop if out of sand
549
		if not T:place("sand", -1, "down", false) then
550-
function network.moveItemsFromTurtle(turtleName, toInventoryName, fromTurtleSlot, quantity, toSlot)
550+
551
			sleep(2)
552-
	Move quantity of an item from one inventory to another. Turtles MUST use attachedInventory.pullItems()
552+
553-
	eg network.moveItemsFromTurtle(turtleName, chestName, turtleSlot, turtleCount, nil)
553+
554-
	turtleName:			The name of the turtle (via getLocalName())
554+
555-
	toInventoryName: 	The name of the inventory to move items into.
555+
556-
	fromTurtleSlot: 	The slot to move from. must be pre-determined for the item required
556+
557-
	quantity: 			The amount to transfer (nil for full stack)
557+
558-
	toSlot: 			The slot to move to. (nil will use any available slot(s))
558+
559
	allows 2 turtles to co-operate
560-
	return peripheral.call(toInventoryName, "pullItems", turtleName, fromTurtleSlot, quantity, toSlot)
560+
561
	R.side = "R" or "L"
562
	]]
563-
function network.moveItemStack(inventoryName, fromSlot, toSlot)
563+
564-
	--[[ adapted from https://github.com/cc-tweaked/CC-Tweaked/discussions/1552
564+
565-
	Move an item from one slot to another in a given inventory.
565+
566-
	inventoryName The name of the inventory to move items in.
566+
567-
	fromSlot The slot to move from.
567+
568-
	toSlot The slot to move to.
568+
569
	local finished = false
570-
	return peripheral.call(inventoryName, "pushItems", inventoryName, fromSlot, nil, toSlot)
570+
571
	rs.setAnalogueOutput("front", 0) -- switch off output
572
	local blockType = T:getBlockType("forward")
573-
function network.sendItemToNetworkStorage(R, storageType, itemToSend, amountToSend)
573+
574-
	-- used to remove items from turtle inventory
574+
575-
	-- Must be next to a modem: MUST remove crafting table if modem on that side. Other tools ok
575+
576
		sleep(0.1)
577
		timer = timer + 0.1
578-
	function lib.sendItem(savedItems, peripheralNames, turtleName, turtleSlot, item, slotCount, itemsPerSlot)
578+
579-
		local storageToUse = ""
579+
580-
		local storageList = lib.getStorageFromList(savedItems, item, slotCount, itemsPerSlot)	-- try from savedList
580+
581-
		if storageList == nil then	-- no match found, but use first one found with network.wrapModem
581+
582-
			T:saveToLog("No storage with matching items found, using first empty chest")
582+
583-
			storageToUse = lib.findEmptyStorage(peripheralNames, item, itemsPerSlot, slotCount)
583+
584
	endTimer = 0
585-
			T:saveToLog("Storage with matching items found, checking capacity")
585+
586-
			storageToUse  = lib.checkCapacity(storageList, item, slotCount, itemsPerSlot)
586+
587-
			if storageToUse == "" then	-- no capacity in known storage list, so start a new one
587+
588-
				storageToUse = lib.findEmptyStorage(peripheralNames, item, itemsPerSlot, slotCount)
588+
589
				if confirmed then
590
					menu.colourWrite("Turtle confirmed: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
591-
		--network.moveItemsFromTurtle(turtleName, toInventoryName, fromTurtleSlot, quantity, toSlot)
591+
592-
		T:saveToLog("network.moveItemsFromTurtle(turtleName = "..turtleName..", storageToUse = "..tostring(storageToUse)..", slot = "..tostring(turtleSlot)..", slotCount = "..tostring(slotCount)..")")
592+
593-
		network.moveItemsFromTurtle(turtleName, storageToUse, turtleSlot, slotCount)
593+
594
			else
595
				menu.colourWrite("Waiting: input = "..rsIn.." output = "..rsOut, colors.orange, nil, nil, false, true)
596-
	function lib.findEmptyStorage(peripheralNames, itemName, itemsPerSlot, itemCount)
596+
597-
		T:saveToLog("lib.findEmptyStorage("..textutils.serialise(peripheralNames,{compact = true})..", itemName = "..itemName.. ", itemsPerSlot = "..itemsPerSlot)
597+
598-
		for store = 1, #peripheralNames do 
598+
599-
			inStock, canStore, partMatch = network.checkInventory(peripheralNames[store], itemName, itemsPerSlot, "")
599+
600-
			if canStore > itemCount then
600+
601-
				return peripheralNames[store]
601+
602
		end
603
		if endTimer >= 10 then -- allows time for other computer to get ready
604-
		return nil
604+
605
		end
606
		rs.setAnalogueOutput("front", 1) -- output 1 as a signal initially
607-
	function lib.getStorageFromList(savedItems, item, sendAmount, itemsPerSlot)
607+
608-
		if savedItems[item] == nil then								-- no record of this item stored
608+
609-
			T:saveToLog("lib.getStorageFromList() "..item.." not found")
609+
610-
			local parts = T:getNames(item)								-- eg minecraft:jungle_planks = "minecraft", "jungle", "planks"
610+
611-
			for part = #parts, 1, -1 do 								-- iterate "planks", "jungle", "minecraft"
611+
612-
				local searchTerm = parts[part]
612+
613-
				if searchTerm ~= "minecraft" and searchTerm ~= "mysticalagriculture" then
613+
614-
					for itemName, storageList in pairs(savedItems) do	-- iterate items used as keys eg minecraft:jungle_log matches jungle
614+
615-
						if itemName:find(searchTerm) ~= nil then 		-- partial match eg "sapling" found in "minecraft:oak_sapling"
615+
616-
							T:saveToLog("lib.getStorageFromList() matched "..searchTerm.." with "..itemName)
616+
617-
							return storageList							-- eg {"minecraft:chest_22", "minecraft:chest_23"}
617+
618
			confirmed = true
619
			rsOut = 15
620
		elseif rsIn == 15 or confirmed then
621
			menu.colourWrite("endTimer active = "..endTimer, colors.orange, nil, nil, false, true)
622
			endTimer = endTimer + 1 -- start endTimer
623-
			T:saveToLog("lib.getStorageFromList() ["..item.."] found")
623+
624-
			return savedItems[item]	-- list of chests with this item available
624+
625
	T:go(R.side.."3")
626-
		return nil
626+
627
	return rsIn -- 15
628
end
629-
	function lib.checkCapacity(storageList, item, sendAmount, itemsPerSlot)
629+
630-
		-- find a chest/barrel with sufficient capacity from list of storage
630+
631-
		for store = 1, #storageList do 
631+
632-
			local inStock, canStore, partMatch = network.checkInventory(storageList[store], item, itemsPerSlot, "")
632+
633-
			if canStore > sendAmount then
633+
634-
				return storageList[store]
634+
635
	maxDescent = maxDescent or 1 -- prevents continuous down due to lack of water
636
	if goIn == nil then	-- turtle should submerge
637
		goIn = true
638
	end
639
	local descent = 0 -- counter for going down
640-
	amountToSend = amountToSend or 0						-- 0 = remove all of this item
640+
641-
	local totalSent = 0										-- track quantity sent 
641+
642-
	local minSend = 0										-- minimum amount to send
642+
643-
	if amountToSend > 0 then minSend = amountToSend end		-- update minimum to send
643+
644-
	local _, turtleName, peripheralNames = network.wrapModem(R, storageType)	-- _, name of turtle, list of names of storage
644+
645
			if T:getBlockType("forward"):find("water") ~= nil or T:getBlockType("forward"):find("bubble") ~= nil then
646-
	T:saveToLog("network.sendItemToNetworkStorage(R, storageType = '"..storageType.."', itemToSend = '"..itemToSend.."', amountToSend = "..amountToSend..")")
646+
647-
	T:saveToLog("network.wrapModem(R, storageType = "..storageType..", turtleName = "..turtleName..")")
647+
648-
	local savedItems = nil
648+
649-
	if storageType == "barrel" then
649+
650-
		savedItems = barrelItems
650+
651-
	elseif storageType == "chest" then
651+
652-
		savedItems = chestItems
652+
653
	end
654
	-- should now be above water, but may be further down so onWater still false
655-
	if itemToSend == "all" then	-- empty Turtle, so item names not relevant
655+
656-
		T:saveToLog("itemToSend = all")
656+
657
			descent = descent + 1
658-
			local item, turtleSlot, slotCount, itemsPerSlot = "", 0, 0, 64
658+
659-
			for slot = 1, 16 do
659+
660-
				item, slotCount = T:getSlotContains(slot)
660+
661-
				if slotCount > 0 then
661+
662-
					turtleSlot = slot
662+
663-
					T:saveToLog("for slot = 1, 16 do: item = "..item..", slotCount = "..slotCount)
663+
664-
					itemsPerSlot = utils.getSlotCapacity(slot)	-- most items capacity is 64 per slot
664+
665-
					T:saveToLog("sending'"..item.."' from slot "..slot..", quantity = "..slotCount)
665+
666
	end
667
	-- now above water
668
	if goIn then
669-
			if turtleSlot > 0 then
669+
670-
				lib.sendItem(savedItems, peripheralNames, turtleName, turtleSlot, item, slotCount, itemsPerSlot)
670+
671
	end
672-
		until turtleSlot == 0
672+
673-
		return 0	-- exit function
673+
674
675-
		local storageToUse  = ""
675+
676-
		repeat	-- until item no longer present in inventory or requested amount has been sent
676+
677-
			local sourceSlot, total, data = T:getItemSlot(itemToSend)	-- which slot and how much of itemToSend is in turtle?
677+
678-
			local slotCount = data.leastCount
678+
679-
			T:saveToLog("T:getItemSlot('"..itemToSend.."' sourceSlot = "..sourceSlot..", total = "..total..")")
679+
680-
			if sourceSlot == 0 then
680+
681-
				T:saveToLog(itemToSend.." not found in turtle inventory")
681+
682-
				return 0	-- exit function
682+
683
684-
				local itemsPerSlot = utils.getSlotCapacity(sourceSlot)	-- most items capacity is 64 per slot
684+
685-
				itemToSend = data.leastName								-- full name of item with lowest itemCount
685+
	local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:bucket", -1)
686-
				T:saveToLog("network.sendItemToNetworkStorage(R, '"..itemToSend.."', sourceSlot = "..sourceSlot..", slotCount = "..slotCount) --..", data = "..textutils.serialise(data)..")")
686+
687-
				if sourceSlot > 0 then									-- item is present in turtle inventory
687+
688-
					local newStore = false
688+
689-
					local sent = 0
689+
690-
					local storageList = lib.getStorageFromList(savedItems, itemToSend, slotCount, itemsPerSlot)
690+
691-
					if storageList == nil then
691+
692-
						T:saveToLog("not found in any storage, finding empty")
692+
693-
						storageToUse = lib.findEmptyStorage(peripheralNames, itemToSend, itemsPerSlot, total)
693+
694-
						T:saveToLog("new storage: "..storageToUse.." is available")
694+
695-
						network.addToStorageList(storageType, itemToSend, storageToUse, true)
695+
696-
						sent = network.moveItemsFromTurtle(turtleName, storageToUse, sourceSlot, slotCount)	
696+
697
	
698-
						storageToUse  = lib.checkCapacity(storageList, itemToSend, slotCount, itemsPerSlot)
698+
699-
						if storageToUse == "" then	-- no capacity in known storage list, so start a new one
699+
700-
							storageToUse = lib.findEmptyStorage(peripheralNames, itemToSend, itemsPerSlot, total)
700+
701-
							newStore = true
701+
702
	end
703-
						T:saveToLog("sent = network.moveItemsFromTurtle(turtleName = "..turtleName..", storageToUse = "..storageToUse..", sourceSlot = "..sourceSlot..", slotCount = ".. slotCount)
703+
704-
						sent = network.moveItemsFromTurtle(turtleName, storageToUse, sourceSlot, slotCount)
704+
705
	end
706-
					totalSent = totalSent + sent
706+
707-
					if minSend > 0 and totalSent >= minSend then
707+
708-
						return totalSent
708+
709
710-
					if amountToSend > 0 then	-- sending specified amount
710+
711-
						amountToSend = amountToSend - sent
711+
712
		T:getWater("down") -- take water from source
713-
					if newStore then
713+
714-
						network.addToStorageList(storageType, itemToSend, storageName, true)
714+
715
	else
716
		if not turtle.detectDown() then
717
			T:go("C2", false, 0, false)
718-
		until sourceSlot == 0
718+
719
		T:getWater("forward") -- take water from source
720
		sleep(0.2)
721-
	return totalSent
721+
722
	end
723
end
724-
function network.sendItemsToCrafter(crafterName, fromInventoryName, fromInventorySlot, quantity, toCrafterSlot)
724+
725
function utils.getWaterBucketCount()
726-
	fromInventoryName: 	The name of the inventory to move items from.
726+
	-- lastSlot, leastModifier, total, slotData  = T:getItemSlot(item, useDamage)
727-
	fromInventorySlot: 	The slot to move from. must be pre-determined for the item required
727+
	local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:water_bucket", -1)
728-
	quantity: 			The amount to transfer (nil for full stack)
728+
729-
	toCrafterSlot: 		The slot to move to. (nil will use any available slot(s))
729+
730
731-
	return peripheral.call(fromInventoryName, "pushItems", crafterName, fromInventorySlot, quantity, toCrafterSlot)
731+
732
	--[[ Usage:
733
	local inWater, onWater = utils.getWaterStatus() -- returns turtle position near water
734-
function network.sendItemsToTurtle(turtleName, fromInventoryName, fromInventorySlot, quantity, toTurtleSlot)
734+
735-
	--network.sendItemsToTurtle(turtleName, storageName, storageSlot, count, toTurtleSlot)
735+
736
	]]
737-
	Move quantity of an item from one inventory to another. Turtles MUST use attachedInventory.pushItems()
737+
738-
	eg network.sendItemsToTurtle(turtleName, chestName, chestSlot, chestCount, 16) -- move to slot 16 so must be empty
738+
739-
	fromInventoryName: 	The name of the inventory to move items from.
739+
740-
	fromInventorySlot: 	The slot to move from. must be pre-determined for the item required
740+
741-
	quantity: 			The amount to transfer (nil for full stack)
741+
742-
	toTurtleSlot: 		The slot to move to. (nil will use any available slot(s))
742+
743
		T:turnRight(1)
744-
	return peripheral.call(fromInventoryName, "pushItems", turtleName, fromInventorySlot, quantity, toTurtleSlot)
744+
745
	if T:getBlockType("down"):find("water") ~= nil or T:getBlockType("down"):find("bubble") ~= nil then
746
		onWater = true
747-
function network.transferItem(fromInventoryName, toInventoryName, itemName, quantity, toSlot)
747+
748
	return inWater, onWater
749-
	Move a specific number of an item from one inventory to another
749+
750-
	fromInventoryName:	The name of the chest/barrel/dropper to search.
750+
751-
	toInventoryName:	The name of the receiving inventory (chest/barrel/dropper/smelter)
751+
752-
	itemName: 			The name of the item to find.
752+
753-
	toSlot: 			optional. nil picks any slot
753+
754-
	return: 			boolean success Whether or not the item was successfully moved to toSlot (or already existed there)
754+
755
		if not turtle.back() then
756-
	--T:saveToLog("network.transferItem(from: "..fromInventoryName..", to: "..toInventoryName..", itemName = "..itemName..", quantity = "..tostring(quantity)..", toSlot = "..tostring(toSlot))
756+
757-
	local list = peripheral.call(fromInventoryName, "list")
757+
758-
	local size = peripheral.call(fromInventoryName, "size")
758+
759-
	--T:saveToLog("network.transferItem() size = "..size..", list = \n"..textutils.serialize(list))
759+
760-
	local count, data = network.findItemCountInInventory(list, itemName)	-- either nil or eg {{1, 64},{4, 22}}
760+
761-
	--T:saveToLog("network.transferItem() data = "..textutils.serialize(data, {compact = true}))
761+
762-
	local remaining = quantity			-- eg 22 items needed
762+
763
764-
	if data == nil then	-- Item not found
764+
765-
		return quantity	-- return amount requested = nothing sent
765+
766
	menuPromptColour = menuPromptColour or colors.white
767
	
768-
	local fromSlot = 0
768+
769-
	local count = 64
769+
770-
	local available = 0
770+
771-
	for _, v in pairs(data) do	-- eg {1, 64},{2, 64}
771+
772-
		if v[2] < count and v[2] >= quantity then
772+
773-
			fromSlot = v[1]
773+
774-
			count = v[2]
774+
775
end
776-
			available = available + v[2]
776+
777
function utils.move(R, blocks, reverse)
778
	if reverse == nil then
779-
	if fromSlot > 0 then						-- now have slot with min required quantity
779+
780-
		T:saveToLog("network.transferItem() from: "..fromInventoryName..", to: "..toInventoryName..", fromSlot: "..fromSlot..", toSlot: "..tostring(toSlot)..", quantity: "..tostring(quantity))
780+
781-
		network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, quantity)
781+
782-
		return 0
782+
		if R.subChoice == 2 then -- reverse direction
783-
	else									-- available must be at least 1
783+
784-
		for i = 1, #data do					-- itreate all slots containg at least 1 item
784+
785-
			fromSlot = data[i][1]			-- eg slot 1
785+
786-
			local send = data[i][2]			-- eg 10 items
786+
787-
			if remaining - send < 0 then	-- eg 22 - 10 = 12
787+
788-
				send = remaining
788+
789-
				remaining = 0
789+
790
			T:up(blocks)
791-
				remaining = remaining - send-- eg remaining = 22 - 10 = 12
791+
792
			T:down(blocks)
793-
			network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, send)
793+
794-
			if remaining <= 0 then			-- all required items transferred
794+
795-
				return 0
795+
796
end
797
798
function utils.setStorageOptions()
799
	local storage = ""
800-
	return remaining						-- return remaining items to be found from a  different inventory
800+
801
	if T:getItemSlot("barrel") > 0 then
802
		storage = "barrel"
803-
function network.transferItems(fromInventoryName, toInventoryName, fromSlot, toSlot, quantity)
803+
804
	end
805-
	Move quantity of an item from one inventory to another
805+
806-
	fromInventoryName:	The name of the inventory to move items from.
806+
807-
	toInventoryName: 	The name of the inventory to move items into.
807+
808-
	fromSlot: 			The slot to move from. must be pre-determined for the item required
808+
809-
	toSlot: 			The slot to move to. (nil will use any available slot(s))
809+
810-
	quantity: 			The amount to transfer (nil for full stack)
810+
811
	return storage, storageBackup
812-
	T:saveToLog("network.transferItems(from: "..fromInventoryName..", to: "..toInventoryName..", fromSlot: "..fromSlot..", toSlot: "..tostring(toSlot)..", quantity: "..tostring(quantity)..")")
812+
813-
	return peripheral.call(fromInventoryName, "pushItems", toInventoryName, fromSlot, quantity, toSlot)
813+
814
local pp = utils.getPrettyPrint()
815
816-
function network.transferItemToTurtle(availableStorage, availableStorageKeys, turtleName, crafterData)
816+
817-
	-- network.transferItemToTurtle(<availableStorage>, data = {{1, 64},{4, 22}}, "crafter_01", <crafterData>)
817+
818-
	-- availableStorage.minecraft:chest_114 = {count = 86, data = {{1, 64},{4, 22}},
818+
819-
	-- availableStorage.minecraft:chest_115 = {count = 1024, data = {{1, 64},{2, 64},{3, 64}, ... }
819+
820-
	-- crafterData = {{2,64}, {4,64}, {6,64}, {8,64}} 64 items in each of 4 slots in the crafter
820+
821-
	-- glitch? in crafter inventory, cannot add sequentially to existing items. 
821+
822-
	-- send to turtle slot first, then transfer
822+
823-
	T:saveToLog("network.transferItemToTurtle(availableStorage = "..textutils.serialise(availableStorage, {compact = true})..
823+
824-
				"\navailableStorageKeys = "..textutils.serialise(availableStorageKeys, {compact = true})..
824+
825-
				"\n"..turtleName..", crafterData = "..textutils.serialise(crafterData, {compact = true}))
825+
826
			T:go("C1", false, 0, false, R.useBlockType)
827-
	local total = 0
827+
828-
	local numSlots = 0
828+
829-
	local sent = 0
829+
830-
	for _, v in ipairs(crafterData) do								-- how many items required in total?
830+
831-
		total = total + v[2]										-- how many slots does it go in
831+
832-
		numSlots = numSlots + 1
832+
833
			if l == R.length and R.data == "house" then
834-
	for _, availableStorageKey in ipairs(availableStorageKeys) do	-- eg {minecraft:chest_114, minecraft:chest_115}
834+
835-
		local storageName = availableStorageKey						-- eg minecraft:chest_114
835+
836-
		local object = availableStorage[storageName]				-- availableStorage.minecraft:chest_114 = {count = 90, data = {{14,64},{15,26}}
836+
837-
		local storageData = object.data								-- eg data = {{14,64},{15,26}}
837+
838-
		local storageCount = object.count							-- eg count = 90
838+
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
839+
840-
			local toCrafterSlot = crafterSlotData[1]				-- eg slot 2 in turtle
840+
841-
			local amountToSend = crafterSlotData[2]					-- eg place 22 items in slot 2
841+
842-
			T:saveToLog("storageData = "..textutils.serialise(storageData, {compact = true}))
842+
843-
			T:saveToLog("crafterSlotData = "..textutils.serialise(crafterSlotData, {compact = true}))
843+
844-
			for i = 1, #storageData do								-- {{14,64},{15,26}}					
844+
845-
				local slotData = storageData[i]						-- {14,64}
845+
846-
				local availableToSend = slotData[2]					-- 64
846+
847-
				local fromStorageSlot = slotData[1]					-- 14
847+
848-
				local confirmedSent = 0
848+
849
		end
850-
				T:saveToLog("i = "..i..", slotData = "..textutils.serialise(slotData, {compact = true}))
850+
851-
				if availableToSend >= amountToSend then
851+
852-
					T:saveToLog("availableToSend ("..availableToSend..") >= amountToSend: ("..amountToSend.."), current value of sent = "..sent)
852+
853-
					T:saveToLog("?confirmedSent = peripheral.call("..storageName..", 'pushItems', "..turtleName..
853+
854-
								", from slot "..fromStorageSlot..", amountToSend = "..
854+
855-
								amountToSend..", to turtle slot "..toCrafterSlot)
855+
856-
					confirmedSent = peripheral.call(storageName, "pushItems", turtleName, fromStorageSlot, amountToSend, toCrafterSlot)
856+
857-
					sent = sent + confirmedSent
857+
858-
					T:saveToLog("verified confirmedSent = "..confirmedSent..", sent = "..sent)
858+
859-
					slotData[2] = slotData[2] - confirmedSent
859+
860-
					crafterSlotData[2] = 0
860+
861-
					T:saveToLog("slotData[2] = "..slotData[2]..", crafterSlotData[2] = "..crafterSlotData[2])
861+
862
		T:turnRight(2)				-- rotate 180
863-
					T:saveToLog("availableToSend ("..availableToSend..") < amountToSend: ("..amountToSend.."), current value of sent = "..sent)
863+
864-
					T:saveToLog("?confirmedSent = peripheral.call("..storageName..", 'pushItems', "..turtleName..
864+
865-
								", from slot "..fromStorageSlot..", availableToSend = "..
865+
866-
								availableToSend..", to turtle slot "..toCrafterSlot)
866+
867-
					-- taking items from multiple storage slots requires loading into turtle first
867+
868-
					confirmedSent = peripheral.call(storageName, "pushItems", turtleName, fromStorageSlot, availableToSend, toCrafterSlot)
868+
869-
					sent = sent + confirmedSent
869+
870-
					T:saveToLog("verified confirmedSent = "..confirmedSent..", sent = "..sent)
870+
871-
					amountToSend = amountToSend - confirmedSent
871+
872-
					slotData[2] = slotData[2] - confirmedSent
872+
873-
					crafterSlotData[2] = amountToSend
873+
874-
					T:saveToLog("slotData[2] = "..slotData[2]..", crafterSlotData[2] = "..crafterSlotData[2])
874+
875
				T:go("U3F1R2")
876
			end
877-
				if crafterSlotData[2] == 0 then
877+
878-
					T:saveToLog("crafterSlotData[2]("..crafterSlotData[2]..") == 0: breaking\n")
878+
879-
					break	-- already sent correct amount
879+
880
		elseif remaining == 2 then
881
			lib.doubleLayer(R)
882
		end
883-
		if sent >= total then 
883+
884-
			T:saveToLog("sent("..sent..") >= total ("..total.."): breaking\n")
884+
885
		while turtle.down() do end
886
	end
887
	
888
	return {}
889-
	return sent
889+
890
891
local function buildStructure(R)
892-
function network.pullItems(fromName, fromSlot, quantity, toName, toSlot)
892+
893-
	quantity = quantity or 1
893+
894-
	toSlot = toSlot or nil
894+
895-
	if type(fromName) == "table" then			-- already a wrapped peripheral
895+
896-
		fromName = peripheral.getName(fromName)
896+
897
			T:down(1)
898-
	if type(toName) == "string" then
898+
899-
		toName = peripheral.wrap(toName)
899+
900
	local buildHeight = R.height
901-
	toName.pullItems(fromName, fromSlot, quantity, toSlot)
901+
902
	local width = R.width
903
	local length = R.length
904-
function network.updateList(storageType)
904+
905-
	local output = ""
905+
906-
	if storageType == "barrel" then
906+
907-
		output = textutils.serialize(barrelItems)		-- serialise to json ready to write to file
907+
908-
	elseif storageType == "chest" then
908+
909-
		output = textutils.serialize(chestItems)		-- serialise to json ready to write to file
909+
910
	end
911-
	local fileName = storageType.."Items.lua"			-- barrelList.lua or chestList.lua
911+
912-
	local outputHandle = fs.open(fileName, "w")			-- open file
912+
913-
	outputHandle.writeLine("return")					-- start file with return
913+
914-
	outputHandle.write(output)							-- add serialised table
914+
915-
	outputHandle.close()								-- close file
915+
916
		buildWall(R)
917
		
918-
function network.wrapModem(R, storageType)
918+
919-
	--[[To move turtle inventory items use the target peripheral:
919+
920-
		local modem = peripheral.wrap("front")		-- wrap modem next to turtle (beware crafting table!)
920+
921-
		local turtleName = modem.getNameLocal()		-- get name of the turtle
921+
922-
		local barrel = peripheral.find("barrel")	-- find barrel name you want to receive goods
922+
923-
		barrel.pushItems(turtleName, 1, 1)			-- push items FROM turtle to barrel  pushItems(toName, fromSlot , limit , toSlot)
923+
924-
		barrel.pullItems(turtleName, fromSlot , limit , toSlot)
924+
925
		lib.goDown(R)
926-
	local modem = peripheral.find("modem")		-- find modem
926+
927-
	if modem == nil then
927+
928-
		return nil, "Modem not found"
928+
929
		height = height - R.height	-- 1, 2 or 3
930-
	local turtleName = modem.getNameLocal()		-- get name of the turtle
930+
931-
	local rawStorage = nil						-- peripheral find can return duplicate values
931+
932-
	if storageType:find("barrel") ~= nil then
932+
933-
		rawStorage = {peripheral.find("minecraft:barrel")}
933+
934-
	elseif storageType:find("chest") ~= nil then
934+
935-
		rawStorage = {peripheral.find("minecraft:chest")}
935+
936
			R.length = length
937-
	local storage = {}
937+
938-
	local names = {}
938+
939-
	for k, value in ipairs(rawStorage) do
939+
940-
		local name = peripheral.getName(value)
940+
941-
		if not utils.tableContains(names, name, true) then	-- use exact match as checking peripherals
941+
942-
			table.insert(storage, value)
942+
943-
			table.insert(names, name)
943+
944
	return {}
945
end
946-
	return storage, turtleName, names
946+
947
local function buildGableRoof(R)
948
	--[[
949-
function utils.assessFarm(R)
949+
950-
	-- sets R.networkFarm and R.mysticalAgriculture
950+
951-
	menu.colourPrint("Assessing farm properties...", colors.yellow)
951+
952-
	--local storage = true
952+
953-
	for turns = 1, 4 do
953+
954
	    |   down
955-
		local itemAhead = T:getBlockType("forward")
955+
956-
		if itemAhead:find("modem") ~= nil then
956+
957-
			if not R.networkFarm then	-- prevents repeated text display
957+
958-
				R.networkFarm = true
958+
959-
				menu.colourPrint("Network storage in use.", colors.magenta)
959+
960
		for i = 1, R.length + 2 do
961
			if R.useBlockType:find("stairs") ~= nil then
962-
		if itemAhead:find("mysticalagriculture") ~= nil then
962+
				T:place("stairs", 0, "up")
963-
			R.mysticalAgriculture = true
963+
964-
			menu.colourPrint("Mystical Agriculture deployed.", colors.lime)
964+
965
			end
966
			if i < R.length + 2 then
967-
	sleep(1.5)
967+
968
					T:go("L1F1R1")
969
				else
970
					T:go("R1F1L1")
971
				end
972-
function utils.assessTreeFarm(R)
972+
973
		end
974
	end
975-
	function lib.getSaplingType(R, blockType)
975+
976-
		if blockType == "minecraft:mangrove_log" then
976+
977-
			R.logType = "mangrove"
977+
978-
			R.useBlockType ="mangrove_propagule"
978+
979
			for w = 1, width do
980-
			local parts = T:getNames(blockType)
980+
981-
			if parts[2] == "dark" then
981+
982-
				R.logType = "dark_oak"
982+
983-
				parts[2] = "dark_oak"
983+
984
					else
985-
				R.logType = parts[2]				-- eg "oak"
985+
986
					end
987
				end
988-
			R.useBlockType = parts[2].."_sapling"	-- eg "oak_sapling"
988+
989
			if h < R.height then
990
				if outward then
991-
		turtle.turnLeft()
991+
992
				else
993-
		return R
993+
994
				end
995
			end
996
			width = width - 2
997-
	if blockType:find("modem") ~= nil then
997+
998-
		R.networkFarm = true
998+
999
		return outward
1000-
		if blockType:find("polished") == nil then
1000+
1001-
			R.message = "Not on modem or polished. Check position"
1001+
1002
	local outward = true
1003
	-- go to centre of end wall if odd no, or half width if even
1004
	R.height = math.floor(R.width / 2)
1005-
	if R.networkFarm then
1005+
1006
	
1007
	utils.goBack(1)
1008-
		T:saveToLog("T:forward(1): blockType = "..blockType)
1008+
1009-
		if blockType:find("log") ~= nil then
1009+
1010-
			R = lib.getSaplingType(R, blockType)
1010+
1011-
		elseif blockType:find("barrel") ~= nil then
1011+
1012-
			T:go("R2F2")
1012+
1013
			T:down(1)
1014-
			if blockType:find("log") ~= nil then
1014+
1015-
				R = lib.getSaplingType(R, blockType)
1015+
1016
	end
1017-
		else	-- if in correct position water is 2 blocks below
1017+
1018
		T:go("F"..R.height + 2 .."R2U"..R.height)
1019
	else
1020-
				if blockType:find("water") == nil then
1020+
1021-
					R.message = "No modem below. Check position"
1021+
1022
	for h = 1, R.height + 1 do						-- place tiles on right side of roof
1023
		lib.placeRoof(R, outward)
1024-
					turtle.up()
1024+
1025-
					utils.goBack(1)
1025+
1026-
					T:go("R1F1")
1026+
1027
			outward = not outward
1028-
					if blockType:find("log") ~= nil then
1028+
1029-
						R = lib.getSaplingType(R, blockType)
1029+
1030
	-- gable ends
1031-
						R.message = "Unable to determine location. Check position"
1031+
1032-
						return R
1032+
1033
	else
1034
		T:go("F1L1U1")
1035
	end
1036-
				R.message = "Unable to determine location. Check position"
1036+
1037-
				return R
1037+
1038
	if outward then
1039
		T:go("R1F"..R.height - 1 .."R1")
1040
	else
1041
		T:go("L1F"..R.height - 1 .."L1")
1042-
	return R	-- sets R.networkFarm and R.useBlockType to sapling type
1042+
1043
	outward = not outward
1044
	outward = lib.placeGable(R, outward)
1045
	if isOdd then
1046
		if outward then
1047
			T:go("L1F1R1U2F1")
1048
		else
1049
			T:go("R1F1L1U2F1")
1050
		end
1051
		for i = 1, R.length do
1052
			T:go("C2F1", false, 0, false)
1053
		end
1054
		for i = 1, R.length + 2 do
1055
			utils.goBack(1)
1056
			T:place("slab", 0, "forward")
1057
		end
1058
	end
1059
	while turtle.down() do end
1060
	
1061
	return {}
1062
end
1063
1064
local function buildPitchedRoof(R)
1065
	--[[
1066
	stairs placement:
1067
	   _|   up
1068
	  
1069
	   T L  forward
1070
	   _
1071
	    |   down
1072
1073
	]]
1074
	local lib = {}
1075
		
1076
	function lib.placeRoofSection(length)
1077
		-- starts facing centre of building
1078
		for i = 1, length do
1079
			if i < length then
1080
				if R.useBlockType:find("stairs") ~= nil then
1081
					T:place("stairs", 0, "up")
1082
				else
1083
					T:go("C0", false, 0, false, R.useBlockType)
1084
				end
1085
				T:go("L1F1R1")
1086
			end
1087
		end
1088
		-- ends facing centre of building
1089
	end
1090
	
1091
	function lib.placeRoof(R, width, length)
1092-
function utils.checkFarmPosition(R)
1092+
1093-
	local discovered = ""
1093+
1094-
	local success, storage, detected = false, "", 0
1094+
1095
		T:go("R1")
1096-
	T:saveToLog("Checking position "..blockType.. " down")
1096+
1097-
	if blockType:find("water") ~= nil then -- over water, ? facing E (crops)
1097+
1098-
		-- network: E = __modem_, N = _modem__, W = modem___, S = ___modem
1098+
1099-
		-- storage: E = _chestchest_, N = chestchest__, W = chest__chest, S = __chestchest
1099+
1100-
		-- storage: E = _barrelbarrel_, N = barrelbarrel__, W = barrel__barrel, S = __barrelbarrel
1100+
1101-
		T:saveToLog("? over water = true")
1101+
1102
		-- add slabs at top
1103-
			success, storage = utils.isStorage("forward")	-- true/false, chest, barrel, modem / ""
1103+
1104-
			local itemAhead = T:getBlockType("forward")
1104+
1105
			T:forward(length - 3)
1106-
				discovered = discovered .. storage
1106+
1107-
				if storage == "modem" then
1107+
				T:place("slab", 0, "forward")
1108-
					R.networkFarm = true
1108+
1109
			end
1110
			T:place("slab", 0, "forward")
1111-
				discovered = discovered .. "_"
1111+
1112
			T:place("slab", 0, "forward")
1113-
			if itemAhead:find("mysticalagriculture") ~= nil then
1113+
1114-
				R.mysticalAgriculture = true
1114+
1115
		utils.goBack(1)
1116
	end
1117
	--[[
1118-
		T:saveToLog("Storage blocks found:"..discovered)
1118+
1119-
		if R.networkFarm then
1119+
1120-
			if discovered == "modemmodem__" then
1120+
1121-
			   T:turnLeft(1)
1121+
1122-
			elseif discovered == "modem__modem" then
1122+
1123-
			   T:turnLeft(2)
1123+
1124-
			elseif discovered == "__modemmodem" then
1124+
1125-
			   T:turnRight(1)
1125+
1126
	if width is odd, ignore top layer as is only 1 block wide
1127-
			R.ready = true
1127+
1128
	local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0
1129-
			if discovered == "barrelbarrel__" or
1129+
1130-
			   discovered == "barrelchest__" or
1130+
1131-
			   discovered == "chestchest__" then
1131+
1132-
			   T:turnLeft(1)
1132+
1133-
			elseif discovered == "barrel__barrel" or discovered == "chest__chest" then
1133+
1134-
			   T:turnLeft(2)
1134+
1135-
			elseif discovered == "__barrelbarrel" or discovered == "__chestchest" then
1135+
1136-
			   T:turnRight(1)
1136+
1137
		width = width + 2
1138-
			R.ready = true
1138+
1139
			utils.goBack(1)
1140-
	end	-- else not over water
1140+
1141
			utils.goBack(1)
1142-
	T:saveToLog("utils.checkFarmPosition(R) return R = "..textutils.serialise(R, {compact = true}))
1142+
1143-
	return R -- now facing crops, R.ready = true/false, R.networkFarm = true/false
1143+
1144
	while turtle.down() do end
1145
	
1146
	return {}
1147-
	local fuelNeeded = quantity - turtle.getFuelLevel() -- eg 600
1147+
1148
1149
local function clearAndReplantTrees() -- 25
1150
	--[[ clear all trees in a rectangle area defined by walls, fences or non-dirt blocks
1151
	replant with same type of sapling. If original tree 2 blocks wide, replant 4 if possible. ]]
1152
	
1153
	local lib = {}
1154
	
1155
	function lib.getSaplingFromLogType(log)
1156
		--[[ get type of sapling to plant from log type ]]
1157
		if log:find("oak") ~= nil then
1158
			return "minecraft:oak_sapling"
1159
		elseif log:find("spruce") ~= nil then
1160-
	-- blockType, data
1160+
1161-
	local blockType = T:getBlockType(direction)
1161+
1162
			return "minecraft:birch_sapling"
1163
		elseif log:find("jungle") ~= nil then
1164
			return "minecraft:jungle_sapling"
1165
		elseif log:find("acacia") ~= nil then
1166
			return "minecraft:acacia_sapling"
1167
		elseif log:find("dark_oak") ~= nil then
1168
			return "minecraft:dark_oak_sapling"
1169
		end
1170
		return "sapling"
1171
	end
1172
	
1173
	function lib.plantSapling(sapling, double)
1174
		--[[ plant sapling(s) ]]
1175
		if sapling == "" or sapling == nil then sapling = "sapling" end
1176
		T:up(1)
1177-
function utils.convertEssence(R)
1177+
1178-
	-- R.subChoice = 1 to 5
1178+
1179-
	-- R.size = quantity
1179+
1180-
	-- 1 = inferium to prudentium
1180+
1181-
	-- 2 = prudentium to tertium
1181+
1182-
	-- 3 = Tertium to Imperium
1182+
1183-
	-- 4 = Imperium to Supremium
1183+
					T:place(sapling, -1, "down")
1184-
	-- 5 = Supremium to Insanium
1184+
1185
				end
1186
				T:forward(1)		-- above pre-planted sapling
1187-
	function lib.getCrystal()
1187+
1188-
		local turtleSlot, turtleCount = 0, 0
1188+
				if not T:place(sapling, -1, "down") then
1189-
		if utils.isStorage("up") then
1189+
					T:place("sapling", -1, "down")
1190-
			turtle.select(2)
1190+
1191-
			turtle.suckUp()
1191+
1192
		else
1193-
		turtleSlot = T:getItemSlot("crystal")
1193+
			if not T:place(sapling, -1, "down") then
1194-
		if turtleSlot == 0 then
1194+
				T:place("sapling", -1, "down")
1195-
			turtleSlot, turtleCount = network.getItemFromNetwork("chest", "infusion_crystal", 1)
1195+
1196
		end
1197-
		if turtleSlot > 0 then
1197+
1198-
			turtle.select(turtleSlot)
1198+
1199-
			turtle.transferTo(2)
1199+
1200
	function lib.suck()
1201
		--[[ Collect saplings, sticks and apples ]]
1202
		turtle.select(1)
1203
		turtle.suck()
1204
		turtle.suckUp()
1205
		turtle.suckDown()
1206-
	function lib.loadCrafter(crafterName)
1206+
1207-
		-- up to 64 essences stored in turtle slots 2, 4, 6, 8
1207+
1208-
		local slots = {2, 4, 6, 8}
1208+
1209-
		for _, slot in ipairs(slots) do		-- drop each slot contents into crafter ? slot 1
1209+
1210
		if direction == "r" then
1211-
			turtle.drop()
1211+
1212-
			peripheral.call(crafterName, "pushItems", crafterName, 1, nil, slot)	-- move to correct place
1212+
1213
		else
1214
			T:turnLeft(1)
1215
			direction = "r"
1216-
	function lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
1216+
1217-
		-- collect essence as above and place in minecraft:crafter slots 2, 4, 6, 8
1217+
1218-
		local crafterData = {{2, loaded}, {4, loaded}, {6, loaded}, {8, loaded}} -- eg 64 items in each of 4 slots in the crafter
1218+
1219-
		network.transferItemToTurtle(availableStorage, availableStorageKeys, turtleName, crafterData)
1219+
1220
	function lib.emptyInventory(blockTypeD)
1221
		--[[ Empty all except 32 of each sapling and 1 chest ]]
1222-
	function lib.runCrafter(crafterName, count)
1222+
1223-
		-- can only craft once, then crystal + output is returned to turtle
1223+
1224-
		-- repeat process count times
1224+
1225-
		-- drop crystal into crafter, move to slot 5
1225+
1226
			-- empty logs, apples, sticks and all but 1 stack of each sapling type
1227-
			local slot = T:getItemSlot("crystal")
1227+
1228-
			if slot > 0 then
1228+
1229
		else
1230-
				turtle.drop()
1230+
1231-
				network.moveItem(crafterName, "crystal", 5)
1231+
1232-
				for i = 1, 3 do
1232+
1233-
					rs.setAnalogOutput("front",15)
1233+
1234-
					sleep(0.1)
1234+
1235-
					rs.setAnalogOutput("front", 0)
1235+
1236
		if blockTypeD == nil then
1237
			blockTypeD = T:getBlockType("down")
1238
		end
1239-
		while turtle.suck() do end
1239+
1240
			T:down(1)
1241
			lib.suck()
1242-
	function lib.storeCrystal()
1242+
1243-
		if utils.isStorage("up") then
1243+
1244-
			T:dropItem("crystal", "up")
1244+
1245
	end
1246-
			network.sendItemToNetworkStorage(R, "chest", "crystal", 0)	-- empty turtle to storage chests
1246+
1247
	function lib.moveForward()
1248
		--[[ Move forward 1 block only, go down to ground while air or leaves below ]]
1249
		local blockTypeF = T:getBlockType("forward")
1250-
	function lib.storeOutput()
1250+
1251-
		if utils.isStorage("up") then
1251+
1252-
			T:dropItem("crystal", "up")
1252+
1253
			T:dig("up")													-- remove leaves / low branches above to allow space for player
1254-
		network.sendItemToNetworkStorage(R, "chest", "all", 0)	-- empty turtle to storage chests
1254+
1255
			blockTypeD = lib.moveDown()
1256
			if not lib.emptyInventory(blockTypeD) then					-- check if above a corner chest / barrel
1257-
	function lib.getStorageData(essence)
1257+
1258-
		local _, turtleName, storageNames = network.wrapModem(R, "chests")	-- _, turtleName, list of chest names
1258+
1259-
		if turtleName == "Modem not found" then return 0, nil, nil, turtleName end
1259+
1260-
		local availableStorage = {}
1260+
1261-
		local availableStorageKeys = {}
1261+
1262-
		local total = 0
1262+
1263-
		for _, storageName in pairs(storageNames) do 
1263+
1264-
			local storageCount, storageData = network.findItemCountInInventory(storageName, essence)	-- eg 86, {{1, 64},{4, 22}}
1264+
1265-
			if storageCount > 0 then		-- eg 86: storage has some items
1265+
1266-
				T:saveToLog("storageCount = "..storageCount)
1266+
1267-
				availableStorage[storageName] = {}
1267+
1268-
				availableStorage[storageName].count = storageCount
1268+
1269-
				availableStorage[storageName].data = storageData
1269+
1270-
				table.insert(availableStorageKeys, storageName)
1270+
1271-
				total = total + storageCount
1271+
1272
		while blockTypeF:find("dirt") ~= nil or
1273
			  blockTypeF:find("grass_block") ~= nil or
1274
			  T:isVegetation(blockTypeF) do	-- go up while dirt, grass-block or any vegetation in front
1275-
		return total, availableStorage, availableStorageKeys, turtleName
1275+
1276
			blockTypeF = T:getBlockType("forward")
1277-
			availableStorage.minecraft:chest_114 = {count = 86, data = {{1, 64},{4, 22}},
1277+
1278-
			availableStorage.minecraft:chest_115 = {count = 1024, data = {{1, 64},{2, 64},{3, 64}, ... }
1278+
1279
				return T:getBlockType("forward")
1280
			elseif blockTypeF:find("leaves") ~= nil then
1281
				T:dig("forward")
1282-
	local essences = {"mysticalagriculture:inferium_essence",
1282+
1283-
					"mysticalagriculture:prudentium_essence",
1283+
1284-
					"mysticalagriculture:tertium_essence",
1284+
1285-
					"mysticalagriculture:imperium_essence",
1285+
1286-
					"mysticalagriculture:supremium_essence",
1286+
1287-
					"mysticalagriculture:insanium_essence"}
1287+
1288
	function lib.harvestTree(blockTypeF)
1289-
	local message = network.loadStorageLists()
1289+
1290-
	if message ~= nil then return {message} end
1290+
1291-
	local essence = essences[R.subChoice]
1291+
1292-
	local missing = ""
1292+
1293-
	local crafter = peripheral.find("minecraft:crafter")
1293+
1294-
	local crafterName = ""
1294+
1295-
	local completed = 0
1295+
1296-
	if R.size > 0 then
1296+
1297-
		R.size = math.floor(R.size / 4) * 4
1297+
1298-
		if R.size == 0 then R.size = 4 end
1298+
1299
		local success = true
1300-
	if crafter == nil then
1300+
1301-
		return {"No crafter found"}
1301+
1302
			if not success then 								-- did not move forwards, block in the way: either log, dirt/grass, border block or vegetation
1303-
		crafterName = peripheral.getName(crafter)
1303+
1304-
		T:saveToLog("utils.convertEssence started using "..essence..", quantity = "..R.size )
1304+
1305-
		while turtle.suck() do end						-- empty crafter
1305+
1306-
		lib.storeOutput()	-- empty turtle to storage chests, (except crystal if storage above)
1306+
1307-
		if not lib.getCrystal() then
1307+
1308-
			return {"Failed: missing infusion crystal"}
1308+
1309
						blockTypeF = lib.moveUp(blockTypeF)		-- move up until leaves/log/air
1310-
		lib.storeCrystal()
1310+
1311-
		local totalInStorage, availableStorage, availableStorageKeys, turtleName = lib.getStorageData(essence)
1311+
1312-
		if totalInStorage < 4 then
1312+
1313-
			return {"Only "..totalInStorage.." ".. essence:sub(20).." available"}
1313+
1314
							end
1315-
			-- can only transfer full amount direct to crafter
1315+
1316-
			-- if a chest has 32 items in 1 slot and 32 in another Slot
1316+
1317-
			-- these have to be sent into the turtle first, dropped into crafter slot 1 and moved to correct position
1317+
1318-
			totalInStorage = math.floor(totalInStorage / 4) * 4
1318+
1319-
			if R.size == 0 then	-- process all
1319+
1320-
				T:saveToLog("initial call lib.loadTurtle("..turtleName..", "..totalInStorage.." essence")
1320+
1321-
				local processed = 0
1321+
1322-
				local loaded = 0
1322+
1323
	function lib.isBorder(blockType)
1324-
				while totalInStorage > 0 do		-- use ALL stored essence
1324+
1325-
					if totalInStorage - 256 > 0 then
1325+
1326-
						loaded = 64
1326+
1327
		end
1328-
						loaded = totalInStorage / 4
1328+
1329
			return false, ""
1330-
					lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
1330+
1331-
					lib.loadCrafter(crafterName)
1331+
1332-
					lib.getCrystal()
1332+
1333-
					processed = processed + loaded
1333+
1334-
					totalInStorage = totalInStorage - loaded * 4
1334+
1335-
					lib.runCrafter(crafterName, loaded)
1335+
1336-
					lib.storeOutput()
1336+
1337
		end
1338-
			elseif R.size <= 64 then
1338+
1339-
				local loaded = math.min(R.size, totalInStorage)	-- process requested or available if less
1339+
1340-
				if loaded > 0 then
1340+
1341-
					lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
1341+
1342-
					lib.loadCrafter(crafterName)
1342+
1343-
					lib.getCrystal()
1343+
1344-
					lib.runCrafter(crafterName, loaded)
1344+
1345-
					lib.storeOutput()
1345+
1346
		end
1347-
			else	-- amount > 64
1347+
1348-
				local processed = 0
1348+
1349-
				local loaded = 0
1349+
1350-
				while totalInStorage > 0 and processed < R.size do	-- stop if run out of essence, or reached target
1350+
1351-
					if totalInStorage - 256 > 0 and R.size - processed >= 64 then
1351+
1352-
						loaded = 64
1352+
1353-
					elseif totalInStorage - 256 > 0 and R.size - processed > 0 then
1353+
1354-
						loaded = R.size - processed
1354+
1355
		else
1356-
					lib.loadTurtle(availableStorage, availableStorageKeys, turtleName, essence, loaded)
1356+
1357-
					lib.loadCrafter(crafterName)
1357+
1358-
					lib.getCrystal()
1358+
1359-
					processed = processed + loaded
1359+
1360-
					totalInStorage = totalInStorage - loaded * 4
1360+
1361-
					lib.runCrafter(crafterName, loaded)
1361+
1362-
					lib.storeOutput()
1362+
1363
		--[[ assume started after reset. if log above harvest tree else return to ground. Find starting corner]]
1364
		local blockType = T:getBlockType("up")					-- dig any logs above, return to ground
1365-
			lib.storeOutput()
1365+
1366
		if blockType:find("log") ~= nil then					-- originally felling a tree so complete it
1367-
		return {"success"}
1367+
1368
			local double = T:harvestTree(false, false, "up")	-- assume single tree, will auto-discover
1369
			lib.plantSapling(log, double)
1370
		else													-- no log above so go downm
1371-
function utils.craftItem(R)
1371+
1372-
	local message = network.loadStorageLists()	-- initialises or creates lists of where an item can be found: GLOBAL LISTS!
1372+
1373-
	if message ~= nil then return {message} end
1373+
1374-
	T:saveToLog("call network.emptyInventory(R, {'sapling', 'propagule', 'dirt', 'crafting'}, {'all'}, true)")
1374+
1375-
	network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)	-- 2 lists, one for barrels, one for chests
1375+
1376-
	T:saveToLog("\ncall network.getItemFromNetwork('barrel', 'minecraft:dirt', 169)")
1376+
1377-
	--network.getItemFromNetwork(storageType, itemRequired, countRequired, toTurtleSlot, ignoreStock)
1377+
1378-
	local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 169, nil, false)
1378+
1379-
	T:saveToLog("Get from barrel completed: turtleSlot = "..turtleSlot..", turtleCount = "..turtleCount..", ignoreStock = "..tostring(ignoreStock))
1379+
1380-
	if turtleCount < 169 then
1380+
1381-
		T:saveToLog("\ncall network.getItemFromNetwork('chest', 'minecraft:dirt', ".. 169 - turtleCount..", ignoreStock = "..tostring(ignoreStock)..")")
1381+
1382-
		turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 169 - turtleCount, nil, true)
1382+
1383-
		if turtleCount < 169 then	-- ask player for saplings
1383+
1384-
			T:checkInventoryForItem({"dirt"}, {169 - turtleCount})
1384+
1385
	end
1386
	local secondBorderFound = false
1387
	while not secondBorderFound do
1388
		lib.safeMove()														-- moves forward until reaches border forward or below
1389
		lib.turn(direction)													-- turn r or l. direction is not changed
1390
		success, blockTypeF = lib.isBorder()								-- no blockType passed as parameter so will return current block in new forward direction
1391
		if success then
1392
			secondBorderFound = true										-- game over
1393
		elseif blockTypeF:find("log") ~= nil then							-- tree in front
1394
			lib.harvestTree(blockTypeF)
1395
		elseif blockTypeF == "" or blockTypeF:find("leaves") ~= nil then	-- air or leaves in front
1396
			T:forward(1)													-- move forward 1 block
1397
			lib.moveDown()													-- go down if required
1398
		elseif	blockTypeF:find("dirt") ~= nil or
1399
				blockTypeF:find("grass_block") ~= nil or
1400
				T:isVegetation(blockTypeF) then								-- dirt, grass_block or vegetation in front
1401
			blockTypeF = lib.moveUp(blockTypeF)								-- move up until air or border ahead.
1402
			if lib.isBorder(blockTypeF) then								-- border ahead
1403
				secondBorderFound = true
1404
			else															-- air ahead									
1405
				T:forward(1)												-- move forward 1 block
1406
			end
1407
		end
1408
		direction = lib.turn(direction)										-- turn r or l. direction is changed to opposite
1409
	end
1410
	lib.moveDown()															-- return to ground level
1411
	lib.emptyInventory()
1412
	return {}
1413
end
1414
1415
local function clearArea(R) -- 71, called from 22
1416
	local evenWidth = false
1417
	local evenHeight = false
1418
	local loopWidth
1419
	-- go(path, useTorch, torchInterval, leaveExisting)
1420
	if R.width % 2 == 0 then
1421
		evenWidth = true
1422
		loopWidth = R.width / 2
1423
	else
1424
		loopWidth = math.ceil(R.width / 2)
1425
	end
1426
	if R.length % 2 == 0 then
1427
		evenHeight = true
1428
	end
1429
	turtle.select(1)
1430-
						T:place("minecraft:torch", "forward", false)
1430+
1431
	-- if R.width is even no, then complete the up/down run
1432
	-- if R.width odd no then finish at top of up run and reverse
1433
	-- should be on flat ground, check voids below, harvest trees
1434
	for x = 1, loopWidth do
1435
		-- Clear first column (up)
1436
		for y = 1, R.length do
1437
			if R.useBlockType == "dirt" then
1438
				if not turtle.detectDown() then
1439
					T:place("minecraft:dirt", -1, "down", true)
1440
				else --if not water, dirt, grass , stone then replace with dirt
1441
					blockType, blockModifier = T:getBlockType("down")
1442
					if blockType ~= "" then
1443
						if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
1444
							turtle.digDown()
1445
							T:place("minecraft:dirt", -1, "down", true)
1446-
function utils.createStorage()
1446+
1447-
	-- start in centre, above 1st level
1447+
1448-
	T:place("modem", "down")
1448+
1449
			end
1450
			if y < R.length then
1451-
	T:place("chest", "down")	-- places with handle at back of turtle
1451+
1452
			end
1453-
	T:place("chest", "down")	-- 2nd of pair
1453+
1454-
	for i = 1, 3 do
1454+
1455
		if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
1456-
		T:place("chest", "down")
1456+
1457-
		T:go("R1F1L1")
1457+
1458-
		T:place("chest", "down")
1458+
1459
					if not turtle.detectDown() then
1460
						T:place("minecraft:dirt", -1, "down", true)
1461-
	T:go("F1L1F1")	-- end at starting position
1461+
1462-
	network.attachModem()
1462+
						blockType, blockModifier = T:getBlockType("down")
1463
						if blockType ~= "" then
1464
							if blockType ~= "minecraft:dirt" and blockType ~= "minecraft:grass_block" then
1465
								turtle.digDown()
1466
								T:place("minecraft:dirt", -1, "down", true)
1467
							end
1468
						end
1469
					end
1470
				end
1471
				if y < R.length then
1472
					T:go("F1+1", false, 0, false)
1473
				end
1474
			end
1475
			if x < loopWidth then 
1476
				T:go("L1F1+1L1", false,0,false)
1477
			else
1478
				T:turnRight(1)
1479
				T:forward(R.width - 1)
1480
				T:turnRight(1)
1481
			end
1482
		else -- equals R.width but is 1,3,5,7 etc
1483
			T:turnLeft(2) --turn round 180
1484
			T:forward(R.length - 1)
1485
			T:turnRight(1)
1486
			T:forward(R.width - 1)
1487
			T:turnRight(1)
1488
		end
1489
	end
1490
	return {}
1491
end
1492
1493
local function clearRectangle(R) -- 72
1494
	--local function clearRectangle(width, length, up, down)
1495
	-- height = 0: one level, 1 = +up, 2 = +down, 3 = +up/down
1496
	local lib = {}
1497
	function lib.UpDown(length)
1498
		for l = 1, length do
1499
			T:go("x0x2F1x0x2")
1500
		end
1501
	end
1502
	
1503
	function lib.Up(length)
1504
		for l = 1, length do
1505
			T:go("x0F1x0")
1506
		end
1507
	end
1508
	
1509
	function lib.Down(length)
1510
		for l = 1, length do
1511
			T:go("x2F1x2")
1512
		end
1513
	end
1514
	
1515
	function lib.Forward(length)
1516
		T:forward(length)
1517
	end
1518
	
1519
	-- could be 1 wide x xx R.length (trench) R.up and return
1520
	-- could be 2+ x 2+
1521
	-- even no of runs return after last run
1522
	-- odd no of runs forward, back, forward, reverse and return
1523
	turtle.select(1)
1524
	if R.width == 1 then 					-- single block trench ahead only
1525
		if R.up and R.down then				-- single block wide trench dig R.up and R.down = 3 blocks deep
1526
			lib.UpDown(R.length - 1)
1527
		elseif R.up then					-- single block wide trench dig R.up = 2 blocks deep
1528
			lib.Up(R.length - 1)
1529
		elseif R.down then				-- single block wide trench dig R.down = 2 blocks deep
1530
			lib.Down(R.length - 1)
1531
		else 							-- single block wide = 1 block deep
1532
			lib.Forward(R.length - 1)
1533
		end
1534
		T:turnRight(2)					-- turn at the top of the run
1535
		T:forward(R.length - 1)			-- return to start
1536
		T:turnRight(2)					-- turn round to original position
1537
	else 								-- R.width 2 or more blocks
1538
		local iterations = 0 			-- R.width = 2, 4, 6, 8 etc
1539
		if R.width % 2 == 1 then  		-- R.width = 3, 5, 7, 9 eg R.width 7
1540
			iterations = (R.width - 1) / 2 -- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
1541
		else
1542
			iterations = R.width / 2		-- iterations 1, 2, 3, 4 for widths 2, 4, 6, 8
1543
		end
1544
		for i = 1, iterations do 		-- eg 3 blocks wide, iterations = 1
1545
			if R.up and R.down then							-- dig R.up and R.down
1546
				lib.UpDown(R.length - 1)
1547
				T:go("x0x2R1F1x0x2R1x0x2")				-- turn round
1548
				lib.UpDown(R.length - 1)
1549
			elseif R.up then								-- dig R.up
1550
				lib.Up(R.length - 1)
1551
				T:go("x0R1F1x0R1x0")
1552
				lib.Up(R.length - 1)
1553
			elseif R.down then							-- dig R.down
1554
				lib.Down(R.length - 1)
1555
				T:go("x2R1F1x2R1x2")
1556
				lib.Down(R.length - 1)
1557
			else										-- no digging R.up or R.down
1558
				lib.Forward(R.length - 1)
1559
				T:go("R1F1R1")
1560
				lib.Forward(R.length - 1)
1561
			end
1562
			-- if 1 less than end, reposition for next run
1563
			if i < iterations then
1564
				T:go("L1F1L1", false, 0, false)
1565
			end
1566
		end
1567
		if R.width % 2 == 1 then  -- additional run and return to base needed
1568
			T:go("L1F1L1", false, 0, false)
1569
			if R.up and R.down then
1570
				lib.UpDown(R.length - 1)
1571
			elseif R.up then
1572
				lib.Up(R.length - 1)
1573
			elseif R.down then
1574
				lib.Down(R.length - 1)
1575
			else
1576
				lib.Forward(R.length - 1)
1577
			end
1578
			T:turnRight(2)
1579
			T:forward(R.length - 1)
1580
		end
1581
		T:go("R1F"..R.width - 1 .."R1", false, 0, false)
1582
	end
1583
	return {}
1584
end
1585
1586
local function clearPerimeter(R) -- 74
1587
	local lib = {}
1588
	function lib.UpDown(length)
1589
		for l = 1, length do
1590
			T:go("x0x2F1x0x2")
1591
		end
1592
	end
1593
	
1594
	function lib.Up(length)
1595
		for l = 1, length do
1596
			T:go("x0F1x0")
1597
		end
1598
	end
1599
	
1600
	function lib.Down(length)
1601
		for l = 1, length do
1602
			T:go("x2F1x2")
1603
		end
1604
	end
1605
	
1606
	function lib.Forward(length)
1607
		T:forward(length)
1608
	end
1609
	
1610
	if R.up and R.down then
1611
		for i = 1, 2 do
1612
			lib.UpDown(R.length - 1)
1613
			T:turnRight(1)
1614
			lib.UpDown(R.width - 1)
1615
			T:turnRight(1)
1616
		end
1617
	elseif R.up then
1618
		for i = 1, 2 do
1619
			lib.Up(R.length - 1)
1620
			T:turnRight(1)
1621
			lib.Up(R.width - 1)
1622
			T:turnRight(1)
1623
		end
1624
	elseif R.down then
1625
		for i = 1, 2 do
1626
			lib.Down(R.length - 1)
1627
			T:turnRight(1)
1628
			lib.Down(R.width - 1)
1629
			T:turnRight(1)
1630
		end
1631
	else
1632
		for i = 1, 2 do
1633
			lib.Forward(R.length - 1)
1634
			T:turnRight(1)
1635
			lib.Forward(R.width - 1)
1636
			T:turnRight(1)
1637
		end
1638
	end
1639
	return {}
1640
end
1641
1642
local function clearBuilding(R) -- 75, 43
1643
	--[[
1644
	Clear the outer shell of a building, leaving inside untouched. Optional floor/ceiling removal
1645
	clearBuilding(R)
1646
	R.subChoice = 1-'up' or 2-'down'
1647
	R.data.ceiling = true / false
1648
	R.data.floor = true / false
1649
	]]
1650
	local height = 1
1651
	local remaining = R.height -- eg 5
1652
	local start = true
1653
	local finish = false
1654
	local lib = {}
1655
	
1656
	function lib.floorOrCeiling(R)
1657
		T:go("F1R1 F1L1")
1658
		R.length = R.length - 2
1659
		R.width = R.width - 2
1660
		clearRectangle(R)
1661
		R.length = R.length + 2
1662
		R.width = R.width + 2
1663
		T:go("L1F1R1")
1664
		utils.goBack(1)
1665
	end
1666
	
1667
	function lib.singleLayer(R)
1668
		R.up = false
1669
		R.down = false
1670
		if start then
1671
			if R.data.ceiling or R.data.floor then	-- floor / ceiling to go. only one layer, so clearRectangle
1672
				lib.floorOrCeiling(R)
1673
			end
1674
			start = false
1675
		end
1676
		if finish then
1677
			if R.data.ceiling or R.data.floor then	-- floor / ceiling to go. only one layer, so clearRectangle
1678
				lib.floorOrCeiling(R)
1679
			end
1680
			finish = false
1681
		end
1682
		clearPerimeter(R)						-- no floor / ceiling
1683
	end
1684
	
1685
	function lib.doubleLayer(R)
1686
		R.up = false
1687
		R.down = false
1688
		if start then
1689
			if R.data.floor and R.subChoice == 1 then		-- going up and floor needs removing
1690
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1691
			elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing
1692
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1693
			end
1694
			start = false
1695
		end
1696
		if finish then
1697
			if R.data.ceiling and R.subChoice == 1 then		-- going down and ceiling needs removing
1698
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1699
			elseif R.data.floor and R.subChoice == 2 then 	-- going down and floor needs removing
1700
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1701
			end
1702
			finish = false
1703
		end
1704
		if R.subChoice == 1 then
1705
			R.up = true
1706
		else
1707
			R.down = true
1708
		end
1709
		clearPerimeter(R)
1710
	end
1711
	
1712
	function lib.tripleLayer(R)
1713
		-- turtle in centre layer
1714
		R.up = false
1715
		R.down = false
1716
		if start then
1717
			if R.data.floor and R.subChoice == 1 then		-- going up and floor needs removing
1718
				height = height + utils.move(R, 1, true)	-- move down 1 block
1719
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1720
				height = height + utils.move(R, 1)		-- move up 1 block
1721
			elseif R.data.ceiling and R.subChoice == 2 then -- going down and ceiling needs removing
1722
				height = height + utils.move(R, 1, true)	-- move up 1 block
1723
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1724
				height = height + utils.move(R, 1)		-- move down 1 block
1725
			end
1726
			start = false
1727
		end
1728
		if finish then
1729
			if R.data.ceiling and R.subChoice == 1 then		-- going up and ceiling needs removing
1730
				height = height + utils.move(R, 1, true)					-- move down 1 block
1731
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1732
				height = height + utils.move(R, 1)							-- move up 1 block
1733
			elseif R.data.floor and R.subChoice == 2 then 	-- going down and floor needs removing
1734
				height = height + utils.move(R, 1, true)					-- move up 1 block
1735
				lib.floorOrCeiling(R)						-- remove floor/ceiling
1736
				height = height + utils.move(R, 1)							-- move up 1 block
1737
			end
1738
			finish = false
1739
		end
1740
		R.up = true
1741
		R.down = true
1742
		clearPerimeter(R)
1743
	end
1744
	--[[
1745
	R.data = "up" or "down" as direction of travel
1746
	R.up = true to remove ceiling
1747
	R.down = true to remove floor
1748
	]]
1749-
		if not T:place("sand", "down", false) then
1749+
1750
	if R.height < 3 then 						--1-3 layers only
1751
		if R.height == 1 then 					--one layer only
1752
			lib.singleLayer(R)
1753
		elseif R.height == 2 then 				--2 layers only current + dig up/down
1754
			lib.doubleLayer(R)
1755
		end
1756
	else -- 3 or more levels
1757
		height = height + utils.move(R, 1)							-- move up/down 1 block for first layer
1758
		while remaining >= 3 do -- min 3 levels
1759
			lib.tripleLayer(R)
1760
			remaining = remaining - 3
1761
			if remaining == 0 then				-- all finished
1762
				break
1763
			elseif remaining == 1 then
1764
				height = height + utils.move(R, 2)					-- move up/down 2 blocks
1765
				lib.singleLayer(R)
1766
			elseif remaining == 2 then
1767
				height = height + utils.move(R, 2)					-- move up/down 2 blocks
1768
				lib.doubleLayer(R)
1769
			else
1770
				height = height + utils.move(R, 3)					-- move up/down 3 blocks
1771
				if remaining == 3 then
1772
					finish = true
1773
				else
1774
					--height = height + 3
1775
				end
1776
			end
1777
		end
1778
	end
1779
	
1780
	if height > 1 then
1781
		utils.move(R, height - 1, true) -- reverse direction
1782
	end
1783
	
1784
	return {}
1785
end
1786
1787
local function clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- 19
1788
	local lib = {}
1789
	
1790
	function lib.checkCobweb(directions, inInventory)
1791
		assert(type(directions) == "table", "directions must be a table eg {'up','down'}")
1792
		for _, direction in ipairs(directions) do
1793
			local blockType = T:getBlockType(direction)
1794
			if inInventory == "minecraft:diamond_sword" then -- using a sword
1795
				local side = "left"
1796
				
1797
				if blockType:find("cobweb") ~= nil then
1798
					--clsTurtle.equip(self, side, useItem, useDamage)
1799
					if equippedRight == "minecraft:diamond_pickaxe" then
1800
						side = "right"
1801
					end
1802
					T:equip(side, "minecraft:diamond_sword")
1803
					T:dig(direction)
1804
					T:equip(side, "minecraft:diamond_pickaxe")
1805
				elseif blockType ~= "" then
1806
					T:dig(direction)
1807
				end
1808
			else
1809
				T:dig(direction)
1810
			end
1811
		end
1812
	end
1813
1814
	-- check position by rotating until facing away from wall
1815
	length = 0
1816
	torch = 0
1817
	turns = 0
1818
	while not turtle.detect() do
1819
		T:turnRight(1)
1820
		turns = turns + 1
1821
		if turns > 4 then
1822
			return {"I am not facing a wall. Unable to continue"}
1823
		end
1824
	end
1825
	T:turnRight(2)
1826
	-- move forward until obstructed, digging up/down. place torches
1827
	while not turtle.detect() do
1828
		lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
1829
		length = length + 1
1830
		torch = torch + 1
1831
		if torch == R.torchInterval then
1832
			torch = 0
1833
			T:place("minecraft:torch", -1, "down", false) ---(self, blockType, damageNo, direction, leaveExisting, signText)
1834
		end
1835
		lib.checkCobweb({"forward"}, inInventory) -- dig cobweb or any other block in front
1836
		T:forward(1)
1837
	end
1838
	-- turn right, forward, right, return to start with up/down dig
1839
	T:go("R1")
1840
	lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
1841
	T:go("F1R1")
1842
	for i = 1, length, 1 do
1843
		lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
1844
		T:forward(1)
1845
	end
1846
	-- move to other wall and repeat.
1847
	T:go("R1")
1848
	lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
1849
	T:go("F1")
1850
	lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
1851
	T:go("F1R1")
1852
	lib.checkCobweb({"up","down"}, inInventory) -- dig cobweb or any other block up/down
1853
	for i = 1, length, 1 do
1854
		lib.checkCobweb({"up", "down", "forward"}, inInventory) -- dig cobweb or any other block up/down/forward
1855
		T:forward(1)
1856
	end
1857
	lib.checkCobweb({"up", "down"}, inInventory) -- dig cobweb or any other block up/down/forward
1858
	
1859
	return {}
1860
end
1861
1862
local function clearMonumentLayer(R) -- 85
1863
	R.up = true
1864
	R.down = true
1865
	R.silent = true
1866
	if R.subChoice == 0 then
1867
		R.up = false
1868
		R.down = false
1869
	end
1870
	-- send turtle down until it hits bottom
1871
	-- then clear rectangle of given size
1872
	-- start above water, usually on cobble scaffold above monument
1873
	if T:detect("down") then -- in case not over wall
1874
		T:forward(1)
1875
	end
1876
	local height = 1
1877
	-- go down until solid block detected
1878
	while utils.clearVegetation("down") do
1879
		T:down(1)
1880
		height = height + 1
1881
	end
1882
	T:down(1)
1883
	height = height + 1
1884
	clearRectangle(R)
1885-
	local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:bucket")
1885+
1886
	
1887
	return {}
1888
end
1889
1890
local function clearWaterPlants(R) -- 87
1891
	local lib = {}
1892
	
1893
	function lib.getLength()
1894
		local length = 1
1895
		print("Checking water length")
1896
		while utils.clearVegetation("forward") do
1897
			T:forward(1)
1898
			length = length + 1
1899
		end
1900
		for i = 1, length do
1901
			turtle.back()
1902
		end
1903
		return length
1904
	end
1905
	
1906
	function lib.clearDown(D)
1907
		while utils.clearVegetation("down") do --clears any grass or sea plants, returns true if air or water, bubble column or ice
1908
			T:down(1)
1909
			D.depth = D.depth + 1
1910-
function utils.getSlotCapacity(slot)
1910+
1911-
	return turtle.getItemSpace(slot) + turtle.getItemCount(slot)
1911+
1912
		D.blockType = T:getBlockType("down")
1913
		if D.blockType:find("slab") ~= nil then
1914
			T:go("C2")
1915
		end
1916
		if D.depth > D.maxDepth then
1917
			D.maxDepth = D.depth
1918
		end
1919
		
1920
		return D
1921
	end
1922
	
1923
	function lib.clearLength(D)
1924
		local moves = 0
1925
		local blockHeight = 1
1926
		D.floorLength = 0 -- reset
1927
		while moves < D.length - 1 do
1928
			if utils.clearVegetation("forward") then
1929
				T:forward(1)
1930-
	-- lastSlot, leastModifier, total, slotData  = T:getItemSlot(item)
1930+
1931-
	local lastSlot, leastModifier, total, slotData = T:getItemSlot("minecraft:water_bucket")
1931+
1932
					if not D.monumentArchesClear then
1933
						D = lib.checkArches(D)
1934
					end
1935
				end
1936
				local temp = D.depth
1937
				D = lib.clearDown(D) -- go down if in water/air
1938
				if blockHeight == 4 and D.depth - temp == 3 then -- could be just gone over 3 block high column in ocean monument
1939
					if not D.monumentTopClear then
1940
						D = lib.checkTop(D)
1941
					end
1942
					blockHeight = 1
1943
				end
1944
				if D.useBlockType == "prismarine" then
1945
					if D.blockType:find("prismarine") == nil then
1946
						-- on monument floor so restrict forward movement to 8 blocks
1947
						D.floorLength = D.floorLength + 1
1948
						if D.floorLength == 8 then
1949
							D.blockType = T:getBlockType("forward")
1950
							while D.blockType:find("prismarine") == nil do
1951
								T:up(1)
1952
								D.blockType = T:getBlockType("forward")
1953
							end
1954
							D.floorLength = 0
1955
						end
1956
					end
1957
				end
1958
				if moves >= D.length - 1 then
1959
					D.width = D.width + 1	-- another length completed so increase width
1960
					return D
1961
				end
1962
			else -- block in front
1963
				blockHeight = 1
1964
				local waterAbove = utils.clearVegetation("up")
1965
				local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
1966
				while not waterAhead do 	-- solid block in front
1967
					if waterAbove then 		-- move up
1968
						T:up(1)
1969
						D.depth = D.depth - 1
1970
						blockHeight = blockHeight + 1
1971
						if D.depth < 1 then
1972
							D.width = D.width + 1	-- another length completed so increase width
1973
							return D
1974
						end
1975
					else 					-- block above so go back
1976
						while not waterAbove do
1977
							utils.goBack()	--  returns true if no object behind, but moves anyway
1978
							waterAbove = utils.clearVegetation("up")
1979
							moves = moves - 1
1980
							if moves == 0 then
1981-
function utils.isStorage(direction)
1981+
1982-
	local blockType = T:getBlockType(direction)
1982+
1983-
	if blockType:find("barrel") ~= nil then
1983+
1984-
		return true, "barrel"
1984+
1985-
	elseif blockType:find("chest") ~= nil then
1985+
1986-
		return true, "chest"
1986+
1987-
	elseif blockType:find("modem") ~= nil then
1987+
1988-
		return true, "modem"
1988+
1989
						end
1990
						-- go up 1 to prevent loop
1991-
	return false, blockType
1991+
1992
						D.depth = D.depth - 1
1993
					end
1994-
function utils.isTableEmpty(aTable)
1994+
1995-
	if next(aTable) == nil then
1995+
1996
				end
1997
			end
1998-
	return false
1998+
1999
		D.width = D.width + 1	-- another length completed so increase width
2000
		D.maxDepth = D.maxDepth + 1 -- +1 to allow for starting pos in top layer
2001
		
2002-
	if blocks == 0 then return 0 end
2002+
2003
	end
2004
	
2005
	function lib.checkArches(D)
2006
		-- gone under a block so could be monument arch (6)
2007-
		--if R.subChoice == 2 then -- reverse direction
2007+
2008-
		if R.direction == "down" or R.subChoice == 2 then -- reverse direction
2008+
2009
			T:go("B1U2F1R1")
2010
			if T:getBlockType("forward"):find("prismarine") ~= nil then -- correct guess
2011
				direction = "R"
2012
			else	-- wrong direction. turn round and check other side
2013
				T:go("R2")
2014
				if T:getBlockType("forward"):find("prismarine") ~= nil then
2015-
		--if R.subChoice == 1 then
2015+
2016-
		if R.direction == "up" or R.subChoice == 1 then
2016+
2017
			end
2018
			local path = "U1F1 U1F3 D1F1 D1R2 U2F5 D2"
2019
			--for i = 1, 6 do
2020
			T:go(path) -- clears arch top 1 and returns
2021
			T:go(direction.."1F6"..direction.."1")
2022
			T:go(path) -- clears arch top 2 and returns
2023
			T:go(direction.."1F6"..direction.."1")
2024
			T:go(path) -- clears arch top 3 and returns
2025-
function utils.printR(R)
2025+
2026
			T:go(path) -- clears arch top 4 and returns
2027-
		choice = 0,
2027+
2028-
		subChoice = 0,
2028+
2029-
		size = 0,
2029+
2030-
		width = 0,
2030+
2031-
		length = 0,
2031+
2032-
		height = 0,
2032+
2033-
		depth = 0,
2033+
2034-
		up = false,
2034+
2035-
		down = false,
2035+
2036-
		silent = false,
2036+
2037-
		data = {},
2037+
2038-
		torchInterval = 0,
2038+
2039-
		useBlockType = "",
2039+
2040-
		auto = false,
2040+
2041-
		side = "",
2041+
2042-
		direction = "",
2042+
2043-
		ready = false,
2043+
2044-
		networkFarm = false,
2044+
2045-
		mysticalAgriculture = false,
2045+
2046-
		logType = "",
2046+
2047-
		treeSize = "",
2047+
2048-
		message = ""
2048+
2049
				end
2050
			end
2051-
	print("choice= ".. tostring(R.choice)..", subChoice= ".. tostring(R.subChoice))
2051+
2052-
	print("size= ".. tostring(R.size)..", width= ".. tostring(R.width))
2052+
2053-
	print("length= ".. tostring(R.length)..", height= ".. tostring(R.height)..", depth= ".. tostring(R.depth))
2053+
2054-
	print("silent= "..tostring(R.silent)..", up= ".. tostring(R.up)..", down= "..tostring(R.down))
2054+
2055-
	print("torchInterval= ".. tostring(R.torchInterval))
2055+
2056-
	print("useBlockType= "..tostring(R.useBlockType))
2056+
2057-
	print("auto= ".. tostring(R.auto)..", side= "..tostring(R.side)..", direction= "..tostring(R.direction))
2057+
2058-
	print("ready= ".. tostring(R.ready)..", networkFarm= "..tostring(R.networkFarm)..", mysticalAgriculture= "..tostring(R.mysticalAgriculture))
2058+
2059-
	print("logType= ".. tostring(R.logType)..", treeSize= "..tostring(R.treeSize)..", message= "..tostring(R.message))
2059+
2060-
	if type(R.data) == "table" then
2060+
2061-
		io.write("data= ")
2061+
2062-
		for k,v in pairs(R.data) do
2062+
2063-
			print(k ..": "..tostring(v))
2063+
2064
		repeat
2065
			if utils.clearVegetation("forward") then
2066-
		print("data= ".. tostring(R.data))
2066+
2067
				D = lib.clearDown(D) -- go down if in water/air, D.blockType is updated with floor type
2068-
	io.write("Enter to continue")
2068+
2069
				local waterAbove = utils.clearVegetation("up")
2070
				local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
2071
				while not waterAhead do 	-- solid block in front
2072
					if waterAbove then 		-- move up
2073
						T:up(1)
2074
					else 					-- block above so go back
2075
						while not waterAbove do
2076
							utils.goBack()	--  returns true if no object behind, but moves anyway
2077
							waterAbove = utils.clearVegetation("up")
2078
						end
2079
					end
2080
					waterAbove = utils.clearVegetation("up")
2081
					waterAhead = utils.clearVegetation("forward")
2082
				end
2083
			end
2084
		until D.blockType:find(D.useBlockType) == nil
2085
		-- now above a non-prismarine block, facing away from monument
2086
		T:turnRight(2) -- facing monument
2087
		D.blockType = T:getBlockType("forward")
2088
		while D.blockType:find(D.useBlockType) ~= nil do
2089
			T:up(1)
2090
			D.blockType = T:getBlockType("forward")
2091
		end
2092
		T:go("F1L1")
2093
		D.blockType = T:getBlockType("down")
2094
		while D.blockType:find(D.useBlockType) ~= nil do
2095
			T:forward(1)
2096
			D.blockType = T:getBlockType("down")
2097
		end
2098
		turtle.back()
2099
		-- should now be at end of monument base
2100-
function utils.tableContains(tableName, value, exactMatch)
2100+
2101-
	exactMatch = exactMatch or false
2101+
2102-
	for k, v in ipairs(tableName) do
2102+
2103-
		if exactMatch then
2103+
2104-
			if v == value then
2104+
2105
			direction = "L"
2106
		end
2107
		T:go(direction.. 1)
2108-
			if v:find(value) ~= nil then
2108+
2109
			T:forward(1)
2110
			--D.depth = D.depth + lib.clearDown(depth)
2111
			D = lib.clearDown(D)
2112
		else
2113-
	return false
2113+
2114
				T:up(1)
2115
				D.depth = D.depth - 1
2116-
function utils.useSticksAsFuel()
2116+
2117-
	local slot = T:getItemSlot("minecraft:stick") 
2117+
2118-
	if slot > 0 then -- use any sticks to refuel
2118+
2119-
		turtle.select(slot)
2119+
2120-
		turtle.refuel()
2120+
2121
		
2122-
	slot = T:getItemSlot("minecraft:mangrove_roots") 
2122+
2123-
	if slot > 0 then -- use any roots to refuel
2123+
2124-
		turtle.select(slot)
2124+
2125-
		turtle.refuel()
2125+
2126
	D.depth = 0
2127
	D.maxDepth = 0
2128
	D.blockType = ""
2129-
function utils.waitForInput(message)
2129+
2130-
	-- debugging. Pause script and asks user to continue
2130+
2131-
	-- global dbug flag has to be set first
2131+
2132-
	if dbug then 
2132+
2133-
		if message ~= nil then
2133+
2134-
			print(message)
2134+
2135-
			T:saveToLog(message, false)
2135+
2136
	D.onWater = false
2137-
		menu.colourPrint("Enter to continue...", colors.lightBlue)
2137+
2138-
		--io.write("Press Enter to continue...")
2138+
2139-
		return read()
2139+
2140
	if R.data == "clearWaterPlants" then -- NOT monument corner discovery
2141
		D.inWater, D.onWater = utils.startWaterFunction(D.onWater, D.inWater, 2, true) -- move into water
2142
		if R.length == 0 then
2143-
function utils.writeTraceTable(description, tbl)
2143+
2144-
	local text = ""
2144+
2145-
	for key, value in pairs(tbl) do
2145+
2146-
		if type(value) == "table" then
2146+
2147-
			for k,v in pairs(value) do
2147+
2148-
				text = text.."k = "..k..", v = "..v.."; "
2148+
2149
		end
2150
	end
2151-
			text = "key = "..key..", value = "..value
2151+
2152
	D = lib.clearDown(D) -- go down to floor, set depth, maxDepth, blockType
2153
	if R.data == "clearWaterPlants" then -- NOT monument corner discovery
2154-
	T:saveToLog(description.."\n".. text)
2154+
2155
			print("Single row clearing")
2156
			D = lib.clearLength(D) --D.width also increased
2157
		else
2158
			while D.width < R.width do -- D.width starts at 0
2159
				-- now on floor, move along sea/river bed following contour
2160
				D = lib.clearLength(D) --D.width also increased
2161
				-- now turn and repeat
2162
				if D.width < R.width then	
2163
					D = lib.turn(D)
2164
					if D.depth <= 0 then
2165
						break
2166
					end
2167
				end
2168
			end
2169
		end
2170
		-- finished so return to surface
2171
		T:up(1) -- up 1 to check for water below
2172
		while T:getBlockType("down"):find("water") ~= nil do
2173
			T:up(1)
2174
		end
2175
		T:down(2) -- return to surface
2176
		--[[while utils.clearVegetation("forward") do
2177
			T:forward(1)
2178
		end]]
2179
	elseif R.data == "oceanMonumentColumns" then -- monument corner discovery
2180
		-- this function used to find edge of monument base
2181
		if D.blockType:find(D.useBlockType) ~= nil then
2182
			lib.findBlockTypeEnd(D)
2183
			return {""}
2184
		else
2185
			T:up(D.depth)
2186
			return {"Prismarine not found on ocean floor"}
2187
		end
2188
	end
2189
	if R.silent then
2190
		return {D.maxDepth, R.length}
2191
	else
2192
		return {""}
2193
	end
2194
end
2195
2196
local function clearMountainSide(R) -- 78
2197
	--[[
2198
	First row              outward  l  s  f  mid    (length, start, finish, midPoint)
2199
2200
	      >|*|*|           true                     lib.clearRow() moves: 7-5=2, midPoint starts at 2 
2201
	      +|*|*|
2202
	      +|*|*|
2203
	      ^|*|*|        <  false    7  5  6  2      lib.clearRow() moves: 9-2=7, midPoint starts at -4 -1 = -5
2204
	       |*|*|*|	    +
2205
	     |*|*|*|*|*|    +
2206
	  >  |*|*|*|*|*|    ^  true     9  2  6  -4     lib.getStartingLength(). Ends 1 block after block finish
2207
	  ^|*|*|*|*|*|*|*|*|                            starts here, moves up 1
2208
	    1 2 3 4 5 6 7 8                             block index
2209
		 
2210
	Second row                outward l  s  f  mid
2211
	             <            false
2212
                 +
2213
          |*|*|  +
2214
	   >|*|*|*|*|^            true
2215
	   +|*|*|*|*|
2216
	   +|*|*|*|*|
2217
	   ^|*|*|*|*|          <  false   6  5  6  2
2218
	    |*|*|*|*|*|*|      +
2219
	  |*|*|*|*|*|*|*|*|    +
2220
	  |*|*|*|>|*|*|*|*|    ^  true    7+5   5 -7    lib.getHalf(R); goBack(7) 
2221
	|*|*|*|*|*|*|*|*|*|*|*|                           starts at midPoint of previous row eg block 4
2222
	 0 1 2 3 4 5 6 7 8 9 10
2223
	]]
2224
	
2225
	-- variables declared before lib for them to be used within lib as is then in scope
2226
	local turn = "R"
2227
	local oTurn = "L"
2228
	if R.subChoice == 1 then 	-- remove left side
2229
		turn = "L"
2230
		oTurn = "R"
2231
	end
2232
	local outward = true		-- direction flag
2233
	
2234
	local lib = {}
2235
	
2236
	function lib.isAnyAbove(above)
2237
		T:saveToLog("lib.isAnyAbove: "..utils.tableConcat(above, ", "), false)
2238
		for k,v in ipairs(above) do
2239
			if v then
2240
				T:saveToLog("lib.isAnyAbove Found: "..k , false)
2241
				return true
2242
			end
2243
		end
2244
		return false
2245
	end
2246
		
2247
	function lib.clearLevel(R, above)	-- eg 9, 2, 6, -4 from lib.getStartingLength OR 7, 5, 6, 3 from previous
2248
		-- clearLevel always follows either lib.getStartingLength or a previous lib.clearLevel
2249
		-- midPoint should be adjusted as turtle moves to reflect current row length
2250
		if #above == 0 then return above, 1 end
2251
		--local index = 0
2252
		local minMoves = math.floor(#above / 2)
2253
		local up, forward, down = lib.getDetect()
2254
		if outward then										-- follow table indexes
2255
			for x = 1, minMoves do							-- clear first half
2256
				above[x] = up								-- reset this with new value
2257
				T:go("x0x2F1")								-- clear and move forward
2258
				up, forward, down = lib.getDetect()
2259
				--index = index + 1
2260
			end
2261
			for x = minMoves + 1, #above do					-- check remaing half and clear
2262
				T:go("x0x2")								-- clear above / below
2263
				if above[x] then							-- is a block recorded as present?(now below)
2264
					above[x] = up							-- reset this with new value
2265
					T:forward(1)							-- move forward
2266
					up, forward, down = lib.getDetect()
2267
					--index = index + 1
2268
				else
2269
					break
2270
				end
2271
			end
2272
		else												-- iterate table in reverse
2273
			--index = #above
2274
			for x = #above, minMoves, -1 do					-- clear first half
2275
				above[x] = up								-- reset this with new value
2276
				T:go("x0x2F1")								-- clear and move forward
2277
				up, forward, down = lib.getDetect()
2278
				--index = index - 1
2279
			end
2280
			for x = minMoves - 1, 1, -1 do					-- check remaing half and clear
2281
				T:go("x0x2")								-- clear up / down
2282
				if above[x] then							-- is a block recorded as present?(now below)
2283
					above[x] = up							-- reset this with new value
2284
					T:forward(1)							-- move forward
2285
					up, forward, down = lib.getDetect()
2286
					--index = index - 1
2287
				else
2288
					break
2289
				end
2290
			end
2291
		end
2292
		T:go("x0x2 F1R2 x0x2 F1")							-- face opposite direction, delete blocks above and below
2293
		outward = not outward								-- switch direction flag
2294
		return above										-- eg {false, true, true, true, false}
2295
	end
2296
	
2297
	function lib.getDetect()
2298
		return turtle.detectUp(),  turtle.detect(),  turtle.detectDown()
2299
	end
2300
	
2301
	function lib.getStartingLength(R)
2302
		--[[
2303
			length of column by excavating blocks above, ahead or below
2304
			Rotate 180 at end of run ready to return
2305-
				T:place("stairs", "up")
2305+
2306
		]]
2307
		local above = {}									-- empty table of boolean values
2308
		local length = 0									-- used as counter							
2309
		T:forward(1)										-- start check 1 block ahead
2310
		local up, forward, down = lib.getDetect() 			-- check if anything around current block
2311
		if up or forward or down then						-- block found nearby: continue
2312
			while up or forward or down do					-- while blocks ahead / up / down move forward
2313
				table.insert(above, up)
2314
				T:go("x0x2F1")
2315
				up, forward, down = lib.getDetect() 		-- check if anything around current block
2316
				length = length + 1
2317
				if length >= R.length then					-- check if going out of range
2318
					T:saveToLog("lib.getStartingLength(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
2319
					break
2320
				end
2321
			end
2322
			T:go("R2x0x2")									-- Rotate 180 and clear blocks above/below
2323
		else												-- no blocks nearby: exit
2324
			T:go("R2F1")									-- return to start position rotated 180
2325
		end
2326
		outward = not outward
2327
2328
		return above 										-- above = {false, true, true, true, true, false, false}
2329
	end
2330
	
2331
	function lib.firstRow(R)
2332
		local height = 1									-- starts at ground level, but forced up 1
2333
		T:up(1)
2334
		local above = lib.getStartingLength(R)				-- clear the ground level and 1 above eg 9, 2, 5, 4
2335
		if T:saveToLog("startLength: "..#above, true) then
2336
			T:saveToLog(utils.tableConcat(above, ", "), false)
2337
			if dbug then read() end
2338
		end													-- at end of first row as already turned 180, outward set to false in getStartingLength
2339
		while lib.isAnyAbove(above) do
2340
			T:go("U3")	-- go up 3
2341
			height = height + 3
2342
			above = lib.clearLevel(R, above)	-- returns start and finish of blocks above, rotates 180
2343
			if T:saveToLog("checking level: "..height, true) then
2344
				T:saveToLog(utils.tableConcat(above, ", "), false)
2345
				if dbug then read() end
2346
			end
2347
		end													-- first row all levels completed. 
2348
		T:down(height)										-- now on ground + 1, facing last column cleared.
2349
		
2350
		return above
2351
	end
2352
		
2353
	function lib.deepCopy(tbl)
2354
		local copy = {}
2355
		for key, value in ipairs(tbl) do
2356
			table.insert(copy, value)
2357
		end
2358
		return copy
2359
	end
2360
   
2361
	function lib.getHalf(R, above)
2362
		-- already 1 block above ground
2363
		local maxLength = R.length
2364
		local temp = {}
2365
		local retValue = {}
2366
		if #above > 0 then								-- not empty table, so must be second half
2367
			temp = lib.deepCopy(above)					-- copy existing table
2368
			above = {}									-- initialise above
2369
		end
2370
		local up, forward, down = lib.getDetect()
2371
		
2372
		while up or forward or down do					-- while blocks ahead / up / down move forward
2373
			T:go("x0x2F1")
2374
			table.insert(above, up)
2375
			up, forward, down = lib.getDetect() 		-- check if anything around current block
2376
			
2377
			if #above >= math.floor(maxLength / 2) then	-- check if going out of range
2378
				T:saveToLog("lib.getHalf(R) : outward = "..tostring(outward).." MaxLength "..maxLength.." reached", false)
2379
				T:go("x0x2")
2380
				break
2381
			end
2382
		end
2383
		T:turnRight(2)									-- ready for next half or return
2384
		outward = not outward
2385
		if #temp > 0 then								-- completing a second half measurement
2386
			for i = #above, 1, -1 do
2387
				table.insert(retValue, above[i])		-- combine 2 tables into 1
2388
			end
2389
			for i = 1, #temp do
2390
				table.insert(retValue, temp[i])
2391
			end
2392
		else
2393
			retValue = above
2394
		end
2395
		return retValue
2396
	end
2397
	
2398
	function lib.nextRow(R)
2399-
			T:place("slab", "forward")
2399+
2400
		T:saveToLog("lib.nextRow(R)", false)
2401
		T:up(1)
2402
		local pattern = turn.."1F1"..turn.."1"
2403
		if not outward then
2404
			pattern = oTurn.."1F1"..oTurn.."1"
2405
		end
2406
		T:go(pattern)
2407
		T:saveToLog("    T:go("..pattern..")", false)
2408
		outward = not outward -- reverse direction flag
2409
		-- now in next vertical row
2410
		local above = lib.getHalf(R, {})
2411
		local index = 0
2412
		if T:saveToLog("\t  first half Length: "..#above.." Enter", true) then 
2413
			T:saveToLog(utils.tableConcat(above, ", "), false)
2414
			if dbug then read() end
2415
		end
2416
		lib.returnToMidPoint(#above)					-- return to starting point
2417
		T:forward(1)		
2418
		above = lib.getHalf(R, above)					-- returns length - 1 eg 5, 4
2419
		if T:saveToLog("\t  total length: "..#above.." Enter", true) then
2420
			T:saveToLog(utils.tableConcat(above, ", "), false)
2421
			if dbug then read() end
2422
		end
2423
		
2424-
					T:place("stairs", "up")
2424+
2425
			T:go("U3")				-- go up 3
2426
			height = height + 3		-- increment height
2427
			T:saveToLog("\tClear height loop: height = "..height, false)
2428
			above = lib.clearLevel(R, above)	-- returns start and finish of blocks above
2429
		end
2430
		T:down(height)	-- now on ground + 1
2431
		lib.returnToMidPoint(above)
2432
	end
2433
	
2434
	function lib.returnToMidPoint(above)
2435
		--[[ value can be integer or table]]
2436
		if type(above) == "table" then
2437
			T:saveToLog("lib.returnToMidPoint("..#above..")", false)
2438
			if #above > 0 then
2439
				local midPoint = math.floor(#above / 2)
2440
				if #above % 2 == 1 and  not outward then -- length is odd no
2441
					midPoint = math.ceil(#above / 2)
2442
					T:saveToLog("    midPoint adjusted "..midPoint..")", false)
2443
				end
2444
				T:saveToLog("    T:forward("..midPoint..")", false)
2445
				T:forward(midPoint)
2446
			end
2447
		else
2448
			T:saveToLog("lib.returnToMidPoint("..above..")", false)
2449
			if above > 0 then
2450-
				T:place("slab", "forward")
2450+
2451
				T:forward(above)
2452
			end
2453-
			T:place("slab", "forward")
2453+
2454
		-- now back at starting point
2455-
			T:place("slab", "forward")
2455+
2456
	
2457
	-- Start here
2458
	-- if "tk log d.." typed instead of "tk" will start logfile and display comments. read() will be activated for debugging
2459
	T:saveToLog("Starting function clearMountainSide", false)
2460
	local above = lib.firstRow(R) 			-- outward depends on height eg 1-2 = false, 3-5 = true, 6-8 = false
2461
	lib.returnToMidPoint(above)				-- return to mid first row of blocks
2462
	for row = 1, R.width -1 do
2463
		lib.nextRow(R)
2464
	end
2465
	
2466
	return {}
2467
end
2468
2469
local function clearSandWall(R) -- 81
2470
	--dig down while on top of sand/red_sand/soul_sand
2471
	local lib = {}
2472
	
2473
	function lib.checkAbove(height)
2474
		if turtle.detectUp() then -- moved under a ledge
2475
			T:go("B1U1")
2476
			height = height - 1
2477
		end
2478
		return height
2479
	end
2480
	
2481
	function lib.moveDown(height)
2482
		blockType = T:getBlockType("down")
2483
		while blockType:find("sand") ~= nil do
2484
			T:down(1)
2485
			height = height + 1
2486
			blockType = T:getBlockType("down")
2487
		end
2488
		return height
2489
	end
2490
	
2491
	function lib.moveForward(length)
2492
		lib.digForward()
2493
		T:forward(1)
2494
		length = length + 1
2495
		local blockType = T:getBlockType("forward")
2496
		return length, blockType
2497
	end
2498
	
2499
	function lib.digForward()
2500
		while T:dig("forward") do
2501
			while T:suck("forward") do end
2502
			while T:suck("up") do end
2503
		end
2504
	end
2505
	
2506
	local moves  = 0
2507
	local height = 0
2508
	local length = 0
2509
	local search = 0
2510
	local reverse = false
2511
	local blockType = T:getBlockType("down")
2512
	if R.length == 0 then
2513
		R.length = 64
2514
	end
2515
	
2516
	print("Checking for sand below")
2517
	while blockType:find("sand") == nil do --move forward until sand detected or 3 moves
2518
		T:forward(1)
2519
		search = search + 1
2520
		blockType = T:getBlockType("down")
2521
		if search > 3 then
2522
			T:go("B"..search)
2523
			return {"Unable to locate sand"}
2524
		end
2525
	end
2526-
					T:place(sapling, "down")
2526+
2527
	height = lib.moveDown(height)	-- go down if sand below
2528
	-- repeat until height == 0
2529
	repeat -- starts at bottom of sand wall
2530
		blockType = T:getBlockType("forward")
2531-
				if not T:place(sapling, "down") then
2531+
2532-
					T:place("sapling", "down")
2532+
2533
			if blockType == "" or  blockType:find("sand") ~= nil then -- sand or nothing in front
2534
				height = lib.moveDown(height)	-- go down if sand below
2535
			end
2536-
			if not T:place(sapling, "down") then
2536+
2537-
				T:place("sapling", "down")
2537+
2538
				blockType = T:getBlockType("down")
2539
				if blockType:find("sand") ~= nil then -- sand below
2540
					T:dig("down")
2541
				end
2542
				T:up(1)
2543
				height = height - 1
2544
			else -- air/water in front so move forward
2545
				if length < 60 then -- in case missing wall and in open ocean
2546
					length, blockType = lib.moveForward(length) -- move forward 1 and dig sand
2547
					height = lib.checkAbove(height)
2548
				else -- already > monument length of 56
2549
					T:up(1)
2550
					height = height - 1
2551
				end
2552
			end
2553
		end
2554
	until height == 0 or length == R.length
2555
	blockType = T:getBlockType("down")
2556
	if blockType:find("sand") ~= nil then -- sand below
2557
		T:dig("down")
2558
	end
2559
	if height > 0 then -- finished as length ran out
2560
		T:up(height)
2561
	end
2562
	-- stay at end of cleared wall unless user chose to return
2563
	if R.data == "return" then
2564
		T:go("R2F"..length.."R2")
2565
	end
2566
	
2567
	return {}
2568
end
2569
2570
local function clearSolid(R) -- 76
2571
	--[[ direction = R.subChoice = 1 up or 2 down ]]
2572
	local height = 1
2573
	local remaining = R.height 
2574
	local lib = {}
2575
	
2576
	function lib.singleLayer(R)
2577
		R.up = false
2578
		R.down = false
2579
		clearRectangle(R)
2580
	end
2581
	
2582
	function lib.doubleLayer(R)
2583
		R.up = false
2584
		R.down = false
2585
		if R.subChoice == 1 then
2586
			R.up = true
2587
		else
2588
			R.down = true
2589
		end
2590
		clearRectangle(R)
2591
	end
2592
		
2593
	function lib.tripleLayer(R)
2594
		-- turtle in centre layer
2595
		R.up = true
2596
		R.down = true
2597
		clearRectangle(R)
2598
	end
2599
2600
	R.silent = true
2601
	if R.height < 3 then 							--1-3 layers only
2602
		if R.height == 1 then 						--one layer only
2603
			lib.singleLayer(R)
2604
		elseif R.height == 2 then 					--2 layers only current + dig up/down
2605
			lib.doubleLayer(R)
2606
		end
2607
	else -- 3 or more levels
2608
		height = height + utils.move(R, 1)			-- move up/down 1 block for first layer
2609
		while remaining >= 3 do 					-- min 3 levels
2610
			lib.tripleLayer(R)
2611
			remaining = remaining - 3
2612
			if remaining == 0 then					-- all finished
2613
				break
2614
			elseif remaining == 1 then
2615
				height = height + utils.move(R, 2)	-- move up/down 2 blocks
2616
				lib.singleLayer(R)
2617
			elseif remaining == 2 then
2618
				height = height + utils.move(R, 2)	-- move up/down 2 blocks
2619
				lib.doubleLayer(R)
2620
			else
2621
				height = height + utils.move(R, 3)	-- move up/down 3 blocks
2622
				if remaining == 3 then
2623
					finish = true
2624
				end
2625
			end
2626
		end
2627
	end
2628
	
2629
	if height > 1 then
2630
		utils.move(R, height - 1, true) -- reverse direction
2631
	end
2632
	
2633
	return {}
2634
end
2635
2636
local function clearSandCube(R) -- 81
2637
	R.data = ""
2638
	for w = 1, R.width do
2639
		clearSandWall(R)
2640
		if w < R.width then
2641
			if w % 2 == 1 then
2642
				T:go("R1F1R1")
2643
			else
2644
				T:go("L1F1L1")
2645
			end
2646
		end
2647
	end
2648
	
2649
	return {}
2650
end
2651
2652
local function clearWall(R) -- 73
2653
	local lib = {}
2654
	
2655
	function lib.move(direction, blocks, reverse)
2656
		--[[ Move up or down by blocks count ]]
2657
		if reverse == nil then
2658
			reverse = false
2659
		end
2660
		if reverse then
2661
			if direction == "down" then -- reverse direction
2662
				T:up(blocks)
2663
			else
2664
				T:down(blocks)
2665
			end
2666
		else
2667
			if direction == "up" then
2668
				T:up(blocks)
2669
			else
2670
				T:down(blocks)
2671
			end
2672
		end
2673
		return blocks
2674
	end
2675
	
2676
	function lib.singleLayer(length)
2677
		T:go("F"..length - 1)
2678
	end
2679
	
2680
	function lib.doubleLayer(modifier, length)
2681
		for i = 1, length do
2682
			if i < length then
2683
				T:go("x"..modifier.."F1")
2684
			else
2685
				T:go("x"..modifier)
2686
			end
2687
		end
2688
	end
2689
	
2690
	function lib.tripleLayer(direction, length)
2691
		for i = 1, length do
2692
			if i < length then
2693
				T:go("x0x2F1")
2694
			else
2695
				T:go("x0x2")
2696
			end
2697
		end
2698
	end
2699
	
2700
	
2701
	-- R.width preset to 1
2702
	-- R.subChoice = 1 up / 2 down
2703
	if R.height < 3 then
2704
		R.silent = true
2705
	end
2706
	-- dig along and up/down for specified R.length
2707
	local modifier = "0"
2708
	local direction = "U"
2709
	local outbound = true
2710
	local height = 0
2711
	if R.subChoice == 2 then
2712
		 modifier = "2"
2713
		 direction = "D"
2714
	end
2715
	if R.height == 1 then 				-- single block so dig and return
2716
		lib.singleLayer(R.length)
2717
	elseif R.height == 2 then
2718
		lib.doubleLayer(modifier, R.length)
2719
	else								-- 4 blocks or more. start with bulk 3 blocks
2720
		local remaining = R.height
2721
		T:go(direction.."1")			-- up 1 or down 1
2722
		height = 1
2723
		while remaining >= 3 do 
2724
			lib.tripleLayer(direction, R.length)
2725
			remaining = remaining - 3
2726
			
2727
			if remaining == 0 then		-- no more, return home, already in position
2728
				
2729
			elseif remaining == 1 or remaining == 2 then
2730
				T:go(direction.."2")
2731
				height = height + 2
2732
			else
2733
				T:go(direction.."3")
2734
				height = height + 3
2735
				if remaining >= 3 then -- another iteration
2736
					T:go("R2")
2737
					outbound = not outbound
2738
				end
2739
			end
2740
		end
2741
		-- 0, 1 or 2 layers left
2742
		if remaining > 0 then
2743
			T:go("R2")
2744
			outbound = not outbound
2745
			if remaining == 1 then
2746
				lib.singleLayer(R.length)
2747
			elseif remaining == 2 then
2748
				lib.doubleLayer(modifier, R.length)
2749
			end
2750
		end
2751
	end
2752
	if outbound then
2753
		T:go("R2F"..R.length)
2754
	else
2755
		T:forward(1)
2756
	end
2757
	direction = "D" -- reverse direction
2758
	if R.subChoice == 2 then
2759
		 direction = "U"
2760
	end
2761
	if height > 0 then
2762
		T:go(direction..height.."R2")
2763
	else
2764
		T:go("R2")
2765
	end
2766
	return {}
2767
end
2768
2769
local function convertWater(R) -- 88
2770
	--[[
2771
	if dry need enough buckets to place along (width + length - 1) / 2
2772
	use 12 buckets
2773
	start on floor + 1
2774
	place slab down and water up along 2 edges. stay on this level
2775
	return round same 2 edges removing slabs and and placing them 1 above
2776
	placeUp water onto slabs on both edges
2777
	repeat recover slabs, place 1 above , placeUp water
2778
	
2779
	for sloping water, place full area with slabs
2780
	place sloping water on top of slabs
2781
	remove slabs
2782-
					T:place("minecraft:dirt", "down", true)
2782+
2783
	]]
2784
	local lib = {}
2785
	
2786
	function lib.checkStartPosition()
2787
		--[[
2788-
							T:place("minecraft:dirt", "down", true)
2788+
2789
		1 W|S|F|F|F|F|F -- sloping flowing water
2790
		2 W|F|F|F|F|F|F -- blocks removed after placing flowing water above
2791
		3 W|S|S|S|S|S|S -- original sources
2792
		4 W|?|?|?|?|?|? -- may be sources
2793
		]]
2794
		-- need to be on floor or R.height if specified
2795
		local depth = 0
2796
		local blockType = T:getBlockType("down")
2797
		local isWaterUp, isSourceUp = T:isWater("up")
2798
		local isWaterForward, isSourceForward = T:isWater("forward")
2799
		local isWaterDown, isSourceDown = T:isWater("down")
2800
		print("Block below is "..blockType)
2801
		print("Water above is "..tostring(isWaterUp))
2802
		print("Water forward is "..tostring(isWaterForward))
2803-
						T:place("minecraft:dirt", "down", true)
2803+
2804
		if blockType:find("water") == nil then -- on at least level 0
2805-
						blockType = T:getBlockType("down")
2805+
2806
			sleep(2)
2807
			T:forward(1)
2808
			blockType = T:getBlockType("down")
2809-
								T:place("minecraft:dirt", "down", true)
2809+
2810
				print("Water found. Going down to floor")
2811
				depth = -1
2812
			else
2813
				T:down(1)
2814
				blockType = T:getBlockType("down")
2815
				if blockType:find("water") ~= nil then
2816
					depth = -2
2817
				else
2818
					return 0, "Not close to water. Aborting..."
2819
				end
2820
			end
2821
		end
2822
		while turtle.down() do
2823
			depth = depth + 1
2824
		end
2825
		local emptyBuckets = utils.getEmptyBucketCount()
2826
		for i = depth, 0, -1 do
2827
			if emptyBuckets > 0 then
2828
				lib.fillBuckets()
2829
				emptyBuckets = utils.getEmptyBucketCount()
2830
			end
2831
			turtle.up()
2832
		end
2833
		
2834
		return depth, ""
2835
	end
2836
	
2837
	function lib.fillBuckets()
2838
		local emptyBuckets = utils.getEmptyBucketCount()
2839
		local direction = "forward"-- start with forward
2840
		local isWater, isSource, isIce = T:isWater(direction)
2841
		if emptyBuckets > 0 then
2842-
			--T:go("x0x2F1x0x2")
2842+
2843-
			turtle.digDown()				-- dig below
2843+
2844-
			while turtle.digUp() do end		-- dig up including gravity blocks
2844+
2845-
			while not turtle.forward() do	-- if no block in front, moves forward
2845+
2846-
				turtle.dig()				-- block in front, so dig it
2846+
2847
					isWater, isSource, isIce = T:isWater(direction)
2848-
			turtle.digDown()				-- now moved forward so dig down again
2848+
2849-
			while turtle.digUp() do end		-- dig up again including gravity blocks
2849+
2850
					end
2851
				end
2852
			end
2853
			if direction == "" then
2854
				print("Unable to locate water source")
2855-
			--T:go("x0F1x0")
2855+
2856-
			while turtle.digUp() do end
2856+
2857-
			while not turtle.forward() do	-- if no block in front, moves forward
2857+
2858-
				turtle.dig()				-- block in front, so dig it
2858+
2859
						sleep(0.3)
2860-
			while turtle.digUp() do end
2860+
2861
						print("Unable to fill bucket ".. i .." / "..emptyBuckets)
2862
					end
2863
				end
2864
			end
2865
		end
2866-
			--T:go("x2F1x2")
2866+
2867-
			turtle.digDown()
2867+
2868-
			while not turtle.forward() do	-- if no block in front, moves forward
2868+
2869-
				turtle.dig()				-- block in front, so dig it
2869+
2870
		for i = 1, length do
2871-
			turtle.digDown()
2871+
			T:place("slab", -1, "down", false)
2872
			if i < length then
2873
				T:forward(1)
2874
			end
2875
		end
2876
	end
2877
	
2878
	function lib.placeSources(length, place)
2879
		local moves = 1
2880
		local waterBuckets = utils.getWaterBucketCount()
2881
		-- place sources alternate positions + start and finish
2882
		while moves < length do
2883
			if place then
2884
				if T:placeWater("up") then
2885
					print("Placed source up")
2886
					waterBuckets = waterBuckets - 1
2887
				end
2888
			end
2889-
		elseif R.down then					-- single block wide trench dig R.down = 2 blocks deep
2889+
2890
			if moves < length then
2891-
		else 								-- single block wide = 1 block deep
2891+
2892
				moves = moves + 1
2893
			end
2894-
		T:turnRight(2)						-- turn at the top of the run
2894+
2895-
		T:forward(R.length - 1)				-- return to start
2895+
2896-
		T:turnRight(2)						-- turn round to original position
2896+
2897-
	else 									-- R.width 2 or more blocks
2897+
2898-
		local iterations = 0 				-- R.width = 2, 4, 6, 8 etc
2898+
				T:place("slab", -1, "down", false)
2899-
		if R.width % 2 == 1 then  			-- R.width = 3, 5, 7, 9 eg R.width 7
2899+
2900-
			iterations = (R.width - 1) / 2 	-- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
2900+
2901
		if T:placeWater("up") then -- end of length
2902
			print("Placed final source up")
2903
		end
2904-
		for i = 1, iterations do 			-- eg 3 blocks wide, iterations = 1
2904+
2905
	end
2906
	
2907
	function lib.moveSlabs(length)
2908
		for i = 1, length do
2909
			T:dig("down")
2910
			T:up(1)
2911
			T:place("slab", -1, "down", true)
2912
			if i < length then
2913
				T:forward(1)
2914
				T:down(1)
2915
			end
2916
		end
2917
	end
2918
	
2919
	function lib.recoverSlabs(length)
2920
		for i = 1, length do
2921
			T:dig("down")
2922
			if i < length then
2923
				T:forward(1)
2924
			end
2925
		end
2926
	end
2927
	
2928
	local depth, message = lib.checkStartPosition()
2929
	if message ~= "" then
2930
		return {message}
2931
	end
2932
	local maxDepth = R.height
2933
	local buckets = utils.getWaterBucketCount()
2934
	R = utils.calculateDimensions(R) -- if R.width or R.length == 0
2935
	T:down(depth)
2936
	lib.placeSlabs(R.length)
2937
	T:go("R1")
2938
	lib.placeSlabs(R.width)
2939
	T:go("R2")
2940
	
2941
	while depth > 0 do
2942
		local place = true
2943
		lib.fillBuckets()
2944
		place = lib.placeSources(R.width, place)
2945
		T:go("L1")
2946
		place = lib.placeSources(R.length, place)
2947
		lib.fillBuckets()
2948
		T:go("R2")
2949
		lib.moveSlabs(R.length) -- dig slab from below, move up and replace below
2950
		T:go("R1F1D1")
2951
		lib.moveSlabs(R.width - 1)
2952
		T:go("R2") -- now moved up 1 layer
2953
		depth = depth - 1
2954
		if depth == 0 then
2955
			place = lib.placeSources(R.width, true)
2956
			T:go("L1")
2957
			place = lib.placeSources(R.length, place)
2958
			T:go("R2")
2959
			lib.recoverSlabs(R.length)
2960
			T:go("R1")
2961
			lib.recoverSlabs(R.width)
2962
		end
2963
	end
2964
	
2965
	return {}
2966
end
2967
2968
local function createBoatLift(R) -- 59 state:0=new, size:1=extend, side:0=left, 1=right
2969
	-- build stepped lift with fencing gates and soul sand
2970
	local lib = {}
2971
	
2972
	function lib.getWater(backToWater, downToWater)
2973
		if backToWater > 0 then
2974
			utils.goBack(backToWater)
2975
		end
2976
		if downToWater > 0 then
2977
			T:down(downToWater)
2978
		end
2979
		T:getWater("down") -- take water from source
2980
		sleep(0.2)
2981
		T:getWater("down") -- take water from source
2982
		if downToWater > 0 then
2983
			T:up(downToWater)
2984
		end
2985
		if backToWater > 0 then
2986
			T:forward(backToWater)
2987
		end
2988
	end
2989
	
2990
	--T:place(blockType, damageNo, direction, leaveExisting, signText)
2991
	
2992
	local backToWater = 0
2993
	local downToWater = 0
2994
	
2995
	T:go("R1F1L1") 										-- over canal facing forward
2996
	for h = 1, R.height do
2997
		lib.getWater(backToWater, downToWater)			-- check water supplies, return to starting position
2998
		T:go("L1C1 R1D1 L1C1 R1", false, 0, false)		-- place towpath, forward, down, place towpath, face forward
2999
		T:place("soul", -1, "down", false) 				-- place soulsand down
3000
		T:place("soul", -1, "forward", false) 			-- place soulsand forward
3001
		T:go("R1F1C1L1", false, 0, false)				-- place right towpath face forward
3002
		T:place("soul", -1, "down", false) 				-- place soulsand down
3003
		T:place("soul", -1, "forward", false) 			-- place soulsand forward
3004-
	menu item: Clear hollow structure
3004+
3005
		T:placeWater("down") 							-- place water down
3006-
	if outside active area will have already moved in
3006+
3007-
	R.direction = "up" or "down" as direction of travel
3007+
		T:place("gate", -1, "forward", false) 			-- place fence gate
3008-
	R.up = true / false to dig up as well 
3008+
3009-
	R.down = true / false to dig down as well
3009+
3010-
	R.data.ceiling = true / false to remove ceiling
3010+
3011-
	R.data.floor = true / false to remove floor
3011+
		T:place("gate", -1, "forward", false) 			-- place fence gate
3012-
	examples use a 5 x 5 x 7 cube
3012+
3013
		T:go("R1F1 L1x1 R1C1")
3014-
--utils.printR(R)									-- debug values in R
3014+
3015-
	local height = 1								-- current level of turtle
3015+
3016-
	local cleared = false
3016+
3017
			backToWater = 1
3018-
	R.up = false
3018+
3019-
	R.down = false
3019+
3020-
	-- check if floor/ceiling is to be cleared
3020+
3021-
	if R.direction == "up" then						-- from bottom to top
3021+
3022-
		if R.data.floor then
3022+
3023-
			clearRectangle(R)
3023+
3024-
			cleared = true
3024+
3025
	T:go("D1 L1C1 U1C1")					-- build left towpath, facing towpath, above water level
3026-
	else											-- from top to bottom
3026+
3027-
		if R.data.ceiling then
3027+
3028-
			clearRectangle(R)
3028+
3029-
			cleared = true
3029+
3030
	utils.goBack(1)
3031
	T:go("L1F1")
3032
	T:placeWater("down")  
3033-
	if R.height == 1 and not cleared then			-- only 1 layer, perimeter only eg R.height = 7
3033+
3034
	return {}
3035-
	elseif R.height == 2 and not cleared then		-- only 2 layers, perimeter only
3035+
3036-
		if R.direction == "up" then					-- from bottom to top
3036+
3037
local function createBorehole(R)
3038
	--[[go down to bedrock and return. Chart all blocks dug/ passed through]]
3039
	local diary = {}
3040
	local lib = {}
3041
	local depth = R.height	-- eg 63 start position
3042-
	elseif R.height >= 3 then 						-- 3 or more levels, floor/ceiling already assessed eg R.height = 7
3042+
3043
	--R.height = current level
3044
	
3045-
		height = height + utils.move(R, 1)			-- move up/down 1 block for first layer eg height: 1 + 1 = 2
3045+
3046-
		-- height h + 3 R.height   loop
3046+
3047-
		--	2		5		5		end
3047+
3048-
		--	2		5		7		+
3048+
3049-
		--	5		8		7		end
3049+
3050-
		repeat 			
3050+
3051-
			clearPerimeter(R)						-- runs at least once, removes 3 layers: 1,2,3
3051+
3052-
			local move = 3
3052+
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			
3053+
3054-
				--height = height + utils.move(R, move)	-- move up/down 3 blocks eg height 5, 8, 11, 14
3054+
3055-
			--else
3055+
3056-
				--move = R.height - height - 1
3056+
3057-
				--height = height + utils.move(R, move)	-- move up/down 1-2 blocks eg height = 2 + 3 = 5
3057+
3058
				end
3059
			end
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			
3060+
3061-
				move = R.height - height
3061+
3062
			end
3063-
			height = height + utils.move(R, move)	-- move up/down 1-2 blocks eg height = 2 + 3 = 5
3063+
3064-
		until height > R.height - 3				-- min 3 levels eg height = 2, R.height - 3 --> 7 - 3 = 4, 4 - 3 = 1
3064+
3065
		return diary
3066-
		R.down = false	
3066+
3067-
		if height == R.height then						-- already on top/bottom layer eg height = 5, R.height = 5
3067+
3068-
			if R.direction == "up" then						-- reverse digging direction. Up = move to top and dig down
3068+
3069-
				R.down = true
3069+
3070-
			else										-- reverse digging direction. Up = move to floor and dig up
3070+
3071-
				R.up = true
3071+
3072
		return item
3073-
			clearPerimeter(R)
3073+
3074
	
3075-
			if R.direction == "up" then						-- reverse digging direction. Up = move to top and dig down
3075+
3076-
				R.down = true
3076+
3077-
			else										-- reverse digging direction. Up = move to floor and dig up
3077+
3078-
				R.up = true
3078+
3079
		for l = 1, levelsPerCol do						-- add 32 empty strings
3080
			table.insert(lines, "")
3081-
			clearPerimeter(R)
3081+
3082
		local lineNo = 1
3083
		for k, v in ipairs(diary) do
3084
			local level = R.height - k 					-- eg 63 range 63 to -59
3085-
	R.up = false
3085+
3086-
	R.down = false
3086+
3087-
	if R.direction == "up" then
3087+
3088-
		if R.data.ceiling then		-- from bottom to top
3088+
3089-
			clearRectangle(R)
3089+
3090
				lev = "-0"..math.abs(level).."   "		-- "-09   " to "-01   " 
3091-
	elseif R.direction == "down" then
3091+
3092-
		if R.data.floor then	-- from top to bottom
3092+
3093-
			clearRectangle(R)
3093+
3094
				lev = " "..level.."   "					-- " 10   " to " 99   "
3095
			else
3096
				lev = " "..level.."  " 					-- " 100  " to " 319  "
3097
			end
3098
			local output = lev..item					-- eg "-10   grass_block"
3099
			if #output > 20 then						-- eg "-10   some_long_block_name"  
3100
				output = output:sub(1, 20)				-- eg "-10   some_long_block_" 
3101
			else
3102
				output = menu.padRight(output, 20, " ")	-- eg "-10   grass_block     "
3103
			end
3104
			lines[lineNo] = lines[lineNo]..output		-- add new entry to this line
3105
			lineNo = lineNo + 1							-- increase line no
3106
			if lineNo > levelsPerCol then				-- past last line number
3107
				lineNo = 1								-- reset to 1
3108
			end
3109
		end
3110
		
3111
		local fileName = "borehole"..os.getComputerID()..".txt"
3112
		local handle = fs.open(fileName, "w") 		--create file eg "borehole0.txt"
3113
		handle.writeLine("Level Block         Level Block         Level Block         Level Block")
3114
		for k,v in ipairs(lines) do
3115
			handle.writeLine(v)
3116
		end
3117
		
3118
		handle.close()
3119
		
3120
		return fileName
3121
	end
3122
	
3123
	local blockType = T:getBlockType("down")
3124
	while T:down(1) do
3125
		depth = depth - 1
3126
		moves = moves + 1
3127
		if depth == R.depth then
3128
			break
3129
		end
3130
		diary = lib.addBlock(depth, blockType, diary)
3131
		blockType = T:getBlockType("down")
3132
	end
3133
	local fileName = lib.writeReport(R, diary)
3134
	T:up(moves)
3135
	
3136
	return {"File '"..fileName.."' written"}
3137
end
3138
3139
local function createBubbleLift(R) -- 15
3140
	local lib = {}
3141
	
3142
	function lib.addLayer()
3143
		T:go("F2 L1C1 R1C1 R1C1 L1", false, 0, true)
3144
		turtle.back()
3145
		T:dig("up")	-- clear block above so completed lift can be found
3146
		T:placeWater("forward") 
3147
		turtle.back()
3148
		T:go("C1x0")		
3149
	end
3150-
			T:place("minecraft:torch", "down", false) ---(self, blockType, damageNo, direction, leaveExisting, signText)
3150+
3151
	function lib.addSign()
3152
		turtle.back()
3153
		T:placeWater("forward") 
3154
		T:go("L1B1")
3155
		T:place("sign", -1, "forward")
3156
	end
3157
	
3158
	function lib.buildLift(toHeight)
3159
		local built = lib.goToWater() 		-- returns lift blocks already placed, total height of drop from starting point
3160
		local toBuild = toHeight - built 	-- no of blocks remaining to increase lift size
3161
		local water = 0
3162
		while toBuild > 0 do 				-- at least 1 block height remaining
3163
			water = lib.fillBuckets(toBuild, false) -- no of water buckets onboard (could be more than required)
3164
			if water > toBuild then			-- more water than required
3165
				water = toBuild				-- reduce to correct amount
3166
			end
3167
			T:up(built)						-- climb to top of existing lift
3168
			while water > 0 and toBuild > 0 do
3169
				lib.addLayer()
3170
				water = water - 1
3171
				T:up(1)
3172
				toBuild = toBuild - 1
3173
			end
3174
			-- may still be some height to complete, but needs refill
3175
			if toBuild > 0 then
3176
				built = lib.goToWater() --return to source
3177
				toBuild = toHeight - built
3178
				--lib.fillBuckets(toBuild)
3179
			end
3180
		end
3181
	end
3182
	
3183
	function lib.cleanUp(fromHeight)
3184
		local plug = false
3185
		T:turnRight(2)
3186
		for i = 1, fromHeight do
3187
			plug = false
3188
			if turtle.detect() then
3189
				plug = true
3190
			end
3191
			turtle.down()
3192
			if plug then
3193
				T:place("stone", -1, "up")
3194
			end
3195
		end
3196
		T:go("D1 C1R1x1 R1C1 R1F1 R1x1 L2x1 L1C1 x1") -- delete water sources
3197
		T:go("D1 C1R1x1 R1")
3198
		local blockType = T:getBlockType("forward")
3199
		if blockType:find("dirt") == nil and blockType:find("soul") == nil then -- not dirt or soul sand in front
3200
			T:go("C1")
3201
		end
3202
		T:go("R1F1 R1x1 L2x1 L1C1 x1")
3203
	end
3204
	
3205
	function lib.fillBuckets(toBuild, withSort)
3206
		local emptySlots, water = lib.stackBuckets(withSort)-- gets no of empty slots + no of water buckets
3207
		if water < toBuild then 					-- no of water buckets onboard less than required quantity
3208
			for i = 1, toBuild do 					-- fill required no of buckets up to max space in inventory
3209
				if emptySlots == 0 then 			-- inventory full
3210
					break
3211
				else
3212
					if T:getWater("down") then
3213
						water = water + 1
3214
						sleep(0.5)
3215
					end
3216
				end
3217
				emptySlots = lib.getEmptySlots()
3218
			end
3219
		end
3220
		
3221
		return water
3222
	end
3223
	
3224
	function lib.getEmptySlots()
3225
		local empty = 0
3226
		for i = 1, 16 do
3227
			if turtle.getItemCount(i) == 0 then
3228
				empty = empty + 1
3229
			end
3230
		end
3231
		return empty
3232
	end
3233
	
3234
	function lib.goToWater()
3235
		local built = 0 -- measures completed lift height
3236
		while turtle.down() do -- takes turtle to bottom of water source
3237
			if turtle.detect() then
3238
				built = built + 1
3239
			end
3240
		end
3241
		T:up(1) -- above watersource ready to fill buckets
3242
		-- height = height - 1
3243
		-- built = built - 1 not required as next block is water source: not detected
3244
		return built -- , height
3245
	end
3246
	
3247
	function lib.stackBuckets(withSort)
3248
		if withSort == nil then withSort = false end
3249
		local data = {}
3250
		local bucketSlot = 0
3251
		local emptySlots = 0
3252
		local water = 0
3253
		if withSort then
3254
			T:sortInventory()
3255
		end
3256
		for i = 1, 16 do
3257
			-- find first empty bucket
3258
			if turtle.getItemCount(i) > 0 then
3259
				data = turtle.getItemDetail(i)
3260
				if data.name == "minecraft:bucket" then
3261
					if bucketSlot == 0 then
3262
						bucketSlot = i
3263
					else
3264
						turtle.select(i)
3265
						turtle.transferTo(bucketSlot)
3266
					end
3267
				elseif data.name == "minecraft:water_bucket" then
3268
					water = water + 1
3269
				end
3270
			else
3271
				emptySlots = emptySlots + 1
3272
			end
3273
		end
3274
		return emptySlots, water
3275
	end
3276
	
3277
	
3278
	T:go("C1R1")												-- place block next to ladder support block, turn right to check ladder
3279
	local blockType = T:getBlockType("forward") 				-- Is there a ladder to the right?
3280
	if blockType:find("ladder") == nil then
3281
		T:go("C1L2")											-- Place block as ladder not present
3282
	else														-- ladder present
3283
		T:go("L2")												-- ready to check other side
3284
	end
3285
	blockType = T:getBlockType("forward") 
3286
	if blockType:find("ladder") == nil then
3287
		T:go("C1R1")
3288
	else
3289
		T:go("R1")
3290
	end
3291
	blockType = T:getBlockType("down")
3292
	local dirt = "minecraft:dirt"
3293
	if T:getItemSlot("minecraft:soul_sand") > 0 then
3294
		dirt = "minecraft:soul_sand"
3295
	end
3296
	if blockType:find("bedrock") ~= nil then
3297
		utils.goBack(1)
3298
		T:place(dirt, -1, "forward", false) 					-- placed at end of potential water source, next to ladder
3299
	else
3300
		T:place(dirt, -1, "down", false) 						-- placed in ground, next to ladder
3301
		utils.goBack(1)
3302
		T:placeWater("forward") 							-- place extra water source
3303
	end
3304
	T:go("R1C1 R2C1 L1F1C2 R1C1 L2C1 R1F1C2 R1C1 L1C1 L1C1 L1F1", false, 0, true)
3305
	-- ready for water sources to be placed
3306
	T:placeWater("forward") 								-- place front water source
3307
	T:turnRight(2)											-- facing backward
3308
	T:placeWater("forward") 								-- place back water source
3309
	T:go("R2U1") 											-- facing forward, U1, above centre of water source
3310
	lib.fillBuckets(R.height, true)							-- fill as many buckets as required or until inventory full, sort inventory as well
3311
	local nextToLadder = false
3312
	--T:go("F2R1")
3313
	T:go("x0F1 x0F1C1 R1") 									-- move forward 2 taking out blocks above, plug behind soul sand
3314
	if T:getBlockType("forward"):find("ladder") == nil then	-- no ladder here
3315
		T:turnLeft(2)
3316
		if T:getBlockType("forward"):find("ladder") ~= nil then	-- ladder here
3317
			nextToLadder = true
3318
		end
3319
		T:turnRight(1)
3320
	else
3321
		nextToLadder = true
3322
		T:turnLeft(1)
3323
	end
3324
	-- now above soul sand, facing forward
3325
	if nextToLadder then								-- if nextToLadder, no need for signs
3326
		utils.goBack(2) 								-- return to source centre
3327
	else
3328
		T:go("F2 L1C1R1C1R1C1L1", false, 0, true)		-- prepare layer 1
3329
		lib.addSign()
3330
		T:go("U1F1R1F1 L1C1R1C1R1C1L1", false, 0, true)	-- prepare layer 2
3331
		lib.addSign()
3332
		T:go("L1F1 R1F1R1", false, 0, true)	 			-- above source, level 2
3333
	end
3334
	-- ready to build lift
3335
	lib.buildLift(R.height - 1)
3336
	lib.cleanUp(R.height - 1)
3337
	
3338
	return {"Bubble lift created", "Check correct operation", "Check exit before using" }
3339
end
3340
3341
local function createBubbleTrap(R) -- 34
3342
	--[[
3343
	Replace floor of existing volume of water with soulsand
3344
	Used in river biome for squid farm. Area should be enclosed
3345
	with solid walls surface to floor.
3346
	Usually 7 blocks wide
3347
	]]
3348
	local lib = {}
3349
	
3350
	function lib.clearDown(depth)
3351
		while utils.clearVegetation("down") do
3352
			T:down(1)
3353
			depth = depth + 1
3354
		end
3355
		T:place("soul_sand", -1, "down", false)
3356
		return depth
3357
	end
3358
	
3359
	function lib.clearLength(length, depth)
3360
		local moves = 0
3361
		while moves < length - 1 do
3362
			if utils.clearVegetation("forward") then
3363
				T:forward(1)
3364
				moves = moves + 1 
3365
				depth = lib.clearDown(depth) -- go down if in water/air
3366
				if moves >= length - 1 then
3367
					return depth
3368
				end
3369
			else -- block in front
3370
				local waterAhead = utils.clearVegetation("forward") -- true if air/water in front
3371
				while not waterAhead do 	-- solid block in front
3372
					T:up(1)
3373
					depth = depth - 1
3374
					if depth < 1 then
3375
						return 0
3376
					end
3377
					waterAhead = utils.clearVegetation("forward")
3378
				end
3379
			end
3380
		end
3381
3382
		return depth
3383
	end
3384
	
3385
	function lib.turn(facingForward, depth)
3386
		local direction = "R"
3387
		if not facingForward then
3388
			direction = "L"
3389
		end
3390
		T:go(direction.. 1)
3391
		if utils.clearVegetation("forward") then
3392
			T:forward(1)
3393
			depth = depth + lib.clearDown(depth)
3394
		else
3395
			while not utils.clearVegetation("forward") do
3396
				T:up(1)
3397
				depth = depth - 1
3398
			end
3399
		end
3400
		T:go(direction.. 1)
3401
		
3402
		return depth
3403
	end
3404
	
3405
	local depth = 0
3406
	local length = 0
3407
	local width = 0
3408
	local outbound = true
3409
	local facingForward = true
3410
	local inWater, onWater = utils.getWaterStatus()
3411
	inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,true) -- move into water, max descent 2
3412
	if R.length == 0 then
3413
		R.length = lib.getLength()
3414
	end
3415
	if R.width == 0 then
3416
		T:turnRight(1)
3417
		R.width = lib.getLength()
3418
		T:turnLeft(1)
3419
	end
3420
	-- go down to floor
3421
	depth = lib.clearDown(depth)
3422
	while width < R.width do
3423
		-- now on floor, move along sea/river bed following contour
3424
		depth = lib.clearLength(R.length, depth)
3425
		width = width + 1
3426
		-- now turn and repeat
3427
		if width < R.width then	
3428
			depth = lib.turn(facingForward, depth)
3429
			facingForward = not facingForward
3430
		end
3431
	end
3432
	-- finished so return to surface
3433
	T:up(1) -- up 1 to check for water below
3434
	while T:isWater("down") do
3435
		T:up(1)
3436
	end
3437
	
3438
	return {}
3439
end
3440
3441
local function createCorridor(R) -- 52
3442
	--[[create a corridoor 2 blocks high, with floor and ceiling guaranteed
3443
	T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)]]
3444
	local lib = {}
3445
	
3446
	function lib.continue(R, currentSteps, totalSteps)
3447
		if not R.silent then
3448
			if currentSteps >= 64 and R.length == 0 then
3449
				-- request permission to continue if infinite
3450
				T:clear()
3451
				print("Completed "..totalSteps..". Ready for 64 more")
3452
				print("Do you want to continue? (y/n)")
3453
				response = read()
3454
				if response:lower() ~= "y" then
3455
					return true, 0
3456
				else
3457
					return false, currentSteps
3458
				end
3459
			end
3460
		end
3461
		return true, currentSteps
3462
	end
3463
	
3464
	function lib.seal()	
3465
		local blockType = T:getBlockType("forward")
3466
		if blockType:find("water") ~= nil then
3467
			T:place("stone", 0, "forward", false)
3468
			return "water"	-- water found
3469
		elseif blockType:find("lava") ~= nil then
3470
			T:place("stone", 0, "forward", false)
3471
			return "lava"	-- lava found
3472
		end
3473
		return ""	-- no water or lava
3474
	end
3475
	
3476
	function lib.checkSeal(R)
3477
		local fluidType = ""
3478
		if R.data == "seal" then 		-- check for lava/water at the sides
3479
			T:turnRight(1)
3480
			fluidType = lib.seal()		-- could be "", "water", "lava"
3481
			T:turnLeft(2)
3482
			local blockType = lib.seal()
3483
			if fluidType == "" then		-- no water / lava so far
3484
				fluidType = blockType	-- could be "", "water", "lava"
3485
			end
3486
			T:turnRight(1)
3487
		end
3488
		return fluidType				-- could be "", "water", "lava"
3489
	end
3490
	
3491
	function lib.placeTorch(R, torchSpaces, totalSteps)
3492
		if R.torchInterval > 0 then -- torches onboard
3493
			if torchSpaces == R.torchInterval then -- time to place another torch
3494
				if totalSteps < R.length then -- not at end of run
3495
					if T:getItemSlot("minecraft:torch") > 0 then
3496
						T:place("minecraft:torch", -1, "down")
3497
					end
3498
					torchSpaces = 1
3499
				end
3500
			end
3501
		end
3502
		return torchSpaces -- original value or 1
3503
	end
3504
	
3505
	local currentSteps = 0					-- counter for infinite length. pause every 64 blocks
3506
	local totalSteps = 0					-- counter for all steps so far
3507
	local torchSpaces = R.torchInterval		-- if torches present, counter to place with 8 blocks between
3508
	local fluidType = ""
3509
	local damLength = 0
3510
	local damStarted = false
3511
	local doContinue = true
3512
	if T:getItemSlot("minecraft:torch") == 0 then
3513
		R.torchInterval = 0 -- set to default 9 in getTask()
3514
	end
3515
	for steps = 1, R.length do
3516
		-- starts on floor of tunnel
3517
		doContinue, currentSteps = lib.continue(R, currentSteps, totalSteps) -- continue tunnelling?
3518
		if not doContinue then
3519
			break
3520
		end
3521
		T:go("C2U1C0", false, 0, true)		-- place floor, up 1, place ceiling
3522
		fluidType = lib.checkSeal(R)		-- if R.data == "seal", check for water/lava at ceiling level
3523
		if fluidType == "" then	-- either R.data ~= "seal" or no fluid found
3524
			torchSpaces = lib.placeTorch(R, torchSpaces, totalSteps) -- original value or 1 if torch placed
3525
			T:go("F1D1")
3526
		elseif fluidType == "water" then
3527
			T:go("F1R2 C1D1 C1L2", false, 0, true)
3528
			damStarted = true
3529
			damLength = damLength + 1
3530
		else	--lava
3531
			T:go("F1D1")
3532
		end
3533
		blockType = lib.checkSeal(R)
3534
		if blockType ~= "" then
3535
			fluidType = blockType
3536
		end
3537
		currentSteps = currentSteps + 1
3538
		totalSteps = totalSteps + 1
3539
		torchSpaces = torchSpaces + 1
3540
		if damStarted and fluidType == "" then -- was in water, but no more
3541
			T:go("R2 F"..damLength + 1 .."U1L2F"..damLength + 1 .."D1")
3542
			damStarted = false
3543
		end
3544
	end
3545
	if fluidType ~= "" then -- water or lava found while tunnelling
3546
		T:go("U1C0", false, 0, true)
3547
		lib.checkSeal(R)
3548
		T:go("C1", false, 0, true)
3549
		T:down(1)
3550
	end
3551
	return {}
3552
end
3553
3554
local function createDragonTrap() -- 49
3555
	local lib = {}
3556
	
3557
	function lib.attack()
3558
		local totalHitsF = 0
3559
		local totalHitsU = 0
3560
		local totalHitsD = 0
3561
		while true do
3562
			local hitF = false
3563
			local hitU = false
3564
			local hitD = false
3565
			if turtle.attackUp() then
3566
				hitU = true
3567
				totalHitsU = totalHitsU + 1
3568
			end
3569
			if turtle.attackDown() then
3570
				hitD = true
3571
				totalHitsD = totalHitsD + 1
3572
			end
3573
			if turtle.attack() then
3574
				hitF = true
3575
				totalHitsF = totalHitsF + 1
3576
			end
3577
			if hitF or hitU or hitD then
3578
				print("hits forward: "..totalHitsF..", up: "..totalHitsU..", down: "..totalHitsD)
3579
			end
3580
		end
3581
	end
3582
	-- build up 145 blocks with ladders
3583
	T:clear()
3584
	menu.colourPrint("Press Enter to start 1 minute delay\n", colors.red)
3585
	menu.colourPrint("Run to island centre across the bridge\n", colors.orange)
3586
	menu.colourPrint("You have already made the bridge?...", colors.lime)
3587
	read()
3588
	for t = 60, 1, -1 do
3589
		sleep(1)
3590
		T:clear()
3591
		io.write("Starting in "..t.. " seconds ")
3592
	end
3593
	for i = 1, 145 do
3594
		T:go("U1C2")
3595
		turtle.back()
3596
		T:place("minecraft:ladder", -1, "down")
3597
		turtle.forward()
3598
	end
3599
	T:go("R2F1C1 L1C1 L2C1 R1")
3600
	for i = 1, 100 do
3601
		T:go("F1C2U1C0D1")
3602
	end
3603
	T:forward(1)
3604
	T:place("minecraft:obsidian", -1, "down")
3605
	T:go("R2F1x2R2")
3606
	T:placeWater("forward") 
3607
	T:go("R2F6R2")
3608
	lib.attack()
3609
	
3610
	return {}
3611
end
3612
	
3613
local function createEnderTower(stage) -- 66
3614
	--[[ lower base = stage 1, upper base = 2, tower = 3 ]]
3615
	local lib = {}
3616
	--[[ go(path, useTorch, torchInterval, leaveExisting, preferredBlock) ]]
3617
	function lib.getEmptySlots()
3618
		local empty = 0
3619
		for i = 1, 16 do
3620
			if turtle.getItemCount(i) == 0 then
3621
				empty = empty + 1
3622
			end
3623
		end
3624
		return empty
3625
	end
3626
3627
	function lib.getStone(direction, stacks)
3628
		--[[ get block user wants to use ]]
3629
		local suck = turtle.suck	
3630
		if direction == "down" then
3631
			suck = turtle.suckDown
3632
		end
3633
		if T:getBlockType(direction) == "minecraft:chest" then
3634
			T:sortInventory()
3635
			local slot = T:getFirstEmptySlot() --find spare slot
3636
			if slot > 0 then --empty slot found
3637
				turtle.select(1)
3638
				if stacks == 0 then
3639
					while suck() do end
3640
				else
3641
					for i = 1, stacks do -- get # stacks of stone from chest
3642
						suck()
3643
					end
3644
				end
3645
				if T:getSlotContains(slot) == "" then
3646
					return T:getMostItem()				-- empty chest
3647
				else
3648
					return T:getSlotContains(slot) 		-- use this as default building block
3649
				end
3650
			else
3651
				return T:getMostItem()				-- full inventory
3652
			end
3653
		else
3654-
			utils.waitForInput()
3654+
3655
		end
3656
	end
3657
	
3658
	function lib.stackBuckets()
3659
		local data = {}
3660
		local bucketSlot = 0
3661
		local emptySlots = 0
3662-
				utils.waitForInput()
3662+
3663
		T:sortInventory()
3664
		for i = 1, 16 do
3665
			-- find first empty bucket
3666
			if turtle.getItemCount(i) > 0 then
3667
				data = turtle.getItemDetail(i)
3668
				if data.name == "minecraft:bucket" then
3669
					if bucketSlot == 0 then
3670
						bucketSlot = i
3671
					else
3672
						turtle.select(i)
3673
						turtle.transferTo(bucketSlot)
3674
					end
3675
				elseif data.name == "minecraft:water_bucket" then
3676
					water = water + 1
3677
				end
3678
			else
3679
				emptySlots = emptySlots + 1
3680
			end
3681
		end
3682
		return emptySlots, water
3683
	end
3684
	
3685
	function lib.countWaterBuckets()
3686
		local data = {}
3687
		local buckets = 0
3688
		for i = 1, 16 do
3689
			data = turtle.getItemDetail(i)
3690
			if data.name == "minecraft:water_bucket" then
3691
				buckets = buckets + 1
3692
			end
3693
		end
3694
		return buckets
3695
	end
3696
	
3697
	function lib.baseRun(preferredBlock, count, turn)
3698
		for i = 1, count do
3699
			T:go("C2F1", false, 0, false, preferredBlock)
3700
		end
3701
		T:go("C2"..turn, false, 0, false, preferredBlock)
3702
	end
3703
	
3704
	function lib.outsideRun(preferredBlock)
3705
		T:place("fence", -1, "down", false)
3706
		T:forward(1)
3707
		T:place(preferredBlock, -1, "down", false)
3708
		T:forward(1)
3709
		T:place(preferredBlock, -1, "down", false)
3710
		T:forward(2)
3711
		T:place(preferredBlock, -1, "down", false)
3712
	end
3713
	
3714
	function lib.signRun(preferredBlock ,message)
3715
		T:place(preferredBlock, -1, "down", false)
3716
		T:forward(4)
3717
		T:place(preferredBlock, -1, "down", false)
3718
		turtle.back()
3719
		turtle.back()
3720
		T:down(1)
3721
		T:place("sign", -1, "forward", false, message)
3722
		T:go("U1F2")
3723
	end
3724
	
3725
	function lib.goToWater(height)
3726
		local built = 0 -- measures completed lift height
3727
		while turtle.down() do -- takes turtle to bottom of water source
3728
			height = height + 1
3729
			if turtle.detect() then
3730
				built = built + 1
3731-
			utils.waitForInput()
3731+
3732
		end
3733
		T:up(1) -- above watersource assuming it is 1-1.5 blocks deep
3734
		height = height - 1
3735
		-- built = built - 1 not required as next block is water source: not detected
3736
		return built, height
3737
	end
3738-
			utils.waitForInput()
3738+
3739
	function lib.fillBuckets(toBuild)
3740
		local emptySlots, water = lib.stackBuckets() -- gets no of empty slots + no of water buckets
3741
		if water < toBuild then -- no of water buckets onboard less than required quantity
3742
			for i = 1, toBuild do -- fill required no of buckets up to max space in inventory
3743
				emptySlots = lib.getEmptySlots()
3744
				if emptySlots == 0 then -- inventory full
3745
					break
3746
				else
3747
					if T:getWater("down") then
3748
						water = water + 1
3749
						sleep(0.5)
3750
					end
3751
				end
3752
			end
3753
		end
3754
		
3755
		return water
3756
	end
3757
	
3758
	function lib.buildLift(preferredBlock)
3759
		local built = 0 -- measures completed lift height
3760
		local height = 0 -- measures total height from starting position
3761
		built, height = lib.goToWater(height) -- returns lift blocks already placed, total height of drop from starting point
3762
		local toBuild = height - built -- no of blocks to increase lift size
3763
		while toBuild > 0 do -- at least 1 block height remaining
3764
			local water = lib.fillBuckets(toBuild) -- no of water buckets onboard (could be more than required)
3765
			if water > toBuild then
3766
				water = toBuild
3767
			end
3768
			while turtle.detect() do -- climb to top of existing lift
3769
				turtle.up()
3770
				height = height - 1
3771
			end
3772
			T:forward(1)
3773
			for i = 1, water do -- build lift by no of water buckets
3774
				if T:placeWater("forward")  then
3775
					T:up(1)
3776
					height = height - 1
3777
					toBuild = toBuild - 1
3778
					T:place(preferredBlock, -1, "down", false)
3779
				end
3780
			end
3781
			turtle.back()
3782
			-- may still be some height to complete, but needs refill
3783
			if toBuild > 0 then
3784
				lib.goToWater(0) --return to source
3785
				lib.fillBuckets(toBuild)
3786
			end
3787
		end
3788
		if height > 0 then -- if any remaining distance
3789
			T:up(height)
3790
		end
3791
		
3792
	end
3793
	
3794
	function lib.buildSection(preferredBlock, solid)
3795
		-- builds a section without any blocks in the centre
3796
		-- second layer of each section end walls have fence posts
3797
		T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- first side solid row
3798
		if solid then -- first layer of each section
3799
			T:go("F1C2 F1R1", false, 0, false, preferredBlock) -- top side solid row
3800
		else
3801
			T:go("F1") -- top side solid row
3802
			if not T:place("fence", -1, "down", false) then-- first side
3803
				T:place(preferredBlock, -1, "down", false)
3804
			end
3805
			T:go("F1R1") -- top side solid row
3806
		end
3807
		T:go("F1C2 F2C2 F1R1", false, 0, false, preferredBlock) -- far side solid row
3808
		T:go("F1C2 F1R1U1", false, 0, false, preferredBlock) -- bottom side solid row
3809
	end	
3810
	--[[
3811
		clsTurtle methods:
3812
		clsTurtle.place(self, blockType, damageNo, direction, leaveExisting)
3813
		clsTurtle.go(self, path, useTorch, torchInterval, leaveExisting, preferredBlock)
3814
	]]
3815
	-- remove 1 stack stone from chest
3816
	local preferredBlock = lib.getStone("down", 1) -- use this as default building block
3817
	if stage == 1 then
3818
		-- build base floor
3819
		--T:go("R2F2R1F3R1", false, 0, false, preferredBlock)
3820
		T:go("R2F1C2R1F1C2F1C2F1C2R1", false, 0, false, preferredBlock)
3821
		for i = 1, 2 do
3822
			lib.baseRun(preferredBlock, 8, "R1F1R1")
3823
			lib.baseRun(preferredBlock, 8, "L1F1L1")
3824
			lib.baseRun(preferredBlock, 8, "R1F4R1")
3825
		end
3826
		-- move back to centre, build water source, with soul sand at base of first source
3827
		--T:go("R1F3L1C2F1C2F2D1", false, 0, false, preferredBlock) --just behind chest, 1 below ground level
3828
		T:go("R1F3L1F2C2F1D1", false, 0, false, preferredBlock) --1 block behind chest, 1 below ground level
3829
		T:place("minecraft:soul_sand", -1, "down", false) -- over block 1 of water source
3830
		T:go("F1C2F1C2", false, 0, false, preferredBlock) -- over block 2 of water source
3831
		T:go("F1C2U1C2", false, 0, false, preferredBlock) -- over block 4 of water source
3832
		T:go("F1C2F1C2R2F5R2", false, 0, false, preferredBlock) -- over block 1 of water source
3833
		T:placeWater("down") 
3834
		T:forward(2) -- over block 3 of water source
3835
		T:placeWater("down")
3836
		turtle.back() -- over block 2 of water source
3837
		T:getWater("down")
3838
		T:go("F2D1R2C2") -- over block 4 of water source
3839
		T:go("U1", false, 0, false, preferredBlock)
3840
		T:placeWater("down")
3841
		T:forward(4)
3842
		lib.stackBuckets() -- put all buckets in same slot
3843
		T:dropItem("minecraft:dirt", "up", 0) -- drop dirt up:  clsTurtle.dropItem(self, item, direction, keepAmount)
3844
		preferredBlock = lib.getStone("down", 6)
3845
		T:go("R1F2R1U1") -- move to start position
3846
		for i = 1, 2 do
3847
			-- build first level of tower: 2 x outside run, 2 x sign run
3848
			lib.outsideRun(preferredBlock)
3849
			if i == 1 then -- place door
3850
				T:go("L1F1L1F1L1D1")
3851
				T:place("door", -1, "forward", false)
3852
				T:go("U1L1F1R1F1L1")
3853
			end
3854
			T:go("R1F1R1")
3855
			lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
3856
			T:go("L1F1L1C2", false, 0, false, preferredBlock)
3857
			T:forward(4) -- miss out centre block
3858
			T:place(preferredBlock, -1, "down", false)
3859
			T:go("R1F1R1")
3860
			lib.signRun(preferredBlock, "Pint size\nzombies\nProhibited")
3861
			T:go("L1F1L1")
3862
			lib.outsideRun(preferredBlock)
3863
			if i == 1 then -- layer 1
3864
				T:go("R1F1R1F1R1D1") -- place door
3865
				T:place("door", -1, "forward", false)
3866
				T:go("U1 R1F1 L1F5 L1U1 F2D1  F2R2 U1") -- go over door
3867
			else -- layer 2
3868
				T:go("L1F5L1F6R2U1") -- over corner of lower platform
3869
			end
3870
		end
3871
		for i = 1, 2 do -- build both sides of platform, leave centre missing
3872
			lib.baseRun(preferredBlock, 8, "R1F1R1")
3873
			lib.baseRun(preferredBlock, 8, "L1F1L1")
3874
			lib.baseRun(preferredBlock, 8, "R1F4R1")
3875
		end
3876
		T:go("R1F3L1C2F1C2F1C2F4C2F1C2F1C2", false, 0, false, preferredBlock) --fill in centre row
3877
		--T:go("R2F6R1F1R1U1") -- go to start of tower base
3878
		T:go("R2F7R2D3") -- go to start on top of chest
3879
		T:sortInventory()
3880
	elseif stage == 2 then
3881
		-- start on top of chest, should have sufficient stone in inventory
3882
		T:go("U3L1F1R1F1U1") -- go to start of tower base
3883
		for i = 1, 7 do -- build 14 block high tower
3884
			lib.buildSection(preferredBlock, false)
3885
			lib.buildSection(preferredBlock, true)
3886
		end
3887
		T:go("R2F4R1F4R1", false, 0, false, preferredBlock) -- build upper platform (154 blocks remaining)
3888-
	--[[ direction = R.direction "up" or "down" ]]
3888+
3889
			lib.baseRun(preferredBlock, 12, "R1F1R1")
3890
			lib.baseRun(preferredBlock, 12, "L1F1L1")
3891
			lib.baseRun(preferredBlock, 12, "R1F1R1")
3892
			lib.baseRun(preferredBlock, 12, "L1F1L1")
3893
			lib.baseRun(preferredBlock, 12, "R1F6R1")
3894
		end
3895
		T:go("R1F5 L1C2 F1C2 F1C2 F1C2 F1C2 F4C2 F1C2 F1C2 F1C2 F1C2 ", false, 0, false, preferredBlock) --fill in centre row
3896
		T:go("R2F5") -- return to drop area
3897
		lib.buildLift(preferredBlock) -- build bubble lift
3898
		T:go("F3R1F1R1U1") -- go to start of tower base
3899
		T:go("C2F4 C2R1F1R1", false, 0, false, preferredBlock) 		-- left side layer 21
3900
		T:go("F2C2 F2C2 L1F1L1", false, 0, false, preferredBlock) 	-- centre layer 21
3901
		T:go("C2F4 C2R2U1", false, 0, false, preferredBlock) 		-- right side layer 21
3902-
		if R.direction == "up" then
3902+
3903
		T:place("fence", -1, "down", false)							-- fence centre of bottom side layer 22
3904
		T:go("F2C2 F2L1F1L1", false, 0, false, preferredBlock)		-- centre layer 22
3905
		T:go("C2F4 C2R2F2L1F1R2D2", false, 0, false, preferredBlock) --ready to place ladder
3906
		T:place("ladder", -1, "forward", false)
3907
		T:up(1)
3908
		T:place("ladder", -1, "forward", false)
3909
		--T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
3910
		T:go("U2R1F4R1F1R1") -- ready to make upper part of tower base
3911
		for i = 1, 2 do -- build both sides of platform, leave centre missing
3912
			lib.baseRun(preferredBlock, 8, "R1F1R1")
3913
			lib.baseRun(preferredBlock, 8, "L1F1L1")
3914
			lib.baseRun(preferredBlock, 8, "R1F4R1")
3915
		end
3916
		T:go("R1F3 L1C2 F1C2 F1C2 F1", false, 0, false, preferredBlock) --fill in centre row
3917
		T:place("minecraft:soul_sand", -1, "down", false) 
3918
		T:go("F1C2 F2C2 F1C2 F1C2", false, 0, false, preferredBlock)
3919
		T:go("R2F6R1F1R1U1") -- go to start of tower base
3920
		-- build 2 levels, finish signs and ladders
3921
		T:go("C2F2 R1D2 U1", false, 0, false, preferredBlock)
3922
		T:place("ladder", -1, "down", false)
3923
		T:turnRight(1)
3924
		T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
3925
		T:go("U1R2F2C2 R1F2C2 R1", false, 0, false, preferredBlock) --top right corner
3926
		T:go("F4C2B2D1", false, 0, false, preferredBlock)
3927
		T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
3928
		T:go("U1F2R1F1C2F1R1U1", false, 0, false, preferredBlock) --ready for second level
3929
		T:go("C2F2 R2D1", false, 0, false, preferredBlock)
3930
		T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
3931
		T:go("U1R2F2C2R1", false, 0, false, preferredBlock) --top left corner
3932
		T:go("F1R1C2F4C2", false, 0, false, preferredBlock) --mid bottom row
3933
		T:go("L1F1L1C2", false, 0, false, preferredBlock) -- bottom right corner
3934
		T:go("F2R2D1", false, 0, false, preferredBlock)
3935
		T:place("sign", -1, "forward", false, "UP\n^\n|\n|")
3936
		T:go("U1R2F2C2", false, 0, false, preferredBlock) -- top right corner
3937
		-- return to chest
3938
		T:go("L1F1L1 F5D23R2", false, 0, false, preferredBlock) -- return to chest
3939
		T:sortInventory()
3940
	elseif stage == 3 then
3941
		--[[ move to top of structure
3942
		| 4 |
3943
		|3 5|
3944
		| X |
3945
		|2 6|
3946
		| 1 |
3947
		]]
3948
		local towerHeight = 128 -- even no only suggest 128
3949
		while turtle.detect() do
3950
			turtle.up()
3951
		end
3952
		T:go("F1U1", false, 0, false, preferredBlock) -- return to finish tower
3953
		for i = 1, towerHeight do -- 1
3954
			T:go("C2U1", false, 0, false, preferredBlock)
3955
		end
3956
		T:go("F1L1F1R1D2")
3957
		while turtle.down() do -- 2
3958
			T:fillVoid("up", {preferredBlock})
3959
		end
3960
		T:go("F1R2C1R2F1D1", false, 0, false, preferredBlock)
3961
		for i = 1, towerHeight / 2 do -- 3
3962
			T:go("U2C2", false, 0, false, preferredBlock)
3963
		end
3964
		T:go("U1F1R1F1R1D1", false, 0, false, preferredBlock) -- back of tower facing front
3965
		local deviate = false
3966
		while turtle.down() do -- 4
3967
			T:place("fence", -1, "up", false)
3968
			if turtle.down() then
3969
				T:fillVoid("up", {preferredBlock})
3970
			else
3971
				T:go("F1R2C1R1F1R1D1", false, 0, false, preferredBlock)
3972
				deviate = true
3973
				break
3974
			end
3975
		end
3976
		if not deviate then
3977
			T:go("F1L1F1R1D1", false, 0, false, preferredBlock)
3978
		end
3979
		for i = 1, towerHeight / 2 do -- 5
3980
			T:go("U2C2", false, 0, false, preferredBlock)
3981
		end
3982
		T:go("F2R2", false, 0, false, preferredBlock) -- facing back of tower
3983
		while turtle.down() do -- 6
3984
			T:fillVoid("up", {preferredBlock}) --layer 129
3985
		end
3986
		T:go("F1L2C1U"..towerHeight)
3987
		T:go("F4R1F3R1U1", false, 0, false, preferredBlock)
3988
		-- add small platform at the top
3989
		lib.baseRun(preferredBlock, 8, "R1F1R1")
3990
		lib.baseRun(preferredBlock, 8, "L1F3L1")
3991
		lib.baseRun(preferredBlock, 8, "L1F1L1")
3992
		lib.baseRun(preferredBlock, 8, "R1F1R1")
3993
		T:go("C2 F1C2 F1C2 F4C2 F1C2 F1C2 R2F3", false, 0, false, preferredBlock) --fill in centre row
3994
		lib.buildLift(preferredBlock) -- build bubble lift
3995
	end
3996
	return {}
3997
end
3998
3999
local function createFarm(R, extend) -- 31
4000
	-- if extend ~= nil then this has been called from createFarmExtension()
4001
	-- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
4002
	local lib = {}
4003
	function lib.addWaterSource(R, pattern, storage)
4004
		-- pattern = {"d","c","c","d"} t = place crafting  instead of dirt
4005
		-- place(self, blockType, damageNo, direction, leaveExisting, signText)
4006
		T:go("D1x2C2", false, 0, false, R.useBlockType)
4007
		for i = 1, 4 do
4008
			T:dig("forward")
4009
			if pattern[i] == "d" then
4010
				T:place("dirt", -1, "forward", false)
4011
			elseif pattern[i] == "t" then
4012
				--if not T:place("minecraft:crafting_table", -1, "forward", false) then
4013
				if T:place(storage, -1, "forward", false) then
4014
					if T:dropItem("crafting", "forward", 0) then
4015
						print("Crafting table -> buried storage")
4016
					end
4017
				else
4018
					T:place("dirt", -1, "forward", false) -- dirt if no storage available
4019
				end
4020
			else
4021
				T:place(R.useBlockType, -1, "forward", false)
4022
			end
4023
			T:turnRight(1)
4024
		end
4025
		T:up(1)
4026
		T:placeWater("down")
4027
	end
4028
	
4029
	function lib.placeDirt(count, atCurrent)
4030
		if atCurrent then
4031
			local blockType = T:getBlockType("down")
4032
			if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
4033
				T:place("dirt", -1, "down", false)
4034
			end
4035
		end
4036
		for  i = 1, count do
4037
			T:forward(1)
4038
			T:dig("up")
4039
			local blockType = T:getBlockType("down")
4040
			if blockType:find("dirt") == nil and blockType:find("grass_block") == nil then
4041
				T:place("dirt", -1, "down", false)
4042
			end
4043
		end
4044
	end
4045
4046
	function lib.placeStorage(storage, storageBackup)
4047
		T:dig("down")
4048
		if not T:place(storage, -1, "down", false) then-- place barrel/chest below
4049
			T:place(storageBackup, -1, "down", false) -- place chest below
4050
		end
4051
	end
4052
4053
	
4054
	-- extend "", "right" or "forward". only adds a single new farm.
4055
	-- right adds farm and checks for existing front extensions, dealt with separately
4056
	-- clsTurtle.place(blockType, damageNo, direction, leaveExisting)
4057
	if extend == nil then
4058
		extend = ""
4059
	end
4060
	local blockType = ""
4061
	-- extend = "right": placed on cobble corner of existing farm facing right side
4062
	-- extend = "front": placed on cobble corner of existing farm facing front
4063
	-- else placed on ground at corner of potential new farm facing front
4064
	
4065
	local storage, storageBackup = utils.setStorageOptions()
4066
	-- step 1 dig ditch round perimeter wall
4067
	if extend == "right" then
4068
		-- move to front corner ground ready for ditch
4069
		T:go("F1L1F12D1R1", false, 0, false, R.useBlockType)
4070
		-- cut ditch round new farm extension
4071
		for i = 1, 12 do
4072
			T:go("x0F1")
4073
		end
4074
		T:go("R1x0")
4075
		for i = 1, 13 do
4076
			T:go("x0F1")
4077
		end
4078
		T:go("R1x0")
4079
		-- now at lower right corner. if extension below, do not cut ditch
4080
		blockType = T:getBlockType("forward")
4081
		if blockType:find("stone") ~= nil then -- already a farm extension on left side
4082
			-- return to start for adding chests and walls
4083
			T:go("U1R1F1L1F12", false, 0, false, R.useBlockType)
4084
		else -- finish ditch
4085
			for i = 1, 12 do
4086
				T:go("x0F1")
4087
			end
4088
			T:go("R1U1F1") -- on corner of new extension
4089
		end
4090
	elseif extend == "forward" then
4091
		T:go("L1F2R1D1", false, 0, false, R.useBlockType)
4092
		-- cut ditch round new farm extension
4093
		for i = 1, 12 do
4094
			T:go("x0F1", false, 0, false, R.useBlockType)
4095
		end
4096
		T:go("R1x0", false, 0, false, R.useBlockType)
4097
		for i = 1, 13 do
4098
			T:go("x0F1", false, 0, false, R.useBlockType)
4099
		end
4100
		T:go("R1x0", false, 0, false, R.useBlockType)
4101
		for i = 1, 11 do
4102
			T:go("x0F1", false, 0, false, R.useBlockType)
4103
		end
4104
		T:go("U1x0F1R1F12R1", false, 0, false, R.useBlockType) -- on corner of new extension
4105
	else -- new farm. cut a groove round the entire farm base
4106
		-- move to left side of intended wall
4107
		T:go("L1F1x0R1", false, 0, false, R.useBlockType)
4108
		for j = 1, 4 do
4109
			for i = 1, 12 do
4110
				T:go("x0F1", false, 0, false, R.useBlockType)
4111
			end
4112
			T:go("R1x0F1", false, 0, false, R.useBlockType)
4113
		end
4114
		T:go("R1F1L1U1", false, 0, false, R.useBlockType)
4115
	end
4116
	-- stage 2 place sapling and double barrel/chest
4117
	T:dig("down") --remove cobble if present
4118
	T:place("dirt", -1, "down", false)
4119
	T:go("F1R2")
4120
	T:place("sapling", -1, "forward", false) -- plant sapling
4121
	T:go("L1")
4122
	lib.placeStorage(storage, storageBackup)
4123
	T:go("L1F1R1")
4124
	lib.placeStorage(storage, storageBackup)
4125
	T:turnLeft(1)
4126
	if extend == "right" then -- cobble wall exists so go forward to its end
4127
		T:forward(9)
4128
	else -- new farm or extend forward
4129
		for i = 1, 9 do -- complete left wall to end of farm
4130
			T:go("F1x0x2C2", false, 0, false, R.useBlockType)
4131
		end
4132
	end
4133
	T:go("R1F1 R1x0 x2C2 F1D1", false, 0, false, R.useBlockType)-- turn round ready for first dirt col
4134
	lib.addWaterSource(R, {"d","c","c","d"}, storage) -- water at top of farm
4135
	lib.placeDirt(9, false) -- place dirt back to start
4136
	lib.addWaterSource(R, {"c","c","t","d"}, storage) -- water source next to chests, includes crafting table
4137
	T:go("U1F1R2")
4138
	if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
4139
		lib.placeStorage(storage, storageBackup)
4140
	end
4141
	T:go("R1F1L1")
4142
	if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
4143
		lib.placeStorage(storage, storageBackup)
4144
	end
4145
	T:go("F1D1")
4146
	lib.placeDirt(9, true)
4147
	local turn = "R"
4148
	for i = 1, 7 do
4149
		T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
4150
		lib.placeDirt(9, true)
4151
		if turn == "R" then
4152
			turn = "L"
4153
		else
4154
			turn = "R"
4155
		end
4156
	end
4157
	T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0x2C2F1D1", false, 0, false, R.useBlockType)
4158
	lib.addWaterSource(R, {"d","c","c","d"}, storage)
4159
	lib.placeDirt(9, false)
4160
	lib.addWaterSource(R, {"c","c","d","d"}, storage)
4161
	T:go("F1U1R1C2x0F1x0x2C2R1", false, 0, false, R.useBlockType)
4162
	for i = 1, 11 do
4163
		T:go("F1x0x2C2", false, 0, false, R.useBlockType)
4164
	end
4165
	-- add barrel/chest to any existing farm extension to the right
4166
	T:go("L1F1L1")
4167
	if T:getBlockType("down"):find("stone") == nil then -- farm extension already exists to right
4168
		lib.placeStorage(storage, storageBackup)
4169
	end
4170
	T:go("L1F11")
4171
	
4172
	return {"Modular farm completed"}
4173
end
4174
4175
local function createFarmExtension(R) -- 32
4176
	-- assume inventory contains 4 chests, 64 cobble, 128 dirt, 4 water, 1 sapling
4177
	-- check position by rotating to face tree/sapling
4178
	local doContinue = true
4179
	local treePresent = false
4180
	local extend = "right" -- default
4181
	if R.subChoice == 1 then
4182
		extend = "forward"
4183
	end
4184
	local storage, storageBackup = utils.setStorageOptions()
4185
	local blockType = T:getBlockType("down")
4186
	if blockType:find(storage) == nil and blockType:find(storageBackup) == nil then
4187
		return
4188-
			T:place("slab", "down", false)
4188+
4189
			"Barrel or chest not present below\n",
4190
			"Unable to calculate position",
4191
			"Move me next to/front of the tree/sapling",
4192
			"lower left corner of the existing farm."
4193
		}
4194
	else
4195
		for i = 1, 4 do
4196
			blockType = T:getBlockType("forward")
4197
			if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
4198
				treePresent = true
4199
				break
4200
			end
4201
			T:turnRight()
4202
		end
4203
		if not treePresent then
4204
			return
4205
			{
4206
				"Unable to locate tree or sapling",
4207
				"Plant a sapling on the lower left",
4208
				"corner of the farm, or move me there"
4209
			}
4210
		end
4211
	end
4212
	if doContinue then -- facing tree. check if on front or l side of farm
4213
		if extend == "forward" then
4214
			T:go("R1F11") -- to other side of farm. may be stone or barrel/chest below
4215-
				T:place("slab", "down", false)
4215+
4216
			if blockType:find(storage) ~= nil or blockType:find(storageBackup) ~= nil then
4217
				doContinue = false
4218
			end
4219
		else
4220
			T:go("R2F9") -- to right of farm, may be sapling/tree in front
4221
			blockType = T:getBlockType("forward")
4222
			if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
4223
				doContinue = false
4224
			end
4225
		end
4226
		if doContinue then -- extend farm.
4227
			createFarm(R, extend)
4228-
			T:place("slab", "down", true)
4228+
4229
			return
4230
			{
4231
				"This farm has already been extended",
4232
				"Move me next to/front of the tree / sapling",
4233
				"of the last extension in this direction."
4234
			}
4235
		end
4236
	end
4237
	return {"Modular crop farm extended"}
4238
end
4239
4240
local function createFloorCeiling(R) -- 79 size integer 1 to 4
4241
	--[[
4242
	R.up = true for ceiling
4243
	R.down = true for floor
4244
	R.height = 0 for normal
4245
	R.height combined with R.up/R.down used for remote access
4246
	]]
4247
	
4248
	local useBlock = T:getSlotContains(1)
4249
	local waterPresent = false
4250
	
4251
	if R.useBlockType ~= "" then
4252
		useBlock = R.useBlockType
4253
	end
4254
	print("Using ".. useBlock)
4255
	local direction = "down"
4256
	if R.up then
4257
		direction = "up"
4258
	end
4259
	if R.height > 0 then -- remote placing. go up/down R.height first
4260
		R.silent = true
4261
		local depth = 0
4262
		if R.down then -- floor could be under water
4263
			while turtle.down() do
4264
				depth = depth + 1
4265
			end
4266
		elseif R.up then
4267
			while turtle.up() do
4268
				depth = depth + 1
4269
				if depth > R.height + 3 then
4270
					break
4271
				end
4272
			end
4273
		end
4274
		if not(R.height - depth <= 2 or depth - R.height <= 2) then
4275
			T:up(depth)
4276
			return {"Measured depth/height of "..depth.." > setting: "..R.height}
4277
		end
4278
		-- not returned so depth acceptable
4279
	end
4280
	-- check if block above/below
4281
	local blockBelow = turtle.detectDown()
4282
	local blockAbove = turtle.detectUp()
4283
	if R.subChoice == 2 then -- New floor over existing
4284
		-- if no block below, assume in correct position and continue
4285
		-- else move up 1 and continue
4286
		if blockBelow then T:up(1) end
4287
	elseif R.subChoice == 4 then -- New ceiling under existing
4288
		-- if no block above, assume in correct position and continue
4289
		-- else move down 1 and continue
4290
		if blockAbove then T:down(1) end
4291
	end
4292
	
4293
	local evenWidth = false
4294
	local evenHeight = false
4295
	local loopWidth
4296
	-- go(path, useTorch, torchInterval, leaveExisting)
4297
	if R.width % 2 == 0 then
4298
		evenWidth = true
4299
		loopWidth = R.width / 2
4300
	else
4301
		loopWidth = math.ceil(R.width / 2)
4302
	end
4303
	if R.length % 2 == 0 then
4304
		evenHeight = true
4305
	end
4306
	-- if R.width is even no, then complete the up/down run
4307-
	--T:place(blockType, direction, leaveExisting, signText)
4307+
4308
	for x = 1, loopWidth do
4309
		-- Clear first column (up)
4310
		local tAvailable = T:getStock(useBlock, -1)
4311
		if tAvailable.total < R.length and not R.silent then
4312
			return {"Insufficient resources to complete current row"}
4313
		end
4314
		for y = 1, R.length do
4315
			local blockType = T:getBlockType("forward")
4316-
		T:place("soul", "down", false) 				-- place soulsand down
4316+
4317-
		T:place("soul", "forward", false) 			-- place soulsand forward
4317+
4318
					waterPresent = true
4319-
		T:place("soul", "down", false) 				-- place soulsand down
4319+
4320-
		T:place("soul", "forward", false) 			-- place soulsand forward
4320+
4321
			T:place(useBlock, -1, direction, false) -- leaveExisting = false
4322
			if y < R.length then
4323
				T:go("F1", false, 0, false)
4324-
		T:place("gate", "forward", false) 			-- place fence gate
4324+
4325
		end
4326
		-- clear second column (down)
4327
		if x < loopWidth or (x == loopWidth and evenWidth) then -- go down if on R.width 2,4,6,8 etc
4328-
		T:place("gate", "forward", false) 			-- place fence gate
4328+
			T:go("R1F1R1", false,0,false)
4329
			tAvailable = T:getStock(useBlock, -1)
4330
			if tAvailable.total < R.length and not R.silent then
4331
				return {"Insufficient resources to complete current row"}
4332
			end
4333
			for y = 1, R.length do
4334
				T:place(useBlock, -1, direction, false) -- leaveExisting = false
4335
				if y < R.length then
4336
					T:go("F1", false, 0, false)
4337
				end
4338
			end
4339
			if x < loopWidth then 
4340
				T:go("L1F1L1", false,0,false)
4341
			else
4342
				T:turnRight(1)
4343
				T:forward(R.width - 1)
4344
				T:turnRight(1)
4345
			end
4346
		else -- equals R.width but is 1,3,5,7 etc
4347
			T:turnLeft(2) --turn round 180
4348
			T:forward(R.length - 1)
4349
			T:turnRight(1)
4350
			T:forward(R.width - 1)
4351
			T:turnRight(1)
4352
		end
4353
	end
4354
	if waterPresent then
4355
		return {"water or lava found"}
4356
	end
4357
	return {""}
4358
end
4359
4360
local function createIceCanal(R) -- 55
4361
	--[[
4362
		R.subChoice = 
4363
		1: move right into canal, build left towpath
4364
		2: build left towpath
4365
		3: build right towpath
4366
		4: move left into canal, build right towpath
4367
		5/8: clear path 3 blocks high, place slabs/torches
4368
		6/7: build alternating ice road / create 3 block high air gap (2 over water)
4369
	]]
4370
	local oTurn = "R"
4371
	if R.side == "R" then
4372
		oTurn = "L"
4373
	end
4374
	local lib = {}
4375
	
4376
	function lib.convertTowpath(R)
4377
		-- only used to convert existing water canal, so assume towpath already present
4378
		-- starting position 1 block above existing towpath
4379
		for i = 1, R.length do
4380
			if turtle.detectDown() then							-- eg existing torch
4381
				T:dig("down")
4382
			end
4383
			local placeSlab = true
4384
			if R.torchInterval > 0 then							-- place torches
4385
				if i == 1 or i % R.torchInterval == 0 then		-- ready to place torch
4386
					--go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
4387
					T:go("C2x0", false, 0, false, R.useBlockType)-- place solid block below
4388
					T:go("F1R2x0")
4389
					T:place("torch", 0, "forward")				-- place torch, move forward
4390
					T:turnRight(2)								-- turn round
4391
					placeSlab = false
4392
				end
4393
			end
4394
			if placeSlab then
4395
				T:dig("up")
4396
				if not T:place("slab", 0, "down") then			-- break if out of slabs
4397
					break
4398
				end
4399
				if i < R.length then
4400
					T:forward(1)								-- move forward
4401
				end
4402
			end
4403
		end
4404
	end
4405
	
4406
	function lib.iceCanalTowpath(R)
4407
		-- move forward placing slabs along the way. If existing water canal, ceiling will be raised by 1 block
4408
		local torchInterval = 0
4409
		local placeIce = true
4410
		for i = 1, R.length do
4411
			local addTorch = false
4412
			if R.torchInterval > 0 then
4413
				if i == 1 then addTorch = true end
4414
				if torchInterval >= R.torchInterval then
4415
					addTorch = true
4416
					torchInterval = 0
4417
				end
4418
			end
4419
			lib.iceCanalEdge(R, addTorch, i, placeIce)
4420
			torchInterval = torchInterval + 1
4421
			placeIce = not placeIce
4422
		end
4423
		T:go(oTurn.."1")
4424
	end
4425
	
4426
	function lib.iceCanalEdge(R, addTorch, numBlocks, placeIce)
4427
		-- starting position facing canal side
4428
		local blockType = T:getBlockType("forward")			-- ? air / slab / other
4429
		local isWater, isSource, isIce = T:isWater("down")	-- water / ice below
4430
		if blockType:find("slab") == nil then 				-- add slab
4431
			if addTorch then								-- check if torch needed
4432
				-- T:place(blockType, damageNo, direction, leaveExisting, signText)
4433
				if not T:place("stone", -1, "forward", false) then
4434
					T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
4435
				end
4436
				T:go("U1x1 U1x1 D1")	 				-- water level to 2 above water level
4437
				if T:getItemSlot("minecraft:torch", -1) > 0 then
4438
					T:place("torch", -1, "forward", false)
4439
				end
4440
				T:down(1)								-- back to above water level
4441
				if not isIce then						-- break block below if NOT ice
4442
					T:dig("down")
4443
				end
4444
			else
4445
				if not T:place("slab", -1, "forward", false) then
4446
					T:checkInventoryForItem({"slab"}, {R.length - numBlocks}, true)
4447
				end
4448
				if not isSource then					-- NOT on water, so dig above
4449
					T:go("U1x1 U1x1 D2")
4450
				end
4451
				if not isIce and not isSource then
4452
					T:dig("down")
4453
				end
4454
			end
4455
		else -- slab already on side
4456
			if addTorch then							-- check if torch needed
4457
				T:dig("forward")
4458
				if not T:place("stone", -1, "forward", false) then
4459
					T:checkInventoryForItem({"stone"}, {math.ceil(R.length / R.torchInterval)}, true)
4460
				end
4461
				T:go("U1x1 U1x1 D1")	 				-- water level to 2 above water level
4462
				if T:getItemSlot("minecraft:torch", -1) > 0 then
4463
					T:place("torch", -1, "forward", false)
4464
				end
4465
				T:down(1)								-- back to above water level
4466
				if not isIce then						-- break block below if NOT ice
4467
					T:dig("down")
4468
				end
4469
			end
4470
		end
4471
		if R.data == "ice" and placeIce and not isIce then -- R.data = "ice", placeIce = true, not already ice present
4472-
		T:place("sign", "forward")
4472+
			T:place("ice", -1, "down", true)
4473
		end
4474
		if numBlocks < R.length then
4475
			T:go(oTurn.."1F1"..R.side.."1")
4476
		end
4477
	end
4478
	
4479
	function lib.convertIcepath(length)
4480
		-- use only for placing ice to convert a water canal
4481
		-- place ice on alternate blocks until length reached or run out of ice
4482
		local placeIce = true
4483
		for i = 1, length do
4484
			if T:getBlockType("down"):find("ice") == nil then -- no ice below
4485
				T:dig("down") -- remove any existing block
4486
				if placeIce then
4487
					if not T:place("ice", -1, "down", true) then -- out of ice
4488
						break
4489
					end
4490
					if i == length - 1 then
4491
						break
4492
					end
4493
				end
4494
			else -- ice already below
4495
				placeIce = true
4496
			end
4497
			T:go("U1x0 D1F1")
4498
			placeIce = not placeIce -- reverse action
4499
		end
4500
	end
4501
	
4502
	function lib.convertToAir(length)
4503
		-- use only for converting a water canal. start at ground level
4504
		-- dig up/down/forward to clear space
4505
		for i = 1, length + 1 do
4506
			T:go("U1x0D1")
4507
			if i < length + 1 then
4508
				T:go("x2F1")
4509
			else
4510-
				T:place("stone", "up")
4510+
4511
			end
4512
		end
4513
	end
4514
	
4515
	function lib.initialise(R)
4516
		if R.subChoice == 1 or R.subChoice == 4 then		
4517
			local blockType = T:getBlockType("down")		-- ? at ground/water level or on top of existing slab
4518
			if blockType:find("slab") ~= nil then 			-- slab already present
4519
				T:go(oTurn.."1F1D1"..R.side.."2")			-- move right/left forward, down onto ice canal top, face canal wall
4520
			elseif blockType:find("torch") ~= nil then
4521
				T:go(oTurn.."1F1D2"..R.side.."2")			-- move right/left forward, down onto ice canal top, face canal wall
4522
			else											-- assume on ground / water level
4523
				T:go(oTurn.."1F1"..R.side.."2")				-- move right/left forward onto ice canal top, face canal wall
4524
			end
4525
		else
4526
			if T:isWater("forward") then 					-- player put turtle inside canal water
4527
				T:up(1)
4528
			end
4529
			T:go(R.side.."1")								-- face canal wall
4530
		end
4531
	end
4532
	
4533
	if R.length == 0 then R.length = 1024 end
4534
4535
	if R.subChoice <= 4  then								-- towpath 1,2,3,4
4536
		lib.initialise(R)									-- reposition
4537
		lib.iceCanalTowpath(R)								-- build towpath
4538
	elseif R.subChoice == 5 or R.subChoice == 8 then		-- assume placed on towpath
4539
		if T:getBlockType("down"):find("slab") ~= nil then 	-- slab already present
4540
			T:go("F1")
4541
		else
4542
			T:up(1)
4543
		end
4544
		lib.convertTowpath(R)
4545
	elseif R.subChoice == 6 or R.subChoice == 7 then	
4546
		if R.data == "ice" then							-- assume placed on existing ice or initial ice position
4547
			lib.convertIcepath(R.length)-- place ice
4548
		else											-- assume placed on empty path
4549
			lib.convertToAir(R.length)					-- clear 3 high area
4550
		end
4551
	end
4552
	
4553
	return {}
4554
end
4555
4556
local function createLadder(R) -- 12
4557
	-- createLadder(R.data ="bedrock", R.height = 70, R.depth = -48)
4558
	-- go(path, useTorch, torchInterval, leaveExisting)
4559
	-- place(blockType, damageNo, direction, leaveExisting)
4560
	local lib = {}
4561
	
4562
	function lib.placeLadder(direction, ledge, i, height)
4563
		-- 1 check both sides and behind
4564
		local fluid = false
4565
		local block = T:isWaterOrLava("forward", ledge)
4566
		if block:find("water") ~= nil or block:find("lava") ~= nil then
4567
			--[[ surround 2 block shaft with blocks ]]
4568
			T:go("R1C1 R1C1 R1C1 R1F1 L1C1 R1C1 R1C1 R1C1F1 R2C1 x1")
4569
		else
4570
			--[[ no water/lava so prepare ladder site]]
4571
			T:go("F1 L1C1 R1C1 R1C1 L1B1", false, 0, true)
4572
		end
4573
		if not T:place("ladder", -1, "forward", false) then
4574
			T:checkInventoryForItem({"ladder"}, {height - i}, false)
4575
		end
4576
		-- 3 check if ledge, torch
4577
		if ledge == 0 and i > 1 then -- place block above unless new ladder
4578
			T:place("common", -1, direction, false) -- any common block
4579
		elseif ledge == 1 then
4580
			T:place("minecraft:torch", -1, direction, false)
4581
		elseif ledge == 2 then
4582
			ledge = -1
4583
		end
4584
		
4585
		return ledge
4586
	end
4587
	
4588
	local retValue = {}
4589
	local ledge = 0
4590
	local height = math.abs(R.depth - R.height) --height of ladder
4591
	local blockType = T:getBlockType("forward")
4592
	if R.up then -- create ladder from current level to height specified
4593
		for i = 1, height do -- go up, place ladder as you go
4594
			ledge = lib.placeLadder("down", ledge, i, height) -- ladder placed forward, stone ledge for torch placed down
4595
			if i <  height then
4596
				T:up(1)
4597
				ledge = ledge + 1
4598
			end
4599
		end		
4600
	else -- R.down = true: ladder towards bedrock		
4601
		local success = true
4602
		local numBlocks, errorMsg = 0, ""
4603
		T:down(1)
4604
		for i = 1, height do -- go down, place ladder as you go
4605
			ledge = lib.placeLadder("up", ledge, i, heigt) -- ladder placed forward, stone torch placed up
4606
			--success, blocksMoved, errorMsg, blockType = clsTurtle.down(self, steps, getBlockType)
4607
			if i < height then
4608
				success, numBlocks, errorMsg, blockType = T:down(1, true) -- true = return blockType
4609
				ledge = ledge + 1
4610
			end
4611
			-- if looking for stronghold then check for stone_bricks 
4612
			if blockType:find("stone_bricks") ~= nil then
4613
				table.insert(retValue, "Stronghold discovered")
4614
				break -- stop descent at stronghold
4615-
		T:place(dirt, "forward", false) 					-- placed at end of potential water source, next to ladder
4615+
4616
		end
4617-
		T:place(dirt, "down", false) 						-- placed in ground, next to ladder
4617+
4618
		if R.data == "chamber" then -- user has chosen to build a chamber
4619
			table.insert(retValue, "Shelter constucted at level".. R.depth)
4620
			if blockType:find("bedrock") ~= nil then
4621
				T:findBedrockTop(0) -- test to check if on safe level immediately above tallest bedrock
4622
			end
4623
			-- In shaft, facing start direction, on lowest safe level
4624
			-- create a square space round shaft base, end facing original shaft, 1 space back
4625
			T:go("L1n1 R1n3 R1n2 R1n3 R1n1", false, 0, true)
4626
			T:go("U1Q1 R1Q3 R1Q2 R1Q3 R1Q1 R1D1", false, 0, true)
4627
		end
4628
	end
4629
	
4630
	return retValue
4631
end
4632
4633
local function createLadderToWater(R) -- 86
4634
	-- go down to water/lava with alternaate solid/open layers
4635
	-- create a working area at the base
4636
	-- Return to surface facing towards player placing ladders
4637
	local inAir = true
4638
	local numBlocks, errorMsg = 0, ""
4639
	local height = 2
4640
	local blockType = T:getBlockType("down")
4641
	if blockType ~= "" then -- not over air
4642
		T:forward(1)
4643
	end
4644
	T:go("R2D1") -- face player, go down 2
4645
	while inAir do --success = false when hits water/lava
4646
		blockType = T:isWaterOrLava("down")
4647
		if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
4648
			inAir = false
4649
		end
4650
		T:go("C1R1 C1R2 C1R1", false, 0, false)	-- surround front  and sides with cobble
4651
		if inAir then
4652
			T:down(1)
4653
			height = height + 1
4654
		end
4655
		T:place("ladder", 0, "up")
4656
	end
4657
	-- In shaft, facing opposite start direction, on water/lava, ladders above
4658
	T:go("C2", false, 0, false)
4659
	utils.goBack(1)
4660
	T:place("ladder", 0, "forward")
4661
	T:up(3)
4662
	height = height - 3
4663
	for i = 1, height do
4664
		if i < height then
4665
			T:go("C2U1", false, 0, false)
4666
		else
4667
			T:go("C2", false, 0, false)
4668
		end
4669
	end
4670
4671
	return {}
4672-
		T:place("soul_sand", "down", false)
4672+
4673
4674
local function createMine() -- 11
4675
	-- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
4676
	T:clear()	
4677
	T:go("m32U1R2M16", true, 8, true) -- mine ground level, go up, reverse and mine ceiling to mid-point
4678
	T:go("U2D2") -- create space for chest
4679
	T:place("minecraft:chest", -1, "up", false)
4680
	T:emptyTrash("up")
4681
	T:go("D1R1m16U1R2M16", true, 8, true) -- mine floor/ceiling of right side branch
4682
	T:emptyTrash("up")
4683
	T:go("D1m16U1R2M16", true, 8, true) -- mine floor/ceiling of left side branch
4684
	T:emptyTrash("up")
4685
	T:go("L1M15F1R1D1", true, 8, true) -- mine ceiling of entry corridor, turn right
4686
	T:go("F1x0 F1x0 n14 R1n32 R1n32 R1n32 R1n14 F1x0 F1U1", true, 8, true)-- mine floor of 36 x 36 square corridor
4687
	T:go("R1F16R2") --return to centre
4688
	T:emptyTrash("up")
4689
	T:go("F16R1") --return to entry shaft
4690
	T:go("F2Q14R1Q32R1Q32R1Q32R1Q14F2R1", true, 8, true) --mine ceiling of 36x36 square corridor. return to entry shaft + 1
4691
	T:go("F16R2") --return to centre
4692
	T:emptyTrash("up")
4693
	-- get rid of any remaining torches
4694
	while T:getItemSlot("minecraft:torch", -1) > 0 do
4695
		turtle.select(T:getItemSlot("minecraft:torch", -1))
4696
		turtle.dropUp()
4697
	end
4698
	T:go("F16R1F1R1") --return to shaft + 1
4699
	for i = 1, 8 do
4700
		T:go("N32L1F1L1", true, 8, true)
4701
		T:go("N16L1F"..(i * 2).."R2", true, 8, true)
4702
		T:emptyTrash("up")
4703
		if i < 8 then
4704
			T:go("F"..(i * 2).."L1N16R1F1R1", true, 8, true)
4705
		else
4706
			T:go("F"..(i * 2).."L1N16L1", true, 8, true)
4707
		end
4708
	end
4709
	T:go("F17L1") -- close gap in wall, return to ladder + 1
4710
	for i = 1, 8 do
4711
		T:go("N32R1F1R1", true, 8, true)
4712
		T:go("N16R1F"..(i * 2).."R2", true, 8, true)
4713
		T:emptyTrash("up")
4714
		if i < 8 then
4715
			T:go("F"..(i * 2).."R1N16L1F1L1", true, 8, true)
4716
		else
4717
			T:go("F"..(i * 2).."R1N16R1", true, 8, true)
4718
		end
4719
	end
4720
	T:go("F16R1")
4721
	T:clear()
4722
	return{"Mining operation complete"}
4723
end
4724
4725
local function createMobFarmCube(R) -- 61, 62
4726
	--[[
4727
	Part 1 / 3 Mob Spawner Farm
4728
	blaze = true: blaze spawner in nether
4729
		R.subChoice is set to:
4730
		1 = on top of spawner
4731
		2 = line of sight
4732
		3 = room below
4733
	blaze = false: overworld mob spawner
4734
		R.subChoice is set to:
4735
		1 = on top of spawner
4736
		2 = bottom left corner
4737
		3 = top left corner
4738
		4 = bottom right, corner
4739
		5 = top right corner
4740
		R.width / R.length set by player (external size)
4741
	]]
4742
	local blaze = true
4743
	if R.data == "spawner" or R.data == "chest" then
4744
		blaze = false
4745
	end
4746
	local continue = false
4747
	if R.data == "restart" then
4748
		continue = true
4749
	end
4750
	R.direction = "clock"		-- starting on right side
4751
	if not blaze then
4752
		print("R.width: "..tostring(R.width))
4753
		R.width = R.width - 2		-- internal width
4754
		R.length = R.length - 2		-- internal length
4755
		
4756
		if R.subChoice == 2 or R.subChoice == 3 then
4757
			R.direction = "anticlock"
4758
		end
4759
	end
4760
	-- R.data allows for 2-part operation "blaze" = main cube, "restart" = killzone
4761
	T:clear()
4762
	local lib = {}
4763
	
4764
	function lib.floorSection(length)
4765
		for i = 1, length do		-- starts on top left corner
4766
			T:go("C2")
4767
			if i < length then
4768
				T:forward(1)
4769
			else
4770
				T:go("R1F1")
4771
			end
4772
		end
4773
	end
4774
	
4775
	function lib.wallSection(blaze)
4776
		blaze = blaze or false
4777
		for i = 1, 4 do
4778
			for j = 1, 11 do
4779
				if blaze then
4780
					T:place("slab", 0, "up", false)
4781
					T:go("C2", false, 0, false)
4782
				else
4783
					T:go("C0C2", false, 0, false)
4784-
			T:place("stone", "forward", false)
4784+
4785
				if j < 11 then
4786
					T:forward(1)
4787-
			T:place("stone", "forward", false)
4787+
4788
				else
4789
					T:turnRight(1)
4790
				end
4791
			end
4792
		end
4793
	end
4794
	
4795
	function lib.ceiling(blaze)
4796
		-- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
4797
		-- all outer walls complete, now for remaining 9x9 ceiling
4798
		blaze = blaze or false
4799
		for i = 1, 9 do
4800
			for j = 1, 9 do
4801
				if blaze then
4802
					T:place("slab", 0, "up", false)
4803
					T:dig("down")
4804
				else
4805
					T:go("C0x2", false, 0, true)
4806
				end
4807
				if j < 9 then
4808
					T:forward(1)
4809
				else	-- end of length
4810
					local place = false
4811
					if i%2 == 1 then -- odd numbers 1,3,5,7,9
4812
						if i < 9 then
4813-
						T:place("minecraft:torch", "down")
4813+
4814
							T:go("R1F1 R1")
4815
						end
4816
					else
4817
						place = true
4818
						T:go("L1F1 L1")
4819
					end
4820
					if place then
4821
						if blaze then
4822
							T:place("slab", 0, "up", false)
4823
							T:dig("down")
4824
						else
4825
							T:go("C0x2", false, 0, true)
4826
						end
4827
					end
4828
				end
4829
			end
4830
		end
4831
	end
4832
	
4833
	function lib.clearWall(length)
4834
		for i = 1, 4 do
4835
			for j = 1, length do 
4836
				if j < length then
4837
					T:go("x0x2F1")
4838
				else
4839
					T:go("x0x2R1")
4840
				end
4841
			end
4842
		end
4843
	end
4844
	
4845
	function lib.isSpawner()
4846
		local blockType = T:getBlockType("down")
4847
		if blockType:find("spawner") ~= nil then
4848
			return true, "top"
4849
		end
4850
		blockType = T:getBlockType("up")
4851
		if blockType:find("spawner") ~= nil then
4852
			return true, "bottom"
4853
		end
4854
		blockType = T:getBlockType("forward")
4855
		if blockType:find("spawner") ~= nil then
4856
			return true, "forward"
4857
		end
4858
		return false, ""
4859
	end
4860
	
4861
	function lib.placeFloor(width, length, blockType)
4862
		-- T:place(blockType, damageNo, direction, leaveExisting, signText)
4863
		for i = 1, width do				
4864
			for j = 1, length do
4865
				T:place(blockType, -1, "down", false)
4866
				if j < length then
4867
					T:forward(1)
4868
				else
4869
					if i%2 == 1 then -- odd numbers 1,3,5,7,9
4870
						if i < width then
4871
							T:go("R1F1R1", false, 0, true)
4872
						end
4873
					else
4874
						T:go("L1F1L1", false, 0, true)
4875
					end
4876
				end
4877
			end
4878
		end
4879
	end
4880
	
4881
	function lib.searchStrip(distance)
4882
		--go forward until hit either a wall or a chest
4883
		local blocks = 1
4884
		print("Searching strip, distance = "..distance)
4885
		while blocks < distance do --max travel is external width/length
4886
			if turtle.forward() then
4887
				blocks = blocks + 1
4888
			else
4889
				print("Checking for chest")
4890
				if lib.isChest("forward") then
4891
					if turtle.forward() then
4892
						blocks = blocks + 1
4893
					end
4894
				else
4895
					break
4896
				end
4897
			end
4898
		end
4899
	end
4900
	
4901
	function lib.findChests(R)
4902
		for i = 1, 4 do
4903
			print("Searching wall "..i)
4904
			if i == 1 or i == 3 then
4905
				lib.searchStrip(R.width) 	-- find and empty chests along width
4906
			else
4907
				lib.searchStrip(R.length) 	-- find and empty chests along length
4908
			end
4909
			if R.direction == "clock" then
4910
				T:turnRight(1)
4911
			else
4912
				T:turnLeft(1)
4913-
		T:place("minecraft:ladder", "down")
4913+
4914
		end
4915
4916
		-- checked all walls
4917
		T:go("F".. math.floor(R.width / 2)) -- now at mid-dungeon, next to wall
4918
		if T:getItemSlot("chest") > 0 then
4919
			if R.direction == "clock" then
4920
				T:turnLeft(1)
4921-
	T:place("minecraft:obsidian", "down")
4921+
4922
				T:turnRight(1)
4923
			end
4924
			-- now at mid-dungeon, facing wall
4925
			-- deposit chest outside the dungeon
4926
			while turtle.back() do end -- backing spawner
4927
			T:go("x0 F1x0 F1x0 F1x0 F1x0 F1x0 F1x0 x1x2")
4928
			-- place(self, blockType, damageNo, direction, leaveExisting, signText)
4929
			T:place("chest", -1, "forward", false)
4930
			-- empty out all except stone and slab
4931
			T:emptyInventorySelection("forward", {"cobble", "tuff", "slab", "granite", "andesite", "diorite" }, {0,0,0,0,0,0})
4932
			T:turnLeft(2)
4933
			T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements")
4934
			while turtle.forward() do end -- facing spawner
4935
		else
4936
			if R.direction == "clock" then
4937
				T:turnRight(1)
4938
			else
4939
				T:turnLeft(1)
4940
			end
4941
		end -- now at mid-dungeon, facing spawner
4942
	end
4943
	
4944
	function lib.enterDungeon(R)
4945
		--[[ find and empty any chests, return to dungeon wall ]]
4946
		print("Entering dungeon")
4947
		local blockType = T:getBlockType("forward")
4948
		if blockType == "" then -- nothing in front.Error
4949
			return false, "No block in front: Check position."
4950
		else -- attempt entry into dungeon wall
4951
			if R.subChoice == 2 then 		-- bottom left
4952
				T:go("R1F1 L1U2 F2R1")
4953
			elseif R.subChoice == 3 then	-- top left
4954
				T:go("R1F1 L1D1 F2R1")
4955
			elseif R.subChoice == 4 then	-- bottom right
4956
				T:go("L1F1 R1U2 F2L1")
4957
			elseif R.subChoice == 5 then	-- top right
4958
				T:go("L1F1 R1D1 F2L1")
4959
			end
4960
			while turtle.down() do end -- either on floor or chest
4961
			if lib.isChest("down") then
4962
				turtle.down()
4963
			end
4964
			print("Searching for chests")
4965
			lib.findChests(R)	-- go round inside walls  emptying chests. Finish mid-wall
4966
		end
4967
		return true, ""-- success, message
4968
	end
4969
	
4970
	function lib.isChest(direction)
4971
		direction = direction or "forward"
4972
		local blockType = T:getBlockType(direction)
4973
		if blockType:find("chest") ~= nil then -- chest found. early stages so empty and break it
4974
			print("Chest found")
4975
			while T:suck(direction) do end
4976
			T:dig(direction, false) -- false prevents checking for chests
4977
			return true
4978
		elseif blockType:find("torch") ~= nil then 
4979
			print("Torch found")
4980
			T:dig(direction, false) -- false prevents checking for chests
4981
			return true
4982
		end
4983
		return false
4984
	end
4985
		
4986
	function lib.findSpawner(blaze)
4987
		local moves  = 0
4988
		local quit = false
4989
		-- assume turtle placed on centre of inside spawner wall in front of spawner
4990
		-- or as close as possible in Nether
4991
		print("Checking if next to spawner")
4992
		local found, position = lib.isSpawner() -- true/false, top/bottom/nil
4993
		if not found then -- move forward towards spawner
4994
			print("Not close to spawner")
4995
			while turtle.forward() and not quit do
4996
				moves = moves + 1
4997
				if moves > 16 then
4998
					quit = true
4999
				end
5000
			end
5001
			found, position = lib.isSpawner() -- true/false, top/bottom/nil
5002
			if not found then
5003
				if blaze then -- could be behind a wall
5004
					print("Assuming blaze spawner behind a wall")
5005
					T:forward(1)
5006
					moves = moves + 1
5007
					while turtle.forward() and not quit do 
5008
						moves = moves + 1
5009
						if moves > 16 then
5010
							quit = true
5011
						end
5012
					end
5013
					found, position = lib.isSpawner() -- true/false, top/bottom/nil
5014
					if not found then
5015
						T:go("R2F"..moves + 2 .."R2")
5016
					end
5017
				end
5018
			end
5019
		end
5020
		
5021
		return found, position
5022-
		T:place("fence", "down", false)
5022+
5023
	
5024-
		T:place(preferredBlock, "down", false)
5024+
5025
	if not continue then -- new mob cube either dungeon or blaze
5026-
		T:place(preferredBlock, "down", false)
5026+
5027
		-- determine spawner position level 4, move to top of spawner (level 6)
5028-
		T:place(preferredBlock, "down", false)
5028+
5029
		local found, position = lib.isSpawner() -- already on spawner?
5030
		if blaze then 
5031
			if not found then -- away from spawner
5032-
		T:place(preferredBlock, "down", false)
5032+
5033
					T:go("U5")
5034-
		T:place(preferredBlock, "down", false)
5034+
5035
				found, position = lib.findSpawner(blaze)
5036
			end
5037
		else -- go to bottom of dungeon and empty chests
5038-
		T:place("sign", "forward", false, message)
5038+
5039
				local success, message = lib.enterDungeon(R)
5040
				if not success then
5041
					return {message}
5042
				end
5043
				found, position = lib.findSpawner(blaze) -- is spawner in front / above / below?
5044
			end 
5045
		end
5046
		
5047
		if found then -- true: move to correct starting position
5048
			--[[
5049
			1 |c|c|c|c|c|c|c|c|c|c|c|
5050
			2 |w| | | | | | | | | |w|
5051
			3 |w| | | | | | | | | |w|
5052
			4 |w| | | | | | | | | |w|
5053
			5 |w| | | | | | | | | |w|
5054
			6 |w| | | | |s| | | | |w|
5055
			7 |w| | | | | | | | | |w|
5056
			8 |w| | | | | | | | | |w|
5057
			9 |w| | | | | | | | | |w|
5058
		   10 |w| | | | | | | | | |w| exit level for overworld
5059
		   11 |f|f|f|f|f|f|f|f|f|f|f|
5060
		   12 |f|f|f|f|f|f|f|f|f|f|f| sub floor for overworld
5061
			   1 2 3 4 5 6 7 8 9 1 1
5062
			                     0 1
5063
			]]
5064
			-- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
5065
			if position == "bottom" then
5066
				T:go("B1U2F1")
5067
			elseif position == "forward" then
5068
				T:go("U1F1")
5069
			end
5070
			
5071
			T:up(1)
5072
			T:place("slab", -1, "down", true) 				-- place slab on top T:place(blockType, damageNo, direction, leaveExisting)
5073
			-- go up 2 blocks, forward 5, right, forward 5, right
5074
			T:go("U2F5 R1F5 R1") 							-- Level 2: now placed 1 below ceiling inside wall, top right corner of new dungeon
5075
			lib.wallSection(blaze) 							-- fix layers 1, 2, 3 including ceiling margin turtle at Level 2			
5076
			T:go("F1R2 C1L1 F1R2 C1R1", false, 0, false)	-- exit wall, repair behind, still Level 2
5077
			lib.ceiling(blaze)								-- fix ceiling, end opposite corner to start
5078
			T:go("R2D3")									-- clear the inner walls inside original dungeon
5079
			lib.clearWall(9)								-- clear the 9 x 9 area around the spawner
5080
			T:go("F1R1F1L1")
5081
			lib.clearWall(7)								-- clear the 7 x 7 area around the spawner
5082
			T:go("F1R1F1L1")
5083
			lib.clearWall(5)								-- clear the 5 x 5 area around the spawner. Also needed for cave spiders
5084
			T:go("R2F1R1F1R1")
5085
			T:go("F7R1 F8L1F1R2", false, 0, false)			-- return from ceiling, enter wall below previous section: Level 5
5086
			lib.wallSection() 								-- deal with areas from spawner level up (4,5,6). walls only	
5087
			T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8
5088
			clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 7,8,9
5089
			T:go("L1F1 L1F1L2", false, 0, false) 			-- go inside wall sectio, ready for next wall section
5090
			lib.wallSection() 								-- deal with walls on levels 7,8,9
5091
			T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 4 below original floor: Level 11
5092
			--print("Check: about to clear 3 floors 3 below spawner") read()
5093
			clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 10,11,12 
5094
			
5095-
					T:place(preferredBlock, "down", false)
5095+
5096
				T:go("L1F1 L1F1L2", false, 0, false) 			-- ready for next wall section
5097
				lib.wallSection() 								-- wall on layers 10,11,12
5098
				T:go("F1R2 C1L1 F1R2 C1R1 D3", false, 0, false) -- exit wall, repair behind, embed 1 below original floor: Level 8
5099
				clearRectangle({width = 9, length = 9, up = true, down = true}) -- clear levels 13, 14, 15
5100
			end
5101
			
5102
			T:go("L1F1L1F1L2", false, 0, false) -- ready for next wall section
5103
			--print("Check: level 11, 5 north, 5 east")
5104
			--read()
5105
			lib.wallSection() 	-- wall on layers 10,11,12 or 12,13,14 if blaze
5106
			T:go("F1R1 F1R2 C1R1 U1", false, 0, false) -- exit wall, repair behind: Level 10, facing entry point top right corner
5107
			T:down(1)
5108
			if blaze then
5109
				lib.placeFloor(9, 9, brick) 			-- place brick floor on level 14
5110
				T:go("L1F4 R1F2 U4")					-- ends facing out to lower chamber ?below staircase
5111
				-- now needs to build killzone
5112
			else
5113
				lib.placeFloor(9, 9, "stone") 			-- ends facing wall on entrance side
5114
				T:go("U1R2")
5115
				lib.placeFloor(9, 9, "stone") 			-- ends facing wall on opposite side
5116
				-- return to mid-point front
5117
				T:go("R2F8 R1F4 L1F2")					-- exit at bottom of dungeon
5118
				T:go("x1U1 x1U1 x1U1 x1D3 R2") 			-- rise to chest, then return ready for next stage	
5119-
			if not T:place("fence", "down", false) then-- first side
5119+
5120-
				T:place(preferredBlock, "down", false)
5120+
5121
		else
5122
			return
5123
			{
5124
				"Spawner not found. Place me on top,",
5125
				"immediately below, or facing it.",
5126
				"\nEnter to quit"
5127
			}
5128
		end
5129
	end
5130
	if continue then
5131
		T:clear()
5132
		local text =
5133
[[~yellow~Items required to continue:
5134
5135
~lightGray~slabs            81
5136
~orange~nether bricks    88
5137
~yellow~lava buckets     4
5138
~brown~chest / barrel   1
5139
~gray~hopper           1      
5140
5141
~red~WARNING ~yellow~Inventory ejects items if you
5142
continue! ~orange~(Choose at next menu.)
5143
5144
~white~Next -> Enter]]
5145
		menu.colourText(nil, text, true)
5146-
		T:place("minecraft:soul_sand", "down", false) -- over block 1 of water source
5146+
5147
		pp.itemColours = {colors.red, colors.lime}
5148
		local choice = menu.new("Choose your option", {"Continue with build", "Re-start later"}, pp, "Type number + Enter") -- 1 = continue, 2= quit
5149
		if choice == 1 then
5150
			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
5151
			if choice == 1 then
5152
				T:emptyInventory("down")
5153
			else
5154
				T:emptyInventory("up")
5155
			end
5156
		else
5157
			return {"Blaze spawner partial build halted"}
5158
		end
5159
		
5160
		--clsTurtle.getItemSlot(self, item, useDamage): return slotData.lastSlot, slotData.leastModifier, total, slotData
5161
		T:checkInventoryForItem({brick}, {88})
5162
		T:checkInventoryForItem({"slab"}, {81})
5163
		T:checkInventoryForItem({"lava"}, {4})
5164
		T:checkInventoryForItem({"sign"}, {1})
5165
		T:checkInventoryForItem({"hopper"}, {1})
5166
		T:checkInventoryForItem({"chest", "barrel"}, {1, 1})
5167
		print("Stand clear. Starting in 2 secs")
5168-
				T:place("door", "forward", false)
5168+
5169
		-- place upper floor and slabs under it
5170
		T:go("R2D4F2 L1F4 R1U4")	
5171
		lib.placeFloor(9, 9, brick) 			-- place brick floor on level 10
5172
		T:down(2)
5173
		T:place(brick, 0, "up")
5174
		T:go("D1R2")
5175-
			T:place(preferredBlock, "down", false)
5175+
5176
		
5177
		-- place lava
5178
		T:go("L1F4 L1F4 U4")					-- through hole in ceiling
5179
		T:go("F4 L1F4 R2")
5180
		for i = 1, 4 do
5181
			T:place("lava", 0 , "down")
5182-
				T:place("door", "forward", false)
5182+
5183
		end
5184
		T:go("F4 R1F4 D2 F1 R2")
5185
		-- place sign and repair above
5186
		T:dig("forward")
5187
		T:place("sign", 0, true, "")
5188
		T:down(1)
5189
		T:place(brick, 0 , "up")
5190
		T:forward(1)
5191
		-- place blocks under exit hole
5192
		for i = 1, 4 do
5193
			T:place(brick, 0 , "forward")
5194
			T:turnRight(1)
5195
		end
5196
		-- place chest and hopper
5197
		
5198
		T:go("D2x2")
5199
		if not T:place("chest", 0, "down") then
5200
			T:place("barrel", 0, "down")
5201
		end
5202
		T:up(1)
5203
		T:place("hopper", 0, "down")
5204
		utils.goBack(1)
5205
		T:place("slab", 0, "forward")
5206
		T:go("R2F5U3")-- return to starting point and create entrance
5207
	end
5208
	return {}
5209
end
5210
5211
local function floodMobFarm(R) -- 63
5212
	--[[Part 2 / 3 Mob Spawner Farm turtle on floor, pointing towards water source wall, single hole]]
5213
	local lib ={}
5214
	
5215
	function lib.setPosition(addWater)
5216
		local width = 0
5217
		while turtle.forward() do end					-- move forward until hit wall
5218
		T:go("U1L1")
5219
		while turtle.forward() do end					-- move forward until hit left wall
5220-
		T:place("fence", "down", false)							-- fence centre of bottom side layer 22
5220+
5221
			T:placeWater("down") 			 			-- place water down
5222
		end
5223-
		T:place("ladder", "forward", false)
5223+
5224
		while turtle.forward() do
5225-
		T:place("ladder", "forward", false)
5225+
5226
		end			-- go forward 7
5227
		if addWater then								-- back 1
5228
			T:placeWater("down") 						-- place water					
5229
		end
5230
		T:go("L2F".. math.floor(width / 2) .."L1")		-- turn round, go forward 3 (centre of wall), turn left
5231
	end
5232
5233
	function lib.digFloor()
5234-
		T:place("minecraft:soul_sand", "down", false) 
5234+
5235
		
5236
		T:turnLeft(1)									-- left turn, go back into right side, facing left
5237
		utils.goBack(1)
5238
		T:go("x2 F1x2 F1x2 R1F1")						-- go right to left dig 3 blocks, forward on left side
5239-
		T:place("ladder", "down", false)
5239+
5240
		T:turnRight(1)									-- right turn, go back into left side, facing right
5241-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
5241+
5242
		T:go("x2 F1x2 F1x2 F1x2 F1x2 L1F1")				-- go left to right dig 5 blocks, forward on right side
5243
		
5244-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
5244+
5245
		utils.goBack(1)
5246
		T:go("x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 R1F1")	-- go right to left dig 7 blocks, forward on left side
5247-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
5247+
5248
		T:turnRight(1)									-- right turn, go back into left side, facing right
5249
		utils.goBack(1)
5250
		T:go("x2 F1x2 F1x2 F1x2 F1x2 F1x2  F1x2  F1x2  F1x2 L1")	-- go left to right dig 5 blocks, face forward on right side
5251
	end
5252-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
5252+
5253
	lib.setPosition(false)					-- move to back of cube and verify position
5254
	if R.subChoice == 1 then
5255
		T:forward(3)						-- forward 4 (centre of chamber)
5256
	else
5257
		T:forward(2)						-- forward 3
5258
	end
5259
	T:down(1)
5260
	lib.digFloor()
5261
	if R.subChoice == 1 then		
5262
		T:go("D1F1 L1F8")
5263
		utils.goBack(4)
5264
		T:go("L1U1")
5265
		lib.setPosition(true)				-- place water sources
5266
		T:go("F8D2")
5267
		-- go down 2, check floor, up 1, place fence
5268
		T:go("D2C2U1", false, 0, true)
5269
		T:place("fence", -1, "down", false)
5270
		T:go("F1D1C2U1", false, 0, true)
5271
		T:place("fence", -1, "down", false)
5272
		T:go("F1U1R2", false, 0, true)
5273
		T:go("F1R1U1")
5274
		T:place("sign", -1, "down", false)
5275
		T:go("U1C0D1")
5276
		T:place("slab", -1, "up", false)
5277
		T:go("R2F1R2")
5278
		T:place("sign", -1, "forward", false)
5279
		T:go("R1F1R2C1R1F1D1L1") --sitting on soul sand/dirt facing spawner
5280
		if not T:place("minecraft:soul_sand", -1, "down", false) then
5281
			T:place("minecraft:dirt", -1, "down", false)
5282
		end
5283
	else
5284-
			T:place("fence", "up", false)
5284+
5285
		T:go("R1F1 R1F8")
5286
		utils.goBack(4)
5287
		T:go("R1U1")
5288
		lib.setPosition(true)		-- place water sources
5289
		T:go("F8D2 F1C2C0 F1")		-- exit leaving single hole in wall, facing away from spawner
5290
	end
5291
	
5292
	return {}
5293
end
5294
5295
local function createMobBubbleLift(R) -- 64
5296
	-- Part 3 / 3 Mob Spawner Farm
5297
	-- R.subChoice = 1 or 2 (left/right)
5298
	local lib = {}
5299
	
5300
	function lib.initialise()
5301
		local blockType = T:getBlockType("down")
5302
		if blockType ~= "minecraft:soul_sand" then
5303
			T:dig("down")
5304
			if not T:place("minecraft:soul_sand", -1, "down", false) then
5305
				return {"Unable to find or place soulsand."}
5306
			end
5307
		end
5308
		-- check facing sign, rotate if not
5309
		blockType = T:getBlockType("forward")
5310
		local turns = 0
5311
		while blockType:find("sign") == nil do
5312
			T:turnRight(1)
5313
			turns = turns + 1
5314
			if turns == 4 then
5315
				return {"Unable to find sign."}
5316-
local function createFarmNetworkStorage(R, withStorage, removeLegacy)
5316+
5317-
	removeLegacy = removeLegacy or false
5317+
5318-
	-- new or converted farm will have:
5318+
5319-
	-- 2 modems, 1 barrel per plot
5319+
5320-
	-- primary plot and storage needs 1 modem, 1 barrel, 8 chests
5320+
5321
	
5322
	function lib.createWaterSource(oTurn)
5323-
	function lib.createBasement(R, up, down, width, length)
5323+
5324-
		-- start facing lower left
5324+
5325-
		R.up = up
5325+
5326-
		R.down = down
5326+
5327-
		R.width = width
5327+
5328-
		R.length = length
5328+
5329-
		clearRectangle(R)	-- dig 10 x 10 x 2 area, return to starting position
5329+
5330-
		-- add network cable, modems and chests
5330+
5331
		T:go("R2F1") 				-- face column move to middle
5332
		T:placeWater("forward")
5333-
	function lib.placeNetwork(count, pattern)
5333+
5334
		T:placeWater("forward")
5335-
			T:place("computercraft:cable", "up", true)
5335+
5336-
			if i < count then
5336+
5337-
				T:go(pattern)
5337+
5338
	function lib.goToWater(moves)
5339
		T:down(moves)
5340
		T:getWater("down")
5341
		sleep(0.1)
5342-
	-- called when starting at lower left side of plot, facing crops
5342+
5343-
	if removeLegacy then
5343+
5344
	
5345-
		while turtle.suckDown() do end
5345+
5346-
		--T:dig("down", false)	-- do not bypass chests
5346+
5347-
		turtle.digDown()
5347+
5348-
		T:place("dirt", "down")
5348+
5349-
		T:go("R2F1")
5349+
5350-
		while turtle.suck() do end
5350+
			T:place("chest", 0, "down")
5351-
		T:go("F1L1 F1U1 R2")	-- remove barrel/wall or double chest. face tree
5351+
5352-
		T:place("stone", "down")
5352+
5353
			T:place("chest", 0, "down")
5354-
		T:place("modem", "down")
5354+
5355-
		-- could be tree/sapling in front
5355+
5356
			T:go("D1x1")
5357-
		if T:getBlockType("down") == "minecraft:dirt" then
5357+
			T:place("hopper", 0, "forward")
5358-
			T:place("barrel", "down")
5358+
5359-
			T:go("U1x0")
5359+
5360-
			T:place("dirt", "up")
5360+
5361-
			T:go("B1U2")
5361+
5362-
			if T:getBlockType("forward"):find("log") ~= nil then
5362+
5363-
				T:place("sapling", "forward")
5363+
5364
		while turtle.detect() do
5365-
			T:go("D3F1 R1F1")
5365+
5366
			moves = moves + 1
5367-
			T:place("barrel", "down")
5367+
5368
5369
		return moves
5370-
		while turtle.suckDown() do end
5370+
5371-
		T:place("modem", "down")
5371+
5372-
		network.attachModem()
5372+
5373-
		T:go("F1x2 R2C2 F1L1 F1D1")
5373+
5374
		D.width  = 4
5375-
	T:go("L1D3") -- move below crop field, face N
5375+
5376-
	lib.createBasement(R, true, true, 10, 10)	-- ends facing N below water source
5376+
5377-
	T:go("U1 F9R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8") -- facing W below water source
5377+
5378-
	T:go("F1 R2C1 R1 F1L1 x0x2")	-- move to corner, face along front edge
5378+
5379-
	for c = 1, 4 do
5379+
5380-
		if c == 1 then
5380+
5381-
			lib.placeNetwork(12, "F1x0x2")
5381+
5382
5383-
			lib.placeNetwork(11, "F1x0x2")
5383+
5384
	end
5385-
		if c < 4 then
5385+
5386-
			T:go("L1F1 x0x2 L1C1R1")
5386+
5387
		for i = 1, 9 do -- fill in a solid block bar from bubble column for 8 spaces
5388
			T:go("F1C0C2 R1C1 R1C1 R1C1 R1C1")
5389-
	-- now in bottom left facing S
5389+
5390-
	T:go("L2F1R1")	-- under modem/netwok cable facing in
5390+
5391-
	for i = 1, 3 do
5391+
5392-
		T:go("L1C1 R1C1 R1C1 L1D1")
5392+
5393-
		T:place("computercraft:cable", "up", true)
5393+
5394
	end
5395-
	T:go("C1L1 C1L1 C1L1 C1L1 D1L1")-- ready for clearing rectangle up/down
5395+
5396-
	T:place("computercraft:cable", "up", true)
5396+
5397
	local oTurn = "L"
5398-
	T:place("computercraft:cable", "up", true)
5398+
5399-
	lib.createBasement(R, true, true, 11, 11)
5399+
5400
		oTurn = "R"
5401-
	lib.placeNetwork(11, "F1")
5401+
5402-
	T:go("R2F4 R1")
5402+
5403-
	lib.placeNetwork(11, "F1")
5403+
5404-
	T:go("L1F5 L1F9 R1D1 C1")	-- ready to make ladder column
5404+
5405
		return data 						-- eg {"Unable to find sign."}
5406-
		if i < 5 then
5406+
5407-
			T:go("U1C1")
5407+
5408
	for i = 1, 3 do		-- fill in back and one side, go up
5409
		T:go(turn.."1C1"..turn.."1C1"..turn.."1x1"..turn.."1U1", false, 0, true)
5410
	end
5411-
		T:place("ladder", "down")
5411+
5412
	local colHeight = 19
5413-
	if withStorage then
5413+
5414-
		T:go("R1F4 R1F3 D1x2")
5414+
5415-
		T:place("computercraft:cable", "down", true) --ready to build chest storage area
5415+
5416
	-- facing spawner 20 blocks up. move either left/right 8 blocks, repairing ceiling and sides
5417-
		utils.createStorage()
5417+
5418-
		T:go("U1R1 F5R1 F5U1 C2U1 R2")	-- end on plot starting position, facing crops
5418+
5419
	lib.mobTransporter()
5420-
		T:go("U1F2 L1F1 U1C2 U1L1")	-- end on plot starting position, facing crops
5420+
5421
	-- now create bubble column
5422
	T:down(colHeight + 2)
5423-
	return "Farm converted to network storage"
5423+
5424
	repeat
5425
		lib.goToWater(moves)	-- get water
5426
		moves = lib.up()
5427
		T:go("F1")
5428-
	-- extend "right" or "forward". only adds a single new farm.
5428+
5429
		T:go("U1C2")
5430
		T:placeWater("forward")
5431
		utils.goBack(1)
5432
		T:go("C1")
5433
		moves = moves + 1
5434
	until moves >= colHeight + 1
5435
	lib.goToWater(moves)	-- get water for last time
5436
	lib.up()				-- finishes above lower part of the transport bar
5437
	T:go("F2R2C1D1")		-- seal off bubble column
5438
	utils.goBack(1)
5439
	T:placeWater("forward")	-- place source on top of bubble column
5440
	utils.goBack(7)			-- over down shaft
5441
	T:down(1)				-- start shaft, facing bubble column
5442
	for i = 1, 17 do
5443-
				T:place("dirt", "forward", false)
5443+
5444
		T:go("R1C1 R1C1 R1C1 R1C1 D1", false, 0, true)
5445-
				--if not T:place("minecraft:crafting_table", "forward", false) then
5445+
5446-
				if T:place(storage, "forward", false) then
5446+
5447
	T:go("x0")
5448
	T:go(oTurn.."1C1".. turn.."1D1C2"..oTurn.."1C1"..turn.."1F1".. oTurn.."1F1"..oTurn.."1") -- facing end wall ready to place slabs
5449
	for i = 1, 6 do
5450
		T:place("slab", 0, "down")
5451-
					T:place("dirt", "forward", false) -- dirt if no storage available
5451+
5452
			T:go(oTurn.."1")
5453
		end
5454-
				T:place(R.useBlockType, "forward", false)
5454+
5455
		T:go("C1")
5456
	end
5457
	
5458
	T:go("D2F2"..turn.."1F5")
5459-
		T:placeWater("down")	-- ends facing same direction as started, over water source
5459+
5460
	T:go(turn.."1F1"..oTurn.."1") -- facing down mob channel floor
5461
	for i = 1, 5 do
5462
		T:go("C1")
5463
		utils.goBack(1)
5464
	end
5465
	T:go("C1"..turn.."1F1"..turn.."1F1")
5466-
				T:place("dirt", "down", false)
5466+
5467
		T:go("C2x0")
5468
		if i < 7 then
5469
			T:forward(1)
5470
		end
5471
	end
5472
	T:go("U3R2")
5473
	for i = 1, 7 do
5474-
				T:place("dirt", "down", false)
5474+
5475
	end
5476
	T:go("D3")
5477
	
5478
	lib.placeCollector(turn, oTurn) -- if hopper / chests present
5479
	
5480
	return {}
5481-
		if not T:place(storage, "down", false) then-- place barrel/chest below
5481+
5482-
			T:place(storageBackup, "down", false) -- place chest below
5482+
5483
local function createPlatform(R) -- 56
5484
	-- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
5485
	local forward = true
5486
	for w = 1, R.width do
5487-
	-- current position if extend == nil is on ground/farm level facing N
5487+
5488-
	-- if extend = "right", "front" above water source facing crops
5488+
5489-
	local numPlots = 0
5489+
5490
				T:dig("up")
5491
			end
5492
			if l < R.length then
5493
				T:forward(1)
5494
			end
5495-
			T:forward(11)
5495+
5496-
			numPlots = numPlots + 1
5496+
5497-
		until not utils.isStorage("down") -- on top of chest, barrel or modem
5497+
5498-
		T:go("R1F1R2")	-- move to front right corner of last plot on right side
5498+
5499-
		--T:go("R1U1 F1L1 F10L1") -- move to front right corner
5499+
5500
				else
5501
					T:go("R1F1 R1")
5502
				end
5503
			else
5504-
			T:forward(11)
5504+
5505-
			numPlots = numPlots + 1
5505+
5506-
		until not utils.isStorage("down") -- on top of chest, barrel or modem
5506+
5507-
		T:go("L1F1 R1x2")	-- could dig tree or sapling + block below
5507+
5508-
		--T:go("L2U1 F1R1 F10")
5508+
5509-
	elseif extend == "convertWithStorage" then
5509+
5510-
		-- convert normal (storage) primary plot farm to networked storage
5510+
5511-
		--T:turnLeft(1)	-- over water source, facing N
5511+
5512-
		local response = createFarmNetworkStorage(R, true, true)
5512+
5513-
		return {response}
5513+
5514-
	elseif extend == "convert" or extend == "convertWithStorage" then
5514+
5515-
		-- convert normal (storage) extended farm to networked storage
5515+
5516-
		--T:turnLeft(1)	-- over water source, facing N
5516+
5517-
		createFarmNetworkStorage(R, false, true)
5517+
5518-
		return {"Farm converted to network storage"}
5518+
5519-
	else -- new farm.
5519+
5520-
		T:up(1) -- assume on the ground, go up 1
5520+
5521
	R.data = "bury" to embed bottom into ground
5522
	R.subChoice 1 = facing portal, 2 = aligned
5523-
	-- design change: sapling placed 2 blocks above corner for ease of walking round
5523+
5524-
	if R.networkFarm then	-- barrel on corner of plot, modems on each side N/E
5524+
5525-
		T:place("barrel", "down", false)
5525+
5526
	function lib.buildBase()
5527-
		T:place(R.useBlockType, "down", false)
5527+
5528
		T:go("C2", false, 0, false, R.useBlockType)
5529-
	-- stage 2 place sapling
5529+
5530
		for i = 1, R.length - 2 do -- R.length = 4: place when i=1,2
5531-
	T:place("dirt", "down")
5531+
			T:place("minecraft:obsidian", 0, "down", false)
5532-
	T:up(1)
5532+
5533-
	T:place("sapling", "down") -- plant sapling
5533+
5534-
	T:go("F1D4")
5534+
5535-
	if R.networkFarm then
5535+
5536-
		T:place("modem", "down", false)
5536+
5537-
		network.attachModem()
5537+
5538
		T:place("minecraft:obsidian", 0, "down", false)
5539-
		T:place(R.useBlockType, "down", false)
5539+
5540
			T:forward(1)
5541-
		-- stage 2 place double barrel/chest
5541+
5542
		T:place("minecraft:obsidian", 0, "down", false)
5543
	end
5544-
		T:go("R1F1L1")
5544+
5545
	if R.data ~= "bury" then
5546
		T:up(1)
5547
	end
5548
	if R.subChoice == 1 then
5549
		T:go("F1R1")
5550
	end
5551
	local out = true
5552-
			T:go("F1 x0x2C 2", false, 0, false, R.useBlockType)
5552+
5553
		lib.buildBase()
5554
		for i = 1, R.height - 2 do
5555
			T:go("R2U1")
5556
			out = not out
5557-
	lib.placeDirt(9, false) 	-- place dirt back to start
5557+
5558-
	if R.networkFarm then	-- water source next to modem
5558+
5559-
		lib.addWaterSource(R, {"c","c","d","d"}, storage)
5559+
5560-
		-- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock
5560+
5561-
		T:go("U1F1L1")
5561+
5562-
		T:place("modem", "down", false)
5562+
5563-
		T:go("F1C2 L1F1 D1", false, 0, false, R.useBlockType)
5563+
5564
		end
5565-
		lib.addWaterSource(R, {"c","c","t","d"}, storage)  -- put barrel / chest in floor
5565+
5566-
		T:go("U1F1R2")
5566+
5567-
		if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
5567+
5568-
			lib.placeStorage(storage, storageBackup)
5568+
5569
			T:go("L1F"..R.width.."D"..R.height - 1 .."R2")
5570-
		T:go("R1F1L1")
5570+
5571-
		if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
5571+
5572-
			lib.placeStorage(storage, storageBackup)
5572+
5573
		end
5574-
		T:go("F1D1")
5574+
5575
	
5576
	return {}
5577
end
5578
5579-
		T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0 x2C2 F1D1", false, 0, false, R.useBlockType)
5579+
5580
	--[[ Used in End World to use a trapdoor to push player through portal ]]
5581
	local lib ={}
5582
	
5583
	function lib.findPortal()
5584
		local found = false
5585
		local onSide = false
5586
		for i = 1, 64 do
5587
			if not turtle.up() then -- hit block above
5588-
	lib.addWaterSource(R, {"d","c","c","d"}, storage)	-- bottom right
5588+
5589
				break
5590-
	lib.addWaterSource(R, {"c","c","d","d"}, storage)	-- top right, facing away from plot
5590+
5591-
	T:go("F1U1 R1C2 x0F1 x0x2 C2R1", false, 0, false, R.useBlockType)
5591+
5592-
	for i = 1, 11 do	-- build right wall from top of plot to bottom
5592+
5593
			-- are we under the centre block, or one of the sides?
5594
			if turtle.detect() then -- under a side
5595-
	T:go("R1F10")				-- ends on top of front storage/ modem facing tree
5595+
5596-
	if R.networkFarm then		-- network storage
5596+
5597-
		network.attachModem()
5597+
5598-
		T:go("R1F1D1R1")	-- over water source, facing E (crops)
5598+
5599-
		if extend == "" then	-- primary plot
5599+
5600-
			createFarmNetworkStorage(R, true)
5600+
5601
						break
5602-
			createFarmNetworkStorage(R, false)
5602+
5603
				end
5604
			end
5605
			if onSide then-- move to centre
5606
				T:go("D1F1")
5607-
		utils.goBack(numPlots * 11)
5607+
5608
		end
5609
		local height = 3 -- allows for 2 bedrock + starting space
5610-
		T:go("R1U1F".. numPlots * 11 .."D1L1")
5610+
5611
			height = height + 1
5612
		end
5613
		return found, height
5614
	end
5615
	
5616
	function lib.addFloor(length)
5617
		for i = 1, length do
5618
			if i < length then
5619-
	--T:setUseLog(true, "farmCreateLog.txt", true)
5619+
5620-
	--dbug = true	-- set dbug flag
5620+
5621-
	--utils.waitForInput("Logging and debugging enabled")	--utils.waitForInput(message)
5621+
5622
			end
5623
		end
5624
	end
5625
	
5626
	function lib.buildLadder(height)
5627
		for i = 1, height do
5628-
	R = utils.checkFarmPosition(R)
5628+
5629
			T:go("F1C1 R1C1 L2C1 R1", false, 0, true)
5630-
	if not R.ready then
5630+
5631-
		return {"Unable to determine starting position"}
5631+
5632
				T:go("C2")
5633
			end
5634-
	createFarm(R, extend)
5634+
			T:place("minecraft:ladder", 0, "forward", true)
5635
			T:up(1)
5636
		end
5637
	end
5638
	
5639
	local found, height = lib.findPortal()
5640
	if found then	-- position under centre of beacon
5641
		-- build ladder up and create platform
5642
		T:go("L1F1L1F2L2")
5643
		T:checkInventoryForItem({"minecraft:ladder"},{height})
5644-
	R.data == "random" for random floor placement
5644+
5645
		T:checkInventoryForItem({"trapdoor"},{1})
5646
		lib.buildLadder(height) -- ends facing ladder, 1 block above
5647
		
5648
		T:go("R1")
5649-
	function lib.goToRemote(R)
5649+
5650
		T:go("C2F1 C2F1 C2F1 C2")
5651
		T:go("R1F1R1")
5652
		T:go("C2F1 C2F1 C2F1 C2")
5653
		utils.goBack(2)
5654
		T:go("R1F1")			-- facing portal entrance
5655
		T:place("trapdoor", -1, "up", false)
5656
	else
5657
		return {"Portal not found. Move me under","the centre if possible.", "wait for purple beacon."}
5658
	end
5659
	return {}
5660
end
5661
5662
local function createRailway(R) -- 93
5663
	-- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
5664
	--[[Build steps up or down ready for railtrack]]
5665
	if R.down then
5666-
			return "Measured depth/height of "..depth.." > setting: "..R.height
5666+
5667
			local blockType = ""
5668
			while blockType == "" do
5669
				T:go("F1D1", false, 0, true)
5670
				blockType = T:getBlockType("down")
5671
				if blockType == "" then
5672-
	function lib.checkPosition(R)
5672+
5673-
		-- check if block above/below
5673+
5674-
		local blockBelow = turtle.detectDown()
5674+
5675-
		local blockAbove = turtle.detectUp()
5675+
5676-
		if R.subChoice == 2 then -- New floor over existing
5676+
5677-
			-- if no block below, assume in correct position and continue
5677+
				T:go("U1x0 D1x1 F1x0x1 D1x1 C2", false, 0, false)
5678-
			-- else move up 1 and continue
5678+
5679-
			if blockBelow then T:up(1) end
5679+
5680-
		elseif R.subChoice == 4 then -- New ceiling under existing
5680+
5681-
			-- if no block above, assume in correct position and continue
5681+
5682-
			-- else move down 1 and continue
5682+
			T:go("C1U2 x0D1F1", false, 0, false) --put stone in front, up 2 excavate 1, down 1, forward 1
5683-
			if blockAbove then T:down(1) end
5683+
5684
	end
5685
	return {}
5686
end
5687-
	function lib.placeRow(R, direction, waterPresent)
5687+
5688
local function createRectanglePath(R) -- 710, 83 direct commands
5689
	-- allow user to control length / width of each path
5690
	-- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
5691
	--local pp = utils.getPrettyPrint()
5692
	local lib = {}
5693
	
5694
	function lib.forward(R)
5695-
			R = lib.getRandomBlock(R)	-- changes block randomly ONLY if R.data == "random"
5695+
5696-
			R = lib.changeCheckered(R)	-- changes to next block type ONLY if R.data == "checked"
5696+
5697-
			-- ONLY if R.data == "striped" has already been changed for whole row
5697+
5698-
			T:place(R.inventory.useBlock, direction, false) -- leaveExisting = false
5698+
5699
		else
5700
			for i = 1, R.length do
5701
				T:go("F1U1C0D1C2", false, 0, true)
5702
			end
5703-
		return waterPresent, R
5703+
5704
	end
5705
	
5706-
	function lib.getRandomBlock(R)
5706+
5707-
		if R.data == "random" then
5707+
5708-
			local index = math.random(1, #R.inventory.names)	-- random index between 1 and no of block types
5708+
5709-
			local success = false
5709+
5710-
			for i = index, R.inventory.blockTypeCount do		-- iterate from index upwards
5710+
5711-
				if R.inventory.quantities[i] > 0 then			-- at least 1 block left
5711+
5712-
					R.inventory.useBlock = R.inventory.names[i]
5712+
5713-
					R.inventory.quantities[i] = R.inventory.quantities[i] - 1
5713+
5714-
					R.inventory.blockCount = R.inventory.blockCount - 1
5714+
5715-
					success = true
5715+
5716
	function lib.right(R)
5717
		T:turnRight(R.length)
5718
	end
5719
	
5720-
			if not success then								-- no blocks left in the range of index -> no of block types
5720+
5721-
				for i = index, 1, -1 do						-- go backwards from index to 1
5721+
5722-
					if R.inventory.quantities[i] > 0 then		-- at least 1 block left
5722+
5723-
						R.inventory.useBlock = R.inventory.names[i]
5723+
5724-
						R.inventory.quantities[i] = R.inventory.quantities[i] - 1
5724+
5725-
						R.inventory.blockCount = R.inventory.blockCount - 1
5725+
5726-
						success = true
5726+
5727
	
5728
	function lib.down()
5729
		T:go("D1C2", false, 0, true)
5730
	end
5731-
		end	
5731+
5732
	if R.data == "menu" then
5733-
		return R
5733+
5734
		local width = 0
5735
		local length = 0
5736-
	function lib.changeStripe(R)
5736+
5737-
		if R.data == "striped" then
5737+
5738-
			R.size = R.size + 1
5738+
5739-
			if R.size > R.inventory.blockTypeCount then
5739+
5740-
				R.size = 1
5740+
5741
			"Back # blocks",
5742-
			R.inventory.useBlock = R.inventory.names[R.size]
5742+
5743
			"Turn Left",
5744-
		return R
5744+
5745
			"Down 1 block",
5746
			"Quit"
5747-
	function lib.changeCheckered(R)
5747+
5748-
		--swap between 2 block types
5748+
5749-
		if R.data == "checked" then
5749+
5750-
			if R.inventory.useBlock == R.inventory.names[1] then
5750+
5751-
				R.inventory.useBlock = R.inventory.names[2]
5751+
5752
			if choice == 1 then
5753-
				R.inventory.useBlock = R.inventory.names[1]
5753+
5754
				lib.forward(R)
5755
			elseif choice == 2 then
5756-
		return R
5756+
5757
				R.length = menu.getInteger("Move forward how many blocks?", 1, 250, nil, colors.lime)
5758
				lib.forward(R)
5759
			elseif choice == 3 then
5760
				R.length = 1
5761-
	if R.data == "random" then
5761+
5762-
		math.randomseed(R.inventory.blockCount)
5762+
5763-
		print("Using random blocks")
5763+
5764-
	elseif R.data == "striped" then
5764+
5765-
		print("Using striped pattern")
5765+
5766-
	elseif R.data == "checked" then
5766+
5767-
		print("Using checkered pattern")
5767+
5768
			elseif choice == 6 then
5769
				R.length = 1
5770
				lib.left(R)
5771
			elseif choice == 7 then
5772
				lib.up(R)
5773
			elseif choice == 8 then
5774
				lib.down()
5775-
		local message = lib.goToRemote(R)
5775+
5776-
		if message ~= "" then	-- error encountered
5776+
5777-
			return {message}
5777+
5778
		local instructions = 
5779
[[~lightGray~Commands:
5780
5781-
	lib.checkPosition(R)
5781+
5782-
	-- based on clearRectangle code
5782+
5783-
	if R.width == 1 then 					-- single block ahead only
5783+
5784-
		waterPresent, R = lib.placeRow(R, direction, waterPresent)
5784+
5785-
		T:turnRight(2)						-- turn at the top of the run
5785+
5786-
		T:forward(R.length - 1)				-- return to start
5786+
5787-
		T:turnRight(2)						-- turn round to original position
5787+
5788
~red~q = quit
5789-
		local iterations = 0 				-- R.width = 2, 4, 6, 8 etc
5789+
5790-
		if R.width % 2 == 1 then  			-- R.width = 3, 5, 7, 9 eg R.width 7
5790+
5791-
			iterations = (R.width - 1) / 2 	-- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
5791+
5792
		while cmd ~= "q" do
5793
			local line = menu.clear()
5794
			line = menu.colourText(line, instructions)
5795-
		R = lib.changeStripe(R)
5795+
5796-
		R = lib.changeCheckered(R)
5796+
5797-
		for i = 1, iterations do 			-- eg 3 blocks wide, iterations = 1
5797+
5798-
			waterPresent, R = lib.placeRow(R, direction, waterPresent)
5798+
5799
			cmd = input:sub(1,1)
5800-
			R = lib.changeStripe(R)
5800+
5801-
			--R = lib.changeCheckered(R)
5801+
5802-
			waterPresent, R = lib.placeRow(R, direction, waterPresent)
5802+
5803
			end
5804
			if cmd == "q" then
5805
				return{"User has quit application"}
5806-
				R = lib.changeStripe(R)
5806+
5807
			if cmd == "f" then
5808
				lib.forward(R)
5809
			elseif cmd == "b" then
5810
				lib.back(R)
5811-
			R = lib.changeStripe(R)
5811+
5812-
			waterPresent, R = lib.placeRow(R, direction, waterPresent)
5812+
5813
			elseif cmd == "r" then
5814
				lib.right(R)
5815
			elseif cmd == "u" then
5816
				lib.up(R)
5817
			elseif cmd == "d" then
5818
				lib.down()
5819
			end
5820
		end
5821
	end
5822
	return {}
5823
end
5824
5825
local function createRetainingWall(R) -- 34, 82
5826
	-- facing direction wall will take
5827
	-- will need to rotate 180 to build
5828
	-- if R.height > 0 then build to specified depth
5829
	local lib = {}
5830
		
5831
	function lib.checkFloor()
5832
		local newDepth = 0
5833
		place = utils.clearVegetation("down") -- in case col in front is deeper
5834
		while place do -- loop will be entered at least once
5835
			T:down(1)
5836
			newDepth = newDepth + 1
5837
			place = utils.clearVegetation("down")
5838
		end
5839
		if newDepth > 0 then
5840
			for j = 1, newDepth do	-- go up until column base is met
5841
				T:go("U1C2")
5842
			end
5843
		end
5844
	end
5845
	
5846
	function lib.patchMissingBlock()
5847
		if turtle.back() then
5848
			T:go("C1")
5849
		else
5850
			T:go("B1C1")
5851
		end
5852
	end
5853
	
5854
	function lib.placeSingle(height)
5855-
					T:place("torch", "forward")				-- place torch, move forward
5855+
5856
		if height > 0 then
5857
			T:go("D"..height)
5858
			y = height
5859
		else
5860
			local place = utils.clearVegetation("down")
5861
			while place do -- loop will be entered at least once
5862-
				if not T:place("slab", "down") then			-- break if out of slabs
5862+
5863
				if place then
5864
					T:down(1)
5865
					y = y + 1
5866
				end
5867
			end
5868
		end
5869
		-- return to surface, placing below
5870
		for i = 1, y do
5871
			T:go("U1C2", false, 0, true)
5872
		end
5873
	end
5874
	
5875
	function lib.placeDouble(height)
5876
		--T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
5877
		local y = 0
5878
		if not turtle.back() then
5879
			T:go("B1")
5880
		end
5881
		if height > 0 then
5882
			for i = 1, height do
5883
				T:go("C1D1", false, 0, true)
5884
			end
5885
			T:go("C1", false, 0, true)
5886
			y = height
5887
		else
5888
			local place = utils.clearVegetation("down")
5889
			-- build back column
5890
			while place do -- loop will be entered at least once
5891
				place = utils.clearVegetation("down")
5892
				if place then
5893
					T:go("C1D1", false, 0, true)
5894
					y = y + 1
5895
				end
5896
			end
5897
			-- reached bottom. floor in front could drop down
5898-
				-- T:place(blockType, direction, leaveExisting, signText)
5898+
5899-
				if not T:place("stone", "forward", false) then
5899+
5900
			turtle.back() -- back at starting point
5901
			T:go("C1", false, 0, true) 
5902
		end
5903-
				if T:getItemSlot("minecraft:torch") > 0 then
5903+
5904-
					T:place("torch", "forward", false)
5904+
5905
			T:go("U1C2", false, 0, true)
5906
		end
5907
	end
5908
		
5909
	function lib.placeTriple(height)
5910
		--T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
5911-
				if not T:place("slab", "forward", false) then
5911+
5912
		if turtle.back() then
5913
			T:go("C1")
5914
		else
5915
			T:go("B1C1")
5916
		end
5917
		if height > 0 then
5918
			for i = 1, height do
5919
				T:go("C1D1", false, 0, true)
5920
			end
5921
			for i = 1, height do
5922
				T:go("C1D1", false, 0, true)
5923
			end
5924-
				if not T:place("stone", "forward", false) then
5924+
5925
			y = height
5926
		else
5927
			local place = utils.clearVegetation("down")
5928-
				if T:getItemSlot("minecraft:torch") > 0 then
5928+
5929-
					T:place("torch", "forward", false)
5929+
5930
				place = utils.clearVegetation("down")
5931
				if place then
5932
					T:go("C1D1", false, 0, true)
5933
					y = y + 1
5934
				end
5935
			end
5936
			-- reached bottom. floor in front could drop down
5937
			T:go("F1") -- move under first column
5938-
			T:place("ice", "down", true)
5938+
5939
			T:go("B1C1R2F1", false, 0, true) 
5940
			lib.checkFloor()
5941
			T:go("B1C1")
5942
			-- return to surface , placing below and to front
5943
		end
5944
		for i = 1, y do
5945
			T:go("C1U1C2", false, 0, true)
5946
		end
5947
		T:go("F1R2C1", false, 0, true)
5948
		-- facing back again inside edge of col 3
5949
		return y -- depth of this run
5950
	end
5951
	
5952
	local topInPlace = false -- topInPlace = true already a path across the water eg monument rectangle
5953-
					if not T:place("ice", "down", true) then -- out of ice
5953+
5954
		topInPlace = true
5955
	end
5956
	local place = false
5957
	local inWater = false
5958
	local onWater = false
5959
	if not topInPlace then
5960
		if R.length > 1 then
5961
			inWater, onWater = utils.getWaterStatus() -- returns whether above water, or immersed
5962
		end
5963
	end
5964
	
5965
	local maxDepth = 5 --initial estimated value
5966
	-- start at surface, move back 1 block
5967
	-- each iteration completes 3 columns
5968
	local numBlocks = T:getSolidBlockCount()
5969
	print("Solid blocks in inventory: "..numBlocks)
5970
	
5971
	if R.length == 1 then -- single column down to water bed
5972
		lib.placeSingle(R.height)
5973
	elseif R.length == 2 then--down then up: 2 cols
5974
		inWater, onWater = utils.startWaterFunction(onWater, inWater, 2, true) -- move into water
5975
		T:go("R2") -- move to face player
5976
		lib.placeDouble(R.height)
5977
		if not inWater then
5978
			T:go("U1C2", false, 0, true)
5979
		end
5980
	else -- R.length 3 or more
5981
		if topInPlace then
5982
			T:down(1) -- break through top
5983
		else
5984
			inWater, onWater = utils.startWaterFunction(onWater, inWater, 2, true) -- move into water
5985
		end
5986
		T:go("R2") -- move to face player
5987
		-- now at water surface
5988
		local remain = R.length
5989
		while remain >= 3 do
5990
			numBlocks = T:getSolidBlockCount()
5991
			print("Inventory blocks: "..numBlocks.." depth: "..maxDepth)
5992
			if numBlocks < maxDepth * 3 then
5993
				--ask player for more
5994
				T:checkInventoryForItem({"stone"}, {maxDepth * remain}, false)
5995
			end
5996
			local y = lib.placeTriple(R.height) -- moves back, places col in front, centre and behind. R.height = 0 for auto depth
5997
			if y > maxDepth then
5998
				maxDepth = y
5999
			end
6000
			remain = remain - 3
6001
			if remain > 1 then
6002
				lib.patchMissingBlock()
6003
			end
6004
		end
6005
		if remain == 1 then -- 1 more column
6006
			lib.patchMissingBlock()
6007
			lib.placeSingle(R.height)
6008
		elseif remain == 2 then -- 2 cols
6009
			lib.placeDouble(R.height)
6010
		end
6011
		T:go("U1C2") -- above surface
6012
	end
6013
	return {}
6014
end
6015
6016
local function createSafeDrop(R) -- 14
6017
	-- dig down height blocks, checking for blocks on all sides
6018
	local drop = 0
6019
	local isBedrock = false
6020
	T:down(2)
6021
	drop = 2
6022
	for i = 1, R.height - 1 do
6023
		for j = 1, 4 do
6024
			-- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
6025
			T:go("C1R1", false, 0, true)
6026
		end
6027
		if T:down(1) then
6028
			 drop = drop + 1
6029
		else
6030
			isBedrock = true
6031
			break
6032
		end
6033
		if T:isWaterOrLava("up") ~= "" then
6034
			T:go("C0x0", false, 0, false) -- delete water/ lava block
6035
		end
6036
	end
6037
	if not isBedrock then -- not sitting on bedrock, so break foot level exit block
6038
		T:go("U1R2x1")
6039-
		if not T:place("ladder", "forward", false) then
6039+
6040
	T:placeWater("down")
6041
	if isBedrock then
6042
		T:go("U1x1 U1x1")
6043
	else
6044-
			T:place("common", direction, false) -- any common block
6044+
6045
	end
6046-
			T:place("minecraft:torch", direction, false)
6046+
6047
	
6048
	return {"Safe drop completed "..drop .. " blocks"}
6049
end
6050
6051
local function createSlopingWater(R) -- 34, 89
6052
	--[[
6053
	creates a sloping water area above existing lake/river/ocean
6054
	R.width is usually 7 with an existing wall on 8th row
6055
	R.length  is user choice, limited to bucket/slab quantities
6056
	Places slabs into existing surface, places row of sources
6057
	Removes slabs
6058
	]]
6059
	local lib = {}
6060
	
6061
	function lib.fillBuckets()
6062
		local emptyBuckets = utils.getEmptyBucketCount()
6063
		for i = 1, emptyBuckets do
6064
			if utils.fillBucket("down") then
6065
				print("Bucket filled down")
6066
				sleep(0.3)
6067
			else
6068
				print("Unable to fill bucket ".. i .." / "..emptyBuckets)
6069
			end
6070
		end
6071
		return utils.getWaterBucketCount()
6072
	end
6073
	
6074
	local outbound = true
6075
	local inWater, onWater = utils.getWaterStatus()
6076
	inWater, onWater = utils.startWaterFunction(onWater, inWater, 2 ,false) -- move above water, max descent 2
6077
	local waterBuckets = lib.fillBuckets()
6078
	for w = 1, R.width do
6079
		for l = 1, R.length do
6080
			T:place("slab", -1, "down", false)
6081
			if l < R.length then
6082
				T:forward(1)
6083
			end
6084
		end
6085
		if w < R.width then
6086
			if outbound then
6087
				T:go("R1F1R1")
6088
			else
6089
				T:go("L1F1L1")
6090
			end
6091
			outbound = not outbound
6092
		end
6093
	end
6094
	if outbound then
6095
		T:go("L1F"..R.width - 1 .."L1")
6096
	else
6097
		T:go("R1F"..R.width - 1 .."R1")
6098
	end
6099
	T:placeWater("up")  -- place in corner
6100
	local move = true
6101
	while move do
6102
		move = turtle.forward()
6103
		move = turtle.forward() -- false if at end of run
6104
		T:placeWater("up")  -- alternate positions + end of run
6105
	end
6106
	T:go("R2D1")
6107
	T:sortInventory() -- get all buckets into 1 slot
6108
	for w = 1, R.width do
6109
		for l = 1, R.length do
6110
			if l < R.length then
6111
				T:forward(1)
6112
			end
6113
		end
6114
		if w < R.width then
6115
			if outbound then
6116
				T:go("R1F1R1")
6117
			else
6118
				T:go("L1F1L1")
6119
			end
6120
			outbound = not outbound
6121-
		T:place("ladder", "up")
6121+
6122
	end
6123
	if outbound then
6124
		T:go("L1F"..R.width - 1 .."L1")
6125
	else
6126-
	T:place("ladder", "forward")
6126+
6127
	end
6128
	T:go("U2")
6129
	
6130
	return {}
6131
end
6132
6133
local function createSquidFarmBase(R) -- 34
6134
	-- dig down to y=45. assume starting at water level (64)
6135
	local depth = 0
6136
	local message =
6137
[[Place the turtle under the grid
6138
left corner above current pit
6139
opening.
6140
It will descend to the base and
6141
continue to level y=45.
6142
6143
Enter to continue...
6144
]]
6145-
	T:place("minecraft:chest", "up", false)
6145+
6146
	while turtle.down()do
6147
		depth = depth + 1
6148
	end
6149
	T:down(1)
6150
	R.height = 21 - depth
6151
	R.width = 15
6152
	R.length = 15
6153
	R.silent = true
6154
	R.data = "down"
6155
	clearSolid(R)
6156
	T:up(depth + 4)
6157
	return {}
6158
end
6159
6160-
	while T:getItemSlot("minecraft:torch") > 0 do
6160+
6161-
		turtle.select(T:getItemSlot("minecraft:torch"))
6161+
6162
	--move above water
6163
	local maxMove = 2
6164
	while turtle.detectDown() and maxMove > 0 do
6165
		T:forward(1)
6166
		maxMove = maxMove - 1
6167
	end
6168
	if R.length > 0 then
6169
		for i = 1, R.length - 1 do
6170
			success = utils.dropSand()
6171
			T:forward(1, false)
6172
		end
6173
		success = utils.dropSand()
6174
	else
6175
		while not turtle.detectDown() do -- over water
6176
			while not turtle.detectDown() do -- nested to allow forward movement
6177
				success = utils.dropSand() -- drops sand and checks supplies
6178
			end
6179
			if success then
6180
				T:forward(1, false)
6181
			else -- out of sand
6182
				break
6183
			end
6184
		end
6185
	end
6186
	return {}
6187
end
6188
6189
local function createSinkingPlatform(R) -- 58
6190
	local lib = {}
6191
	
6192
	function lib.stage1a(R)							-- build side wall left side
6193
		for l = 1, R.length do 						--            | |*| |
6194
			T:go("L1C1 R1C2", false, 0, false)		-- |*|>| | to |*|>| | place left wall
6195
			if l == 1 then							-- first iteration
6196
				T:go("U1C2 D1 F1C2", false, 0, false)-- |*|>| | to |*|*|>| up/down block to delete source at corner
6197
			elseif l < R.length then				-- mid run
6198
				T:go("F1C2", false, 0, false)		-- |*|>| | to |*|*|>| move forward
6199
			else									-- end of run
6200
				T:go("C1U1 C2D1", false, 0, false)	-- |*|>| | to |*|>|*| place end wall
6201
			end
6202
		end
6203
	end
6204
	
6205
	function lib.stage1b(R)							-- same as stage1a on right side
6206
		for l = 1, R.length do 
6207
			T:go("R1C1 L1C2", false, 0, false)
6208
			if l == 1 then
6209
				T:go("U1C2 D1 F1C2", false, 0, false)
6210
			elseif l < R.length then
6211
				T:go("F1C2", false, 0, false)
6212
			else
6213
				T:go("C1U1 C2D1", false, 0, false)
6214
			end
6215
		end
6216
	end
6217
	
6218
	function lib.stage2(forward)
6219
		if forward then
6220
			T:go("C1R1 F1L1 C1R2", false, 0, false)
6221
		else
6222
			T:go("C1L1 F1R1 C1L2", false, 0, false)
6223
		end
6224
	end
6225
		
6226
	local forward = true
6227
	local goingRight = true
6228
	local blockType = T:getBlockType("down")
6229
	if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
6230
		T:up(1)
6231
	end
6232
	for h = 1, R.height do						-- repeatedly create a platform, move down and repeat
6233
		T:down(1) 								-- move down into existing platform
6234
		if goingRight then 						-- first side
6235
			if forward then						-- complete left side
6236
				T:go("R2C1 L2", false, 0, false) -- | |>| | to |*|<| | to |*|>| | 
6237
				lib.stage1a(R)					-- build left wall
6238
				T:go("R1F1 L1C1 R2C2", false, 0, false)			-- turn ready for next side
6239
			else
6240
				T:go("L2C1 R2", false, 0, false) -- block 1, 1
6241
				lib.stage1b(R)					-- turn ready for next side
6242
				T:go("L1F1 R1C1 L2C2", false, 0, false)
6243
			end
6244
		else 									-- on right side so different approach
6245
			if forward then
6246-
					T:place("slab", "up", false)
6246+
6247
				lib.stage1b(R)					
6248
				T:go("C1L1 F1R1 C1L2 C2", false, 0, false)		-- turn ready for next side
6249
			else								-- complete left side
6250
				T:go("R2C1 L2", false, 0, false) -- block 1, 1
6251
				lib.stage1a(R)					-- turn ready for next side
6252
				T:go("C1R1 F1L1 C1R2 C2", false, 0, false)
6253
			end
6254
		end
6255
		forward = not forward					-- continue strips across until at far edge
6256
		for w = 1, R.width - 2 do
6257
			for l = 1, R.length do
6258
				if l < R.length then
6259
					T:go("C2F1", false, 0, false)
6260
				else
6261
					T:go("C2", false, 0, false)
6262
				end
6263
			end
6264
			if goingRight then
6265
				lib.stage2(forward)
6266
			else
6267
				lib.stage2(not forward)
6268-
					T:place("slab", "up", false)
6268+
6269
			forward = not forward
6270
		end										-- far side
6271
		if goingRight then
6272
			if forward then
6273
				lib.stage1b(R)
6274
			else
6275
				lib.stage1a(R)
6276
			end
6277
		else
6278
			if forward then
6279
				lib.stage1a(R)
6280
			else
6281
				lib.stage1b(R)
6282
			end
6283
		end
6284
		goingRight = not goingRight
6285
		T:turnRight(2)
6286
		forward = not forward
6287
	end
6288-
							T:place("slab", "up", false)
6288+
6289
end
6290
6291
local function createStaircase(R) -- 13
6292
	-- R# L# F# B# U# D# +0 -0 = Right, Left, Forward, Back, Up, Down, up while detect and return, down while not detect
6293
	-- dig:			  x0,x1,x2 (up/fwd/down)
6294
	-- suck:		  s0,s1,s2
6295
	-- place chest:   H0,H1,H2 
6296
	-- place sapling: S0,S1,S2
6297
	-- place Torch:   T0,T1,T2
6298
	-- place Hopper:  P0,P1,P2
6299
	-- mine floor:	  m# = mine # blocks above and below, checking for valuable items below, and filling space with cobble or dirt
6300
	-- mine ceiling:  M# = mine # blocks, checking for valuable items above, and filling space with cobble or dirt
6301
	-- mine ceiling:  N# same as M but not mining block below unless valuable
6302
	-- 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
6303
	
6304
	-- 3| |B| |
6305
	--   - - - 
6306
	-- 2|A| |C|
6307
	--   - - - 
6308
	-- 1|^|D| |
6309
	--   - - - 
6310
	--   1 2 3 
6311
	local lib = {}
6312
	
6313
	function lib.checkFluids()
6314
		local isFluid = false
6315
		-- check if water or lava present
6316
		for i = 1, 4 do
6317
			blockType = T:isWaterOrLava("forward")
6318
			if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then
6319
				isFluid = true
6320
			end
6321
		end
6322
		return isFluid
6323
	end
6324
	
6325
	function lib.createStaircaseSection(onGround, levels, level)
6326
		-- start 1,1,1, n
6327
		-- stage A
6328-
		-- T:place(blockType, direction, leaveExisting, signText)
6328+
6329
		local blockType = ""
6330
		local data = T:getStock("stairs")
6331-
				T:place(blockType, "down", false)
6331+
6332
			T:craft('stairs', 4)
6333
		end
6334
		if onGround and isFluid then
6335
			-- add right side and block entrance
6336
			T:go("R1C1R1C1R2")
6337
		end
6338
		if isFluid then
6339
			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
6340
		else
6341
			T:go("F1x1 R1C1 L1C2B1 ^1C2", false, 0, true)
6342
		end
6343
		if not onGround then
6344
			-- stage A1
6345
			T:go("L2C1L2", false, 0, true) -- start 1,1,1,n fix corner on level 1 end: 1,1,1,n
6346
		end
6347
		-- stage B
6348
		T:go("U1L1", false, 0, true) -- end  1,1,1,w layer 2
6349
		level = level + 1
6350
		isFluid = lib.checkFluids()
6351
		if isFluid then
6352
			T:go("C1", false, 0, true) -- end  1,1,1,w layer 2
6353
		end
6354
		if not onGround then
6355
			if isFluid then
6356
				T:go("L1C1R1", false, 0, true) -- end  1,1,1,w layer 2
6357
			end
6358
		end
6359
		-- stage C1
6360
		if isFluid then
6361
			T:go("R1C1F1C1x1 L1C1 R2C1 L1B1", false, 0, true)
6362
		else
6363
			T:go("R1F1 R1C1 L1B1", false, 0, true)
6364
		end
6365
		--level = level + 1
6366
		--if level == levels then
6367
			--return false, level
6368
		--end
6369
		-- stage C2
6370
		T:go("U1")
6371
		level = level + 1
6372
		--if level == levels then
6373
			--return true, level
6374
		--end
6375
		isFluid = lib.checkFluids()
6376
		if isFluid then
6377
			T:go("L1C1L1 C1L2 C1F1L1 C1R2 C1L1 B1C2 D1", false, 0, true) -- end 1,1,2,n
6378
		else
6379
			T:go("F1R1 C1L1 B1D1", false, 0, true) -- end 1,1,2,n
6380
		end
6381
		level = level - 1 -- went down in branch above
6382
		--if level == levels then
6383
			--return false, level
6384
		--end
6385
		-- stage D
6386
		isFluid = lib.checkFluids()
6387
		if isFluid then
6388
			T:go("C1F1C1F1C1x1L1 C1R1 C1R1", false, 0, true) -- 3,1,2,e
6389
		else
6390
			T:go("F2 C1R1", false, 0, true) -- 3,1,2,e
6391
		end
6392
		
6393
		return false, level
6394
	end
6395-
			T:place("chest", "forward", false)
6395+
6396
	--local height = currentLevel -- eg 64 at top or 5 at bedrock
6397
	local data = T:getStock("stairs")
6398
	--{rt.total, rt.mostSlot, rt.leastSlot, rt.mostCount, rt.leastCount}
6399
	local numStairs = data.total
6400
	local levels = math.abs(R.depth - R.height) --height of stairs
6401
	local numStairsNeeded = levels
6402
	numStairsNeeded = numStairsNeeded - numStairs
6403
	if numStairsNeeded > 40 then
6404
		print('crafting '..numStairsNeeded..' : '..numStairs.. ' in stock')
6405
		if T:craft('stairs', 40) then	-- max 40 so repeat
6406
			data = T:getStock("stairs")
6407
			if data.total == 0 then
6408
				data = T:getStock("stairs")
6409
			end
6410
			numStairs = data.total
6411
			numStairsNeeded = numStairsNeeded - numStairs
6412
		else
6413
			return {"Unable to craft stairs"}
6414
		end
6415
	end
6416
	if numStairsNeeded > 0 then
6417
		T:craft('stairs', numStairsNeeded)
6418
	end
6419
	local level = 0
6420
	if R.down then -- go down towards bedrock
6421
		local atBedrock = false
6422
		for i = 1, levels do
6423
			level = level - 1
6424
			if not T:down() then
6425
				atBedrock = true
6426
				break
6427
			end
6428
		end
6429
		if atBedrock then -- hit bedrock so get to level 5 / -59
6430
			level = T:findBedrockTop(level)
6431
			T:go("R1F1R1", false, 0, true)
6432
		end
6433
	end
6434
	local onGround = true
6435
	level = 0
6436
	while level < levels do
6437
		onGround, level = lib.createStaircaseSection(onGround, levels, level)
6438
	end
6439
	if not turtle.detectDown() then
6440
		T:go("C2")
6441
	end
6442
	
6443
	return{"Staircase completed"}
6444
end
6445
6446
local function createStripMine(R)
6447
	--[[
6448
	R.length should be a multiple of 16
6449
	mine a corridoor repairing floor and ceiling
6450
	check sides, remove valuable items
6451
	plug if lava present
6452
	Every 16 blocks dig a side passage 1 block deep 2 blocks long
6453
	]]
6454
	local lib = {}
6455
	
6456
	function lib.seal(R)	
6457
		if T:isValuable("forward") then	-- valuable block in front. If debris then refuse already dumped
6458
			T:dig("forward")
6459
		end
6460
		local blockType = T:getBlockType("forward")
6461
		if blockType:find("lava") ~= nil then
6462
			--T:place("stone", 0, "forward", false) -- place does not allow for specific blocktype
6463
			T:go("C1", false, 0, false, R.useBlockType)
6464
			return true
6465
		end
6466
		
6467
		return false
6468
	end
6469
	
6470
	function lib.checkSeal(R)
6471
		local retValue = false
6472
		T:turnRight(1)
6473
		if lib.seal(R) then
6474
			retValue = true
6475
		end
6476
		T:turnLeft(2)
6477
		if lib.seal(R) then
6478
			retValue = true
6479
		end
6480
		T:turnRight(1)
6481
		return retValue
6482
	end
6483
		
6484
	function lib.alcove(R)
6485
		-- right side, starting at ceiling
6486
		T:go("R1F1 C0", false, 0, false, R.useBlockType)-- stone ceiling, facing alcove wall (upper)
6487
		lib.seal(R)										-- seal alcove wall (upper)	
6488
		T:go("D1C2", false, 0, false, "cobble")			-- cobble floor, facing alcove wall (lower)	
6489
		lib.seal(R)										-- seal alcove wall (lower)		
6490
		T:go("L2 F1")									-- down 1, turn round, return to corridoor.
6491
		-- left side	
6492
		T:go("F1 C2", false, 0, false, "cobble")		-- cobble floor, facing alcove wall (lower)	
6493
		lib.seal(R)										-- seal alcove wall (lower)
6494
		T:go("U1 C0", false, 0, false, R.useBlockType)	-- stone ceiling, still facing alcove wall
6495
		lib.seal(R)										-- seal alcove wall (upper)						
6496
		T:go("L2F1L1")									-- return to corridoor at ceiling position
6497
		lib.placeTorch(R)								
6498
	end
6499
	
6500
	function lib.placeTorch(R)
6501
		if R.torchInterval > 0 then 					-- torches onboard
6502
			if T:getItemSlot("minecraft:torch") > 0 then
6503
				T:place("minecraft:torch", -1, "down")
6504
			end
6505
		end
6506
	end
6507
	
6508
	local seal = false
6509
	if T:getItemSlot("minecraft:torch") == 0 then
6510
		R.torchInterval = 0 -- set to default 16 above
6511
	end
6512
	for steps = 1, R.length do
6513
		-- go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
6514
		T:go("C2U1C0", false, 0, true, R.useBlockType)		-- check and repair floor / ceiling
6515
		if steps % 16 == 0 or steps % 16 == 1 then
6516
			lib.alcove(R) -- enter and exit at ceiling position
6517
		else
6518
			seal = lib.checkSeal(R)
6519
		end
6520
		T:go("F1D1", false, 0, true)
6521
		seal = lib.checkSeal(R)
6522
	end
6523
	if seal then -- water or lava found while tunnelling
6524
		T:go("U1C0", false, 0, true, R.useBlockType)
6525
		lib.checkSeal(R)
6526
		T:go("C1", false, 0, true, R.useBlockType)
6527
		T:down(1)
6528
	end
6529
	return {}
6530
end
6531
6532
local function createTreefarm(R) -- 22
6533
	local lib = {}
6534
	--go(path, useTorch, torchInterval, leaveExisting, preferredBlock)
6535
	function lib.buildWallSection(length, placePolished, useBlockType)
6536
		for i = 1, length do
6537
			if placePolished and i == length - 4 then
6538-
			T:place("slab", "down", true) 				-- place slab on top T:place(blockType, direction, leaveExisting)
6538+
				T:place("polished", 0, "down")
6539
				T:forward(1)
6540
			else
6541
				if i < length then
6542
					T:go("C2F1", false, 0, false, useBlockType)
6543
				end
6544
			end
6545
		end
6546
	end
6547
	
6548
	function lib.placeFloor(length, useBlockType)
6549
		for i = 1, length do
6550
			T:go("x0C2", false, 0, false, useBlockType)
6551
			if i < length then
6552
				T:forward(1)
6553
			end
6554
		end
6555
	end
6556
	
6557
	function lib.placeWater(length)
6558
		T:placeWater("down") 
6559
		T:go("F"..length.."R1")
6560
	end
6561
	
6562
	function lib.placeCorners(length, numBlocks, useBlockType)
6563
		for i = 1, numBlocks do
6564
			T:go("C2F1", false, 0, false, useBlockType)
6565
		end
6566
		-- now at 5th space
6567
		T:forward(length - (numBlocks * 2))
6568
		for i = 1, numBlocks do
6569
			T:go("C2", false, 0, false, useBlockType)
6570
			if i < numBlocks then
6571
				T:forward(1)
6572
			end
6573
		end
6574
	end
6575
	
6576
	function lib.turn(outward)
6577
		if outward then
6578
			T:go("R1F1R1")
6579
		else
6580
			T:go("L1F1L1")
6581
		end
6582
		return not outward
6583
	end
6584
	
6585
	local blockType
6586
	local blockModifier
6587
	-- R.data = "existing" if on existing tree farm
6588
	-- R.up = true if clear area
6589
	if R.up then
6590
		clearArea(R)
6591
	end
6592
6593
	if R.data == "existing" then
6594
		T:go("R1F1 D1", false, 0, false) -- move 14 blocks, right, forward, down 1
6595
		lib.buildWallSection(R.width - 1, false, R.useBlockType)
6596
		T:turnLeft(1)
6597
		lib.buildWallSection(R.length, false, R.useBlockType)
6598
		T:turnLeft(1)
6599
		lib.buildWallSection(R.width - 1, false, R.useBlockType)
6600
		T:go("C2U1R2")
6601
		lib.buildWallSection(R.width - 1, true, R.useBlockType)
6602
		T:turnRight(1)
6603
		lib.buildWallSection(R.length, true, R.useBlockType)
6604
		T:turnRight(1)
6605
		lib.buildWallSection(R.width, true, R.useBlockType)
6606
		T:go("R1") -- on lower left corner facing forward
6607
	else
6608
		T:down(1)
6609
		local placePolished = false
6610
		for i = 1, 2 do
6611
			lib.buildWallSection(R.length, placePolished, R.useBlockType)
6612
			T:turnRight(1)
6613
			lib.buildWallSection(R.width, placePolished, R.useBlockType)
6614
			T:turnRight(1)
6615
			lib.buildWallSection(R.length, placePolished, R.useBlockType)
6616
			T:turnRight(1)
6617
			lib.buildWallSection(R.width, placePolished, R.useBlockType)
6618
			T:turnRight(1)
6619
			placePolished = true
6620
			if i == 1 then
6621
				T:up(1)
6622
			end
6623
		end -- on lower left corner facing forward
6624
	end
6625
	T:go("F1R1 F1L1 D2") -- over 13 x 13 internal area
6626
	local outward = true
6627
	for i = 1, R.width - 2 do
6628
		lib.placeFloor(R.length - 2, R.useBlockType)
6629
		if i < R.width - 2 then
6630
			outward = lib.turn(outward)
6631
		end
6632
	end
6633
	T:go("U1R2") -- over 13 x 13 internal area opposite corner
6634
	-- now add corners
6635
	lib.placeCorners(R.length - 2, 4, R.useBlockType)
6636
	outward = lib.turn(outward)
6637
	lib.placeCorners(R.length - 2, 3, R.useBlockType)
6638
	outward = lib.turn(outward)
6639-
		T:place(brick, "up")
6639+
	lib.placeCorners(R.length - 2, 2, R.useBlockType)
6640
	outward = lib.turn(outward)
6641
	lib.placeCorners(R.length - 2, 1, R.useBlockType)
6642
	if outward then
6643
		T:go("R1F"..R.width - 9 .."R1")
6644
	else
6645
		T:go("L1F"..R.width - 9 .."L1")
6646
	end
6647-
			T:place("lava", "down")
6647+
6648
	lib.placeCorners(R.length - 2, 1, R.useBlockType)
6649
	outward = lib.turn(outward)
6650
	lib.placeCorners(R.length - 2, 2, R.useBlockType)
6651
	outward = lib.turn(outward)
6652
	lib.placeCorners(R.length - 2, 3, R.useBlockType)
6653-
		T:place("sign", true, "")
6653+
	outward = lib.turn(outward)
6654
	lib.placeCorners(R.length - 2, 4, R.useBlockType) -- should be back in starting corner facing front
6655-
		T:place(brick, "up")
6655+
6656
	T:go("U1R1")
6657
	lib.placeWater(R.length - 3) -- place water down then move forward, turn right
6658
	lib.placeWater(R.width - 3)
6659-
			T:place(brick, "forward")
6659+
	lib.placeWater(R.length - 3) 
6660
	lib.placeWater(R.width - 3)
6661
	T:go("F".. math.floor((R.length - 2) / 2).."R1F".. math.floor((R.width - 2) / 2)) -- should be in centre
6662
	T:go("D4C2 R1C1 R1C1 R1C1 R1F1 R2") -- facing back of hole ready to place water
6663
	T:placeWater("forward") 
6664
	T:go("R2F7U4")
6665-
		if not T:place("chest", "down") then
6665+
6666-
			T:place("barrel", "down")
6666+
6667
end
6668
6669-
		T:place("hopper", "down")
6669+
6670
	local lib = {}
6671-
		T:place("slab", "forward")
6671+
6672
	function lib.placeBarrel(R)
6673
		if R.data == "barrel" then
6674
			utils.goBack(1)
6675
			T:go("L1F1")
6676
			T:place("barrel", 0, "down", false)
6677
			utils.goBack(1)
6678
			T:go("R1")
6679
			T:forward(1)
6680
		end
6681
	end
6682
	
6683
	function lib.placeTorch(R)
6684
		T:up(1)
6685
		local up = 1
6686
		local blockType = T:getBlockType("forward")
6687
		while blockType:find(R.useBlockType) ~= nil and blockType ~= "" do -- prevent continuous upward travel
6688
			T:up(1)
6689
			up = up + 1
6690
			blockType = T:getBlockType("forward")
6691
		end
6692
		T:place("torch", 0, "forward", true)
6693
		T:down(up)
6694
	end
6695
	
6696
	function lib.buildWall(R, length)
6697
		-- T:place(blockType, damageNo, direction, leaveExisting, signText)
6698
		local blockType = ""
6699
		local blocks = 0
6700
		lib.placeBarrel(R)
6701
		while blocks < length do
6702
			if turtle.back() then
6703
				T:place(R.useBlockType, 0, "forward", true)
6704
				if R.torchInterval > 0 then
6705
					if blocks == 0 or blocks % R.torchInterval == 0 then
6706
						lib.placeTorch(R)
6707
					end
6708
				end
6709
				blocks = blocks + 1 -- still facing start position
6710
				while turtle.down() do
6711
					T:place(R.useBlockType, 0, "up", true)
6712
				end
6713
			else -- obstruction
6714
				T:turnRight(2) -- facing away from start
6715
				blockType = T:getBlockType("forward")
6716
				if blockType:find("torch") ~= nil then
6717
					T:go("F1R2")
6718
					T:place(R.useBlockType, 0, "forward")
6719
					blocks = blocks + 1 -- facing start
6720
				elseif blockType:find("log") ~= nil then
6721
					T:harvestTree()
6722
					T:turnRight(2)
6723
					T:place(R.useBlockType, 0, "forward")
6724
					blocks = blocks + 1 -- facing start
6725
				elseif T:isVegetation(blockType) then
6726
					T:go("F1R2")
6727
					T:place(R.useBlockType, 0, "forward")
6728
					blocks = blocks + 1 -- facing start
6729
				else -- cant go forward, go up instead
6730
					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
6731
						while turtle.detectUp() do -- will only run if block above
6732
							utils.goBack(1)
6733
							blocks = blocks - 1
6734
						end
6735-
		T:place("fence", "down", false)
6735+
6736
						T:place(R.useBlockType, 0, "down", true)
6737-
		T:place("fence", "down", false)
6737+
6738
					end
6739
					T:turnRight(2) -- facing start
6740-
		T:place("sign", "down", false)
6740+
6741
			end
6742-
		T:place("slab", "up", false)
6742+
6743
	end
6744-
		T:place("sign", "forward", false)
6744+
6745
	T:turnRight(2) --facing start position
6746-
		if not T:place("minecraft:soul_sand", "down", false) then
6746+
6747-
			T:place("minecraft:dirt", "down", false)
6747+
6748
	else	
6749
		lib.buildWall(R, R.length - 1)
6750
		T:go("R1") -- facing start so left turn = turnRight
6751
		lib.buildWall(R, R.width - 1)
6752
		T:go("R1")
6753
		lib.buildWall(R, R.length - 1)
6754
		T:go("R1")
6755
		lib.buildWall(R, R.width - 2)
6756
		T:go("U1")
6757
		T:place(R.useBlockType, 0, "down", true)
6758
	end
6759
	
6760
	return {"Wall or fence completed"}
6761
end
6762
6763
local function createWaterCanal(R) -- 53
6764
	--[[
6765
	designed for 4 turtles, but can be done with 2 as well
6766
	R.data = 1 (2 turtles) or 2 (4 turtles)
6767
	R.height = 0 (in water/ on canal floor) or 1 (at ground level)
6768
	R.side = "R" or "L"
6769
	R.subChoice =
6770-
			if not T:place("minecraft:soul_sand", "down", false) then
6770+
6771
		2 = left side above canal water (new canal only)
6772
		3 = right side above canal water (new canal only)
6773
		4 = right side, ground level (on towpath)
6774
		5 = left side in canal water (if present)
6775
		6 = right side in canal water (if present)
6776
	
6777
	if R.height = 0 then already at correct height on canal floor
6778
		check block below, block to left and block above, move forward tunnelling
6779
		if entering water then move up, onto canal wall and continue pathway
6780
		if tunnelling then flood canal
6781
	else R.height = 1 then above water and on path across
6782
		move forward, checking for water below
6783
		if water finishes, move into canal, drop down and continue tunnelling
6784
	]]
6785
	local lib = {}
6786
	
6787
	function lib.newCanalSide(oTurn)
6788
		T:go("C1 U1x1 U1x1 D2"..oTurn.."1", false, 0, false)
6789
	end
6790
	
6791
	function lib.newCanalBase(R)
6792
		local oTurn = "R"								-- assume R.side = "L"
6793
		if R.side == "R" then
6794
			oTurn = "L"
6795
		end
6796
		if not turtle.detectDown() then					-- air / water below: fill floor
6797
			T:go(oTurn.."1D1")							-- *|>| | | to *|V| | | turn towards canal centre, go down ready to repair neighbouring canal base 
6798
			if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position
6799
				if R.side == "L" then					-- only left side repairs, so wait 1 second
6800
					sleep(1)
6801
					T:go("C1")							-- repair neighbouring canal base
6802
				end
6803
			else
6804
				T:go("C1")								-- repair neighbouring canal base
6805
			end
6806
			T:go(R.side.."1")							-- *|V| | | to *|>| | | turn to face start 
6807
			T:up(1)										-- *|>| | | return to canal floor 
6808
		end
6809
		T:go("C2", false, 0, false)
6810
	end
6811
	
6812
	function lib.newCanal(R)
6813
		--  no source in front as this function called												-- *|<| | |  facing end wall ready for new canal canal base level
6814
		local oTurn = "R"									-- assume R.side = "L"
6815
		if R.side == "R" then
6816-
			T:place("chest", "down")
6816+
6817
		end
6818
		lib.newCanalSide(oTurn)								-- *|<| | | wall fixed. to -- *|^| | | 
6819-
			T:place("chest", "down")
6819+
6820
		lib.newCanalBase(R)									-- *|>| | | base fixed
6821
		T:go("F1"..R.side.."1") 							-- *|>| | | to *| |>| | to *| |^| |
6822
		lib.newCanalSide(oTurn)								-- *| |^| | to *| |>| |
6823-
			T:place("hopper", "forward")
6823+
6824
		T:go("F1"..R.side.."1") 							-- *| |>| | to *| | |>| to *| | |^|
6825
		lib.newCanalSide(oTurn)								-- *| | |^| to *| | |>|
6826
		lib.newCanalBase(R)									-- *| | |>| base fixed
6827
		T:go(R.side.."2") 									-- *| | |>| to *| | |<|facing existing / back wall 
6828
		T:forward(1)										-- *| |<| |
6829
		T:placeWater("forward") 							-- *|W|<| | placed against start wall  
6830
		T:go("L2")											-- *|W|>| |
6831
		T:placeWater("forward") 							-- *|W|>|W| placed direction of travel 
6832
		T:go("R2") 											-- *|W|<|W| rotate
6833
		if deletesWater then
6834
			T:up(1)
6835
		else
6836
			sleep(0.2)
6837
		end
6838
		utils.getWater()									-- *|W|<|W| 
6839
		T:go(oTurn.."2F1")									-- *|W|<|W|  to *|W|W|>|  ready to go	
6840
	end
6841
	
6842
	function lib.towpathOnly(R)
6843
		--[[single turtle on towpath only using 4 turtles. Starts at ground level]]
6844
		for i = 1, R.length do
6845
			if turtle.detectDown() then						-- eg dirt, stone
6846
				T:dig("down")								-- remove block below
6847
			end
6848
			local placeOnly = true
6849
			if R.torchInterval > 0 then						-- place torches
6850
				if i == 1 or i % R.torchInterval == 0 then	-- ready to place torch
6851
					T:go("C2U1")							-- place solid block below, up 1
6852
					T:place("torch", 0, "down")				-- place torch, move forward
6853
					T:go("F1D1")							-- move forward, down
6854
					placeOnly = false		
6855
				end
6856
			end
6857
			if placeOnly then
6858
				T:dig("up")									-- clear blocks above
6859
				if not T:place("stone", 0, "down") then		-- place stone below
6860
					break
6861
				end
6862
				if i < R.length then
6863
					T:forward(1)							-- move forward
6864
				end							
6865
			end
6866
		end
6867
	end
6868
	
6869
	function lib.initialiseCanal(R)
6870
		--[[ move turtle to correct position. return moves]]
6871
		local moves = 1
6872
		local oTurn = "R"
6873
		if R.side == "R" then
6874
			oTurn = "L"
6875
		end
6876
		local newCanal, isWater, isSource = false, false, false
6877
		if R.data == 1 then -- use 2 turtles only
6878
			if R.subChoice == 1 or R.subChoice == 4 then 	-- left / right side on towpath- move into canal space
6879
				if deletesWater then
6880
					T:go(oTurn.."1F1")						-- turn to face canal centre, go forward over water
6881
					isWater, isSource = T:isWater("down")
6882
					if isSource then 						-- canal already exists
6883
						T:go(oTurn.."1")					-- stay above water, face existing canal
6884
					else									-- NOT above source
6885
						T:go("D1"..oTurn.."1")				-- go to canal floor, face existing
6886
						newCanal = true						-- flag create 6 water source blocks
6887
					end
6888
				else										-- NOT deletesWater
6889
					T:go(oTurn.."1F1D1"..oTurn.."1") 		-- move into canal, face back along any existing canal
6890
					isWater, isSource = T:isWater("forward")
6891
					if isSource then
6892
						T:go(R.side.."2") 					-- face forward for new canal
6893
					else
6894
						newCanal = true
6895
					end
6896
				end
6897
			elseif R.subChoice == 2 or R.subChoice == 3 then-- left / right side above canal finishing pos if deletesWater
6898
				if deletesWater then
6899
					isWater, isSource = T:isWater("down")
6900
					if isSource then 
6901
						T:go(R.side.."2")					-- face towards existing canal
6902
					else
6903
						T:go("D1"..R.side.."2")				-- go down and face existing canal		 				-- no water ahead
6904
						newCanal = true						-- already in newCanal starting position
6905
					end
6906
				else										-- NOT deletesWater
6907
					T:go("D1"..R.side.."2")					-- facing existing on canal floor
6908
					isWater, isSource = T:isWater("forward")
6909
					if isSource then						-- water ahead
6910
						T:go(R.side.."2")					-- face forward for new canal
6911
					else 									
6912
						newCanal = true
6913
					end
6914
				end
6915
			elseif R.subChoice == 5 or R.subChoice == 6 then -- left / right  side in canal base. Assume NOT deletesWater
6916-
		T:place("slab", "down")
6916+
6917
				isWater, isSource = T:isWater("forward")
6918
				if isSource then
6919
					T:go(oTurn.."2") 	
6920
				else
6921
					newCanal = true
6922
				end
6923
			end
6924
		else	-- use 4 turtles
6925
			if R.subChoice == 1 or R.subChoice == 4 then 	-- left / right side on towpath stays in place for 4 part canal
6926
			
6927
			elseif R.subChoice == 2 or R.subChoice == 3 then-- left / right side above canal finishing pos if deletesWater
6928
			
6929
			elseif R.subChoice == 5 or R.subChoice == 6 then -- left / right  side in canal base. Assume NOT deletesWater
6930
			
6931
			end
6932
		end
6933
		if newCanal then 								-- no water ahead, facing start wall of new canal *|<| | |
6934
			lib.newCanal(R) 							-- start new canal, finish facing new canal 6 block water sources
6935
			moves = 2
6936
		end
6937
		
6938
		return moves 									-- facing forward ready for new canal *|>| | |
6939
	end
6940
	
6941
	function lib.side(R, maxLength)
6942
		-- Already in position facing new canal, 2 water buckets
6943
		local torch = R.length - maxLength					-- start torch count at 1-2 depending on lib.initialise()
6944
		local sourceCount = 0								-- allow for 1 iteration of placing source blocks when changing from solid to water
6945
		local numBlocks = 0									-- distance travelled
6946
		local _, isSource = nil, false						-- initialise variables
6947
		local oTurn = "R"									-- assume R.side == "L" -> oTurn = "R"
6948
		if R.side == "R" then								-- R.side = "R"
6949
			oTurn = "L"										-- oTurn = "L"
6950
		end
6951
		
6952
		while numBlocks < maxLength do						-- loop from here. Facing forwards to extend canal
6953
			torch = torch + 1								-- increase torch spacing interval
6954
			numBlocks = numBlocks + 1						-- inrease block count
6955
			if deletesWater then							-- up to and including mc 1.12.2
6956
				T:forward(1)								-- move forward to extend canal  | |>|
6957
				_, isSource = T:isWater("down")				-- check if source water below
6958
				if isSource then
6959
					sourceCount = sourceCount + 1			-- count source blocks
6960
				else										
6961
					T:down(1)								-- down to canal floor
6962
					sourceCount = 0							-- reset
6963
					T:go("C2", false, 0, false)				-- place block below
6964
					T:up(1)									-- up to water level
6965
				end											-- still facing away from canal
6966
				T:go(R.side.."1F1C2", false, 0, false) 		-- go above towpath, place stone down, facing out
6967
				if turtle.detectUp() then 					-- ? block above
6968
					T:go(R.side.."2U1F1D1"..R.side.."2")	-- rotate to face canal, up 1 forward over canal, back down to water level, face towpath
6969
				else
6970
					utils.goBack(1)							-- face towpath
6971
				end
6972
				-- facing towpath
6973
				if R.torchInterval > 0 then					-- Are torches required?
6974
					if torch == R.torchInterval  or numBlocks == 0 then		-- check if ready to place
6975
						torch = 0							-- reset interval counter
6976
						T:go("U1F1")
6977
						T:place("torch", -1, "down")		-- place torch
6978
						utils.goBack(1)
6979
						T:down(1)
6980
					end
6981
				end											-- facing towpath, above water
6982
				-- facing towpath
6983
				if isSource and scoreCount > 0 then
6984
					T:go(oTurn.."1x0")						-- face new canal direction
6985
				else										-- not source below, or first time found, ensures continous canal
6986
					T:go(R.side.."1x0")						-- face back to existing canal
6987
					T:placeWater("down")					-- place water
6988
					T:forward(1)							-- forward 1
6989
					T:placeWater("down")					-- place water
6990
					utils.getWater() 							-- collects water from below
6991
					utils.goBack(1) 						-- back 1
6992
					T:go(oTurn.."1x0")						-- face new canal
6993
				end
6994
			else
6995
				T:forward(1) 								-- move forward to extend canal
6996
				_, isSource = T:isWater("forward")			-- check if source water ahead
6997-
			T:place("minecraft:obsidian", "down", false)
6997+
6998
					sourceCount = sourceCount + 1
6999
				else
7000
					sourceCount = 0
7001
					if not turtle.detectDown() then			-- air / water below, but no source in front, so fill it
7002
						T:go(oTurn.."1D1")					-- ready to repair neighbouring canal base
7003
						if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position
7004-
		T:place("minecraft:obsidian", "down", false)
7004+
7005
								sleep(1)
7006
								T:go("C1")					-- repair neighbouring canal base
7007
							end
7008-
		T:place("minecraft:obsidian", "down", false)
7008+
7009
						else
7010
							T:go("C1"..R.side.."1")			-- repair neighbouring canal base if air
7011
						end
7012
						T:up(1)
7013
					end
7014
					T:go("C2", false, 0, false)				-- place block below if not already source
7015
				end
7016
				T:go(R.side.."1C1", false, 0, false) 		-- face canal wall, replace with stone
7017
				
7018
				local placeTorch = false
7019
				if R.torchInterval > 0 then					-- Are torches required?
7020
					if torch == R.torchInterval  or numBlocks == 0 then		-- check if ready to place
7021
						torch = 0							-- reset interval counter
7022
						placeTorch = true
7023
					end
7024
				end
7025
				if (isSource and placeTorch) or not isSource then
7026
					T:go("U1x1 U1x1")						-- up 2 and excavate blocks above tow path
7027
					if placeTorch then						-- torch required
7028
						T:forward(1)						-- move over towpath
7029
						T:place("torch", -1, "down")		-- place torch
7030
						utils.goBack(1)						-- move back
7031
					end
7032
					T:down(2)								-- return to canal base
7033
				end
7034
				if isSource and sourceCount > 1 then 		-- source ahead found at least once
7035
					T:go(oTurn.."1")						-- face newcanal as no water refill required
7036
				else										-- not source in front, or first time found, ensures continous canal
7037
					T:go(oTurn.."1C1") 						-- *| | | |>| face along new canal and block entrance
7038
					utils.goBack(1)							-- *| | |>| | back 1
7039
					T:placeWater("forward")					-- *| | |>|W| place water
7040
					T:go(oTurn.."2") 						-- *| | |<|W| face existing canal 
7041
					_, isSource = T:isWater("forward")		-- *| |?|<|W| check if source water ahead 
7042
					if not isSource then
7043
						if not T:placeWater("forward") then	-- place water again *| |W|<|W|
7044
							while not T:getWater("forward") do -- wait for other turtle
7045
								print("Out of water buckets")
7046
								sleep(1)
7047
							end
7048
							sleep(0.2)
7049
							T:getWater("forward") 
7050
						end
7051
					end
7052
					utils.getWater() 							-- collects water *| |W|<|W|
7053
					T:go(R.side.."2F1") 						-- face along new canal *| |W|>|W| to *| |W|W|>|
7054
				end
7055
			end
7056
		end
7057
	end
7058
		
7059
	function lib.waterOnly(R, maxLength)
7060
		-- Already in position facing new canal, 2 water buckets
7061
		local torch = R.length - maxLength					-- start torch count at 1-2 depending on lib.initialise()
7062
		local sourceCount = 0								-- allow for 1 iteration of placing source blocks when changing from solid to water
7063
		local numBlocks = 0									-- distance travelled
7064
		local _, isSource = nil, false						-- initialise variables
7065
		local oTurn = "R"									-- assume R.side == "L" -> oTurn = "R"
7066
		if R.side == "R" then								-- R.side = "R"
7067
			oTurn = "L"										-- oTurn = "L"
7068
		end
7069
		
7070
		while numBlocks < maxLength do						-- loop from here. Facing forwards to extend canal
7071
			torch = torch + 1								-- increase torch spacing interval
7072
			numBlocks = numBlocks + 1						-- inrease block count
7073
			if deletesWater then							-- up to and including mc 1.12.2
7074
				T:forward(1)								-- move forward to extend canal  | |>|
7075
				_, isSource = T:isWater("down")				-- check if source water below
7076
				if isSource then
7077
					sourceCount = sourceCount + 1			-- count source blocks
7078
				else										
7079
					T:down(1)								-- down to canal floor
7080
					sourceCount = 0							-- reset
7081
					T:go("C2", false, 0, false)				-- place block below
7082
					T:up(1)									-- up to water level
7083
				end											-- still facing away from canal
7084
				if turtle.detectUp() then 					-- ? block above
7085
					T:go("U1x0")							-- break block above
7086
				end
7087
				if not isSource or scoreCount == 0 then		-- not source below, or first time found, ensures continous canal
7088
					T:go(R.side.."2x0")						-- face back to existing canal
7089
					T:placeWater("down")					-- place water
7090
					T:forward(1)							-- forward 1
7091
					T:placeWater("down")					-- place water
7092
					utils.getWater() 						-- collects water from below
7093
					utils.goBack(1) 						-- back 1
7094
					T:go(R.side.."2")						-- face new canal
7095
				end
7096
			else
7097
				T:forward(1) 								-- move forward to extend canal
7098
				_, isSource = T:isWater("forward")			-- check if source water ahead
7099
				if isSource then							-- ? source ahead
7100-
			T:place("minecraft:ladder", "forward", true)
7100+
7101
				else
7102
					sourceCount = 0
7103
					if not turtle.detectDown() then			-- air / water below, but no source in front, so fill it
7104
						T:go(oTurn.."1D1")					-- ready to repair neighbouring canal base
7105
						if T:getBlockType("forward"):find("turtle") ~= nil then -- turtle in similar position
7106
							if R.side == "L" then			-- only left side repairs, so wait 1 second
7107
								sleep(1)
7108
								T:go("C1", false, 0, true)	-- repair neighbouring canal base
7109
							end
7110
							T:go(R.side.."1")				-- face forward
7111
						else
7112
							T:go("C1"..R.side.."1",false, 0, true)	-- repair neighbouring canal base if air
7113
						end
7114
						T:up(1)
7115
					end
7116
					T:go("C2", false, 0, false)				-- place block below if not already source
7117
				end
7118
				if not isSource then
7119
					T:go("U1x0D1")							-- up 1 and excavate blocks above canal. return to canal base
7120
				end
7121-
		T:place("trapdoor", "up", false)
7121+
7122
				if not isSource	and sourceCount == 0 then	-- not source in front, or first time found, ensures continous canal					
7123
					T:go("C1", false, 0, true) 				-- *| | | |>| face along new canal and block entrance
7124
					utils.goBack(1)							-- *| | |>| | back 1
7125
					T:placeWater("forward")					-- *| | |>|W| place water
7126
					T:go(oTurn.."2") 						-- *| | |<|W| face existing canal 
7127
					_, isSource = T:isWater("forward")		-- *| |?|<|W| check if source water ahead 
7128
					if not isSource then
7129
						if not T:placeWater("forward") then	-- place water again *| |W|<|W|
7130
							while not T:getWater("forward") do -- wait for other turtle
7131-
		Build steps up or down ready for railtrack
7131+
7132-
		R.depth = headroom, default 2
7132+
7133
							end
7134
							sleep(0.2)
7135
							T:placeWater("forward") 
7136
						end
7137
					end
7138
					utils.getWater() 							-- collects 2 water *| |W|<|W|
7139
					T:go(R.side.."2F1") 						-- face along new canal *| |W|>|W| to *| |W|W|>|
7140
				end
7141
			end
7142
		end
7143
	end
7144
		
7145
	local maxLength = 512
7146-
				--T:go("U1x0 D1x1 F1x0x1 D1x1 C2", false, 0, false)
7146+
7147-
				T:go("U"..R.depth - 1 .."x0 D"..R.depth - 1 .."x1 F1x0x1 D1x1 C2", false, 0, false)
7147+
7148
	end
7149
	menu.clear()
7150
	menu.colourWrite("Building canal "..R.side.." side", colors.yellow, nil, nil, false, true)
7151
	local moves = lib.initialiseCanal(R) -- move to correct position and/or start new canal
7152-
			--T:go("C1U2 x0D1F1", false, 0, false) --put stone in front, up 2 excavate 1, down 1, forward 1
7152+
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
7153+
7154
	else -- 4 turtles 
7155
		if R.subChoice == 1 or R.subChoice == 4 then -- towpath
7156
			lib.towpathOnly(R)
7157
			--lib.waterCanalTowpath(R, maxLength - moves)
7158
		else -- main canal only
7159
			lib.waterOnly(R, maxLength - moves)
7160
		end
7161
	end
7162
	
7163
	return {}
7164
end
7165
7166
local function createMobGrinder(R)
7167
	-- go down 5 and create a cavity 9 wide, 5 long, 8 high
7168
	-- assume facing out from spawner cube at base of exit (6 blocks above ground
7169
	-- R.subChoice = 1 or 2 (sticky or normal pistons)
7170
	
7171
	local lib = {}
7172
	
7173
	function lib.getInventory(R)
7174
		T:clear()
7175
		menu.colourPrint("All blocks to be ejected. Ready? Enter", colors.red)
7176
		read()
7177
		T:emptyInventory("up")
7178
		T:checkInventoryForItem({"stone"}, {20}, true, "Match existing walls?")
7179
		if R.subChoice == 1 then -- sticky pistons
7180
			T:checkInventoryForItem({"computercraft:computer_normal"}, {1})
7181
			T:checkInventoryForItem({"minecraft:sticky_piston"}, {2})
7182
		else
7183
			T:checkInventoryForItem({"computercraft:computer_normal"}, {2})
7184
			T:checkInventoryForItem({"minecraft:piston"}, {4})
7185
			T:checkInventoryForItem({"computercraft:cable"}, {6})
7186
			T:checkInventoryForItem({"computercraft:wired_modem"}, {2})
7187
		end
7188
		T:checkInventoryForItem({"polished"}, {23}, true, "Any polished block")
7189
		T:checkInventoryForItem({"wall"}, {2}, true, "Any wall block ? match")
7190
		T:checkInventoryForItem({"slab"}, {7}, true, "Any stone slab. ? polished / match")
7191
		T:checkInventoryForItem({"minecraft:glass"}, {2})
7192
		T:checkInventoryForItem({"minecraft:stone_pressure_plate"}, {1})
7193
		T:checkInventoryForItem({"minecraft:dispenser"}, {1})
7194
		T:checkInventoryForItem({"hopper"}, {1})
7195
		T:checkInventoryForItem({"chest"}, {2})
7196
		T:checkInventoryForItem({"minecraft:redstone"}, {9})
7197
		T:checkInventoryForItem({"lava"}, {1})
7198
		R.useBlockType = T:getPolishedItem("")
7199
		if R.useBlockType == "" then
7200
			R.useBlockType = T:getMostItem("", true)
7201
		end
7202
	end
7203
	
7204
	function lib.placeRedstone()
7205
		T:go("D2U2")								-- in left corner facing right 
7206
		T:place("slab", 0, "down")					-- place slab layer 1
7207
		T:up(2)
7208
		T:place("slab", 0, "down")					-- place slab layer 2
7209
		T:up(1)
7210
		T:place("redstone", 0, "down")
7211
		T:go("F1D4 C2L1C1 L1U1", false, 0, false)	-- facing ground level slab
7212
		T:place("redstone", 0, "forward")			-- redstone on ground level slab
7213
		T:up(1)
7214
		T:place("slab", 0, "down")					-- slab on layer 1
7215
		T:up(2)
7216
		T:place("slab", 0, "down")					-- slab on layer 3
7217
		T:up(1)
7218
		T:place("redstone", 0, "down")				-- redstone on layer 3 slab
7219
		utils.goBack(1)
7220
		T:down(3)									-- facing layer 1 slab
7221
		T:place("redstone", 0, "forward")			-- redstone on layer 1 slab
7222
		T:go("D2C2", false, 0, false)				-- under end of chest position
7223
		T:place("redstone", 0, "forward")			-- redstone on level 0 floor
7224
		T:go("R1C1R1", false, 0, false)				-- face right, repair back wall
7225
		T:go("F1C2 L1C1 R1", false, 0, false)		-- under chest start
7226
		T:go("F1C2 L1C1 R1", false, 0, false)		-- under hopper
7227
		T:go("F1C2 L1C1 R1", false, 0, false)		-- under right side wall block
7228
		T:go("U1L2")								-- ready for redstone
7229
		for i = 1, 4 do
7230
			T:place("redstone", 0, "down")			-- redstone under chest etc
7231
			if i < 4 then
7232
				T:forward(1)
7233
			end
7234
		end
7235
		-- finishes facing slab at ground level, redstone below
7236
	end
7237
	
7238
	function lib.placeStorage()
7239
		-- starts facing slab at ground level, redstone below
7240
		T:go("L1F1L2")								-- up and out ready for chest placement
7241
		T:place("chest", 0, "forward")				-- end chest
7242
		T:go("R1F1 L1F1 R1U2")						-- at above start chest position facing right
7243
		T:place("slab", 0, "down")					-- slab above chest
7244
		T:turnLeft(1)
7245
		utils.goBack(1)								
7246
		T:down(2)									-- in front of start chest position
7247
		T:place("chest", 0, "forward")				-- start chest
7248
		T:go("R1F2L2")								-- at pressure plate position facing left
7249
		T:place("wall", 0, "forward")				-- place wall
7250
		T:up(1)
7251
		T:place("pressure", 0, "down")				-- place pressure plate
7252
		T:go("R1F1 L1D1")							-- at second wall position
7253
		T:place("hopper", 0, "forward")				-- place hopper into chest
7254
		utils.goBack(1)
7255
		T:place("wall", 0, "forward")				-- place second wall
7256
		-- finishes on level 1 (ground) facing right side wall block
7257
	end
7258
	
7259
	function lib.placePistons(R)
7260
		-- starts on level 1 (ground) facing right side wall block
7261
		T:go("U1F2 R1")									-- go over wall block, facing back wall layer 2
7262
		T:place(R.useBlockType, 0, "forward", false)	-- replace back wall with polished block layer 2
7263
		T:up(1)											-- layer 3
7264
		T:place(R.useBlockType, 0, "forward", false)	-- replace back wall with polished block layer 3
7265
		T:turnRight(1)									-- face right side
7266
		if R.subChoice == 1 then						-- use sticky pistons x 2
7267
			T:place(R.useBlockType, 0, "forward", false)-- polished block above second wall layer 3
7268
			T:go("R2F1")								-- ready to place lower piston (works ok as slab already in place behind it)
7269
		else
7270
			T:go("F2R2")								-- move forward 2 and face left
7271
			T:place("piston", 0, "forward")				-- lower replacer piston placed
7272
			T:go("U1F2D1F1")							-- go up and over piston forward 1 ready for other piston
7273
		end
7274
		T:place("piston", 0, "forward")					-- lower piston placed
7275
		utils.goBack(1)
7276
		T:go("U1R1")									-- layer 4
7277
		T:place(R.useBlockType, 0, "forward", false)	-- polished block back wall layer 4
7278
		T:go("L1F2R2")									-- head left ready for dispenser
7279
		T:place("dispenser", 0, "forward")				-- dispenser placed
7280
		T:dropItem("lava", "forward")					-- drop lava bucket into dispenser
7281
		T:go("U1F2 D1")									-- up and over dispenser, facing right side
7282
		T:place("slab", 0, "down")						-- lower piston slab placed
7283
		if R.subChoice == 1 then
7284
			T:place(R.useBlockType, 0, "forward", false)-- polished block above second wall layer 4
7285
			T:turnLeft(1)								-- facing back wall
7286
		else
7287
			T:go("F1L1")								-- at second computer position, facing back wall
7288
			utils.goBack(1)								-- ready to place computer
7289
			T:place("computercraft:computer_normal", 0, "forward", false)	-- place computer
7290
			T:go("L1F1R1F1")							-- facing back wall in mob drop, level 4
7291
		end
7292
		T:place(R.useBlockType, 0, "forward", false)	-- polished block back wall layer 4
7293
		T:turnLeft(1)
7294
		T:go("U1F3R2")									-- level 5 ready for upper piston
7295
		T:place("piston", 0, "forward")					-- upper piston placed
7296
		T:go("U1F3D1R2")								-- up and over piston, facing left, level 5
7297
		T:turnRight(1)									-- at mob drop, facing wall, level 5
7298
		T:place(R.useBlockType, 0, "forward", false)	-- polished block back wall layer 5
7299
		T:turnRight(1)									-- facing right side
7300
		if R.subChoice == 1 then
7301
			T:place(R.useBlockType, 0, "forward", false)-- right side polished block layer 5, facing right side, in mob drop 							-- layer 5 facing left side, in mob drop		
7302
		else
7303
			T:go("F1C1")								-- move forward, place temporary block
7304
			utils.goBack(1)
7305
			T:place("piston", 0, "forward")				-- upper replacer piston placed				
7306
		end
7307
		T:turnRight(2)	
7308
		T:place("slab", 0, "forward")					-- upper piston slab placed
7309
		T:turnLeft(1)									-- facing away from back wall
7310
	end
7311
	
7312
	function lib.placeComputer(R)
7313
		-- starts facing away from back wall, layer 5, in mob drop 			
7314
		T:go("F1R1 F2R1 D1")							-- move to left computerposition, facing back wall, layer 4
7315
		T:place("computercraft:computer_normal", 0, "forward", false)		-- place computer in gap, layer 4
7316
	end
7317
	
7318
	function lib.placeColumnSection(direction)
7319
		T:place(R.useBlockType, 0, "forward", false)
7320
		T:go(direction.."1")
7321
		T:place(R.useBlockType, 0, "forward", false)
7322
		T:go(direction.."1")
7323
		T:place(R.useBlockType, 0, "forward", false)	-- facing right
7324
	end
7325
	
7326
	function lib.placeColumns(R)
7327
		-- starts facing left computer, layer 4
7328
		T:go("R1F2 L1")									-- facing mob drop level 4
7329
		T:place("glass", 0, "down", false)
7330
		T:up(1)											-- facing mob drop level 5
7331
		T:place("glass", 0, "down", false)				-- on top of glass facing back wall at dungeon base level 5
7332
		T:up(1)	
7333
		T:place(R.useBlockType, 0, "down", false)		-- level 6 dungeon exit
7334
		T:go("F1L1")
7335
		lib.placeColumnSection("L")						-- facing right
7336
		T:up(1)
7337
		lib.placeColumnSection("R")						-- facing left
7338
		T:up(1)
7339
		lib.placeColumnSection("L")						-- facing right
7340
		T:up(1)
7341
		lib.placeColumnSection("R")						-- facing left
7342
		T:up(1)
7343
		T:place(R.useBlockType, 0, "forward", false)
7344
		T:turnLeft(2)
7345
		T:place(R.useBlockType, 0, "forward", false)	-- facing right
7346
		T:turnLeft(1)									-- at top of column
7347
		T:go("x1D1 x1D1 x1U2")							-- open exit for mobs
7348
		utils.goBack(2)
7349
		T:place(R.useBlockType, 0, "forward", false)
7350
		T:down(9)
7351
	end
7352
	
7353
	function lib.placeNetwork()
7354
		T:go("R1F2L1 F3U3 F1L1F1 L1x1")								-- go behind second computer and remove block
7355
		T:place("computercraft:wired_modem", 0, "forward", false)	-- place modem
7356
		utils.goBack(1)
7357
		T:place("computercraft:cable", 0, "forward", false)			-- place network cable
7358
		T:place("computercraft:cable", 0, "forward", false)			-- place network cable (no need to move)
7359
		T:go("R1F1 x2L1")											-- move forward, face back wall
7360
		T:place("computercraft:cable", 0, "forward", false)
7361
		T:go("R1F1 x2L1")
7362
		T:place("computercraft:cable", 0, "forward", false)
7363
		T:go("R1F1 x2L1F1 x1x2")									-- come behind left computer and expose back
7364
		T:place("computercraft:wired_modem", 0, "forward", false)	-- place modem
7365
		utils.goBack(1)
7366
		T:place("computercraft:cable", 0, "forward", false)
7367
		T:place("computercraft:cable", 0, "forward", false)
7368
		T:go("L1D3 F4R1 F3U4 D4")									-- removes temporary block
7369
	end
7370
	
7371
	local tempSubChoice = R.subChoice	-- store for later use
7372
	R.width = 4							-- settings for createFloorCeiling()
7373
	R.length = 9
7374
	R.height = 0
7375
	R.up = true
7376
	T:turnRight(2)
7377
	local isWater, isSource, isIce, level, isAir = T:isWater("forward")
7378
	if not isWater then
7379
		T:turnRight(2)
7380
		return{"Not in correct position. Must be water behind"}
7381
	end
7382
	--T:go("U1x1 U1L1 F4R2")					-- go up to starting point
7383
	T:go("U2L1 F4R2")					-- go up to starting point
7384
	local data = createFloorCeiling(R)[1] 	-- place ceiling, returns to starting position. if water or lava present is returned as "water or lava found"
7385
	if data == "water or lava found" then
7386
		R.height = 10
7387
		R.silent = true
7388
		T:up(1)
7389
		createSinkingPlatform(R)
7390
		T:go("F4L1 U5x1 U1x1 U3R1 F4C0 R1F3C0 R1F8C0 R1F3C0 R1D9") 			-- re-open exit hole, return to floor level
7391
	else -- no water or lava found so empty out area
7392
		R.height = 10
7393
		R.subChoice = 2
7394
		clearSolid(R) -- 76
7395
		T:down(R.height - 1)
7396
		R.width = 4							-- settings for createFloorCeiling()
7397
		R.length = 9
7398
		R.height = 0
7399
		R.down = true
7400
		R.up = false
7401
		R.subChoice = 1						-- replace existing floor
7402
		createFloorCeiling(R)
7403
	end
7404
	
7405
	R.subChoice = tempSubChoice
7406
	lib.getInventory(R)
7407
	lib.placeRedstone()
7408
	lib.placeStorage()
7409
	lib.placePistons(R)
7410
	lib.placeComputer(R)		-- ends facing computer
7411
	lib.placeColumns(R)
7412
	if R.subChoice == 2 then
7413
		lib.placeNetwork()
7414
	end
7415
	
7416
	return {}
7417
end
7418
7419
local function sandFillArea(R) -- 81
7420
	--clearRectangle with sand drop
7421
	-- could be 1 wide x xx length (trench) up and return
7422
	-- could be 2+ x 2+
7423
	-- even no of runs return after last run
7424
	-- odd no of runs forward, back, forward, reverse and return
7425
	local success
7426
	local directReturn = true
7427
	if R.width % 2 == 1 then
7428
		directReturn = false
7429
	end
7430
	if R.width == 1 then -- trench ahead, so fill then return
7431
		for i = 1, R.length - 1 do
7432
			success = utils.dropSand()
7433
			T:forward(1, false)
7434
		end
7435
		success = utils.dropSand()
7436
		T:go("R2F"..(R.length - 1).."R2", false, 0, false)
7437
	else --2 or more columns
7438
		if directReturn then -- R.width = 2,4,6,8 etc
7439
			for i = 1, R.width, 2 do -- i = 1,3,5,7 etc
7440
				-- move along R.length, dropping sand
7441
				for j = 1, R.length - 1 do
7442
					success = utils.dropSand()
7443
					T:forward(1, false)
7444
				end
7445
				success = utils.dropSand()
7446
				T:go("R1F1R1") --turn right and return on next column
7447
				for j = 1, R.length - 1 do
7448
					success = utils.dropSand()
7449
					T:forward(1, false)
7450
				end
7451
				success = utils.dropSand()
7452
				if i < R.width - 2 then -- eg R.width = 8, i compares with 6: 1, 3, 5, 7
7453
					T:go("L1F1L1")
7454
				end
7455
			end
7456
			T:go("R1F"..R.width - 1 .."R1") --return home
7457
		else
7458
			for i = 1, R.width, 2 do -- i = 1,3,5,7 etc
7459
				-- move along R.length, dropping sand
7460
				for j = 1, R.length - 1 do
7461
					success = utils.dropSand()
7462
					T:forward(1, false)
7463
				end
7464
				success = utils.dropSand()
7465
				T:go("R1F1R1") --turn right and return on next column
7466
				for j = 1, R.length - 1 do
7467
					success = utils.dropSand()
7468
					T:forward(1, false)
7469
				end
7470
				success = utils.dropSand()
7471
				T:go("L1F1L1")
7472
			end
7473
			-- one more run then return
7474
			for j = 1, R.length - 1 do
7475
				success = utils.dropSand()
7476
				T:forward(1, false)
7477
			end
7478
			success = utils.dropSand()
7479
			T:go("R2F"..R.length.."R1F"..R.width - 1 .."R1")
7480
		end
7481
	end
7482
	return {}
7483
end
7484
7485
local function deactivateDragonTower() -- 45
7486
	-- go up centre of tower to bedrock
7487
	local height = 0
7488
	--numBlocksMoved, errorMsg = clsTurtle.doMoves(self, numBlocksRequested, direction)
7489
	local numBlocks, message = T:doMoves(1, "up")
7490
	while message == nil do
7491
		numBlocks, message = T:doMoves(1, "up")
7492
		height = height + 1
7493
	end
7494
	-- go round bedrock and destroy crystal
7495
	T:go("F1R2U2x1U1x1")
7496
	-- return to start
7497
	T:down(height + 5)
7498
	return {}
7499
end
7500
7501
local function undermineDragonTowers() -- 44
7502
	--[[
7503
	        -13, -40....12, -40						NNW (4)   	NNE (5)
7504
			
7505
	    -34, -25............33, -25				NWW	(2)				NEE (9)
7506
		
7507
	-42, -1....................42, 0		W (1)						E (8)
7508
	
7509
	     -34, 24............33,24				SWW	(3)				SEE (10)
7510
		 
7511
		      -13,39....12, 39						SSW	(7)		SSE (6)
7512
	
7513
	North towers centres 25 blocks apart, 40 blocks north of axis
7514
	Mid-North towers 67 blocks apart, 25 blocks north of axis
7515
	W-E centres 84 blocks apart, on 0 axis
7516
	Mid-south towers 67 blocks apart, 24 blocks south of axis
7517
	South towers centres 25 blocks apart, 39 blocks south of axis
7518
	]]
7519
	
7520
	local lib = {}
7521
	function lib.findNextTower(maxDistance, withMarker)
7522
		local distance = 0
7523
		local blockTypeF = T:getBlockType("forward")
7524
		local blockTypeD = T:getBlockType("down")
7525
		for i = 1, maxDistance do
7526
			if blockTypeF ~= "minecraft:obsidian" and blockTypeD ~= "minecraft:obsidian" then -- not in a tower
7527
				if withMarker and blockTypeD ~= "minecraft:obsidian" then -- used to mark 0 coordinate
7528
					T:place("cobble", -1, "down", false) -- place cobblestone or cobbled deepslate to mark zero coordinate
7529
				end
7530
			else	-- obsidian found, could still be in an earlier tower
7531
				if i > 10 then
7532
					break
7533
				end
7534
			end
7535
			T:go("F1x0")
7536
			distance = distance + 1
7537
			blockTypeF = T:getBlockType("forward")
7538
			blockTypeD = T:getBlockType("down")
7539
		end
7540
		if distance == maxDistance then -- obsidian not found ? wrong place/ direction
7541
			print("Obsidian not found")
7542
			error()
7543
		end
7544
		-- will now be at side of a tower
7545
		lib.findCentre() -- move into tower to find the other side
7546
		return distance
7547
	end
7548
	
7549
	function lib.findCentre()
7550
		local width = 0
7551-
			T:place("slab", "down", false)
7551+
7552
		local blockTypeF = T:getBlockType("forward")
7553
		local blockTypeD = T:getBlockType("down")
7554
		while blockTypeF == "minecraft:obsidian" or blockTypeD == "minecraft:obsidian" do
7555
			T:go("F1x0")
7556
			width = width + 1
7557
			blockTypeF = T:getBlockType("forward")
7558
			blockTypeD = T:getBlockType("down")
7559
		end
7560
		-- will always go outside the tower 1 block. width of 5 block tower = 6
7561
		T:go("R2F"..math.ceil(width / 2)) --return to centre of tower
7562
		T:turnLeft(1) -- now find another edge of the tower, dig forward until out of obsidian
7563
		for i = 1, math.ceil(width) do  -- give additional loops if missed centre
7564
			blockTypeF = T:getBlockType("forward")
7565
			blockTypeD = T:getBlockType("down")
7566
			if blockTypeF == "minecraft:obsidian" or blockTypeD == "minecraft:obsidian" then
7567
				T:go("F1x0")
7568
			else
7569
				break
7570
			end
7571
		end
7572
		-- now outside different edge of the tower
7573
		-- reverse and move width/2, dig up + 1 to mark centre, face original direction
7574
		T:go("L2F"..math.ceil(width / 2).."R1U2x1")
7575
		T:place("minecraft:end_stone", -1, "forward", false) -- place endstone to mark facing direction
7576
		T:down(2)
7577
	end
7578
	
7579
	function lib.findPath(maxLength)
7580
		local blockTypeD = T:getBlockType("down")
7581
		local distance = 0
7582
		while blockTypeD:find("cobble") == nil and distance < maxLength do
7583
			T:go("F1x0")							-- return to 0 axis, 
7584
			distance = distance + 1
7585
			blockTypeD = T:getBlockType("down")
7586
		end
7587
		return distance
7588
	end
7589
	
7590
	-- start at 0,y,0, facing West
7591
	T:dig("up")									-- in case not already done
7592
	local maxLength = 0
7593
	local blockTypeD
7594
	local distance = lib.findNextTower(45, true)-- find W tower (1) and mark trail with cobble
7595
	T:turnRight(2)						
7596
	for i = 1, 8 do								-- head back East 8 blocks, turn left (facing north)
7597
		T:go("F1x0")							-- this path may be off-axis, so dig double height
7598
	end
7599
	T:turnLeft(1)
7600
	lib.findNextTower(30)						-- find NWW tower (2)
7601
	T:turnRight(2)
7602
	distance = lib.findPath(30)
7603
	distance = distance + lib.findNextTower(30)	-- find SWW tower (3)
7604
	T:turnRight(2)
7605
	distance = lib.findPath(30)
7606
	T:turnRight(1) 								-- should be on cobble path
7607
	for i = 1, 21 do							-- move East 21 blocks, turn left facing North
7608
		T:go("F1x0")
7609
	end
7610
	T:turnLeft(1)
7611
	
7612
	distance = lib.findNextTower(45)		-- find NNW tower (4)
7613
	T:turnRight(1)							
7614
	distance = lib.findNextTower(30)		-- find NNE tower (5)
7615
	T:turnRight(1)
7616
	distance = lib.findNextTower(85)		-- find SSE tower (6)
7617
	T:turnRight(1)
7618
7619
	distance = lib.findNextTower(30)		-- find SSW tower (7)
7620
	T:turnRight(1)
7621
	distance = lib.findPath(40)				-- head North to 0 axis
7622
	T:go("R1F13") 							-- return to 0,0 facing East
7623
	distance = lib.findNextTower(45, true)	-- find E tower (8)
7624
	
7625
	T:turnRight(2)						
7626
	for i = 1, 9 do
7627
		T:go("F1x0")						-- this path may be off-axis, so dig double height
7628
	end
7629
	T:turnRight(1)
7630
	
7631
	distance = lib.findNextTower(30)		-- find NEE tower (9)
7632
	T:turnRight(2)
7633
	distance = lib.findPath(30) -- return to 0 axis
7634
	distance = lib.findNextTower(30)		-- find SEE tower (10)
7635
	T:turnRight(2)
7636
	distance = lib.findPath(30) 			-- return to 0 axis
7637
	T:go("L1F33")							-- return to 0, 0
7638
	
7639
	return {}
7640
end
7641
7642
local function demolishPortal(R) -- 43
7643
	--[[
7644
	R.length = length of portal NOT width default 4
7645
	R.height = height of portal default 5
7646
	R.width = thickness of portal default 1
7647
	R.data = "bury" to embed bottom into ground
7648
	R.subChoice 1 = facing portal, 2 = aligned
7649
	]]
7650
	local data = R.data
7651
	if R.subChoice == 1 then -- facing portal
7652
		T:go("F"..R.width.."R1")
7653
	else
7654
		T:forward(1)
7655
	end
7656
	if R.data == "bury" then
7657
		T:down(1)
7658
	end
7659
7660
	R.data = "up"
7661
	R.silent = true
7662
	if R.width == 1 then
7663
		clearWall(R)
7664
	else
7665
		clearBuilding(R, true, true)
7666
	end
7667
	if data == "bury" then
7668
		T:up(1)
7669
	end
7670
	if R.subChoice == 1 then -- facing portal
7671
		T:go("R1F1L1F1L1")
7672
	end
7673
	
7674
	return {}
7675
end
7676
7677
local function digTrench(R) -- 77
7678
	local blockType
7679
	-- go down R.height, move forward
7680
	if R.length == 0 then
7681
		R.length = 4096 -- will go out of loaded chunks and stop or max 4096 on a server
7682
	end
7683
	for i = 1, R.length do
7684
		local count = 0
7685
		for down = 1, R.height do
7686
			blockType = T:isWaterOrLava("down") 
7687
			-- go down only if no water or lava below
7688
			if blockType:find("water") == nil and blockType:find("lava") == nil then
7689
				T:down(1)
7690
				count = count + 1
7691
			end 
7692
		end
7693
		T:go("C2", false, 0, true)				-- if empty below fill void
7694
		T:go("U"..count)						-- return to surface, continue if block above
7695
		while turtle.detect() do				-- go up while block in front
7696
			blockType = T:getBlockType("forward")
7697
			if T:isVegetation(blockType) then
7698
				T:dig("forward")
7699
				break
7700
			elseif blockType:find("log") ~= nil then
7701
				T:harvestTree("forward", false)
7702
			else
7703
				T:up(1)
7704
			end
7705
		end
7706
		T:forward(1)							-- move forward
7707
		while not turtle.detectDown() do		-- go down until block detected
7708
			blockType = T:isWaterOrLava("down") 
7709
			if blockType:find("water") == nil and blockType:find("lava") == nil then
7710
				T:down(1)
7711
			else
7712
				break
7713
			end
7714
		end
7715
	end
7716
	
7717
	return {}
7718
end
7719
7720
local function harvestTreeFarm(R) -- 24
7721
	local lib = {}
7722
	
7723
	function lib.getLogCount()
7724
		local count = 0
7725
		for i = 1,16 do
7726
			local item, itemCount = T:getSlotContains(i)
7727
			if item:find("log") ~= nil then
7728
				count = count + itemCount
7729
			end
7730
		end
7731
		
7732
		return count
7733
	end
7734
	
7735
	function lib.initialise()
7736
		local blockType = T:getBlockType("forward")
7737
		local logType = ""
7738
		local startHeight = 0
7739
		local range = 0
7740
		if blockType == "" then
7741
			while turtle.forward() do
7742
				range = range + 1
7743
				if range == 3 then
7744
					break
7745
				end
7746
			end
7747
		end
7748
		blockType = T:getBlockType("forward")
7749
		if blockType:find("dirt") ~= nil then
7750
			T:up(1)
7751
			startHeight = 1
7752
		else
7753
			if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil then
7754
				logType = blockType
7755
			end
7756
		end
7757
		
7758
		return logType, startHeight
7759
	end
7760
	
7761
	R.silent = true
7762
	local treeType, startHeight = lib.initialise() -- possible ID tree type + move to correct position 1 above dirt
7763
	
7764
	T:forward(1)	-- dig first log/sapling/ air if not planted
7765
	clearRectangle({width = 7, length = 7, up = true, down = true})
7766
	T:go("L1F2L1F2R2")
7767
	local height = 0
7768
	local pastLogCount = -1
7769
	local currentLogCount = lib.getLogCount()
7770
	while currentLogCount ~= pastLogCount do
7771
		T:up(3)
7772
		height = height + 3
7773
		pastLogCount = currentLogCount -- 0 when loop starts
7774
		clearRectangle({width = 12, length = 12, up = true, down = true})
7775
		currentLogCount = lib.getLogCount() -- eg 20 logs from first round
7776
	end	
7777
	T:down(height + startHeight)
7778
	T:go("R1F2R1F2R2")
7779
	
7780
	return {}
7781
end
7782
7783
local function harvestObsidian(R) -- 41
7784
	local lib = {}
7785
	
7786
	function lib.forward(move)
7787
		T:isWaterOrLava("forward")	-- automatically use lava ahead to refuel
7788
		T:isWaterOrLava("down") 	-- automatically use lava down to refuel
7789
		T:go("C2", false, 0, false)	-- place / replace block below
7790
		if move then
7791
			T:forward(1)
7792
		end
7793
	end
7794
	
7795
	function lib.home(outward)
7796
		if outward then
7797
			T:go("L1F"..R.width - 1 .."L1F"..R.length - 1)
7798
		else	
7799
			T:go("R1F"..R.width - 1 .."R1")
7800
		end
7801
	end
7802
	
7803
	function lib.start()
7804
		local lavaSlot = T:getItemSlot("lava")
7805
		if lavaSlot > 0 then
7806
			turtle.select(slot)
7807
			turtle.refuel()
7808
		end
7809
		T:down(1)
7810
	end
7811
	
7812
	local outward = true
7813
	
7814
	lib.start()						-- use lava bucket if placed, move down into block below
7815
	for w = 1, R.width do
7816
		for l = 1, R.length do
7817
			if l < R.length then
7818
				lib.forward(true)
7819
			else
7820
				lib.forward(false)
7821
			end
7822
		end
7823
		if w < R.width then
7824
			if outward then
7825
				T:go("R1F1R1")
7826
			else
7827
				T:go("L1F1L1")
7828
			end
7829
			outward = not outward
7830
		end
7831
	end
7832
	
7833
	lib.home(outward)
7834
	
7835
	return {}
7836
end
7837
7838
local function harvestShulkers(R)
7839
	local lib = {}
7840
	
7841
	function lib.attackAll()
7842
		return turtle.attack(), turtle.attackUp(), turtle.attackDown()
7843
	end
7844
7845
	function lib.attack()
7846
		local forward, up, down = lib.attackAll()
7847
		while forward or up or down do
7848
			forward, up, down = lib.attackAll()
7849
			sleep(0.2)
7850
		end
7851
	end
7852
	
7853
	function lib.approach(direction, limit, dig)
7854
		-- move forward until stopped by shulker
7855
		limit = limit or 64
7856
		dig = dig or false
7857
		local count = 0
7858
		local solidDown = false
7859
		move = turtle.forward
7860
		if direction == "up" then
7861
			move = turtle.up
7862
		elseif direction == "down" then
7863
			move = turtle.down
7864
		end
7865
		local forward, up, down = lib.attackAll()
7866
		if forward or up or down then -- attacks suceeded
7867
			return true, 0, solidDown
7868
		else
7869
			while move() do
7870
				count = count + 1
7871
				if turtle.detectDown() then
7872
					solidDown = true
7873
				end
7874
				if count >= limit then
7875
					return false, count, solidDown
7876
				end
7877
				forward, up, down = lib.attackAll()
7878
				if forward or up or down then
7879
					return true, count, solidDown
7880
				else
7881
					if dig then
7882
						T:dig("forward")
7883
					end
7884
				end
7885
			end
7886
			return false, count, solidDown
7887
		end
7888
	end
7889
	
7890
	function lib.home(direction, moves)
7891
		local move = turtle.back
7892
		if direction == "up" then
7893
			move = turtle.down
7894
		elseif direction == "down" then
7895
			move = turtle.up
7896
		end
7897
		for i = 1, moves do
7898
			move()
7899
		end
7900
	end
7901
	
7902
	function lib.checkPosition()
7903
		if T:detect("forward") then			-- wall in front
7904
			T:turnRight(1)
7905
			if T:detect("forward") then		-- wall to right
7906
				T:turnLeft(1)
7907
				return true					-- position corrected
7908
			else
7909
				T:turnLeft(2)
7910
				if T:detect("forward") then	-- wall in front. position correct
7911
					return true
7912
				end
7913
			end
7914
		end
7915
		return false
7916
	end
7917
	
7918
	function lib.getLength()
7919
		local count = 0
7920
		while turtle.detectDown() do
7921
			count = count + 1
7922
			T:forward(1)
7923
		end
7924
		utils.goBack(1)
7925
		return count
7926
	end
7927
	
7928
	function lib.clearWall()
7929
		local distance = 0
7930
		while distance < 9 do	-- smallest external walls are 8 x 8
7931
			local success, count = lib.approach("forward", 8 - distance)
7932
			if success then
7933-
			--T:place("stone", "forward", false) -- place does not allow for specific blocktype
7933+
7934
			end
7935
			distance = distance + count
7936
		end
7937
		T:turnLeft(1)
7938
		if T:detect("forward") then	-- larger than 8 blocks
7939
			T:turnRight(1)
7940
			while distance < 14 do	-- larger builds are 14 x 14
7941
				local success, count = lib.approach("forward", 13 - distance)
7942
				if success then
7943
					lib.attack()
7944
				end
7945
				distance = distance + count
7946
			end
7947
			T:go("L1x2")
7948
		end
7949
	end
7950
	
7951
	function lib.roof()
7952
		-- check position
7953
		local doContinue = lib.checkPosition()
7954
		
7955
		if doContinue then
7956
			T:go("U2F3 R1F3 R1")
7957
			local length = lib.getLength()
7958
			local width = 1
7959
			local outward = lib.turnRound(true)	
7960
			local success, count, onRoof = false, 0, true	
7961
			while onRoof do
7962
				local distance = 0
7963
				while distance < length - 1 do
7964
					success, count, onRoof = lib.approach("forward", length - 1 - distance)
7965
					if success then
7966
						lib.attack()
7967
					end
7968
					if count == 0 then
7969
						turtle.dig()
7970
					end
7971
					distance = distance + count
7972
				end
7973
				width = width + 1
7974-
				T:place("minecraft:torch", "down")
7974+
7975
			end
7976
			if outward then
7977
				T:go("F".. 3 .."L1F"..width - 3 .."D2L1")
7978
			else
7979
				T:go("F".. length - 3 .."R1F"..width - 3 .."D2L1")
7980
			end
7981
			return {}
7982
		else
7983
			return {"Turtle not in front of a wall"}
7984
		end
7985
	end
7986
	
7987
	function lib.turnRound(outward)
7988
		if outward then
7989
			T:go("R1F1R1")
7990
		else
7991
			T:go("L1F1L1")
7992
		end
7993
		return not outward
7994
	end
7995
7996
	function lib.upAndOver()
7997
		local start, height, forward = 0, 0, 0
7998
		while turtle.detect() do
7999
			turtle.up()
8000
			start = start + 1
8001
		end
8002
		while turtle.forward() do
8003
			forward = forward + 1
8004
		end
8005
		turtle.turnRight()
8006-
	function lib.buildWallSection(section, useBlockType)
8006+
8007-
		-- build a layer 1 block high below turtle
8007+
8008-
		for i = 1, #section do
8008+
8009-
			local block = section:sub(i, i)
8009+
8010-
			if block == "l" then
8010+
8011-
				T:place("log", "down")
8011+
8012-
			elseif block == "m" then
8012+
8013-
				T:place("modem", "down")
8013+
8014-
			elseif block == "b" then
8014+
8015-
				T:place("barrel", "down")
8015+
8016-
			elseif block == "c" then
8016+
8017-
				T:place("cable", "down")
8017+
8018
		end
8019-
				T:place(useBlockType, "down")
8019+
8020
		for i = 1, forward do
8021-
			if i < #section then
8021+
8022
		end
8023
		for i = 1, start do
8024
			turtle.down()
8025
		end
8026
		T:turnRight(2)
8027
	end
8028
	
8029-
			while turtle.digUp() do end
8029+
8030-
			turtle.digDown()
8030+
8031-
			T:place(useBlockType, "down")
8031+
8032-
			--T:go("x0C2", false, 0, false, useBlockType)
8032+
8033
			for i = 1, 4 do
8034-
				while not turtle.forward() do
8034+
8035-
					turtle.dig()
8035+
8036
			T:go("F2L1 U1F2 R2")
8037-
				--T:forward(1)
8037+
8038
			return {"Turtle not in front of a wall"}
8039
		end
8040
	end
8041
		
8042
	local direction = "forward"
8043
	local doContinue = false
8044
	
8045
	if R.subChoice == 1 then		-- Shulker is above
8046
		direction = "up"
8047
		doContinue = true
8048
	elseif R.subChoice == 2 then	-- Shulker is ahead
8049
		doContinue = true
8050
	elseif R.subChoice == 3 then	-- Shulker is below
8051
		direction = "down"
8052
		doContinue = true
8053
	else
8054
		if R.subChoice == 4 then	-- Climb tower wall
8055
			lib.upAndOver()
8056
		elseif R.subChoice == 5 then	-- Clear roof above
8057
			return lib.roof()
8058
		elseif R.subChoice == 6 then	-- Clear outside walls
8059
			lib.walls()
8060
		end
8061
	
8062
	end
8063
	if doContinue then
8064
		local success, moves = lib.approach(direction, 64)
8065
		if success then
8066
			lib.attack()
8067
		end
8068
		lib.home(direction, moves)
8069
	end
8070-
	function lib.findLegacyStart()
8070+
8071
	return {}
8072-
		local block = T:getBlockType("down")
8072+
8073-
		if block:find("polished") ~= nil then
8073+
8074-
			return ""	-- in correct position, facing centre of front wall
8074+
8075
	local lib = {}
8076-
		-- assume on left corner
8076+
8077-
		T:forward (1)
8077+
	function lib.checkEquipment()
8078-
		local couint = 0
8078+
		--[[ Needs pickaxe and hoe equipped ]]
8079-
		while (T:getBlockType("down")):find("polished") == nil do
8079+
8080
		--T:checkInventoryForItem(items{}, quantities{}, required, message)
8081
		print("Checking equipment. Please wait...")
8082-
			if count > 10 then
8082+
		local equippedRight, equippedLeft, inInventory = T:setEquipment() -- any tools equipped except diamond_pickaxe and crafting_table have been removed to inventory
8083-
				return "Unable to locate polished block"
8083+
		--[[if equippedRight ~= "minecraft:crafting_table" then
8084
			T:checkInventoryForItem({"minecraft:crafting_table"}, {1})
8085
			local equippedRight, equippedLeft = T:setEquipment()
8086
		end]]
8087
		T:suck("down")		-- if hoe already in storage get it out
8088
		if inInventory ~= "minecraft:diamond_hoe" then
8089-
	function lib.floodFarm(R)
8089+
			if T:getItemSlot("minecraft:diamond_hoe") > 0 then
8090
				return true
8091-
		T:sortInventory(false)
8091+
8092-
		for i = 1, R.width - 2 do
8092+
				T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!")
8093-
			lib.placeFloor(R.length - 2, R.useBlockType)
8093+
8094-
			if i < R.width - 2 then
8094+
8095-
				outward = lib.turn(outward)
8095+
		if T:getItemSlot("minecraft:diamond_hoe") > 0 then
8096
			return true
8097
		end
8098-
		T:go("U1R2") -- over 13 x 13 internal area opposite corner
8098+
8099-
		-- now add corners
8099+
8100-
		lib.placeCorners(R.length - 2, 4, R.useBlockType)
8100+
8101-
		outward = lib.turn(outward)
8101+
8102-
		lib.placeCorners(R.length - 2, 3, R.useBlockType)
8102+
8103-
		outward = lib.turn(outward)
8103+
		--[[ first function called on start]]
8104-
		lib.placeCorners(R.length - 2, 2, R.useBlockType)
8104+
		local atHome = false
8105-
		outward = lib.turn(outward)
8105+
8106-
		lib.placeCorners(R.length - 2, 1, R.useBlockType)
8106+
		print("Checking position "..blockType.. " below")
8107
		if blockType:find("water") ~= nil then -- over water
8108-
			T:go("R1F"..R.width - 9 .."R1")
8108+
			if lib.isStorage("forward") then
8109
				atHome = true
8110-
			T:go("L1F"..R.width - 9 .."L1")
8110+
8111
				if lib.isStorage("forward") then-- confirms in correct position, back to crops
8112
					T:turnRight(2)
8113-
		lib.placeCorners(R.length - 2, 1, R.useBlockType)
8113+
				else -- facing crafting table
8114-
		outward = lib.turn(outward)
8114+
8115-
		lib.placeCorners(R.length - 2, 2, R.useBlockType)
8115+
8116-
		outward = lib.turn(outward)
8116+
			else -- not a chest: facing crops or crafting table
8117-
		lib.placeCorners(R.length - 2, 3, R.useBlockType)
8117+
8118-
		outward = lib.turn(outward)
8118+
				if lib.isStorage("forward") then -- confirms was facing crops
8119-
		lib.placeCorners(R.length - 2, 4, R.useBlockType) -- should be back in starting corner facing front
8119+
					atHome = true
8120
					T:turnLeft(1)
8121-
		T:go("U1R1")
8121+
8122-
		lib.placeWater(R.length - 3) -- place water down then move forward, turn right
8122+
8123-
		lib.placeWater(R.width - 3)
8123+
			-- should now be facing crops. may be crafting table to left
8124-
		lib.placeWater(R.length - 3) 
8124+
8125-
		lib.placeWater(R.width - 3)
8125+
		return atHome-- now facing crops
8126-
		T:go("F".. math.floor((R.length - 2) / 2).."R1F".. math.floor((R.width - 2) / 2)) -- should be in centre
8126+
8127
	
8128-
		--T:go("D6x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 R1F7 R1U1")
8128+
	function lib.crossFarm()
8129-
		T:go("D6F7 R1F7 R1U1") -- end facing back at left corner, 1 block above floor/1 below ceiling
8129+
8130
		local blockType = ""
8131
		local isReady, cropType, status = lib.isCropReady("down")
8132-
	function lib.clearBasement()
8132+
		-- will go forward until chest or cobble detected below
8133-
		T:sortInventory(false)
8133+
8134-
		T:dropItem("seeds", "forward")
8134+
8135-
		T:dropItem("flint", "forward")
8135+
8136-
		clearRectangle({width = 15, length = 15, up = true, down = true})
8136+
8137-
		-- area has been cleared. starts facing back, 1 block above ground, 1 block below ceiling
8137+
			blockType = T:getBlockType("down", -1)
8138
			if blockType == "" or cropType ~= "" then --crops or nothing below
8139-
		for i = 1, 14 do	-- place cable into gutter beneath front of farm
8139+
8140-
			T:place("cable", "up")
8140+
			elseif  blockType:find("barrel") ~= nil or blockType:find("chest") ~= nil or blockType:find("cobble") ~= nil then
8141-
			if i < 14 then
8141+
8142
			end
8143
			numMoves = numMoves + 1
8144
		end
8145-
		-- ends right side facing right, just below ceiling
8145+
		return blockType -- either chest or cobble
8146
	end
8147
	
8148
	function lib.farmInFront()
8149
		--[[ facing crops on first farm. move to next farm in front ]]
8150
		T:go("U1L1F11D1R1")							-- on next farm, facing crops
8151-
	-- R.data = "new", "left", "right" or "back" to extend tree farm
8151+
		local crop = lib.manageTree()				-- refuel, gather seeds and other crops
8152
		local isFarmToRight, _ = lib.harvest(crop)	-- harvest field, store crops
8153-
	-- R.networkFarm to create storage area
8153+
		return isFarmToRight
8154
	end
8155
	
8156
	function lib.farmToRight()
8157-
	-- R.data = "new", "left", "right", "back", "convertStorage", "convert"
8157+
8158-
	if R.data == "new" then -- new treeFarm, Start at current position
8158+
		T:go("U1F11 D1")				-- on next farm, facing crops
8159-
		-- build 4 wall sections in 2 passes
8159+
		local crop = lib.manageTree()	-- refuel, gather seeds and other crops
8160
		lib.harvest(crop)				-- harvest field, store crops
8161-
		lib.buildWallSection("---------------", R.useBlockType)		-- left wall (15 blocks)
8161+
8162-
		T:go("R1F1")
8162+
8163
	function lib.getCrops()
8164-
			lib.buildWallSection("--------------", R.useBlockType)	-- back/ right wall (14 blocks)
8164+
8165
8166
		if lib.isStorage("forward") then
8167-
		lib.buildWallSection("------c------", R.useBlockType)		-- front wall (14 blocks) c = network cable
8167+
			lib.getSeeds("forward")
8168
		end
8169-
		lib.buildWallSection("---------------", R.useBlockType)		-- left wall top (15 blocks)
8169+
8170-
		T:go("R1F1")
8170+
		if lib.isStorage("forward") then
8171
			lib.getVeg("forward")
8172-
			lib.buildWallSection("--------------", R.useBlockType)	--back/right wall (14 blocks)
8172+
8173
		T:turnRight(2)
8174
	end
8175-
		--lib.buildWallSection("-----lmb-----", R.useBlockType)	--front wall (14 blocks) log/modem/barrel
8175+
8176-
		lib.buildWallSection("-----lmb", R.useBlockType)
8176+
	function lib.getSaplings(direction)
8177
		--[[ get a single sapling from the chest ]]
8178-
		network.attachModem()
8178+
8179
			direction = "forward"
8180-
		lib.buildWallSection("-----", R.useBlockType)	
8180+
8181-
		T:go("R1F1 D2") -- over 13 x 13 internal area
8181+
		while T:suck(direction, 1) do end -- remove saplings/ seeds
8182-
	elseif R.data == "left" or R.data == "right" or R.data == "back" then
8182+
8183-
		-- build 3 wall sections in 2 passes
8183+
		T:dropItem("sapling", direction, 1) -- drop all but 1 saplings
8184-
		if R.data == "left" then										-- should be on left corner of existing
8184+
		if not T:dropItem("seeds", direction, 0) then-- drop all seeds
8185-
			T:go("L1F1 D1") 											-- move left 1 blocks, down 1: <-
8185+
			T:dropItem("seeds", "up", 0)
8186-
			lib.buildWallSection("------c-------", R.useBlockType)		-- front wall (14 blocks) c = network cable <-
8186+
8187
		
8188-
			lib.buildWallSection("--------------", R.useBlockType)		-- left wall (14 blocks) ^
8188+
		return T:getItemSlot("sapling", -1)
8189
	end
8190-
			lib.buildWallSection("-------------", R.useBlockType)		-- back wall (13 blocks) ->
8190+
8191-
			T:go("U1R2")												-- turn round ready to add next layer <-
8191+
	function lib.getSeeds(direction)
8192-
			lib.buildWallSection("--------------", R.useBlockType)		-- back wall top (14 blocks) <-
8192+
		--[[ get 1 stack of wheat seeds or 1 stack of beetroot seeds ]]	
8193
		print("Collecting seeds from storage")
8194-
			lib.buildWallSection("--------------", R.useBlockType)		-- left wall top (14 blocks) v
8194+
		while T:suck(direction, 1) do end -- remove saplings/ seeds
8195
		T:dropItem("sapling", direction, 0) -- drop all saplings
8196-
			lib.buildWallSection("-----bm", R.useBlockType)				-- front wall (7 blocks) barrel/modem ->
8196+
		T:dropItem("minecraft:wheat_seeds", direction, 64) -- drop all but 64 seeds
8197-
			network.attachModem()
8197+
		T:dropItem("minecraft:beetroot_seeds", direction, 64)
8198
		local crop = ""
8199-
			lib.buildWallSection("l-----", R.useBlockType)				-- front wall (5 blocks) log ->
8199+
		if T:getItemSlot("minecraft:wheat_seeds", -1) > 0 then
8200-
			T:go("R2F12 R1F1 D2") 										-- over 13 x 13 internal area lower left side
8200+
			crop = "wheat"
8201-
		elseif R.data == "right" then									-- should be on right corner of existing
8201+
			print("Field crop = "..crop)
8202-
			T:go("R1F1 D1") 											-- move right, forward, down 1
8202+
		elseif T:getItemSlot("minecraft:beetroot_seeds", -1) > 0 then
8203-
			lib.buildWallSection("------c-------", R.useBlockType)		-- front wall (14 blocks) c = network cable
8203+
			crop = "beetroot"
8204
			print("Field crop = "..crop)
8205-
			lib.buildWallSection("--------------", R.useBlockType)		-- right wall (14 blocks)
8205+
8206
		
8207-
			lib.buildWallSection("-------------", R.useBlockType)		-- back wall (13 blocks)
8207+
		return crop
8208-
			T:go("U1R2")												-- turn round ready to add next layer
8208+
8209-
			lib.buildWallSection("--------------", R.useBlockType)		-- back wall top (14 blocks)
8209+
8210
	function lib.getVeg(direction)
8211-
			lib.buildWallSection("--------------", R.useBlockType)		-- left wall top (14 blocks)
8211+
8212
		print("Collecting crops from storage")
8213-
			lib.buildWallSection("-----lmb", R.useBlockType)
8213+
8214
		while T:suck(direction, 1) do end -- remove carrots / potatoes / wheat / beetroot
8215-
			network.attachModem()
8215+
		--clsTurtle.dropItem(self, item, direction, keepAmount)
8216-
			T:forward(2)
8216+
		T:dropItem("wheat", direction, 0)		-- drop all wheat
8217-
			lib.buildWallSection("-----", R.useBlockType)	
8217+
		T:dropItem("beetroot", direction, 0)	-- drop all beetroot
8218-
			T:go("R1F1 D2") 											-- over 13 x 13 internal area
8218+
		T:dropItem("carrot", direction, 64)		-- drop all but 64 carrots
8219-
		elseif R.data == "back" then									-- should be on left front corner of existing
8219+
		T:dropItem("potato", direction, 64)		-- drop all but 64 potato
8220-
			T:go("R2F1 D4R2 F1") 										-- move forward 14 blocks, down 1
8220+
		local crop = ""
8221-
			for i = 1, 15 do
8221+
		if T:getItemSlot("potato", -1) > 0 then
8222-
				T:place("cable", "up")
8222+
			crop = "potato"
8223
			print("Field crop = "..crop)
8224
		elseif T:getItemSlot("carrot", -1) > 0 then
8225
			crop = "carrot"
8226-
			if T:getBlockType("up") == R.useBlockType then				-- already a farm on left side
8226+
			print("Field crop = "..crop)
8227-
				T:go("U2C2 U1C2 F13R1 F1D1", false, 0, false, R.useBlockType)
8227+
8228-
				lib.buildWallSection("--------------", R.useBlockType)	-- back wall (14 blocks)
8228+
8229
		--T:turnRight(2) -- face crops
8230
		return crop
8231
	end
8232-
				lib.buildWallSection("--------------", R.useBlockType)	-- left wall (14 blocks)
8232+
8233
	function lib.goHome()
8234-
				lib.buildWallSection("--------------", R.useBlockType)	-- back wall (14 blocks)
8234+
8235
		local onTree = false
8236
		-- is tree above or in front
8237
		-- check if log in front
8238-
			lib.buildWallSection("-------------", R.useBlockType)		--right wall (13 blocks) no special blocks
8238+
8239-
			T:go("U1R2")	-- turn round ready to add next layer
8239+
			lib.harvestTree("forward") -- will only harvest if fuel below half of limit
8240-
			for i = 1, 2 do
8240+
8241-
				lib.buildWallSection("--------------", R.useBlockType)	--right wall top (14 blocks) no special blocks
8241+
8242-
				T:go("L1F1")
8242+
			lib.harvestTree("up")
8243
			onTree = true
8244-
			lib.buildWallSection("-------------", R.useBlockType)		-- left wall top (13 blocks) no special blocks
8244+
		elseif T:getItemSlot("log", -1) > 0 then -- tree just harvested 
8245-
			T:go("F1L1 F7x2")
8245+
8246-
			T:go("D1x2")
8246+
8247-
			T:place("cable", "down")
8247+
8248
				lib.harvestTree("up")
8249-
			T:place("modem", "down")
8249+
8250-
			T:go("F1R2x2")
8250+
				while turtle.down() do end
8251-
			T:place("log", "down")
8251+
8252-
			T:go("F2x2")
8252+
8253-
			T:place("barrel", "down")
8253+
8254
		if onTree then -- tree harvested, but direction unknown
8255-
			network.attachModem()
8255+
8256-
			T:go("F6R1 F1D2")
8256+
			local turns = 0
8257
			local onChest = lib.isStorage("down")
8258-
	else -- convertStorage or convert
8258+
			while not onChest do
8259-
		-- legacy farm had polished block on positions 4 / (10) from left corner
8259+
8260-
		 local message = lib.findLegacyStart()
8260+
					if lib.isStorage("down") then
8261-
		 if message ~= "" then
8261+
						onChest = true
8262-
			return {message}
8262+
8263-
		 end
8263+
						turtle.back()
8264-
		 -- now on top of polished block, 4 from left corner, facing Centre
8264+
8265-
		 T:forward(2)
8265+
8266-
		 T:place("barrel", "down")
8266+
				if not onChest then
8267-
		 T:go("F1D1")
8267+
8268-
		 T:place("cable", "down")
8268+
					turns = turns + 1
8269-
		 T:up(1)
8269+
8270-
		 T:place("modem", "down")
8270+
				if turns == 4 then
8271-
		 network.attachModem()
8271+
8272-
		 T:forward(1)
8272+
8273-
		 T:place("log", "down")
8273+
			end -- should be on chest. If not should be over water
8274-
		 T:go("R1F1 R1F1 D5R1 F1L1 F7R1")-- left corner, facing back ready to clear basement
8274+
			if onChest then -- onChest and onTree, go left,down
8275
				T:go("R1F1D1R1")
8276-
	if (R.data):find("convert") == nil then
8276+
8277-
		lib.floodFarm(R)
8277+
			atHome = lib.checkPosition()
8278
			if atHome then
8279-
	lib.clearBasement() -- area has been cleared. ends right side facing right, just below ceiling
8279+
				return true -- exit function
8280
			end
8281-
	if R.data == "back" then
8281+
8282-
		T:go("R2F6 R1D1")
8282+
8283
		end
8284-
		T:go("R2F6 L1F1 U4D5 R2F1") -- make exit for player. end mid floor/ceiling height, facing back, in centre
8284+
8285
		return false
8286-
	if R.data == "new" or R.data == "convertStorage" then	-- put storage in this farm
8286+
8287
	
8288-
			T:place("cable", "up")
8288+
	function lib.gotoTree(logSlot)
8289
		-- assume facing crops
8290
		T:turnRight(1)
8291-
		T:place("cable", "up")
8291+
		print("Extracting saplings from storage")
8292
		lib.getSaplings("forward") -- gets one sapling only (if present)
8293-
		utils.createStorage()	-- creates on ground, 1 below current
8293+
		print("Moving to tree position")
8294
		T:go("U1F1R1")
8295-
		T:place("cable", "forward")
8295+
		lib.harvestTree("forward") -- fell tree or plant sapling, ends facing tree / dirt / sapling. sticks already used for fuel. excess saplings placed
8296
		
8297
		if logSlot == 0 then -- no logs passed as parameter
8298-
			T:place("cable", "up")
8298+
			logSlot = T:getItemSlot("log")
8299
		end
8300
		T:go("R1F1D1")			-- return to base, facing buried storage 
8301
		if logSlot == 0 then 	-- has logs so needs to craft and refuel
8302-
		for i = 1, 6 do
8302+
			T:turnRight(1)		-- facing crops
8303-
			T:place("cable", "up")
8303+
8304
		
8305
		return logSlot
8306
	end
8307-
	T:place("modem", "up")
8307+
8308-
	T:go("F1R2U2")
8308+
	function lib.harvest(crop)
8309-
	T:place("barrel", "down")
8309+
8310-
	T:drop("down", "dirt", 64)-- override 'slot' with item string
8310+
8311-
	T:up(1)
8311+
		harvest crops if ripe
8312-
	T:place("hopper", "down")
8312+
8313
		place seeds / harvest in chests
8314-
	network.attachModem()
8314+
8315-
	T:go("U1C2 U2F6 R2")
8315+
8316-
	--network.attachModem()
8316+
8317
		local isFarmToRight = false
8318
		local isFarmToFront = false
8319
		local width = 9
8320
		local length = 10
8321
		local toRight = true
8322
		for l = 1, length do
8323
			for w = 1, width do
8324
				isReady, blockType, _ = lib.isCropReady("down")	-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
8325
				turtle.select(1)
8326
				if blockType == "" then					-- air (above water, storage or dirt)
8327
					--turtle.digDown("left")			-- use pickaxe
8328-
			T:place("barrel", "down", false)
8328+
					turtle.digDown("right")				-- use hoe
8329
					lib.plantCrop(crop, "down")			-- plant crop
8330
				elseif isReady then						-- crop below is ready
8331
					turtle.digDown("left")				-- use pickaxe
8332
					lib.plantCrop(blockType, "down")	-- plant crop
8333
				end
8334
				T:forward(1)
8335
				if l == 1 and w == width then -- last block of first row at front of farm
8336
					T:forward(1)
8337
					if lib.isStorage("down") then
8338
						isFarmToRight = true
8339
					end
8340
					turtle.back()
8341
				end
8342
			end
8343
			-- end of the row: change direction
8344-
		T:place("torch", "forward", true)
8344+
8345
				lib.plantCrop(crop, "down")
8346
				if toRight then
8347
					T:go("L1F1L1")
8348
				else
8349-
		-- T:place(blockType, direction, leaveExisting, signText)
8349+
8350
				end	
8351
			end
8352
			toRight = not toRight
8353
		end
8354
		T:go("R1F1") -- goes over chest/cobble on top wall
8355-
				T:place(R.useBlockType, "forward", true)
8355+
		if lib.isStorage("down") then
8356
			isFarmToFront = true
8357
		end
8358
		T:go("R2F"..length.."D1L1") -- go straight across to seed chest 10 blocks, facing crops
8359
		lib.storeCrops() -- rotates from start to deposit seeds and crops, ends facing crops
8360
		return isFarmToRight, isFarmToFront
8361
	end	
8362
	
8363-
					T:place(R.useBlockType, "up", true)
8363+
	function lib.harvestTree(direction)
8364
		--[[
8365
			start in front of / during tree harvest
8366
			Check if sapling present
8367
			Harvest tree if present, replant sapling
8368
			Dispose of apples. Use sticks as fuel
8369
			Return to base
8370-
					T:place(R.useBlockType, "forward")
8370+
8371
		if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then -- only harvest tree if fuel < half max
8372
			direction = direction or "forward"
8373
			local inFront = T:getBlockType("forward")
8374
			print("Checking tree")
8375-
					T:place(R.useBlockType, "forward")
8375+
			if inFront == "" then -- no tree or sapling
8376
				print("No sapling: planting sapling")
8377
				T:place("sapling", -1, "forward", false)
8378
			elseif inFront:find("log") ~= nil or direction == "up" then -- tree above or in front
8379-
					T:place(R.useBlockType, "forward")
8379+
				-- clsTurtle.harvestTree(self, extend, craftChest, direction)
8380
				print("Harvesting tree")
8381
				T:harvestTree(false, false, direction) --do not investigate side branches in case chunk unloaded
8382
				T:go("R2F1R2") -- face dirt
8383
				-- place(self, blockType, damageNo, direction, leaveExisting, signText)
8384
				T:place("sapling", -1, "forward", false)
8385
			end
8386
			print("Dropping saplings into storage")
8387
			T:dropItem("sapling", "down", 0) -- drop all saplings down into chest
8388-
						T:place(R.useBlockType, "down", true)
8388+
			print("Disposing of apples")
8389
			T:dropItem("apple", "up", 0) -- drop any apples
8390
			local slot = T:getItemSlot("minecraft:stick") 
8391
			if slot > 0 then -- use any sticks to refuel
8392
				turtle.select(slot)
8393
				turtle.refuel()
8394
			end
8395
		end
8396
	end
8397
	
8398
	function lib.manageTree()
8399
		--[[ starting position facing crops ]]
8400
		local crop = ""
8401
		local logSlot = T:getItemSlot("stick")
8402
		if logSlot > 0 then
8403
			turtle.select(logSlot)
8404
			turtle.refuel()
8405
		end
8406
		logSlot = T:getItemSlot("log")
8407
		local needsFuel = false
8408
		
8409-
		T:place(R.useBlockType, "down", true)
8409+
8410
			needsFuel = true
8411
		end
8412
		if needsFuel then
8413
			print("Running Tree Manager")
8414
			logSlot = lib.gotoTree(logSlot) -- check for sapling or harvest tree, retuns to start, ends facing buried barrel/chest if has logs, logSlot returned
8415
		end
8416
		if logSlot > 0 then
8417
			if not needsFuel then 			-- logs already onboard, no tree harvest, so turn towards buried chest
8418
				T:turnLeft(1)
8419
			end
8420
			T:go("F1") 						-- move to buried storage chest/barrel
8421
			lib.refuelWithLogs(logSlot) 	-- use any logs for fuel
8422
			T:go("R2F1")					-- facing seed chest/barrel
8423
		else
8424
			T:turnRight(1) 					-- facing seed chest/barrel
8425
		end
8426
		
8427
		crop = lib.getSeeds("forward") 		-- get 1 stack of beetroot / wheat seeds
8428
		if crop == "" then
8429
			print("No seeds available. Checking root veg")
8430
			T:turnRight(1)					-- face crop chests
8431
			crop = lib.getVeg("forward")	-- gets any carrots / potatoes
8432
			T:turnRight(2)					-- face crops
8433
		else
8434
			T:turnLeft(1)					-- face crops
8435
		end
8436
		return crop
8437
	end
8438
	
8439
	function lib.isCropReady(direction)
8440
		local isReady = false
8441
		local status = ""
8442
		local cropType = ""
8443
		local success = false
8444
		local data = {}
8445
8446
		direction = direction or "forward"
8447
8448
		if direction == "down" then
8449
			success, data = turtle.inspectDown()
8450
		else
8451
			success, data = turtle.inspect()
8452
		end
8453
		if success then
8454
			cropType = data.name
8455
			--print("cropType: "..cropType) read()
8456
			if data.name == "minecraft:carrots" then
8457
				status = data.state.age.." / 7"
8458
				--print("Carrots status: "..status) read()
8459
				if data.state.age == 7 then
8460
					isReady = true
8461
				end
8462
			elseif data.name == "minecraft:potatoes" then
8463
				status = data.state.age.." / 7"
8464
				if data.state.age == 7 then
8465
					isReady = true
8466
				end
8467
			elseif data.name == "minecraft:wheat" then
8468
				status = data.state.age.." / 7"
8469
				if data.state.age == 7 then
8470
					isReady = true
8471
				end
8472
			elseif data.name == "minecraft:beetroots" then
8473
				status = data.state.age.." / 3"
8474
				if data.state.age == 3 then
8475
					isReady = true
8476
				end
8477
			end
8478
		end
8479
		return isReady, cropType, status	-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
8480
	end
8481
8482
	function lib.isStorage(direction)
8483
		blockType = T:getBlockType(direction)
8484
		if blockType:find("barrel") ~= nil then
8485
			return true, "barrel"
8486
		elseif blockType:find("chest") ~= nil then
8487
			return true, "chest"
8488
		end
8489
		
8490
		return false, ""
8491
	end
8492
	
8493
	function lib.plantCrop(crop, direction)
8494
		local planted = false
8495
		--turtle.digDown("left") -- harvest existing
8496
		--turtle.digDown("right") -- till soil
8497
		if crop:find("potato") ~= nil then
8498
			T:dropItem("poison", "up", 0)
8499
		end
8500
		planted = T:place("carrot", -1, direction)
8501
		if not planted then
8502
			planted = T:place("potato", -1, direction)
8503
		end
8504-
					T:place("torch", "down")				-- place torch, move forward
8504+
		if not planted then
8505
			planted = T:place("beetroot_seeds", -1, direction)
8506
		end
8507
		if not planted then
8508
			planted = T:place("wheat_seeds", -1, direction)
8509
		end
8510
	end
8511-
				if not T:place("stone", "down") then		-- place stone below
8511+
8512
	function lib.refuelWithLogs(logSlot)
8513
		-- assume positioned in front of buried chest / barrel, saplings already dropped, apples dumped, sticks used as fuel
8514
		print("Logs present: collecting crafting table")
8515
		-- earlier versions used crafting table buried in the ground
8516
		-- newer versions have a barrel or chest embedded in the ground, containing the crafting table
8517
		print("Sorting Inventory")
8518
		T:sortInventory()
8519
		while T:suck("down") do end					-- empty out barrel/chest to find crafting table
8520
		if T:getItemSlot("crafting") == 0 then
8521
			T:checkInventoryForItem({"crafting"}, {1}, true, "Crafting table required for logs->planks")
8522
		end
8523
		if T:equip("right", "minecraft:crafting_table") then -- swap equipment on right side
8524
			for i = 1, 16 do						-- drop anything except logs down into barrel/chest/pit
8525
				if T:getSlotContains(i):find("log") == nil then
8526
					T:drop("down", i)
8527
				else
8528
					logSlot = i
8529
				end
8530
			end
8531
			turtle.select(logSlot)
8532
			turtle.transferTo(1)
8533
			turtle.craft()							-- craft logs to planks
8534
			logSlot = T:getItemSlot("planks")
8535
			while logSlot > 0 do
8536
				turtle.select(logSlot)
8537
				turtle.refuel()
8538
				logSlot = T:getItemSlot("planks")				
8539
			end
8540
							-- refuel using planks
8541
			while T:suck("down") do end				-- recover items from storagebelow
8542
			if not T:equip("right", "minecraft:diamond_hoe") then		-- re-equip
8543
				T:equip("right", "minecraft:diamond_pickaxe")			
8544
			end
8545
			if T:dropItem("minecraft:crafting_table", "down") then
8546
				turtle.refuel() -- use any sticks
8547
			end
8548
		else
8549
			print("Unable to equip crafting table.\n\nCheck turtle inventory and chest or barrel below")
8550
			error()
8551
		end
8552
	end
8553
	
8554
	function lib.returnToBack()
8555
		--[[ move from farm at front back to starting farm ]]
8556
		T:go("U1R1F11D1L1")
8557
	end
8558
	
8559
	function lib.returnToLeft()
8560
		--[[ move from farm on right back to starting farm ]]
8561
		T:go("U1R2F11D1R2")
8562
	end
8563
		
8564
	function lib.storeCrops()
8565
		-- place crops and seeds into chests
8566
		T:turnRight(1)
8567
		if lib.isStorage("forward") then
8568
			lib.storeSeeds("forward")
8569
		end
8570
		T:turnRight(1)
8571
		if lib.isStorage("forward") then
8572
			lib.storeVeg("forward")
8573
		end
8574
		T:turnRight(2) -- facing crops again
8575
	end
8576
	
8577
	function lib.storeSeeds(direction)
8578
		direction = direction or "forward"
8579
		if lib.isStorage(direction) then -- chest exists
8580
			if T:getItemSlot("minecraft:wheat_seeds") > 0 then
8581
				if not T:dropItem("minecraft:wheat_seeds", direction, 0) then
8582
					T:dropItem("minecraft:wheat_seeds", "up", 0)
8583
				end -- drop all wheat seeds
8584
			elseif T:getItemSlot("minecraft:beetroot_seeds") > 0 then
8585
				if not T:dropItem("minecraft:beetroot_seeds", direction, 0) then-- drop all beetroot seeds
8586
					T:dropItem("minecraft:beetroot_seeds", "up", 0)
8587
				end
8588
			end
8589
		end
8590
	end
8591
	
8592
	function lib.storeVeg(direction)
8593
		direction = direction or "forward"
8594
		T:dropItem("apple", "up", 0) -- drop all apples
8595
		T:dropItem("poison", "up", 0) -- drop all poison potatoes
8596
		if lib.isStorage(direction) then
8597
			if not T:dropItem("carrot", direction, 0) then-- drop carrots
8598
				--return false
8599
			end
8600
			T:dropItem("potato", direction, 0) -- drop potato
8601
			T:dropItem("minecraft:wheat", direction, 0) -- drop all wheat
8602
			T:dropItem("minecraft:beetroot", direction, 0) -- drop all beetroot
8603
		end
8604
	end
8605
	
8606
	function lib.watchFarm()
8607
		--[[
8608
		check status of crops in front of turtle.
8609
		call lib.harvest when ripe
8610
		return farm(s) found in front or to the right
8611
		]]
8612
		local isReady, crop, status = lib.isCropReady("forward")		-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
8613
		-- check state of crop in front. Harvest if ripe		
8614
		while not isReady do
8615
			isReady, crop, status = lib.isCropReady("forward")			-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
8616
			if not isReady then
8617
				if crop == "" then
8618
					print("No crops found in front")
8619
					print("Plant seeds, carrots, potatoes")
8620
					error()
8621
				else
8622
					print("Waiting for "..crop.." status: "..status)
8623
				end
8624
				sleep(60)
8625
			end
8626
		end
8627
		print("Local crops ripe")
8628
		
8629-
						T:place("torch", "down")		-- place torch
8629+
		return lib.manageTree() -- "" or collected seeds / root crops
8630
	end
8631
	
8632
	--[[
8633
		called from args on start, or from user choice
8634
		farm already built, needs planting and/or harvesting
8635
		needs both pickaxe and hoe
8636
		may start in any position if chunk unloaded while running
8637
	]]
8638
	--local pp = utils.getPrettyPrint()
8639
	
8640
	local atHome = lib.checkPosition()-- facing crops, placed above water source
8641
	if not atHome then
8642
		if not lib.goHome() then -- try to find home
8643
			return
8644
			{
8645
				"Unable to determine my position.\n",
8646
				"Place me in the lower left corner",
8647
				"over water, facing the crops with",
8648
				"barrels or chests to my right and behind"
8649
			}
8650
		end
8651
	end
8652
	-- check equipment
8653
	T:go("L1F1") -- over barrel
8654
	local isStorage, storageType = lib.isStorage("down")
8655
	if not isStorage then
8656
		local message =
8657
[["Farm upgrade required:
8658
Previous designs had a crafting table
8659
next to the water source.
8660
8661
 1. Place a barrel or chest under the turtle
8662
    instead.
8663
	
8664
 2. Restart"
8665
]]
8666
		print(message)
8667
		error()
8668
	end
8669
	-- must be storage below to get this far
8670
	if lib.checkEquipment() then
8671
		T:equip("right", "minecraft:diamond_hoe", 0) -- equip hoe and put crafting chest into inventory
8672
		T:dropItem("crafting", "down")
8673
		utils.goBack(1)
8674
		T:turnRight(1)
8675
	else
8676
		return {"Unable to equip hoe."}
8677
	end
8678
8679
	
8680
	-- check if crops already planted
8681-
						T:place("torch", "down")		-- place torch
8681+
	local isReady, crop, status = lib.isCropReady("forward")
8682
	local watch = true	-- assume watching farm already planted
8683
	if crop == "" then	-- nothing has been planted
8684
		watch = false-- not watching, continue with planting
8685
		pp.itemColours = {colors.lightGray, colors.red, colors.orange, colors.brown}
8686
		crops = {"minecraft:wheat_seeds", "minecraft:beetroot_seeds", "minecraft:carrots", "minecraft:potatoes"}
8687
		choices = {"wheat (seeds)", "beetroot (seeds)", "carrot", "potato"}
8688
		choice = menu.menu("Choose preferred crop", choices, pp, "Type number of your choice")
8689
		crop = crops[choice]
8690
		T:checkInventoryForItem({crop}, {95}, true, "Do not mix! add as many as you want")
8691
	end
8692
8693
	while true do -- start infinite loop of watching crops, farming all modules
8694
		if watch then -- not already in inventory
8695
			crop = lib.watchFarm() --waits if required, returns crop type when ripe
8696
		end
8697
		print("Beginning "..crop.." management")
8698
		local isFarmToRight, isFarmToFront = lib.harvest(crop)
8699
		if isFarmToRight then
8700
			lib.farmToRight() -- no action if no farmToRight
8701
			lib.returnToLeft() -- return home and continue with front
8702
			isFarmToRight = false
8703
		end
8704
		
8705
		if isFarmToFront then
8706
			isFarmToRight = lib.farmInFront()
8707
			if isFarmToRight then
8708
				lib.farmToRight() -- no action if no farmToRight
8709
				lib.returnToLeft() -- return home 
8710
			end
8711
			lib.returnToBack()
8712
		end
8713
		if not R.auto then -- not started from startup.lua
8714
			T:go("L1F1")
8715
			while T:suck("down") do end						-- recover items from storagebelow
8716
			T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table 
8717
			T:dropItem("diamond_hoe", "down") 				-- drop hoe into storage
8718
			T:dropItem("crafting", "down") 					-- in case spare one picked by mistake
8719
			utils.goBack(1)
8720
			T:turnRight(1)
8721
			return {"Crop management of all modules completed"}
8722
		end
8723
	end
8724
	return {}
8725
end
8726
8727
local function manageFarmSetup(R) -- 33
8728
	local lib = {}
8729
	
8730
	function lib.disableAutostart()
8731
		if fs.exists("start.txt") then
8732
			fs.delete("start.txt")
8733
		end
8734
		if fs.exists("startup.lua") then
8735
			fs.delete("startup.lua")
8736
		end
8737
	end
8738
	
8739
	function lib.enableAutostart()
8740
		if not fs.exists("startup.lua") then
8741
			local h = fs.open("startup.lua", "w")
8742
			h.writeLine('function main()')
8743
			h.writeLine('	if fs.exists("start.txt") then')
8744
			h.writeLine('		local handle = fs.open("start.txt", "r")')
8745
			h.writeLine('		local cmd = handle.readLine()')
8746
			h.writeLine('		handle.close()')
8747
			h.writeLine('		shell.run("tk.lua "..cmd)')
8748
			h.writeLine('	end')
8749
			h.writeLine('end')
8750
			h.writeLine('main()')
8751
			h.close()
8752
		end
8753
		local h = fs.open("start.txt", "w")
8754
		if R.data == "farm" then
8755
			h.writeLine('farm')
8756
		end
8757
		h.close()
8758
		print("Startup files written")
8759
	end
8760
	
8761
	T:clear()
8762
	--local pp = utils.getPrettyPrint()
8763
	local choices = {"Plant or harvest this farm complex"}
8764
	local isManaged = fs.exists("start.txt")
8765
	if isManaged then
8766
		table.insert(choices, "Disable automatic farm management")
8767
	else
8768
		table.insert(choices, "Enable automatic farm management")
8769
	end
8770
	pp.itemColours = {colors.lime, colors.lightGray}
8771
	local userChoice, modifier = menu.menu("Choose your option", choices, pp) -- 1 to 2
8772
	if modifier == "q" then -- quit chosen
8773
		return {"Player has quit"}
8774
	end
8775
	R.subChoice = userChoice
8776
	if R.subChoice == 1 then -- harvest now
8777
		R.silent = false
8778
		R.data = "farm"
8779
		R.auto = false
8780
		return manageFarm(R)
8781
	else -- enable/disable auto farm
8782
		local line = menu.clear()
8783
		if isManaged then
8784
			local message = ( "This turtle has been configured to"..
8785
							  "start automatically and run the farm"..
8786
							  "management program.\n")
8787
			line = menu.colourText(line, message, true, true)
8788
			if menu.getBoolean("Do you want to disable this? (y/n)", line, colors.yellow, colors.black) then
8789
				lib.disableAutostart()
8790
			end
8791
			return {"Autostart disabled. Reboot to activate"}
8792
		else -- not managed
8793
			local message = ( "~yellow~This turtle can be configured to be\n"..
8794
							  "a dedicated farm manager.\n\n"..
8795
							  "~lightGray~It will then start automatically and\n"..
8796
							  "monitor the farm complex:\n\n"..
8797
							  "~green~harvesting~yellow~ and ~lime~replanting ~yellow~continuously.\n")
8798
			line = menu.colourText(line, message, true, true)
8799
			if menu.getBoolean("Do you want to enable this? (y/n)", line + 2, colors.orange, colors.black) then
8800
				lib.enableAutostart()
8801
			else
8802
				return {"Player cancelled operation"}
8803
			end
8804
			return {"Autostart enabled. Reboot to activate"}
8805
		end
8806
	end
8807
	
8808
	return {}
8809
end
8810
8811
local function measure(R) -- 101
8812
	-- measure height/ depth / length
8813
	local lib = {}
8814
	
8815
	function lib.checkBlocks(R, blocks)
8816
		local dimension = "height"
8817
		local message = ""
8818
		local measure = ""
8819
		local doContinue = true
8820
		if R.choice == 102 then
8821
			dimension = "depth"
8822
		elseif R.choice == 103 then
8823
			dimension = "length"
8824
		end
8825
		blocks = blocks + 1
8826
		if blocks > R.size then
8827
			message = "Max "..dimension.." of "..R.size.." stopped measurement"
8828
			measure = ""
8829
			doContinue = false
8830
		else
8831
			measure = dimension.." measured: "..blocks.." blocks"
8832
		end
8833
		return doContinue, blocks, measure, message
8834
	end
8835
	
8836
	local blocks = 1
8837
	local method = ""
8838
	local measure = ""
8839
	local message = ""
8840
	local doContinue = true
8841
	if R.choice == 101 then				-- height
8842
		if R.subChoice == 1 then		-- obstruction above
8843
			method = "Method: Until obstruction above"
8844
			while turtle.up() and doContinue do
8845
				doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8846
			end
8847
		elseif R.subChoice == 2 then	-- end of blocks in front of turtle eg cliff, wall
8848
			method = "Method: Until no block detected in front"
8849
			while turtle.detect() and doContinue do
8850
				if turtle.up() then
8851
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8852
				else
8853
					message = "Obstruction above stopped measurement"
8854
					measure = ""
8855
					doContinue = false
8856
				end
8857
			end
8858-
		T:place("slab", "down")					-- place slab layer 1
8858+
8859
			method = "Method:Until search: '"..R.data.."' met"
8860-
		T:place("slab", "down")					-- place slab layer 2
8860+
8861
				if turtle.up() then
8862-
		T:place("redstone", "down")
8862+
8863
					if doContinue then
8864-
		T:place("redstone", "forward")			-- redstone on ground level slab
8864+
8865
						if blockType:find(R.data) ~= nil then
8866-
		T:place("slab", "down")					-- slab on layer 1
8866+
8867
							message = "Found "..blockType
8868-
		T:place("slab", "down")					-- slab on layer 3
8868+
8869
						end
8870-
		T:place("redstone", "down")				-- redstone on layer 3 slab
8870+
8871
				else
8872
					message = "Obstruction above stopped measurement"
8873-
		T:place("redstone", "forward")			-- redstone on layer 1 slab
8873+
8874
					doContinue = false
8875-
		T:place("redstone", "forward")			-- redstone on level 0 floor
8875+
8876
			end
8877
		elseif R.subChoice == 4 then	-- When block above changes eg dragon tower height
8878
			local blockType = T:getBlockType("up")
8879
			local compare = blockType
8880
			method = "Method: Until "..blockType.." changes"
8881
			while blockType == compare and doContinue do
8882-
			T:place("redstone", "down")			-- redstone under chest etc
8882+
8883
				doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8884
				if doContinue then
8885
					blockType = T:getBlockType("up")
8886
				end
8887
			end
8888
			measure = "Height measured: "..blocks.." blocks"
8889
			message = "Found "..blockType
8890
		end
8891
		
8892
		for i = 1, blocks do
8893-
		T:place("chest", "forward")				-- end chest
8893+
8894
		end
8895-
		T:place("slab", "down")					-- slab above chest
8895+
8896
		T:go("F1R2D1") -- go off the edge and face cliff/pit wall
8897
		blocks = blocks + 1
8898
		if R.subChoice == 1 then		-- obstruction water / lava below
8899-
		T:place("chest", "forward")				-- start chest
8899+
8900
			while move do
8901-
		T:place("wall", "forward")				-- place wall
8901+
8902
				if blockType:find("water") ~= nil or blockType:find("lava") ~= nil then
8903-
		T:place("pressure", "down")				-- place pressure plate
8903+
8904
					move = false
8905-
		T:place("hopper", "forward")				-- place hopper into chest
8905+
8906
					move = turtle.down()
8907-
		T:place("wall", "forward")				-- place second wall
8907+
8908
						blocks = blocks + 1
8909
					else
8910
						measure = "Depth measured: "..blocks.." blocks"
8911
					end
8912
				end
8913
			end
8914-
		T:place(R.useBlockType, "forward", false)	-- replace back wall with polished block layer 2
8914+
8915
		elseif R.subChoice == 2 then	-- end of wall in front`
8916-
		T:place(R.useBlockType, "forward", false)	-- replace back wall with polished block layer 3
8916+
8917
				if turtle.down() then
8918
					blocks = blocks + 1
8919-
			T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 3
8919+
8920
				else
8921
					message1 = "Obstruction below stopped measurement"
8922
					break
8923-
			T:place("piston", "forward")				-- lower replacer piston placed
8923+
8924
			end
8925
			method = "Method: Until no block detected ahead"
8926-
		T:place("piston", "forward")					-- lower piston placed
8926+
8927
			method = "Method:Until search: '"..R.data.."' met"
8928
			while turtle.detect() do
8929-
		T:place(R.useBlockType, "forward", false)	-- polished block back wall layer 4
8929+
8930
					blocks = blocks + 1
8931-
		T:place("dispenser", "forward")				-- dispenser placed
8931+
8932
					if blockType:find(R.data) ~= nil then
8933
						measure = "Depth measured: "..blocks.." blocks"
8934-
		T:place("slab", "down")						-- lower piston slab placed
8934+
8935
						break
8936-
			T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 4
8936+
8937
				else
8938
					message = "Obstruction below stopped measurement"
8939
					break
8940
				end
8941-
			T:place("computercraft:computer_normal", "forward", false)	-- place computer
8941+
8942
		end
8943
		for i = 1, blocks do
8944-
		T:place(R.useBlockType, "forward", false)	-- polished block back wall layer 4
8944+
8945
		end
8946
		T:go("F1R2")
8947-
		T:place("piston", "forward")					-- upper piston placed
8947+
8948
		if R.subChoice == 1 then		-- obstruction ahead
8949
			method = "Method: Until obstruction ahead"
8950-
		T:place(R.useBlockType, "forward", false)	-- polished block back wall layer 5
8950+
8951
				doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8952
			end
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		
8953+
8954
			method = "Method: Until no block detected above"
8955
			while turtle.detectUp() and doContinue do
8956
				if turtle.forward() then
8957-
			T:place("piston", "forward")				-- upper replacer piston placed				
8957+
8958
				else
8959
					message = "Obstruction ahead stopped measurement"
8960-
		T:place("slab", "forward")					-- upper piston slab placed
8960+
8961
					doContinue = false
8962
				end
8963
			end
8964
		elseif R.subChoice == 3 then	-- end of floor below
8965
			method = "Method: Until no block detected below"
8966
			while turtle.detectDown() and doContinue do
8967-
		T:place("computercraft:computer_normal", "forward", false)		-- place computer in gap, layer 4
8967+
8968
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8969
				else
8970
					message = "Obstruction ahead stopped measurement"
8971-
		T:place(R.useBlockType, "forward", false)
8971+
8972
					doContinue = false
8973-
		T:place(R.useBlockType, "forward", false)
8973+
8974
			end
8975-
		T:place(R.useBlockType, "forward", false)	-- facing right
8975+
8976
			method = "Method:Until search: '"..R.data.."' above met"
8977
			while turtle.detectUp() and doContinue do
8978
				if turtle.forward() then
8979
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8980
					if doContinue then
8981-
		T:place("glass", "down", false)
8981+
8982
						if blockType:find(R.data) ~= nil then
8983-
		T:place("glass", "down", false)				-- on top of glass facing back wall at dungeon base level 5
8983+
8984
							measure = "Length measured: "..blocks.." blocks"
8985-
		T:place(R.useBlockType, "down", false)		-- level 6 dungeon exit
8985+
8986
						end
8987
					end
8988
				else
8989
					message = "Obstruction ahead stopped measurement"
8990
					measure = ""
8991
					doContinue = false
8992
				end
8993
			end
8994
		elseif R.subChoice == 5 then	-- search for specific block down min 3 characters
8995-
		T:place(R.useBlockType, "forward", false)
8995+
8996
			--while turtle.detectDown() and doContinue do
8997-
		T:place(R.useBlockType, "forward", false)	-- facing right
8997+
8998
				if turtle.forward() then
8999
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
9000
					if doContinue then
9001-
		T:place(R.useBlockType, "forward", false)
9001+
9002
						if blockType:find(R.data) ~= nil then
9003
							message = "Found "..blockType
9004
							measure = "Length measured: "..blocks.." blocks"
9005
							doContinue = false
9006
						end
9007-
		T:place("computercraft:wired_modem", "forward", false)	-- place modem
9007+
9008
				else
9009-
		T:place("computercraft:cable", "forward", false)			-- place network cable
9009+
9010-
		T:place("computercraft:cable", "forward", false)			-- place network cable (no need to move)
9010+
9011
					doContinue = false
9012-
		T:place("computercraft:cable", "forward", false)
9012+
9013
			end
9014-
		T:place("computercraft:cable", "forward", false)
9014+
9015
		T:turnRight(2)	-- head home
9016-
		T:place("computercraft:wired_modem", "forward", false)	-- place modem
9016+
9017
			turtle.forward()
9018-
		T:place("computercraft:cable", "forward", false)
9018+
9019-
		T:place("computercraft:cable", "forward", false)
9019+
9020
	elseif R.choice == 104 then	-- depth of stretch of water
9021
		--R.length = 0 to auto calculate
9022
		R.width = 1
9023
		R.silent = true
9024
		R.useBlockType = ""
9025
		R.data = "clearWaterPlants"
9026
		local data = clearWaterPlants(R)
9027
		R.height = data[1]
9028
		local length = data[2]
9029
		T:go ("R2F"..length - 1 .."R2U1")
9030
		return {"Greatest depth measured: ".. R.height,"Width of water: "..R.length}
9031
	end
9032
	if message == "" then
9033
		return{method, measure}
9034
	else
9035
		return{method, measure, message}
9036
	end
9037
end
9038
9039
local function mineBedrockArea(R) -- 19
9040
	--[[ 
9041
	Assume on level 5 or -59
9042
	for 1, width do
9043
		for 1, length do
9044
			go down until bedrock, digging/replacing all directions
9045
			return to 5 / -59
9046
			move forward 1 blocks
9047
		end
9048
		turn right/ forward 2 turn right
9049
	end
9050
	]]	
9051
	local lib = {}
9052
	
9053
	function lib.clearColumn(R)
9054
		local level = 0
9055
		--T:go("L1x1R2x1L1")
9056
		local success = T:down(1)
9057
		while success do
9058
			level = level + 1
9059
			if R.data == "leaveExposed" then
9060
				T:go("R1x1R1x1R1x1R1x1", false, 0, true)
9061
			else
9062
				T:go("R1C1R1C1R1C1R1C1", false, 0, true)
9063
			end
9064
			success = T:down(1)
9065
		end
9066
		if R.data == "leaveExposed" then
9067
			T:go("U"..level)
9068
		else
9069
			T:go("U"..level.."C2")
9070
		end
9071-
local function createTrialCover(R)
9071+
9072
	
9073
	local goRight = true
9074
	for i = 1, R.width do
9075
		for j = 1, R.length do
9076
			lib.clearColumn(R)
9077
			T:forward(1)
9078
		end
9079
		if goRight then
9080
			T:go("R1F1R1")
9081
		else
9082
			T:go("L1F1L1")
9083
		end
9084
		goRight = not goRight
9085
	end
9086
	return {}
9087
end
9088
9089
local function oceanMonumentColumns(R)
9090-
	function lib.findSpawner()
9090+
9091
	local lib = {}
9092
	
9093-
		-- assume turtle placed facing trial spawner
9093+
9094
		local depth = 0
9095
		while T:isWater("forward") do
9096
			T:go("U1C2")
9097
			depth = depth + 1
9098
		end
9099
		return depth
9100-
				if moves > 32 then
9100+
9101
	
9102
	function lib.buildTower()
9103
		T:go("F1C2 F1C2 F1C2")
9104
		T:go("L1F1 L1C2 F1C2 F1C2 F1C2")
9105-
			if not found then	-- could be behind a wall
9105+
9106-
				print("Assuming spawner behind a wall")
9106+
9107
		
9108
		T:go("R2")
9109-
				while turtle.forward() and not quit do 
9109+
9110
			T:go("U1C2")
9111-
					if moves > 32 then
9111+
9112-
						quit = true
9112+
9113
			end
9114
		end
9115-
				found, position = lib.isSpawner() -- true/false, top/bottom/nil
9115+
9116-
				if not found then
9116+
9117-
					T:go("R2F"..moves + 2 .."R2")
9117+
9118
	local blockType = T:getBlockType("down")
9119
	while blockType:find("water") == nil do
9120
		T:down(1) -- if on a platform will break through
9121
		blockType = T:getBlockType("down")
9122
	end
9123
	--R.useBlockType = "prismarine", R.data = "oceanMonumentColumns" from getTask
9124
	--local tempData = R.data
9125
	--R.data = "clearWaterPlants"
9126
	local result = clearWaterPlants(R)[1]
9127
	if result ~= "" then
9128
		return {result}
9129
	else
9130
		--on corner of monument, facing out to ocean
9131
		local depth = lib.buildColumn()
9132
		-- now above surface, block below at surface level
9133
		for i = 1, 4 do
9134
			T:turnRight(1)
9135
			R.length = 57
9136
			utils.createPath(R) -- roughly at next corner
9137
			if i < 4 then
9138
				T:down(depth-2) -- roughly at correct depth
9139
				local waterBelow = utils.clearVegetation("down")
9140
				while waterBelow do
9141
					T:down(1)
9142
					waterBelow = utils.clearVegetation("down")
9143
				end
9144
				blockType = T:getBlockType("down")
9145
				while blockType:find("prismarine") ~= nil do
9146
					T:forward(1)
9147
					blockType = T:getBlockType("down")
9148
				end
9149
				turtle.back()
9150
				depth = lib.buildColumn()
9151-
	local found, position = lib.findSpawner() -- move forwards until meet Spawner, go through wall if present
9151+
9152-
	if not found then --outside dungeon
9152+
9153-
		return {"Trial spawner not found"}
9153+
9154-
	end 
9154+
9155-
	if position == "top" then
9155+
9156-
		T:go("B2D1")
9156+
9157-
	elseif position == "forward" then
9157+
9158-
		T:go("B1")
9158+
9159
9160-
		T:go("B2U1")
9160+
9161
	local moves = 2
9162-
	T:go("R1F2R2")	--on lower right corner
9162+
9163-
	-- starts with wall across spawner
9163+
9164-
	buildStructure(R)
9164+
9165-
	T:go("U3F1 R1F1 L1U1 F1")
9165+
9166
		if blockType:find("rail") ~= nil then
9167-
	R.width = 3
9167+
9168-
	R.length = 3
9168+
9169
		T:down(moves)
9170-
	createFloorCeiling(R)
9170+
9171-
	T:go("F1R1 B1D1 B1D2 F1")
9171+
9172
		T:place(R.useBlockType, -1, "forward", false)
9173
		utils.goBack(1)
9174
		T:place("minecraft:redstone_torch", -1, "forward", true)
9175
		T:turnLeft(1)
9176
		utils.goBack(1)
9177
		T:up(moves)
9178
		T:go("F1R1F1")
9179
	elseif R.data == "up" then -- sloping rail up/down is relative to dirtection facing
9180
		moves = 3
9181
		T:turnLeft(1)
9182
		utils.goBack(1)
9183
		if blockType:find("rail") ~= nil then
9184
			 moves = 4
9185
		end
9186
		T:down(moves)
9187
		T:go("F1L1")
9188
		T:place("minecraft:redstone_torch", -1, "up", false)
9189
		
9190
		T:turnRight(1)
9191
		utils.goBack(1)
9192
		T:up(moves)
9193
		T:go("F1R1")
9194
	end
9195
	return {}
9196
end
9197
9198
local function plantTreefarm(R) -- 23
9199
	--T:place(blockType, damageNo, direction, leaveExisting, signText)
9200
	local lib = {}
9201
	
9202
	function lib.checkSaplings(saplings, firstChoice, secondChoice)
9203
		local saplingSlot, sapling, count = T:getSaplingSlot(firstChoice)
9204
		if count < 4  and secondChoice ~= "" then
9205
			saplingSlot, sapling, count = T:getSaplingSlot(secondChoice)
9206
		end
9207
		if count == 0 then
9208
			sapling = ""
9209
		end
9210
		
9211
		return sapling, count
9212
	end
9213
	
9214
	function lib.getSaplingInventory()
9215
		local saplings = {}
9216
		saplings.oak_sapling = 0
9217
		saplings.spruce_sapling = 0
9218
		saplings.birch_sapling = 0
9219
		saplings.jungle_sapling = 0
9220
		saplings.acacia_sapling = 0
9221
		saplings.dark_oak_sapling = 0
9222
9223
		local firstChoice = ""
9224
		local firstCount = 0
9225
		local secondChoice  = ""
9226
		local secondCount = 0
9227
		for i = 1, 16 do
9228
			if turtle.getItemCount(i) > 0 then
9229
				local data = turtle.getItemDetail(i)
9230
				if data.name:find("sapling") ~= nil then
9231
					local name = data.name:sub(11) -- removes "minecraft:"
9232
					saplings[name] = saplings[name] + data.count
9233
				end
9234
			end
9235
		end
9236
		
9237
		for sapling, count in pairs(saplings) do
9238
			if count > firstCount then
9239
				firstCount = count
9240
				firstChoice = sapling
9241
			else
9242
				if count > secondCount then
9243
					secondCount = count
9244
					secondChoice = sapling
9245
				end
9246
			end
9247
		end
9248
		return saplings, firstChoice, secondChoice -- table, "oak_sapling", "dark_oak_sapling"
9249
	end
9250
	
9251
	function lib.createIsland(sapling, count, exit)
9252
		-- place 4 dirt with saplings on all 4 unless jungle
9253
		-- sapling count/type already checked
9254
		T:forward(2) -- assume starting outside planting area
9255
		for i = 1, 4 do
9256
			T:go("R1F1")
9257
			T:place("dirt", -1, "down", false)
9258
		end
9259
		T:up(1)
9260
		if count >= 4 then
9261
			for i = 1, 4 do
9262
				T:go("R1F1")
9263
				T:place(sapling, -1, "down", false)
9264
			end
9265
		else
9266
			if sapling:find("dark") == nil and sapling ~= "" then
9267
				T:place(sapling, -1, "down", false)
9268
			end
9269
		end
9270
		if exit == "forward" then
9271
			T:go("F1D1")
9272
		elseif exit == "right" then
9273
			T:go("R1F2D1")
9274
		elseif exit == "left" then
9275
			T:go("L1F1D1")
9276
		elseif exit == "back" then
9277
			T:go("R2F2D1")
9278
		end
9279
	end
9280
	
9281
	function lib.createSingle(sapling, exit)
9282
		-- place single dirt with sapling on top
9283
		-- sapling count/type already checked
9284
		T:place("dirt", -1, "down", false)
9285-
					T:place("cobble", "down", false) -- place cobblestone or cobbled deepslate to mark zero coordinate
9285+
9286
		if not T:place(sapling, -1, "down", false) then -- try specific sapling
9287
			T:place("sapling", -1, "down", false)		-- any available sapling
9288
		end
9289
		if exit == "forward" then
9290
			T:go("F1D1")
9291
		elseif exit == "right" then
9292
			T:go("R1F1D1")
9293
		elseif exit == "left" then
9294
			T:go("L1F1D1")
9295
		elseif exit == "back" then
9296
			T:go("R2F1D1")
9297
		end
9298
	end
9299
9300
	local saplings, firstChoice, secondChoice = lib.getSaplingInventory()
9301
9302
	if firstChoice ~= "" then
9303
		print("first sapling choice: "..firstChoice .. " ("..saplings[firstChoice]..")")
9304
	end
9305
	if secondChoice ~= "" then
9306
		print("second sapling choice: "..secondChoice .. " ("..saplings[secondChoice]..")")
9307
	end
9308
9309
	-- check type/size of farm
9310
	if R.subChoice == 1 then -- 16 single trees
9311
		local sapling, count = lib.checkSaplings(saplings, firstChoice, secondChoice)
9312
		T:go("U1F4") -- outside first area
9313
		for i = 1, 3 do	-- column 1/4
9314
			lib.createSingle(sapling, "forward")
9315
			T:forward(1)
9316
		end
9317
		for i = 1, 2 do
9318
			lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
9319
			T:forward(1)
9320
		end
9321
		for i = 1, 2 do -- column 2/4
9322
			lib.createSingle(sapling, "forward")
9323
			T:forward(1)
9324
		end
9325
		for i = 1, 2 do
9326
			lib.createSingle(sapling, "left") -- place 4th dirt/saling and exit to right
9327
			T:forward(1)
9328
		end
9329
		for i = 1, 2 do -- column 3/4
9330
			lib.createSingle(sapling, "forward")
9331
			T:forward(1)
9332-
		T:place("minecraft:end_stone", "forward", false) -- place endstone to mark facing direction
9332+
9333
		for i = 1, 2 do
9334
			lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
9335
			T:forward(1)
9336
		end
9337
		for i = 1, 3 do -- column 4/4
9338
			lib.createSingle(sapling, "forward")
9339
			T:forward(1)
9340
		end
9341
		T:go("R1F6L1F2R2D1")	
9342
	elseif R.subChoice == 2 then -- 4 double trees (4 saplings)
9343
		-- assume placed 4 blocks from start
9344
		local sapling, count = lib.checkSaplings(mostName, secondMostName)
9345
		
9346
		if count >= 4 then
9347
			T:go("U1F3") -- outside first area
9348
			lib.createIsland(sapling, count, "forward")
9349
			sapling, count = lib.checkSaplings(mostName, secondMostName)
9350
			T:go("F2")
9351
			lib.createIsland(sapling, count, "right")
9352
			sapling, count = lib.checkSaplings(mostName, secondMostName)
9353
			T:go("F2")
9354
			lib.createIsland(sapling, count,  "right")
9355
			sapling, count = lib.checkSaplings(mostName, secondMostName)
9356
			T:go("F2")
9357
			lib.createIsland(sapling, count, "forward")
9358
			T:go("R1D1F6L1F3R2") -- outside first area
9359
		else
9360
			return {"Insufficient saplings to plant"}
9361
		end
9362
	end
9363
	return {}
9364
end
9365
9366
local function quickMine(R) -- 17
9367
	--[[
9368
	mine valuable blocks from specified area
9369
	if R.up set or lava/water found, ceiling is formed
9370
	if R.down is set, or lava/water found layer is kept 1 block high
9371
	R.subChoice
9372
	1 At mine area start, on the floor
9373
	2 At mine area start, on the ceiling
9374
	3 On floor, start 1 block ahead
9375
	4 On ceiling, start 1 block ahead
9376
	5 On floor diagonally to left"
9377
	]]
9378
	local lib = {}
9379
	
9380
	function lib.refuel(direction)
9381
		if T:getWater(direction)  then
9382
			T:refuel(1000, false)
9383
		end
9384
	end
9385
	
9386
	function lib.mine(R)
9387
		-- starts on ceiling
9388
		local isValuable, blockType
9389
		for i = 1, R.length do
9390
			local fillUp = R.up
9391
			local fillDown = R.down
9392
			isValuable, blockType = T:isValuable("down")
9393
			if isValuable then
9394
				T:dig("down")
9395
			elseif blockType:find("water") ~= nil then
9396
				fillDown = true
9397
			elseif blockType:find("lava") ~= nil then
9398
				lib.refuel("down")
9399
				fillDown = true
9400
			end
9401
			isValuable, blockType = T:isValuable("up")
9402
			if isValuable then
9403
				T:dig("up")
9404
			elseif blockType:find("water") ~= nil then
9405
				fillUp = true
9406
			elseif blockType:find("lava") ~= nil then
9407
				lib.refuel("up")
9408
				fillUp = true
9409
			end
9410
			--if not turtle.detectUp() and fillUp then
9411
			if fillUp then
9412
				T:fillVoid("up")
9413
			end
9414
			--if not turtle.detectDown() and fillDown then
9415
			if fillDown then
9416
				T:fillVoid("down")
9417
			end
9418
			if i < R.length then 
9419
				T:forward(1)
9420
			end
9421
		end
9422
	end
9423
	
9424
	local outbound = true
9425
	
9426
	if R.subChoice == 1 then
9427
		T:up(1)
9428
	elseif R.subChoice == 3 then
9429
		T:go("U1F1")
9430
	elseif R.subChoice == 4 then
9431
		T:go("F1")
9432
	elseif R.subChoice == 5 then
9433
		T:go("U1R1 F1L1 F1")
9434
	end
9435
	
9436
	for w = 1, R.width do
9437
		lib.mine(R)
9438
		if w < R.width then
9439
			if outbound then
9440
				T:go("R1F1R1")
9441
			else
9442
				T:go("L1F1L1")
9443
			end
9444
			outbound = not outbound
9445
		end
9446
		if T:getFirstEmptySlot() == 0 then
9447
			T:dumpRefuse("forward", 1)
9448
		end
9449
	end
9450
	if outbound then
9451
		T:go("L1F"..R.width - 1 .."L1F"..R.length - 1)
9452
	else
9453
		T:go("R1F"..R.width - 1 .."R1")
9454
	end
9455
	
9456
	return {}
9457
end
9458
9459
local function quickMineCorridor(R) -- 16
9460
	--[[
9461
	R.subChoice
9462
	1: At corridor start, on the floor
9463
	2: At corridor start, on the ceiling
9464
	3: On floor, start 1 block ahead
9465
	4: On ceiling, start 1 block ahead
9466
	]]
9467
	if R.subChoice == 2 then
9468
		T:down(1)
9469
	elseif R.subChoice == 3 then
9470
		T:forward(1)
9471
	elseif R.subChoice == 4 then
9472
		T:go("D1F1")
9473
	end
9474
	local width = R.width - 1
9475
	local length = R.length - 1
9476
	R.silent = true
9477
	R.length = length
9478
	createCorridor(R, true) -- put floor and ceiling for R.length, place torch at start
9479
	T:turnRight(1)
9480
	R.length = width
9481
	createCorridor(R, true)
9482
	T:turnRight(1)
9483
	R.length = length
9484
	createCorridor(R, true)
9485
	T:turnRight(1)
9486
	R.length = width
9487
	createCorridor(R, true)
9488
	T:turnRight(1)
9489
	
9490
	return {}
9491
end
9492
9493-
		-- assumes legacy tree farm with turtle on polished block 4 blocks from corner
9493+
9494-
		local message  = ""
9494+
9495-
		R.treeSize = "single"
9495+
9496
	-- if width = 1
9497-
		--local logType = ""
9497+
9498-
		--local startHeight = 0
9498+
9499
		
9500
			-- replace block with replaceWith ("" = any)
9501
			
9502
			-- move up
9503
			
9504
		--end
9505
		
9506
		-- move back to beginning
9507
		
9508
	-- else
9509-
		if blockType:find("dirt") ~= nil then	-- dirt found
9509+
9510-
			T:go("R1F1L1")
9510+
9511
		
9512-
			if blockType:find("dirt") ~= nil then
9512+
9513-
				R.treeSize = "double"
9513+
9514
			-- for h = startAt, height, 1 do
9515-
			T:go("L1F1 R1")
9515+
9516-
		else	-- dirt NOT found where expected
9516+
9517-
			message = "Unable to determine position"
9517+
9518
				-- move up
9519
				
9520-
		blockType = T:getBlockType("forward")	-- 1 block above dirt
9520+
9521-
		if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil or blockType:find("propagule") ~= nil then
9521+
9522-
			local parts = T:getNames(blockType)
9522+
9523-
			if parts[2] == "dark" then
9523+
9524-
				R.logType = "dark_oak"
9524+
9525
			
9526-
				R.logType = parts[2]				-- eg "oak"
9526+
9527
				
9528-
			if R.logType == "mangrove" then
9528+
9529-
				R.useBlockType = "mangrove_propagule"
9529+
9530
			--end
9531-
				R.useBlockType = parts[2].."_sapling"	-- eg "oak_sapling"
9531+
9532
		-- end
9533
		
9534-
		T:down(1)	-- facing dirt
9534+
9535
	
9536-
		return R, message
9536+
9537
9538
local function getTaskItemsList()
9539-
	function lib.waitForGrowth(R)
9539+
9540-
		local pattern = R.treeSize	--"single","double"
9540+
9541-
		local elapsed = 0
9541+
9542-
		local facing = "left"
9542+
9543-
		local ready = {}
9543+
9544-
		ready.left = false
9544+
9545-
		ready.top = false
9545+
9546-
		ready.right = false
9546+
9547-
		ready.bottom = false
9547+
9548-
		if R.logType == "mangrove" then
9548+
9549-
			pattern = "mangrove"
9549+
9550-
			local facings = {"left", "top", "right", "bottom"}
9550+
9551-
			T:up(1)	-- go up from dirt to sapling level
9551+
9552-
			while not ready.left or not ready.right or not ready.top or not ready.bottom do
9552+
9553
	text[21] = {"1 chest (optional)"}																	-- Fell Tree
9554
	text[22] = {"320 stone", "4 polished stone"} 														-- Create treefarm
9555-
					if blockType:find("propagule") ==  nil then	-- either grown or deleted by roots
9555+
9556-
						ready[facings[i]] = true
9556+
9557
	text[25] = {"width * length * 2 walls or fences", "torches (optional)", "4 barrels (optional)"}		-- fence or wall a forest
9558
	text[26] = {"1 chest", " any saplings"} 															-- harvest and replant walled rectangle of natural forest
9559
				
9560-
				if ready.left and ready.right and ready.top and ready.bottom then
9560+
9561
	text[31] = {"64 stone","128 dirt (optional)", "4 water buckets","4 chests / barrels","1 sapling"}	-- Create modular crop farm
9562
	text[32] = {"64 stone","128 dirt (optional)", "4 water buckets","5 chests/ barrels","1 sapling"}	-- extend modular farm
9563-
					sleep(15)
9563+
9564-
					elapsed = elapsed + 15
9564+
9565-
					if  elapsed / 60 > 15 then	-- max 15 mins real time before farm is harvested
9565+
9566
9567
	-- OBSIDIAN
9568
	text[41] = {"stone to cover area of obsidian"}														-- Harvest obsidian
9569-
				print("Waiting for mangrove growth "..elapsed / 60 .." minutes")
9569+
9570-
				print("Left = "..tostring(ready.left)..
9570+
9571-
					  ", top = "..tostring(ready.top)..
9571+
9572-
					  ", right = "..tostring(ready.right)..
9572+
9573-
					  ", bottom = "..tostring(ready.bottom))
9573+
9574
	text[47] = {"448 stone, 145 ladders, 1 obsidian, 1 water bucket"} 									-- dragon water trap
9575
	text[48] = {"height * 4 stone","height * ladders", "1 trapdoor"}									-- build end portal platform
9576-
			--T:go("L1D1")
9576+
9577-
			T:turnLeft(1)	-- face front
9577+
9578
	text[51] = {"dirt or stone * length","torch (optional)"} 											-- single path
9579-
			while not ready.left or not ready.right do
9579+
9580-
				T:up(1)	-- go up from dirt to sapling level
9580+
9581-
				local blockType = T:getBlockType("forward")
9581+
9582-
				if blockType:find("log") ~=  nil then
9582+
9583-
					ready[facing] = true
9583+
9584
	text[57] = {"height * 10 stone","height * 4 + 2 soul sand, 2 water buckets"} 						-- Boat bubble lift
9585-
				if pattern == "single" then
9585+
9586-
					--alternate between 2 trees, starts facing left
9586+
9587
	text[61] = {"512 stone","1 slab"} 																	-- 9x9 cube round spawner
9588-
					if facing == "left" then
9588+
9589-
						facing = "right"
9589+
9590-
					elseif facing == "right" then
9590+
9591-
						facing = "left"
9591+
9592
	text[64] = {"128 stone","2 water buckets","1 soul sand"} 											--Build bubble tower kill zone
9593-
					blockType = T:getBlockType("forward")
9593+
9594-
					if blockType:find("log") ~=  nil then
9594+
9595-
						ready[facing] = true
9595+
9596
	text[66] = {"1856 stone, diorite etc (inc polished)","1 chest","10 empty buckets",
9597-
					T:down(1)	-- drop below sapling to dirt level
9597+
				"2 water buckets","192 fence","8 signs","3 ladder","2 soul sand"} 						-- build endermen observation tower
9598-
				elseif pattern == "double" then
9598+
9599-
					if ready.left and facing == "left" then-- tree on left now grown. check right
9599+
9600-
						T:go("R2F2")
9600+
9601-
						facing = "right"
9601+
9602
	text[73] = {"No items required"} 																	-- Clear wall height, length
9603-
					blockType = T:getBlockType("forward")
9603+
9604-
					if blockType:find("log") ~=  nil then
9604+
9605-
						ready[facing] = true
9605+
9606
	text[77] = {"No items required"} 																	-- Dig a trench
9607-
					T:down(1)	-- drop below sapling to dirt level
9607+
9608
	text[79] = {"width * height Any material floor / ceiling"} 											-- floor or ceiling
9609
	text[710] =	{"Blocks to add 'floor as you go'"} 													-- Direct control of movement
9610-
				print("Farm type: "..pattern)
9610+
9611-
				print("Waiting for tree growth "..elapsed / 60 .." minutes")
9611+
9612-
				print("Left grown = "..tostring(ready.left)..", right grown = "..tostring(ready.right))
9612+
9613-
				if not ready.left or not ready.right then
9613+
9614-
					sleep(15)
9614+
9615-
					elapsed = elapsed + 15
9615+
9616-
					if pattern == "single" and elapsed / 60 > 10 then	-- max 10 mins real time before farm is harvested
9616+
9617
	text[86] = {"Full inventories of sand or stone"}													-- Ocean monument utilities
9618-
					elseif pattern == "double" and elapsed / 60 > 15 then	-- max 15 mins real time before farm is harvested
9618+
9619
	text[88] = {"No items required"} 																	-- clear water plants
9620
	text[89] = {"water buckets / buckets"} 																-- convert flowing water to source
9621
	text[810] = {"6 buckets","slabs to cover area"} 													-- create sloping water
9622
				
9623
	-- BUILDING and MINECART
9624-
		-- growth complete
9624+
9625-
		if pattern == "single" then
9625+
9626-
			if facing == "right" then
9626+
9627
	text[94] = {"length * width * height stairs", "length * slabs"}										-- Build a pitched roof
9628
	text[95] = {"1 block of choice","1 redstone torch"} 												-- place redstone torch under current block
9629
	text[96] = {"1 block of choice","1 redstone torch"} 												-- place redstone torch on upward slope
9630
	text[97] = {"height x block of choice","height/3 x redstone torch"} 								-- build downward slope
9631-
			--T:go("F1R1 F3R1")			-- facing first dirt
9631+
9632-
			T:go("F1R1 F1R1")			-- facing first dirt
9632+
9633-
		elseif pattern == "double" then -- assume on right side
9633+
9634-
			if facing == "right" then
9634+
9635-
				T:go("R1F1 R1F4 R1")
9635+
9636
	-- display help about selected task
9637-
				T:go("L1F1 R1F2 R1")
9637+
9638
--[[This line of text = 39 characters]]
9639-
		elseif pattern == "mangrove" then 
9639+
9640-
			T:go("D2F6 U1F1 R1F6 R1F1 U1")
9640+
9641
	info = {}
9642-
		-- ends facing dirt at base of first tree
9642+
9643-
		-- no return needed, function exit so trees are grown
9643+
9644
	table.insert(info.main,
9645
	[[                ~lightGray~MINING:~white~
9646-
	function lib.watchFarm(R)
9646+
9647-
		-- rotate to check if dirt on both sides
9647+
9648-
		-- R.subChoice == 1: 16 single trees, 2 = 4 doubles
9648+
9649-
		if R.logType ~= "mangrove" then
9649+
9650-
			R.treeSize = "single"
9650+
9651-
			T:turnRight(2)	-- if no dirt then on 4 x doubles
9651+
9652-
			if T:getBlockType("forward") == "" then
9652+
9653-
				R.treeSize = "double"
9653+
9654
the fuel and time)
9655-
			T:saveToLog("lib.watchFarm: R.treeSize set to '"..R.treeSize.."'")
9655+
9656-
			T:turnLeft(2)	-- face lower left double dirt 
9656+
9657
	table.insert(info.main,
9658-
		lib.waitForGrowth(R)
9658+
9659
Fell Tree can be used in Nether as well
9660-
		return R
9660+
9661
Create a simple 16 single tree farm
9662
or 4 double size (Dark oak or any type)
9663-
	function lib.harvestSingle(direction, moves)
9663+
9664-
		-- if direction == "up": starting inside tree on dirt at dirt level
9664+
9665-
		T:saveToLog("lib.harvestSingle('"..direction.."', moves = "..moves)
9665+
9666
~green~Forest can be harvested and replanted.
9667-
			while turtle.detectUp() do
9667+
9668
9669
]])
9670
	table.insert(info.main,
9671-
		else	-- direction = "down", but could be mid-tree
9671+
9672-
			local movesUp = 0
9672+
9673-
			while turtle.detectUp() do
9673+
9674
or rectangular pattern.~lime~
9675-
				movesUp = movesUp + 1
9675+
9676
turtle, which must be equipped with a
9677-
			T:down(movesUp)
9677+
9678-
			T:down(moves)
9678+
9679
corner of each module.
9680
Double chests store produce and seeds.
9681
]])
9682
	table.insert(info.main,
9683-
	function lib.harvestSingleRow()
9683+
9684-
		-- start next to tree/dirt
9684+
9685
lava areas safely.~pink~
9686-
		local moves = lib.harvestSingle("up", 0)
9686+
9687-
		T:go("F2")
9687+
9688-
		lib.harvestSingle("down", moves)
9688+
9689-
		T:go("F2")
9689+
9690-
		moves = lib.harvestSingle("up", 0)
9690+
9691-
		T:go("F2")
9691+
9692-
		lib.harvestSingle("down", moves)
9692+
9693
Minecart end portal stations built.
9694
]])
9695-
	function lib.harvestDouble()
9695+
9696-
		T:forward(1)	-- dig dirt, move into left (S) corner
9696+
9697
Can be used in Nether and End.~lightGray~
9698-
		while turtle.detectUp() do
9698+
9699-
			turtle.dig()
9699+
9700-
			turtle.digUp()
9700+
9701
at the same time.~blue~
9702
Build a water canal with towpath.~cyan~
9703
Build a super-fast ice canal.~brown~
9704-
		turtle.dig()
9704+
9705-
		T:go("R1F1L1")	-- move to right corner
9705+
9706
1 block lower each time
9707-
			turtle.dig()
9707+
9708-
			turtle.digDown()
9708+
9709
	[[             ~lightGray~SPAWNER FARMS:~brown~
9710
Tools to create mob farms round
9711-
		turtle.dig()
9711+
9712-
		T:go("F1L1F1R1") -- move to left corner (N)
9712+
9713
uses rail collection.~cyan~
9714
Choice of bubble lift mob dropper
9715-
	--T:setUseLog(true, "treeFarmLog.txt", true)	-- T:setUseLog(use, filename, delete)
9715+
9716-
	--dbug = true								-- set dbug flag
9716+
9717
built >128 above ground: is ~red~expensive.~gray~
9718
Re-spawns new mobs when used.~red~
9719-
	-- if on modem, R.networkFarm has already been set
9719+
9720-
	T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm))
9720+
9721
	table.insert(info.main,
9722-
	if R.networkFarm then
9722+
9723-
		local message = network.loadStorageLists()	-- initialises or creates lists of where an item can be found: GLOBAL LISTS!
9723+
9724-
		if message ~= nil then return {message} end
9724+
9725-
		network.emptyInventory(R, {"sapling", "propagule", "dirt"}, {"all"}, true)
9725+
9726
Clear hollow and~orange~solid structures.~brown~
9727
Dig a trench.~gray~
9728-
	if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then
9728+
9729-
		local turtleSlot, turtleCount = network.getItemFromNetwork("chest", "log", 16)
9729+
9730-
		if turtleSlot > 0 then
9730+
9731-
			if turtle.craft() then
9731+
9732
9733-
				T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm))
9733+
9734
	table.insert(info.main,
9735
	[[      ~blue~WATER AND LAVA TOOLS:~white~
9736
Used to drain ocean monuments and
9737
shipwrecks. Can also be used to make
9738-
	if R.networkFarm then			-- monitor trees for growth
9738+
9739-
		if R.logType == "mangrove" then
9739+
9740
Destructive draining uses solid block
9741-
			T:place("dirt", "up")
9741+
9742-
			T:go("F6x2U1L1")	-- move under dirt covering, clear roots from hopper, move level with dirt, face left
9742+
9743
damaging structures.~lightBlue~
9744-
			T:go("F4R1")				-- either in between 2 trees or in gap between double trees at dirt level
9744+
9745-
			if turtle.detect() then		-- single trees, move between 1st and 2nd rows
9745+
9746-
				T:go("R1F1 R1F2 R1F1 L1")
9746+
9747-
			else	-- using double trees
9747+
9748-
				T:go("R2F1")
9748+
9749-
				if not turtle.detect() then
9749+
9750-
					return {"Unable to determine position"}
9750+
9751
~orange~Used to build diagonal uphill slope~brown~
9752
and downhill slope for placing
9753
45 degree rail tracks.~red~
9754-
		R = lib.watchFarm(R)	-- wait for trees to grow, then start harvest
9754+
9755
rails when above ground level (viaduct)
9756-
		--logType, startHeight, R = lib.initialise(R) -- possible ID tree type + move to correct position 1 above dirt
9756+
9757-
		R, message = lib.initialise(R) 		-- possible ID tree type + move to correct position next to first dirt
9757+
9758-
		if message ~= "" then
9758+
9759-
			return{message}
9759+
9760
	table.insert(info.main,
9761
	[[           ~yellow~MEASURING TOOLS:
9762-
	T:saveToLog("R.networkFarm = "..tostring(R.networkFarm)..", logType = "..R.logType..", treeSize = "..R.treeSize)
9762+
9763-
	-- different clearing for different trees:
9763+
9764-
	-- double spruce and jungle: staight up/down or small
9764+
9765-
	if R.logType == "mangrove" then
9765+
9766-
		clearRectangle({width = 13, length = 13, up = true, down = true })
9766+
9767-
		T:go("U2F2 R1F2L1")
9767+
9768-
		clearSolid({width = 9, length = 9, height = 18, direction ="up"})
9768+
9769-
		T:go("D3R1 F4R1 F3R2")
9769+
9770-
		network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9770+
9771-
	elseif R.logType == "birch" or R.logType == "spruce" or R.logType == "jungle" then	-- use column harvest
9771+
9772-
		if R.treeSize == "single" then
9772+
9773-
			lib.harvestSingleRow()
9773+
9774-
			T:go("F1R1F2R1")
9774+
9775-
			lib.harvestSingleRow()
9775+
9776-
			T:go("F1L1F2L1")
9776+
9777-
			lib.harvestSingleRow()
9777+
9778-
			T:go("F1R1F2R1")
9778+
9779-
			lib.harvestSingleRow()
9779+
9780-
			if R.networkFarm then
9780+
9781-
				T:go("F1R1 F3L1 F3R2")
9781+
9782-
				network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9782+
9783
~lightGray~| | | | | |
9784-
				T:go("F1R1 F6L1 F3R2")
9784+
9785
9786
]]-- Ladder up/down
9787-
			lib.harvestDouble()
9787+
9788-
			T:go("F3")
9788+
9789-
			lib.harvestDouble()
9789+
9790-
			T:go("R1F4")
9790+
9791-
			lib.harvestDouble()
9791+
9792-
			T:go("R1F4")
9792+
9793-
			lib.harvestDouble()
9793+
9794-
			if R.networkFarm then
9794+
9795-
				T:go("F1R1 F3L1 F3R2")
9795+
9796-
				network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9796+
9797
9798-
				T:go("F1R1 F6L1 F3R2")
9798+
9799
]] -- Stairs up/down
9800
		info.sub[13] = 
9801-
	else	-- use cube harvest, including mangrove
9801+
9802-
		local size = 10
9802+
9803-
		local start = "L1F1 L1F1 R2"
9803+
9804-
		local finish = "R1F1 R1F3 R2"
9804+
9805-
		if R.logType == "acacia" then
9805+
9806-
			size = 12
9806+
9807-
			start = "L1F2 L1F2 R2"
9807+
9808-
			finish = "R1F2 R1F2 R2"
9808+
9809-
		elseif R.logType == "cherry" then
9809+
9810-
			size = 14
9810+
9811-
			start = "L1F3 L1F3 R2"
9811+
9812-
			finish = "R1F3 R1F1 R2"
9812+
9813
	else
9814-
		T:go("U1F1")	-- into first log at base of tree
9814+
9815-
		clearRectangle({width = 7, length = 7, up = true, down = true})
9815+
9816-
		--T:go("L1F2 L1F2 R2")	-- rect size 12
9816+
9817-
		--T:go("L1F1 L1F1 R2")	-- rect size 10
9817+
9818-
		T:go(start)
9818+
9819-
		local height = 0
9819+
9820-
		local pastLogCount = -1
9820+
9821-
		local currentLogCount = lib.getLogCount()
9821+
9822-
		--while currentLogCount ~= pastLogCount do
9822+
9823-
		while currentLogCount - pastLogCount > 5 do	-- ony continue if at least 5 logs harvested last round
9823+
9824-
			T:up(3)
9824+
9825
~lightGray~| | | | | | ~red~^ = Turtle facing forward
9826-
			pastLogCount = currentLogCount -- 0 when loop starts
9826+
9827-
			--clearRectangle({width = 12, length = 12, up = true, down = true})
9827+
9828-
			clearRectangle({width = size, length = size, up = true, down = true})
9828+
9829-
			currentLogCount = lib.getLogCount() -- eg 20 logs from first round
9829+
9830-
		end	
9830+
9831-
		T:down(height + 1)
9831+
9832-
		--T:go("R1F2 R1F2 R2")		-- on polished stone rect size 12
9832+
9833-
		--T:go("R1F1 R1F3 R2")		-- on polished stone rect size 10
9833+
9834-
		T:go(finish)
9834+
9835-
		if R.networkFarm then
9835+
9836-
			T:go("R1F3 L1")			-- on modem
9836+
9837-
			network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9837+
9838
| |~blue~^~brown~|L|~blue~^~lightGray~| | ~brown~L = ladder
9839
~lightGray~| | | | | | ~blue~^ = Turtle facing forward
9840
~lightGray~| | | | | | ~blue~^ = Bubble column above
9841-
	return {}	-- if player initiated, stops here. If R.auto then returns to plantTreeFarm()
9841+
9842
]] -- single column bubble lift
9843
	info.sub[16] = 
9844
[[~yellow~Place me as below:
9845
 1. On ~blue~floor   ~yellow~(feet height)
9846
 2. On ~lime~ceiling ~yellow~(eye height)
9847
9848
~lightGray~B|B|B|B|B|B|B    ~yellow~W I D T H
9849
~lightGray~B| | | | | |B               ~orange~L
9850
~lightGray~B| |B|B|B| |B               ~orange~E
9851
~lightGray~B| |B|B|B| |B               ~orange~N
9852
~lightGray~B| |B|B|B| |B               ~orange~G 
9853
~lightGray~B|~red~^~lightGray~| | | | |B  ~red~^~lightGray~ = Turtle   ~orange~T
9854
~lightGray~B|~cyan~P~lightGray~|B|B|B|B|B  ~cyan~P~lightGray~ = Player   ~orange~H
9855
]] -- quick corridor system
9856
	info.sub[17] = 
9857
[[~yellow~~yellow~Place me as below:
9858
 1. On ~blue~floor   ~yellow~(feet height)
9859
 2. On ~lime~ceiling ~yellow~(eye height)
9860
~lightGray~B|B|B|B|B|B|B 
9861
B| | | | | |B
9862
B| |B|B|B| |B
9863
B| |B|B|B| |B
9864
B| |~lime~^~lightGray~|B|B| |B
9865
B|~red~^~lightGray~|~magenta~^~lightGray~| | | |B ~white~^~lightGray~ = turtle
9866
B|~cyan~P~lightGray~|B|B|B|B|B ~cyan~P~lightGray~ = Player
9867
~yellow~Note colour of ~white~^~yellow~ matches next screen->
9868
]] -- quick mine
9869
		info.sub[18] = 
9870
[[~yellow~Place me level -59 / 5 on the floor to
9871
expose bedrock ~red~(slow and inefficient)
9872
9873
~lightGray~| | | |B| |B|     ~yellow~W I D T H
9874
~lightGray~|B| | | | | |B               ~orange~L
9875
~lightGray~| | | |B|B| |                ~orange~E
9876
~lightGray~| | |B| | |B|                ~orange~N
9877
~lightGray~|B| | | |B| |                ~orange~G 
9878
~lightGray~| | | | | | |B               ~orange~T
9879
~lightGray~|~red~^~lightGray~| | | |B| |B  ~red~^~lightGray~ = Turtle   ~orange~H
9880
]] -- mine all blocks to bedrock pre 1.12
9881
		info.sub[19] = 
9882
[[~yellow~Place me on the end wall of a disused
9883
mine in the centre block, 1 block above
9884
the floor.
9885
Provide a ~cyan~diamond ~yellow~sword for
9886
harvesting string from spider webs~lightGray~
9887
9888
~gray~-------   - = Ceiling
9889
~lightGray~| | | |
9890
| |~red~T~lightGray~| |  ~red~T = Turtle (facing wall)
9891
~lightGray~| | | |
9892
~gray~-------  - = Floor
9893
]] -- salvage mineshaft
9894
	info.sub[21] = 
9895
[[~yellow~Place me as below.
9896
~brown~Chest ~yellow~ONLY required if ~blue~0 ~yellow~fuel
9897
9898
Plan view:
9899
9900
~green~   | | | |
9901
~green~   | |~lime~T~green~| |  ~lime~T = Tree
9902
~green~   | |~red~^~green~| |  ~red~^ = Turtle
9903
~green~   | | | |
9904
9905
9906
9907
]] -- Fell Tree
9908
	info.sub[22] = 
9909
[[~yellow~Place me on ground as below ~red~^
9910
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| 
9911
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | | | | |
9912
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | ~brown~|D| |D|
9913
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | |
9914
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | |
9915
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | |
9916
~lime~|~red~^~lime~|*|*|*|~blue~M~lime~|*| | ~green~or |~red~^~green~|*|*|*|~blue~M~green~|*|*|
9917
~lime~4 ~brown~double ~green~       or 16 ~brown~single
9918
~brown~D = Dirt, ~red~^ = Turtle, ~blue~M = Marker stone
9919
]] -- Create treefarm
9920
	info.sub[23] = 
9921
[[~yellow~Place me on ground as below ~red~^
9922
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| 
9923
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | | | | |
9924
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | ~green~or |*|~blue~ | | ~brown~|D| |D|
9925
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | |
9926
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | |
9927
~lime~|*|~blue~ | | | | | | ~green~or |*|~blue~ | | | | | |
9928
~lime~|*|*|*|*|~red~^~lime~|*| | ~green~or |*|*|*|*|~red~^~green~|*|*|
9929
~green~4 ~brown~double ~green~       or 16 ~brown~single
9930
~brown~D = dirt,~red~^ = Turtle, ~yellow~Max 16 saplings
9931
Mixed OK. ~lime~Group 4 for double trees
9932
]] -- Plant treefarm / Harvest treefarm
9933
	info.sub[24] = info.sub[23] 
9934
	info.sub[25] =
9935
[[~yellow~Place me at ~red~^
9936
9937
~lightGray~|F|F|F|F|F|F|F| F = Fence or Wall
9938
~lightGray~|F|~brown~B~lime~| | | |~brown~B~lightGray~|F| ~brown~B = Barrel (corners)
9939
~lightGray~|F|~lime~ | | | | ~lightGray~|F|
9940
~lightGray~|F|~lime~ | | | |~cyan~T~lightGray~|F| ~cyan~T = Tree
9941
~lightGray~|F|~lime~ |~cyan~T~lime~| | | ~lightGray~|F|
9942
~lightGray~|F|~lime~ | | | | ~lightGray~|F|
9943
~lightGray~|F|~brown~B~lime~| |~cyan~T~lime~| |~brown~B~lightGray~|F| 
9944
~lightGray~|~red~^~lightGray~|F|F|F|F|F|F| ~red~^ = Turtle
9945
~yellow~Fence/Wall follows land contours
9946
]] -- 
9947
	info.sub[26] =
9948
[[~yellow~A rectangular walled area of forest:
9949
Place me at ~red~^
9950
9951
~lightGray~|F|F|F|F|F|F|F| F = Fence or wall
9952
~lightGray~|F|~brown~B~lime~| | | |~brown~B~lightGray~|F| ~brown~B = Barrel (corners)
9953
~lightGray~|F|~lime~ | | | | ~lightGray~|F|
9954
~lightGray~|F|~lime~ | | | |~cyan~T~lightGray~|F| ~cyan~T = Tree
9955
~lightGray~|F|~lime~ |~cyan~T~lime~| | | ~lightGray~|F|
9956
~lightGray~|F|~lime~ | | | | ~lightGray~|F|
9957
~lightGray~|F|~red~^~lime~| |~cyan~T~lime~| |~brown~B~lightGray~|F| ~red~^ = Turtle ~brown~(on Barrel)
9958
~lightGray~|F|F|F|F|F|F|F|
9959
9960
]] -- manage walled forest
9961
	info.sub[31] = 
9962
[[~yellow~Place me on the ground as below ~red~^
9963
9964
~lightGray~|*|~green~ | | | | | | | | ~lightGray~* = Wall
9965
~lightGray~|*|~green~ | | | | | | | |
9966
~lightGray~|*|~green~ | | | | | | | |
9967
~lightGray~|*|~green~ | | | | | | | |
9968
~lightGray~|*|~green~ | | | | | | | | 
9969
~brown~|B|B~green~| | | | | | | | ~brown~B = Barrel or Chest
9970
~brown~|B|~blue~W~green~| | | | | | | | ~blue~W = Water
9971
~lime~|~red~^~lime~|~brown~B|B|~lightGray~*|*|*|*|*|*| ~red~^ = Turtle
9972
~yellow~                    Size = 13 x 13
9973
]] -- Create modular crop farm
9974
	info.sub[32] = 
9975
[[~yellow~Place next to the tree as below ~red~^
9976
9977
~lightGray~|*|~green~ | | | | | | | | ~lightGray~* = Wall
9978
~lightGray~|*|~green~ | | | | | | | |
9979
~lightGray~|*|~green~ | | | | | | | | 
9980
~lightGray~|*|~green~ | | | | | | | | 
9981
~lightGray~|*|~green~ | | | | | | | | ~brown~B = Barrel or Chest
9982
~brown~|B|B~green~| | | | | | | | ~blue~W = Water
9983
~brown~|B|~blue~W~green~| | | | | | | | ~orange~S = Sapling or Tree
9984
~orange~|S|~red~^~brown~|B|~lightGray~*|*|*|*|*|*| ~red~^ = Turtle
9985
~yellow~                    Size = 13 x 13
9986
]] -- Extend farm
9987
	info.sub[33] = 
9988
[[~yellow~Place as below (2 choices) ~blue~> ~yellow~or ~red~<
9989
9990
~lightGray~|*|~green~ | | | | | | | | ~lightGray~* = Wall
9991
~lightGray~|*|~green~ | | | | | | | |
9992
~lightGray~|*|~green~ | | | | | | | | 
9993
~lightGray~|*|~green~ | | | | | | | | ~brown~B = Barrel or Chest
9994
~lightGray~|*|~green~ | | | | | | | | ~blue~> = turtle on Water
9995
~brown~|B|B~green~| | | | | | | | C = Crop (first)
9996
~brown~|B|~blue~>~green~|C| | | | | | | ~orange~S = Sapling or Tree
9997
~orange~|S|~red~<~brown~|B|~lightGray~*|*|*|*|*|*| ~red~< = Turtle on Chest
9998
~yellow~Options to harvest or manage to follow.
9999
]] -- Manual harvest and auto setup
10000
	info.sub[34] = 
10001
[[~yellow~Build a ~brown~fence ~yellow~or ~lightGray~wall ~yellow~to chosen length.
10002
10003
Turtle goes ~orange~BACKWARDS ~yellow~when started.
10004
10005
Start: length = 6, Turtle facing right
10006
10007
~lightGray~| |~red~>~lightGray~| | | | | | | ~red~> = Turtle
10008
10009
Finish:
10010
10011
~lightGray~| |F|F|F|F|F|F| | F = Fence or Wall
10012
]] -- build fence or wall
10013
	info.sub[35] = 
10014
[[~yellow~Build a ~brown~fence ~yellow~or ~lightGray~wall ~yellow~
10015
rectangular area.
10016
10017
~lightGray~| | | | | | | | ~brown~F = Fence or Wall
10018
~lightGray~| ~brown~|F|F|F|F|F~lightGray~| |
10019
~lightGray~| ~brown~|F| | | |F~lightGray~| |
10020
~lightGray~| ~brown~|F| | | |F~lightGray~| |
10021
~lightGray~| ~brown~|F| | | |F~lightGray~| |
10022
~lightGray~| |~red~^~brown~|F|F|F|F| | ~red~^ = Turtle
10023
~lightGray~| | | | | | | |
10024
10025
]] -- build rectangular fence or wall
10026
	info.sub[41] = 
10027
[[~yellow~Place me on any block on the left 
10028
side facing the obsidian field.
10029
10030
~gray~|O|O|O|O|O| O = Obsidian
10031
|O|O|O|O|O|
10032
|O|O|O|O|O|
10033
|O|O|O|O|O|
10034
|~red~^~gray~|O|O|O|O| ~red~^ = Turtle
10035
|~red~^~gray~| | | | |
10036
10037
]] -- Harvest obsidian
10038
	info.sub[42] = 
10039
[[~yellow~Place me on the ground as below ~red~> ~pink~^
10040
~yellow~Start ~red~> ~yellow~(facing right) or ~pink~^ ~yellow~ahead
10041
  
10042
~lightGray~| |~red~>~lightGray~|O|O|*| | |    |*|O|O|*| face view             
10043
   ~pink~^~lightGray~               |O|~purple~+ +~lightGray~|O|
10044
                   |O|~purple~+ +~lightGray~|O|
10045
~yellow~Result (plan)      ~lightGray~|O|~purple~+ +~lightGray~|O|
10046
~lightGray~| |O|O|O|O| | |    |*|O|O|*|
10047
                   ~green~--------- ground
10048
~yellow~width=4, ~orange~height=5 ~red~(frame size)
10049
]] -- build Nether portal
10050
	info.sub[43] = info.sub[42] -- Demolish Nether portal
10051
	info.sub[44] = 
10052
[[~yellow~Press F3+G for chunk boundaries
10053
Netherite stripmine plan view
10054
               
10055
~lightGray~|*|*|*~lime~N~lightGray~*|*|*|
10056
~lightGray~|*|*|*~lime~|~lightGray~*|*|*| ~lime~-| = Chunk Boundaries
10057
~lightGray~|*|~red~^~lightGray~|*~lime~|~lightGray~*|~red~^~lightGray~|*|  ~red~^ = Turtle
10058
~lime~W*-*-*~blue~+~lime~*-*-*E  ~blue~+ = Boundaries junction
10059
~lightGray~|*|*|*~lime~|~lightGray~*|*|*|
10060
~lightGray~|*|*|*~lime~|~lightGray~*|*|*|  ~yellow~North of WE
10061
~lightGray~|*|*|*~lime~S~lightGray~*|*|*|  ~yellow~1 block from NS
10062
Most generate close to chunk boundaries
10063
]] -- Netherite stripping
10064
	info.sub[45] = 
10065
[[~yellow~Place me on the ground ~red~<~yellow~ facing ~red~West.
10066
10067
~lime~x
10068
                 ~lightGray~N
10069
~lime~a~lightGray~   -1        | | | |  
10070
~lime~x~lightGray~    0       ~red~W~lightGray~| |~red~<~lightGray~| |E  ~red~< = Turtle
10071
~lime~i~lightGray~    1        | | | |  
10072
~lime~s~lightGray~                S
10073
    ~green~z axis    ~lightGray~-1 0 1
10074
  
10075
Centre of the dragon arena ~lime~X = 0, ~green~Z = 0
10076
~yellow~                           facing ~red~West 
10077
]] -- Find dragon tower centres
10078
	info.sub[46] = 
10079
[[~yellow~Place turtle in ceiling facing endstone
10080
10081
Plan view    Side view
10082
~gray~             |*|*|*|*|*|
10083
    |*|      |*|*|*|*|*|
10084
  |*|*|*|    |*|*|*|*|*|
10085
|*|*|*|*|*|  |*|*|*|*|*|  * ~lightGray~= Obsidian
10086
~gray~|*|*|~yellow~E~gray~|*|*|  |*|*|*|*|*|  ~yellow~E ~lightGray~= Endstone
10087
~gray~  |*|~red~^~gray~|*|    |*|*|~red~T~gray~|*|*|~red~ ^T ~lightGray~= Turtle
10088
~gray~    |*|      |*|*| |*|*|
10089
             |*|*| |*|*|
10090
]] -- deactivate dragon tower
10091
	info.sub[47] = 
10092
[[~yellow~Place turtle on the ground at 100,49,0
10093
10094
|*|*|*|*|*|*|*|*|*|   ~lightGray~= Dragon Island
10095
10096
10097
~yellow~    Facing WEST
10098
~gray~    |*|*|*|*|*|     * ~lightGray~= Obsidian plate
10099
~gray~    |*|*|*|*|*|
10100
~yellow~  S ~gray~|*|*|~red~T~gray~|*|*| ~yellow~N   ~red~T ~lightGray~= Turtle
10101
~gray~    |*|*|*|*|*|
10102
    |*|*|*|*|*|
10103
~yellow~         E]] -- build dragon water trap
10104
	info.sub[48] = 
10105
[[~yellow~Place turtle under end world portal
10106
10107
~gray~        |B|     B ~lightGray~= Bedrock
10108
~gray~      |B|B|B|
10109
        ~purple~|P|     P ~lightGray~= Portal
10110
~gray~      |B|B|B|
10111
        |B|
10112
         ~green~|		
10113
         ~green~|      ~lime~Height measured first		
10114
         ~green~|		
10115
~red~         T	     T ~lightGray~= Turtle	
10116
~yellow~  |*|*|*|*|*|*| ~red~Inventory AFTER height
10117
]] -- build end portal minecart
10118
	
10119
	info.sub[491] = 
10120
[[~yellow~Place turtle <64 blocks from shulker
10121
Directly below or 1 block in front
10122
~lightGray~|*|*|*|*|*|*|*|
10123
     ~gray~> ~lime~S ~gray~<       > T < = kill positions
10124
       ~gray~T
10125
10126
10127
10128
     ~red~> T <       Attacks ahead / above
10129
~lightGray~|*|*|*|*|*|*|*|
10130
10131
~red~> T <~lightGray~ = Turtle   ~lime~S~lightGray~ = Shulker]] -- Shulker is above
10132
10133
	info.sub[492] = 
10134
[[~yellow~Place turtle <64 blocks from shulker
10135-
local function upgradeFarmland(R)
10135+
10136-
	local essences = {":inferium", ":prudentium", ":tertium", ":imperium", ":supremium", ":awakened" , ":insanium"}
10136+
10137
   ~red~>~lightGray~ | | | | | |~lime~S~lightGray~|
10138
  
10139
~yellow~Side view:
10140-
	function lib.isHigherTeir(essence, farmLand)
10140+
10141-
		-- eg "ma:prudentium_essence", "mc:farmland"
10141+
10142-
		local teir = 0
10142+
10143-
		for index = 1, #essences do
10143+
10144-
			if farmLand:find(essences[index]) ~= nil then
10144+
10145-
				teir = index	-- 0 if vanilla, else eg 2 for prudentium
10145+
10146
	info.sub[493] = 
10147
[[~yellow~Place turtle <64 blocks from shulker
10148
Directly above or 1 block in front
10149-
		for index = 1, #essences do
10149+
10150-
			if essence:find(essences[index]) ~= nil then
10150+
10151-
				if index > teir then
10151+
10152
10153
10154
       ~gray~T
10155
     ~gray~> ~lime~S ~gray~<       > T < = kill positions
10156
~lightGray~|*|*|*|*|*|*|*|
10157
10158
~red~> T <~lightGray~ = Turtle   ~lime~S~lightGray~ = Shulker]] -- Shulker is below
10159-
	function lib.upgrade(essence, slot)
10159+
10160-
		-- essence is the slot no of any essence
10160+
10161-
		turtle.select(slot)
10161+
10162-
		local blockType = T:getBlockType("up")
10162+
10163-
		if blockType:find("farmland") ~= nil then			-- farmland found (vanilla or modded)
10163+
10164-
			if lib.isHigherTeir(essence, blockType) then	-- eg "ma:inferium", mc:farmland"
10164+
10165-
				turtle.placeUp()
10165+
10166
~lightGray~|*|~orange~+~lightGray~| | |~red~+~lightGray~| | |~blue~+~lightGray~|*|     ~yellow~Plan view
10167
~lightGray~|*|~orange~+|+|+|~red~+|~blue~+|+|+~lightGray~|*|    |*|*|*|*|*|
10168
~lightGray~|*|*|*|~orange~+|~red~+|~blue~+~lightGray~|*|*|*|    |*| |~red~T~lightGray~| |*|
10169-
	-- check if any essence still onboard
10169+
10170-
	T:checkInventoryForItem({"essence"}, {95}, false)
10170+
10171-
	-- return slotData.lastSlot, total, slotData -- integer, integer, table
10171+
10172-
	local name = ""
10172+
10173-
	local slot, amount, data = T:getItemSlot("essence")
10173+
10174-
	name = data.mostName or ""
10174+
10175-
	local empty = T:getFirstEmptySlot()
10175+
10176
clear the roof above and return
10177-
	if slot > 0 then
10177+
10178-
		T:go("D2")
10178+
10179
~lightGray~|*|~red~<~lightGray~| | | | | | |~red~^~lightGray~|*|  ~yellow~area regardless
10180-
		for w = 1, 10 do
10180+
10181-
			for i = 1, 9 do
10181+
10182-
				if turtle.getItemCount(slot) == 0 then
10182+
10183-
					slot, amount, data = T:getItemSlot("essence")
10183+
10184-
					name = data.mostName or ""
10184+
10185-
					if slot == 0 then
10185+
10186-
						slot = empty
10186+
10187
[[~yellow~Place turtle in corner against ceiling
10188
Face ~red~direction ~yellow~shown. It will exit out,
10189-
				lib.upgrade(name, slot)
10189+
10190-
				if w == 1 and i == 1 then
10190+
10191-
					T:go("F1R2 C1R2")
10191+
10192-
				elseif w == 10 and i == 1 then
10192+
10193-
					
10193+
10194
10195
~lightGray~|*| | | | | | | | |*|
10196
~lightGray~|*|~red~V~lightGray~| | | | | | |~red~>~lightGray~|*|
10197
~lightGray~|*|*|*|*|*|*|*|*|*|*|]] -- Clear outside wall
10198
10199-
				lib.upgrade(name, slot)
10199+
10200-
				if w == 1 then
10200+
10201-
					T:go("L1F1 L2C1 R1")
10201+
10202-
				elseif w == 9 then
10202+
10203-
					T:go("L1F1 L1F1 L2C1 L2")
10203+
10204
~blue~        |-|-|-|
10205
~lightGray~        |*|~red~^~lightGray~|*|    ~red~^ = Turtle
10206
10207
~yellow~Result:~blue~ |-|~lightGray~*|~blue~-|    - = air/water
10208-
				if w < 10 then
10208+
10209-
					lib.upgrade(name, slot)
10209+
10210
~lightGray~        |*|*|*|    * = Solid block
10211
]] -- Single path
10212-
					T:go("L1F1 L2C1 R2F8 L1U1 C2U2") -- 1 above normal position
10212+
10213
[[~yellow~Place ~red~^ T~yellow~ at start of path or tunnel
10214
10215
~yellow~Plan view    Face view
10216
10217-
		-- sometimes original essence pops out of the ground when upgraded, so rescue it
10217+
10218-
		for w = 1, 10 do
10218+
10219-
			for i = 1, 9 do
10219+
10220-
				turtle.suckDown()
10220+
10221-
				turtle.suck()
10221+
10222
10223
~green~Floor + ceiling ~yellow~placed for your safety!
10224
]] -- Covered walkway / tunnel
10225-
				turtle.suckDown()
10225+
10226-
				turtle.suck()
10226+
10227
10228
~lightGray~|*|~blue~-|-~lightGray~|*|
10229-
				if w < 10 then
10229+
10230-
					turtle.suckDown()
10230+
10231-
					turtle.suck()
10231+
10232
10233
~yellow~New canal       ~lime~1 ~orange~2 ~brown~3 ~green~4 ~yellow~ground level-63
10234-
					T:go("L1F9 L1D1") -- normal position
10234+
10235
~yellow~Extend existing   ~blue~5 ~cyan~6   ~yellow~water  level-62
10236
]] -- new/existing canal
10237
	info.sub[54] = 
10238
[[~lime~New ~yellow~ice canal or ~lightBlue~convert ~yellow~existing water
10239
10240-
	return ({"Farmland Upgraded"})
10240+
10241
~lightGray~ |~orange~T~lightGray~|~blue~I~lightGray~| |*| 	 ~blue~I = Ice (packed or blue)
10242
~lightGray~ |*| | |*| 	| | = Air (empty block)
10243
~lightGray~ |*|~blue~I~lightGray~| |~orange~T~lightGray~|   ~orange~T = Torch (optional)
10244
~lime~  1 2 3 4    New ice canal
10245
~lightBlue~  5 6 7 8    Convert water canal
10246-
	function lib.askPlayerForCrops()
10246+
10247-
		local seed  = ""
10247+
10248-
		pp.itemColours = {colors.lightGray, colors.red, colors.orange, colors.brown, colors.magenta, colors.yellow}
10248+
10249-
		crops = {"minecraft:wheat_seeds", "minecraft:beetroot_seeds", "minecraft:carrots", "minecraft:potatoes", "mysticalagriculture", "none"}
10249+
10250-
		choices = {"wheat (seeds)", "beetroot (seeds)", "carrot", "potato", "Mystical Agriculture", "Till soil only"}
10250+
10251
[[~yellow~Place ~red~^~yellow~ any level air, water or lava.~lightGray~
10252
10253-
		if crop == "none" then
10253+
10254-
			return "", ""
10254+
10255-
		elseif crop == "mysticalagriculture" then
10255+
10256-
			T:checkInventoryForItem({"seeds"}, {95}, true, "Add one type of M. Agriculture seeds")
10256+
10257
| |*|*|*|*|*| |
10258-
			T:checkInventoryForItem({crop}, {95}, true, "Do not mix! add as many as you want")
10258+
10259
| | | | | | | |
10260-
		crop = T:getMostItem("", false)		-- not searching for any specific item, not checking stone only
10260+
10261-
		-- crop could be wheat/beetroot seeds, carrots, potatoes or mystical agriculture seeds
10261+
10262-
		seed, crop = lib.getCropSeed(crop)	-- seed type or "", crop type
10262+
10263-
		return seed, crop	
10263+
10264
[[~yellow~Place ~red~^~yellow~ above water.~lightGray~
10265
Existing platform replaced below
10266-
	function lib.assessPlot(R)
10266+
10267-
		local crop = T:getBlockType("forward")	-- convert ma:inferium_crop to ma:inferium_seeds
10267+
10268-
		local seed = lib.getCropSeed(crop)
10268+
10269-
		turtle.down()									-- into water source
10269+
10270-
		local soil = T:getBlockType("forward")
10270+
10271-
		turtle.up()										-- at crop level
10271+
10272-
		return crop, seed, soil
10272+
10273
10274
Blocks placed under the turtle
10275-
	function lib.checkEquipment(R, itemRequired)
10275+
10276-
		-- Check if item is equipped and return it to slot
10276+
10277
[[~yellow~Boat Lift (Ice or Water)
10278
Place turtle left side. ~blue~Source~yellow~ to right
10279-
		local equipped, slot = T:getEquipped("right", false)	-- see what is equipped and replace it 
10279+
10280-
		if equipped == itemRequired then
10280+
10281-
			equipped, slot = T:getEquipped("right", true)		-- remove item and return slot
10281+
10282-
			return slot
10282+
10283
|*|*|*|*|    |*|~brown~S|S~lightGray~|*| ~brown~S = ~lightGray~Sand + gate
10284
|~red~^~lightGray~|~blue~W|W~lightGray~|*|    |*~blue~|W|W|~lightGray~*| ~red~^ ~lightGray~= Turtle
10285-
		return 0	-- not found
10285+
10286
|*|~blue~ | ~lightGray~|*|    |*|~blue~ | ~lightGray~|*| ~yellow~Ice canal needs
10287
~lightGray~|*|~blue~ | ~lightGray~|*|    |*|~blue~ | ~lightGray~|*| ~yellow~2x2 water source
10288-
	function lib.crossFarm(R)
10288+
10289
	info.sub[61] = 
10290
[[~red~NOT ~yellow~for Blaze spawners!
10291-
		local isReady, cropType, seed, status
10291+
10292-
		isReady, cropType, seed, status, R = lib.isCropReady(R,"down")
10292+
10293-
		-- will go forward until chest, barrel, modem or cobble detected below
10293+
10294
T|*| | | | | |*|T  |*| | | | | |*|
10295
 |*| | |~magenta~5~lightGray~| | |*|   |*| | |~magenta~5~lightGray~| | |*|
10296
 |*| |~magenta~5~lightGray~|~orange~S~lightGray~|~magenta~5~lightGray~| |*|   |*|~lime~3~lightGray~|~magenta~5|~orange~S~lightGray~|~magenta~5|~green~4~lightGray~|*| Base
10297
 |*| | |~magenta~5~lightGray~| | |*|
10298
T|*| | | | | |*|T  * = Dungeon Wall
10299
 |*|*|*|*|*|*|*|   ~orange~S = Spawner
10300
~lightGray~    T       T      T = Turtle ~brown~1 ~yellow~2 ~lime~3 ~green~4
10301-
			elseif  blockType:find("barrel") ~= nil or
10301+
10302-
					blockType:find("chest") ~= nil or
10302+
10303-
					blockType:find("modem") ~= nil or
10303+
10304-
					blockType:find("cobble") ~= nil then
10304+
10305
Plan view          Side view
10306
10307
~lightGray~|*|*|*|*|*|*|*|*|  ~lime~> T = Continue build
10308
~lightGray~|*| | | | | | | |  ~red~< T = New build
10309-
		return R, blockType -- either barrel, chest, modem or cobble
10309+
10310
|*| | | |~purple~S~lightGray~| | | |~lime~>~red~<          T
10311
~lightGray~|*| | | | | | | |   |*| | | |~purple~S~lightGray~| | | |~red~T
10312-
	function lib.farmAll(R, isFarmToRight, isFarmToFront)
10312+
10313-
		local plotCountR = 0		-- plot a1 harvested
10313+
10314-
		local plotCountF = 0		-- plot a1 harvested
10314+
10315
                                     ~red~T]] -- 9x9 cube round blaze spawner
10316-
			while isFarmToRight do	-- do all plots on this axis
10316+
10317-
				R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin
10317+
10318-
				plotCountR = plotCountR + 1
10318+
10319
~lightGray~ |*| | | | | | | | | |*|  |*| | | | | |
10320-
			lib.goToLeft(R, plotCountR)
10320+
10321
 |*| | | | | | | | | |*|  |*| | | | | |
10322
 |*| | | | | | | | | |*|  |*| | | | | |
10323-
			while isFarmToFront do	-- do all plots on this axis
10323+
10324-
				plotCountR = 0				-- reset
10324+
10325-
				R, isFarmToRight, isFarmToFront = lib.farmInFront(R)
10325+
10326-
				if isFarmToRight then
10326+
10327-
					while isFarmToRight do	-- do all plots on this axis
10327+
10328-
						R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin
10328+
10329-
						plotCountR = plotCountR + 1
10329+
10330
[[~yellow~Bubble lift: Plan view at start~lightGray~
10331-
					lib.goToLeft(R, plotCountR)	-- return home and continue with front
10331+
10332
 |*| | | | |~brown~F~lightGray~| | | | |*|
10333-
				plotCountF = plotCountF + 1
10333+
10334
           ~brown~|~red~^~brown~|~lightGray~= Turtle on ~brown~Soul Sand
10335-
			lib.goToFront(R, plotCountF)
10335+
10336
~yellow~Plan view completed~lightGray~		   
10337
 |*| | | | |~brown~F~lightGray~| | | | |*|
10338
 |*|*|*|*|*|~brown~F~lightGray~|*|*|*|*|*|  ~brown~F ~lightGray~= Fence
10339-
	function lib.farmInFront(R)
10339+
10340
           ~lightGray~|*|        ~blue~S ~lightGray~= Bubble lift
10341-
		T:go("U1L1 F11D1 R1")						-- on next farm, facing crops
10341+
10342-
		local seed, crop = lib.manageTree(R)		-- refuel, gather seeds or other crops
10342+
10343
[[~yellow~Computercraft mob grinder
10344-
		R, isFarmToRight = lib.harvest(R, seed, crop)		-- harvest field, store crops
10344+
10345-
		return R, isFarmToRight
10345+
10346
          |*~blue~| | | | | | | | | |~lightGray~*|
10347
          |*|*|*|*|*~blue~| |~lightGray~*|*|*|*|*| Front
10348-
	function lib.farmToRight(R)
10348+
10349
                          
10350-
		T:go("U1F11 D1")								-- on next farm, facing crops
10350+
10351-
		local seed, crop = lib.manageTree(R)					-- refuel, gather seeds and other crops
10351+
10352-
		R, isFarmToRight = lib.harvest(R, seed, crop)		-- harvest field, store crops
10352+
10353-
		-- now at starting position of current plot
10353+
10354-
		return R, isFarmToRight
10354+
10355
]] -- Computercraft mob grinder
10356
	info.sub[66] = 
10357-
	function lib.getCropSeed(crop)
10357+
10358-
		-- change growing crops into equivalent seed names
10358+
10359-
		-- crop could be seeds, so return equivalent crop
10359+
10360-
		local start = crop:find("_crop")
10360+
10361-
		if start ~= nil then	-- only modded seeds have "crop"
10361+
10362-
			return crop:sub(1, start).."seeds", crop
10362+
10363
10364-
		if crop:find("seeds") ~= nil then	-- asked to return crop from seed type
10364+
10365-
			if crop:find("wheat") ~= nil then
10365+
10366-
				return "minecraft:wheat_seeds", "minecraft:wheat"
10366+
10367
]] -- Build endermen observation tower
10368-
			if crop:find("beetroot") ~= nil then
10368+
10369-
				return "minecraft:beetroot_seeds", "minecraft:beetroot"
10369+
10370
[[~yellow~Clear field
10371
10372-
		if crop:find("wheat") ~= nil then
10372+
10373-
			return "minecraft:wheat_seeds", "minecraft:wheat"
10373+
10374
~lightGray~| | | | | |  Remove blocks > ground
10375-
		if crop:find("beetroot") ~= nil then
10375+
10376-
			return "minecraft:beetroot_seeds", "minecraft:beetroot"
10376+
10377
|~red~^~lightGray~| | | | |  ~red~^ ~lightGray~= Turtle position
10378-
		if crop:find("carrot") ~= nil then
10378+
10379-
			return "", "minecraft:carrot"
10379+
10380
10381
]] -- Clear field
10382-
			return "", "minecraft:potato"
10382+
10383
[[~yellow~Clear rectangle
10384-
		-- planted crops are plural, harvested singular: carrots / carrot, pototoes/ potato
10384+
10385-
		return "", crop -- no seed for carrot / potato
10385+
10386
~lightGray~| | | | | |  Optional dig ~lime~up
10387
~lightGray~| | | | | |  Optional dig ~blue~down
10388-
	function lib.getHoe()
10388+
10389
| | | | | |
10390-
		if R.networkFarm then	-- get hoe from storage
10390+
10391-
			hoeSlot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1)
10391+
10392-
			if hoeSlot == 0 then
10392+
10393-
				if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then
10393+
10394-
					hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
10394+
10395
]] -- Clear rectangle
10396
10397-
		else	-- put crafting table into barrel in floor
10397+
10398-
			T:go("L1F1")		-- over barrel
10398+
10399-
			local isStorage, storageType = utils.isStorage("down")
10399+
10400-
			if not isStorage then
10400+
10401-
				message =
10401+
10402
~lightGray~                   |*|*|*|*|*|*|
10403
                   |*|*|*|*|*|*|
10404
                   |*|*|*|*|*|*|
10405
                   |*|*|*|*|*|*|
10406
                  ~lime~T~lightGray~|~green~T~lightGray~|*|*|*|*|*| Base
10407-
	instead.
10407+
10408
T = Turtle top / bottom/ inside / out
10409
~yellow~Bottom to top or top to bottom
10410
]] -- Clear wall
10411-
				return 0, message
10411+
10412
[[~yellow~Clear rectangle ~red~perimeter only
10413-
			-- must be storage below to get this far
10413+
10414-
			T:suck("down")		-- if hoe already in storage get it out
10414+
10415-
			hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
10415+
10416-
			if hoeSlot == 0 then
10416+
10417-
				if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then
10417+
10418-
					hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
10418+
10419
| |*|*|*| |
10420
|~red~^~lightGray~| | | | |  ~red~^ ~lightGray~= Turtle position
10421
~red~ ^
10422-
		return hoeSlot, ""
10422+
10423
10424
]] -- Clear rectangle (perimeter only) 
10425-
	function lib.getSaplings(R, direction)
10425+
10426
[[~yellow~Demolish cube structure
10427
Plan view        Side view
10428
               ~gray~T ~lightBlue~T
10429
~lightGray~|*|*|*|*|*|*|  ~cyan~T~lightGray~|~blue~T~lightGray~|*|*|*|*|*|
10430-
		if R.networkFarm then
10430+
10431-
			network.getItemFromNetwork("barrel", "sapling", 1)
10431+
10432-
			--lib.getItemFromNetworkBarrels(R, "sapling", 1)
10432+
10433
|*|*|*|*|*|*|   |*|*|*|*|*|*|
10434-
			while T:suck(direction, 1) do end -- remove saplings/ seeds
10434+
10435-
			T:dropItem("sapling", direction, 1) -- drop all but 1 saplings
10435+
10436-
			if not T:dropItem("seeds", direction, 0) then-- drop all seeds
10436+
10437-
				T:dropItem("seeds", "up", 0)
10437+
10438
	info.sub[76] = info.sub[75]
10439
	info.sub[77] = 
10440
[[~yellow~Dig a trench (Plan view)
10441-
		return T:getItemSlot("sapling")
10441+
10442
~lightGray~      |~red~>~lightGray~| | | | | | |
10443
  
10444-
	function lib.getSeeds(R, direction, seed)
10444+
10445-
		--[[ 
10445+
10446-
			seed = name of growing crops seed or ""
10446+
10447-
			turtle facing crops on networked, else facing storage
10447+
10448-
			allow for other seeds from mods eg MysticalAgriculture
10448+
10449-
			get 1 stack of seeds of whatever type is being farmed
10449+
10450
]] -- Dig a trench
10451-
		if seed == "" then
10451+
10452-
			return "", 0
10452+
10453
~yellow~Side view            Plan view
10454-
		local inventorySlot, seedCount = 0, 0
10454+
10455-
		T:saveToLog("Collecting seeds from storage")
10455+
10456-
		if R.networkFarm then
10456+
10457-
			inventorySlot, seedCount = network.getItemFromNetwork("chest", seed, 64)
10457+
10458
~gray~      |*~lightGray~|*|*|*|      ~gray~|*|*~lightGray~|*|*|*|*|  ~yellow~G
10459-
			while T:suck(direction, 1) do end -- remove saplings/ seeds
10459+
10460-
			T:dropItem("sapling", direction, 0) -- drop all saplings
10460+
10461-
			T:dropItem("seeds", direction, 64)	-- drop all but 64 of any seed type
10461+
10462-
			seedCount = T:getItemCount(seed)	
10462+
10463
]] -- Carve mountain
10464-
		if seedCount > 0 then
10464+
10465-
			T:saveToLog("planting " ..seed)
10465+
10466
10467-
		return seed, seedCount	-- could be: "", 0 or "minecraft:wheat_seeds", 64
10467+
10468
~lightGray~| | | | | |    |*|*|*|*|*|
10469
| | | | | |     T          Ceiling
10470-
	function lib.getVeg(R, direction, crop)
10470+
10471
| | | | | |
10472-
		-- local item, itemName, shortName, slot = "", "","", 0
10472+
10473-
		local inventorySlot, cropCount = 0, 0
10473+
10474
10475-
		if R.networkFarm then
10475+
10476-
			inventorySlot, cropCount = network.getItemFromNetwork("chest", crop, 64)
10476+
10477
]] -- (Re)place floor or ceiling
10478-
			if not R.mysticalAgriculture then
10478+
10479-
				print("Collecting root crops from storage")
10479+
10480-
				direction = direction or "forward"
10480+
10481-
				while T:suck(direction, 1) do end 			-- remove carrots / potatoes / wheat / beetroot / essence
10481+
10482-
				--item, itemName, shortName, slot = T:getFirstItem()
10482+
10483-
				local found = false
10483+
10484-
				if T:getItemSlot("potato") > 0 then
10484+
10485-
					T:dropItem("potato", direction, 64)		-- drop all but 65 potato
10485+
10486-
					found = true
10486+
10487-
					crop = "minecraft:potato"
10487+
10488
~lightGray~u = up       ~cyan~d = down
10489-
				if T:getItemSlot("carrot") > 0 then
10489+
10490-
					T:dropItem("carrot", direction, 64)		-- drop all but 64 carrots
10490+
10491-
					found = true
10491+
10492-
					crop = "minecraft:carrot"
10492+
10493
  ~yellow~Place me on water/lava surface
10494-
				if not found then
10494+
10495-
					T:dropAll(direction)					-- drop everything back
10495+
10496
  ~yellow~Place  on left corner of area
10497
 
10498-
			cropCount = T:getItemCount(crop)
10498+
10499
  ~yellow~Place me on the surface of sand.
10500
10501-
		if cropCount > 0 then
10501+
10502-
			print("planting " ..crop)
10502+
10503
]] -- Sand based utilities
10504-
		return crop, cropCount -- could be: "", 0 or "minecraft:potato", 64
10504+
10505
[[~yellow~Turtle position ~red~> T ~gray~(~red~V ~gray~to enclose)
10506
~yellow~Plan view                      ~gray~Start:~red~V
10507-
	function lib.goHome(R)
10507+
10508
                            ~gray~*  area
10509
~yellow~Side view
10510
 ~red~T
10511
~blue~| | | | | | | ~yellow~to ~lightGray~|*|*|*|*|*|*|
10512
~blue~| | | | | | |    ~lightGray~|*|*|*|*|*|*|
10513-
			lib.harvestTree(R, "forward") 		-- will only harvest if fuel below half of limit
10513+
10514-
			onTree = true					-- end on dirt
10514+
10515
~yellow~|S|S|S|S|S|S|    |S|S|S|S|S|S|
10516-
			lib.harvestTree(R, "up")			-- end on dirt
10516+
10517
	info.sub[83] = 
10518-
		elseif T:getItemSlot("log") > 0 then-- tree just harvested 
10518+
10519
10520
10521
~yellow~L ~lightGray~|*|*|*|*|*|*|
10522-
				lib.harvestTree(R, "up")		-- end on dirt
10522+
10523
~yellow~n ~lightGray~|*| | | | |*|
10524-
				while turtle.down() do end	-- end on dirt
10524+
10525
~yellow~t ~lightGray~|*|*|*|*|*|*|
10526
~yellow~h  ~red~^
10527
~yellow~   W i d t h      ~red~^ ~lightGray~= Turtle
10528-
		if onTree then 
10528+
10529-
			local success, storage = false, ""
10529+
10530-
			-- tree harvested, sitting on dirt, but direction unknown
10530+
10531-
			T:down(1) 				-- dig dirt, go down
10531+
10532-
			-- if storage type farm chest/barrel will give position
10532+
10533-
			for turns = 1, 4 do
10533+
10534
Plan view
10535-
				success, storage = utils.isStorage("forward")
10535+
10536
|*|*~blue~| | |~lightGray~*|*~blue~| |~lightGray~*|  ~blue~| ~lightGray~= Water
10537-
					T:go("L2U1")
10537+
10538-
					T:place("dirt", "down")
10538+
10539-
					T:go("B1R1 F1D1R1")
10539+
10540-
					R.ready = true
10540+
10541
|*|~red~^~lightGray~|*~blue~| | | | |~lightGray~*|  ~red~^ ~lightGray~= Turtle
10542
|*|*|*|*|*|*|*|*|  ~yellow~Width~blue~: ~yellow~6, ~orange~length~blue~:~orange~ 6
10543
10544-
			-- if networked will be in air 2 blocks above barrel or stone
10544+
10545
	info.sub[85] = info.sub[56] -- Sinking platform
10546-
			T:place("dirt", "up")
10546+
10547-
			T:down(1)	 --should be on corner
10547+
10548-
			for turns = 1, 4 do
10548+
10549
~red~******    ******  * ~lightGray~= Avoid this area
10550-
				success, storage = utils.isStorage("down")
10550+
10551-
				if storage == "modem" then
10551+
10552-
					T:go("R1F1D1")
10552+
10553-
					R.ready = true
10553+
10554
******~lime~++++~green~******  ~green~* ~lightGray~= Good position
10555
~green~****************
10556-
				T:go("B1R1")
10556+
10557
****************  blocks from edge
10558
]]-- Ocean monument 85 subChoice 1: 4 corner pillars
10559
10560
	info.sub[862] = 
10561
[[~yellow~Turtle positions ~red~> ^ < V
10562-
		return R	-- R.ready == false
10562+
10563
~lightGray~|*|~red~>~lightGray~|*|*|*|*|*|~red~<~lightGray~|*|  ~red~NOT ~lightGray~corner blocks!
10564
|~red~V~lightGray~|             |~red~V~lightGray~|
10565-
	function lib.goToLeft(R, plotCountR)
10565+
10566-
		T:go("U1R2 F"..plotCountR * 11 .."D1R2")	-- return home and continue with front
10566+
10567-
		if R.config ~= nil then
10567+
10568-
			local coord = R.config.currentPlot
10568+
10569-
			for i = 1, plotCountR do
10569+
10570-
				coord = lib.configUpdateCoords(R, coord, "left")
10570+
10571
|*|~red~>~lightGray~|*|*|*|*|*|~red~<~lightGray~|*|  ~yellow~Add when asked
10572-
			R.config.currentPlot = coord
10572+
10573
10574
	info.sub[863] = 
10575
[[~yellow~Turtle ~red~> < ~yellow~on side walls only
10576-
	function lib.goToFront(R, plotCountF)
10576+
10577-
		T:go("U1R1F"..plotCountF * 11 .."D1L1")
10577+
10578-
		if R.config ~= nil then
10578+
10579-
			local coord = R.config.currentPlot
10579+
10580-
			for i = 1, plotCountF do
10580+
10581-
				coord = lib.configUpdateCoords(R, coord, "back")
10581+
10582
~lightGray~|~red~>~cyan~| *****+++***** |~red~<~lightGray~|
10583-
			R.config.currentPlot = coord
10583+
10584
~lightGray~|~red~>~cyan~| ************* |~red~<~lightGray~|
10585
|*|*|*|*|*|*|*|*|*|*|
10586
]] -- clear plants before sand draining
10587-
	function lib.gotoTree(R)
10587+
10588
	info.sub[865] = info.sub[863]
10589-
		if not R.networkFarm then
10589+
10590-
			T:turnRight(1)							-- face storage
10590+
10591
[[~yellow~Turtle positions ~red~> ^ < V
10592-
		T:saveToLog("Extracting saplings from storage")
10592+
10593-
		lib.getSaplings(R, "forward") 				-- gets one sapling only (if present)
10593+
10594-
		T:saveToLog("Moving to tree position")
10594+
10595-
		if R.networkFarm then
10595+
10596-
			T:turnRight(1)							-- face wall next to corner barrel
10596+
10597
~orange~|*|- - - - ~lime~- - - -|*| ~lightGray~6 chests / area
10598-
		T:go("U1F1R1")								-- move on top of wall/storage. face tree direction
10598+
10599
~orange~|*|- - - - ~lime~- - - -|*|
10600-
		-- check if tree or dirt ahead
10600+
10601-
		if turtle.forward() then 					-- No tree or sapling ahead. assume tree is missing or 2 blocks above
10601+
10602-
			if T:getBlockType("down") == "minecraft:dirt" then
10602+
10603-
				turtle.back()						-- older design, return 
10603+
10604
[[~yellow~Ladder to water / lava: Plan view
10605
10606-
				if turtle.detectUp() then			-- dirt above = new tree layout
10606+
10607-
					if T:getBlockType("up") == "minecraft:dirt" then
10607+
10608-
						T:go("B1U2")				-- check tree in elevated position
10608+
10609
|*|*|*|~red~^~lightGray~|*|*|*|  |*|*|*|*|*|*|*|
10610-
						turtle.back()				-- not dirt above ? removed or lost
10610+
10611
|*|*|*|*|*|*|*|  |*|*|*|*|*|*|*|
10612
10613
~red~^ ~lightGray~= Turtle facing water / lava
10614
~brown~L ~lightGray~= Ladder
10615-
		lib.harvestTree(R, "forward") 				-- fell tree or plant sapling, ends facing tree / dirt / sapling. sticks already used for fuel. excess saplings placed
10615+
10616-
		T:go("R1F1D1R1")							-- return to base, facing crops 
10616+
10617-
		if R.networkFarm then
10617+
10618-
			network.sendItemToNetworkStorage(R, "barrel", "sapling", 64) --move saplings to any attached barrel
10618+
10619
Returns max ~blue~d~yellow~epth. ~yellow~Water ~green~p~yellow~lants~yellow~ removed
10620-
			T:turnRight(1)							-- facing plot storage 
10620+
10621-
			T:saveToLog("Dropping saplings into storage")
10621+
10622-
			T:dropItem("sapling", "forward", 0)	-- drop all saplings forward into chest/barrel
10622+
10623
|*|*| ~blue~| | | | | | | | | ~lightGray~|*|*|
10624
|*|*| ~blue~| | | | | | | ~lightGray~|*|*|*|*|
10625-
		-- ends in field facing crops
10625+
10626
|*|*|*| ~blue~| | |~green~p~lightGray~|*|*|*|*|*|*|*|
10627
|*|*|*|*~blue~|d~lightGray~|*|*|*|*|*|*|*|*|*|
10628-
	function lib.harvest(R, seed, crop)
10628+
10629
]] -- Clear water plants from enclosed area
10630
	info.sub[89] = 
10631-
		harvest crop if ripe
10631+
10632
of retaining wall facing water
10633
]] -- Convert all water to source
10634
	info.sub[810] = 
10635-
		crop is full name. if mixed seeds only one type returned
10635+
10636
of retaining wall facing water.
10637
The source blocks are placed ahead to
10638
selected length
10639
]] -- Create sloping water
10640
10641
-- Building and railway
10642
	info.sub[91] = 
10643
[[~yellow~Build a wall
10644
10645-
				lib.replant(R, seed, crop)	-- check and replant crop below
10645+
10646
10647
~red~>~lightGray~| | | | | | |   |*|*|*|*|*|*|
10648
                 |*|*|*|*|*|*|
10649-
					if utils.isStorage("down") then	-- chest, barrel or modem
10649+
10650
                 |*|*|*|*|*|*|
10651
                ~red~T~lightGray~|~red~T~lightGray~|*|*|*|*|*|
10652
10653
~red~> T~lightGray~ = Turtle
10654
				 
10655
]] -- Build a wall
10656
	info.sub[92] = 
10657-
				lib.replant(R, seed, crop)	-- check and replant crop below
10657+
10658
10659
Plan view         Side view
10660
10661
~yellow~L ~lightGray~|*|*|*|*|*|*|   |*|*|*|*|*|*|
10662
~yellow~e ~lightGray~|*| | | | |*|   |*|*|*|*|*|*|
10663-
				lib.replant(R, seed, crop)
10663+
10664
~yellow~g ~lightGray~|*| | | | |*|   |*|*|*|*|*|*|
10665
~yellow~t ~lightGray~|~red~^~lightGray~|*|*|*|*|*|  ~red~T~lightGray~|~red~T~lightGray~|*|*|*|*|*|
10666
~yellow~h  ~red~^
10667
~yellow~   W i d t h      ~red~^ T ~lightGray~= Turtle
10668-
		if utils.isStorage("down") then
10668+
10669
]] -- Build a rectangular structure
10670
	info.sub[93] = 
10671
[[~yellow~Build a gable roof
10672-
		lib.storeCrops(R) -- rotates from start to deposit seeds and crops, ends facing crops
10672+
10673-
		return R, isFarmToRight, isFarmToFront
10673+
10674
                     ~gray~+      gable top
10675
~yellow~L ~lightGray~|*|*|*|*|*|      ~gray~+ + +    gable end
10676-
	function lib.harvestTree(R, direction)
10676+
10677
~yellow~n ~lightGray~|*| | | |*|   |*|*|*|*|*| top of wall
10678
~yellow~g ~lightGray~|*| | | |*|   |*|*|*|*|*|
10679
~yellow~t ~lightGray~|*| | | |*|   |*|*|*|*|*|
10680
~yellow~h ~lightGray~|~red~^~lightGray~|*|*|*|*|   |*|*|*|*|*|
10681
~yellow~  W i d t h     W i d t h   ~red~^T ~lightGray~= Turtle
10682-
			Return to top of storage
10682+
10683
	info.sub[94] =
10684
[[~yellow~Build a pitched roof
10685
Width ~red~MUST ~yellow~be ~red~<= ~yellow~Length eg ~red~4~yellow~ x 6
10686-
		local inFront = T:getBlockType("forward")
10686+
10687-
		print("Checking tree")
10687+
10688-
		if inFront == "" then -- no tree or sapling
10688+
10689-
			print("No sapling: planting sapling")
10689+
10690-
			T:place("sapling", "forward")
10690+
10691-
		elseif inFront:find("log") ~= nil or direction == "up" then -- tree above or in front
10691+
10692-
			-- clsTurtle.harvestTree(self, extend, craftChest, direction)
10692+
10693-
			print("Harvesting tree")
10693+
10694-
			T:harvestTree(false, false, direction) --do not investigate side branches in case chunk unloaded
10694+
10695-
			T:back(1) -- face dirt
10695+
10696-
			-- place(self, blockType, direction, leaveExisting, signText)
10696+
10697-
			T:place("sapling", "forward")
10697+
10698
[[~yellow~Place me on suspended railway stone
10699-
		print("Disposing of apples")
10699+
10700-
		T:dropItem("apple", "up", 0) -- drop any apples
10700+
10701-
		utils.useSticksAsFuel()
10701+
10702
~lightGray~|*|*|\                           ~red~>~lightGray~|*|
10703-
		while turtle.down() do end	-- ends facing tree, on top of plot storage
10703+
10704
      ~lightGray~|*|______~red~T~lightGray~_________    /~lightGray~|*|~red~!
10705
       ~red~!~lightGray~|*|*|*|*|*|*|*|*|\ /|*|
10706-
	function lib.manageTree(R)
10706+
10707
10708-
		local isReady, crop, seed, status, R = lib.isCropReady(R, "forward")
10708+
10709-
		if crop == "" and not R.auto then			-- only ask player if not running via startup
10709+
10710-
			seed, crop = lib.askPlayerForCrops()	-- "" or  specific seed type,
10710+
10711
	info.sub[96] = info.sub[95]
10712
	info.sub[97] = 
10713
[[~yellow~Place me on last block before up/down
10714
10715
Build down            Build up~lightGray~
10716
10717
_____~red~T~lightGray~                        ___
10718
|*|*|*|_                     _|*|
10719
      |*|_                 _|*|
10720
        |*|_             _|*|
10721
          |*|__________~red~T~lightGray~|*|
10722
            |*|*|*|*|*|*|		
10723
~red~T~lightGray~ = Turtle on block, not above rail	
10724
]] -- build down
10725-
			T:saveToLog("Running Tree Manager")
10725+
10726-
			lib.gotoTree(R) 					-- check for sapling or harvest tree, retuns to facing crops
10726+
10727
--Measurement tools
10728
	info.sub[101] = 
10729
[[~yellow~Place me on floor.~lightGray~
10730-
		if logSlot > 0 then						--logs onboard, need to equip crafting table
10730+
10731-
			if R.networkFarm then
10731+
10732-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
10732+
10733
  |*|*|*|
10734-
				T:go("L1F1") 					-- move to buried storage chest/barrel
10734+
10735-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
10735+
10736-
				T:go("R2F1")					-- facing seed chest/barrel
10736+
10737
  |*|*|*|
10738
  |*|*|*|
10739-
			if not R.networkFarm then
10739+
10740
]] -- measure height
10741
	info.sub[102] = 
10742
[[~yellow~Depth measurement
10743-
		-- get seeds or veg based on what is growing
10743+
10744-
		if seed ~= "" then
10744+
10745-
			local seedType, seedCount = lib.getSeeds(R, "forward", seed) 	-- table: get 95 of beetroot / wheat / mysticalagriculture seeds
10745+
10746-
			if seedCount == 0 then
10746+
10747-
				T:saveToLog("No seeds available.")
10747+
10748
3|*|*|
10749-
		else	-- seed  = ""
10749+
10750-
			local veg, vegCount = "", 0
10750+
10751-
			if R.networkFarm then
10751+
10752-
				veg, vegCount = lib.getVeg(R, "forward", crop)	-- gets any carrots / potatoes
10752+
10753
]] -- measure depth
10754-
				T:turnRight(1)					-- face crop chests
10754+
10755-
				veg, vegCount = lib.getVeg(R, "forward", crop)	-- gets any carrots / potatoes
10755+
10756-
				T:turnRight(2)					-- face crops
10756+
10757
~lightGray~1 2 3 4 ~lime~5~lightGray~ 6 ~lime~7 ~cyan~8 ~lightBlue~9~lightGray~ 10
10758-
			if veg ~= "" then
10758+
10759-
				crop = veg
10759+
10760
~red~T~lightGray~                |*|  ~lightBlue~9. Obstruction
10761
~lightGray~*|*|*|*|~lime~S~lightGray~|*|*| |*|*|  ~lime~5. Search block
10762
                      ~cyan~8. No block down
10763-
		return seed, crop	-- name of seed / "",  crop / ""
10763+
10764
~red~T ~lightGray~= Turtle
10765
10766-
	function lib.isCropReady(R, direction)
10766+
10767
	info.sub[104] = info.sub[88] -- measure deepest section of water
10768
	info.sub[105] =
10769
[[~yellow~Place turtle anywhere:
10770-
		local crop, seed = "", ""
10770+
10771
 1. make a ~blue~borehole~yellow~ to chosen level.
10772
10773
 2. Write a report called:
10774
10775
 3. ~lime~borehole~blue~X~lime~.txt ~yellow~( ~blue~X ~yellow~= computer ID )
10776
10777
 4. ~orange~Return home
10778
10779
]] -- Borehole: Analyse blocks below
10780-
		--T:saveToLog("lib.isCropReady(R,".. direction..")")
10780+
10781-
		if success then			-- inspect() success
10781+
10782-
			crop = data.name	-- name of growing plant
10782+
10783-
			if crop:find("flower") ~= nil then
10783+
10784-
				T:saveToLog("Flower "..crop.." found")
10784+
10785-
				return true, crop, "open"	-- eg torchflower
10785+
10786
10787-
				if data.name:find("beetroot") ~= nil then
10787+
10788-
					status = data.state.age.." / 3"
10788+
10789-
					if data.state.age == 3 then
10789+
10790-
						isReady = true
10790+
10791
~yellow~Enter 1 to use ~lime~2 ~yellow~turtles or 2 to use ~orange~4]]	-- initial menu for water canal
10792-
				else			-- all other crops inc Mystical Agriculture
10792+
10793-
					status = data.state.age.." / 7"
10793+
10794-
					if data.state.age == 7 then
10794+
10795-
						isReady = true
10795+
10796
		read()
10797
		return ""
10798
	else -- item specific help
10799-
			seed, crop = lib.getCropSeed(crop)
10799+
10800
			line = menu.colourText(line, info.sub[menuItem], true, true)
10801-
		--T:saveToLog("return isReady = "..tostring(isReady)..", crop = "..crop..", seed = "..seed..", status = "..status)
10801+
10802-
		-- crop: "", "minecraft:carrots", "minecraft:beetroot", "minecraft:potatoes", "minecraft:wheat", "mysticalagriculture:*_crop"
10802+
10803-
		return isReady, crop, seed, status, R	-- eg true, "minecraft:carrots", "7 / 7" or false, "mysticalagriculture:inferium_crop", "1 / 7"
10803+
10804
				if getInteger then
10805
					return line -- ready for further input
10806-
	function lib.locateFarm(R)
10806+
10807-
		T:saveToLog("? over water = false")
10807+
10808
					menu.enterToContinue()
10809
				end
10810-
				detected = i
10810+
10811
				term.setCursorPos(1, 13)
10812
				term.write("Enter=exit, Any key + Enter=more ")
10813
				return read()
10814-
		T:saveToLog("Neighbouring blocks detected at: "..detected)
10814+
10815-
		-- check if on corner
10815+
10816-
		if detected > 0 then
10816+
10817-
			--assume tree / sapling on corner on older farm type
10817+
10818-
			T:saveToLog("Assuming next to tree / sapling. Moving..")
10818+
10819-
			T:go("R"..detected .."F1D1R1")
10819+
10820-
		else	-- no surrounding blocks
10820+
10821
	options.main =
10822
	{
10823-
				success, storage = utils.isStorage("down")
10823+
10824-
				T:saveToLog("i = "..i..",success = "..tostring(success)..". storage = "..storage)
10824+
10825
		"Farming",
10826-
					discovered = discovered .. storage
10826+
10827-
					if storage == "modem" then
10827+
10828-
						R.networkFarm = true
10828+
10829
		"Area shaping and clearing",
10830
		"Lava and Water",
10831-
					if storage == "" then
10831+
10832-
						discovered = discovered .. "_"
10832+
		"Measuring tools"
10833
	}
10834-
						discovered = discovered .. "wall"
10834+
10835
	{
10836
		"Ladder up or down",
10837
		"Stairs up or down",
10838
		"Create mine at this level",
10839
		"Safe drop to water block",
10840-
			T:saveToLog("Neighbouring blocks found:"..discovered)
10840+
10841
		"QuickMine corridor system",
10842-
		-- check discovered for patterns eg {_wall_barrel}
10842+
10843-
		-- |W|*|B| * = turtle on wall
10843+
10844-
		-- | | |M|
10844+
10845-
		if R.networkFarm then
10845+
10846-
			-- E = wall_barrel_, N = _barrel_wall, W = wall_barrel_, S = _wall_barrel 
10846+
10847-
			if discovered == "_wall_barrel" then
10847+
10848-
				T:go("F1D1R1")
10848+
10849-
			elseif discovered == "barrel_wall_" then
10849+
		"Create tree farm",
10850
		"Plant tree farm",
10851-
			elseif discovered == "_barrel_wall" then
10851+
10852-
				T:go("R2F1D1R1")
10852+
10853-
			elseif discovered == "wall_barrel_" then
10853+
10854-
				T:go("L1F1D1R1")
10854+
10855
	table.insert(options,
10856-
		else	-- normal storage farm
10856+
10857-
			if discovered == "_chest_chest" then
10857+
10858-
				T:go("F1D1R1")
10858+
10859-
			elseif discovered == "chest__chest" then
10859+
		"Plant, harvest or manage crop farm",
10860
		"Build a wall or fence",
10861-
			elseif discovered == "_chest_chest" then
10861+
10862-
				T:go("R2F1D1R1")
10862+
10863-
			elseif discovered == "chest_chest_" then
10863+
10864-
				T:go("L1F1D1R1")
10864+
10865
		"Dig obsidian field",
10866
		"Build Nether Portal",
10867
		"Demolish Nether Portal",
10868
		"Stripmine Netherite",
10869
		"Undermine Dragon Towers",
10870-
				success, storage = utils.isStorage("forward")	-- true/false, chest, barrel, modem / ""
10870+
10871-
				if success and storage == "modem" then
10871+
10872-
					R.networkFarm = true
10872+
10873
		"Shulker harvester"
10874
	})
10875
	table.insert(options,
10876-
			R.ready = true
10876+
10877
		"Simple path on air, water or lava",
10878
		"Covered path or tunnel",
10879
		"Water canal (mulitple options)",
10880-
	function lib.plantCrop(R, seed, crop, direction)
10880+
10881
		"Platform",
10882
		"Sinking platform",
10883
		"Boat bubble lift",
10884
	})
10885
	table.insert(options,
10886-
		--T:saveToLog("lib.plantCrop(R, seed = "..seed..", crop = "..crop)
10886+
10887
		"Cube around spawner (NOT blaze)",
10888-
		-- place(blockType, direction, leaveExisting, signText, doNotAttack)
10888+
10889-
		if seed == "" then	-- must be a crop
10889+
10890-
			success = T:place(crop, direction, true, "", true)
10890+
10891-
			--success = T:place(crop, direction, false, "", true)
10891+
10892-
			--T:saveToLog("Seed = "..seed..". Placing "..crop..": success = "..tostring(success))
10892+
		"Build Endermen observation tower"
10893
	})
10894-
			success = T:place(seed, direction, true, "", true) 	-- eg "mysticalagriculture:air_seeds"
10894+
10895-
			--success = T:place(seed, direction, false, "", true) 	-- eg "mysticalagriculture:air_seeds"
10895+
10896-
			--T:saveToLog("Placing "..seed..": success = "..tostring(success))
10896+
10897
		"Clear a rectangle (+ u/d opt)",
10898-
		if not success then
10898+
10899-
			success = T:place("seed", direction, true, "", true)			-- failsafe
10899+
10900-
			--success = T:place("seed", direction, false, "", true)			-- failsafe
10900+
10901-
			--T:saveToLog("Placing generic 'seeds' : success = "..tostring(success))
10901+
10902
		"Dig a trench",
10903-
		return success
10903+
10904
		"Place a floor or ceiling",
10905
		"Direct control of movement"
10906-
	function lib.replant(R, seed, crop)
10906+
10907-
		-- check crop below. If ripe, dig and replant seed
10907+
10908-
		local isReady, cropType, seedType, status
10908+
10909-
		isReady, cropType, seedType, status, R = lib.isCropReady(R, "down")	-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
10909+
10910-
		if cropType == "" then					-- no crop below (above water, storage or dirt)
10910+
10911-
			turtle.digDown("right")				-- use hoe
10911+
10912-
			lib.plantCrop(R, seed, crop, "down")-- plant crop
10912+
10913-
		elseif isReady then						-- crop below is ready
10913+
10914-
			turtle.digDown("left")				-- use pickaxe
10914+
10915-
			lib.plantCrop(R, seedType, cropType, "down")	-- plant crop
10915+
10916
		"Clear water plants",
10917
		"Convert all water to source",
10918-
		return R
10918+
10919
	})
10920
	table.insert(options,
10921-
	function lib.refuelWithLogs(R, logSlot)
10921+
10922-
		-- saplings already dropped, apples dumped, sticks used as fuel
10922+
10923-
		-- assume positioned in front of crops if networked, or over buried storage
10923+
10924
		"Build a gable end roof",
10925
		"Build a pitched roof",
10926-
		-- networked version uses remote storage, turtle faces crops and has modem at back
10926+
10927-
		local slot, count = 0, 0
10927+
10928-
		T:saveToLog("Sorting Inventory")	-- make sure all items collected together
10928+
10929-
		T:sortInventory(true)
10929+
10930-
		T:saveToLog("Logs present: collecting crafting table")
10930+
10931-
		if R.networkFarm then
10931+
10932-
			slot, count = network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
10932+
10933-
			--slot = lib.getItemFromNetworkBarrels(R, "minecraft:crafting_table", 1)
10933+
10934
		"Measure depth",
10935-
			while T:suck("down") do end					-- empty out barrel/chest to find crafting table
10935+
10936
		"Measure greatest depth",
10937
		"Borehole: Analyse blocks below"
10938
	})
10939
	
10940
	return options
10941-
			if R.networkFarm then
10941+
10942-
				network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1)
10942+
10943
local function getTaskColours()
10944
	local options = {}
10945
	options.main =
10946-
					T:drop("down", i)	-- into water if networked, buried chest otherwise
10946+
10947
		colors.lightGray, 	-- Mining (includes Nether)
10948
		colors.lime, 		-- Forestry
10949
		colors.green, 		-- Farming
10950
		colors.red, 		-- Obsidian, Nether & End Portal
10951
		colors.brown, 		-- Canal, bridge and walkway
10952
		colors.lightGray, 	-- Mob farm tools
10953
		colors.orange,		-- Area shaping and clearing
10954
		colors.blue, 		-- Lava and Water
10955-
			while logSlot > 0 and turtle.getFuelLevel() < turtle.getFuelLimit() do
10955+
10956
		colors.purple 		-- Measuring tools
10957-
				turtle.refuel()						-- refuel using planks
10957+
10958
	table.insert(options,
10959
	{
10960-
			while T:suck("down") do end			-- recover items from water / storage below
10960+
10961-
			--T:unequip("right")
10961+
10962-
			if R.networkFarm then
10962+
10963-
				slot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1)
10963+
10964
		colors.blue, 		-- Single column bubble lift
10965-
			if not T:equip("right", "minecraft:diamond_hoe") then		-- re-equip hoe/remove crafting table
10965+
10966
		colors.pink, 		-- QuickMine rectangle
10967
		colors.gray, 		-- Mine bedrock level
10968-
			if R.networkFarm then
10968+
10969-
				network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1)
10969+
10970
	table.insert(options,
10971-
				T:dropItem("minecraft:crafting_table", "down")
10971+
10972
		colors.brown, 		-- Fell Tree
10973
		colors.lightGray, 	-- Create tree farm
10974
		colors.lime, 		-- Plant tree farm
10975
		colors.green, 		-- Harvest tree farm
10976
		colors.brown, 		-- Fence or wall an enclosure
10977
		colors.lime 		-- Harvest and replant forest
10978
	})
10979-
	function lib.storeCrops(R)
10979+
10980-
		-- place crops and seeds into chests. starts facing crops
10980+
10981
		colors.yellow, 		-- Create modular crop farm
10982
		colors.green, 		-- Extend modular crop farm
10983-
		if R.networkFarm then
10983+
10984-
			network.emptyInventory(R, {"sapling", "diamond_hoe", "crafting"}, {"all"}, true)
10984+
10985
		colors.brown 		-- Build rectangle wall or fence
10986-
			T:turnRight(1)	-- face seed storage
10986+
10987-
			lib.storeSeeds(R, "forward")
10987+
10988
	{
10989-
			if utils.isStorage(direction) then
10989+
10990-
				T:dropAll(direction) -- drops everything including essences
10990+
10991
		colors.gray, 		-- Demolish Nether Portal
10992-
			T:turnRight(2) -- facing crops again
10992+
10993
		colors.orange, 		-- Undermine Dragon Towers
10994
		colors.orange, 		-- Deactivate Dragon Tower
10995
		colors.blue, 		-- Build dragon water trap
10996-
	function lib.storeSeeds(R, direction)
10996+
10997
		colors.red			-- Shulker harvesting
10998-
		if utils.isStorage(direction) then -- chest exists
10998+
10999-
			if not R.networkFarm then
10999+
11000-
				if T:getItemSlot("minecraft:wheat_seeds") > 0 then
11000+
11001-
					if not T:dropItem("minecraft:wheat_seeds", direction, 0) then
11001+
11002-
						T:dropItem("minecraft:wheat_seeds", "up", 0)
11002+
11003-
					end -- drop all wheat seeds
11003+
11004-
				elseif T:getItemSlot("minecraft:beetroot_seeds") > 0 then
11004+
11005-
					if not T:dropItem("minecraft:beetroot_seeds", direction, 0) then-- drop all beetroot seeds
11005+
11006-
						T:dropItem("minecraft:beetroot_seeds", "up", 0)
11006+
11007
		colors.cyan 		-- Boat bubble lift
11008-
				elseif T:getItemSlot("seeds") > 0 then
11008+
11009-
					if not T:dropItem("seeds", direction, 0) then	-- drop all other seeds as chest is full
11009+
11010-
						T:dropItem("seeds", "up", 0)
11010+
11011-
						-- or could print a message and wait for player to empty storage
11011+
11012
		colors.red, 		-- Cube around Blaze spawner
11013
		colors.cyan, 		-- Flood mob farm floor
11014
		colors.blue, 		-- Create mob bubble lift
11015
		colors.brown, 		-- Dig mob drop trench
11016
		colors.gray 		-- Build Endermen observation tower
11017
	})
11018-
	function lib.watchFarm(R)
11018+
11019
	{
11020
		colors.lime, 		-- Clear field (inc trees)
11021
		colors.magenta, 	-- Clear a rectangle (+ u/d opt)
11022
		colors.pink, 		-- Clear single wall up/down
11023
		colors.purple, 		-- Clear rectangular wall section
11024-
		local isReady, crop, seed, status	-- bool, string, string, integer
11024+
11025-
		isReady, crop, seed, status, R = lib.isCropReady(R, "forward")		-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
11025+
11026
		colors.brown, 		-- Dig a trench
11027
		colors.gray, 		-- Carve mountain side
11028
		colors.lightBlue, 	-- Place a floor or ceiling
11029
		colors.red 			-- Direct control of movement
11030
	})
11031
	table.insert(options,
11032
	{
11033
		colors.yellow, 		-- Sand based utilities
11034
		colors.blue, 		-- Vertical wall from surface
11035-
					if crop:find("mysticalagriculture") ~= nil then
11035+
11036-
						R.mysticalAgriculture = true
11036+
11037
		colors.lightGray,	-- Sinking platform
11038
		colors.orange, 		-- Ocean monument utilities
11039
		colors.brown, 		-- Ladder down to water/lava
11040-
				isReady, crop, seed, status, R = lib.isCropReady(R, "forward")			-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
11040+
11041
		colors.lightBlue, 	-- Convert all water to source
11042-
		until isReady
11042+
11043-
		T:saveToLog("Local crops ripe", true)
11043+
11044-
		seed, crop = lib.manageTree(R) -- "", "" or name of seed, crop
11044+
11045-
		return seed, crop
11045+
11046
		colors.yellow,		-- build a wall
11047
		colors.orange,		-- build rectangular structure
11048
		colors.lightGray,	-- gable end roof
11049-
		ENTRY POINT**********************************************
11049+
11050
		colors.red, 		-- Place Redstone:torch level track
11051
		colors.red, 		-- Place Redstone:torch upward track
11052
		colors.orange, 		-- Build downward track
11053
		colors.brown 		-- Build upward track
11054
	})
11055
	table.insert(options,
11056
	{
11057-
	--T:setUseLog(true, "farmLog.txt", true)	-- T:setUseLog(use, filename, delete)
11057+
11058-
	--dbug = true								-- set dbug flag
11058+
11059-
	--if not R.auto then						-- not running from startup.lua
11059+
11060-
		--utils.waitForInput("Logging and debugging enabled")	--utils.waitForInput(message)
11060+
11061-
	--end
11061+
11062
	})
11063-
	R = utils.checkFarmPosition(R)	-- should be facing crops, placed above water source. R.ready, R.networkFarm is true/false
11063+
11064-
	if R.networkFarm then
11064+
11065-
		local message = network.loadStorageLists()	-- initialises or creates lists of where an item can be found: GLOBAL LISTS!
11065+
11066-
		if message ~= nil then return {message} end
11066+
11067
local function chooseTask(R)
11068-
	if not R.ready then		-- not in correct starting place
11068+
11069-
		R = lib.goHome(R)
11069+
11070-
		if not R.ready then -- try to find home
11070+
11071
	coloured menu:	
11072
	local pp = 
11073
	{
11074
		prompt = colors.green,
11075
		itemColours = {colors.white, colors.red, ... one for each item},
11076-
				"barrel or chest to my right and behind",
11076+
11077-
				"(or modem behind if networked farm)"
11077+
11078
	choice, modifier = menu.menu or menu.new("Choose your option", options, pp)
11079
	]]
11080
	local lib = {}
11081-
	if not T:isEmpty() then		-- items in turtle inventory
11081+
11082-
		local logSlot = T:getItemSlot("log")
11082+
11083
		local listOfItems = itemsRequired[choice]
11084-
			if R.networkFarm then
11084+
11085-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
11085+
11086
			lib.showItems(listOfItems)
11087-
				T:go("L1F1") 					-- move to buried storage chest/barrel
11087+
11088-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
11088+
11089-
				T:go("R2F1")					-- facing seed chest/barrel
11089+
11090
		local options ={"Continue with selected task", "return to menu", "Return to main menu","Quit application"}
11091
		local option = menu.menu("Choose your option", options, pp, "Type number + Enter ")
11092-
		if not T:isEmpty() then					-- still items in turtle inventory
11092+
11093-
			lib.storeCrops(R)
11093+
11094
		elseif option == 3 then
11095
			choice = 0 -- return to main menu
11096-
	-- in correct position. Check equipment first, harvest tree, re-equip then harvest crops
11096+
11097-
	local hoeSlot = lib.checkEquipment(R, "minecraft:diamond_hoe")	-- returns slot  or 0
11097+
11098
		-- else return original value of choice
11099-
	if hoeSlot == 0 then		-- hoe not in inventory
11099+
11100-
		local message
11100+
11101-
		hoeSlot, message = lib.getHoe()
11101+
11102-
		if message ~= "" then
11102+
11103-
			return {message}
11103+
11104
	function lib.showItems(listOfItems)
11105
		T:clear()
11106-
	-- hoe present or user cancelled request for hoe. Turtle is ready to exchange items
11106+
11107-
	if hoeSlot > 0 then
11107+
11108-
		T:equip("right", "minecraft:diamond_hoe", 0) -- equip hoe and put crafting chest into barrel
11108+
11109-
		if R.networkFarm then	-- drop crafting table into storage
11109+
11110-
			network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1)
11110+
11111-
		else	-- put crafting table into barrel in floor
11111+
11112-
			T:dropItem("crafting", "down")
11112+
11113-
			T:go("B1R1")
11113+
11114
		menu.colourWrite("Enter to continue", colors.yellow, colors.black, nil, true)
11115-
	else	-- hoe not present: return to start and exit
11115+
11116-
		if not R.networkFarm then
11116+
11117-
			T:go("B1R1")
11117+
11118
	function lib.getItemList(subChoice, itemsRequired)
11119
		local listOfItems = itemsRequired[subChoice]
11120
		lib.showItems(listOfItems)
11121
	end
11122
	
11123-
	local isFarmToRight, isFarmToFront = false, false
11123+
11124-
	local isReady, crop, seed, status
11124+
11125-
	isReady, crop, seed, status, R = lib.isCropReady(R, "forward")
11125+
11126
		else -- eg main option 1 (mining), sub-option 1 (create mine) = 1 + 10 = 11
11127-
	local init = false
11127+
11128
		end
11129-
		seed, crop = lib.askPlayerForCrops()
11129+
11130-
		if crop ~= "" or seed  ~= "" then	-- something has been chosen
11130+
11131-
			T:saveToLog("Initial planting of "..crop, true)
11131+
11132-
			R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop)	-- harvest plot a1 plots to right / front recorded	
11132+
11133-
			init = true
11133+
11134
	local prompt = "Choose an option"
11135-
			watch = false	-- not watching, continue with planting
11135+
11136
	local subPrompt = "Choose (+h = help +i = items eg 3h):"
11137
	local options = getTaskOptions()
11138
	local menuColours = getTaskColours()
11139-
		if watch and not init then -- init true when farm first planted
11139+
11140-
			seed, crop = lib.watchFarm(R) -- waits if required, returns seed / crop
11140+
11141-
			init = false
11141+
11142
	--local pp = utils.getPrettyPrint()-- uses default colours
11143-
		T:saveToLog("Beginning "..crop.. " management", true)
11143+
11144-
		R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop)	-- harvest plot a1 plots to right / front recorded
11144+
11145-
		lib.farmAll(R, isFarmToRight, isFarmToFront)
11145+
11146
		menu returns choice=nil if user enters just q or h
11147-
			if R.networkFarm then
11147+
11148-
				T:unequip("right")	-- unequip hoe
11148+
11149-
				network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
11149+
11150-
				network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1)
11150+
11151-
				T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table
11151+
11152
		Canal, bridge and walkway		pink	
11153-
				T:go("L1F1")
11153+
11154-
				while T:suck("down") do end						-- recover items from storagebelow
11154+
11155-
				T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table 
11155+
11156-
				T:dropItem("minecraft:diamond_hoe", "down") 				-- drop hoe into storage
11156+
11157-
				T:dropItem("crafting", "down") 					-- in case spare one picked by mistake
11157+
11158
		]]
11159
		
11160
		if menuState == 0 then
11161
			pp.itemColours = menuColours.main
11162
			local mainChoice, modifier = menu.menu(mainPrompt, options.main, pp) -- open main menu options
11163
			if modifier == "q" then
11164
				R.choice = -1
11165
				return R -- quit application
11166
			elseif modifier == "h" then -- get help on main menu items
11167
				getTaskHelp(1, mainChoice) -- "" or any return string for more
11168
				R.choice = 0
11169
				return R -- quit task system so it re-starts as help menu chosen R.choice = 0
11170
			else
11171
				menuState = 1 -- next level so use sub-menu
11172
				R.choice = mainChoice -- 1-10
11173
			end
11174
		else
11175
			pp.prompt = colors.yellow
11176
			pp.itemColours = menuColours[R.choice]
11177
			subChoice, modifier = menu.menu(subPrompt, options[R.choice], pp, "Back = 'q' or number + Enter: ") -- open submenu options
11178
			if modifier == "q" then
11179
				R.choice = 0	-- return to root menu. change this to -1 if quit application preferred
11180
				return R -- quit task system so it re-starts first menu
11181
			elseif modifier == "i" then -- get list of items
11182
				local index = lib.getChoice(R.choice, subChoice)
11183
				lib.getItemList(index, itemsRequired) -- list of items shown
11184
				subChoice = nil -- allow menu to continue
11185
			elseif modifier == "h" then -- get help on main menu items
11186
				local index = lib.getChoice(R.choice, subChoice)
11187
				index = lib.getHelp(index, itemsRequired, pp)
11188
				--R = lib.getHelp(R, itemsRequired, pp) -- if R.choice reset to 0 then will continue
11189
				if index == -2 then -- redraw sub-menu
11190
					subChoice = nil -- allow menu to continue
11191
				elseif index == -1 then -- if R.choice reset to 0 then will continue
11192
					R.choice = -1
11193
					return R
11194
				elseif index == 0 then 
11195
					R.choice = 0
11196
					menuState = 0 -- if R.choice reset to 0 then back to main menu
11197
				end
11198
			end
11199
			if subChoice ~= nil then
11200
				R.choice = lib.getChoice(R.choice, subChoice)
11201
				return R -- exit loop
11202-
	--local pp = utils.getPrettyPrint()	
11202+
11203-
	local choices = {"Plant or harvest this farm complex"}	-- 1.
11203+
11204
	end
11205
	return R
11206
end
11207-
		table.insert(choices, "Disable automatic farm management") -- 2.
11207+
11208
local function getTask(R)
11209-
		table.insert(choices, "Enable automatic farm management") -- 2.
11209+
	-- Called from main(): R = getTask(R)
11210
	local lib = {}
11211
	
11212-
	if not R.networkFarm then
11212+
11213-
		table.insert(choices, "Convert to Network Storage")		-- 3.
11213+
11214-
		table.insert(pp.itemColours, colors.magenta)
11214+
11215
				return true
11216-
	if R.mysticalAgriculture then
11216+
11217-
		--table.insert(choices, "Convert to Mystical Agriculture")
11217+
11218-
		table.insert(choices, "Upgrade Mystical Agriculture soil")	--3/4
11218+
11219-
		table.insert(pp.itemColours, colors.green)
11219+
11220
	
11221
	local prompt = "Choose an option"
11222
	local noAutoHelp = {24, 47, 49, 53, 54, 81, 85}
11223
	if not lib.isAutoHelp(R.choice, noAutoHelp) then -- exclude Water canal, ice canal, sand utilities, monument utilities, dragon trap
11224
		getTaskHelp(2, R.choice, true)
11225
		menu.clear()
11226
	end
11227
-- 01. MINING
11228
	if R.choice >= 11 and  R.choice <= 13 then	-- createLadder, createStaircase, createMine)
11229
		--getTaskHelp(2, R.choice, true)
11230
		--menu.clear()
11231
	elseif R.choice == 14 then	-- safe drop to water
11232-
	elseif R.subChoice == 2 then -- enable/disable auto farm
11232+
11233
		local destLevel = menu.getInteger("Go down to level? ("..currentLevel - 2 .." to "..bedrock + 5 ..")", bedrock + 5 , currentLevel - 2, nil, colors.blue, nil, bedrock + 5)
11234
		R.height 	= math.abs(destLevel - currentLevel)
11235
	elseif R.choice == 15 then	-- bubble lift
11236
		local currentLevel = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5 , ceiling, nil, colors.blue, nil, bedrock + 5)
11237
		local destLevel = menu.getInteger("Go up to level? ("..currentLevel + 2 .." to "..ceiling ..") ", currentLevel + 2, ceiling, nil, colors.lightGray)
11238
		--[[if currentLevel <= bedrock + 5 then
11239
			if menu.getBoolean("Confirm close to bedrock (y / n) ", nil, colors.yellow, colors.black) then
11240
				R.data = "bedrock"
11241
			end
11242
		end]]
11243
		R.height 	= math.abs(destLevel - currentLevel)
11244
	elseif R.choice == 16 then -- create mining corridor system default: square 17 x 17 
11245
		local choices = {"At corridor start, on the floor",
11246
						 "At corridor start, on the ceiling",
11247
						 "On floor, move forward to start",
11248
						 "On ceiling, move forward to start"}
11249
		pp.itemColours = {colors.lime, colors.green, colors.magenta, colors.pink}
11250
		local userChoice, modifier = menu.menu("Starting position?", choices, pp, "Type number + Enter ") -- 1 to 4
11251
		if modifier == "q" then -- quit chosen
11252
			R.data = "quit"
11253
			return R
11254
		end
11255
		R.width 	= menu.getInteger("Width (2-64 default 17) ", 2, 64, nil, colors.yellow, nil, 17)
11256
		R.length  	= menu.getInteger("Length (2-64 default 17) ", 2, 64, nil, colors.orange, nil, 17)
11257-
	--elseif R.subChoice == 3 and #choices == 4 then -- convert normal farm to network storage
11257+
11258-
	elseif R.subChoice == 3 then -- convert normal farm to network storage
11258+
11259-
		local isMain = false
11259+
11260
		end
11261-
		local message = ("~yellow~You have chosen to convert this farm "..
11261+
11262-
						 "to ~magenta~network storage ~yellow~with modems."..
11262+
11263-
						 "All ~brown~chests and barrels ~red~will be removed.\n")
11263+
11264-
		line = menu.colourText(line, message, true, true)
11264+
11265-
		if menu.getBoolean("Is this the main or only plot? (y/n)", line + 3, colors.orange, colors.black) then
11265+
11266-
			isMain = true
11266+
11267
						 "On floor diagonally to left"} -- just finished corridor
11268-
		T:checkInventoryForItem({"stone"}, {16})
11268+
11269-
		T:checkInventoryForItem({"dirt"}, {2})
11269+
11270
		if modifier == "q" then -- quit chosen
11271-
		T:checkInventoryForItem({"barrel"}, {1})
11271+
11272-
		T:checkInventoryForItem({"ladder"}, {5})
11272+
11273-
		if isMain then
11273+
11274-
			T:checkInventoryForItem({"chest"}, {8})
11274+
11275-
			T:checkInventoryForItem({"wired_modem_full"}, {3})
11275+
11276-
			T:checkInventoryForItem({"computercraft:cable"}, {70})
11276+
11277-
			return createFarm(R, "convertWithStorage")
11277+
11278
		--getTaskHelp(2, R.choice, true)
11279-
			T:checkInventoryForItem({"wired_modem_full"}, {2})
11279+
11280-
			T:checkInventoryForItem({"computercraft:cable"}, {57})
11280+
11281-
			return createFarm(R, "convert")
11281+
11282
		if menu.getBoolean("Leave bedrock exposed? (y/n) ", nil, colors.yellow) then
11283-
	--elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present)
11283+
11284-
	--elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present)
11284+
11285-
		--return upgradeFarmland(R)
11285+
11286-
	elseif R.subChoice == 4 then -- upgrade farmland with essence
11286+
11287-
		return upgradeFarmland(R)
11287+
11288
	elseif R.choice == 22 then --Create treefarm
11289
		R.width = 15
11290
		R.length = 15
11291
		pp.itemColours = {colors.lightGray, colors.green}
11292
		choices = {"New tree farm. Start here", "On right side of existing farm" }
11293
		local choice = menu.menu(prompt, choices, pp, "Type number + Enter ")
11294
		if choice == 2 then
11295
			R.data = "existing"
11296
		end
11297
		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)
11298
	elseif R.choice == 23 then -- plant treefarm
11299
		local choices 	= {"16 single trees", "4 double trees any type"}
11300
		pp.itemColours = {colors.lime, colors.green}
11301
		R.subChoice = menu.menu(prompt, choices, pp, "Type number + Enter ")
11302
	--elseif R.choice == 24 then -- Harvest treefarm
11303
	
11304
	elseif R.choice == 25 then -- Build wall or fence
11305
		R.width 	= menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow)
11306
		R.length  	= menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange)
11307
		R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
11308
		if menu.getBoolean("Storage barrels in corners? (y/n)", nil, colors.brown) then
11309
			R.data = "barrel"
11310
		end
11311
	elseif R.choice == 26 then -- Harvest and replant natural forest
11312
11313
		
11314
-- 03. FARMING
11315
	elseif R.choice == 31 then -- new crop farm
11316
11317
	elseif R.choice == 32 then -- extend crop farm
11318
		local choices 	= {"Add a farm at the back", "Add a farm to the right"}
11319
		pp.itemColours = {colors.lime, colors.green}
11320
		R.subChoice = menu.menu(prompt, choices, pp, "Type number + Enter ")
11321
	elseif R.choice == 33 then -- manage crop farm
11322
11323
	elseif R.choice == 34 then -- fence or wall
11324
		R.length  	= menu.getInteger("Length of wall / fence (1-256)", 1, 256, nil, colors.orange)
11325
		R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
11326
	elseif R.choice == 35 then -- rectangle fence or wall
11327
		R.width 	= menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow)
11328
		R.length  	= menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange)
11329
		R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
11330
	
11331
-- 04. OBSIDIAN
11332
	elseif R.choice == 41 then	-- Harvest obsidian
11333
		R.width 	= menu.getInteger("Width of the area (1-64) ", 1, 64, nil, colors.yellow)
11334
		R.length  	= menu.getInteger("Length of the area (1-64) ", 1, 64, nil, colors.orange)
11335
	elseif R.choice == 42 or R.choice == 43 then -- build Nether portal / demolish Nether portal
11336
		local choices = {"Facing portal: forward, turn right",
11337
						 "Aligned with portal: start ahead"}
11338
		pp.itemColours = {colors.pink, colors.red}
11339
		local userChoice, modifier = menu.menu("Starting position?", choices, pp, "Type number + Enter ") -- 1 to 2
11340
		R.subChoice = userChoice
11341
		if modifier == "q" then -- quit chosen
11342
			R.data = "quit"
11343
			return R
11344
		end
11345
		R.length 	= menu.getInteger("Portal width", 1, 64, nil, colors.yellow, nil, 4)
11346
		R.height 	= menu.getInteger("Portal height (inc. buried base)", 1, 64, nil, colors.lightGray, nil, 5)
11347
		R.width 	= menu.getInteger("Thickness (Usually 1) Enter = 1)", 1, 64, nil, colors.red, nil, 1)
11348
		if menu.getBoolean("Base below surface (y/n)", nil, colors.orange) then
11349
			R.data = "bury"
11350
		end
11351
	elseif R.choice == 44 then -- Netherite stripping
11352
		R.width  	= 1
11353
		while R.length == 0 or R.length % 16 > 0 do
11354
			R.length = menu.getInteger("Strip length (divisible by 16) ", 16, 512, 1, colors.orange)
11355
			if R.length % 16 > 0 then
11356
				menu.colourText(1, "~red~Must be multiple of 16")
11357
			end
11358
		end
11359
		R.torchInterval = 16
11360
		R.data = "seal"
11361
	elseif R.choice == 45 then -- undermine dragon towers
11362
11363
	elseif R.choice == 46 then -- deactivate dragon tower
11364
	
11365
	elseif R.choice == 47 then -- build dragon water trap
11366
		local text = 
11367
[[~yellow~You ~red~MUST ~yellow~have already constructed a 
11368
bridge / tunnel into the dragon island
11369
to allow for safe construction of the
11370
dragon trap.
11371
11372
If not use toolkit:
11373
  ~brown~5.~gray~2 Covered path or tunnel~yellow~ length 100
11374
  
11375
start centre of obsidian platform:
11376
  100,49,0 facing west]]
11377
		menu.colourText(1, text)
11378
		if menu.getBoolean("Bridge already made? (y/n)", 12, colors.orange) then
11379
			getTaskHelp(2, R.choice, true)
11380
			menu.clear()
11381
		else
11382
			R.data = "quit"
11383
			return R
11384
		end
11385
	elseif R.choice == 48 then -- build end portal minecart station
11386
	elseif R.choice == 49 then -- Shulker harvesting
11387
		local items	= 
11388
		{
11389
			"Shulker is above",
11390
			"Shulker is ahead",
11391
			"Shulker is below",
11392
			"Climb tower wall",
11393
			"Clear roof above",
11394
			"Clear outside walls"
11395
		}
11396
		pp.itemColours = {colors.lightGray, colors.brown, colors.blue, colors.yellow, colors.orange, colors.lightGray}
11397
		R.subChoice = menu.menu("Which utility? ", items, pp)
11398
		getTaskHelp(2, R.choice * 10 + R.subChoice, true)  -- eg 490 + 1 = 491
11399
		menu.clear()	
11400
		
11401
-- 05. CANAL BRIDGE
11402
	elseif R.choice == 51 then	--single path
11403
		if menu.getBoolean("Shorten an existing path? (y/n)", nil, colors.brown) then
11404
			R.data = "reduce"
11405
		end
11406
		if R.data == "reduce" then
11407
			R.length = menu.getInteger("Reduce by? 0 = here to end", 0, 1024, nil, colors.orange, nil, 64)
11408
		else
11409
			R.length = menu.getInteger("Path length? 0 = continuous ", 0, 1024, nil, colors.orange, nil, 64)
11410
			R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
11411
		end
11412
	elseif R.choice == 52 then	-- 2 block corridor / covered walkway
11413
		R.length 	= menu.getInteger("Corridor length?", 1, 1024, nil, colors.orange, nil, 64)
11414
		R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
11415
		if menu.getBoolean("Seal off water or lava? (y/n)", nil, colors.brown) then
11416
			R.data = "seal"
11417
		end
11418
	elseif R.choice == 53 then	--left/right side of new/existing canal
11419
		local line = getTaskHelp(2, 110, true, true) -- request line no of help display if needed for getInteger
11420
		R.data = menu.getInteger("Choose method 1 or 2", 1, 2, line + 1, colors.white)	-- 2 or 4 turtles
11421
		menu.clear()
11422
		line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger
11423
		R.subChoice = menu.getInteger("Type position of this turtle", 1, 6, line + 1, colors.white)
11424
		local position = "on ground"
11425
		local side = "left"
11426
		local colour = colors.lime
11427
		if R.subChoice == 1 then
11428
			R.side = "L"
11429
			R.height = 1
11430
			position = "on ground"
11431
			colour = colors.lime
11432
		elseif R.subChoice == 2 then
11433
			R.side = "L"
11434
			R.height = 1
11435
			position = "above canal"
11436
			colour = colors.orange
11437
		elseif R.subChoice == 3 then
11438
			R.side = "R"
11439
			side = "right"
11440
			R.height = 1
11441
			position = "above canal"
11442
			colour = colors.brown
11443
		elseif R.subChoice == 4 then
11444
			R.side = "R"
11445
			side = "right"
11446
			R.height = 1
11447
			colour = colors.green
11448
		elseif R.subChoice == 5 then
11449
			R.side = "L"
11450
			R.height = 0
11451
			position = "on canal base"
11452
			colour = colors.blue
11453
		elseif R.subChoice == 6 then
11454
			R.side = "R"
11455
			side = "right"
11456
			R.height = 0
11457
			position = "on canal base"
11458
			colour = colors.cyan
11459
		end
11460
		line = menu.clear()
11461
		if R.data == 1 or (R.data == 2 and (R.subChoice == 1 or R.subChoice == 4)) then
11462
			R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
11463
		end
11464
		-- menu.colourPrint(text, fg, bg, width)
11465
		-- menu.colourText(row, text, reset)
11466
		menu.colourPrint("Turtle placed "..side.." "..position, colour)
11467
		R.length 	= menu.getInteger("Canal length? 0 = continuous ", 0, 512, line + 2, colors.orange, nil, 64)
11468
	elseif R.choice == 54 then	--ice canal 4 sections: edge+torch, edge, centre+ice, centre no ice
11469
		local line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger
11470
		R.subChoice = menu.getInteger("Type turtle position", 1, 8, line, colors.white)
11471
		R.side = "L"
11472
		local position = "on towpath"
11473
		local side = "left"
11474
		local colour = colors.lime
11475
		line = menu.clear()
11476
		--[[
11477
			new canal
11478
			1 = left towpath- move to centre left
11479
			2 = centre left ice or hollow
11480
			3 = centre right ice or hollow
11481
			4 = right side - move to centre right
11482
			convert water canal
11483
			5 = left towpath
11484
			6 = centre left ice or air
11485
			7 = centre right ice or air
11486
			8 = right towpath
11487
		]]
11488
		if R.subChoice == 1 or R.subChoice == 4 or R.subChoice == 5 or R.subChoice == 8 then
11489
			-- on towpath r/l
11490
			R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
11491
			if R.subChoice == 4 or R.subChoice == 8 then
11492
				side = "right"
11493
				R.side = "R"
11494
			end
11495
			if R.subChoice <= 4 then -- 1 or 4 only
11496
				if menu.getBoolean("Place Ice as well? (y/n)", line + 1, colors.blue) then
11497
					R.data = "ice"
11498
				end
11499
			end
11500
		else -- on canal centre r/l
11501
			if R.subChoice == 3 or R.subChoice == 7 then
11502
				side = "right"
11503
				R.side = "R"
11504
			end
11505
			if R.subChoice == 2 or R.subChoice == 3 then -- new canal
11506
				R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, line, colors.red, nil, 0)
11507
				position = "above air/ice"
11508
			end
11509
			if menu.getBoolean("Place Ice as well? (y/n)", line + 1, colors.blue) then
11510
				R.data = "ice"
11511
				if R.subChoice == 6 or R.subChoice == 7 then	
11512
					position = "alternate air/ice"
11513
					colour = colors.lightBlue
11514
				end
11515
			else
11516
				if R.subChoice == 6 or R.subChoice == 7 then	
11517
					position = "on air spaces"
11518
					colour = colors.lighGray
11519
					if R.subChoice == 7 then
11520
						side = "right"
11521
						R.side = "R"
11522
					end
11523
				end
11524
			end
11525
		end
11526
		R.length 	= menu.getInteger("Canal length? 0 = continuous ", 0, 1024, line + 2, colors.orange, nil, 64)
11527
		menu.colourPrint("Turtle on "..side.." side "..position, colour)
11528
		sleep(2)
11529
	elseif R.choice == 55 then	--platform
11530
		R.width 	= menu.getInteger("Platform width", 1, 256, 1, colors.yellow)
11531
		R.length 	= menu.getInteger("Platform length", 1, 256, 2, colors.orange)
11532
		if menu.getBoolean("Remove blocks above? (y/n)",3, colours.red) then
11533
			R.up = true
11534
		end
11535
		
11536
	elseif R.choice == 56 then	--sinking platform
11537
		R.width 	= menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow)
11538
		R.length 	= menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange)
11539
		R.height 	= menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue)
11540
	elseif R.choice == 57 then	--boat bubble lift
11541
		R.height 	= menu.getInteger("Levels to go up?", 1, ceiling - 2, nil, colors.lightBlue)
11542
		
11543
-- 06. MOB SPAWNER TOOLS
11544
	elseif R.choice == 61 then -- create cube round mob spawner
11545
		local text =
11546
[[~yellow~Turtle placement options:
11547
11548
~lime~1. On top or in front of the spawner
11549
   ~green~(cave spider OR no chests around)
11550
~lightGray~2. Outside the dungeon at floor or
11551
   ceiling level ~red~1 block from corner
11552
~yellow~Make sure you have access to the block
11553
facing the spawner, as any chests
11554
found inside will be placed outside
11555
the new dungeon wall at this height
11556
11557
~white~Enter to continue
11558
]]
11559
		menu.colourText(nil, text, true)
11560
		read()
11561
		menu.clear()
11562
		R.data = "spawner"
11563
		if menu.getBoolean("Any chests around spawner? (y/n)",1, colours.red) then
11564
			R.data = "chest"
11565
		end
11566
		local choices = {"Turtle on spawner (no chests)",
11567
						 "Outside wall: left side, floor",
11568
						 "Outside wall: left side, ceiling",
11569
						 "Outside wall: right side, floor",
11570
						 "Outside wall: right side, ceiling"}
11571
		pp.itemColours = {colors.red, colors.lime, colors.orange, colors.green, colors.yellow}
11572
		local userChoice, modifier = menu.new("Select turtle position", choices, pp) -- 1 to 5
11573
		
11574
		if modifier == "q" then -- quit chosen
11575
			R.data = "quit"
11576
			return R
11577
		end
11578
		R.subChoice 	= userChoice
11579
		if R.subChoice > 1 then -- get dungeon wall dimensions
11580
			R.width 	= menu.getInteger("Dungeon external width ", 0, 11, nil, colors.yellow, nil, 11)
11581
			R.length 	= menu.getInteger("Dungeon external length ", 0, 11, nil, colors.orange, nil, 11)
11582
		end
11583
		
11584
	elseif R.choice == 62 then -- Blaze spawner
11585
		local text =
11586
[[~yellow~Turtle placement options:
11587
11588
~red~1a On top of the spawner
11589
11590
~red~1b ~orange~At the same level in direct line of
11591
spawner.~yellow~ (can be behind a safety wall)
11592
11593
~red~1c~lightGray~ Room below spawner (via stairs)
11594
11595
~lime~2 Finish build: In brick floor outside
11596
  existing cube. (facing player)
11597
11598
~white~Enter to continue]]
11599
		menu.colourText(nil, text, true)
11600
		read()
11601
		pp.itemColours = {colors.red, colors.lime}
11602
		R.subChoice = menu.new("Choose your option", {"New Blaze spawner", "Complete part build (killzone)"}, pp, "Type number + Enter") -- 1 = new, 2= continue
11603
		R.data = "blaze"			-- default
11604
		if R.subChoice == 1 then	-- new blaze spawner
11605
			text =
11606
[[~yellow~Turtle placement options:
11607
~red~1. On top of the spawner
11608
~orange~2. In direct sight (safety wall ok)
11609
~lightGray~3. Room below spawner (via stairs)
11610
   |*|*|*|*|*|   Ceiling
11611
   |*|*|~red~T~lightGray~|*|*|   Turtle under ceiling
11612
   |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*|   Top of fence
11613
   |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*|
11614
   |*|~brown~+~lightGray~|*|~brown~+~lightGray~|*|   Bottom of fence
11615
   |*|*|*|*|*|   Floor level]]
11616
			--R.subChoice = menu.new("Choose your position", {"On top of spawner", "In direct sight (safety wall ok)", "Room below spawner"}, pp, "Type number + Enter")
11617
			--getInteger(prompt, minValue, maxValue, row, fg, bg, default) 
11618
			T:clear()
11619
			menu.colourText(nil, text, true)
11620
			R.subChoice = menu.getInteger("Enter position number", 1, 3, 12, colors.white)
11621
		else
11622
			R.data = "restart"		-- complete part build
11623
		end
11624
	elseif R.choice == 63 then -- flood spawner cube
11625
		local choices = {"Bubble lift", "Computercraft mob softener"}
11626
		pp.itemColours = {colors.lime, colors.orange}
11627
		local userChoice = menu.menu("Flood for Mob grinder type?", choices, pp, "Type number + Enter ")
11628
		R.subChoice = userChoice -- 1 bubble, 2 computercraft
11629
	elseif R.choice == 64 then -- create bubble lift at mob spawner
11630
		local choices = {"Dropzone on left", "Dropzone on right"}
11631
		pp.itemColours = {colors.lime, colors.orange}
11632
		local userChoice = menu.menu("Which side do you want the mobs?", choices, pp, "Type number + Enter")
11633
		R.subChoice = userChoice -- 1 left, 2 right
11634
	elseif R.choice == 65 then -- Computercraft mob grinder
11635
		local choices = {"Use Sticky pistons", "Use non-sticky pistons"}
11636
		pp.itemColours = {colors.lime, colors.orange}
11637
		local userChoice = menu.menu("Which type of pistons?", choices, pp, "Type number + Enter ")
11638
		R.subChoice = userChoice -- 1 sticky, 2 normal
11639
	
11640
-- 07. AREA CARVING
11641
	elseif R.choice == 71 then --Clear field
11642
		R.width 	= menu.getInteger("Width of the area (1-64)", 1, 64, nil, colors.yellow)
11643
		R.length  	= menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange)
11644
		if menu.getBoolean("Dirt on the surface (y/n)", nil, colors.brown) then
11645
			R.useBlockType = "dirt"
11646
		end
11647
	elseif R.choice == 72 then -- Clear solid rectangle R.width, R.length
11648
		R.width 	= menu.getInteger("Rectangle width (1-256)", 1, 256, nil, colors.yellow)
11649
		R.length  	= menu.getInteger("Rectangle length (1-256)", 1, 256, nil, colors.orange)
11650
		R.up 		= menu.getBoolean("Remove blocks above?", nil, colors.yellow)
11651
		R.down 		= menu.getBoolean("Remove blocks below?", nil, colors.orange)
11652
		if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then
11653
			T:forward(1)
11654-
		T:place(R.useBlockType, "forward", false)
11654+
11655
	elseif R.choice == 73 then -- Clear wall
11656-
		T:place("minecraft:redstone_torch", "forward", true)
11656+
11657
		R.length 	= menu.getInteger("Length of wall (1-256) ", 1, 256, nil, colors.orange)
11658
		R.height 	= menu.getInteger("Height of wall (1-50) ", 1, 50, nil, colors.lightGray)
11659
		pp.itemColours = {colors.lime, colors.orange}
11660
		R.subChoice = menu.menu("Which direction?", {"Bottom -> Top", "Top -> Bottom"}, pp, "Type number + Enter ") -- open direction menu options
11661
		if R.subChoice == 1 then
11662
			if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then
11663
				T:forward(1)
11664
			end
11665
		else
11666
			pp.itemColours = {colors.lightBlue, colors.cyan, colors.blue, colors.gray}
11667
			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 ") 
11668
			if choice == 1 then
11669
				T:down(1)
11670-
		T:place("minecraft:redstone_torch", "up", false)
11670+
11671
				T:forward(1)
11672
			elseif choice == 4 then
11673
				T:go("D1F1")
11674
			end
11675
		end
11676
	elseif R.choice == 74 then -- Clear rectangle perimeter only R.width, R.length
11677
		R.width 	= menu.getInteger("Perimeter width (1-256) ", 1, 256, nil, colors.yellow)
11678
		R.length  	= menu.getInteger("Perimeter length (1-256) ", 1, 256, nil, colors.orange)
11679
		R.height 	= 1
11680
		if menu.getBoolean("Remove blocks above? (y/n)", 3, colours.red) then
11681-
	-- already known R.networkFarm, R.subChoice (1 = singe, 2 = double, 3 = mangrove)
11681+
11682-
	--T:place(blockType, damageNo, leaveExisting, signText)
11682+
11683
		if menu.getBoolean("Remove blocks below? (y/n)", 4, colours.red) then
11684
			R.down = true
11685-
	function lib.checkSaplings(firstChoice, secondChoice)
11685+
11686
		if menu.getBoolean("Am I outside clearing zone (y/n)?", 5, colors.yellow) then
11687
			T:forward(1)
11688
		end
11689
	elseif R.choice == 75 or R.choice == 76 then -- Clear hollow building floor/walls/ceiling OR clear solid object
11690
		R.width 	= menu.getInteger("Structure width (1-256)", 1, 256, nil, colors.yellow)
11691
		R.length  	= menu.getInteger("Structure length (1-256)", 1, 256, nil, colors.orange)
11692
		R.height  	= menu.getInteger("Depth/Height (1-256)", 1, 256, nil, colors.lightGray)
11693
		if R.choice == 75 then -- hollow building so need to check if floors/ceilings to be removed
11694
			R.data = {}
11695
			R.data.ceiling = false
11696
			R.data.floor = false
11697-
	function lib.emptyInventory(R)
11697+
11698-
		if not T:isEmpty() then
11698+
11699-
			utils.useSticksAsFuel()
11699+
11700-
			network.sendItemToNetworkStorage(R, "barrel", "sapling", 64)
11700+
11701-
			network.sendItemToNetworkStorage(R, "barrel", "propagule", 64)
11701+
11702-
			network.sendItemToNetworkStorage(R, "barrel", "apple", 64)
11702+
11703-
			network.sendItemToNetworkStorage(R, "barrel", "dirt", 64)
11703+
11704-
			network.sendItemToNetworkStorage(R, "chest", "all", 0)
11704+
11705
		R.subChoice = menu.menu("Which direction?", {"Bottom -> Top", "Top -> Bottom"}, pp, "Type number + Enter ") -- open direction menu options
11706
		if R.subChoice == 1 then
11707
			if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then
11708-
	function lib.getSaplingInventory(R)
11708+
11709
			end
11710
		else
11711
			pp.itemColours = {colors.lightBlue, colors.cyan, colors.blue, colors.gray}
11712
			local choice = menu.menu("Exact position?", {"On top of clearing zone", "Outside clearing zone", "Inside clearing zone","Above AND outside"}, pp, "Type number + Enter ") 
11713
			if choice == 1 then
11714
				T:down(1)
11715
			elseif choice == 2 then
11716-
		saplings.cherry_sapling = 0
11716+
11717-
		saplings.mangrove_propagule = 0
11717+
11718
				T:go("D1F1")
11719
			end
11720
		end
11721
	elseif R.choice == 77 then	-- Dig a trench
11722
		R.height 	= menu.getInteger("Depth of the trench (1-64) ", 1, 64, nil, colors.blue)
11723-
		if T:getItemSlot("sapling") > 0 then
11723+
11724-
			for i = 1, 16 do
11724+
11725-
				if turtle.getItemCount(i) > 0 then
11725+
11726-
					local data = turtle.getItemDetail(i)
11726+
11727-
					if data.name:find("sapling") ~= nil then
11727+
11728-
						local name = data.name:sub(11) -- removes "minecraft:"
11728+
11729-
						saplings[name] = saplings[name] + data.count
11729+
11730
		local items = {	"Replacing current floor",
11731
						"New floor over existing",
11732
						"Replacing current ceiling",
11733-
		elseif T:getItemSlot("propagule") > 0 then
11733+
11734-
			saplings.mangrove_propagule = turtle.getItemCount(T:getItemSlot("propagule"))
11734+
11735-
		else	-- no saplings onBoard: ? automated networked farm
11735+
11736-
			if R.networkFarm then
11736+
11737-
				-- networked farms use 1 type of sapling indicated by log embedded to right of modem
11737+
11738-
				-- discovered from utils.assessTreeFarm() on manual Startup
11738+
11739-
				if R.auto then	-- called here as NOT manual startup
11739+
11740-
					R = utils.assessTreeFarm(R)
11740+
11741-
					if R.message ~= "" then
11741+
11742-
						return {R.message}	-- location of turtle error
11742+
11743
		else
11744
			R.up = true
11745-
				local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", R.useBlockType, 16)
11745+
11746-
				if turtleCount == 0 then	-- ask player for saplings
11746+
11747-
					T:checkInventoryForItem({R.useBlockType}, {16}, true, "Saplings required for tree farm")
11747+
11748
	elseif R.choice == 710 or R.choice == 83 then -- Direct movement
11749-
				saplings[R.useBlockType] = saplings[R.useBlockType] + turtleCount
11749+
11750-
				turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 16)
11750+
11751-
				if turtleCount == 0 then
11751+
11752-
					turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 16)
11752+
11753
		choices = {"Command driven", "Menu driven"}
11754-
				if turtleCount == 0 then	-- ask player
11754+
11755-
					T:checkInventoryForItem({"minecraft:dirt"}, {16}, true, "Dirt required for tree farm")
11755+
11756
			R.data = "cmd"
11757-
				return saplings, R.useBlockType, R.useBlockType
11757+
11758
			R.data = "menu"
11759
		end
11760
		
11761
-- 08. WATER LAVA
11762
	elseif R.choice == 81 then -- Sand based utilities
11763
		local line = getTaskHelp(2, R.choice, true, true) -- request line no of help display if needed for getInteger
11764
		R.subChoice = menu.getInteger("Type number of choice", 1, 4, line, colors.white)
11765
		T:clear()
11766
		if R.subChoice == 1 then -- drop sand into water or lava surface until solid ground reached
11767
			R.width	  = 1
11768
			R.length  = menu.getInteger("Length of sand wall (0=to block) ", 0, 60, nil, colors.orange)
11769
		elseif R.subChoice == 2 then	-- clear rectangle on top of building and fill with sand
11770
			R.width   = menu.getInteger("Width of area (<=30) ", 1, 30, nil, colors.yellow)
11771
			R.length  = menu.getInteger("Length of of area (<=30) ", 1, 30, nil, colors.orange)
11772
		elseif R.subChoice == 3 then	-- clear sand wall or harvest sand
11773
			R.width   = 1
11774
			R.length  = menu.getInteger("Length of sand (0=auto-detect)", 0, 60, nil, colors.orange)
11775
			choices = {"Stay at end of wall", "Return home"}
11776
			pp.itemColours = {colors.lime, colors.orange}
11777
			userChoice = menu.menu("Choose your preference", choices, pp, "Type number + Enter ")
11778
			if userChoice == 2 then
11779
				R.data = "return"
11780-
			T:place("dirt", "down", false, "", true)
11780+
11781
		elseif R.subChoice == 4 then	-- remove sand from cube. start at top
11782
			R.width   = menu.getInteger("Width of sand (<=30) ", 1, 30, nil, colors.yellow)
11783
			R.length  = menu.getInteger("Length of of sand (<=30) ", 1, 30, nil, colors.orange)
11784
			R.height  = 0
11785
			R.data = "down" -- always starts at the top
11786-
				T:place(sapling, "down", false, "", true)
11786+
11787
		if menu.getBoolean("Am I outside the active zone (y/n)?", nil, colors.yellow) then
11788
			T:forward(1)
11789
		end
11790-
				T:place(sapling, "down", false, "", true)
11790+
11791
		R.width 	= 1
11792
		if menu.getBoolean("Going 90 deg. from existing? (y/n)", nil, colors.yellow, colors.black) then
11793
			getTaskHelp(2, 852, true)
11794
			menu.clear()	
11795
			R.length = 56
11796
			R.data = "withPath" -- ensures turtle will break through path
11797
			R.length = menu.getInteger({"Wall length minus corners","(Ocean monument default 56)","Number -> Enter or Enter only (56)"},
11798
										1, 64, nil, {colors.yellow, colors.orange, colors.green}, colors.black, 56)
11799
		else
11800
			R.length 	= menu.getInteger("Length of the wall (1-60) ", 1, 60, nil, colors.yellow)
11801
			R.height 	= menu.getInteger("Fixed depth or 0 = to floor ", 0, 60, nil, colors.yellow)
11802
		end
11803
	-- for 83 see 710
11804
	elseif R.choice == 84 then -- Clear area of water bounded by blocks
11805
		R.width 	= menu.getInteger("Width of water (0=autodetect) ", 0, 64, nil, colors.yellow)
11806
		if R.width > 0 then
11807-
		T:place("dirt", "down", false, "", true)
11807+
11808
		end
11809-
		if not T:place(sapling, "down", false, "", true) then -- try specific sapling
11809+
11810-
			T:place("sapling", "down", false, "", true)		-- any available sapling
11810+
11811
		R.width 	= menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow)
11812
		R.length 	= menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange)
11813
		R.height 	= menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue)
11814
	elseif R.choice == 86 then -- ocean monument utilities
11815
		local items	= 
11816
		{
11817
			"Build 4 corner marker columns",
11818
			"Retaining wall beween 2 columns",
11819
			"Clear plants pre sand draining",
11820
			"Drop sand wall",
11821
			"Recover sand wall",
11822
			"Sinking platform",
11823-
	function lib.getMangroveSupplies()
11823+
11824-
		local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 169)
11824+
11825-
		if turtleCount < 169 then
11825+
11826-
			turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 169 - turtleCount)
11826+
11827-
			if turtleCount < 169 then	-- ask player for saplings
11827+
11828-
				T:checkInventoryForItem({"dirt"}, {169 - turtleCount})
11828+
11829
		end
11830
		menu.clear()	
11831-
		turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:mangrove_propagule", 25)
11831+
11832-
		if turtleCount == 0 then	-- ask player for saplings
11832+
11833-
			T:checkInventoryForItem({"mangrove_propagule"}, {25}, true, "Mangrove propagules required")
11833+
11834
		elseif R.subChoice == 2 then -- Retaining wall beween 2 columns
11835
			R.length = 56
11836
			R.data = "withPath" -- ensures turtle will break through path
11837-
	function lib.plantMangrove()
11837+
11838-
		T:go("L1F6 R1F1 U1")
11838+
11839-
		createFloorCeiling({width = 13, length = 13, up = false, down = true,
11839+
11840-
							height = 0, subChoice = 0, useBlockType = "minecraft:dirt",
11840+
11841-
							inventory = T:getInventory()})
11841+
11842
			R.data = "clearWaterPlants"
11843-
		--T:go("U1F5 R1F5 L1")			-- lower left of planting area, facing Back
11843+
11844-
		T:go("U1F4 R1F4 L1")			-- lower left of planting area, facing Back
11844+
11845-
		for x = 1, 5 do
11845+
11846-
			for i = 1, 5 do
11846+
11847-
				T:place("propagule", "down")	-- left 1
11847+
11848-
				if i < 5 then
11848+
11849
		elseif R.subChoice == 5 then -- remove sand wall using sand utilities
11850
			R.width	  = 1
11851
			R.length  = 0
11852-
			if x % 2 == 1 then
11852+
11853-
				if x < 5 then
11853+
11854
			R.length = menu.getInteger("Length (excluding retaining wall)? ", 1, 1024 / R.width, nil, colors.orange)
11855
			R.height = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue)
11856
		elseif R.subChoice == 7 then -- Drain and remove structure
11857
			R.width = 28
11858
			R.length = 28
11859
			R.height = menu.getInteger("Go down how far from current", 1, 64, nil, colors.blue)
11860-
		T:go("L1F2 L1F2 D2U2 F7R2 D2")
11860+
11861
	elseif R.choice == 87 then -- Ladder to water/lava	
11862-
		T:place("propagule", "down")	-- left 1
11862+
11863
	elseif R.choice == 88 then -- Clear water plants from enclosed area
11864-
		T:place("propagule", "down")	-- left 2
11864+
11865
		R.width 	= menu.getInteger("water width (0=auto detect) ", 0, 64, nil, colors.yellow)
11866-
		T:place("propagule", "down")	-- left 3/top 1
11866+
11867
	elseif R.choice == 89 then -- convert flowing water to source
11868-
		T:go("R1F1")
11868+
11869-
		T:place("propagule", "down")	-- top 2
11869+
11870
			R.length = menu.getInteger("water length (0=auto detect) ", 0, 64, nil, colors.orange)
11871-
		T:place("propagule", "down")	-- top 3/right 1
11871+
11872-
		T:go("R1F1")
11872+
11873
	elseif R.choice == 810 then -- create sloping water
11874-
		T:place("propagule", "down")	-- right 2
11874+
11875
		R.length 	= menu.getInteger("water slope length ", 1, 64, nil, colors.orange)
11876-
		T:place("propagule", "down")	-- right 3/bottom 1
11876+
11877-
		T:go("R1F1")
11877+
11878-
		T:place("propagule", "down")	-- bottom 2]]
11878+
11879
		R.width 	= 1
11880-
		--T:go("R1F1R2 D2U2 F7R2 D2")
11880+
11881
		R.height 	= menu.getInteger("Height of wall (1-50) ", 1, 50, nil, colors.lightGray)
11882
		pp.itemColours = {colors.lime, colors.magenta}
11883-
	function lib.plantSingle(R)
11883+
11884-
		local sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11884+
11885-
		if count >= 1 then
11885+
11886-
			if R.networkFarm then
11886+
11887-
				T:go("U1L1 F3R1 F4") -- outside first area
11887+
11888
		pp.itemColours = {colors.lime, colors.magenta}
11889-
				T:go("U1F4") -- outside first area
11889+
11890
	elseif R.choice == 93 or R.choice == 94 then -- Build gable roof / pitched roof
11891-
			for i = 1, 3 do	-- column 1/4
11891+
11892-
				lib.createSingle(sapling, "forward")
11892+
11893
	elseif R.choice == 97 then -- build downward slope
11894
		R.height  	= menu.getInteger("How many blocks down (0=to ground)?", 0, 256, nil, colors.blue)
11895-
			for i = 1, 2 do
11895+
11896-
				lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
11896+
11897
		R.height  	= menu.getInteger("Go up by how many blocks?", 1, 256, nil, colors.lightGray)
11898
		R.up = true
11899-
			for i = 1, 2 do -- column 2/4
11899+
11900-
				lib.createSingle(sapling, "forward")
11900+
11901
	elseif R.choice == 101 then -- measure height
11902
		pp.itemColours = {colors.lightBlue, colors.cyan, colors.lime, colors.gray}
11903-
			for i = 1, 2 do
11903+
11904-
				lib.createSingle(sapling, "left") -- place 4th dirt/saling and exit to right
11904+
11905
			R.data = menu.getString({"Search for? eg 'ore', 'obsidian'",">"}, false, 3, 20, nil, {colors.lime, colors.yellow})
11906
		end
11907-
			for i = 1, 2 do -- column 3/4
11907+
11908-
				lib.createSingle(sapling, "forward")
11908+
11909
		pp.itemColours = {colors.lime, colors.orange, colors.green}
11910
		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
11911-
			for i = 1, 2 do
11911+
11912-
				lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
11912+
11913
		end
11914
	elseif R.choice == 103 then -- measure length
11915-
			for i = 1, 3 do -- column 4/4
11915+
11916-
				lib.createSingle(sapling, "forward")
11916+
11917
													"No further blocks above",
11918
													"No further blocks below",
11919-
			if R.networkFarm then
11919+
11920-
				T:go("R1F3 R1F2L1") -- in-between 2 trees
11920+
11921-
				if R.auto then
11921+
11922-
					harvestTreeFarm(R)
11922+
11923
		end
11924-
					T:go("L1F4R2D1")
11924+
11925
	elseif R.choice == 104 then -- measure greatest depth of water body
11926
		pp.itemColours = {colors.lime, colors.orange}
11927-
				T:go("R1F6 L1F2 R2D1")
11927+
11928
		-- 1 = player entry, 2 = water length
11929
		if R.subChoice == 1 then
11930-
			return "No saplings to plant"
11930+
11931
		end
11932
	elseif R.choice == 105 then -- drill borehole and write borhole.txt to file
11933
		R.height = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.lightGray)
11934
		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)
11935
	end
11936-
	function lib.plantDouble(R)
11936+
11937
	return R
11938
end
11939
11940
local function getTaskInventoryTo30(R)
11941-
			if R.networkFarm then
11941+
11942-
				T:go("U1L1 F3R1 F3") -- outside first area
11942+
11943
	--local pp = utils.getPrettyPrint()
11944-
				T:go("U1F3") -- outside first area
11944+
11945
	if R.choice == 0 then --Missing pickaxe
11946
		T:checkInventoryForItem({"minecraft:diamond_pickaxe"}, {1})
11947-
			sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11947+
11948
		T:setEquipment()
11949
	elseif R.choice == 1 then --Missing crafting table
11950-
			sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11950+
11951
		print("Crafting table being tested...")
11952
		T:setEquipment()
11953-
			sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11953+
11954
		T:checkInventoryForItem({"minecraft:chest"}, {1}) -- 0 if not present
11955
		sleep(1.5)
11956
		
11957-
			if R.networkFarm then
11957+
11958-
				T:go("R1F4 R1F1 L1") 			-- on left side of double tree
11958+
11959-
				if R.auto then
11959+
11960-
					harvestTreeFarm(R)
11960+
11961
		pp.itemColours = {colors.blue, colors.lightGray}
11962-
					T:go("L1F4 L1F1 L1D1")	-- back to start
11962+
11963
		local inAir = false
11964
		local inNether = menu.getBoolean("Are you in the nether? (y/n) ", nil, colors.yellow, colors.black)
11965-
				T:go("R1D1 F6L1 F3R2") -- outside first area
11965+
11966
		if inNether then
11967
			bedrock = 0 
11968-
			return "Insufficient saplings to plant"
11968+
11969
		end
11970
		local option = menu.menu("Which direction?", {"Going down","Going up"}, pp) 
11971
		if option == 1 then
11972
			R.down = true
11973-
	if R.networkFarm then
11973+
11974-
		local message = network.loadStorageLists()	-- initialises or creates lists of where an item can be found: GLOBAL LISTS!
11974+
11975-
		if message ~= nil then return {message} end
11975+
11976-
		lib.emptyInventory(R)
11976+
11977
					R.data = "chamber"
11978-
	if R.subChoice == 3 then	-- mangrove, R.networkFarm only 
11978+
11979-
		lib.getMangroveSupplies()
11979+
11980-
		lib.plantMangrove()
11980+
11981
				description = "Creating stairs going down"
11982-
		local saplings, firstChoice, secondChoice = lib.getSaplingInventory(R)
11982+
11983-
		if firstChoice ~= "" then
11983+
11984-
			print("first sapling: "..firstChoice .. " ("..saplings[firstChoice]..")")
11984+
11985
			--R.depth = utils.getSize(true,"Current level (F3->Y coord)? ", bedrock + 5, ceiling)
11986-
		if secondChoice ~= "" then
11986+
11987-
			print("second sapling: "..secondChoice .. " ("..saplings[secondChoice]..")")
11987+
11988
			R.height = menu.getInteger("Go up to level? ("..R.depth + 2 .." to "..ceiling ..") ", R.depth + 2, ceiling, nil, colors.lightGray)
11989
			if R.choice == 11 then
11990-
		-- check type/size of farm
11990+
11991
			else
11992-
		if R.subChoice == 1 then 			-- 16 single trees
11992+
11993-
			message = lib.plantSingle(R)	-- always ""
11993+
11994-
		elseif R.subChoice == 2 then 		-- 4 double trees (4 saplings)
11994+
11995-
			message = lib.plantDouble(R)	-- "" or error about numbers 
11995+
11996
		
11997
		if not inAir then
11998-
	if R.networkFarm then
11998+
11999-
		lib.emptyInventory(R)
11999+
12000
		--[[
12001-
	return {message}
12001+
12002
		-50 to -59 = -59 -(-50) = -9   down
12003
		-59 to -50 = -50 -(-59) = 9    up
12004
		 70 to -48 = -48 -   70 = -118 down
12005
		  5 to  64 =  64 -   5  = 59   up
12006
		]]
12007
		T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
12008
		if R.choice == 11 then -- ladders
12009
			utils.checkFuelNeeded(range * 2)
12010
			T:checkInventoryForItem({"minecraft:ladder"}, {range})
12011
			T:checkInventoryForItem({"minecraft:torch"}, {math.floor(range / 3)}, false)
12012
			if inAir then
12013
				range = range * 4 -- more blocks needed
12014
			end
12015
			T:checkInventoryForItem({"stone"}, {range})
12016
		else -- stairs
12017
			utils.checkFuelNeeded(range * 10) -- stairs: each layer needs 10 moves
12018
			local numStairsNeeded = range
12019
			local data = T:getStock("stairs")
12020
			local numStairs = data.total
12021
			local cobbleNeeded = math.min(range * 6, 256)
12022
			if inAir then
12023
				cobbleNeeded = range * 6 -- 5 blocks / layer unless in water or lava
12024
			end
12025
			if numStairs < numStairsNeeded then
12026
				cobbleNeeded = cobbleNeeded + (math.floor((2 * (numStairsNeeded - numStairs)) / 3))
12027
			end
12028
			T:checkInventoryForItem({"stairs"}, {numStairsNeeded}, false)
12029
			T:checkInventoryForItem({"stone"}, {cobbleNeeded})
12030
			T:checkInventoryForItem({"minecraft:chest"}, {1}) 	-- needed for crafting
12031
		end
12032
		menu.colourPrint(description, colors.lightBlue)
12033
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12034
		if R.choice == 11 then
12035
			retValue = createLadder(R) -- "bedrock", 70, -48
12036
		else
12037
			retValue = createStaircase(R)
12038
		end
12039
	elseif R.choice == 13 then --Create Mine at this level
12040
		utils.checkFuelNeeded(960)
12041
		T:checkInventoryForItem({"minecraft:torch"}, {24}, false)
12042
		T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
12043
		T:checkInventoryForItem({"stone"}, {64})
12044
		T:checkInventoryForItem({"minecraft:chest"}, {1})
12045
		menu.colourPrint("CreateMine starting", colors.lightBlue)
12046
		sleep(2)
12047
		retValue = createMine()
12048
	elseif R.choice == 14 then	-- safe drop to water
12049
		utils.checkFuelNeeded(R.height * 2)
12050
		T:checkInventoryForItem({"minecraft:water_bucket"}, {1})
12051
		T:checkInventoryForItem({"stone"}, {R.height * 2}, false) -- estimate only partial cloaking needed
12052
		menu.colourPrint("Creating safe drop ".. R.height.. " blocks deep", colors.lightBlue)
12053
		menu.colourPrint("Wait for my return!", colors.yellow)
12054
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12055
		retValue = createSafeDrop(R)
12056
	elseif R.choice == 15 then	-- single column bubble lift
12057
		local needSigns = true
12058
		utils.checkFuelNeeded(R.height * 6)
12059
		--print(text, fg, bg, width)
12060
		menu.colourPrint("Checking if near ladder", colors.red)
12061
		T:turnRight(1)
12062
		local blockType = T:getBlockType("forward")
12063
		if blockType:find("ladder") == nil then
12064
			T:turnLeft(2)
12065
			blockType = T:getBlockType("forward")
12066
			if blockType:find("ladder") == nil then
12067
				needSigns = false
12068
			end
12069
			T:turnRight(1)
12070
		else
12071
			needSigns = false
12072
			T:turnLeft(1)
12073
		end
12074
		sleep(1)
12075
		if needSigns then
12076
			T:checkInventoryForItem({"sign"}, {2}, true, "Ladder not found")
12077
		else
12078
			menu.colourPrint("Ladder found, signs not required", colors.orange)
12079
			sleep(1)
12080
		end
12081
		if T:getBlockType("down"):find("bedrock") == nil then -- NOT bedrock below
12082
			T:checkInventoryForItem({"minecraft:water_bucket"}, {3})
12083
		else
12084
			T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
12085
		end
12086
		T:checkInventoryForItem({"minecraft:soul_sand", "minecraft:dirt"}, {1, 1}, true, "? use dirt as soul sand placeholder")
12087
		T:checkInventoryForItem({"stone"}, {R.height * 2}, false) -- estimate only partial cloaking needed
12088
		local _, slots = T:getFirstEmptySlot() -- returns first empty slot, no of empty slots
12089
		T:checkInventoryForItem({"minecraft:bucket"}, {slots}, false, "Add empty buckets for speed!")
12090
		menu.colourPrint("Creating bubble lift ".. R.height.. " blocks high", colors.lime)
12091
		if not needSigns then -- ladder present as signs not required
12092
			menu.colourPrint("Wait at the top via ladder...", colors.orange)
12093
		end
12094
		menu.colourPrint("\nSTAND ON THE LADDER FOR SAFETY!", colors.red)
12095
		menu.colourPrint("\nEnter to continue", colors.yellow)
12096
		read()
12097
		retValue = createBubbleLift(R)
12098
	elseif R.choice == 16 then --QuickMine corridor
12099
		utils.checkFuelNeeded((R.width * 2 + R.length * 2) * 2)
12100
		T:checkInventoryForItem({"stone"}, {R.width * 2 + R.length * 2}, false)
12101
		T:checkInventoryForItem({"minecraft:torch"}, {math.floor((R.width * 2 + R.length * 2) / R.torchInterval)}, false)
12102
		T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
12103
		menu.colourPrint("QuickMine corridor: R.subChoice "..R.width.. " x "..R.length, colors.lightBlue)
12104
		retValue = quickMineCorridor(R)
12105
	elseif R.choice == 17 then --QuickMine
12106
		utils.checkFuelNeeded(R.width * R.length)
12107
		T:checkInventoryForItem({"stone"}, {64})
12108
		T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
12109
		menu.colourPrint("QuickMine rectangle: R.subChoice "..R.width.. " x "..R.length, colors.lightBlue)
12110
		retValue = quickMine(R)
12111
	elseif R.choice == 18 then --Mine bedrock area
12112
		utils.checkFuelNeeded(R.width * R.length)
12113
		T:checkInventoryForItem({"stone"}, {64})
12114
		T:checkInventoryForItem({"minecraft:bucket"}, {1}, false)
12115
		retValue = mineBedrockArea(R) -- R.data = "leaveExposed" or ""
12116
	elseif R.choice == 19 then	-- salvage mineshaft
12117
		local equippedRight, equippedLeft, inInventory = T:setEquipment() -- check for crafting table, sword, pickaxe, Put sword in spare slot
12118
		if equippedLeft ~= "minecraft:diamond_pickaxe" and equippedRight ~= "minecraft:diamond_pickaxe" then
12119
			T:checkInventoryForItem({"minecraft:diamond_pickaxe"}, {1}, true)
12120
			equippedRight, equippedLeft, inInventory = T:setEquipment() -- check for crafting table, sword, pickaxe, Put sword in spare slot
12121
		end
12122
		if inInventory ~= "minecraft:diamond_sword" then
12123
			T:checkInventoryForItem({"minecraft:diamond_sword"}, {1}, false, "To harvest spider webs\nyou need a diamond sword.") --checkInventoryForItem(self, items, quantities, required, message, name)
12124
		end
12125
		if T:getItemSlot("minecraft:diamond_sword") > 0 then
12126
			inInventory = "minecraft:diamond_sword"
12127
		end
12128
		T:checkInventoryForItem({"minecraft:torch"}, {R.torchInterval}, false)
12129
		if inInventory == "minecraft:diamond_sword" then
12130
			menu.colourPrint("Clearing Mineshaft and cobwebs", colors.orange)
12131
		else
12132
			menu.colourPrint("Clearing Mineshaft", colors.yellow)
12133
		end
12134
		retValue = clearMineshaft(R, equippedRight, equippedLeft, inInventory) -- pass whether the sword is present
12135
		
12136
	-- FORESTRY
12137
	elseif R.choice == 21 then	-- Fell tree
12138
		if T:isLog("forward") then
12139
			if turtle.getFuelLevel() < 30 then
12140
				T:checkInventoryForItem({"minecraft:chest"}, {1}, false,"Fuel level critical: "..turtle.getFuelLevel())
12141
				turtle.select(1)
12142
				T:dig("forward")
12143
				T:craft("planks", 4)
12144
				T:refuel()
12145
				T:forward(1)
12146
				T:up(2)
12147
				T:craft("chest", 1)
12148
			else
12149
				T:forward(1)
12150
			end
12151
			menu.colourPrint("Felling tree", colors.lime)
12152
			os.sleep(2)    -- pause for 2 secs to allow time to press esc
12153
			T:harvestWholeTree("up")
12154
			while turtle.down() do end
12155
			retValue = {"Tree Harvested"}
12156
		else
12157
			retValue =
12158
			{
12159
				"No log in front..",
12160
				"Move me in front of a tree!"
12161
			}
12162
		end
12163
	elseif R.choice == 22 then --Create treefarm
12164
		utils.checkFuelNeeded(900)
12165
		--T:checkInventoryForItem({"minecraft:dirt"}, {16})
12166
		T:checkInventoryForItem({"stone"}, {320})
12167
		T:checkInventoryForItem({"polished"}, {4}) -- used to mark launch positions
12168
		T:checkInventoryForItem({"minecraft:water_bucket"}, {5})
12169
		R.useBlockType = T:getMostItem("", true)
12170
		menu.colourPrint("Creating Tree Farm with "..R.useBlockType, colors.lime)
12171
		sleep(2)
12172
		retValue = createTreefarm(R)
12173
	elseif R.choice == 23 then -- Plant treefarm
12174
		if R.subChoice == 1 then
12175
			utils.checkFuelNeeded(180)
12176
			T:checkInventoryForItem({"dirt"}, {16})
12177
			T:checkInventoryForItem({"sapling"}, {16}, false, "Max 16. NOT dark oak")
12178
		elseif R.subChoice == 2 then
12179
			utils.checkFuelNeeded(180)
12180
			T:checkInventoryForItem({"dirt"}, {16})
12181
			T:checkInventoryForItem({"sapling"}, {16}, false, "Max 16. 4 saplings / tree")
12182
		end
12183
		menu.colourPrint("plantTreefarm starting: size "..R.subChoice, colors.lime)
12184
		retValue = plantTreefarm(R)
12185
	elseif R.choice == 24 then	-- Harvest treefarm
12186
		print(thanks)
12187
		os.sleep(2)
12188
		menu.colourPrint("Harvesting treefarm starting", colors.lime)
12189
		retValue = harvestTreeFarm(R)
12190
	elseif R.choice == 25 then	-- Build wall / fence
12191
		utils.checkFuelNeeded(R.width * R.length * 2)
12192
		local quantity = math.ceil((R.width + R.length) * 2.3)
12193
		T:checkInventoryForItem({"wall", "fence"}, {quantity, quantity})
12194
		if R.torchInterval > 0 then
12195
			T:checkInventoryForItem({"minecraft:torch"}, {math.floor(quantity / R.torchInterval)}, false)
12196
		end
12197
		if R.data == "barrel" then
12198
			T:checkInventoryForItem({"barrel"}, {4}, false)
12199
		end
12200
		R.useBlockType = T:getMostItem("", false) -- no excluded blocks, any block type
12201
		menu.colourPrint("Creating "..R.width.." x "..R.length.." walled enclosure", colors.yellow)
12202
		menu.colourPrint("Using: "..R.useBlockType, colors.orange)
12203
		retValue = createWallOrFence(R)
12204
	elseif R.choice == 26 then	-- clear natural forest
12205
		T:checkInventoryForItem({"minecraft:chest"}, {1})
12206
		T:checkInventoryForItem({"sapling"}, {64}, false)
12207
		menu.colourPrint("Clearing and replanting trees", colors.lime)
12208
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12209
		retValue = clearAndReplantTrees()
12210
	end
12211
	return retValue
12212
end
12213
12214
local function getTaskInventoryTo70(R)
12215
	local retValue = {}
12216
	local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n"
12217
	-- FARMING
12218
	if R.choice == 31 then	-- Create modular farm
12219
		utils.checkFuelNeeded(300)
12220
		T:checkInventoryForItem({"cobble"}, {64})
12221
		T:checkInventoryForItem({"dirt"}, {128}, false)
12222
		T:checkInventoryForItem({"water_bucket"}, {4})
12223
		T:checkInventoryForItem({"chest", "barrel"}, {5,5})
12224
		T:checkInventoryForItem({"sapling"}, {1})
12225
		R.useBlockType = T:getMostItem("dirt", true) -- exclude dirt from count
12226
		print(thanks)
12227
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12228
		print("Creating modular farm with "..R.useBlockType)
12229
		retValue = createFarm(R, false)
12230
	elseif R.choice == 32 then	-- Extend modular farm
12231
		utils.checkFuelNeeded(300)
12232
		T:checkInventoryForItem({"cobble"}, {64})
12233
		T:checkInventoryForItem({"dirt"}, {128}, false)
12234
		T:checkInventoryForItem({"water_bucket"}, {4})
12235-
				"2 water buckets","192 fence","8 signs","3 ladder","2 soul sand"}						-- build endermen observation tower
12235+
		T:checkInventoryForItem({"chest", "barrel"}, {5,5})
12236-
	text[67] = {"24 blocks of any type"}																-- Cover Trial spawners to prevent mobs escaping
12236+
12237
		T:checkInventoryForItem({"crafting"}, {1}) -- will be placed inside barrel / chest next to water source
12238
		R.useBlockType = T:getMostItem("dirt", true) -- exclude dirt from count
12239
		menu.colourPrint("Checking position...\n", colors.green)
12240
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12241
		retValue = createFarmExtension(R) -- subChoice = 1 for ahead, 2 for to the right
12242
	elseif R.choice == 33 then	-- manage modular farm
12243
		-- inventory checked in function depending on option taken
12244
		R.data = "farm"
12245
		retValue = manageFarmSetup(R)
12246
	elseif R.choice == 34 then	-- build single fence
12247
		utils.checkFuelNeeded(R.length)
12248
		T:checkInventoryForItem({"wall", "fence"}, {R.length, R.length})
12249
		if R.torchInterval > 0 then
12250
			T:checkInventoryForItem({"minecraft:torch"}, {math.ceil(R.length / R.torchInterval)}, false)
12251
		end
12252
		R.useBlockType = T:getMostItem("minecraft:torch") -- exclude torch
12253
		menu.colourPrint("Creating "..R.length.." wall or fence", colors.green)
12254
		menu.colourPrint("Using: "..R.useBlockType, colors.orange)
12255
		retValue = createWallOrFence(R) -- barrels not included in R.data, R.width = 0 so only single length
12256
	elseif R.choice == 35 then	-- build fence
12257
		utils.checkFuelNeeded(R.width * R.length * 2)
12258
		local quantity = math.ceil((R.width + R.length) * 2.3)
12259
		T:checkInventoryForItem({"wall", "fence"}, {quantity, quantity})
12260
		if R.torchInterval > 0 then
12261
			T:checkInventoryForItem({"minecraft:torch"}, {math.floor(quantity / R.torchInterval)}, false)
12262
		end
12263
		R.useBlockType = T:getMostItem("minecraft:torch") -- exclude torch
12264
		menu.colourPrint("Creating "..R.width.." x "..R.length.." walled enclosure", colors.green)
12265
		menu.colourPrint("Using: "..R.useBlockType, colors.orange)
12266
		retValue = createWallOrFence(R) -- barrels not included in R.data
12267
	-- OBSIDIAN
12268
	elseif R.choice == 41 then --harvest obsidian
12269
		utils.checkFuelNeeded(R.width * R.length * 3)
12270
		T:checkInventoryForItem({"stone"}, {R.width * R.length})
12271
		T:checkInventoryForItem({"minecraft:bucket", "minecraft:lava_bucket"}, {1, 1}, false, "Get extra fuel as well!")
12272
		menu.colourPrint("Harvesting obsidian area: size "..R.width.. " x "..R.length, colors.orange)
12273
		sleep(2)
12274
		retValue = harvestObsidian(R)
12275
	elseif R.choice == 42 then --build nether portal
12276
		utils.checkFuelNeeded(R.length * R.height * R.width)	-- length = width when facing standard = 5 high 4 length 1 width
12277
		T:checkInventoryForItem({"minecraft:obsidian"}, {((R.length - 2 + R.height - 2) * R.width * 2)})
12278
		T:checkInventoryForItem({"stone"}, {R.width * 4})
12279
		R.useBlockType = T:getMostItem("obsidian", true) -- exclude obsidian from count
12280
		menu.colourPrint("Building Nether portal", colors.orange)
12281
		sleep(2)
12282
		retValue = createPortal(R)
12283
	elseif R.choice == 43 then --demolish nether portal
12284
		utils.checkFuelNeeded(20)
12285
		print("Demolishing Nether portal")
12286
		retValue = demolishPortal(R)
12287
	elseif R.choice == 44 then -- Strip mine Netherite
12288
		utils.checkFuelNeeded(R.length * 2)
12289
		T:checkInventoryForItem({"stone"}, {R.length * 4})
12290
		R.useBlockType = T:getMostItem("", true) -- exclude none, use stone only/netherrack
12291
		T:checkInventoryForItem({"cobble"}, {math.floor(R.length / 16) * 4}, true, "For marking Chunk boundaries")
12292
		T:checkInventoryForItem({"minecraft:bucket", "minecraft:lava_bucket"}, {1, 1})
12293
		T:checkInventoryForItem({"minecraft:torch"}, {math.floor(R.length / 16)}, false)
12294
		retValue = createStripMine(R)
12295
	elseif R.choice == 45 then --undermine dragon towers
12296
		utils.checkFuelNeeded(500)
12297
		T:checkInventoryForItem({"minecraft:cobblestone", "minecraft:cobbled_deepslate"}, {84, 84})
12298
		print("Undermining dragon towers")
12299
		retValue = undermineDragonTowers()
12300
	elseif R.choice == 46 then --deactivate dragon tower
12301
		utils.checkFuelNeeded(50)
12302
		print("Deactivating dragon tower")
12303
		retValue = deactivateDragonTower()
12304
	elseif R.choice == 47 then --build dragon water trap
12305
		utils.checkFuelNeeded(256)
12306
		T:checkInventoryForItem({"stone"}, {356})
12307
		T:checkInventoryForItem({"minecraft:obsidian"}, {1})
12308
		T:checkInventoryForItem({"minecraft:ladder"}, {145})
12309
		T:checkInventoryForItem({"minecraft:water_bucket"}, {1})
12310
		print("Building dragon water trap")
12311
		retValue = createDragonTrap()
12312
	elseif R.choice == 48 then --build portal minecart station
12313
		utils.checkFuelNeeded(200)
12314
		menu.colourPrint("Inventory after height measurement", colors.red)
12315
		menu.colourPrint("Enter to start measurement.", colors.lime)
12316
		read()
12317
		print("Building portal platform")
12318
		retValue = createPortalPlatform()
12319
	elseif R.choice == 49 then -- shulker harvesting
12320
		retValue = harvestShulkers(R)
12321
		
12322
	-- CANAL BRIDGE
12323
	elseif R.choice == 51 then	-- continuous path over void/water/lava
12324
		utils.checkFuelNeeded(R.length) -- allow for R.length
12325
		if R.data ~= "reduce" then
12326
			T:checkInventoryForItem({"stone"}, {R.length}, false)
12327
			if R.torchInterval > 0 then
12328
				T:checkInventoryForItem({"minecraft:torch"}, {math.floor(R.length/R.torchInterval)}, false)
12329
			end
12330
			print("Building continuous path")
12331
		end
12332
		retValue = utils.createPath(R) -- returns {numBlocks}
12333
	elseif R.choice == 52 then	-- simple 2 block corridor
12334
		utils.checkFuelNeeded(R.length)
12335
		T:checkInventoryForItem({"stone"}, {R.length * 2}, false)
12336
		if R.torchInterval > 0 then
12337
			T:checkInventoryForItem({"minecraft:torch"}, {math.ceil(R.length / R.torchInterval)}, false)
12338
		end
12339
		print(thanks)
12340
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12341
		print("Building simple corridor")
12342
		retValue = createCorridor(R)
12343
	elseif R.choice == 53 then	-- canal management
12344
		local torches = 0
12345
		local length = R.length
12346
		if length > 0 then
12347
			utils.checkFuelNeeded(length * 4) -- allow for 1024 R.length
12348
			if R.torchInterval > 0 then
12349
				torches = math.floor(length / R.torchInterval)
12350
			end
12351
		else
12352
			utils.checkFuelNeeded(2048) -- allow for 1024 R.length
12353
			length = 256
12354
		end
12355
		T:checkInventoryForItem({"stone"}, {length})
12356
		R.useBlockType = T:getMostItem("", true) 
12357
		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
12358
			T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
12359
		end
12360
		if torches > 0 then
12361
			T:checkInventoryForItem({"minecraft:torch"}, {torches}, false)
12362
		end
12363
		retValue = createWaterCanal(R)
12364
	elseif R.choice == 54 then	-- ice canal
12365
		local default = R.length
12366
		if R.length > 0 then
12367
			utils.checkFuelNeeded(R.length)
12368
		else
12369
			default = 64
12370
			utils.checkFuelNeeded(default * 2) -- allow for 128 min R.length
12371
		end
12372
		--[[
12373
			new canal
12374
			1 = left towpath- move to centre left
12375
			2 = centre left ice or hollow
12376
			3 = centre right ice or hollow
12377
			4 = right side - move to centre right
12378
			convert water canal
12379
			5 = left towpath
12380
			6 = centre left ice or air
12381
			7 = centre right ice or air
12382
			8 = right towpath
12383
		]]
12384
		if R.subChoice <= 5 or R.subChoice == 8 then	-- towpath
12385
			T:checkInventoryForItem({"slab"}, {default}, true, "Add slabs to length required")
12386
		end
12387
		if R.torchInterval > 0 then
12388
			--checkInventoryForItem(items, quantities, required, message)
12389
			T:checkInventoryForItem({"stone"}, {math.ceil(default / R.torchInterval)}, true, "NOT bricks!")
12390
			R.useBlockType = T:getMostItem("", true) 
12391
			T:checkInventoryForItem({"torch"}, {math.ceil(default / R.torchInterval)}, false)
12392
		end
12393
		if R.data == "ice" then	-- ice canal with 2 spaces above
12394
			T:checkInventoryForItem({"minecraft:packed_ice", "minecraft:blue_ice"}, {math.ceil(R.length / 2), math.ceil(R.length / 2)}, false)
12395
		end
12396
		print(thanks)
12397
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12398
		print("Building ice canal")
12399
		retValue = createIceCanal(R)
12400
	elseif R.choice == 55 then -- platform
12401
		local volume = R.width * R.length
12402
		utils.checkFuelNeeded(volume)
12403
		T:checkInventoryForItem({"stone", "dirt"}, {volume, volume})
12404
		R.useBlockType = T:getMostItem("", true) 
12405
		print(thanks)
12406
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12407
		print("Building platform")
12408
		retValue = createPlatform(R)
12409
	elseif R.choice == 56 then -- sinking platform
12410
		local volume = (R.width + 1) * (R.length + 1) 
12411
		utils.checkFuelNeeded(volume * (R.height + 1))
12412
		T:checkInventoryForItem({"stone"}, {volume + ((R.length * 2) + (R.width * 2) * R.height) + 1})
12413
		print(thanks)
12414
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12415
		print("Building sinking platform")
12416
		retValue = createSinkingPlatform(R)
12417
	elseif R.choice == 57 then -- boat bubble lift
12418
		utils.checkFuelNeeded(R.height * 20)
12419
		T:checkInventoryForItem({"minecraft:bucket","minecraft:water_bucket"}, {2, 2})
12420
		T:checkInventoryForItem({"stone"}, {R.height * 10})
12421
		T:checkInventoryForItem({"gate"}, {R.height * 2})
12422
		T:checkInventoryForItem({"minecraft:soul_sand"}, {R.height * 2 + 2})
12423
		print(thanks)
12424
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12425
		print("Building boat bubble lift")
12426
		retValue = createBoatLift(R)
12427
		--retValue = createBoatLift(R) -- R.subChoice:0=new, R.subChoice:1=extend, R.length:0=left, 1=right
12428
		
12429
	-- MOB SPAWNER
12430
	elseif R.choice == 61 then	--  9x9 hollow cube cobble lined
12431
		utils.checkFuelNeeded(600) -- allow for 600 moves
12432
		T:checkInventoryForItem({"slab","stone"}, {1, 3}, true, "Slab can be crafted from 3 stone")
12433
		if T:getItemSlot("stone") > 0 and T:getItemSlot("slab") == 0 then -- no slabs, but is stone
12434
			local craftOK, message = T:craft("slab")
12435
		end
12436
		if R.data == "chest" then
12437
			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)
12438
			read()
12439
		else
12440
			T:checkInventoryForItem({"stone"}, {512}, false, "Full cube uses ~700 blocks\nEstimate your requirements")
12441
		end
12442
		print(thanks)
12443
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12444
		retValue = createMobFarmCube(R) -- R.data = "spawner" or "chest": not blaze
12445
	elseif R.choice == 62 then	-- Blaze spawner
12446
		utils.checkFuelNeeded(2500) -- allow for 2500 moves
12447
		if R.data == "blaze" then
12448
			T:checkInventoryForItem({"slab"}, {122}, true)
12449
			T:checkInventoryForItem({"stone"}, {576})
12450
			print("You will be asked for more assets later")
12451
			print("Enter to continue")
12452
			read()
12453
		end	 -- else R.data == "restart"
12454
		retValue = createMobFarmCube(R)	--R.data = "blaze" or R.data = "restart"
12455
	elseif R.choice == 63 then	--  flood mob spawner
12456
		utils.checkFuelNeeded(60) -- allow for 60 moves
12457
		T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
12458
		if R.subChoice == 1 then
12459
			T:checkInventoryForItem({"fence"}, {2})
12460
			T:checkInventoryForItem({"sign"}, {2})
12461
			T:checkInventoryForItem({"slab"}, {1})
12462
			T:checkInventoryForItem({"minecraft:soul_sand", "minecraft:dirt"}, {1, 1}, true)
12463
		end
12464
		print(thanks)
12465
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12466
		retValue = floodMobFarm(R)
12467
	elseif R.choice == 64 then -- build bubble lift on top of soul sand
12468
		utils.checkFuelNeeded(200) -- allow for 200 moves
12469
		T:checkInventoryForItem({"slab","stone"}, {6, 3}, true, "Slabs can be crafted from 3 stone")
12470
		if T:getItemSlot("stone") > 0 and T:getItemSlot("slab") == 0 then -- no slabs, but is stone
12471
			local craftOK, message = T:craft("slab")
12472
		end
12473
		T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
12474
		T:checkInventoryForItem({"stone"}, {256})
12475
		if T:getBlockType("down") ~= "minecraft:soul_sand" then
12476
			T:checkInventoryForItem({"minecraft:soul_sand"}, {1})
12477
		end
12478
		T:checkInventoryForItem({"hopper"}, {1}, false)
12479
		if T:getItemSlot("hopper") > 0 then
12480
			T:checkInventoryForItem({"chest"}, {2})
12481
		end
12482
		print(thanks)
12483
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12484
		retValue = createMobBubbleLift(R)
12485
	elseif R.choice == 65 then -- computercraft mob grinder
12486
		utils.checkFuelNeeded(1000) -- allow for 1000 moves
12487
		T:checkInventoryForItem({"stone"}, {256}) -- for ceiling, walls and floor of area
12488
		R.useBlockType = T:getMostItem("", true) -- stone only, no exclusions
12489
		print(thanks)
12490
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12491
		retValue = createMobGrinder(R)
12492
	elseif R.choice == 66 then -- build endermen tower
12493
		-- build in 3 sections, base, tower, top
12494
		getTaskHelp(2, 66) -- compulsory help display
12495
		read() -- pause until user ready
12496
		local numFuel = 700
12497
		local choices = 
12498
		{
12499
			"New tower lower base",
12500
			"Add tower upper base + killzone",
12501
			"128 block tower to existing base"
12502
		}
12503
		pp.itemColours = {colors.lime, colors.orange, colors.green}
12504
		local option, modifier = menu.menu("Select build stage:", choices, pp)
12505
		if option == 1 then --lower base
12506
			T:checkInventoryForItem({"minecraft:chest"}, {1})
12507
			T:place("chest", -1, "down", false)
12508
			T:emptyInventory("up")
12509
			utils.checkFuelNeeded(320) -- allow for 320 moves
12510
			T:checkInventoryForItem({"stone"}, {144}) -- <3 stacks
12511
			T:checkInventoryForItem({"minecraft:water_bucket"}, {2})
12512
			T:checkInventoryForItem({"fence"}, {4})
12513
			T:checkInventoryForItem({"sign"}, {4})
12514
			T:checkInventoryForItem({"door"}, {2})
12515
			T:checkInventoryForItem({"minecraft:soul_sand"}, {1})
12516
		elseif option == 2 then -- upper base
12517
			utils.checkFuelNeeded(710) -- allow for 703 moves
12518
			T:checkInventoryForItem({"stone"}, {384}) -- 6 stacks
12519
			T:checkInventoryForItem({"minecraft:bucket"}, {4})
12520
			T:checkInventoryForItem({"fence"}, {15})
12521
			T:checkInventoryForItem({"sign"}, {4})
12522
			T:checkInventoryForItem({"ladder"}, {3})
12523
			T:checkInventoryForItem({"minecraft:soul_sand"}, {1})
12524
		else -- main tower
12525
			utils.checkFuelNeeded(3000) -- allow for 3000 moves
12526
			if T:getBlockType("down") ~= "minecraft:chest" then
12527
				T:checkInventoryForItem({"minecraft:chest"}, {1})
12528
				T:place("chest", -1, "down", false)
12529
			end
12530
			T:checkInventoryForItem({"stone"}, {768}) -- 12 stacks
12531
			T:checkInventoryForItem({"minecraft:bucket"}, {10})
12532
			T:checkInventoryForItem({"fence"}, {64})	-- 1 stacks		
12533
		end
12534
		print(thanks)
12535
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
12536
		retValue = createEnderTower(option) -- 1, 2, or 3
12537
	end
12538
	return retValue
12539
end
12540
12541
local function getTaskInventory(R)
12542
	-- run this loop 2x per second to check if player has put anything in the inventory
12543
	-- fuel 1 coal = 60 = 4 planks. 64 planks = 16 coal = 960 units
12544
	local retValue = {}
12545
	local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n"
12546
	
12547
	if R.choice < 31 then 
12548-
[[~yellow~New, extend left/back=~red~^ ~orange~Extend Right=^
12548+
12549-
~lightGray~|*|~blue~ | | | | | | ~brown~|D| |D| ~blue~| | ~lightGray~|*|
12549+
12550-
~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | | | | | | | ~lightGray~|*|
12550+
12551-
~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | ~brown~|D| |D| ~blue~| | ~lightGray~|*|
12551+
12552-
~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
12552+
12553-
~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
12553+
12554-
~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
12554+
12555-
~lightGray~|~red~^~lightGray~|*|*|*|*|*|*~magenta~|M|~lightGray~*|*|*|*|*|*|~orange~^|
12555+
12556-
~lime~4 ~brown~double trees~green~ or 16 ~brown~single trees
12556+
12557-
~brown~D = Dirt, ~magenta~M = Modem
12557+
12558-
~red~^~yellow~ = Turtle ~red~(new/left/back) ~orange~^ on right
12558+
12559
			end
12560
			print(thanks)
12561-
[[~yellow~Place me on ground as below ~lightGray~^ ~magenta~^
12561+
12562-
~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| |
12562+
12563-
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | | | | | |
12563+
12564-
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | ~brown~|D| |D| |
12564+
12565-
~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | |
12565+
12566-
~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | |
12566+
12567-
~lime~|*|*|*|*|~lightGray~^~lime~|*| ~magenta~|^| ~green~or |*|*|*|*|~lightGray~^~green~|*|*~magenta~|^|
12567+
12568-
~lime~ 4 ~brown~double trees~green~   or  16 ~brown~single trees
12568+
12569-
~brown~D = dirt
12569+
12570-
~lightGray~^ = Turtle on marker (Legacy storage)
12570+
12571-
~magenta~^ = Turtle on Modem (Network storage)
12571+
12572
			retValue = clearWall(R)
12573
		elseif R.choice == 74 then --Clear single R.height perimeter wall
12574
			utils.checkFuelNeeded((R.width + R.length) * 2)
12575
			print("Recycling wall section "..R.width.." x "..R.length)
12576
			retValue = clearPerimeter(R)
12577
		elseif R.choice == 75 then --Clear hollow structure
12578
			utils.checkFuelNeeded((R.width * R.length) + ((R.width + R.length) * R.height))
12579
			print("Recycling hollow object "..R.width.." x "..R.length.." height: "..R.height)
12580
			retValue = clearBuilding(R)
12581
		elseif R.choice == 76 then --Clear solid structure / extend water pool
12582
			utils.checkFuelNeeded((R.width * R.length) + ((R.width + R.length) * R.height))
12583
			print("Recycling solid object w:"..R.width..", l:"..R.length..", h:"..R.height)
12584
			retValue = clearSolid(R)
12585
		elseif R.choice == 77 then	-- Dig trench
12586
			utils.checkFuelNeeded(R.height * R.length * 2)
12587
			print(thanks)
12588
			os.sleep(2)    -- pause for 2 secs to allow time to press esc
12589
			if R.length == 0 then
12590
				print("Digging continuous trench "..R.height.." blocks deep")
12591
			else
12592
				print("Digging trench "..R.length.." blocks long, "..R.height.." blocks deep")
12593
			end
12594
			retValue = digTrench(R)
12595
		elseif R.choice == 78 then --Carve mountain
12596
			utils.checkFuelNeeded(R.length * R.width * 10)
12597
			print("Carving mountain side "..R.width.." x "..R.length)
12598
			retValue = clearMountainSide(R)
12599
		elseif R.choice == 79 then -- Place floor or Ceiling
12600
			local blocks = R.width * R.length
12601
			utils.checkFuelNeeded(blocks)
12602
			T:checkInventoryForItem({"stone", "log", "planks"}, {blocks, blocks, blocks}, false)
12603
			R.useBlockType = T:getMostItem()
12604-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
12604+
12605-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12605+
12606-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12606+
12607-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | 
12607+
12608-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
12608+
12609-
~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~brown~B = Barrel or Chest
12609+
12610-
~brown~|B|~blue~W~green~| | |~lightGray~or ~magenta~|M|~blue~W~green~| | ~blue~W = Water
12610+
12611-
~lime~|~red~^~lime~|~brown~B|B|~lightGray~*|or ~brown~|~red~^~brown~|~magenta~M|~lightGray~*| ~red~^ = Turtle
12611+
12612-
~brown~Legacy   ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12
12612+
12613
				T:checkInventoryForItem({"sand", "gravel"}, {1024, 1024}, false)
12614
				if R.length == 0 then
12615-
[[~yellow~Place on any ~brown~T ~blue~T ~magenta~T~yellow~ facing < > ^ v
12615+
12616
				else
12617-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
12617+
12618-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12618+
12619-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12619+
12620-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
12620+
12621-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest
12621+
12622-
~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~blue~W = Water
12622+
12623-
~brown~|B~blue~|T| ~green~| |~lightGray~or ~magenta~|M|~blue~T~green~| | ~orange~S = Sapling or Tree
12623+
12624-
~orange~|S|~brown~T|B|~lightGray~*|or ~brown~|B~magenta~|T|~lightGray~*| ~brown~T ~lightGray~= Turtle (~blue~T ~magenta~T~lightGray~)
12624+
12625-
~brown~Legacy   ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12
12625+
12626
				utils.checkFuelNeeded(200)
12627
				if R.length == 0 then
12628-
[[~yellow~Place as below ~blue~T~yellow~ facing < > ^ v
12628+
12629
				else
12630-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
12630+
12631-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12631+
12632-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12632+
12633-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
12633+
12634-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest
12634+
12635-
~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | C = Crop (first)
12635+
12636-
~brown~|B|~blue~T~green~|C| |~lightGray~or ~magenta~|M|~blue~T~green~|C| ~orange~S = Sapling or Tree
12636+
12637-
~orange~|S|~brown~B|B|~lightGray~*|or ~magenta~|M|~brown~B|~lightGray~*| ~blue~T = Turtle on Water
12637+
12638
		
12639
		elseif R.choice == 82 then --build containing wall in water or lava
12640
			utils.checkFuelNeeded(R.length * R.length)
12641
			local depth = R.height
12642
			if depth == 0 then
12643
				depth = 20
12644
			end
12645
			T:checkInventoryForItem({"stone"}, {R.length * depth}, false)
12646
			print("Building retaining wall in lava/water. length "..R.length)
12647
			retValue = createRetainingWall(R)			
12648
		elseif R.choice == 83 then -- create a rectangle path in water/lava
12649
			utils.checkFuelNeeded(200)
12650
			createRectanglePath(R)
12651
		elseif  R.choice == 84 then -- Delete water/lava
12652
			if R.width == 0 then
12653
				utils.checkFuelNeeded(2000)
12654
				T:checkInventoryForItem({"stone"}, {256}, false)
12655
				print("Deleting water using auto-detection")
12656
			else
12657
				if R.height == 0 then
12658
					utils.checkFuelNeeded(2000)
12659
					T:checkInventoryForItem({"stone"}, {256}, false)
12660
				else
12661
					utils.checkFuelNeeded(R.width * R.length * R.height)
12662
					T:checkInventoryForItem({"stone"}, {math.max(R.length, R.width) * 2}, false)
12663
				end
12664
				print("Deleting enclosed water "..R.width.." x "..R.length.." x ".. R.height)
12665
			end
12666
			retValue = utils.drainWaterLava(R)
12667
		elseif  R.choice == 85 then -- Sinking platform
12668
			local volume = (R.width + 1) * (R.length + 1) 
12669
			utils.checkFuelNeeded(volume * (R.height + 1))
12670
			T:checkInventoryForItem({"stone"}, {volume + ((R.length * 2) + (R.width * 2) * R.height) + 1})
12671
			print(thanks)
12672
			os.sleep(2)    -- pause for 2 secs to allow time to press esc
12673
			print("Building sinking platform")
12674
			retValue = createSinkingPlatform(R)
12675
		elseif R.choice == 86 then -- ocean monument utilities
12676
			if R.subChoice == 1 then	-- Build 4 corner marker columns
12677
				--R.useBlockType = "prismarine", R.data = "oceanMonumentColumns"
12678
				T:checkInventoryForItem({"stone"}, {448})
12679
				retValue = oceanMonumentColumns(R)
12680
			elseif R.subChoice == 2 then	-- Retaining wall beween 2 columns
12681
				T:checkInventoryForItem({"stone"}, {1024})
12682
				retValue = createRetainingWall(R)
12683
			elseif R.subChoice == 3 then	-- Clear plants pre sand draining
12684
				retValue = clearWaterPlants(R)
12685
			elseif R.subChoice == 4 then	-- Use sand draining
12686
				utils.checkFuelNeeded(100)
12687
				T:checkInventoryForItem({"sand", "gravel"}, {1024, 1024}, false)
12688
				if R.length == 0 then
12689
					print("Building sand wall. Auto length: ")
12690
				else
12691
					print("Building sand wall. length: "..R.length)
12692
				end
12693
				retValue = createSandWall(R)
12694
			elseif R.subChoice == 5 then	-- remove sand wall
12695
				utils.checkFuelNeeded(200)
12696
				print("Digging sand from ocean monument")
12697
				retValue = clearSandWall(R)
12698
			elseif R.subChoice == 6 then	-- Drain and remove structure
12699
				T:checkInventoryForItem({"stone"}, {1024})
12700
				retValue = utils.drainWaterLava(R)
12701
			end
12702
		elseif R.choice == 87 then --ladder to water/lava
12703
			utils.checkFuelNeeded(R.height * 2)
12704
			T:checkInventoryForItem({"minecraft:ladder"}, {R.height}, true, "Add more to be safe!")
12705
			local cobble = R.height * 3 + 10
12706
			T:checkInventoryForItem({"stone"}, {cobble})
12707
			print(thanks)
12708
			os.sleep(2)    -- pause for 2 secs to allow time to press esc
12709
			print("Creating ladder to bedrock")
12710
			retValue = createLadderToWater()
12711
		elseif R.choice == 88 then --remove plants
12712
			utils.checkFuelNeeded(R.length * R.width * 4)
12713
			T:checkInventoryForItem({"sand", "stone"}, {64, 64})
12714
			local width = R.width
12715
			local length = R.length
12716
			if width == 0 then
12717
				width = "auto"
12718
			end
12719
			if length == 0 then
12720
				length = "auto"
12721
			end
12722
			print("Removing water plants. length: "..length.." width: "..width)
12723
			retValue = clearWaterPlants(R)
12724
		elseif R.choice == 89 then -- convert flowing water to source
12725
			--utils.checkFuelNeeded(R.length * R.width * 4) -- unknown as size not calculated
12726
			T:checkInventoryForItem({"water_bucket", "bucket"}, {12, 12})
12727
			T:checkInventoryForItem({"slab"}, {128})
12728
			print("Converting water to source "..R.width.." x "..R.length.." x ".. R.height)
12729
			retValue = convertWater(R)
12730
		elseif R.choice == 810 then -- create sloping water
12731
			utils.checkFuelNeeded(R.length * R.width * 3)
12732
			local buckets = math.floor(R.length / 2) + 1
12733
			T:checkInventoryForItem({"water_bucket", "bucket"}, {buckets, buckets})
12734
			T:checkInventoryForItem({"slab"}, {R.length * R.width})
12735
			print("Creating sloping water field "..R.width.." x "..R.length.." x ".. R.height)
12736
			retValue = createSlopingWater(R)
12737
		-- BUILDING & RAILWAY
12738
		elseif R.choice == 91 then -- Build a wall
12739
			local blocks = R.height * R.length 
12740
			utils.checkFuelNeeded(blocks)
12741
			T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks})
12742
			R.useBlockType = T:getMostItem()
12743
			print("Building a wall using "..R.useBlockType)
12744
			sleep(2)
12745
			retValue = buildWall(R)
12746
		elseif R.choice == 92 then -- Build a rectangular structure
12747
			local blocks = (R.height * R.length * 2) + (R.height * R.width * 2)
12748
			utils.checkFuelNeeded(blocks)
12749
			T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks})
12750
			R.useBlockType = T:getMostItem()
12751
			print("Building a house using "..R.useBlockType)
12752
			sleep(2)
12753
			retValue = buildStructure(R)
12754
		elseif R.choice == 93 or R.choice == 94 then -- Build a gable end roof / pitched roof
12755
			local blocks = ((R.width + 2) * (R.length + 2))
12756
			utils.checkFuelNeeded(blocks)
12757
			if menu.getBoolean("Using stairs / planks for roof (y/n)", nil, colors.yellow) then
12758
				T:checkInventoryForItem({"planks", "stairs"}, {blocks, blocks})
12759
			else
12760
				T:checkInventoryForItem({"stone"}, {blocks})
12761
			end
12762
			
12763
			R.useBlockType = T:getMostItem()
12764
			if R.choice == 93 then 				-- Build a gableroof
12765
				if R.width % 2 == 1 then
12766
					T:checkInventoryForItem({"slab"}, {R.length + 2}, false, "Match slabs with roof blocks")
12767
				end
12768
				blocks = (R.width * 6)
12769
				T:checkInventoryForItem({"stone", "planks", "bricks"}, {blocks, blocks, blocks}, true, "Match gable with existing building")
12770
			else
12771
				local isWidthOdd, isLengthOdd, width, length = false, false, 0, 0
12772
				R, isWidthOdd, isLengthOdd, width, length = utils.getRoofStats(R)
12773
				if isWidthOdd then
12774
					T:checkInventoryForItem({"slab"}, {length - 2}, false, "Match slabs with roof blocks")
12775
				end
12776
			end
12777
			print("Building a roof using "..R.useBlockType)
12778
			sleep(2)
12779
			if R.choice == 93 then 				-- Build a gableroof
12780
				retValue = buildGableRoof(R)
12781
			else								-- Build a pitched roof
12782
				retValue = buildPitchedRoof(R)
12783
			end
12784
		elseif R.choice == 95 or R.choice == 96 then --place redstone torch level or downward slope
12785
			utils.checkFuelNeeded(10)
12786
			if R.choice == 95 then
12787
				R.data = "level"
12788
			else
12789
				R.data = "up"
12790
			end
12791
			T:checkInventoryForItem({"stone"}, {1})
12792
			R.useBlockType = T:getMostItem("", true)
12793
			T:checkInventoryForItem({"minecraft:redstone_torch"}, {1})
12794
			print("Placing redstone torch on ".. R.useBlockType)
12795
			retValue = placeRedstoneTorch(R)
12796
		elseif R.choice == 97 or R.choice == 98 then --build downward/upward slope
12797
			local blocks = R.height * 2
12798
			if R.height == 0 then
12799
				blocks = 64
12800
			end
12801
			utils.checkFuelNeeded(blocks)
12802
			T:checkInventoryForItem({"stone"}, {blocks})
12803
			print("Building slope")
12804
			sleep(2)
12805
			retValue = createRailway(R)
12806
		elseif R.choice == 101 or R.choice == 102 or R.choice == 103 or R.choice == 104 then -- measure height/depth/length
12807
			retValue = measure(R)
12808
		elseif R.choice == 105 then--Borehole
12809
			retValue = createBorehole(R)
12810
		end
12811
	end
12812
	return retValue
12813
end
12814
12815
local function test(R)
12816
	local lib = {}
12817
	
12818
	function lib.dig(direction, bypass, slot)
12819
		direction = direction or "forward"
12820
		slot = slot or 1
12821
		bypass = bypass or true
12822
		
12823
		print("direction: "..direction)
12824
		print("bypass: "..tostring(bypass))
12825
		print("slot: "..slot)
12826
		
12827
	end
12828
	lib.dig("down")
12829
	read()
12830
end
12831
12832
local function main()
12833
	local lib = {}
12834
	
12835
	function lib.checkLabel()
12836
		if os.getComputerLabel() == nil then
12837
			os.setComputerLabel("toolkit")
12838
			print("Computer label set to "..os.getComputerLabel())
12839
		end
12840
	end
12841
	
12842
	function lib.checkLibs(libDir, filename)
12843
		local fileExists = false
12844
		if fs.exists(libDir) then
12845
			if not fs.isDir(libDir) then
12846
				fs.move(libDir, libDir.."Renamed")
12847
				fs.makeDir(libDir)
12848
			end
12849
		else
12850
			fs.makeDir(libDir)
12851
		end
12852
		if fs.exists(fs.combine(libDir, filename)) or fs.exists(fs.combine(libDir, filename..".lua")) then
12853
			fileExists = true
12854
		end
12855
		return fileExists
12856
	end
12857
	
12858
	local doContinue = true
12859
	lib.checkLabel() -- make sure turtle label is set
12860
	--check if lib folder exists
12861
	if not lib.checkLibs("lib", "clsTurtle") then
12862
		-- use pastebin get to download clsTurtle to libs folder
12863
		print("Missing clsTurtle.lua in libs directory")
12864
		print("Attempting to obtain from Pastebin...")
12865
		if shell.run("pastebin","get","tvfj90gK","lib/clsTurtle.lua") then
12866
			print("clsTurtle.lua installed from Pastebin")
12867
		else
12868
			print("failed to install clsTurtle.lua from Pastebin")
12869
			doContinue = false
12870
		end
12871
	end
12872
	if not lib.checkLibs("lib", "menu") then
12873
		-- use pastebin get to download menu.lua to libs folder
12874
		print("Missing menu.lua in libs directory")
12875
		print("Attempting to obtain from Pastebin...")
12876
		if shell.run("pastebin","get","BhjbYsw4","lib/menu.lua") then
12877
			print("menu.lua installed from Pastebin")
12878
		else
12879
			print("failed to install menu.lua from Pastebin")
12880
			doContinue = false
12881
		end
12882
	end
12883
	if doContinue then
12884
		local result = {}
12885
		local R =
12886
		{
12887
			choice = 0,
12888
			subChoice = 0,
12889
			size = 0,
12890
			width = 0,
12891
			length = 0,
12892
			height = 0,
12893
			depth = 0,
12894
			up = false,
12895
			down = false,
12896
			silent = false,
12897
			data = "",
12898
			torchInterval = 0,
12899
			useBlockType = "",
12900
			auto = false,
12901
			side = ""
12902
		}
12903
		menu = require("lib.menu")
12904
		T = require("lib.clsTurtle").new(false) -- true enables logfile to log.txt note dot NOT colon
12905
		T:clear()
12906
		doContinue = false	-- reset
12907
		if args[1] ~= nil then
12908
			if args[1]:sub(1,1) == "h" then
12909
local help =
12910
[[... = any following characters
12911
12912
tk v...     = mc/ccTweaked versions
12913
tk log      = enable logging
12914
tk log d... = enable logging + debug
12915
tk find     = writes locate.txt 
12916
tk test     = runs test(R)
12917
tk farm     = runs manageFarm(R)
12918
12919
12920
12921
Enter to exit]]
12922
				menu.colourPrint(help, colours.yellow)
12923
				read()
12924
			elseif args[1] == "log" then
12925
				if args[2] ~= nil then
12926
					if args[2]:sub(1,1) == "d" then
12927
						dbug = true	-- set dbug flag
12928
						menu.colourPrint("Logging and debugging enabled", colors.lime)
12929
					end
12930
				else
12931
					menu.colourPrint("Logging enabled", colors.lime)
12932
				end
12933
				if T:getLogExists() then
12934
					if menu.getBoolean("Delete existing log file? (y/n)", 3, colors.orange) then
12935
						T:deleteLog()
12936
						menu.colourPrint("Log file deleted", colors.yellow)
12937
					end
12938
				end
12939
				T:setUseLog(true)
12940
				doContinue = true
12941
				if dbug then
12942
					menu.colourPrint("Enter to continue...", colors.lightBlue)
12943
					read()
12944
				end
12945
			elseif args[1] == "farm" then
12946
				R.silent = true
12947
				R.data = "farm"
12948
				R.auto = true
12949
				manageFarm(R)
12950
			--elseif args[1] == "tree" then
12951
				--manageTreeFarm() -- use file to read status
12952
			elseif args[1] == "find" then
12953
				-- missing turtle: player used 'tk find'
12954
				T:setUseLog(true)
12955
				T:setLogFileName("locate.txt")
12956
				T:appendLine("Booting succeeded")
12957
				T:appendLine("Block ahead: "..T:getBlockType("forward"))
12958
				T:appendLine("Block above: "..T:getBlockType("up"))
12959
				T:appendLine("Block below: "..T:getBlockType("down"))
12960
			elseif args[1] == "test" then
12961
				test(R)
12962
			elseif args[1]:find("v") ~= nil then
12963
				print("_HOST:")
12964
				print()
12965
				print(_HOST)
12966
				print()
12967
				print("Minecraft major version: "..mcMajorVersion)
12968
				print("Minecraft minor version: "..mcMinorVersion)
12969
				print("ccTweaked major version: "..ccMajorVersion)
12970
				print("ccTweaked minor version: "..ccMinorVersion)
12971
				print("tk version:              "..tkVersion)
12972
				print("clsTurtle version:       "..version)
12973
				print("\nEnter to exit")
12974
				read()
12975
			end
12976
		else
12977
			doContinue = true
12978
		end
12979
		if doContinue then
12980
			print("Minecraft major version: "..mcMajorVersion)
12981
			print("Bedrock level: "..bedrock)
12982
			if T:getUseLog() then
12983
				if T:saveToLog("Started with logging enabled", true) then
12984
					menu.colourPrint("\nEnter to continue...", colors.lightBlue)
12985
					read()
12986
				end
12987
			else
12988
				print("Logging disabled")
12989
			end	
12990
			sleep(1)
12991
			while R.choice == 0 do
12992
				R = chooseTask(R)
12993
			end
12994
			if R.choice > 0 then
12995
				R = getTask(R)
12996
				if R.data ~= "quit" then
12997
					result = getTaskInventory(R) -- table of comments
12998
				end
12999
			end
13000
		end
13001
		T:clear()
13002
		table.insert(result, "Thank you for using 'survival toolkit'")
13003
		local clr = {colors.yellow, colors.orange, colors.green, colors.lightBlue}
13004
		local count = 1
13005
		for _, value in ipairs(result) do
13006
			--print(value)
13007
			--.print(text, fg, bg, width)
13008-
	info.sub[67] = 
13008+
13009-
[[Turtle moves toward spawner
13009+
13010-
Place at spawner level.
13010+
13011
				count = 1
13012-
Can be behind a wall for protection
13012+
13013-
of player.
13013+
13014
	else
13015-
Embeds in wall with attack working
13015+
13016
	end
13017-
Needs 24 blocks
13017+
13018
13019-
]] -- Build 3*3*3 wall around trial spawner
13019+