View difference between Paste ID: C1nGR1dA and UFvjc1bw
SHOW: | | - or go back to the newest paste.
1-
version = 20250410.0800
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-
		T:go("L1C1B1")
4471+
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-
			if T:getBlockType("forward"):find("sign") ~= nil then
4485+
4486-
				T:up(1)	
4486+
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:dig("down")
4511
			end
4512-
				T:place("stone", "up")
4512+
4513
	end
4514
	
4515
	function lib.initialise(R)
4516
		if R.subChoice == 1 or R.subChoice == 4 then		
4517-
	function lib.fillBuckets(withSort)
4517+
4518-
		local emptyBuckets = T:getItemCount("minecraft:bucket")
4518+
4519
				T:go(oTurn.."1F1D1"..R.side.."2")			-- move right/left forward, down onto ice canal top, face canal wall
4520-
			if T:getWater("down") then
4520+
4521-
				sleep(0.5)
4521+
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-
		return T:getItemCount("minecraft:water_bucket")
4525+
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-
		T:place(dirt, "forward", false) 					-- placed at end of potential water source, next to ladder
4601+
4602
		local numBlocks, errorMsg = 0, ""
4603-
		T:place(dirt, "down", false) 						-- placed in ground, next to ladder
4603+
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-
	--lib.fillBuckets(R.height, true)							-- fill as many buckets as required or until inventory full, sort inventory as well
4614+
4615-
	lib.fillBuckets(true)							-- fill as many buckets as required or until inventory full, sort inventory as well
4615+
4616
		end
4617
		-- if user requested shelter create chamber at this level
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-
		T:go("L1C1 R1C1 R1C1 L1", false, 0, true)		-- prepare layer 1
4633+
4634
	-- go down to water/lava with alternaate solid/open layers
4635-
		T:go("U1F1 R1F1 L1C1 R1C1 R1C1 L1", false, 0, true)	-- prepare layer 2
4635+
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("soul_sand", "down", false)
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
end
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-
			T:place("stone", "forward", false)
4772+
4773
	end
4774
	
4775-
			T:place("stone", "forward", false)
4775+
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
				end
4785
				if j < 11 then
4786
					T:forward(1)
4787
					T:go("R2C1L2", false, 0, false)
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-
						T:place("minecraft:torch", "down")
4801+
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
							place = true
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-
		T:place("minecraft:ladder", "down")
4901+
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-
	T:place("minecraft:obsidian", "down")
4909+
4910
				T:turnRight(1)
4911
			else
4912
				T:turnLeft(1)
4913
			end
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
			else
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-
		T:place("fence", "down", false)
5010+
5011
						end
5012-
		T:place(preferredBlock, "down", false)
5012+
5013
					found, position = lib.isSpawner() -- true/false, top/bottom/nil
5014-
		T:place(preferredBlock, "down", false)
5014+
5015
						T:go("R2F"..moves + 2 .."R2")
5016-
		T:place(preferredBlock, "down", false)
5016+
5017
				end
5018
			end
5019
		end
5020-
		T:place(preferredBlock, "down", false)
5020+
5021
		return found, position
5022-
		T:place(preferredBlock, "down", false)
5022+
5023
	
5024
	
5025
	if not continue then -- new mob cube either dungeon or blaze
5026-
		T:place("sign", "forward", false, message)
5026+
5027
		-- determine spawner position level 4, move to top of spawner (level 6)
5028
		print("Checking if already at spawner")
5029
		local found, position = lib.isSpawner() -- already on spawner?
5030
		if blaze then 
5031
			if not found then -- away from spawner
5032
				if R.subChoice == 3 then
5033
					T:go("U5")
5034
				end
5035
				found, position = lib.findSpawner(blaze)
5036
			end
5037
		else -- go to bottom of dungeon and empty chests
5038
			if not found then --outside dungeon
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-
					T:place(preferredBlock, "down", false)
5083+
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
			if blaze then
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-
			if not T:place("fence", "down", false) then-- first side
5107+
5108-
				T:place(preferredBlock, "down", false)
5108+
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
				-- ends with turtle facing spawner, in front of exit hole				
5120
			end
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-
		T:place("minecraft:soul_sand", "down", false) -- over block 1 of water source
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
		read()
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-
				T:place("door", "forward", false)
5156+
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:place(preferredBlock, "down", false)
5163+
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
		os.sleep(2)    -- pause for 2 secs to allow time to press esc
5169
		-- place upper floor and slabs under it
5170-
				T:place("door", "forward", false)
5170+
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
		lib.ceiling(true)						-- true uses slabs
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:go("F8 R1")
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-
		T:place("fence", "down", false)							-- fence centre of bottom side layer 22
5208+
5209
end
5210
5211-
		T:place("ladder", "forward", false)
5211+
5212
	--[[Part 2 / 3 Mob Spawner Farm turtle on floor, pointing towards water source wall, single hole]]
5213-
		T:place("ladder", "forward", false)
5213+
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
		if addWater then
5221
			T:placeWater("down") 			 			-- place water down
5222-
		T:place("minecraft:soul_sand", "down", false) 
5222+
5223
		T:turnLeft(2)									-- turn round
5224
		while turtle.forward() do
5225
			width = width + 1 
5226
		end			-- go forward 7
5227-
		T:place("ladder", "down", false)
5227+
5228
			T:placeWater("down") 						-- place water					
5229-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
5229+
5230
		T:go("L2F".. math.floor(width / 2) .."L1")		-- turn round, go forward 3 (centre of wall), turn left
5231
	end
5232-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
5232+
5233
	function lib.digFloor()
5234
		T:go("x2F1 x2")									-- first block, move forward
5235-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
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
		
5240-
		T:place("sign", "forward", false, "UP\n^\n|\n|")
5240+
5241
		utils.goBack(1)
5242
		T:go("x2 F1x2 F1x2 F1x2 F1x2 L1F1")				-- go left to right dig 5 blocks, forward on right side
5243
		
5244
		T:turnLeft(1)									-- left turn, go back into right side, facing left
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
		
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
	
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:place("fence", "up", false)
5272+
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:go("D1F1 L1F8")
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-
local function createFarmNetworkStorage(R, withStorage, removeLegacy)
5304+
			if not T:place("minecraft:soul_sand", -1, "down", false) then
5305-
	removeLegacy = removeLegacy or false
5305+
5306-
	-- new or converted farm will have:
5306+
5307-
	-- 2 modems, 1 barrel per plot
5307+
5308-
	-- primary plot and storage needs 1 modem, 1 barrel, 8 chests
5308+
5309
		blockType = T:getBlockType("forward")
5310
		local turns = 0
5311-
	function lib.createBasement(R, up, down, width, length)
5311+
5312-
		-- start facing lower left
5312+
5313-
		R.up = up
5313+
5314-
		R.down = down
5314+
5315-
		R.width = width
5315+
5316-
		R.length = length
5316+
5317-
		clearRectangle(R)	-- dig 10 x 10 x 2 area, return to starting position
5317+
5318-
		-- add network cable, modems and chests
5318+
5319
		return {""}
5320
	end
5321-
	function lib.placeNetwork(count, pattern)
5321+
5322
	function lib.createWaterSource(oTurn)
5323-
			T:place("computercraft:cable", "up", true)
5323+
5324-
			if i < count then
5324+
5325-
				T:go(pattern)
5325+
5326
			T:go("C2 L1C1 R2C1 L1")
5327
			if i < 3 then
5328
				T:go("F1x0")
5329
			end
5330-
	-- called when starting at lower left side of plot, facing crops
5330+
5331-
	if removeLegacy then
5331+
5332
		T:placeWater("forward")
5333-
		while turtle.suckDown() do end
5333+
5334-
		--T:dig("down", false)	-- do not bypass chests
5334+
5335-
		turtle.digDown()
5335+
5336-
		T:place("dirt", "down")
5336+
5337-
		T:go("R2F1")
5337+
5338-
		while turtle.suck() do end
5338+
5339-
		T:go("F1L1 F1U1 R2")	-- remove barrel/wall or double chest. face tree
5339+
5340-
		T:place("stone", "down")
5340+
5341
		sleep(0.1)
5342-
		T:place("modem", "down")
5342+
5343-
		-- could be tree/sapling in front
5343+
5344
	
5345-
		if T:getBlockType("down") == "minecraft:dirt" then
5345+
5346-
			T:place("barrel", "down")
5346+
5347-
			T:go("U1x0")
5347+
5348-
			T:place("dirt", "up")
5348+
5349-
			T:go("B1U2")
5349+
5350-
			if T:getBlockType("forward"):find("log") ~= nil then
5350+
			T:place("chest", 0, "down")
5351-
				T:place("sapling", "forward")
5351+
5352
			T:dig("down")
5353-
			T:go("D3F1 R1F1")
5353+
			T:place("chest", 0, "down")
5354
			T:go(turn.."1")
5355-
			T:place("barrel", "down")
5355+
5356
			T:go("D1x1")
5357
			T:place("hopper", 0, "forward")
5358-
		while turtle.suckDown() do end
5358+
5359-
		T:place("modem", "down")
5359+
5360-
		network.attachModem()
5360+
5361-
		T:go("F1x2 R2C2 F1L1 F1D1")
5361+
5362
	function lib.up()
5363-
	T:go("L1D3") -- move below crop field, face N
5363+
5364-
	lib.createBasement(R, true, true, 10, 10)	-- ends facing N below water source
5364+
5365-
	T:go("U1 F9R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8R1 F1R2 C1R2 F8") -- facing W below water source
5365+
5366-
	T:go("F1 R2C1 R1 F1L1 x0x2")	-- move to corner, face along front edge
5366+
5367-
	for c = 1, 4 do
5367+
5368-
		if c == 1 then
5368+
5369-
			lib.placeNetwork(12, "F1x0x2")
5369+
5370
	end
5371-
			lib.placeNetwork(11, "F1x0x2")
5371+
5372
	function lib.createChamber()
5373-
		if c < 4 then
5373+
5374-
			T:go("L1F1 x0x2 L1C1R1")
5374+
5375
		D.length = 7
5376
		D.height = 4
5377-
	-- now in bottom left facing S
5377+
5378-
	T:go("L2F1R1")	-- under modem/netwok cable facing in
5378+
5379-
	for i = 1, 3 do
5379+
5380-
		T:go("L1C1 R1C1 R1C1 L1D1")
5380+
5381-
		T:place("computercraft:cable", "up", true)
5381+
5382
5383-
	T:go("C1L1 C1L1 C1L1 C1L1 D1L1")-- ready for clearing rectangle up/down
5383+
5384-
	T:place("computercraft:cable", "up", true)
5384+
5385
	
5386-
	T:place("computercraft:cable", "up", true)
5386+
5387-
	lib.createBasement(R, true, true, 11, 11)
5387+
5388
			T:go("F1C0C2 R1C1 R1C1 R1C1 R1C1")
5389-
	lib.placeNetwork(11, "F1")
5389+
5390-
	T:go("R2F4 R1")
5390+
5391-
	lib.placeNetwork(11, "F1")
5391+
5392-
	T:go("L1F5 L1F9 R1D1 C1")	-- ready to make ladder column
5392+
5393
		end
5394-
		if i < 5 then
5394+
5395-
			T:go("U1C1")
5395+
5396
	local turn = "R"
5397
	local oTurn = "L"
5398
	if R.subChoice == 1 then
5399-
		T:place("ladder", "down")
5399+
5400
		oTurn = "R"
5401-
	if withStorage then
5401+
5402-
		T:go("R1F4 R1F3 D1x2")
5402+
5403-
		T:place("computercraft:cable", "down", true) --ready to build chest storage area
5403+
5404
	if data[1] ~= "" then
5405-
		utils.createStorage()
5405+
5406-
		T:go("U1R1 F5R1 F5U1 C2U1 R2")	-- end on plot starting position, facing crops
5406+
5407
	lib.createWaterSource(oTurn)			-- everything in place, build a water source, facing spawner
5408-
		T:go("U1F2 L1F1 U1C2 U1L1")	-- end on plot starting position, facing crops
5408+
5409
		T:go(turn.."1C1"..turn.."1C1"..turn.."1x1"..turn.."1U1", false, 0, true)
5410
	end
5411-
	return "Farm converted to network storage"
5411+
5412
	local colHeight = 19
5413
	for i = 1, colHeight do		-- tunnel up, filling 3 sides
5414
		T:go(turn.."1C1"..turn.."1C1"..turn.."1x1"..turn.."1C1 U1", false, 0, true)
5415
	end
5416-
	-- extend "right" or "forward". only adds a single new farm.
5416+
5417
	T:go("C0"..turn.."2C1"..turn.."1F1 C0C1"..turn.."1C1"..turn.."2C1"..oTurn.."1", false, 0, true) -- fill top of column
5418
	
5419
	lib.mobTransporter()
5420
	T:go("x2x0 F1x2x0 F1x2x0 R2") -- over water source
5421
	-- now create bubble column
5422
	T:down(colHeight + 2)
5423
	local moves = 0
5424
	repeat
5425
		lib.goToWater(moves)	-- get water
5426
		moves = lib.up()
5427
		T:go("F1")
5428
		T:placeWater("forward")
5429
		T:go("U1C2")
5430
		T:placeWater("forward")
5431-
				T:place("dirt", "forward", false)
5431+
5432
		T:go("C1")
5433-
				--if not T:place("minecraft:crafting_table", "forward", false) then
5433+
5434-
				if T:place(storage, "forward", false) then
5434+
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:place("dirt", "forward", false) -- dirt if no storage available
5439+
5440
	utils.goBack(7)			-- over down shaft
5441
	T:down(1)				-- start shaft, facing bubble column
5442-
				T:place(R.useBlockType, "forward", false)
5442+
5443
		-- tunnel down, filling all 4 sides
5444
		T:go("R1C1 R1C1 R1C1 R1C1 D1", false, 0, true)
5445
	end
5446
	lib.createChamber()
5447-
		T:placeWater("down")	-- ends facing same direction as started, over water source
5447+
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
		if i == 6 then
5452
			T:go(oTurn.."1")
5453
		end
5454-
				T:place("dirt", "down", false)
5454+
5455
		T:go("C1")
5456
	end
5457
	
5458
	T:go("D2F2"..turn.."1F5")
5459
	T:placeWater("forward")
5460
	T:go(turn.."1F1"..oTurn.."1") -- facing down mob channel floor
5461
	for i = 1, 5 do
5462-
				T:place("dirt", "down", false)
5462+
5463
		utils.goBack(1)
5464
	end
5465
	T:go("C1"..turn.."1F1"..turn.."1F1")
5466
	for i = 1, 7 do
5467
		T:go("C2x0")
5468
		if i < 7 then
5469-
		if not T:place(storage, "down", false) then-- place barrel/chest below
5469+
5470-
			T:place(storageBackup, "down", false) -- place chest below
5470+
5471
	end
5472
	T:go("U3R2")
5473
	for i = 1, 7 do
5474
		T:go("F1x2")
5475-
	-- current position if extend == nil is on ground/farm level facing N
5475+
5476-
	-- if extend = "right", "front" above water source facing crops
5476+
5477-
	local numPlots = 0
5477+
5478
	lib.placeCollector(turn, oTurn) -- if hopper / chests present
5479
	
5480
	return {}
5481
end
5482
5483-
			T:forward(11)
5483+
5484-
			numPlots = numPlots + 1
5484+
5485-
		until not utils.isStorage("down") -- on top of chest, barrel or modem
5485+
5486-
		T:go("R1F1R2")	-- move to front right corner of last plot on right side
5486+
5487-
		--T:go("R1U1 F1L1 F10L1") -- move to front right corner
5487+
5488
			T:go("x2C2", false, 0, false, R.useBlockType)
5489
			if R.up then
5490
				T:dig("up")
5491
			end
5492-
			T:forward(11)
5492+
5493-
			numPlots = numPlots + 1
5493+
5494-
		until not utils.isStorage("down") -- on top of chest, barrel or modem
5494+
5495-
		T:go("L1F1 R1x2")	-- could dig tree or sapling + block below
5495+
5496-
		--T:go("L2U1 F1R1 F10")
5496+
5497-
	elseif extend == "convertWithStorage" then
5497+
5498-
		-- convert normal (storage) primary plot farm to networked storage
5498+
5499-
		--T:turnLeft(1)	-- over water source, facing N
5499+
5500-
		local response = createFarmNetworkStorage(R, true, true)
5500+
5501-
		return {response}
5501+
5502-
	elseif extend == "convert" or extend == "convertWithStorage" then
5502+
5503-
		-- convert normal (storage) extended farm to networked storage
5503+
5504-
		--T:turnLeft(1)	-- over water source, facing N
5504+
5505-
		createFarmNetworkStorage(R, false, true)
5505+
5506-
		return {"Farm converted to network storage"}
5506+
5507-
	else -- new farm.
5507+
5508-
		T:up(1) -- assume on the ground, go up 1
5508+
5509
			end
5510
		end
5511-
	-- design change: sapling placed 2 blocks above corner for ease of walking round
5511+
5512-
	if R.networkFarm then	-- barrel on corner of plot, modems on each side N/E
5512+
5513-
		T:place("barrel", "down", false)
5513+
5514
end
5515-
		T:place(R.useBlockType, "down", false)
5515+
5516
local function createPortal(R) -- 42
5517-
	-- stage 2 place sapling
5517+
5518
	R.length = length of portal NOT width default 4
5519-
	T:place("dirt", "down")
5519+
5520-
	T:up(1)
5520+
5521-
	T:place("sapling", "down") -- plant sapling
5521+
5522-
	T:go("F1D4")
5522+
5523-
	if R.networkFarm then
5523+
5524-
		T:place("modem", "down", false)
5524+
5525-
		network.attachModem()
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 double barrel/chest
5529+
5530
		for i = 1, R.length - 2 do -- R.length = 4: place when i=1,2
5531
			T:place("minecraft:obsidian", 0, "down", false)
5532-
		T:go("R1F1L1")
5532+
5533
		end
5534
		T:go("C2", false, 0, false, R.useBlockType)
5535
	end
5536
	
5537
	function lib.buildLayer()
5538
		T:place("minecraft:obsidian", 0, "down", false)
5539
		for i = 1, R.length - 1 do -- R.length = 4: forward when i=1,2,3
5540-
			T:go("F1 x0x2C 2", false, 0, false, R.useBlockType)
5540+
5541
		end
5542
		T:place("minecraft:obsidian", 0, "down", false)
5543
	end
5544
	
5545-
	lib.placeDirt(9, false) 	-- place dirt back to start
5545+
5546-
	if R.networkFarm then	-- water source next to modem
5546+
5547-
		lib.addWaterSource(R, {"c","c","d","d"}, storage)
5547+
5548-
		-- T:go(path, useTorch, torchInterval, leaveExisting, preferredBlock
5548+
5549-
		T:go("U1F1L1")
5549+
5550-
		T:place("modem", "down", false)
5550+
5551-
		T:go("F1C2 L1F1 D1", false, 0, false, R.useBlockType)
5551+
5552
	for width = 1, R.width do
5553-
		lib.addWaterSource(R, {"c","c","t","d"}, storage)  -- put barrel / chest in floor
5553+
5554-
		T:go("U1F1R2")
5554+
5555-
		if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
5555+
5556-
			lib.placeStorage(storage, storageBackup)
5556+
5557
			lib.buildLayer()
5558-
		T:go("R1F1L1")
5558+
5559-
		if T:getBlockType("down"):find(storage) == nil and T:getBlockType("down"):find(storageBackup) == nil then
5559+
5560-
			lib.placeStorage(storage, storageBackup)
5560+
5561
		lib.buildBase()
5562-
		T:go("F1D1")
5562+
5563
			T:go("R2F"..R.length - 1)
5564
		end
5565
		if width < R.width then
5566
			T:go("R1F1D"..R.height.."R1")
5567-
		T:go("F1U1x0C2"..turn.."1F1"..turn.."1x0 x2C2 F1D1", false, 0, false, R.useBlockType)
5567+
5568
		else
5569
			T:go("L1F"..R.width.."D"..R.height - 1 .."R2")
5570
			if R.data ~= "bury" then
5571
				T:down(1)
5572
			end
5573
		end
5574
	end
5575
	
5576-
	lib.addWaterSource(R, {"d","c","c","d"}, storage)	-- bottom right
5576+
5577
end
5578-
	lib.addWaterSource(R, {"c","c","d","d"}, storage)	-- top right, facing away from plot
5578+
5579-
	T:go("F1U1 R1C2 x0F1 x0x2 C2R1", false, 0, false, R.useBlockType)
5579+
5580-
	for i = 1, 11 do	-- build right wall from top of plot to bottom
5580+
5581
	local lib ={}
5582
	
5583-
	T:go("R1F10")				-- ends on top of front storage/ modem facing tree
5583+
5584-
	if R.networkFarm then		-- network storage
5584+
5585-
		network.attachModem()
5585+
5586-
		T:go("R1F1D1R1")	-- over water source, facing E (crops)
5586+
5587-
		if extend == "" then	-- primary plot
5587+
5588-
			createFarmNetworkStorage(R, true)
5588+
5589
				break
5590-
			createFarmNetworkStorage(R, false)
5590+
5591
		end
5592
		if found then
5593
			-- are we under the centre block, or one of the sides?
5594
			if turtle.detect() then -- under a side
5595-
		utils.goBack(numPlots * 11)
5595+
5596
			else	-- nothing in front, probably under centre, or facing wrong direction so check
5597
				for i = 1, 4 do
5598-
		T:go("R1U1F".. numPlots * 11 .."D1L1")
5598+
5599
					if turtle.detect() then
5600
						onSide = true
5601
						break
5602
					end
5603
				end
5604
			end
5605
			if onSide then-- move to centre
5606
				T:go("D1F1")
5607-
	--T:setUseLog(true, "farmCreateLog.txt", true)
5607+
5608-
	--dbug = true	-- set dbug flag
5608+
5609-
	--utils.waitForInput("Logging and debugging enabled")	--utils.waitForInput(message)
5609+
5610
		while turtle.down() do
5611
			height = height + 1
5612
		end
5613
		return found, height
5614
	end
5615
	
5616-
	R = utils.checkFarmPosition(R)
5616+
5617
		for i = 1, length do
5618-
	if not R.ready then
5618+
5619-
		return {"Unable to determine starting position"}
5619+
5620
			else
5621
				T:go("C2", false, 0, true)
5622-
	createFarm(R, extend)
5622+
5623
		end
5624
	end
5625
	
5626
	function lib.buildLadder(height)
5627
		for i = 1, height do
5628
			--T:go("F1C1 R1C1 L2C1 L1F1L2", false, 0, true)
5629
			T:go("F1C1 R1C1 L2C1 R1", false, 0, true)
5630
			utils.goBack(1)
5631
			if i > 3 then
5632-
	R.data == "random" for random floor placement
5632+
5633
			end
5634
			T:place("minecraft:ladder", 0, "forward", true)
5635
			T:up(1)
5636
		end
5637-
	function lib.goToRemote(R)
5637+
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
		T:checkInventoryForItem({"stone"},{height * 4 + 18})
5645
		T:checkInventoryForItem({"trapdoor"},{1})
5646
		lib.buildLadder(height) -- ends facing ladder, 1 block above
5647
		
5648
		T:go("R1")
5649
		utils.goBack(1)
5650
		T:go("C2F1 C2F1 C2F1 C2")
5651
		T:go("R1F1R1")
5652
		T:go("C2F1 C2F1 C2F1 C2")
5653
		utils.goBack(2)
5654-
			return "Measured depth/height of "..depth.." > setting: "..R.height
5654+
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-
	function lib.checkPosition(R)
5660+
5661-
		-- check if block above/below
5661+
5662-
		local blockBelow = turtle.detectDown()
5662+
5663-
		local blockAbove = turtle.detectUp()
5663+
5664-
		if R.subChoice == 2 then -- New floor over existing
5664+
	--[[Build steps up or down ready for railtrack]]
5665-
			-- if no block below, assume in correct position and continue
5665+
5666-
			-- else move up 1 and continue
5666+
5667-
			if blockBelow then T:up(1) end
5667+
5668-
		elseif R.subChoice == 4 then -- New ceiling under existing
5668+
5669-
			-- if no block above, assume in correct position and continue
5669+
5670-
			-- else move down 1 and continue
5670+
5671-
			if blockAbove then T:down(1) end
5671+
5672
					T:go("C2", false, 0, true)
5673
				end
5674
			end
5675-
	function lib.placeRow(R, direction, waterPresent)
5675+
5676
			for i = 1, R.height - 1 do
5677
				T:go("U1x0 D1x1 F1x0x1 D1x1 C2", false, 0, false)
5678
			end
5679
		end
5680
	elseif R.up then
5681
		for i = 1, R.height do
5682
			T:go("C1U2 x0D1F1", false, 0, false) --put stone in front, up 2 excavate 1, down 1, forward 1
5683-
			R = lib.getRandomBlock(R)	-- changes block randomly ONLY if R.data == "random"
5683+
5684-
			R = lib.changeCheckered(R)	-- changes to next block type ONLY if R.data == "checked"
5684+
5685-
			-- ONLY if R.data == "striped" has already been changed for whole row
5685+
5686-
			T:place(R.inventory.useBlock, direction, false) -- leaveExisting = false
5686+
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-
		return waterPresent, R
5691+
5692
	local lib = {}
5693
	
5694-
	function lib.getRandomBlock(R)
5694+
5695-
		if R.data == "random" then
5695+
5696-
			local index = math.random(1, #R.inventory.names)	-- random index between 1 and no of block types
5696+
5697-
			local success = false
5697+
5698-
			for i = index, R.inventory.blockTypeCount do		-- iterate from index upwards
5698+
5699-
				if R.inventory.quantities[i] > 0 then			-- at least 1 block left
5699+
5700-
					R.inventory.useBlock = R.inventory.names[i]
5700+
5701-
					R.inventory.quantities[i] = R.inventory.quantities[i] - 1
5701+
5702-
					R.inventory.blockCount = R.inventory.blockCount - 1
5702+
5703-
					success = true
5703+
5704
	end
5705
	
5706
	function lib.back(R)
5707
		for i = 1, R.length do
5708-
			if not success then								-- no blocks left in the range of index -> no of block types
5708+
5709-
				for i = index, 1, -1 do						-- go backwards from index to 1
5709+
5710-
					if R.inventory.quantities[i] > 0 then		-- at least 1 block left
5710+
5711-
						R.inventory.useBlock = R.inventory.names[i]
5711+
5712-
						R.inventory.quantities[i] = R.inventory.quantities[i] - 1
5712+
5713-
						R.inventory.blockCount = R.inventory.blockCount - 1
5713+
5714-
						success = true
5714+
5715
	
5716
	function lib.right(R)
5717
		T:turnRight(R.length)
5718
	end
5719-
		end	
5719+
5720
	function lib.up(R)
5721-
		return R
5721+
5722
			T:go("U2R2 x1R2 D1C2", false, 0, true)
5723
		else
5724-
	function lib.changeStripe(R)
5724+
5725-
		if R.data == "striped" then
5725+
5726-
			R.size = R.size + 1
5726+
5727-
			if R.size > R.inventory.blockTypeCount then
5727+
5728-
				R.size = 1
5728+
5729
		T:go("D1C2", false, 0, true)
5730-
			R.inventory.useBlock = R.inventory.names[R.size]
5730+
5731
	
5732-
		return R
5732+
5733
		-- mimics direct commands using f.lua, r.lua etc with space between commands and number
5734
		local width = 0
5735-
	function lib.changeCheckered(R)
5735+
5736-
		--swap between 2 block types
5736+
5737-
		if R.data == "checked" then
5737+
5738-
			if R.inventory.useBlock == R.inventory.names[1] then
5738+
5739-
				R.inventory.useBlock = R.inventory.names[2]
5739+
5740
			"Back 1 block",
5741-
				R.inventory.useBlock = R.inventory.names[1]
5741+
5742
			"Turn Right",
5743
			"Turn Left",
5744-
		return R
5744+
5745
			"Down 1 block",
5746
			"Quit"
5747
		}
5748
		local choice, modifier
5749-
	if R.data == "random" then
5749+
5750-
		math.randomseed(R.inventory.blockCount)
5750+
5751-
		print("Using random blocks")
5751+
5752-
	elseif R.data == "striped" then
5752+
5753-
		print("Using striped pattern")
5753+
5754-
	elseif R.data == "checked" then
5754+
5755-
		print("Using checkered pattern")
5755+
5756
				-- getInteger(prompt, minValue, maxValue, row, fg, bg, default) 
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
				lib.back(R)
5762
			elseif choice == 4 then
5763-
		local message = lib.goToRemote(R)
5763+
5764-
		if message ~= "" then	-- error encountered
5764+
5765-
			return {message}
5765+
5766
				R.length = 1
5767
				lib.right(R)
5768
			elseif choice == 6 then
5769-
	lib.checkPosition(R)
5769+
5770-
	-- based on clearRectangle code
5770+
5771-
	if R.width == 1 then 					-- single block ahead only
5771+
5772-
		waterPresent, R = lib.placeRow(R, direction, waterPresent)
5772+
5773-
		T:turnRight(2)						-- turn at the top of the run
5773+
5774-
		T:forward(R.length - 1)				-- return to start
5774+
5775-
		T:turnRight(2)						-- turn round to original position
5775+
5776
		end
5777-
		local iterations = 0 				-- R.width = 2, 4, 6, 8 etc
5777+
5778-
		if R.width % 2 == 1 then  			-- R.width = 3, 5, 7, 9 eg R.width 7
5778+
5779-
			iterations = (R.width - 1) / 2 	-- iterations 1, 2, 3, 4 for widths 3, 5, 7, 9
5779+
5780
5781
direction + ~blue~number ~yellow~eg ~white~f2 ~yellow~= forward ~blue~2
5782
~lightGray~direction without number = ~blue~1
5783-
		R = lib.changeStripe(R)
5783+
5784-
		R = lib.changeCheckered(R)
5784+
5785-
		for i = 1, iterations do 			-- eg 3 blocks wide, iterations = 1
5785+
5786-
			waterPresent, R = lib.placeRow(R, direction, waterPresent)
5786+
5787
5788-
			R = lib.changeStripe(R)
5788+
5789-
			--R = lib.changeCheckered(R)
5789+
5790-
			waterPresent, R = lib.placeRow(R, direction, waterPresent)
5790+
5791
		local cmd = ""
5792
		while cmd ~= "q" do
5793
			local line = menu.clear()
5794-
				R = lib.changeStripe(R)
5794+
5795
			-- menu.getString(prompt, withTitle, minValue, maxValue, row, fg, bg, default) 
5796
			input = menu.getString("command ", false, 1, 5, line, colors.yellow, colors.black):lower()
5797
			-- remove spaces
5798
			input = input:gsub( " ", "")
5799-
			R = lib.changeStripe(R)
5799+
5800-
			waterPresent, R = lib.placeRow(R, direction, waterPresent)
5800+
5801
			if #input > 1 then
5802
				R.length = tonumber(input:sub(2))
5803
			end
5804
			if cmd == "q" then
5805
				return{"User has quit application"}
5806
			end
5807
			if cmd == "f" then
5808
				lib.forward(R)
5809
			elseif cmd == "b" then
5810
				lib.back(R)
5811
			elseif cmd == "l" then
5812
				lib.left(R)
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-
					T:place("torch", "forward")				-- place torch, move forward
5843+
5844
	end
5845
	
5846
	function lib.patchMissingBlock()
5847
		if turtle.back() then
5848
			T:go("C1")
5849
		else
5850-
				if not T:place("slab", "down") then			-- break if out of slabs
5850+
5851
		end
5852
	end
5853
	
5854
	function lib.placeSingle(height)
5855
		local y = 0
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
				place = utils.clearVegetation("down")
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-
				-- T:place(blockType, direction, leaveExisting, signText)
5886+
5887-
				if not T:place("stone", "forward", false) then
5887+
5888
			local place = utils.clearVegetation("down")
5889
			-- build back column
5890
			while place do -- loop will be entered at least once
5891-
				if T:getItemSlot("minecraft:torch") > 0 then
5891+
5892-
					T:place("torch", "forward", false)
5892+
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:go("F1") -- move under first column
5899-
				if not T:place("slab", "forward", false) then
5899+
5900
			turtle.back() -- back at starting point
5901
			T:go("C1", false, 0, true) 
5902
		end
5903
		-- return to surface, placing below
5904
		for i = 1, y do
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
		local y = 0
5912-
				if not T:place("stone", "forward", false) then
5912+
5913
			T:go("C1")
5914
		else
5915
			T:go("B1C1")
5916-
				if T:getItemSlot("minecraft:torch") > 0 then
5916+
5917-
					T:place("torch", "forward", false)
5917+
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
			T:go("C1R2C1", false, 0, true) --fill last block, then turn 180 to build opposite side
5925
			y = height
5926-
			T:place("ice", "down", true)
5926+
5927
			local place = utils.clearVegetation("down")
5928
			-- build back column
5929
			while place do -- loop will be entered at least once
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
			lib.checkFloor()
5939
			T:go("B1C1R2F1", false, 0, true) 
5940
			lib.checkFloor()
5941-
					if not T:place("ice", "down", true) then -- out of ice
5941+
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 R.data == "withPath" then
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 not T:place("ladder", "forward", false) then
6027+
6028
			 drop = drop + 1
6029
		else
6030
			isBedrock = true
6031
			break
6032-
			T:place("common", direction, false) -- any common block
6032+
6033
		if T:isWaterOrLava("up") ~= "" then
6034-
			T:place("minecraft:torch", direction, false)
6034+
6035
		end
6036
	end
6037
	if not isBedrock then -- not sitting on bedrock, so break foot level exit block
6038
		T:go("U1R2x1")
6039
	end
6040
	T:placeWater("down")
6041
	if isBedrock then
6042
		T:go("U1x1 U1x1")
6043
	else
6044
		T:go("U1x1")
6045
	end
6046
	T:up(drop - 2)
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-
		T:place("ladder", "up")
6109+
6110
			if l < R.length then
6111
				T:forward(1)
6112
			end
6113
		end
6114-
	T:place("ladder", "forward")
6114+
6115
			if outbound then
6116
				T:go("R1F1R1")
6117
			else
6118
				T:go("L1F1L1")
6119
			end
6120
			outbound = not outbound
6121
		end
6122
	end
6123
	if outbound then
6124
		T:go("L1F"..R.width - 1 .."L1")
6125
	else
6126
		T:go("R1F"..R.width - 1 .."R1")
6127
	end
6128
	T:go("U2")
6129
	
6130
	return {}
6131
end
6132
6133-
	T:place("minecraft:chest", "up", false)
6133+
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
	read()
6146
	while turtle.down()do
6147
		depth = depth + 1
6148-
	while T:getItemSlot("minecraft:torch") > 0 do
6148+
6149-
		turtle.select(T:getItemSlot("minecraft:torch"))
6149+
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
local function createSandWall(R) -- 81
6161
	local success = true
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-
					T:place("slab", "up", false)
6234+
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:go("L2C1 R2", false, 0, false) -- | |<| | to | |>|* | to | |<|*| 
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-
					T:place("slab", "up", false)
6256+
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
			end
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-
							T:place("slab", "up", false)
6276+
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
	return {}
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-
		-- T:place(blockType, direction, leaveExisting, signText)
6316+
6317
			blockType = T:isWaterOrLava("forward")
6318
			if blockType:find("lava") ~= nil or blockType:find("water") ~= nil then
6319-
				T:place(blockType, "down", false)
6319+
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
		local isFluid = lib.checkFluids()
6329
		local blockType = ""
6330
		local data = T:getStock("stairs")
6331
		if data.total == 0 then
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-
			T:place("chest", "forward", false)
6383+
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
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:place("slab", "down", true) 				-- place slab on top T:place(blockType, direction, leaveExisting)
6526+
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("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-
		T:place(brick, "up")
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-
			T:place("lava", "down")
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
	lib.placeCorners(R.length - 2, 2, R.useBlockType)
6640
	outward = lib.turn(outward)
6641-
		T:place("sign", true, "")
6641+
	lib.placeCorners(R.length - 2, 1, R.useBlockType)
6642
	if outward then
6643-
		T:place(brick, "up")
6643+
		T:go("R1F"..R.width - 9 .."R1")
6644
	else
6645
		T:go("L1F"..R.width - 9 .."L1")
6646
	end
6647-
			T:place(brick, "forward")
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-
		if not T:place("chest", "down") then
6653+
	outward = lib.turn(outward)
6654-
			T:place("barrel", "down")
6654+
	lib.placeCorners(R.length - 2, 4, R.useBlockType) -- should be back in starting corner facing front
6655
	
6656
	T:go("U1R1")
6657-
		T:place("hopper", "down")
6657+
	lib.placeWater(R.length - 3) -- place water down then move forward, turn right
6658
	lib.placeWater(R.width - 3)
6659-
		T:place("slab", "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
	
6666
	return {"Tree farm ready for planting"}
6667
end
6668
6669
local function createWallOrFence(R)
6670
	local lib = {}
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("fence", "down", false)
6723+
					T:place(R.useBlockType, 0, "forward")
6724
					blocks = blocks + 1 -- facing start
6725-
		T:place("fence", "down", false)
6725+
6726
					T:go("F1R2")
6727
					T:place(R.useBlockType, 0, "forward")
6728-
		T:place("sign", "down", false)
6728+
6729
				else -- cant go forward, go up instead
6730-
		T:place("slab", "up", false)
6730+
6731
						while turtle.detectUp() do -- will only run if block above
6732-
		T:place("sign", "forward", false)
6732+
6733
							blocks = blocks - 1
6734-
		if not T:place("minecraft:soul_sand", "down", false) then
6734+
6735-
			T:place("minecraft:dirt", "down", false)
6735+
6736
						T:place(R.useBlockType, 0, "down", true)
6737
						blockType = T:getBlockType("forward")
6738
					end
6739
					T:turnRight(2) -- facing start
6740
				end
6741
			end
6742
		end
6743
	end
6744
	
6745
	T:turnRight(2) --facing start position
6746
	if R.width == 0 then -- single fence
6747
		lib.buildWall(R, R.length)
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-
			if not T:place("minecraft:soul_sand", "down", false) then
6758+
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
		1 = left side, ground level (on towpath)
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:place("chest", "down")
6804+
6805
			end
6806
			T:go(R.side.."1")							-- *|V| | | to *|>| | | turn to face start 
6807-
			T:place("chest", "down")
6807+
6808
		end
6809
		T:go("C2", false, 0, false)
6810
	end
6811-
			T:place("hopper", "forward")
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
			oTurn = "L"
6817
		end
6818
		lib.newCanalSide(oTurn)								-- *|<| | | wall fixed. to -- *|^| | | 
6819
		lib.newCanalSide(oTurn)								-- *|^| | | wall fixed. to -- *|>| | | 
6820
		lib.newCanalBase(R)									-- *|>| | | base fixed
6821
		T:go("F1"..R.side.."1") 							-- *|>| | | to *| |>| | to *| |^| |
6822
		lib.newCanalSide(oTurn)								-- *| |^| | to *| |>| |
6823
		lib.newCanalBase(R)									-- *| |>| | base fixed
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-
		T:place("slab", "down")
6904+
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:go(R.side.."2") 							-- check if water behind	
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-
			T:place("minecraft:obsidian", "down", false)
6985+
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:place("minecraft:obsidian", "down", false)
6992+
6993
				end
6994
			else
6995
				T:forward(1) 								-- move forward to extend canal
6996-
		T:place("minecraft:obsidian", "down", false)
6996+
6997
				if isSource then							-- ? source ahead
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
							if R.side == "L" then			-- only left side repairs, so wait 1 second
7005
								sleep(1)
7006
								T:go("C1")					-- repair neighbouring canal base
7007
							end
7008
							T:go(R.side.."1")				-- face forward
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:place("minecraft:ladder", "forward", true)
7088+
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
					sourceCount = sourceCount + 1
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-
		T:place("trapdoor", "up", false)
7109+
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-
		Build steps up or down ready for railtrack
7119+
7120-
		R.depth = headroom, default 2
7120+
7121
				T:go(R.side.."1C1"..oTurn.."1", false, 0, true) -- face canal wall, replace with stone if empty, face forward										
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
								print("Out of water buckets")
7132
								sleep(1)
7133
							end
7134-
				--T:go("U1x0 D1x1 F1x0x1 D1x1 C2", false, 0, false)
7134+
7135-
				T:go("U"..R.depth - 1 .."x0 D"..R.depth - 1 .."x1 F1x0x1 D1x1 C2", false, 0, false)
7135+
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-
			--T:go("C1U2 x0D1F1", false, 0, false) --put stone in front, up 2 excavate 1, down 1, forward 1
7140+
7141-
			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
7141+
7142
		end
7143
	end
7144
		
7145
	local maxLength = 512
7146
	if R.length ~= 0 then
7147
		maxLength = R.length
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
	if R.data == 1 then -- 2 turtles
7153
		lib.side(R, maxLength - moves)	
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-
			T:place("slab", "down", false)
7539+
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
		-- while obsidian in front or below (previously entered tower) measure width and return to centre
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-
			--T:place("stone", "forward", false) -- place does not allow for specific blocktype
7921+
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
				lib.attack()
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-
				T:place("minecraft:torch", "down")
7962+
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
				outward = lib.turnRound(outward)
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-
	function lib.buildWallSection(section, useBlockType)
7994+
7995-
		-- build a layer 1 block high below turtle
7995+
7996-
		for i = 1, #section do
7996+
7997-
			local block = section:sub(i, i)
7997+
7998-
			if block == "l" then
7998+
7999-
				T:place("log", "down")
7999+
8000-
			elseif block == "m" then
8000+
8001-
				T:place("modem", "down")
8001+
8002-
			elseif block == "b" then
8002+
8003-
				T:place("barrel", "down")
8003+
8004-
			elseif block == "c" then
8004+
8005-
				T:place("cable", "down")
8005+
8006
		while not turtle.detectUp() do
8007-
				T:place(useBlockType, "down")
8007+
8008
			if success then
8009-
			if i < #section then
8009+
8010
			end
8011
			height = height + count
8012
		end
8013
		T:turnRight(2)
8014
		while not turtle.detectDown() do
8015
			if lib.approach("down", 64, true) then
8016
				lib.attack()
8017-
			while turtle.digUp() do end
8017+
8018-
			turtle.digDown()
8018+
8019-
			T:place(useBlockType, "down")
8019+
8020-
			--T:go("x0C2", false, 0, false, useBlockType)
8020+
8021
			turtle.forward()
8022-
				while not turtle.forward() do
8022+
8023-
					turtle.dig()
8023+
8024
			turtle.down()
8025-
				--T:forward(1)
8025+
8026
		T:turnRight(2)
8027
	end
8028
	
8029
	function lib.walls()
8030
		local doContinue = lib.checkPosition()
8031
		if doContinue then
8032
			T:go("F2R1 F2R2 D1x2")		-- on corner outside middle of wall, facing along its length, dig light rod	
8033
			for i = 1, 4 do
8034
				lib.clearWall()
8035
			end
8036
			T:go("F2L1 U1F2 R2")
8037
		else
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-
	function lib.findLegacyStart()
8058+
8059
			lib.walls()
8060-
		local block = T:getBlockType("down")
8060+
8061-
		if block:find("polished") ~= nil then
8061+
8062-
			return ""	-- in correct position, facing centre of front wall
8062+
8063
	if doContinue then
8064-
		-- assume on left corner
8064+
8065-
		T:forward (1)
8065+
8066-
		local couint = 0
8066+
8067-
		while (T:getBlockType("down")):find("polished") == nil do
8067+
8068
		lib.home(direction, moves)
8069
	end
8070-
			if count > 10 then
8070+
8071-
				return "Unable to locate polished block"
8071+
8072
end
8073
8074
local function manageFarm(R)
8075
	local lib = {}
8076
	
8077-
	function lib.floodFarm(R)
8077+
	function lib.checkEquipment()
8078
		--[[ Needs pickaxe and hoe equipped ]]
8079-
		T:sortInventory(false)
8079+
8080-
		for i = 1, R.width - 2 do
8080+
		--T:checkInventoryForItem(items{}, quantities{}, required, message)
8081-
			lib.placeFloor(R.length - 2, R.useBlockType)
8081+
8082-
			if i < R.width - 2 then
8082+
		local equippedRight, equippedLeft, inInventory = T:setEquipment() -- any tools equipped except diamond_pickaxe and crafting_table have been removed to inventory
8083-
				outward = lib.turn(outward)
8083+
		--[[if equippedRight ~= "minecraft:crafting_table" then
8084
			T:checkInventoryForItem({"minecraft:crafting_table"}, {1})
8085
			local equippedRight, equippedLeft = T:setEquipment()
8086-
		T:go("U1R2") -- over 13 x 13 internal area opposite corner
8086+
8087-
		-- now add corners
8087+
		T:suck("down")		-- if hoe already in storage get it out
8088-
		lib.placeCorners(R.length - 2, 4, R.useBlockType)
8088+
		if inInventory ~= "minecraft:diamond_hoe" then
8089-
		outward = lib.turn(outward)
8089+
			if T:getItemSlot("minecraft:diamond_hoe") > 0 then
8090-
		lib.placeCorners(R.length - 2, 3, R.useBlockType)
8090+
8091-
		outward = lib.turn(outward)
8091+
8092-
		lib.placeCorners(R.length - 2, 2, R.useBlockType)
8092+
				T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!")
8093-
		outward = lib.turn(outward)
8093+
8094-
		lib.placeCorners(R.length - 2, 1, R.useBlockType)
8094+
8095
		if T:getItemSlot("minecraft:diamond_hoe") > 0 then
8096-
			T:go("R1F"..R.width - 9 .."R1")
8096+
8097
		end
8098-
			T:go("L1F"..R.width - 9 .."L1")
8098+
8099
		return false
8100
	end
8101-
		lib.placeCorners(R.length - 2, 1, R.useBlockType)
8101+
8102-
		outward = lib.turn(outward)
8102+
8103-
		lib.placeCorners(R.length - 2, 2, R.useBlockType)
8103+
		--[[ first function called on start]]
8104-
		outward = lib.turn(outward)
8104+
		local atHome = false
8105-
		lib.placeCorners(R.length - 2, 3, R.useBlockType)
8105+
8106-
		outward = lib.turn(outward)
8106+
		print("Checking position "..blockType.. " below")
8107-
		lib.placeCorners(R.length - 2, 4, R.useBlockType) -- should be back in starting corner facing front
8107+
		if blockType:find("water") ~= nil then -- over water
8108
			if lib.isStorage("forward") then
8109-
		T:go("U1R1")
8109+
				atHome = true
8110-
		lib.placeWater(R.length - 3) -- place water down then move forward, turn right
8110+
8111-
		lib.placeWater(R.width - 3)
8111+
				if lib.isStorage("forward") then-- confirms in correct position, back to crops
8112-
		lib.placeWater(R.length - 3) 
8112+
8113-
		lib.placeWater(R.width - 3)
8113+
				else -- facing crafting table
8114-
		T:go("F".. math.floor((R.length - 2) / 2).."R1F".. math.floor((R.width - 2) / 2)) -- should be in centre
8114+
8115
				end
8116-
		--T:go("D6x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 F1x2 R1F7 R1U1")
8116+
			else -- not a chest: facing crops or crafting table
8117-
		T:go("D6F7 R1F7 R1U1") -- end facing back at left corner, 1 block above floor/1 below ceiling
8117+
8118
				if lib.isStorage("forward") then -- confirms was facing crops
8119
					atHome = true
8120-
	function lib.clearBasement()
8120+
					T:turnLeft(1)
8121-
		T:sortInventory(false)
8121+
8122-
		T:dropItem("seeds", "forward")
8122+
8123-
		T:dropItem("flint", "forward")
8123+
			-- should now be facing crops. may be crafting table to left
8124-
		clearRectangle({width = 15, length = 15, up = true, down = true})
8124+
8125-
		-- area has been cleared. starts facing back, 1 block above ground, 1 block below ceiling
8125+
		return atHome-- now facing crops
8126
	end
8127-
		for i = 1, 14 do	-- place cable into gutter beneath front of farm
8127+
8128-
			T:place("cable", "up")
8128+
	function lib.crossFarm()
8129-
			if i < 14 then
8129+
8130
		local blockType = ""
8131
		local isReady, cropType, status = lib.isCropReady("down")
8132
		-- will go forward until chest or cobble detected below
8133-
		-- ends right side facing right, just below ceiling
8133+
8134
		local numMoves = 0
8135
		local endOfPath = false
8136
		while not endOfPath do
8137
			blockType = T:getBlockType("down", -1)
8138
			if blockType == "" or cropType ~= "" then --crops or nothing below
8139-
	-- R.data = "new", "left", "right" or "back" to extend tree farm
8139+
8140
			elseif  blockType:find("barrel") ~= nil or blockType:find("chest") ~= nil or blockType:find("cobble") ~= nil then
8141-
	-- R.networkFarm to create storage area
8141+
8142
			end
8143
			numMoves = numMoves + 1
8144
		end
8145-
	-- R.data = "new", "left", "right", "back", "convertStorage", "convert"
8145+
		return blockType -- either chest or cobble
8146-
	if R.data == "new" then -- new treeFarm, Start at current position
8146+
8147-
		-- build 4 wall sections in 2 passes
8147+
8148
	function lib.farmInFront()
8149-
		lib.buildWallSection("---------------", R.useBlockType)		-- left wall (15 blocks)
8149+
8150-
		T:go("R1F1")
8150+
		T:go("U1L1F11D1R1")							-- on next farm, facing crops
8151
		local crop = lib.manageTree()				-- refuel, gather seeds and other crops
8152-
			lib.buildWallSection("--------------", R.useBlockType)	-- back/ right wall (14 blocks)
8152+
		local isFarmToRight, _ = lib.harvest(crop)	-- harvest field, store crops
8153
		return isFarmToRight
8154
	end
8155-
		lib.buildWallSection("------c------", R.useBlockType)		-- front wall (14 blocks) c = network cable
8155+
8156
	function lib.farmToRight()
8157-
		lib.buildWallSection("---------------", R.useBlockType)		-- left wall top (15 blocks)
8157+
8158-
		T:go("R1F1")
8158+
		T:go("U1F11 D1")				-- on next farm, facing crops
8159
		local crop = lib.manageTree()	-- refuel, gather seeds and other crops
8160-
			lib.buildWallSection("--------------", R.useBlockType)	--back/right wall (14 blocks)
8160+
		lib.harvest(crop)				-- harvest field, store crops
8161
	end
8162
	
8163-
		--lib.buildWallSection("-----lmb-----", R.useBlockType)	--front wall (14 blocks) log/modem/barrel
8163+
	function lib.getCrops()
8164-
		lib.buildWallSection("-----lmb", R.useBlockType)
8164+
8165
8166-
		network.attachModem()
8166+
		if lib.isStorage("forward") then
8167
			lib.getSeeds("forward")
8168-
		lib.buildWallSection("-----", R.useBlockType)	
8168+
8169-
		T:go("R1F1 D2") -- over 13 x 13 internal area
8169+
8170-
	elseif R.data == "left" or R.data == "right" or R.data == "back" then
8170+
		if lib.isStorage("forward") then
8171-
		-- build 3 wall sections in 2 passes
8171+
			lib.getVeg("forward")
8172-
		if R.data == "left" then										-- should be on left corner of existing
8172+
8173-
			T:go("L1F1 D1") 											-- move left 1 blocks, down 1: <-
8173+
8174-
			lib.buildWallSection("------c-------", R.useBlockType)		-- front wall (14 blocks) c = network cable <-
8174+
8175
	
8176-
			lib.buildWallSection("--------------", R.useBlockType)		-- left wall (14 blocks) ^
8176+
	function lib.getSaplings(direction)
8177
		--[[ get a single sapling from the chest ]]
8178-
			lib.buildWallSection("-------------", R.useBlockType)		-- back wall (13 blocks) ->
8178+
8179-
			T:go("U1R2")												-- turn round ready to add next layer <-
8179+
8180-
			lib.buildWallSection("--------------", R.useBlockType)		-- back wall top (14 blocks) <-
8180+
8181
		while T:suck(direction, 1) do end -- remove saplings/ seeds
8182-
			lib.buildWallSection("--------------", R.useBlockType)		-- left wall top (14 blocks) v
8182+
8183
		T:dropItem("sapling", direction, 1) -- drop all but 1 saplings
8184-
			lib.buildWallSection("-----bm", R.useBlockType)				-- front wall (7 blocks) barrel/modem ->
8184+
		if not T:dropItem("seeds", direction, 0) then-- drop all seeds
8185-
			network.attachModem()
8185+
			T:dropItem("seeds", "up", 0)
8186
		end
8187-
			lib.buildWallSection("l-----", R.useBlockType)				-- front wall (5 blocks) log ->
8187+
8188-
			T:go("R2F12 R1F1 D2") 										-- over 13 x 13 internal area lower left side
8188+
		return T:getItemSlot("sapling", -1)
8189-
		elseif R.data == "right" then									-- should be on right corner of existing
8189+
8190-
			T:go("R1F1 D1") 											-- move right, forward, down 1
8190+
8191-
			lib.buildWallSection("------c-------", R.useBlockType)		-- front wall (14 blocks) c = network cable
8191+
	function lib.getSeeds(direction)
8192
		--[[ get 1 stack of wheat seeds or 1 stack of beetroot seeds ]]	
8193-
			lib.buildWallSection("--------------", R.useBlockType)		-- right wall (14 blocks)
8193+
		print("Collecting seeds from storage")
8194
		while T:suck(direction, 1) do end -- remove saplings/ seeds
8195-
			lib.buildWallSection("-------------", R.useBlockType)		-- back wall (13 blocks)
8195+
		T:dropItem("sapling", direction, 0) -- drop all saplings
8196-
			T:go("U1R2")												-- turn round ready to add next layer
8196+
		T:dropItem("minecraft:wheat_seeds", direction, 64) -- drop all but 64 seeds
8197-
			lib.buildWallSection("--------------", R.useBlockType)		-- back wall top (14 blocks)
8197+
		T:dropItem("minecraft:beetroot_seeds", direction, 64)
8198
		local crop = ""
8199-
			lib.buildWallSection("--------------", R.useBlockType)		-- left wall top (14 blocks)
8199+
		if T:getItemSlot("minecraft:wheat_seeds", -1) > 0 then
8200
			crop = "wheat"
8201-
			lib.buildWallSection("-----lmb", R.useBlockType)
8201+
			print("Field crop = "..crop)
8202
		elseif T:getItemSlot("minecraft:beetroot_seeds", -1) > 0 then
8203-
			network.attachModem()
8203+
			crop = "beetroot"
8204-
			T:forward(2)
8204+
			print("Field crop = "..crop)
8205-
			lib.buildWallSection("-----", R.useBlockType)	
8205+
8206-
			T:go("R1F1 D2") 											-- over 13 x 13 internal area
8206+
8207-
		elseif R.data == "back" then									-- should be on left front corner of existing
8207+
		return crop
8208-
			T:go("R2F1 D4R2 F1") 										-- move forward 14 blocks, down 1
8208+
8209-
			for i = 1, 15 do
8209+
8210-
				T:place("cable", "up")
8210+
	function lib.getVeg(direction)
8211
		-- assume only one type of crop per field
8212
		print("Collecting crops from storage")
8213
		direction = direction or "forward"
8214-
			if T:getBlockType("up") == R.useBlockType then				-- already a farm on left side
8214+
		while T:suck(direction, 1) do end -- remove carrots / potatoes / wheat / beetroot
8215-
				T:go("U2C2 U1C2 F13R1 F1D1", false, 0, false, R.useBlockType)
8215+
		--clsTurtle.dropItem(self, item, direction, keepAmount)
8216-
				lib.buildWallSection("--------------", R.useBlockType)	-- back wall (14 blocks)
8216+
		T:dropItem("wheat", direction, 0)		-- drop all wheat
8217
		T:dropItem("beetroot", direction, 0)	-- drop all beetroot
8218
		T:dropItem("carrot", direction, 64)		-- drop all but 64 carrots
8219
		T:dropItem("potato", direction, 64)		-- drop all but 64 potato
8220-
				lib.buildWallSection("--------------", R.useBlockType)	-- left wall (14 blocks)
8220+
		local crop = ""
8221
		if T:getItemSlot("potato", -1) > 0 then
8222-
				lib.buildWallSection("--------------", R.useBlockType)	-- back wall (14 blocks)
8222+
			crop = "potato"
8223
			print("Field crop = "..crop)
8224
		elseif T:getItemSlot("carrot", -1) > 0 then
8225
			crop = "carrot"
8226-
			lib.buildWallSection("-------------", R.useBlockType)		--right wall (13 blocks) no special blocks
8226+
			print("Field crop = "..crop)
8227-
			T:go("U1R2")	-- turn round ready to add next layer
8227+
8228-
			for i = 1, 2 do
8228+
8229-
				lib.buildWallSection("--------------", R.useBlockType)	--right wall top (14 blocks) no special blocks
8229+
		--T:turnRight(2) -- face crops
8230-
				T:go("L1F1")
8230+
		return crop
8231
	end
8232-
			lib.buildWallSection("-------------", R.useBlockType)		-- left wall top (13 blocks) no special blocks
8232+
8233-
			T:go("F1L1 F7x2")
8233+
	function lib.goHome()
8234-
			T:go("D1x2")
8234+
8235-
			T:place("cable", "down")
8235+
8236
		-- is tree above or in front
8237-
			T:place("modem", "down")
8237+
8238-
			T:go("F1R2x2")
8238+
8239-
			T:place("log", "down")
8239+
			lib.harvestTree("forward") -- will only harvest if fuel below half of limit
8240-
			T:go("F2x2")
8240+
8241-
			T:place("barrel", "down")
8241+
8242
			lib.harvestTree("up")
8243-
			network.attachModem()
8243+
8244-
			T:go("F6R1 F1D2")
8244+
		elseif T:getItemSlot("log", -1) > 0 then -- tree just harvested 
8245
			onTree = true
8246-
	else -- convertStorage or convert
8246+
8247-
		-- legacy farm had polished block on positions 4 / (10) from left corner
8247+
8248-
		 local message = lib.findLegacyStart()
8248+
				lib.harvestTree("up")
8249-
		 if message ~= "" then
8249+
8250-
			return {message}
8250+
				while turtle.down() do end
8251-
		 end
8251+
8252-
		 -- now on top of polished block, 4 from left corner, facing Centre
8252+
8253-
		 T:forward(2)
8253+
8254-
		 T:place("barrel", "down")
8254+
		if onTree then -- tree harvested, but direction unknown
8255-
		 T:go("F1D1")
8255+
8256-
		 T:place("cable", "down")
8256+
			local turns = 0
8257-
		 T:up(1)
8257+
			local onChest = lib.isStorage("down")
8258-
		 T:place("modem", "down")
8258+
			while not onChest do
8259-
		 network.attachModem()
8259+
8260-
		 T:forward(1)
8260+
					if lib.isStorage("down") then
8261-
		 T:place("log", "down")
8261+
						onChest = true
8262-
		 T:go("R1F1 R1F1 D5R1 F1L1 F7R1")-- left corner, facing back ready to clear basement
8262+
8263
						turtle.back()
8264-
	if (R.data):find("convert") == nil then
8264+
8265-
		lib.floodFarm(R)
8265+
8266
				if not onChest then
8267-
	lib.clearBasement() -- area has been cleared. ends right side facing right, just below ceiling
8267+
8268
					turns = turns + 1
8269-
	if R.data == "back" then
8269+
8270-
		T:go("R2F6 R1D1")
8270+
				if turns == 4 then
8271
					break
8272-
		T:go("R2F6 L1F1 U4D5 R2F1") -- make exit for player. end mid floor/ceiling height, facing back, in centre
8272+
8273
			end -- should be on chest. If not should be over water
8274-
	if R.data == "new" or R.data == "convertStorage" then	-- put storage in this farm
8274+
			if onChest then -- onChest and onTree, go left,down
8275
				T:go("R1F1D1R1")
8276-
			T:place("cable", "up")
8276+
8277
			atHome = lib.checkPosition()
8278
			if atHome then
8279-
		T:place("cable", "up")
8279+
				return true -- exit function
8280
			end
8281-
		utils.createStorage()	-- creates on ground, 1 below current
8281+
8282
			while turtle.down() do end -- no tree around, no logs onboard
8283-
		T:place("cable", "forward")
8283+
8284
			
8285
		return false
8286-
			T:place("cable", "up")
8286+
8287
	
8288
	function lib.gotoTree(logSlot)
8289
		-- assume facing crops
8290-
		for i = 1, 6 do
8290+
8291-
			T:place("cable", "up")
8291+
		print("Extracting saplings from storage")
8292
		lib.getSaplings("forward") -- gets one sapling only (if present)
8293
		print("Moving to tree position")
8294
		T:go("U1F1R1")
8295-
	T:place("modem", "up")
8295+
		lib.harvestTree("forward") -- fell tree or plant sapling, ends facing tree / dirt / sapling. sticks already used for fuel. excess saplings placed
8296-
	T:go("F1R2U2")
8296+
8297-
	T:place("barrel", "down")
8297+
		if logSlot == 0 then -- no logs passed as parameter
8298-
	T:drop("down", "dirt", 64)-- override 'slot' with item string
8298+
			logSlot = T:getItemSlot("log")
8299-
	T:up(1)
8299+
8300-
	T:place("hopper", "down")
8300+
		T:go("R1F1D1")			-- return to base, facing buried storage 
8301
		if logSlot == 0 then 	-- has logs so needs to craft and refuel
8302-
	network.attachModem()
8302+
			T:turnRight(1)		-- facing crops
8303-
	T:go("U1C2 U2F6 R2")
8303+
8304-
	--network.attachModem()
8304+
8305
		return logSlot
8306
	end
8307
	
8308
	function lib.harvest(crop)
8309
		--[[
8310
		cover the field in a set pattern.
8311
		harvest crops if ripe
8312
		till soil and plant new ones
8313
		place seeds / harvest in chests
8314
		return farm(s) to right / front
8315
		]]
8316-
			T:place("barrel", "down", false)
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
					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-
		T:place("torch", "forward", true)
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-
		-- T:place(blockType, direction, leaveExisting, signText)
8337+
					if lib.isStorage("down") then
8338
						isFarmToRight = true
8339
					end
8340
					turtle.back()
8341
				end
8342
			end
8343-
				T:place(R.useBlockType, "forward", true)
8343+
8344
			if l < length then -- do not turn at final row
8345
				lib.plantCrop(crop, "down")
8346
				if toRight then
8347
					T:go("L1F1L1")
8348
				else
8349
					T:go("R1F1R1")
8350
				end	
8351-
					T:place(R.useBlockType, "up", true)
8351+
8352
			toRight = not toRight
8353
		end
8354
		T:go("R1F1") -- goes over chest/cobble on top wall
8355
		if lib.isStorage("down") then
8356
			isFarmToFront = true
8357
		end
8358-
					T:place(R.useBlockType, "forward")
8358+
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, "forward")
8363+
	function lib.harvestTree(direction)
8364
		--[[
8365
			start in front of / during tree harvest
8366
			Check if sapling present
8367-
					T:place(R.useBlockType, "forward")
8367+
8368
			Dispose of apples. Use sticks as fuel
8369
			Return to base
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
			if inFront == "" then -- no tree or sapling
8376-
						T:place(R.useBlockType, "down", true)
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
				-- 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
			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-
		T:place(R.useBlockType, "down", true)
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
		if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then
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-
					T:place("torch", "down")				-- place torch, move forward
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-
				if not T:place("stone", "down") then		-- place stone below
8499+
8500
		planted = T:place("carrot", -1, direction)
8501
		if not planted then
8502
			planted = T:place("potato", -1, direction)
8503
		end
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
	
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-
						T:place("torch", "down")		-- place torch
8617+
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
		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-
						T:place("torch", "down")		-- place torch
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
	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-
		T:place("slab", "down")					-- place slab layer 1
8846+
8847
		elseif R.subChoice == 2 then	-- end of blocks in front of turtle eg cliff, wall
8848-
		T:place("slab", "down")					-- place slab layer 2
8848+
8849
			while turtle.detect() and doContinue do
8850-
		T:place("redstone", "down")
8850+
8851
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8852-
		T:place("redstone", "forward")			-- redstone on ground level slab
8852+
8853
					message = "Obstruction above stopped measurement"
8854-
		T:place("slab", "down")					-- slab on layer 1
8854+
8855
					doContinue = false
8856-
		T:place("slab", "down")					-- slab on layer 3
8856+
8857
			end
8858-
		T:place("redstone", "down")				-- redstone on layer 3 slab
8858+
8859
			method = "Method:Until search: '"..R.data.."' met"
8860
			while turtle.detect() and doContinue do
8861-
		T:place("redstone", "forward")			-- redstone on layer 1 slab
8861+
8862
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8863-
		T:place("redstone", "forward")			-- redstone on level 0 floor
8863+
8864
						local blockType = T:getBlockType("forward")
8865
						if blockType:find(R.data) ~= nil then
8866
							measure = "Height measured: "..blocks.." blocks"
8867
							message = "Found "..blockType
8868
							doContinue = false
8869
						end
8870-
			T:place("redstone", "down")			-- redstone under chest etc
8870+
8871
				else
8872
					message = "Obstruction above stopped measurement"
8873
					measure = ""
8874
					doContinue = false
8875
				end
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-
		T:place("chest", "forward")				-- end chest
8881+
8882
				T:up(1)
8883-
		T:place("slab", "down")					-- slab above chest
8883+
8884
				if doContinue then
8885
					blockType = T:getBlockType("up")
8886
				end
8887-
		T:place("chest", "forward")				-- start chest
8887+
8888
			measure = "Height measured: "..blocks.." blocks"
8889-
		T:place("wall", "forward")				-- place wall
8889+
8890
		end
8891-
		T:place("pressure", "down")				-- place pressure plate
8891+
8892
		for i = 1, blocks do
8893-
		T:place("hopper", "forward")				-- place hopper into chest
8893+
8894
		end
8895-
		T:place("wall", "forward")				-- place second wall
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
			local move = true
8900
			while move do
8901
				local blockType = T:getBlockType("down")
8902-
		T:place(R.useBlockType, "forward", false)	-- replace back wall with polished block layer 2
8902+
8903
					message1 = blockType.." found at "..blocks
8904-
		T:place(R.useBlockType, "forward", false)	-- replace back wall with polished block layer 3
8904+
8905
				else
8906
					move = turtle.down()
8907-
			T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 3
8907+
8908
						blocks = blocks + 1
8909
					else
8910
						measure = "Depth measured: "..blocks.." blocks"
8911-
			T:place("piston", "forward")				-- lower replacer piston placed
8911+
8912
				end
8913
			end
8914-
		T:place("piston", "forward")					-- lower piston placed
8914+
8915
		elseif R.subChoice == 2 then	-- end of wall in front`
8916
			while turtle.detect() do
8917-
		T:place(R.useBlockType, "forward", false)	-- polished block back wall layer 4
8917+
8918
					blocks = blocks + 1
8919-
		T:place("dispenser", "forward")				-- dispenser placed
8919+
8920
				else
8921
					message1 = "Obstruction below stopped measurement"
8922-
		T:place("slab", "down")						-- lower piston slab placed
8922+
8923
				end
8924-
			T:place(R.useBlockType, "forward", false)-- polished block above second wall layer 4
8924+
8925
			method = "Method: Until no block detected ahead"
8926
		elseif R.subChoice == 3 then	-- specific block detected ahead
8927
			method = "Method:Until search: '"..R.data.."' met"
8928
			while turtle.detect() do
8929-
			T:place("computercraft:computer_normal", "forward", false)	-- place computer
8929+
8930
					blocks = blocks + 1
8931
					local blockType = T:getBlockType("forward")
8932-
		T:place(R.useBlockType, "forward", false)	-- polished block back wall layer 4
8932+
8933
						measure = "Depth measured: "..blocks.." blocks"
8934
						message = "Found "..blockType
8935-
		T:place("piston", "forward")					-- upper piston placed
8935+
8936
					end
8937
				else
8938-
		T:place(R.useBlockType, "forward", false)	-- polished block back wall layer 5
8938+
8939
					break
8940
				end
8941-
			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		
8941+
8942
		end
8943
		for i = 1, blocks do
8944
			turtle.up()
8945-
			T:place("piston", "forward")				-- upper replacer piston placed				
8945+
8946
		T:go("F1R2")
8947
	elseif R.choice == 103 then	-- length
8948-
		T:place("slab", "forward")					-- upper piston slab placed
8948+
8949
			method = "Method: Until obstruction ahead"
8950
			while turtle.forward() and doContinue  do
8951
				doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8952
			end
8953
		elseif R.subChoice == 2 then	-- end of ceiling above
8954
			method = "Method: Until no block detected above"
8955-
		T:place("computercraft:computer_normal", "forward", false)		-- place computer in gap, layer 4
8955+
8956
				if turtle.forward() then
8957
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8958
				else
8959-
		T:place(R.useBlockType, "forward", false)
8959+
8960
					measure = ""
8961-
		T:place(R.useBlockType, "forward", false)
8961+
8962
				end
8963-
		T:place(R.useBlockType, "forward", false)	-- facing right
8963+
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
				if turtle.forward() then
8968
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
8969-
		T:place("glass", "down", false)
8969+
8970
					message = "Obstruction ahead stopped measurement"
8971-
		T:place("glass", "down", false)				-- on top of glass facing back wall at dungeon base level 5
8971+
8972
					doContinue = false
8973-
		T:place(R.useBlockType, "down", false)		-- level 6 dungeon exit
8973+
8974
			end
8975
		elseif R.subChoice == 4 then	-- search for specific block up min 3 characters
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
						local blockType = T:getBlockType("up")
8982
						if blockType:find(R.data) ~= nil then
8983-
		T:place(R.useBlockType, "forward", false)
8983+
8984
							measure = "Length measured: "..blocks.." blocks"
8985-
		T:place(R.useBlockType, "forward", false)	-- facing right
8985+
8986
						end
8987
					end
8988
				else
8989-
		T:place(R.useBlockType, "forward", false)
8989+
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("computercraft:wired_modem", "forward", false)	-- place modem
8995+
8996
			--while turtle.detectDown() and doContinue do
8997-
		T:place("computercraft:cable", "forward", false)			-- place network cable
8997+
8998-
		T:place("computercraft:cable", "forward", false)			-- place network cable (no need to move)
8998+
8999
					doContinue, blocks, measure, message = lib.checkBlocks(R, blocks)
9000-
		T:place("computercraft:cable", "forward", false)
9000+
9001
						local blockType = T:getBlockType("down")
9002-
		T:place("computercraft:cable", "forward", false)
9002+
9003
							message = "Found "..blockType
9004-
		T:place("computercraft:wired_modem", "forward", false)	-- place modem
9004+
9005
							doContinue = false
9006-
		T:place("computercraft:cable", "forward", false)
9006+
9007-
		T:place("computercraft:cable", "forward", false)
9007+
9008
				else
9009
					message = "Obstruction ahead stopped measurement"
9010
					measure = ""
9011
					doContinue = false
9012
				end
9013
			end
9014
		end
9015
		T:turnRight(2)	-- head home
9016
		for i = 1, blocks do
9017
			turtle.forward()
9018
		end
9019
		T:turnRight(2)
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-
local function createTrialCover(R)
9059+
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
	end
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-
	function lib.findSpawner()
9078+
9079
		if goRight then
9080
			T:go("R1F1R1")
9081-
		-- assume turtle placed facing trial spawner
9081+
9082
			T:go("L1F1L1")
9083
		end
9084
		goRight = not goRight
9085
	end
9086
	return {}
9087
end
9088-
				if moves > 32 then
9088+
9089
local function oceanMonumentColumns(R)
9090
	-- utility to find corners and build columns to surface
9091
	local lib = {}
9092
	
9093-
			if not found then	-- could be behind a wall
9093+
9094-
				print("Assuming spawner behind a wall")
9094+
9095
		while T:isWater("forward") do
9096
			T:go("U1C2")
9097-
				while turtle.forward() and not quit do 
9097+
9098
		end
9099-
					if moves > 32 then
9099+
9100-
						quit = true
9100+
9101
	
9102
	function lib.buildTower()
9103-
				found, position = lib.isSpawner() -- true/false, top/bottom/nil
9103+
9104-
				if not found then
9104+
9105-
					T:go("R2F"..moves + 2 .."R2")
9105+
9106
		T:go("L1F1 L1C2 F1C2 F1C2 F1C2")
9107
		
9108
		T:go("R2")
9109
		for i = 1, 4 do
9110
			T:go("U1C2")
9111
			for j = 1, 4 do
9112
				T:go("F1C2 F1C2 F1C2 R1")
9113
			end
9114
		end
9115
	end
9116
	
9117
	R.silent = true
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 found, position = lib.findSpawner() -- move forwards until meet Spawner, go through wall if present
9139+
9140-
	if not found then --outside dungeon
9140+
9141-
		return {"Trial spawner not found"}
9141+
9142-
	end 
9142+
9143-
	if position == "top" then
9143+
9144-
		T:go("B2D1")
9144+
9145-
	elseif position == "forward" then
9145+
9146-
		T:go("B1")
9146+
9147
					blockType = T:getBlockType("down")
9148-
		T:go("B2U1")
9148+
9149
				turtle.back()
9150-
	T:go("R1F2R2")	--on lower right corner
9150+
9151-
	-- starts with wall across spawner
9151+
9152-
	buildStructure(R)
9152+
9153-
	T:go("U3F1 R1F1 L1U1 F1")
9153+
9154
		lib.buildTower()
9155-
	R.width = 3
9155+
9156-
	R.length = 3
9156+
9157
	return {}
9158-
	createFloorCeiling(R)
9158+
9159-
	T:go("F1R1 B1D1 B1D2 F1")
9159+
9160
local function placeRedstoneTorch(R) -- 91, 92
9161
	local moves = 2
9162
	local blockType = T:getBlockType("down")
9163
	if R.data == "level" then
9164
		T:turnLeft(1)
9165
		utils.goBack(1)
9166
		if blockType:find("rail") ~= nil then
9167
			 moves = 3
9168
		end
9169
		T:down(moves)
9170
		T:go("F1R1")
9171
		--clsTurtle.place(self, blockType, damageNo, direction, leaveExisting)
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:place("cobble", "down", false) -- place cobblestone or cobbled deepslate to mark zero coordinate
9273+
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:up(1)
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-
		T:place("minecraft:end_stone", "forward", false) -- place endstone to mark facing direction
9320+
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
		end
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-
		-- assumes legacy tree farm with turtle on polished block 4 blocks from corner
9481+
9482-
		local message  = ""
9482+
9483-
		R.treeSize = "single"
9483+
9484
	createCorridor(R, true)
9485-
		--local logType = ""
9485+
9486-
		--local startHeight = 0
9486+
9487
	createCorridor(R, true)
9488
	T:turnRight(1)
9489
	
9490
	return {}
9491
end
9492
9493
local function repairWall(startAt, height, width, replaceWith)
9494
	-- go up to startAt
9495
	
9496
	-- if width = 1
9497-
		if blockType:find("dirt") ~= nil then	-- dirt found
9497+
9498-
			T:go("R1F1L1")
9498+
9499
		
9500-
			if blockType:find("dirt") ~= nil then
9500+
9501-
				R.treeSize = "double"
9501+
9502
			-- move up
9503-
			T:go("L1F1 R1")
9503+
9504-
		else	-- dirt NOT found where expected
9504+
9505-
			message = "Unable to determine position"
9505+
9506
		-- move back to beginning
9507
		
9508-
		blockType = T:getBlockType("forward")	-- 1 block above dirt
9508+
9509-
		if blockType:find("log") ~= nil or blockType:find("sapling") ~= nil or blockType:find("propagule") ~= nil then
9509+
9510-
			local parts = T:getNames(blockType)
9510+
9511-
			if parts[2] == "dark" then
9511+
9512-
				R.logType = "dark_oak"
9512+
9513
		
9514-
				R.logType = parts[2]				-- eg "oak"
9514+
9515
			
9516-
			if R.logType == "mangrove" then
9516+
9517-
				R.useBlockType = "mangrove_propagule"
9517+
9518
				-- move up
9519-
				R.useBlockType = parts[2].."_sapling"	-- eg "oak_sapling"
9519+
9520
			--end
9521
			
9522-
		T:down(1)	-- facing dirt
9522+
9523
			
9524-
		return R, message
9524+
9525
			
9526
				-- replace block with replaceWith ("" = any)
9527-
	function lib.waitForGrowth(R)
9527+
9528-
		local pattern = R.treeSize	--"single","double"
9528+
9529-
		local elapsed = 0
9529+
9530-
		local facing = "left"
9530+
9531-
		local ready = {}
9531+
9532-
		ready.left = false
9532+
9533-
		ready.top = false
9533+
9534-
		ready.right = false
9534+
9535-
		ready.bottom = false
9535+
9536-
		if R.logType == "mangrove" then
9536+
9537-
			pattern = "mangrove"
9537+
9538-
			local facings = {"left", "top", "right", "bottom"}
9538+
9539-
			T:up(1)	-- go up from dirt to sapling level
9539+
9540-
			while not ready.left or not ready.right or not ready.top or not ready.bottom do
9540+
9541
	--MINING
9542
	text[11] = {"1 ladder for each level","levels / 4 torch (optional)","levels * 4 stone"}				-- ladder to bedrock
9543-
					if blockType:find("propagule") ==  nil then	-- either grown or deleted by roots
9543+
9544-
						ready[facings[i]] = true
9544+
9545
	text[14] = {"levels * 4 stone","water_bucket"} 														-- safe drop to water block
9546
	text[15] = {"levels * 4 stone", "1 soul sand", "1 water bucket"} 									-- single column bubble lift
9547
	text[16] = {"1 bucket (optional)", "64 stone"} 														-- quick corridor
9548-
				if ready.left and ready.right and ready.top and ready.bottom then
9548+
9549
	text[18] = {"1 bucket (optional)"}																	-- mine to bedrock
9550
	text[19] = {"1 UNUSED diamond sword (optional)"}													-- rob mineshaft
9551-
					sleep(15)
9551+
9552-
					elapsed = elapsed + 15
9552+
9553-
					if  elapsed / 60 > 15 then	-- max 15 mins real time before farm is harvested
9553+
9554
	text[22] = {"320 stone", "4 polished stone"} 														-- Create treefarm
9555
	text[23] = {"min 4 saplings", "16 dirt"} 															-- plant treefarm
9556
	text[24] = {"No items required"} 																	-- Harvest treefarm
9557-
				print("Waiting for mangrove growth "..elapsed / 60 .." minutes")
9557+
9558-
				print("Left = "..tostring(ready.left)..
9558+
9559-
					  ", top = "..tostring(ready.top)..
9559+
9560-
					  ", right = "..tostring(ready.right)..
9560+
9561-
					  ", bottom = "..tostring(ready.bottom))
9561+
9562
	text[32] = {"64 stone","128 dirt (optional)", "4 water buckets","5 chests/ barrels","1 sapling"}	-- extend modular farm
9563
	text[33] = {"No items required"} 																	-- Manual harvest and auto setup
9564-
			--T:go("L1D1")
9564+
9565-
			T:turnLeft(1)	-- face front
9565+
9566
9567-
			while not ready.left or not ready.right do
9567+
9568-
				T:up(1)	-- go up from dirt to sapling level
9568+
9569-
				local blockType = T:getBlockType("forward")
9569+
9570-
				if blockType:find("log") ~=  nil then
9570+
9571-
					ready[facing] = true
9571+
9572
	text[45] = {"84 stone"} 																			-- undermine dragon towers
9573-
				if pattern == "single" then
9573+
9574-
					--alternate between 2 trees, starts facing left
9574+
9575
	text[48] = {"height * 4 stone","height * ladders", "1 trapdoor"}									-- build end portal platform
9576-
					if facing == "left" then
9576+
9577-
						facing = "right"
9577+
9578-
					elseif facing == "right" then
9578+
9579-
						facing = "left"
9579+
9580
	text[53] = {"2 * length stone or dirt","2 water buckets","torches (optional)"} 						-- water canal
9581-
					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-
					T:down(1)	-- drop below sapling to dirt level
9585+
9586-
				elseif pattern == "double" then
9586+
9587-
					if ready.left and facing == "left" then-- tree on left now grown. check right
9587+
9588-
						T:go("R2F2")
9588+
9589-
						facing = "right"
9589+
9590
	text[63] = {"2 water buckets","If using bubble lift","2 fence","2 signs","1 slab",
9591-
					blockType = T:getBlockType("forward")
9591+
9592-
					if blockType:find("log") ~=  nil then
9592+
9593-
						ready[facing] = true
9593+
9594
				"23 polished stone + 7 slabs","2 glass","1 stone pressure plate","1 dispenser",
9595-
					T:down(1)	-- drop below sapling to dirt level
9595+
9596
	text[66] = {"1856 stone, diorite etc (inc polished)","1 chest","10 empty buckets",
9597
				"2 water buckets","192 fence","8 signs","3 ladder","2 soul sand"} 						-- build endermen observation tower
9598-
				print("Farm type: "..pattern)
9598+
9599-
				print("Waiting for tree growth "..elapsed / 60 .." minutes")
9599+
9600-
				print("Left grown = "..tostring(ready.left)..", right grown = "..tostring(ready.right))
9600+
9601-
				if not ready.left or not ready.right then
9601+
9602-
					sleep(15)
9602+
9603-
					elapsed = elapsed + 15
9603+
9604-
					if pattern == "single" and elapsed / 60 > 10 then	-- max 10 mins real time before farm is harvested
9604+
9605
	text[76] = {"No items required"}																	-- clear solid
9606-
					elseif pattern == "double" and elapsed / 60 > 15 then	-- max 15 mins real time before farm is harvested
9606+
9607
	text[78] = {"No items required"} 																	-- carve mountain
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
				
9611
	-- LAVA WATER
9612-
		-- growth complete
9612+
9613-
		if pattern == "single" then
9613+
9614-
			if facing == "right" then
9614+
9615
	text[84] = {"width * length + extra stone"} 														-- water clearing by repeated block deletion
9616
	text[85] = text[84] 																				-- sinking platform
9617
	text[86] = {"Full inventories of sand or stone"}													-- Ocean monument utilities
9618
	text[87] = {"ladder to height","stone, dirt netherrack 4 X height"} 								-- ladder to water/lava
9619-
			--T:go("F1R1 F3R1")			-- facing first dirt
9619+
9620-
			T:go("F1R1 F1R1")			-- facing first dirt
9620+
9621-
		elseif pattern == "double" then -- assume on right side
9621+
9622-
			if facing == "right" then
9622+
9623-
				T:go("R1F1 R1F4 R1")
9623+
9624
	text[91] = {"length * height stone"}																-- Build a wall
9625-
				T:go("L1F1 R1F2 R1")
9625+
9626
	text[93] = {"length * width * height stairs", "length * slabs"}										-- build a gable roof
9627-
		elseif pattern == "mangrove" then 
9627+
9628-
			T:go("D2F6 U1F1 R1F6 R1F1 U1")
9628+
9629
	text[96] = {"1 block of choice","1 redstone torch"} 												-- place redstone torch on upward slope
9630-
		-- ends facing dirt at base of first tree
9630+
9631-
		-- no return needed, function exit so trees are grown
9631+
9632
	return text
9633
end
9634-
	function lib.watchFarm(R)
9634+
9635-
		-- rotate to check if dirt on both sides
9635+
9636-
		-- R.subChoice == 1: 16 single trees, 2 = 4 doubles
9636+
9637-
		if R.logType ~= "mangrove" then
9637+
9638-
			R.treeSize = "single"
9638+
9639-
			T:turnRight(2)	-- if no dirt then on 4 x doubles
9639+
9640-
			if T:getBlockType("forward") == "" then
9640+
9641-
				R.treeSize = "double"
9641+
9642
	info.main = {}
9643-
			T:saveToLog("lib.watchFarm: R.treeSize set to '"..R.treeSize.."'")
9643+
9644-
			T:turnLeft(2)	-- face lower left double dirt 
9644+
9645
	[[                ~lightGray~MINING:~white~
9646-
		lib.waitForGrowth(R)
9646+
9647
Ladders and ~lightGray~stairs up/down    
9648-
		return R
9648+
9649
mine at chosen level.
9650
~blue~Bubble lift and ~cyan~safe drop to water.~magenta~  
9651-
	function lib.harvestSingle(direction, moves)
9651+
9652-
		-- if direction == "up": starting inside tree on dirt at dirt level
9652+
9653-
		T:saveToLog("lib.harvestSingle('"..direction.."', moves = "..moves)
9653+
9654
the fuel and time)
9655-
			while turtle.detectUp() do
9655+
9656
]])
9657
	table.insert(info.main,
9658
	[[               ~lime~FORESTRY:~brown~
9659-
		else	-- direction = "down", but could be mid-tree
9659+
9660-
			local movesUp = 0
9660+
9661-
			while turtle.detectUp() do
9661+
9662
or 4 double size (Dark oak or any type)
9663-
				movesUp = movesUp + 1
9663+
9664
~brown~ fence or wall a rectangle keeping
9665-
			T:down(movesUp)
9665+
9666-
			T:down(moves)
9666+
9667
(Must be walled off)
9668
9669
]])
9670
	table.insert(info.main,
9671-
	function lib.harvestSingleRow()
9671+
9672-
		-- start next to tree/dirt
9672+
9673
and placed next to each other in linear
9674-
		local moves = lib.harvestSingle("up", 0)
9674+
9675-
		T:go("F2")
9675+
9676-
		lib.harvestSingle("down", moves)
9676+
9677-
		T:go("F2")
9677+
9678-
		moves = lib.harvestSingle("up", 0)
9678+
9679-
		T:go("F2")
9679+
9680-
		lib.harvestSingle("down", moves)
9680+
9681
]])
9682
	table.insert(info.main,
9683-
	function lib.harvestDouble()
9683+
9684-
		T:forward(1)	-- dig dirt, move into left (S) corner
9684+
9685
lava areas safely.~pink~
9686-
		while turtle.detectUp() do
9686+
9687-
			turtle.dig()
9687+
9688-
			turtle.digUp()
9688+
9689
undermined ready for deactivating.
9690
End world towers can have the crystals
9691
destroyed.~red~
9692-
		turtle.dig()
9692+
9693-
		T:go("R1F1L1")	-- move to right corner
9693+
9694
]])
9695-
			turtle.dig()
9695+
9696-
			turtle.digDown()
9696+
9697
Can be used in Nether and End.~lightGray~
9698
Build pathways over air, water or lava
9699-
		turtle.dig()
9699+
9700-
		T:go("F1L1F1R1") -- move to left corner (N)
9700+
9701
at the same time.~blue~
9702
Build a water canal with towpath.~cyan~
9703-
	--T:setUseLog(true, "treeFarmLog.txt", true)	-- T:setUseLog(use, filename, delete)
9703+
9704-
	--dbug = true								-- set dbug flag
9704+
9705
Sinking version is removed and replaced
9706
1 block lower each time
9707-
	-- if on modem, R.networkFarm has already been set
9707+
9708-
	T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm))
9708+
9709
	[[             ~lightGray~SPAWNER FARMS:~brown~
9710-
	if R.networkFarm then
9710+
9711-
		local message = network.loadStorageLists()	-- initialises or creates lists of where an item can be found: GLOBAL LISTS!
9711+
9712-
		if message ~= nil then return {message} end
9712+
9713-
		network.emptyInventory(R, {"sapling", "propagule", "dirt"}, {"all"}, true)
9713+
9714
Choice of bubble lift mob dropper
9715
or ~brown~simple deep trench.~gray~
9716-
	if turtle.getFuelLevel() < turtle.getFuelLimit() / 2 then
9716+
9717-
		local turtleSlot, turtleCount = network.getItemFromNetwork("chest", "log", 16)
9717+
9718-
		if turtleSlot > 0 then
9718+
9719-
			if turtle.craft() then
9719+
9720
]])
9721-
				T:saveToLog("harvestTreeFarm(R) R.networkFarm = "..tostring(R.networkFarm))
9721+
9722
	[[    ~orange~AREA CLEARING AND REFORMING:~lime~
9723
Tools to clear a field including trees~magenta~
9724
Clear rectangles.~pink~
9725
Clear single walls.~brown~
9726-
	if R.networkFarm then			-- monitor trees for growth
9726+
9727-
		if R.logType == "mangrove" then
9727+
9728
Carve away side of a mountain.~lightBlue~
9729-
			T:place("dirt", "up")
9729+
9730-
			T:go("F6x2U1L1")	-- move under dirt covering, clear roots from hopper, move level with dirt, face left
9730+
9731
9732-
			T:go("F4R1")				-- either in between 2 trees or in gap between double trees at dirt level
9732+
9733-
			if turtle.detect() then		-- single trees, move between 1st and 2nd rows
9733+
9734-
				T:go("R1F1 R1F2 R1F1 L1")
9734+
9735-
			else	-- using double trees
9735+
9736-
				T:go("R2F1")
9736+
9737-
				if not turtle.detect() then
9737+
9738-
					return {"Unable to determine position"}
9738+
9739
sand dropping and recycling~cyan~
9740
Destructive draining uses solid block
9741
placing and recycling.~green~
9742-
		R = lib.watchFarm(R)	-- wait for trees to grow, then start harvest
9742+
9743
damaging structures.~lightBlue~
9744-
		--logType, startHeight, R = lib.initialise(R) -- possible ID tree type + move to correct position 1 above dirt
9744+
9745-
		R, message = lib.initialise(R) 		-- possible ID tree type + move to correct position next to first dirt
9745+
9746-
		if message ~= "" then
9746+
9747-
			return{message}
9747+
9748
	[[         ~cyan~BUILDING, MINECART TOOLS:~lightGray~
9749
Build simple walls, buildings and ~gray~roofs
9750-
	T:saveToLog("R.networkFarm = "..tostring(R.networkFarm)..", logType = "..R.logType..", treeSize = "..R.treeSize)
9750+
9751-
	-- different clearing for different trees:
9751+
9752-
	-- double spruce and jungle: staight up/down or small
9752+
9753-
	if R.logType == "mangrove" then
9753+
9754-
		clearRectangle({width = 13, length = 13, up = true, down = true })
9754+
9755-
		T:go("U2F2 R1F2L1")
9755+
9756-
		clearSolid({width = 9, length = 9, height = 18, direction ="up"})
9756+
9757-
		T:go("D3R1 F4R1 F3R2")
9757+
9758-
		network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9758+
9759-
	elseif R.logType == "birch" or R.logType == "spruce" or R.logType == "jungle" then	-- use column harvest
9759+
9760-
		if R.treeSize == "single" then
9760+
9761-
			lib.harvestSingleRow()
9761+
9762-
			T:go("F1R1F2R1")
9762+
9763-
			lib.harvestSingleRow()
9763+
9764-
			T:go("F1L1F2L1")
9764+
9765-
			lib.harvestSingleRow()
9765+
9766-
			T:go("F1R1F2R1")
9766+
9767-
			lib.harvestSingleRow()
9767+
9768-
			if R.networkFarm then
9768+
9769-
				T:go("F1R1 F3L1 F3R2")
9769+
9770-
				network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9770+
9771
9772-
				T:go("F1R1 F6L1 F3R2")
9772+
9773
9774
	info.sub[11] = 
9775-
			lib.harvestDouble()
9775+
9776-
			T:go("F3")
9776+
9777-
			lib.harvestDouble()
9777+
9778-
			T:go("R1F4")
9778+
9779-
			lib.harvestDouble()
9779+
9780-
			T:go("R1F4")
9780+
9781-
			lib.harvestDouble()
9781+
9782-
			if R.networkFarm then
9782+
9783-
				T:go("F1R1 F3L1 F3R2")
9783+
9784-
				network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9784+
9785
9786-
				T:go("F1R1 F6L1 F3R2")
9786+
9787
	info.sub[12] = 
9788
[[~lightGray~Place me on the ground at ~red~^
9789-
	else	-- use cube harvest, including mangrove
9789+
9790-
		local size = 10
9790+
9791-
		local start = "L1F1 L1F1 R2"
9791+
9792-
		local finish = "R1F1 R1F3 R2"
9792+
9793-
		if R.logType == "acacia" then
9793+
9794-
			size = 12
9794+
9795-
			start = "L1F2 L1F2 R2"
9795+
9796-
			finish = "R1F2 R1F2 R2"
9796+
9797-
		elseif R.logType == "cherry" then
9797+
9798-
			size = 14
9798+
9799-
			start = "L1F3 L1F3 R2"
9799+
9800-
			finish = "R1F3 R1F1 R2"
9800+
9801
[[~yellow~Press F3 to check Y level.
9802-
		T:go("U1F1")	-- into first log at base of tree
9802+
9803-
		clearRectangle({width = 7, length = 7, up = true, down = true})
9803+
9804-
		--T:go("L1F2 L1F2 R2")	-- rect size 12
9804+
9805-
		--T:go("L1F1 L1F1 R2")	-- rect size 10
9805+
9806-
		T:go(start)
9806+
9807-
		local height = 0
9807+
9808-
		local pastLogCount = -1
9808+
9809-
		local currentLogCount = lib.getLogCount()
9809+
9810-
		--while currentLogCount ~= pastLogCount do
9810+
9811-
		while currentLogCount - pastLogCount > 5 do	-- ony continue if at least 5 logs harvested last round
9811+
9812-
			T:up(3)
9812+
9813
	else
9814-
			pastLogCount = currentLogCount -- 0 when loop starts
9814+
9815-
			--clearRectangle({width = 12, length = 12, up = true, down = true})
9815+
9816-
			clearRectangle({width = size, length = size, up = true, down = true})
9816+
9817-
			currentLogCount = lib.getLogCount() -- eg 20 logs from first round
9817+
9818-
		end	
9818+
9819-
		T:down(height + 1)
9819+
9820-
		--T:go("R1F2 R1F2 R2")		-- on polished stone rect size 12
9820+
9821-
		--T:go("R1F1 R1F3 R2")		-- on polished stone rect size 10
9821+
9822-
		T:go(finish)
9822+
9823-
		if R.networkFarm then
9823+
9824-
			T:go("R1F3 L1")			-- on modem
9824+
9825-
			network.emptyInventory(R, {"sapling", "propagule", "dirt", "crafting"}, {"all"}, true)
9825+
9826
~lightGray~| | | | | |
9827
		   
9828
]] -- safe drop
9829-
	return {}	-- if player initiated, stops here. If R.auto then returns to plantTreeFarm()
9829+
9830
[[~magenta~Direction of travel = UP!
9831
~yellow~Place me on the ground. I will build a
9832
3 x 1 ~blue~water ~yellow~source and a single column
9833
bubble lift to the chosen height.
9834
If near a ladder, place left or right:
9835
9836
~lightGray~| | | | | |
9837
~lightGray~| | |*| | | * = Ladder support block
9838
| |~blue~^~brown~|L|~blue~^~lightGray~| | ~brown~L = ladder
9839
~lightGray~| | | | | | ~blue~^ = Turtle facing forward
9840
~lightGray~| | | | | | ~blue~^ = Bubble column above
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-
local function upgradeFarmland(R)
10123+
10124-
	local essences = {":inferium", ":prudentium", ":tertium", ":imperium", ":supremium", ":awakened" , ":insanium"}
10124+
10125
10126
10127
10128-
	function lib.isHigherTeir(essence, farmLand)
10128+
10129-
		-- eg "ma:prudentium_essence", "mc:farmland"
10129+
10130-
		local teir = 0
10130+
10131-
		for index = 1, #essences do
10131+
10132-
			if farmLand:find(essences[index]) ~= nil then
10132+
10133-
				teir = index	-- 0 if vanilla, else eg 2 for prudentium
10133+
10134
[[~yellow~Place turtle <64 blocks from shulker
10135
Same level, or 1 block above/below
10136
Plan view:
10137-
		for index = 1, #essences do
10137+
10138-
			if essence:find(essences[index]) ~= nil then
10138+
10139-
				if index > teir then
10139+
10140
   ~red~T~lightGray~ | | | | | |~gray~T~lightGray~|
10141
   ~red~T~lightGray~ | | | | |~gray~T~lightGray~|~lime~S~lightGray~|   ~gray~T = kill positions
10142
   ~red~T~lightGray~ | | | | | |~gray~T~lightGray~|
10143
   
10144
 ~red~> T~lightGray~ = Turtle   ~lime~S~lightGray~ = Shulker]] -- Shulker is ahead
10145
	
10146
	info.sub[493] = 
10147-
	function lib.upgrade(essence, slot)
10147+
10148-
		-- essence is the slot no of any essence
10148+
10149-
		turtle.select(slot)
10149+
10150-
		local blockType = T:getBlockType("up")
10150+
10151-
		if blockType:find("farmland") ~= nil then			-- farmland found (vanilla or modded)
10151+
10152-
			if lib.isHigherTeir(essence, blockType) then	-- eg "ma:inferium", mc:farmland"
10152+
10153-
				turtle.placeUp()
10153+
10154
       ~gray~T
10155
     ~gray~> ~lime~S ~gray~<       > T < = kill positions
10156
~lightGray~|*|*|*|*|*|*|*|
10157-
	-- check if any essence still onboard
10157+
10158-
	T:checkInventoryForItem({"essence"}, {95}, false)
10158+
10159-
	-- return slotData.lastSlot, total, slotData -- integer, integer, table
10159+
10160-
	local name = ""
10160+
10161-
	local slot, amount, data = T:getItemSlot("essence")
10161+
10162-
	name = data.mostName or ""
10162+
10163-
	local empty = T:getFirstEmptySlot()
10163+
10164
~lightGray~|*|~orange~+~lightGray~| |~lime~S|~red~+~lightGray~| | |~blue~+~lightGray~|*| T = turtle places
10165-
	if slot > 0 then
10165+
10166-
		T:go("D2")
10166+
10167
~lightGray~|*|~orange~+|+|+|~red~+|~blue~+|+|+~lightGray~|*|    |*|*|*|*|*|
10168-
		for w = 1, 10 do
10168+
10169-
			for i = 1, 9 do
10169+
10170-
				if turtle.getItemCount(slot) == 0 then
10170+
10171-
					slot, amount, data = T:getItemSlot("essence")
10171+
10172-
					name = data.mostName or ""
10172+
10173-
					if slot == 0 then
10173+
10174-
						slot = empty
10174+
10175
Face ~red~direction ~yellow~shown. It will exit up,
10176
clear the roof above and return
10177-
				lib.upgrade(name, slot)
10177+
10178-
				if w == 1 and i == 1 then
10178+
10179-
					T:go("F1R2 C1R2")
10179+
10180-
				elseif w == 10 and i == 1 then
10180+
10181-
					
10181+
10182
~lightGray~|*| | | | | | | | |*|
10183
~lightGray~|*|~red~V~lightGray~| | | | | | |~red~>~lightGray~|*|
10184
~lightGray~|*|*|*|*|*|*|*|*|*|*|]] -- Clear roof above
10185
10186
	info.sub[496] = 
10187-
				lib.upgrade(name, slot)
10187+
10188-
				if w == 1 then
10188+
10189-
					T:go("L1F1 L2C1 R1")
10189+
10190-
				elseif w == 9 then
10190+
10191-
					T:go("L1F1 L1F1 L2C1 L2")
10191+
10192
~lightGray~|*|~red~<~lightGray~| | | | | | |~red~^~lightGray~|*|  ~yellow~automatically.
10193
~lightGray~|*| | | | | | | | |*|
10194
10195
~lightGray~|*| | | | | | | | |*|
10196-
				if w < 10 then
10196+
10197-
					lib.upgrade(name, slot)
10197+
10198
10199
	info.sub[51] = 
10200-
					T:go("L1F1 L2C1 R2F8 L1U1 C2U2") -- 1 above normal position
10200+
10201
10202
~yellow~Start:~blue~  |-|-|-|    - = air/water
10203
~orange~        |-|-|-|    - = lava
10204
~blue~        |-|-|-|
10205-
		-- sometimes original essence pops out of the ground when upgraded, so rescue it
10205+
10206-
		for w = 1, 10 do
10206+
10207-
			for i = 1, 9 do
10207+
10208-
				turtle.suckDown()
10208+
10209-
				turtle.suck()
10209+
10210
~lightGray~        |*|*|*|    * = Solid block
10211
]] -- Single path
10212
	info.sub[52] = 
10213-
				turtle.suckDown()
10213+
10214-
				turtle.suck()
10214+
10215
~yellow~Plan view    Face view
10216
10217-
				if w < 10 then
10217+
10218-
					turtle.suckDown()
10218+
10219-
					turtle.suck()
10219+
10220
~lightGray~|*|~green~*~lightGray~|*|      *|*|~red~T~lightGray~|*|*   ~red~^ T = Turtle
10221
   ~red~^~lightGray~         ~green~- - * - -   ground
10222-
					T:go("L1F9 L1D1") -- normal position
10222+
10223
~green~Floor + ceiling ~yellow~placed for your safety!
10224
]] -- Covered walkway / tunnel
10225
	info.sub[53] = 
10226
[[~yellow~plan view
10227
10228-
	return ({"Farmland Upgraded"})
10228+
10229
~lightGray~|*|~blue~-|-~lightGray~|*|    ~yellow~Cross section view
10230
~lightGray~|*|~blue~-|-~lightGray~|*|     ~lime~1 ~orange~2 ~brown~3 ~green~4  ~lightGray~= on ground
10231
~lightGray~|~lime~^~lightGray~|~blue~^~lightGray~|~cyan~^~lightGray~|~green~^~lightGray~|    |*|~blue~5~lightGray~|~cyan~6~lightGray~|*| ~lightGray~= in water
10232
10233
~yellow~New canal       ~lime~1 ~orange~2 ~brown~3 ~green~4 ~yellow~ground level-63
10234-
	function lib.askPlayerForCrops()
10234+
10235-
		local seed  = ""
10235+
10236-
		pp.itemColours = {colors.lightGray, colors.red, colors.orange, colors.brown, colors.magenta, colors.yellow}
10236+
10237-
		crops = {"minecraft:wheat_seeds", "minecraft:beetroot_seeds", "minecraft:carrots", "minecraft:potatoes", "mysticalagriculture", "none"}
10237+
10238-
		choices = {"wheat (seeds)", "beetroot (seeds)", "carrot", "potato", "Mystical Agriculture", "Till soil only"}
10238+
10239
10240
~lightGray~ |*| | |*| 	 * = Slab
10241-
		if crop == "none" then
10241+
10242-
			return "", ""
10242+
10243-
		elseif crop == "mysticalagriculture" then
10243+
10244-
			T:checkInventoryForItem({"seeds"}, {95}, true, "Add one type of M. Agriculture seeds")
10244+
10245
~lightBlue~  5 6 7 8    Convert water canal
10246-
			T:checkInventoryForItem({crop}, {95}, true, "Do not mix! add as many as you want")
10246+
10247
~red~All turtles placed at ground level!
10248-
		crop = T:getMostItem("", false)		-- not searching for any specific item, not checking stone only
10248+
10249-
		-- crop could be wheat/beetroot seeds, carrots, potatoes or mystical agriculture seeds
10249+
10250-
		seed, crop = lib.getCropSeed(crop)	-- seed type or "", crop type
10250+
10251-
		return seed, crop	
10251+
10252
10253
| | | | | | | |
10254-
	function lib.assessPlot(R)
10254+
10255-
		local crop = T:getBlockType("forward")	-- convert ma:inferium_crop to ma:inferium_seeds
10255+
10256-
		local seed = lib.getCropSeed(crop)
10256+
10257-
		turtle.down()									-- into water source
10257+
10258-
		local soil = T:getBlockType("forward")
10258+
10259-
		turtle.up()										-- at crop level
10259+
10260-
		return crop, seed, soil
10260+
10261
Blocks placed under the turtle
10262
]] -- Platform
10263-
	function lib.checkEquipment(R, itemRequired)
10263+
10264-
		-- Check if item is equipped and return it to slot
10264+
10265
Existing platform replaced below
10266
10267-
		local equipped, slot = T:getEquipped("right", false)	-- see what is equipped and replace it 
10267+
10268-
		if equipped == itemRequired then
10268+
10269-
			equipped, slot = T:getEquipped("right", true)		-- remove item and return slot
10269+
10270-
			return slot
10270+
10271
| |~red~^~lightGray~|*|*|*|*| |  ~red~^ = Turtle~lightGray~
10272
| | | | | | | |
10273-
		return 0	-- not found
10273+
10274
Blocks placed under the turtle
10275
]] -- Sinking platform
10276-
	function lib.crossFarm(R)
10276+
10277
[[~yellow~Boat Lift (Ice or Water)
10278
Place turtle left side. ~blue~Source~yellow~ to right
10279-
		local isReady, cropType, seed, status
10279+
10280-
		isReady, cropType, seed, status, R = lib.isCropReady(R,"down")
10280+
10281-
		-- will go forward until chest, barrel, modem or cobble detected below
10281+
10282
             |*|~cyan~S|S|~lightGray~*| ~cyan~S ~lightGray~= Soul sand
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
|*|~blue~W|W~lightGray~|*|    |*|~blue~W|W~lightGray~|*|
10286
|*|~blue~ | ~lightGray~|*|    |*|~blue~ | ~lightGray~|*| ~yellow~Ice canal needs
10287
~lightGray~|*|~blue~ | ~lightGray~|*|    |*|~blue~ | ~lightGray~|*| ~yellow~2x2 water source
10288
]] -- boat bubble lift
10289-
			elseif  blockType:find("barrel") ~= nil or
10289+
10290-
					blockType:find("chest") ~= nil or
10290+
10291-
					blockType:find("modem") ~= nil or
10291+
10292-
					blockType:find("cobble") ~= nil then
10292+
10293
 |*|*|*|*|*|*|*|   |*|~brown~1~lightGray~|*|*|*|~yellow~2~lightGray~|*| Top
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-
		return R, blockType -- either barrel, chest, modem or cobble
10297+
10298
T|*| | | | | |*|T  * = Dungeon Wall
10299
 |*|*|*|*|*|*|*|   ~orange~S = Spawner
10300-
	function lib.farmAll(R, isFarmToRight, isFarmToFront)
10300+
10301-
		local plotCountR = 0		-- plot a1 harvested
10301+
10302-
		local plotCountF = 0		-- plot a1 harvested
10302+
10303
	info.sub[62] = 
10304-
			while isFarmToRight do	-- do all plots on this axis
10304+
10305-
				R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin
10305+
10306-
				plotCountR = plotCountR + 1
10306+
10307
~lightGray~|*|*|*|*|*|*|*|*|  ~lime~> T = Continue build
10308-
			lib.goToLeft(R, plotCountR)
10308+
10309
~lightGray~|*| | | | | | | |
10310
|*| | | |~purple~S~lightGray~| | | |~lime~>~red~<          T
10311-
			while isFarmToFront do	-- do all plots on this axis
10311+
10312-
				plotCountR = 0				-- reset
10312+
10313-
				R, isFarmToRight, isFarmToFront = lib.farmInFront(R)
10313+
10314-
				if isFarmToRight then
10314+
10315-
					while isFarmToRight do	-- do all plots on this axis
10315+
10316-
						R, isFarmToRight = lib.farmToRight(R) -- plot harvested and back to plot origin
10316+
10317-
						plotCountR = plotCountR + 1
10317+
10318
10319-
					lib.goToLeft(R, plotCountR)	-- return home and continue with front
10319+
10320
~red~>~lightGray~|*| | | | |~purple~S~lightGray~| | | | |*|~red~<~lightGray~ |*| | | | |~purple~S~lightGray~|
10321-
				plotCountF = plotCountF + 1
10321+
10322
 |*| | | | | | | | | |*|  |*| | | | | |
10323-
			lib.goToFront(R, plotCountF)
10323+
10324
 |*| | | | | | | | | |*|  |*| | | | | |
10325
 |*|*|*|*|*|*|*|*|*|*|*| ~red~T~lightGray~|*|*|*|*|*|*|
10326
            ~red~^
10327-
	function lib.farmInFront(R)
10327+
10328
]] -- Flood spawner chamber
10329-
		T:go("U1L1 F11D1 R1")						-- on next farm, facing crops
10329+
10330-
		local seed, crop = lib.manageTree(R)		-- refuel, gather seeds or other crops
10330+
10331
 |*| | | | | | | | | |*|
10332-
		R, isFarmToRight = lib.harvest(R, seed, crop)		-- harvest field, store crops
10332+
10333-
		return R, isFarmToRight
10333+
10334
           ~brown~|~red~^~brown~|~lightGray~= Turtle on ~brown~Soul Sand
10335
		   
10336-
	function lib.farmToRight(R)
10336+
10337
 |*| | | | |~brown~F~lightGray~| | | | |*|
10338-
		T:go("U1F11 D1")								-- on next farm, facing crops
10338+
10339-
		local seed, crop = lib.manageTree(R)					-- refuel, gather seeds and other crops
10339+
10340-
		R, isFarmToRight = lib.harvest(R, seed, crop)		-- harvest field, store crops
10340+
10341-
		-- now at starting position of current plot
10341+
10342-
		return R, isFarmToRight
10342+
10343
[[~yellow~Computercraft mob grinder
10344
10345-
	function lib.getCropSeed(crop)
10345+
10346-
		-- change growing crops into equivalent seed names
10346+
10347-
		-- crop could be seeds, so return equivalent crop
10347+
10348-
		local start = crop:find("_crop")
10348+
10349-
		if start ~= nil then	-- only modded seeds have "crop"
10349+
10350-
			return crop:sub(1, start).."seeds", crop
10350+
10351
          |*|*|*|*|*|*|*|*|*|*|*|
10352-
		if crop:find("seeds") ~= nil then	-- asked to return crop from seed type
10352+
10353-
			if crop:find("wheat") ~= nil then
10353+
10354-
				return "minecraft:wheat_seeds", "minecraft:wheat"
10354+
10355
]] -- Computercraft mob grinder
10356-
			if crop:find("beetroot") ~= nil then
10356+
10357-
				return "minecraft:beetroot_seeds", "minecraft:beetroot"
10357+
10358
1.New tower lower base: place me on
10359
flat ground in open plain.
10360-
		if crop:find("wheat") ~= nil then
10360+
10361-
			return "minecraft:wheat_seeds", "minecraft:wheat"
10361+
10362
the existing chest at tower base.
10363-
		if crop:find("beetroot") ~= nil then
10363+
10364-
			return "minecraft:beetroot_seeds", "minecraft:beetroot"
10364+
10365
mobs. Expensive, not recommended.
10366-
		if crop:find("carrot") ~= nil then
10366+
10367-
			return "", "minecraft:carrot"
10367+
10368
10369
	info.sub[71] = 
10370-
			return "", "minecraft:potato"
10370+
10371
10372-
		-- planted crops are plural, harvested singular: carrots / carrot, pototoes/ potato
10372+
10373-
		return "", crop -- no seed for carrot / potato
10373+
10374
~lightGray~| | | | | |  Remove blocks > ground
10375
| | | | | |
10376-
	function lib.getHoe()
10376+
10377
|~red~^~lightGray~| | | | |  ~red~^ ~lightGray~= Turtle position
10378-
		if R.networkFarm then	-- get hoe from storage
10378+
10379-
			hoeSlot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1)
10379+
10380-
			if hoeSlot == 0 then
10380+
10381-
				if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then
10381+
10382-
					hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
10382+
10383
[[~yellow~Clear rectangle
10384
10385-
		else	-- put crafting table into barrel in floor
10385+
10386-
			T:go("L1F1")		-- over barrel
10386+
10387-
			local isStorage, storageType = utils.isStorage("down")
10387+
10388-
			if not isStorage then
10388+
10389-
				message =
10389+
10390
|~red~^~lightGray~| | | | |  ~red~^ ~lightGray~= Turtle position
10391
 ~red~^
10392
10393
~yellow~Can be used to clear 3 layers at a time
10394
10395-
	instead.
10395+
10396
10397
	info.sub[73] = 
10398
[[~yellow~Clear wall
10399-
				return 0, message
10399+
10400
                  ~gray~T ~lightBlue~T
10401-
			-- must be storage below to get this far
10401+
10402-
			T:suck("down")		-- if hoe already in storage get it out
10402+
10403-
			hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
10403+
10404-
			if hoeSlot == 0 then
10404+
10405-
				if T:checkInventoryForItem({"minecraft:diamond_hoe"}, {1}, true, "Diamond Hoe required for planting!") ~= nil then
10405+
10406-
					hoeSlot = T:getItemSlot("minecraft:diamond_hoe")
10406+
10407
				  
10408
T = Turtle top / bottom/ inside / out
10409
~yellow~Bottom to top or top to bottom
10410-
		return hoeSlot, ""
10410+
10411
	info.sub[74] = 
10412
[[~yellow~Clear rectangle ~red~perimeter only
10413-
	function lib.getSaplings(R, direction)
10413+
10414
~yellow~Plan view
10415
~lightGray~| | | | | |  Remove all blocks
10416
~lightGray~| |*|*|*| |  Optional dig ~lime~up
10417
~lightGray~| |*|*|*| |  Optional dig ~blue~down
10418-
		if R.networkFarm then
10418+
10419-
			network.getItemFromNetwork("barrel", "sapling", 1)
10419+
10420-
			--lib.getItemFromNetworkBarrels(R, "sapling", 1)
10420+
10421
~red~ ^
10422-
			while T:suck(direction, 1) do end -- remove saplings/ seeds
10422+
10423-
			T:dropItem("sapling", direction, 1) -- drop all but 1 saplings
10423+
10424-
			if not T:dropItem("seeds", direction, 0) then-- drop all seeds
10424+
10425-
				T:dropItem("seeds", "up", 0)
10425+
10426
[[~yellow~Demolish cube structure
10427
Plan view        Side view
10428
               ~gray~T ~lightBlue~T
10429-
		return T:getItemSlot("sapling")
10429+
10430
|*|*|*|*|*|*|   |*|*|*|*|*|*|
10431
|*|*|*|*|*|*|   |*|*|*|*|*|*|
10432-
	function lib.getSeeds(R, direction, seed)
10432+
10433-
		--[[ 
10433+
10434-
			seed = name of growing crops seed or ""
10434+
10435-
			turtle facing crops on networked, else facing storage
10435+
10436-
			allow for other seeds from mods eg MysticalAgriculture
10436+
10437-
			get 1 stack of seeds of whatever type is being farmed
10437+
10438
	info.sub[76] = info.sub[75]
10439-
		if seed == "" then
10439+
10440-
			return "", 0
10440+
10441
10442-
		local inventorySlot, seedCount = 0, 0
10442+
10443-
		T:saveToLog("Collecting seeds from storage")
10443+
10444-
		if R.networkFarm then
10444+
10445-
			inventorySlot, seedCount = network.getItemFromNetwork("chest", seed, 64)
10445+
10446
| |
10447-
			while T:suck(direction, 1) do end -- remove saplings/ seeds
10447+
10448-
			T:dropItem("sapling", direction, 0) -- drop all saplings
10448+
10449-
			T:dropItem("seeds", direction, 64)	-- drop all but 64 of any seed type
10449+
10450-
			seedCount = T:getItemCount(seed)	
10450+
10451
	info.sub[78] = 
10452-
		if seedCount > 0 then
10452+
10453-
			T:saveToLog("planting " ..seed)
10453+
10454
10455-
		return seed, seedCount	-- could be: "", 0 or "minecraft:wheat_seeds", 64
10455+
10456
~gray~ 	    |*~lightGray~|*|            ~gray~|*~lightGray~|*|*|*|    ~yellow~E
10457
~gray~      |*~lightGray~|*|*|*|      ~gray~|*|*~lightGray~|*|*|*|*|  ~yellow~N
10458-
	function lib.getVeg(R, direction, crop)
10458+
10459
~gray~      |*~lightGray~|*|*|*|       ~red~^~gray~|*~lightGray~|*|*|*|    ~yellow~T
10460-
		-- local item, itemName, shortName, slot = "", "","", 0
10460+
10461-
		local inventorySlot, cropCount = 0, 0
10461+
10462
    ~yellow~<--> no. of rows <-->
10463-
		if R.networkFarm then
10463+
10464-
			inventorySlot, cropCount = network.getItemFromNetwork("chest", crop, 64)
10464+
10465
[[~yellow~Place / Replace floor or ceiling
10466-
			if not R.mysticalAgriculture then
10466+
10467-
				print("Collecting root crops from storage")
10467+
10468-
				direction = direction or "forward"
10468+
10469-
				while T:suck(direction, 1) do end 			-- remove carrots / potatoes / wheat / beetroot / essence
10469+
10470-
				--item, itemName, shortName, slot = T:getFirstItem()
10470+
10471-
				local found = false
10471+
10472-
				if T:getItemSlot("potato") > 0 then
10472+
10473-
					T:dropItem("potato", direction, 64)		-- drop all but 65 potato
10473+
10474-
					found = true
10474+
10475-
					crop = "minecraft:potato"
10475+
10476
10477-
				if T:getItemSlot("carrot") > 0 then
10477+
10478-
					T:dropItem("carrot", direction, 64)		-- drop all but 64 carrots
10478+
10479-
					found = true
10479+
10480-
					crop = "minecraft:carrot"
10480+
10481
10482-
				if not found then
10482+
10483-
					T:dropAll(direction)					-- drop everything back
10483+
10484
direction + ~blue~number ~yellow~eg ~white~f2 ~yellow~= forward ~blue~2
10485
10486-
			cropCount = T:getItemCount(crop)
10486+
10487
~lime~l = left     ~red~r = right
10488
~lightGray~u = up       ~cyan~d = down
10489-
		if cropCount > 0 then
10489+
10490-
			print("planting " ..crop)
10490+
10491
	info.sub[81] = 
10492-
		return crop, cropCount -- could be: "", 0 or "minecraft:potato", 64
10492+
10493
  ~yellow~Place me on water/lava surface
10494
  
10495-
	function lib.goHome(R)
10495+
10496
  ~yellow~Place  on left corner of area
10497
 
10498
~yellow~3.Clear ~blue~(1) sand wall
10499
  ~yellow~Place me on the surface of sand.
10500
10501-
			lib.harvestTree(R, "forward") 		-- will only harvest if fuel below half of limit
10501+
10502-
			onTree = true					-- end on dirt
10502+
10503
]] -- Sand based utilities
10504-
			lib.harvestTree(R, "up")			-- end on dirt
10504+
10505
[[~yellow~Turtle position ~red~> T ~gray~(~red~V ~gray~to enclose)
10506-
		elseif T:getItemSlot("log") > 0 then-- tree just harvested 
10506+
10507
~blue~|~red~>~blue~| | | | | | ~yellow~to ~lightGray~|*|*|*|*|*|~red~V~lightGray~|~gray~ enclose
10508
                            ~gray~*  area
10509
~yellow~Side view
10510-
				lib.harvestTree(R, "up")		-- end on dirt
10510+
10511
~blue~| | | | | | | ~yellow~to ~lightGray~|*|*|*|*|*|*|
10512-
				while turtle.down() do end	-- end on dirt
10512+
10513
~blue~| | | | | | |    ~lightGray~|*|*|*|*|*|*|
10514
~yellow~|S|~blue~ | | |~yellow~S|S|    |S|~lightGray~*|*|*|~yellow~S|S|
10515
~yellow~|S|S|S|S|S|S|    |S|S|S|S|S|S|
10516-
		if onTree then 
10516+
10517-
			local success, storage = false, ""
10517+
10518-
			-- tree harvested, sitting on dirt, but direction unknown
10518+
10519-
			T:down(1) 				-- dig dirt, go down
10519+
10520-
			-- if storage type farm chest/barrel will give position
10520+
10521-
			for turns = 1, 4 do
10521+
10522
~yellow~e ~lightGray~|*| | | | |*|
10523-
				success, storage = utils.isStorage("forward")
10523+
10524
~yellow~g ~lightGray~|*| | | | |*|
10525-
					T:go("L2U1")
10525+
10526-
					T:place("dirt", "down")
10526+
10527-
					T:go("B1R1 F1D1R1")
10527+
10528-
					R.ready = true
10528+
10529
10530
]] -- Create enclosed area
10531
	info.sub[84] = 
10532-
			-- if networked will be in air 2 blocks above barrel or stone
10532+
10533
10534-
			T:place("dirt", "up")
10534+
10535-
			T:down(1)	 --should be on corner
10535+
10536-
			for turns = 1, 4 do
10536+
10537
|*~blue~| | | | | | |~lightGray~*|
10538-
				success, storage = utils.isStorage("down")
10538+
10539-
				if storage == "modem" then
10539+
10540-
					T:go("R1F1D1")
10540+
10541-
					R.ready = true
10541+
10542
|*|*|*|*|*|*|*|*|  ~yellow~Width~blue~: ~yellow~6, ~orange~length~blue~:~orange~ 6
10543
10544-
				T:go("B1R1")
10544+
10545
	info.sub[85] = info.sub[56] -- Sinking platform
10546
	info.sub[861] = 
10547
[[~yellow~Turtle placement  ~red~V~lime~ < ^ > ~yellow~over monument
10548
10549
~red~******    ******  * ~lightGray~= Avoid this area
10550-
		return R	-- R.ready == false
10550+
10551
******    ******  ~lime~< ^ > ~lightGray~Ideal facing~lightGray~
10552
******    ******
10553-
	function lib.goToLeft(R, plotCountR)
10553+
10554-
		T:go("U1R2 F"..plotCountR * 11 .."D1R2")	-- return home and continue with front
10554+
10555-
		if R.config ~= nil then
10555+
10556-
			local coord = R.config.currentPlot
10556+
10557-
			for i = 1, plotCountR do
10557+
10558-
				coord = lib.configUpdateCoords(R, coord, "left")
10558+
10559
10560-
			R.config.currentPlot = coord
10560+
10561
[[~yellow~Turtle positions ~red~> ^ < V
10562
10563
~lightGray~|*|~red~>~lightGray~|*|*|*|*|*|~red~<~lightGray~|*|  ~red~NOT ~lightGray~corner blocks!
10564-
	function lib.goToFront(R, plotCountF)
10564+
10565-
		T:go("U1R1F"..plotCountF * 11 .."D1L1")
10565+
10566-
		if R.config ~= nil then
10566+
10567-
			local coord = R.config.currentPlot
10567+
10568-
			for i = 1, plotCountF do
10568+
10569-
				coord = lib.configUpdateCoords(R, coord, "back")
10569+
10570
|~red~^~lightGray~|             |~red~^~lightGray~|  ~yellow~with stone.~lightGray~
10571-
			R.config.currentPlot = coord
10571+
10572
]] -- Ocean monument build retaining walls
10573
10574
	info.sub[863] = 
10575-
	function lib.gotoTree(R)
10575+
10576
10577-
		if not R.networkFarm then
10577+
10578-
			T:turnRight(1)							-- face storage
10578+
10579
~lightGray~|~red~>~cyan~| *****   ***** |~red~<~lightGray~|
10580-
		T:saveToLog("Extracting saplings from storage")
10580+
10581-
		lib.getSaplings(R, "forward") 				-- gets one sapling only (if present)
10581+
10582-
		T:saveToLog("Moving to tree position")
10582+
10583-
		if R.networkFarm then
10583+
10584-
			T:turnRight(1)							-- face wall next to corner barrel
10584+
10585
|*|*|*|*|*|*|*|*|*|*|
10586-
		T:go("U1F1R1")								-- move on top of wall/storage. face tree direction
10586+
10587
	info.sub[864] = info.sub[863]
10588-
		-- check if tree or dirt ahead
10588+
10589-
		if turtle.forward() then 					-- No tree or sapling ahead. assume tree is missing or 2 blocks above
10589+
10590-
			if T:getBlockType("down") == "minecraft:dirt" then
10590+
10591-
				turtle.back()						-- older design, return 
10591+
10592
~green~|*|*|*|*|*~brown~|*|*|*|~red~V~brown~|*|
10593
~green~|~red~>~green~|- - - - ~brown~- - - -|*|
10594-
				if turtle.detectUp() then			-- dirt above = new tree layout
10594+
10595-
					if T:getBlockType("up") == "minecraft:dirt" then
10595+
10596-
						T:go("B1U2")				-- check tree in elevated position
10596+
10597
~orange~|*|- - - - ~lime~- - - -|*| ~lightGray~6 chests / area
10598-
						turtle.back()				-- not dirt above ? removed or lost
10598+
10599
~orange~|*|- - - - ~lime~- - - -|*|
10600
~orange~|*|- - - - ~lime~- - - -|~red~<~lime~| ~lightGray~30,000 fuel each!
10601
~orange~|*|~red~^~orange~|*|*|*~lime~|*|*|*|*|*| ~lightGray~3,000 stone each!
10602
]] -- Ocean monument drain and remove 1 of 4 quarters
10603-
		lib.harvestTree(R, "forward") 				-- fell tree or plant sapling, ends facing tree / dirt / sapling. sticks already used for fuel. excess saplings placed
10603+
10604-
		T:go("R1F1D1R1")							-- return to base, facing crops 
10604+
10605-
		if R.networkFarm then
10605+
10606-
			network.sendItemToNetworkStorage(R, "barrel", "sapling", 64) --move saplings to any attached barrel
10606+
10607
 ~red~- ~blue~- ~red~- ~blue~- ~red~- ~blue~- ~red~-    ~red~- ~blue~- ~red~-~lightGray~|*|- ~blue~- ~red~-
10608-
			T:turnRight(1)							-- facing plot storage 
10608+
10609-
			T:saveToLog("Dropping saplings into storage")
10609+
10610-
			T:dropItem("sapling", "forward", 0)	-- drop all saplings forward into chest/barrel
10610+
10611
|*|*|*|*|*|*|*|  |*|*|*|*|*|*|*|
10612
10613-
		-- ends in field facing crops
10613+
10614
~brown~L ~lightGray~= Ladder
10615
10616-
	function lib.harvest(R, seed, crop)
10616+
10617
	info.sub[88] = 
10618
[[~yellow~Place ~red~T~yellow~urtle at water edge.
10619-
		harvest crop if ripe
10619+
10620
10621
   ~red~T                       T
10622
~lightGray~|*|*| ~blue~| | | | | | | | | | ~lightGray~|*|
10623-
		crop is full name. if mixed seeds only one type returned
10623+
10624
|*|*| ~blue~| | | | | | | ~lightGray~|*|*|*|*|
10625
|*|*|*| ~blue~| | |~green~p~blue~| | ~lightGray~|*|*|*|*|*|
10626
|*|*|*| ~blue~| | |~green~p~lightGray~|*|*|*|*|*|*|*|
10627
|*|*|*|*~blue~|d~lightGray~|*|*|*|*|*|*|*|*|*|
10628
|*|*|*|*|*|*|*|*|*|*|*|*|*|*|
10629
]] -- Clear water plants from enclosed area
10630
	info.sub[89] = 
10631
[[Place me on the left corner of the top
10632
of retaining wall facing water
10633-
				lib.replant(R, seed, crop)	-- check and replant crop below
10633+
10634
	info.sub[810] = 
10635
[[Place me on the left corner of the top
10636
of retaining wall facing water.
10637-
					if utils.isStorage("down") then	-- chest, barrel or modem
10637+
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
                 |*|*|*|*|*|*|
10650
                 |*|*|*|*|*|*|
10651-
				lib.replant(R, seed, crop)
10651+
10652
10653
~red~> T~lightGray~ = Turtle
10654
				 
10655
]] -- Build a wall
10656-
		if utils.isStorage("down") then
10656+
10657
[[~yellow~Build a walled rectangle / house
10658
10659
Plan view         Side view
10660-
		lib.storeCrops(R) -- rotates from start to deposit seeds and crops, ends facing crops
10660+
10661-
		return R, isFarmToRight, isFarmToFront
10661+
10662
~yellow~e ~lightGray~|*| | | | |*|   |*|*|*|*|*|*|
10663
~yellow~n ~lightGray~|*| | | | |*|   |*|*|*|*|*|*|
10664-
	function lib.harvestTree(R, direction)
10664+
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
10669
]] -- Build a rectangular structure
10670-
			Return to top of storage
10670+
10671
[[~yellow~Build a gable roof
10672
Gable built on right side of turtle
10673
Plan view       End view (width)
10674-
		local inFront = T:getBlockType("forward")
10674+
10675-
		print("Checking tree")
10675+
10676-
		if inFront == "" then -- no tree or sapling
10676+
10677-
			print("No sapling: planting sapling")
10677+
10678-
			T:place("sapling", "forward")
10678+
10679-
		elseif inFront:find("log") ~= nil or direction == "up" then -- tree above or in front
10679+
10680-
			-- clsTurtle.harvestTree(self, extend, craftChest, direction)
10680+
10681-
			print("Harvesting tree")
10681+
10682-
			T:harvestTree(false, false, direction) --do not investigate side branches in case chunk unloaded
10682+
10683-
			T:back(1) -- face dirt
10683+
10684-
			-- place(self, blockType, direction, leaveExisting, signText)
10684+
10685-
			T:place("sapling", "forward")
10685+
10686
Plan view        End view (width)
10687-
		print("Disposing of apples")
10687+
10688-
		T:dropItem("apple", "up", 0) -- drop any apples
10688+
10689-
		utils.useSticksAsFuel()
10689+
10690
~yellow~e ~lightGray~|*| | |*|      |*|*|*|*|
10691-
		while turtle.down() do end	-- ends facing tree, on top of plot storage
10691+
10692
~yellow~g ~lightGray~|*| | |*|      |*|*|*|*|
10693
~yellow~t ~lightGray~|*| | |*|
10694-
	function lib.manageTree(R)
10694+
10695
~yellow~  W i d t h     ~red~^ T ~lightGray~= Turtle
10696-
		local isReady, crop, seed, status, R = lib.isCropReady(R, "forward")
10696+
10697-
		if crop == "" and not R.auto then			-- only ask player if not running via startup
10697+
10698-
			seed, crop = lib.askPlayerForCrops()	-- "" or  specific seed type,
10698+
10699
Redstone torch will go below me
10700
10701
~lightGray~_____
10702
~lightGray~|*|*|\                           ~red~>~lightGray~|*|
10703
    |*|~red~<                       ~lightGray~/|*|
10704
      ~lightGray~|*|______~red~T~lightGray~_________    /~lightGray~|*|~red~!
10705
       ~red~!~lightGray~|*|*|*|*|*|*|*|*|\ /|*|
10706
               ~red~!        ~lightGray~|*|*|
10707
10708
~red~T < > ~lightGray~= Turtle ~red~! ~lightGray~= Redstone Torch
10709
On block or above rail, face up slope
10710
]] -- Place redstone torch under block
10711
	info.sub[96] = info.sub[95]
10712
	info.sub[97] = 
10713-
			T:saveToLog("Running Tree Manager")
10713+
10714-
			lib.gotoTree(R) 					-- check for sapling or harvest tree, retuns to facing crops
10714+
10715
Build down            Build up~lightGray~
10716
10717
_____~red~T~lightGray~                        ___
10718-
		if logSlot > 0 then						--logs onboard, need to equip crafting table
10718+
10719-
			if R.networkFarm then
10719+
10720-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
10720+
10721
          |*|__________~red~T~lightGray~|*|
10722-
				T:go("L1F1") 					-- move to buried storage chest/barrel
10722+
10723-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
10723+
10724-
				T:go("R2F1")					-- facing seed chest/barrel
10724+
10725
	info.sub[98] =  info.sub[97]
10726
10727-
			if not R.networkFarm then
10727+
10728
	info.sub[101] = 
10729
[[~yellow~Place me on floor.~lightGray~
10730
            Measured Height:
10731-
		-- get seeds or veg based on what is growing
10731+
10732-
		if seed ~= "" then
10732+
10733-
			local seedType, seedCount = lib.getSeeds(R, "forward", seed) 	-- table: get 95 of beetroot / wheat / mysticalagriculture seeds
10733+
10734-
			if seedCount == 0 then
10734+
10735-
				T:saveToLog("No seeds available.")
10735+
10736
  |*|*|*|
10737-
		else	-- seed  = ""
10737+
10738-
			local veg, vegCount = "", 0
10738+
10739-
			if R.networkFarm then
10739+
10740-
				veg, vegCount = lib.getVeg(R, "forward", crop)	-- gets any carrots / potatoes
10740+
10741
	info.sub[102] = 
10742-
				T:turnRight(1)					-- face crop chests
10742+
10743-
				veg, vegCount = lib.getVeg(R, "forward", crop)	-- gets any carrots / potatoes
10743+
10744-
				T:turnRight(2)					-- face crops
10744+
10745
    ~red~T~lightGray~
10746-
			if veg ~= "" then
10746+
10747-
				crop = veg
10747+
10748
3|*|*|
10749
4|*|*|         Measured depth: 
10750
5|*|~lime~S~lightGray~|         ~lime~5. Specific block found
10751-
		return seed, crop	-- name of seed / "",  crop / ""
10751+
10752
7|*|*|~lightBlue~*~lightGray~|*| |   ~lightBlue~6. Obstruction below
10753
]] -- measure depth
10754-
	function lib.isCropReady(R, direction)
10754+
10755
[[~yellow~Length measurement
10756
10757
~lightGray~1 2 3 4 ~lime~5~lightGray~ 6 ~lime~7 ~cyan~8 ~lightBlue~9~lightGray~ 10
10758-
		local crop, seed = "", ""
10758+
10759
~lightGray~*|*|*|*|*|*|~lime~S~lightGray~| |*|*|  ~lime~7. Search block
10760
~red~T~lightGray~                |*|  ~lightBlue~9. Obstruction
10761
~lightGray~*|*|*|*|~lime~S~lightGray~|*|*| |*|*|  ~lime~5. Search block
10762
                      ~cyan~8. No block down
10763
10764
~red~T ~lightGray~= Turtle
10765
10766
]] -- measure length
10767
	info.sub[104] = info.sub[88] -- measure deepest section of water
10768-
		--T:saveToLog("lib.isCropReady(R,".. direction..")")
10768+
10769-
		if success then			-- inspect() success
10769+
10770-
			crop = data.name	-- name of growing plant
10770+
10771-
			if crop:find("flower") ~= nil then
10771+
10772-
				T:saveToLog("Flower "..crop.." found")
10772+
10773-
				return true, crop, "open"	-- eg torchflower
10773+
10774
10775-
				if data.name:find("beetroot") ~= nil then
10775+
10776-
					status = data.state.age.." / 3"
10776+
10777-
					if data.state.age == 3 then
10777+
10778-
						isReady = true
10778+
10779
]] -- Borehole: Analyse blocks below
10780-
				else			-- all other crops inc Mystical Agriculture
10780+
10781-
					status = data.state.age.." / 7"
10781+
10782-
					if data.state.age == 7 then
10782+
10783-
						isReady = true
10783+
10784
~lightGray~| |~lime~1~lightGray~|~lime~2~lightGray~| |  |~lime~1~lightGray~| | |~lime~2~lightGray~| | | | | | ground 2
10785
~lightGray~|*|~blue~W|W~lightGray~|*|  |*|~blue~W|W~lightGray~|*| |*|~blue~1~lightGray~|~blue~2~lightGray~|*| water  2
10786
10787-
			seed, crop = lib.getCropSeed(crop)
10787+
10788
~lightGray~|~orange~1~lightGray~|~orange~2~lightGray~|~orange~3~lightGray~|~orange~4~lightGray~|                      ground 4
10789-
		--T:saveToLog("return isReady = "..tostring(isReady)..", crop = "..crop..", seed = "..seed..", status = "..status)
10789+
10790-
		-- crop: "", "minecraft:carrots", "minecraft:beetroot", "minecraft:potatoes", "minecraft:wheat", "mysticalagriculture:*_crop"
10790+
10791-
		return isReady, crop, seed, status, R	-- eg true, "minecraft:carrots", "7 / 7" or false, "mysticalagriculture:inferium_crop", "1 / 7"
10791+
10792
	local line = menu.clear()
10793
	if menuLevel == 1 then -- general help
10794-
	function lib.locateFarm(R)
10794+
10795-
		T:saveToLog("? over water = false")
10795+
10796
		read()
10797
		return ""
10798-
				detected = i
10798+
10799
		if info.sub[menuItem] ~= nil then -- help file exists
10800
			line = menu.colourText(line, info.sub[menuItem], true, true)
10801
			if noMenu then
10802-
		T:saveToLog("Neighbouring blocks detected at: "..detected)
10802+
10803-
		-- check if on corner
10803+
10804-
		if detected > 0 then
10804+
10805-
			--assume tree / sapling on corner on older farm type
10805+
10806-
			T:saveToLog("Assuming next to tree / sapling. Moving..")
10806+
10807-
			T:go("R"..detected .."F1D1R1")
10807+
10808-
		else	-- no surrounding blocks
10808+
10809
				end
10810
			else
10811-
				success, storage = utils.isStorage("down")
10811+
10812-
				T:saveToLog("i = "..i..",success = "..tostring(success)..". storage = "..storage)
10812+
10813
				return read()
10814-
					discovered = discovered .. storage
10814+
10815-
					if storage == "modem" then
10815+
10816-
						R.networkFarm = true
10816+
10817
end
10818
10819-
					if storage == "" then
10819+
10820-
						discovered = discovered .. "_"
10820+
10821
	options.main =
10822-
						discovered = discovered .. "wall"
10822+
10823
		"Mining (includes Nether)",
10824
		"Forestry",
10825
		"Farming",
10826
		"Obsidian, Nether & End",
10827
		"Canal, bridge and walkway",
10828-
			T:saveToLog("Neighbouring blocks found:"..discovered)
10828+
10829
		"Area shaping and clearing",
10830-
		-- check discovered for patterns eg {_wall_barrel}
10830+
10831-
		-- |W|*|B| * = turtle on wall
10831+
10832-
		-- | | |M|
10832+
		"Measuring tools"
10833-
		if R.networkFarm then
10833+
10834-
			-- E = wall_barrel_, N = _barrel_wall, W = wall_barrel_, S = _wall_barrel 
10834+
10835-
			if discovered == "_wall_barrel" then
10835+
10836-
				T:go("F1D1R1")
10836+
10837-
			elseif discovered == "barrel_wall_" then
10837+
10838
		"Create mine at this level",
10839-
			elseif discovered == "_barrel_wall" then
10839+
10840-
				T:go("R2F1D1R1")
10840+
10841-
			elseif discovered == "wall_barrel_" then
10841+
10842-
				T:go("L1F1D1R1")
10842+
10843
		"Mine bedrock level",
10844-
		else	-- normal storage farm
10844+
10845-
			if discovered == "_chest_chest" then
10845+
10846-
				T:go("F1D1R1")
10846+
10847-
			elseif discovered == "chest__chest" then
10847+
10848
		"Fell Tree",
10849-
			elseif discovered == "_chest_chest" then
10849+
		"Create tree farm",
10850-
				T:go("R2F1D1R1")
10850+
10851-
			elseif discovered == "chest_chest_" then
10851+
10852-
				T:go("L1F1D1R1")
10852+
10853
		"Harvest and replant forest"
10854
	})
10855
	table.insert(options,
10856
	{
10857
		"Create modular crop farm",
10858-
				success, storage = utils.isStorage("forward")	-- true/false, chest, barrel, modem / ""
10858+
10859-
				if success and storage == "modem" then
10859+
		"Plant, harvest or manage crop farm",
10860-
					R.networkFarm = true
10860+
10861
		"Fence or wall an enclosure"
10862
	})	
10863
	table.insert(options,					
10864-
			R.ready = true
10864+
10865
		"Dig obsidian field",
10866
		"Build Nether Portal",
10867
		"Demolish Nether Portal",
10868-
	function lib.plantCrop(R, seed, crop, direction)
10868+
10869
		"Undermine Dragon Towers",
10870
		"Deactivate Dragon Tower",
10871
		"Build dragon water trap",
10872
		"Build portal ladder & platform",
10873
		"Shulker harvester"
10874-
		--T:saveToLog("lib.plantCrop(R, seed = "..seed..", crop = "..crop)
10874+
10875
	table.insert(options,
10876-
		-- place(blockType, direction, leaveExisting, signText, doNotAttack)
10876+
10877-
		if seed == "" then	-- must be a crop
10877+
10878-
			success = T:place(crop, direction, true, "", true)
10878+
10879-
			--success = T:place(crop, direction, false, "", true)
10879+
10880-
			--T:saveToLog("Seed = "..seed..". Placing "..crop..": success = "..tostring(success))
10880+
10881
		"Platform",
10882-
			success = T:place(seed, direction, true, "", true) 	-- eg "mysticalagriculture:air_seeds"
10882+
10883-
			--success = T:place(seed, direction, false, "", true) 	-- eg "mysticalagriculture:air_seeds"
10883+
10884-
			--T:saveToLog("Placing "..seed..": success = "..tostring(success))
10884+
10885
	table.insert(options,
10886-
		if not success then
10886+
10887-
			success = T:place("seed", direction, true, "", true)			-- failsafe
10887+
10888-
			--success = T:place("seed", direction, false, "", true)			-- failsafe
10888+
10889-
			--T:saveToLog("Placing generic 'seeds' : success = "..tostring(success))
10889+
10890
		"Create mob bubble lift",
10891-
		return success
10891+
10892
		"Build Endermen observation tower"
10893
	})
10894-
	function lib.replant(R, seed, crop)
10894+
10895-
		-- check crop below. If ripe, dig and replant seed
10895+
10896-
		local isReady, cropType, seedType, status
10896+
10897-
		isReady, cropType, seedType, status, R = lib.isCropReady(R, "down")	-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
10897+
10898-
		if cropType == "" then					-- no crop below (above water, storage or dirt)
10898+
10899-
			turtle.digDown("right")				-- use hoe
10899+
10900-
			lib.plantCrop(R, seed, crop, "down")-- plant crop
10900+
10901-
		elseif isReady then						-- crop below is ready
10901+
10902-
			turtle.digDown("left")				-- use pickaxe
10902+
10903-
			lib.plantCrop(R, seedType, cropType, "down")	-- plant crop
10903+
10904
		"Place a floor or ceiling",
10905
		"Direct control of movement"
10906-
		return R
10906+
10907
	table.insert(options,
10908
	{
10909-
	function lib.refuelWithLogs(R, logSlot)
10909+
10910-
		-- saplings already dropped, apples dumped, sticks used as fuel
10910+
10911-
		-- assume positioned in front of crops if networked, or over buried storage
10911+
10912
		"Clear volume of water",
10913
		"Sinking platform",
10914-
		-- networked version uses remote storage, turtle faces crops and has modem at back
10914+
10915-
		local slot, count = 0, 0
10915+
10916-
		T:saveToLog("Sorting Inventory")	-- make sure all items collected together
10916+
10917-
		T:sortInventory(true)
10917+
10918-
		T:saveToLog("Logs present: collecting crafting table")
10918+
10919-
		if R.networkFarm then
10919+
10920-
			slot, count = network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
10920+
10921-
			--slot = lib.getItemFromNetworkBarrels(R, "minecraft:crafting_table", 1)
10921+
10922
		"Build a wall",
10923-
			while T:suck("down") do end					-- empty out barrel/chest to find crafting table
10923+
10924
		"Build a gable end roof",
10925
		"Build a pitched roof",
10926
		"Place Redstone:torch level track",
10927
		"Place Redstone:torch upward track",
10928
		"Build downward track",
10929-
			if R.networkFarm then
10929+
10930-
				network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1)
10930+
10931
	table.insert(options,
10932
	{
10933
		"Measure height",
10934-
					T:drop("down", i)	-- into water if networked, buried chest otherwise
10934+
10935
		"Measure length",
10936
		"Measure greatest depth",
10937
		"Borehole: Analyse blocks below"
10938
	})
10939
	
10940
	return options
10941
end
10942
10943-
			while logSlot > 0 and turtle.getFuelLevel() < turtle.getFuelLimit() do
10943+
10944
	local options = {}
10945-
				turtle.refuel()						-- refuel using planks
10945+
10946
	{
10947
		colors.lightGray, 	-- Mining (includes Nether)
10948-
			while T:suck("down") do end			-- recover items from water / storage below
10948+
10949-
			--T:unequip("right")
10949+
10950-
			if R.networkFarm then
10950+
10951-
				slot = network.getItemFromNetwork("barrel", "minecraft:diamond_hoe", 1)
10951+
10952
		colors.lightGray, 	-- Mob farm tools
10953-
			if not T:equip("right", "minecraft:diamond_hoe") then		-- re-equip hoe/remove crafting table
10953+
10954
		colors.blue, 		-- Lava and Water
10955
		colors.cyan,		-- Railway
10956-
			if R.networkFarm then
10956+
		colors.purple 		-- Measuring tools
10957-
				network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1)
10957+
10958
	table.insert(options,
10959-
				T:dropItem("minecraft:crafting_table", "down")
10959+
10960
		colors.brown, 		-- Ladder up or down
10961
		colors.lightGray, 	-- Stairs up or down
10962
		colors.lightGray, 	-- Create mine at this level
10963
		colors.blue, 		-- Safe drop to water block
10964
		colors.blue, 		-- Single column bubble lift
10965
		colors.magenta, 	-- QuickMine corridor system
10966
		colors.pink, 		-- QuickMine rectangle
10967-
	function lib.storeCrops(R)
10967+
10968-
		-- place crops and seeds into chests. starts facing crops
10968+
10969
	})
10970
	table.insert(options,
10971-
		if R.networkFarm then
10971+
10972-
			network.emptyInventory(R, {"sapling", "diamond_hoe", "crafting"}, {"all"}, true)
10972+
10973
		colors.lightGray, 	-- Create tree farm
10974-
			T:turnRight(1)	-- face seed storage
10974+
10975-
			lib.storeSeeds(R, "forward")
10975+
10976
		colors.brown, 		-- Fence or wall an enclosure
10977-
			if utils.isStorage(direction) then
10977+
10978-
				T:dropAll(direction) -- drops everything including essences
10978+
10979
	table.insert(options,
10980-
			T:turnRight(2) -- facing crops again
10980+
10981
		colors.yellow, 		-- Create modular crop farm
10982
		colors.green, 		-- Extend modular crop farm
10983
		colors.lime, 		-- Manage modular crop farm
10984-
	function lib.storeSeeds(R, direction)
10984+
10985
		colors.brown 		-- Build rectangle wall or fence
10986-
		if utils.isStorage(direction) then -- chest exists
10986+
10987-
			if not R.networkFarm then
10987+
10988-
				if T:getItemSlot("minecraft:wheat_seeds") > 0 then
10988+
10989-
					if not T:dropItem("minecraft:wheat_seeds", direction, 0) then
10989+
10990-
						T:dropItem("minecraft:wheat_seeds", "up", 0)
10990+
10991-
					end -- drop all wheat seeds
10991+
10992-
				elseif T:getItemSlot("minecraft:beetroot_seeds") > 0 then
10992+
10993-
					if not T:dropItem("minecraft:beetroot_seeds", direction, 0) then-- drop all beetroot seeds
10993+
10994-
						T:dropItem("minecraft:beetroot_seeds", "up", 0)
10994+
10995
		colors.blue, 		-- Build dragon water trap
10996-
				elseif T:getItemSlot("seeds") > 0 then
10996+
10997-
					if not T:dropItem("seeds", direction, 0) then	-- drop all other seeds as chest is full
10997+
10998-
						T:dropItem("seeds", "up", 0)
10998+
10999-
						-- or could print a message and wait for player to empty storage
10999+
11000
	{
11001
		colors.lightGray, 	-- Continuous path
11002
		colors.gray, 		-- Covered walkway / tunnel
11003
		colors.blue, 		-- Water canal
11004
		colors.lightBlue, 	-- Ice canal (4 options)
11005
		colors.brown, 		-- Platform
11006-
	function lib.watchFarm(R)
11006+
11007
		colors.cyan 		-- Boat bubble lift
11008
	})
11009
	table.insert(options,
11010
	{
11011
		colors.brown, 		-- Cube around spawner (NOT blaze)
11012-
		local isReady, crop, seed, status	-- bool, string, string, integer
11012+
11013-
		isReady, crop, seed, status, R = lib.isCropReady(R, "forward")		-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
11013+
11014
		colors.blue, 		-- Create mob bubble lift
11015
		colors.brown, 		-- Dig mob drop trench
11016
		colors.gray 		-- Build Endermen observation tower
11017
	})
11018
	table.insert(options,
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-
					if crop:find("mysticalagriculture") ~= nil then
11023+
11024-
						R.mysticalAgriculture = true
11024+
11025
		colors.orange, 		-- Clear solid structure up/down
11026
		colors.brown, 		-- Dig a trench
11027
		colors.gray, 		-- Carve mountain side
11028-
				isReady, crop, seed, status, R = lib.isCropReady(R, "forward")			-- eg true, "minecraft:carrots", "7 / 7" or false, "", ""
11028+
11029
		colors.red 			-- Direct control of movement
11030-
		until isReady
11030+
11031-
		T:saveToLog("Local crops ripe", true)
11031+
11032-
		seed, crop = lib.manageTree(R) -- "", "" or name of seed, crop
11032+
11033-
		return seed, crop
11033+
11034
		colors.blue, 		-- Vertical wall from surface
11035
		colors.blue, 		-- Create enclosed area
11036
		colors.cyan, 		-- Clear volume of water
11037-
		ENTRY POINT**********************************************
11037+
11038
		colors.orange, 		-- Ocean monument utilities
11039
		colors.brown, 		-- Ladder down to water/lava
11040
		colors.green, 		-- Clear water plants
11041
		colors.lightBlue, 	-- Convert all water to source
11042
		colors.blue 		-- Create sloping water
11043
	})
11044
	table.insert(options,
11045-
	--T:setUseLog(true, "farmLog.txt", true)	-- T:setUseLog(use, filename, delete)
11045+
11046-
	--dbug = true								-- set dbug flag
11046+
11047-
	--if not R.auto then						-- not running from startup.lua
11047+
11048-
		--utils.waitForInput("Logging and debugging enabled")	--utils.waitForInput(message)
11048+
11049-
	--end
11049+
11050
		colors.red, 		-- Place Redstone:torch level track
11051-
	R = utils.checkFarmPosition(R)	-- should be facing crops, placed above water source. R.ready, R.networkFarm is true/false
11051+
11052-
	if R.networkFarm then
11052+
11053-
		local message = network.loadStorageLists()	-- initialises or creates lists of where an item can be found: GLOBAL LISTS!
11053+
11054-
		if message ~= nil then return {message} end
11054+
11055
	table.insert(options,
11056-
	if not R.ready then		-- not in correct starting place
11056+
11057-
		R = lib.goHome(R)
11057+
11058-
		if not R.ready then -- try to find home
11058+
11059
		colors.magenta, 	-- Measure length
11060
		colors.pink, 		-- Measure greatest depth
11061
		colors.lightBlue	-- Borehole: Analyse blocks below
11062
	})
11063
	
11064-
				"barrel or chest to my right and behind",
11064+
11065-
				"(or modem behind if networked farm)"
11065+
11066
11067
local function chooseTask(R)
11068
--[[ 
11069-
	if not T:isEmpty() then		-- items in turtle inventory
11069+
11070-
		local logSlot = T:getItemSlot("log")
11070+
11071
	coloured menu:	
11072-
			if R.networkFarm then
11072+
11073-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
11073+
11074
		prompt = colors.green,
11075-
				T:go("L1F1") 					-- move to buried storage chest/barrel
11075+
11076-
				lib.refuelWithLogs(R, logSlot) 	-- use any logs for fuel
11076+
11077-
				T:go("R2F1")					-- facing seed chest/barrel
11077+
11078
	choice, modifier = menu.menu or menu.new("Choose your option", options, pp)
11079
	]]
11080-
		if not T:isEmpty() then					-- still items in turtle inventory
11080+
11081-
			lib.storeCrops(R)
11081+
11082
	function lib.getHelp(choice, itemsRequired, pp)
11083
		local listOfItems = itemsRequired[choice]
11084-
	-- in correct position. Check equipment first, harvest tree, re-equip then harvest crops
11084+
11085-
	local hoeSlot = lib.checkEquipment(R, "minecraft:diamond_hoe")	-- returns slot  or 0
11085+
11086
			lib.showItems(listOfItems)
11087-
	if hoeSlot == 0 then		-- hoe not in inventory
11087+
11088-
		local message
11088+
11089-
		hoeSlot, message = lib.getHoe()
11089+
11090-
		if message ~= "" then
11090+
11091-
			return {message}
11091+
11092
		if option == 2 then
11093
			choice = -2	-- return to subMenu
11094-
	-- hoe present or user cancelled request for hoe. Turtle is ready to exchange items
11094+
11095-
	if hoeSlot > 0 then
11095+
11096-
		T:equip("right", "minecraft:diamond_hoe", 0) -- equip hoe and put crafting chest into barrel
11096+
11097-
		if R.networkFarm then	-- drop crafting table into storage
11097+
11098-
			network.sendItemToNetworkStorage(R, "barrel", "minecraft:crafting_table", 1)
11098+
11099-
		else	-- put crafting table into barrel in floor
11099+
11100-
			T:dropItem("crafting", "down")
11100+
11101-
			T:go("B1R1")
11101+
11102
	end
11103-
	else	-- hoe not present: return to start and exit
11103+
11104-
		if not R.networkFarm then
11104+
11105-
			T:go("B1R1")
11105+
11106
		if next(listOfItems) ~= nil then
11107
			menu.colourPrint("Items required:", colors.lime)
11108
			for k,v in pairs(listOfItems) do
11109
				menu.colourPrint("  "..v, colors.lightGray)
11110
			end
11111-
	local isFarmToRight, isFarmToFront = false, false
11111+
11112-
	local isReady, crop, seed, status
11112+
11113-
	isReady, crop, seed, status, R = lib.isCropReady(R, "forward")
11113+
11114
		menu.colourWrite("Enter to continue", colors.yellow, colors.black, nil, true)
11115-
	local init = false
11115+
11116
	end
11117-
		seed, crop = lib.askPlayerForCrops()
11117+
11118-
		if crop ~= "" or seed  ~= "" then	-- something has been chosen
11118+
11119-
			T:saveToLog("Initial planting of "..crop, true)
11119+
11120-
			R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop)	-- harvest plot a1 plots to right / front recorded	
11120+
11121-
			init = true
11121+
11122
	
11123-
			watch = false	-- not watching, continue with planting
11123+
11124
		if subChoice > 9 then -- need more than 9 sub-options
11125
			choice = subChoice + (choice * 100) -- 10 = 10 + 1000 = 1100
11126
		else -- eg main option 1 (mining), sub-option 1 (create mine) = 1 + 10 = 11
11127-
		if watch and not init then -- init true when farm first planted
11127+
11128-
			seed, crop = lib.watchFarm(R) -- waits if required, returns seed / crop
11128+
11129-
			init = false
11129+
11130
	end
11131-
		T:saveToLog("Beginning "..crop.. " management", true)
11131+
11132-
		R, isFarmToRight, isFarmToFront = lib.harvest(R, seed, crop)	-- harvest plot a1 plots to right / front recorded
11132+
11133-
		lib.farmAll(R, isFarmToRight, isFarmToFront)
11133+
11134
	local prompt = "Choose an option"
11135-
			if R.networkFarm then
11135+
11136-
				T:unequip("right")	-- unequip hoe
11136+
11137-
				network.getItemFromNetwork("barrel", "minecraft:crafting_table", 1)
11137+
11138-
				network.sendItemToNetworkStorage(R, "barrel", "minecraft:diamond_hoe", 1)
11138+
11139-
				T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table
11139+
11140
	local menuState = 0 -- use main menu
11141-
				T:go("L1F1")
11141+
11142-
				while T:suck("down") do end						-- recover items from storagebelow
11142+
11143-
				T:equip("right", "minecraft:crafting_table", 0) -- equip crafting_table 
11143+
11144-
				T:dropItem("minecraft:diamond_hoe", "down") 				-- drop hoe into storage
11144+
11145-
				T:dropItem("crafting", "down") 					-- in case spare one picked by mistake
11145+
11146
		menu returns choice=nil if user enters just q or h
11147
		menu returns choice=2, modifier = "h" if 2h entered
11148
		Mining (includes Nether)		white
11149
		Forestry						lime
11150
		Farming							lime
11151
		Obsidian, Nether & End Portal	brown
11152
		Canal, bridge and walkway		pink	
11153
		Mob farm tools					gray
11154
		Area shaping and clearing		purple	
11155
		Lava and Water					blue
11156
		Railway							magenta
11157
		Measuring tools					cyan		
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-
	--local pp = utils.getPrettyPrint()	
11190+
11191-
	local choices = {"Plant or harvest this farm complex"}	-- 1.
11191+
11192
					R.choice = -1
11193
					return R
11194
				elseif index == 0 then 
11195-
		table.insert(choices, "Disable automatic farm management") -- 2.
11195+
11196
					menuState = 0 -- if R.choice reset to 0 then back to main menu
11197-
		table.insert(choices, "Enable automatic farm management") -- 2.
11197+
11198
			end
11199
			if subChoice ~= nil then
11200-
	if not R.networkFarm then
11200+
11201-
		table.insert(choices, "Convert to Network Storage")		-- 3.
11201+
11202-
		table.insert(pp.itemColours, colors.magenta)
11202+
11203
		end
11204-
	if R.mysticalAgriculture then
11204+
11205-
		--table.insert(choices, "Convert to Mystical Agriculture")
11205+
11206-
		table.insert(choices, "Upgrade Mystical Agriculture soil")	--3/4
11206+
11207-
		table.insert(pp.itemColours, colors.green)
11207+
11208
local function getTask(R)
11209
	-- Called from main(): R = getTask(R)
11210
	local lib = {}
11211
	
11212
	function lib.isAutoHelp(choice, noAutoHelp)
11213
		for _, v in ipairs(noAutoHelp) do
11214
			if choice == v then
11215
				return true
11216
			end
11217
		end
11218
		return false
11219
	end
11220-
	elseif R.subChoice == 2 then -- enable/disable auto farm
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
		local currentLevel = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.lightGray)
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-
	--elseif R.subChoice == 3 and #choices == 4 then -- convert normal farm to network storage
11245+
11246-
	elseif R.subChoice == 3 then -- convert normal farm to network storage
11246+
11247-
		local isMain = false
11247+
11248
						 "On ceiling, move forward to start"}
11249-
		local message = ("~yellow~You have chosen to convert this farm "..
11249+
11250-
						 "to ~magenta~network storage ~yellow~with modems."..
11250+
11251-
						 "All ~brown~chests and barrels ~red~will be removed.\n")
11251+
11252-
		line = menu.colourText(line, message, true, true)
11252+
11253-
		if menu.getBoolean("Is this the main or only plot? (y/n)", line + 3, colors.orange, colors.black) then
11253+
11254-
			isMain = true
11254+
11255
		R.width 	= menu.getInteger("Width (2-64 default 17) ", 2, 64, nil, colors.yellow, nil, 17)
11256-
		T:checkInventoryForItem({"stone"}, {16})
11256+
11257-
		T:checkInventoryForItem({"dirt"}, {2})
11257+
11258
		if mcMajorVersion >= 1.18 then
11259-
		T:checkInventoryForItem({"barrel"}, {1})
11259+
11260-
		T:checkInventoryForItem({"ladder"}, {5})
11260+
11261-
		if isMain then
11261+
11262-
			T:checkInventoryForItem({"chest"}, {8})
11262+
11263-
			T:checkInventoryForItem({"wired_modem_full"}, {3})
11263+
11264-
			T:checkInventoryForItem({"computercraft:cable"}, {70})
11264+
11265-
			return createFarm(R, "convertWithStorage")
11265+
11266
						 "On ceiling, move forward to start",
11267-
			T:checkInventoryForItem({"wired_modem_full"}, {2})
11267+
11268-
			T:checkInventoryForItem({"computercraft:cable"}, {57})
11268+
11269-
			return createFarm(R, "convert")
11269+
11270
		if modifier == "q" then -- quit chosen
11271-
	--elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present)
11271+
11272-
	--elseif R.subChoice == 3 and #choices == 3 then -- upgrade farmland with essence (network opt not present)
11272+
11273-
		--return upgradeFarmland(R)
11273+
11274-
	elseif R.subChoice == 4 then -- upgrade farmland with essence
11274+
11275-
		return upgradeFarmland(R)
11275+
11276
		R.subChoice = userChoice
11277
	elseif R.choice == 18 then -- Mine bedrock area
11278
		--getTaskHelp(2, R.choice, true)
11279
		--menu.clear()
11280
		R.width 	= menu.getInteger("Width (2-64 default 17) ", 2, 64, nil, colors.yellow, nil,  17)
11281
		R.length 	= menu.getInteger("Length (2-64 default 17) ", 2, 64, nil, colors.orange, nil,  17)
11282
		if menu.getBoolean("Leave bedrock exposed? (y/n) ", nil, colors.yellow) then
11283
			R.data = "leaveExposed"
11284
		end
11285
	elseif R.choice == 19 then -- salvage mine shaft
11286
		R.torchInterval = menu.getInteger("Torch spacing? (0-64)", 0, 64, nil, colors.red)
11287
-- 02. FORESTRY
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-
		T:place(R.useBlockType, "forward", false)
11642+
11643
		R.length  	= menu.getInteger("Length of the area (1-64)", 1, 64, nil, colors.orange)
11644-
		T:place("minecraft:redstone_torch", "forward", true)
11644+
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
		end
11655
	elseif R.choice == 73 then -- Clear wall
11656
		R.width 	= 1
11657
		R.length 	= menu.getInteger("Length of wall (1-256) ", 1, 256, nil, colors.orange)
11658-
		T:place("minecraft:redstone_torch", "up", false)
11658+
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-
	-- already known R.networkFarm, R.subChoice (1 = singe, 2 = double, 3 = mangrove)
11669+
11670-
	--T:place(blockType, damageNo, leaveExisting, signText)
11670+
11671
				T:forward(1)
11672
			elseif choice == 4 then
11673-
	function lib.checkSaplings(firstChoice, secondChoice)
11673+
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
			R.up = true
11682
		end
11683
		if menu.getBoolean("Remove blocks below? (y/n)", 4, colours.red) then
11684
			R.down = true
11685-
	function lib.emptyInventory(R)
11685+
11686-
		if not T:isEmpty() then
11686+
11687-
			utils.useSticksAsFuel()
11687+
11688-
			network.sendItemToNetworkStorage(R, "barrel", "sapling", 64)
11688+
11689-
			network.sendItemToNetworkStorage(R, "barrel", "propagule", 64)
11689+
11690-
			network.sendItemToNetworkStorage(R, "barrel", "apple", 64)
11690+
11691-
			network.sendItemToNetworkStorage(R, "barrel", "dirt", 64)
11691+
11692-
			network.sendItemToNetworkStorage(R, "chest", "all", 0)
11692+
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-
	function lib.getSaplingInventory(R)
11696+
11697
			if menu.getBoolean("Remove ceiling? (y/n)", nil, colors.yellow, colors.black) then
11698
				R.data.ceiling = true
11699
			end
11700
			if menu.getBoolean("Remove floor? (y/n)", nil, colors.orange, colors.black) then
11701
				R.data.floor = true
11702
			end
11703
		end
11704-
		saplings.cherry_sapling = 0
11704+
11705-
		saplings.mangrove_propagule = 0
11705+
11706
		if R.subChoice == 1 then
11707
			if menu.getBoolean("Am I outside clearing zone (y/n)?", nil, colors.yellow) then
11708
				T:forward(1)
11709
			end
11710
		else
11711-
		if T:getItemSlot("sapling") > 0 then
11711+
11712-
			for i = 1, 16 do
11712+
11713-
				if turtle.getItemCount(i) > 0 then
11713+
11714-
					local data = turtle.getItemDetail(i)
11714+
11715-
					if data.name:find("sapling") ~= nil then
11715+
11716-
						local name = data.name:sub(11) -- removes "minecraft:"
11716+
11717-
						saplings[name] = saplings[name] + data.count
11717+
11718
				T:go("D1F1")
11719
			end
11720
		end
11721-
		elseif T:getItemSlot("propagule") > 0 then
11721+
11722-
			saplings.mangrove_propagule = turtle.getItemCount(T:getItemSlot("propagule"))
11722+
11723-
		else	-- no saplings onBoard: ? automated networked farm
11723+
11724-
			if R.networkFarm then
11724+
11725-
				-- networked farms use 1 type of sapling indicated by log embedded to right of modem
11725+
11726-
				-- discovered from utils.assessTreeFarm() on manual Startup
11726+
11727-
				if R.auto then	-- called here as NOT manual startup
11727+
11728-
					R = utils.assessTreeFarm(R)
11728+
11729-
					if R.message ~= "" then
11729+
11730-
						return {R.message}	-- location of turtle error
11730+
11731
						"New floor over existing",
11732
						"Replacing current ceiling",
11733-
				local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", R.useBlockType, 16)
11733+
11734-
				if turtleCount == 0 then	-- ask player for saplings
11734+
11735-
					T:checkInventoryForItem({R.useBlockType}, {16}, true, "Saplings required for tree farm")
11735+
11736
		R.height = menu.getInteger({"Enter 0 for on-site placement",
11737-
				saplings[R.useBlockType] = saplings[R.useBlockType] + turtleCount
11737+
11738-
				turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 16)
11738+
11739-
				if turtleCount == 0 then
11739+
11740-
					turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 16)
11740+
11741
			R.width 	= menu.getInteger("Width of floor (1-64) ", 1, 64, nil, colors.yellow)
11742-
				if turtleCount == 0 then	-- ask player
11742+
11743-
					T:checkInventoryForItem({"minecraft:dirt"}, {16}, true, "Dirt required for tree farm")
11743+
11744
			R.up = true
11745-
				return saplings, R.useBlockType, R.useBlockType
11745+
11746
			R.length  	= menu.getInteger("Length of ceiling (1-64) ", 1, 64, nil, colors.orange)
11747
		end
11748
	elseif R.choice == 710 or R.choice == 83 then -- Direct movement
11749
		local choices = {"Simple path", "Covered 2 block high path"}
11750
		pp.itemColours = {colors.lime, colors.orange}
11751
		local userChoice = menu.menu("Choose your path option", choices, pp, "Type number + Enter ")
11752
		R.subChoice	= userChoice -- 1 open, 2 covered
11753
		choices = {"Command driven", "Menu driven"}
11754
		userChoice = menu.menu("Choose your preference", choices, pp, "Type number + Enter ")
11755
		if userChoice == 1 then
11756
			R.data = "cmd"
11757
		else
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-
			T:place("dirt", "down", false, "", true)
11768+
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-
				T:place(sapling, "down", false, "", true)
11774+
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-
				T:place(sapling, "down", false, "", true)
11778+
11779
				R.data = "return"
11780
			end
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
		end
11787
		if menu.getBoolean("Am I outside the active zone (y/n)?", nil, colors.yellow) then
11788
			T:forward(1)
11789
		end
11790
	elseif R.choice == 82 then -- build wall from water or lava surface downwards
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-
		T:place("dirt", "down", false, "", true)
11795+
11796
			R.data = "withPath" -- ensures turtle will break through path
11797-
		if not T:place(sapling, "down", false, "", true) then -- try specific sapling
11797+
11798-
			T:place("sapling", "down", false, "", true)		-- any available sapling
11798+
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
			R.length = menu.getInteger("Length of water", 1, 64, nil, colors.orange)
11808
		end
11809
		R.height 	= menu.getInteger("Depth of water (0=autodetect)", 0, 64, nil, colors.blue)
11810
	elseif R.choice == 85 then -- Sinking platform
11811-
	function lib.getMangroveSupplies()
11811+
11812-
		local turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:dirt", 169)
11812+
11813-
		if turtleCount < 169 then
11813+
11814-
			turtleSlot, turtleCount = network.getItemFromNetwork("chest", "minecraft:dirt", 169 - turtleCount)
11814+
11815-
			if turtleCount < 169 then	-- ask player for saplings
11815+
11816-
				T:checkInventoryForItem({"dirt"}, {169 - turtleCount})
11816+
11817
			"Build 4 corner marker columns",
11818
			"Retaining wall beween 2 columns",
11819-
		turtleSlot, turtleCount = network.getItemFromNetwork("barrel", "minecraft:mangrove_propagule", 25)
11819+
11820-
		if turtleCount == 0 then	-- ask player for saplings
11820+
11821-
			T:checkInventoryForItem({"mangrove_propagule"}, {25}, true, "Mangrove propagules required")
11821+
11822
			"Sinking platform",
11823
			"Drain and remove structure"	
11824
		}
11825-
	function lib.plantMangrove()
11825+
11826-
		T:go("L1F6 R1F1 U1")
11826+
11827-
		createFloorCeiling({width = 13, length = 13, up = false, down = true,
11827+
11828-
							height = 0, subChoice = 0, useBlockType = "minecraft:dirt",
11828+
11829-
							inventory = T:getInventory()})
11829+
11830
		menu.clear()	
11831-
		--T:go("U1F5 R1F5 L1")			-- lower left of planting area, facing Back
11831+
11832-
		T:go("U1F4 R1F4 L1")			-- lower left of planting area, facing Back
11832+
11833-
		for x = 1, 5 do
11833+
11834-
			for i = 1, 5 do
11834+
11835-
				T:place("propagule", "down")	-- left 1
11835+
11836-
				if i < 5 then
11836+
11837
			T:clear()
11838
			R.length = menu.getInteger({"Wall length minus corners","(Ocean monument default 56)","Number -> Enter or Enter only (56)"},
11839
										 1, 64, nil, {colors.yellow, colors.orange, colors.green}, colors.black, 56)
11840-
			if x % 2 == 1 then
11840+
11841-
				if x < 5 then
11841+
11842
			R.data = "clearWaterPlants"
11843
			R.silent = true
11844
			R.width 	= menu.getInteger("water width (0=auto detect) ", 0, 64, nil, colors.yellow)
11845
			R.length  	= menu.getInteger("water length (0=auto detect) ", 0, 64, nil, colors.orange)
11846
		elseif R.subChoice == 4 then -- Drain using sand utilities
11847
			R.width	  = 1
11848-
		T:go("L1F2 L1F2 D2U2 F7R2 D2")
11848+
11849
		elseif R.subChoice == 5 then -- remove sand wall using sand utilities
11850-
		T:place("propagule", "down")	-- left 1
11850+
11851
			R.length  = 0
11852-
		T:place("propagule", "down")	-- left 2
11852+
11853
			R.width = menu.getInteger("Width (excluding retaining wall)? ", 1, 1024, nil, colors.yellow)
11854-
		T:place("propagule", "down")	-- left 3/top 1
11854+
11855
			R.height = menu.getInteger("Levels to go down?", 1, 1024 / R.width * R.length, nil, colors.blue)
11856-
		T:go("R1F1")
11856+
11857-
		T:place("propagule", "down")	-- top 2
11857+
11858
			R.length = 28
11859-
		T:place("propagule", "down")	-- top 3/right 1
11859+
11860-
		T:go("R1F1")
11860+
11861
	elseif R.choice == 87 then -- Ladder to water/lava	
11862-
		T:place("propagule", "down")	-- right 2
11862+
11863
	elseif R.choice == 88 then -- Clear water plants from enclosed area
11864-
		T:place("propagule", "down")	-- right 3/bottom 1
11864+
11865-
		T:go("R1F1")
11865+
11866-
		T:place("propagule", "down")	-- bottom 2]]
11866+
11867
	elseif R.choice == 89 then -- convert flowing water to source
11868-
		--T:go("R1F1R2 D2U2 F7R2 D2")
11868+
11869
		if R.width > 0 then
11870
			R.length = menu.getInteger("water length (0=auto detect) ", 0, 64, nil, colors.orange)
11871-
	function lib.plantSingle(R)
11871+
11872-
		local sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11872+
11873-
		if count >= 1 then
11873+
11874-
			if R.networkFarm then
11874+
11875-
				T:go("U1L1 F3R1 F4") -- outside first area
11875+
11876
	
11877-
				T:go("U1F4") -- outside first area
11877+
11878
	elseif R.choice == 91 then -- Build wall
11879-
			for i = 1, 3 do	-- column 1/4
11879+
11880-
				lib.createSingle(sapling, "forward")
11880+
11881
		R.height 	= menu.getInteger("Height of wall (1-50) ", 1, 50, nil, colors.lightGray)
11882
		pp.itemColours = {colors.lime, colors.magenta}
11883-
			for i = 1, 2 do
11883+
11884-
				lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
11884+
11885
		R.width 	= menu.getInteger("Building width (1-256)", 1, 256, nil, colors.yellow)
11886
		R.length 	= menu.getInteger("Building length (1-256) ", 1, 256, nil, colors.orange)
11887-
			for i = 1, 2 do -- column 2/4
11887+
11888-
				lib.createSingle(sapling, "forward")
11888+
11889
		R.subChoice = menu.menu("What is my current position?", {"Outside building: Start ahead","Within the walls: start here"}, pp, "Type number + Enter")
11890
	elseif R.choice == 93 or R.choice == 94 then -- Build gable roof / pitched roof
11891-
			for i = 1, 2 do
11891+
11892-
				lib.createSingle(sapling, "left") -- place 4th dirt/saling and exit to right
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 -- column 3/4
11895+
11896-
				lib.createSingle(sapling, "forward")
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
11899+
11900-
				lib.createSingle(sapling, "right") -- place 4th dirt/saling and exit to right
11900+
11901
	elseif R.choice == 101 then -- measure height
11902
		pp.itemColours = {colors.lightBlue, colors.cyan, colors.lime, colors.gray}
11903-
			for i = 1, 3 do -- column 4/4
11903+
11904-
				lib.createSingle(sapling, "forward")
11904+
11905
			R.data = menu.getString({"Search for? eg 'ore', 'obsidian'",">"}, false, 3, 20, nil, {colors.lime, colors.yellow})
11906
		end
11907-
			if R.networkFarm then
11907+
11908-
				T:go("R1F3 R1F2L1") -- in-between 2 trees
11908+
11909-
				if R.auto then
11909+
11910-
					harvestTreeFarm(R)
11910+
11911
		if R.subChoice == 3 then
11912-
					T:go("L1F4R2D1")
11912+
11913
		end
11914
	elseif R.choice == 103 then -- measure length
11915-
				T:go("R1F6 L1F2 R2D1")
11915+
11916
		R.subChoice	= menu.menu("Measure using?", {"Obstruction ahead",
11917
													"No further blocks above",
11918-
			return "No saplings to plant"
11918+
11919
													"Detect specific block above",
11920
													"Detect specific block below"}, pp, "Type number + Enter") -- open direction menu options
11921
		if R.subChoice == 4 or R.subChoice == 5 then
11922
			R.data = menu.getString({"Search for? eg 'ore', 'obsidian'",">"}, false, 3, 20, nil, {colors.lime, colors.yellow})
11923
		end
11924-
	function lib.plantDouble(R)
11924+
11925
	elseif R.choice == 104 then -- measure greatest depth of water body
11926
		pp.itemColours = {colors.lime, colors.orange}
11927
		R.subChoice	= menu.menu("Measure using?", {"Player entered", "No further water below"}, pp, "Type number + Enter ") -- open direction menu options
11928
		-- 1 = player entry, 2 = water length
11929-
			if R.networkFarm then
11929+
11930-
				T:go("U1L1 F3R1 F3") -- outside first area
11930+
11931
		end
11932-
				T:go("U1F3") -- outside first area
11932+
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-
			sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11935+
11936
	
11937
	return R
11938-
			sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11938+
11939
11940
local function getTaskInventoryTo30(R)
11941-
			sapling, count = lib.checkSaplings(firstChoice, secondChoice)
11941+
11942
	local thanks = "Thank you.\n\nPress the ESC key\n\nStand Back..\n"
11943
	--local pp = utils.getPrettyPrint()
11944
	
11945-
			if R.networkFarm then
11945+
11946-
				T:go("R1F4 R1F1 L1") 			-- on left side of double tree
11946+
11947-
				if R.auto then
11947+
11948-
					harvestTreeFarm(R)
11948+
11949
	elseif R.choice == 1 then --Missing crafting table
11950-
					T:go("L1F4 L1F1 L1D1")	-- back to start
11950+
11951
		print("Crafting table being tested...")
11952
		T:setEquipment()
11953-
				T:go("R1D1 F6L1 F3R2") -- outside first area
11953+
11954
		T:checkInventoryForItem({"minecraft:chest"}, {1}) -- 0 if not present
11955
		sleep(1.5)
11956-
			return "Insufficient saplings to plant"
11956+
11957
	-- MINING
11958
	
11959
	elseif R.choice == 11 or R.choice == 12 then			-- ladder down / up / stairs down / stairs up
11960
		local description = "Creating ladder going down"	-- default action description
11961-
	if R.networkFarm then
11961+
11962-
		local message = network.loadStorageLists()	-- initialises or creates lists of where an item can be found: GLOBAL LISTS!
11962+
11963-
		if message ~= nil then return {message} end
11963+
11964-
		lib.emptyInventory(R)
11964+
11965
		
11966-
	if R.subChoice == 3 then	-- mangrove, R.networkFarm only 
11966+
11967-
		lib.getMangroveSupplies()
11967+
11968-
		lib.plantMangrove()
11968+
11969
		end
11970-
		local saplings, firstChoice, secondChoice = lib.getSaplingInventory(R)
11970+
11971-
		if firstChoice ~= "" then
11971+
11972-
			print("first sapling: "..firstChoice .. " ("..saplings[firstChoice]..")")
11972+
11973
			R.height = menu.getInteger("Current level (F3->Y coord)? ", bedrock + 5, ceiling, nil, colors.lightGray)
11974-
		if secondChoice ~= "" then
11974+
11975-
			print("second sapling: "..secondChoice .. " ("..saplings[secondChoice]..")")
11975+
11976
				if menu.getBoolean("Build a shelter at base? (y/n) ", nil, colors.yellow, colors.black) then
11977
					R.data = "chamber"
11978-
		-- check type/size of farm
11978+
11979
			end
11980-
		if R.subChoice == 1 then 			-- 16 single trees
11980+
11981-
			message = lib.plantSingle(R)	-- always ""
11981+
11982-
		elseif R.subChoice == 2 then 		-- 4 double trees (4 saplings)
11982+
11983-
			message = lib.plantDouble(R)	-- "" or error about numbers 
11983+
11984
			R.up = true
11985
			--R.depth = utils.getSize(true,"Current level (F3->Y coord)? ", bedrock + 5, ceiling)
11986-
	if R.networkFarm then
11986+
11987-
		lib.emptyInventory(R)
11987+
11988
			R.height = menu.getInteger("Go up to level? ("..R.depth + 2 .." to "..ceiling ..") ", R.depth + 2, ceiling, nil, colors.lightGray)
11989-
	return {message}
11989+
11990
				description = "Creating ladder going up"
11991
			else
11992
				description = "Creating stairs going up"
11993
			end
11994
		end
11995
		local range = math.abs(R.height - R.depth)
11996
		
11997
		if not inAir then
11998
			inAir = menu.getBoolean("Are you in air (add blocks)? (y/n) ", nil, colors.yellow, colors.black)
11999
		end
12000
		--[[
12001
		range examples
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-
	text[15] = {"1 soul sand", "3 water bucket", "levels * 4 stone", "1-9 buckets (optional)",
12172+
12173-
				"2 signs if no ladder present"} 														-- single column bubble lift
12173+
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-
				"2 water buckets","192 fence","8 signs","3 ladder","2 soul sand"}						-- build endermen observation tower
12224+
12225-
	text[67] = {"24 blocks of any type"}																-- Cover Trial spawners to prevent mobs escaping
12225+
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
		T:checkInventoryForItem({"chest", "barrel"}, {5,5})
12236
		T:checkInventoryForItem({"sapling"}, {1})
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-
	[[           ~yellow~NETWORK TOOLS:
12402+
12403-
Still on ToDo List!
12403+
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
		return getTaskInventoryTo30(R) -- Mining, Forestry
12549
	elseif R.choice < 71 then
12550-
[[~yellow~New, extend left/back=~red~^ ~orange~Extend Right=^
12550+
12551-
~lightGray~|*|~blue~ | | | | | | ~brown~|D| |D| ~blue~| | ~lightGray~|*|
12551+
12552-
~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | | | | | | | ~lightGray~|*|
12552+
12553-
~lightGray~|*|~blue~ | | ~brown~|D|D|~blue~ | ~brown~|D| |D| ~blue~| | ~lightGray~|*|
12553+
12554-
~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
12554+
12555-
~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
12555+
12556-
~lightGray~|*|~blue~ | | | | | | | | | | | | ~lightGray~|*|
12556+
12557-
~lightGray~|~red~^~lightGray~|*|*|*|*|*|*~magenta~|M|~lightGray~*|*|*|*|*|*|~orange~^|
12557+
12558-
~lime~4 ~brown~double trees~green~ or 16 ~brown~single trees
12558+
12559-
~brown~D = Dirt, ~magenta~M = Modem
12559+
12560-
~red~^~yellow~ = Turtle ~red~(new/left/back) ~orange~^ on right
12560+
12561
			sleep(2)
12562
			print("Clearing area: size "..R.width.. " x "..R.length)
12563-
[[~yellow~Place me on ground as below ~lightGray~^ ~magenta~^
12563+
12564-
~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | ~brown~|D| |D| |
12564+
12565-
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | | | | | |
12565+
12566-
~lime~|*|~blue~ | | ~brown~|D|D|~blue~ | | ~green~or |*|~blue~ | | ~brown~|D| |D| |
12566+
12567-
~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | |
12567+
12568-
~lime~|*|~blue~ | | | | | | | ~green~or |*|~blue~ | | | | | | |
12568+
12569-
~lime~|*|*|*|*|~lightGray~^~lime~|*| ~magenta~|^| ~green~or |*|*|*|*|~lightGray~^~green~|*|*~magenta~|^|
12569+
12570-
~lime~ 4 ~brown~double trees~green~   or  16 ~brown~single trees
12570+
12571-
~brown~D = dirt
12571+
12572-
~lightGray~^ = Turtle on marker (Legacy storage)
12572+
12573-
~magenta~^ = Turtle on Modem (Network storage)
12573+
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
			retValue = createFloorCeiling(R) -- R.subChoice integer 1 to 4
12605
		elseif R.choice == 710 then -- direct commands
12606-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
12606+
12607-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12607+
12608-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12608+
12609-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | 
12609+
12610-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
12610+
12611-
~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~brown~B = Barrel or Chest
12611+
12612-
~brown~|B|~blue~W~green~| | |~lightGray~or ~magenta~|M|~blue~W~green~| | ~blue~W = Water
12612+
12613-
~lime~|~red~^~lime~|~brown~B|B|~lightGray~*|or ~brown~|~red~^~brown~|~magenta~M|~lightGray~*| ~red~^ = Turtle
12613+
12614-
~brown~Legacy   ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12
12614+
12615
					print("Building sand wall. Auto length: ")
12616
				else
12617-
[[~yellow~Place on any ~brown~T ~blue~T ~magenta~T~yellow~ facing < > ^ v
12617+
12618
				end
12619-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
12619+
12620-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12620+
12621-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12621+
12622-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
12622+
12623-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest
12623+
12624-
~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | ~blue~W = Water
12624+
12625-
~brown~|B~blue~|T| ~green~| |~lightGray~or ~magenta~|M|~blue~T~green~| | ~orange~S = Sapling or Tree
12625+
12626-
~orange~|S|~brown~T|B|~lightGray~*|or ~brown~|B~magenta~|T|~lightGray~*| ~brown~T ~lightGray~= Turtle (~blue~T ~magenta~T~lightGray~)
12626+
12627-
~brown~Legacy   ~lightGray~or ~magenta~Network ~yellow~Size = 12 x 12
12627+
12628
					print("Digging sand. Auto length")
12629
				else
12630-
[[~yellow~Place as below ~blue~T~yellow~ facing < > ^ v
12630+
12631
				end
12632-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~lightGray~* = Wall
12632+
12633-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12633+
12634-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| |
12634+
12635-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~magenta~M = Modem
12635+
12636-
~lightGray~|*|~green~ | | |   ~lightGray~|*| ~green~| | ~brown~B = Barrel or Chest
12636+
12637-
~brown~|B|B~green~| | |~lightGray~or |*| ~green~| | C = Crop (first)
12637+
12638-
~brown~|B|~blue~T~green~|C| |~lightGray~or ~magenta~|M|~blue~T~green~|C| ~orange~S = Sapling or Tree
12638+
12639-
~orange~|S|~brown~B|B|~lightGray~*|or ~magenta~|M|~brown~B|~lightGray~*| ~blue~T = Turtle on Water
12639+
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
			menu.colourPrint(tostring(value), clr[count])
13009
			count = count + 1
13010-
	info.sub[67] = 
13010+
13011-
[[Turtle moves toward spawner
13011+
13012-
Place at spawner level.
13012+
13013
		end
13014-
Can be behind a wall for protection
13014+
13015-
of player.
13015+
13016
	end
13017-
Embeds in wall with attack working
13017+
13018
13019-
Needs 24 blocks
13019+