View difference between Paste ID: RZbvQfWG and 0gjBQHk9
SHOW: | | - or go back to the newest paste.
1-
-- Made By Orwell
1+
--made by me
2-
-- version 0.2 - 3 june 2012
2+
--setup() made by orwell
3-
--local type
3+
4
local tArgs = { ... }
5
if #tArgs < 1 then
6
  error("Usage: blueprint <gunzipped schematic file>")
7
end
8
9
if not fs.exists("textutilsFIX") then
10
	shell.run("pastebin get 3wguFBXn textutilsFIX")
11
end
12
13
os.loadAPI("textutilsFIX")
14
15
local filename = tArgs[1]
16
17
if not fs.exists(filename) then
18
  error("File does not exist.")
19
end
20-
block_id[5] = "Wooden Plank"
20+
21
function save(name,table)
22
	local h = fs.open(name,"w")
23
	table = textutils.serialize(table)
24
	h.write(table)
25
	h.close()
26
end
27
28
function saveIns(name,table)
29
	local h = fs.open(name,"w")
30
	h.writeLine(name.." = {}")
31
	for i,coord in pairs(table) do
32-
block_id[17] = "Log"
32+
		h.writeLine(name.."["..i.."] = {"..table.concat(coord,",").."}")
33
		h.flush()
34
	end
35
	h.close()
36
end
37
38
function saveBlueprint(reference,slots,instructions,uniqueblocks)
39
	local fname = filename:gsub("%.(.*)","")..".blueprint"
40
	local h = fs.open(fname,"w")
41
	h.writeLine("reference ="..textutils.serialize(reference)..";")
42
	h.writeLine("slots = "..textutils.serialize(slots)..";")
43
	h.writeLine("uniqueblocks = "..textutils.serialize(uniqueblocks)..";")
44
	h.writeLine("instructions = "..textutilsFIX.serialize(instructions)..";")
45
	h.close()
46
	return fname
47
end
48
49
local block_id = {}
50
51
block_id[0] = "Air"
52
block_id[1] = "Stone"
53
block_id[2] = "Grass"
54
block_id[3] = "Dirt"
55
block_id[4] = "Cobblestone"
56
block_id[5] = "Wood Planks"
57
block_id[6] = "Sapling"
58
block_id[7] = "Bedrock"
59
block_id[8] = "Water"
60
block_id[9] = "Stationary water"
61
block_id[10] = "Lava"
62
block_id[11] = "Stationary lava"
63
block_id[12] = "Sand"
64
block_id[13] = "Gravel"
65
block_id[14] = "Gold Ore"
66
block_id[15] = "Iron (Ore)"
67
block_id[16] = "Coal Ore"
68
block_id[17] = "Wood"
69
block_id[18] = "Leaves"
70
block_id[19] = "Sponge"
71
block_id[20] = "Glass"
72
block_id[21] = "Lapis Lazuli (Ore)"
73
block_id[22] = "Lapis Lazuli (Block)"
74
block_id[23] = "Dispenser"
75
block_id[24] = "Sandstone"
76
block_id[25] = "Note Block Tile entity"
77
block_id[26] = "Bed"
78
block_id[27] = "Powered Rail "
79
block_id[28] = "Detector Rail "
80
block_id[29] = "Sticky Piston"
81
block_id[30] = "Cobweb"
82
block_id[31] = "Tall Grass"
83
block_id[32] = "Dead Bush"
84
block_id[33] = "Piston"
85
block_id[34] = "Piston Extension"
86
block_id[35] = "Wool"
87
block_id[36] = "Block moved by Piston"
88
block_id[37] = "Dandelionandelion"
89
block_id[38] = "Rose"
90
block_id[39] = "Brown Mushroom"
91
block_id[40] = "Red Mushroom"
92
block_id[41] = "Block of Gold"
93
block_id[42] = "Block of Iron"
94
block_id[43] = "Double Slabs"
95
block_id[44] = "Slabs"
96
block_id[45] = "Brick Block"
97
block_id[46] = "TNT"
98
block_id[47] = "Bookshelf"
99
block_id[48] = "Moss Stone"
100
block_id[49] = "Obsidian"
101
block_id[50] = "Torch"
102
block_id[51] = "Fire"
103
block_id[52] = "Monster Spawner"
104
block_id[53] = "Wooden Stairs"
105
block_id[54] = "Chest"
106
block_id[55] = "Redstone (Wire)"
107
block_id[56] = "Diamond (Ore)"
108
block_id[57] = "Block of Diamond"
109
block_id[58] = "Crafting Table"
110-
block_id[95] = "Locked Chest"
110+
111
block_id[60] = "Farland"
112
block_id[61] = "Furnace"
113-
block_id[98] = "Stone Brick"
113+
114
block_id[63] = "Sign Post"
115
block_id[64] = "Wooden Door"
116
block_id[65] = "Ladders"
117
block_id[66] = "Rails"
118
block_id[67] = "Cobblestone Stairs"
119
block_id[68] = "Wall Sign"
120
block_id[69] = "Lever"
121
block_id[70] = "Stone Pressure Plate"
122
block_id[71] = "Iron Door"
123
block_id[72] = "Wooden Pressure Plates"
124
block_id[73] = "Redstone Ore"
125
block_id[74] = "Glowing Redstone Ore"
126
block_id[75] = "Redstone Torch"
127
block_id[76] = "Redstone Torch"
128
block_id[77] = "Stone Button "
129
block_id[78] = "Snow"
130
block_id[79] = "Ice"
131
block_id[80] = "Snow Block"
132
block_id[81] = "Cactus"
133
block_id[82] = "Clay (Block)"
134
block_id[83] = "Sugar Cane"
135
block_id[84] = "Jukebox"
136
block_id[85] = "Fence"
137
block_id[86] = "Pumpkin"
138
block_id[87] = "Netherrack"
139
block_id[88] = "Soul Sand"
140
block_id[89] = "Glowstone"
141
block_id[90] = "Portal"
142
block_id[91] = "Jack-O-Lantern"
143
block_id[92] = "Cake Block"
144
block_id[93] = "Redstone Repeater"
145
block_id[94] = "Redstone Repeater"
146
block_id[95] = "Stained Glass"
147
block_id[96] = "Trapdoors"
148
block_id[97] = "Hidden Silverfish"
149
block_id[98] = "Stone Bricks"
150
block_id[99] = "Huge brown and red mushroom"
151
block_id[100] = "Huge brown and red mushroom"
152
block_id[101] = "Iron Bars"
153
block_id[102] = "Glass Pane"
154
block_id[103] = "Melon"
155
block_id[104] = "Pumpkin Stem"
156
block_id[105] = "Melon Stem"
157
block_id[106] = "Vines"
158
block_id[107] = "Fence Gate"
159
block_id[108] = "Brick Stairs"
160
block_id[109] = "Stone Brick Stairs"
161
block_id[110] = "Mycelium"
162
block_id[111] = "Lily Pad"
163
block_id[112] = "Nether Brick"
164-
--[[
164+
165
block_id[114] = "Nether Brick Stairs"
166-
if #tArgs ~= 1 then
166+
167-
  print("Usage: build <gunzipped schematic file>")
167+
168-
  return
168+
169
block_id[118] = "Cauldron"
170
block_id[119] = "End Portal"
171
block_id[120] = "End Portal Frame"
172
block_id[121] = "End Stone "
173
block_id[126] = "Wood Slabs"
174-
  print("File does not exist.")
174+
block_id[128] = "Sandstone Stairs"
175-
  return
175+
block_id[134] = "Spruce Wood Stairs"
176
block_id[135] = "Birch Wood Stairs"
177-
]]--
177+
block_id[136] = "Jungle Wood Stairs"
178
block_id[156] = "Quartz Stairs"
179
block_id[159] = "Stained Clay"
180
block_id[160] = "Stained Glass Pane"
181
block_id[163] = "Acacia Wood Stairs"
182
block_id[164] = "Dark Oak Wood Stairs"
183
block_id[171] = "Carpet"
184
block_id[172] = "Hardened Clay"
185
block_id[256] = "Iron Ingotron Shovel"
186
block_id[257] = "Iron Pickaxe"
187
block_id[258] = "Iron Axe"
188
block_id[259] = "Flint and Steel"
189-
    return "UNKNOWN"
189+
190
block_id[261] = "Bow"
191
block_id[262] = "Arrow"
192-
      if(id == 35) then
192+
193-
        str = woolColors[blockData] .. " " .. block_id[id]
193+
194
local woolColors = {}
195
woolColors[0] = "White"
196
woolColors[1] = "Orange"
197
woolColors[2] = "Magenta"
198
woolColors[3] = "Light Blue"
199
woolColors[4] = "Yellow"
200
woolColors[5] = "Lime"
201
woolColors[6] = "Pink"
202
woolColors[7] = "Gray"
203
woolColors[8] = "Light Gray"
204
woolColors[9] = "Cyan"
205
woolColors[10] = "Purple"
206
woolColors[11] = "Blue"
207
woolColors[12] = "Brown"
208
woolColors[13] = "Green"
209
woolColors[14] = "Red"
210
woolColors[15] = "Black"
211
212
local woodTypes = {}
213
woodTypes[0] = "Oak"
214
woodTypes[1] = "Spruce"
215
woodTypes[2] = "Birch"
216
woodTypes[3] = "Jungle"
217
woodTypes[4] = "Acacia"
218
woodTypes[5] = "Dark Oak"
219
220
local stairOrientation = {}
221
stairOrientation[0] = "East"
222
stairOrientation[1] = "West"
223
stairOrientation[2] = "South"
224
stairOrientation[3] = "North"
225
stairOrientation[4] = "East Inverted"
226
stairOrientation[5] = "West Inverted"
227
stairOrientation[6] = "South Inverted"
228
stairOrientation[7] = "North Inverted"
229
230
local nonWoodenSlabs = {
231
	[0] = "Stone",
232
	[1] = "Sandstone",
233
	[2] = "Wooden",
234
	[3] = "Cobblestone",
235
	[4] = "Bricks",
236
	[5] = "Stone Bricks",
237
	[6] = "Nether Brick",
238
	[7] = "Quartz",
239
	[8] = "Inverted Stone",
240
	[9] = "Inverted Sandstone",
241
	[10] = "Inverted Wooden",
242
	[11] = "Inverted Cobblestone",
243
	[12] = "Inverted Bricks",
244
	[13] = "Inverted Stone Bricks",
245-
    
245+
	[14] = "Inverted Nether Brick",
246
	[15] = "Inverted Quartz",
247
}
248
249
250
251
252
local length = 0
253
local height = 0
254
local width = 0
255
local blocks = {}
256
local data = {}
257
258
function getBlockName(id, blockData)
259
  blockData = blockData or nil
260
  local str = nil
261
  if(block_id[id] == nil) then
262
    return tostring(id)..", "..tostring(blockData)
263
  else
264
    if(blockData) then
265
      if(id == 35) or (id == 159) or (id == 95) or (id == 160) or (id == 171) then
266
        str = tostring(woolColors[blockData]) .. " " .. tostring(block_id[id])
267
        return str
268
      elseif id == 5 or id==17 or id==126 then
269
		str = tostring(woodTypes[blockData]).." "..tostring(block_id[id])
270
		return str
271
      elseif id == 44 or id == 43 then
272
		str = tostring(nonWoodenSlabs[blockData]).." "..tostring(block_id[id])
273
		return str
274
	  end
275
    end
276
    return block_id[id]
277
  end
278
end
279
280
function getBlockId(x,y,z)
281
  return blocks[y + z*width + x*length*width + 1]
282
end
283
284
function getData(x,y,z)
285
  return data[y + z*width + x*length*width + 1]
286
end
287
288
function readbytes(h, n)
289
  for i=1,n do
290
    h.read()
291
  end
292
end
293
294
function readname(h)  
295
  local n1 = h.read()
296
  local n2 = h.read()
297
298
  if(n1 == nil or n2 == nil) then
299
    return ""
300
  end
301
  
302
  local n = n1*256 + n2
303
  
304
  local str = ""
305
  for i=1,n do
306
    local c = h.read()
307
    if c == nil then
308
      return
309
    end  
310
    str = str .. string.char(c)
311
  end
312
  return str
313
end
314
315
function parse(a, h, containsName)
316
  local containsName = containsName or true
317
  local i,i1,i2,i3,i4
318
  if a==0 then
319
    return
320
  end
321
  if containsName then
322
    name = readname(h)
323
  end  
324
325
  if a==1 then
326
    readbytes(h,1)  
327
  elseif a==2 then
328
    i1 = h.read()
329
    i2 = h.read()
330
    i = i1*256 + i2
331
    if(name=="Height") then
332
      height = i
333
    elseif (name=="Length") then
334
      length = i
335
    elseif (name=="Width") then
336
      width = i
337-
	a = 0
337+
338
  elseif a==3 then
339
    readbytes(h,4)
340
  elseif a==4 then
341
    readbytes(h,8)
342
  elseif a==5 then
343
    readbytes(h,4)
344
  elseif a==6 then
345
    readbytes(h,8)
346
  elseif a==7 then
347
    i1 = h.read()
348
    i2 = h.read()
349
    i3 = h.read()
350
    i4 = h.read()
351
    i = i1*256*256*256 + i2*256*256 + i3*256 + i4
352
    if name == "Blocks" then
353
      for i=1,i do
354
        table.insert(blocks, h.read())
355
      end
356
    elseif name == "Data" then
357
      for i=1,i do
358
        table.insert(data, h.read())
359
      end
360
    else
361
      readbytes(h,i)
362
    end
363
  elseif a==8 then
364-
			
364+
365-
			
365+
366
    i = i1*256 + i2
367
    readbytes(h,i)
368
  elseif a==9 then
369
  	--readbytes(h,5)
370
  	local type = h.read()
371
  	i1 = h.read()
372
    i2 = h.read()
373
    i3 = h.read()
374
    i4 = h.read()
375
    i = i1*256*256*256 + i2*256*256 + i3*256 + i4
376
    for j=1,i do
377
      parse(h.read(), h, false)
378
    end
379
  end
380
end
381
382
function forward()
383-
  		print(" -" .. getBlockName(v.blockID, v.data) .. ": " .. v.amount)
383+
384
    turtle.dig()
385
  end
386
end
387
388-
	print("Give the numbers of all slots containing the specified block type:")
388+
389
  while not turtle.up() do
390
    turtle.digUp()
391
  end
392
end
393-
  		print(" -in which slots is " .. getBlockName(block.blockID, blockData) .. "?")
393+
394
function down()
395
  while not turtle.down() do
396
    turtle.digDown()
397
  end
398-
  		write("   ")
398+
399-
  		str = read()
399+
400-
  		for i = 1, #str do
400+
401-
    		local c = str:sub(i,i)
401+
402-
    		n = tonumber(c)
402+
403-
    		if(n) then
403+
404-
      			if(n>0 and n<10) then
404+
405-
        			table.insert(slots[block.blockID][blockData], n)
405+
406-
      			end
406+
local function setColor(color)
407-
   			end
407+
	if term.isColor() then
408
		term.setTextColor(color)
409
	end
410
end
411
412
local function show_selected_slot(n)
413-
	save("blocks",blocks)
413+
	local w,h = term.getCursorPos()
414-
	save("data",data)
414+
	local itemData = turtle.getItemDetail(newSelect)
415-
	save("uniqueblocks",uniqueblocks)
415+
	if itemData then
416
		term.clearLine()
417
		term.setCursorPos(1,h)
418
		write("    "..itemData.name..", "..itemData.damage)
419-
setup(...)
419+
	else
420
		term.clearLine()
421
		term.setCursorPos(1,h)
422
		write("    ")
423
	end
424
	return itemData
425
end
426
427
function setup(filename)
428
--input file
429
--returns blocks,data
430
--requires parse, getBlockName
431
432
	if not fs.exists(filename) then
433
  		error("File "..tostring(filename).." does not exist.")
434
	end
435
	h = fs.open(filename, "rb")
436
437
	local a = 0
438
	while (a ~= nil) do
439
 		a = h.read()
440
  		parse(a, h)
441
	end
442
443
	write("length: " .. length)
444
	write("   width: " .. width)
445
	write("   height: " .. height .. "\n")
446
	
447
	uniqueblocks={}
448
	for i,v in ipairs(blocks) do
449
  		found = false
450
  		for j,w in ipairs(uniqueblocks) do
451
452
			--[[if (w.blockID==v and (w.data==data[i] or w.blockID ~= 35)) then
453
      			found = true
454
      			w.amount = w.amount + 1
455
      			break
456
    		end]]--
457
458
    		--for now, data is only accounted for when the block is whool
459
    		if (w.blockID==v) and (w.data==data[i]) then
460
      			found = true
461
      			w.amount = w.amount + 1
462
      			break
463
    		end
464
  		end
465
  
466
  		if found==false then
467
    		uniqueblocks[#uniqueblocks+1] = {}
468
    		uniqueblocks[#uniqueblocks].blockID = v
469
    		uniqueblocks[#uniqueblocks].data = data[i]
470
    		uniqueblocks[#uniqueblocks].amount = 1
471
  		end
472
	end
473
474
	if fs.exists("slots") then
475
		print("slots file discovered...")
476
		print("skipping setup")
477
		h.close()
478
		return
479
	end
480
481
	print("number of block types: " .. #uniqueblocks)
482
	for i,v in ipairs(uniqueblocks) do
483
  		if (i%9)==0 then
484
    		read()
485
  		end
486
		local stacks = math.ceil( (v.amount/64) )
487
		setColor(colors.white)
488
		write(" -" .. getBlockName(v.blockID, v.data))
489
		setColor(colors.lightGray)
490
		write("("..v.blockID..","..v.data..")")
491
		setColor(colors.white)
492
		write(": ")
493
494
		if v.amount > 64 then
495
			setColor(colors.magenta)
496
  			print(stacks.." stacks")
497
		else
498
			setColor(colors.cyan)
499
			print(v.amount)
500
		end
501
	end
502
	setColor(colors.white)
503
	read()
504
505
	print("Use arrowKeys and enter to select slots containing which block the turtle will use for the specified blockType")
506
	print("select an empty block or press x to skip(not use) the specified blockType ie air")
507
508
	slots={}
509
	for i,block in ipairs(uniqueblocks) do
510
		local n = nil
511
  		blockData = block.data
512
		setColor(colors.green)
513
  		print(" -in which slots is " .. getBlockName(block.blockID, blockData).."("..block.blockID..","..blockData .. ") ?")
514
		setColor(colors.white)
515
  		if not slots[block.blockID] then
516
    		slots[block.blockID] = {}
517
  		end
518
  		slots[block.blockID][blockData] = {}
519
		show_selected_slot(turtle.getSelectedSlot())
520
		--input none
521
		--output(n)		
522
523
		--(oldWay)
524
		if tArgs[2] == "sim" or tArgs[2] == "simulate" then
525
  			write("   ")
526
  			str = read()
527
			n = tonumber(str)
528
		else
529
			n = numberSelector()
530
		end
531
532-
function blueprint()
532+
		local itemData = show_selected_slot(n)
533
		if(n and itemData) then
534-
	local x,y,z = 0,0,0
534+
			print()
535
			slots[block.blockID][blockData] = {itemData.name,itemData.damage}
536-
	while true do
536+
537
			local w,h = term.getCursorPos()
538
			term.clearLine()
539
			term.setCursorPos(1,h)
540
			print("    SKIPPING")
541
			slots[block.blockID][blockData] = {}
542
		end
543
	end
544
	
545-
		x,y,z = iterate(x,y,z,0,0,0,height-1,width-1,length-1)
545+
546
	save("slots",slots)
547
end
548
549
function numberSelector()
550
551-
function createInstructions(startx,starty,startz,height,width,length,nTurtles,placeMode)
551+
    local function selectNext(newSelect)
552
        if newSelect >= 1 and newSelect <= 16 then
553-
	 local x,y,z = startx,starty,startz
553+
            turtle.select(newSelect)
554-
	 instructions = {}
554+
			show_selected_slot(newSelect)
555-
	 nTurtles = nTurtles or 1
555+
556-
	 --startx,starty,startz = startx,starty,startz or 0,0,0
556+
557-
	 placeMode = placeMode or "horizontal"
557+
 
558-
	 local oTurtles = {}
558+
    local function ifKey(events,nKey,fn,...)
559
        if events[1] == "key" and events[2] == tonumber(nKey) then
560-
	--if horizontal
560+
            fn(...)
561-
	for i = 1,nTurtles do
561+
562-
		oTurtles[i] = {}
562+
563-
		if i == tonumber(nTurtles) then
563+
 
564-
			oTurtles[tonumber(nTurtles)].responsibleLength = math.floor(x/nTurtles) + (x - (math.floor(x/nTurtles)*nTurtles))
564+
    local bRunning = true
565
	local bNothing = false
566-
			oTurtles[i].responsibleLength =  math.floor(x/nTurtles)
566+
    while bRunning do
567
        local events = { os.pullEvent("key") }
568-
		oTurtles[i].startHeight = startx
568+
        local newSelect
569-
		if i == 1 then
569+
        local selected = turtle.getSelectedSlot()
570-
			oTurtles[i].startWidth = starty
570+
   
571
        ifKey(events,203,function() newSelect = selected - 1 ; selectNext(newSelect) ; end)
572-
			oTurtles[i].startWidth = oTurtles[i-1].startWidth + oTurtles[i].responsibleLength
572+
        ifKey(events,205,function() newSelect = selected + 1 ; selectNext(newSelect) ; end)
573
        ifKey(events,200,function() newSelect = selected - 4 ; selectNext(newSelect) ; end)
574-
		oTurtles[i].startLength = startz
574+
        ifKey(events,208,function() newSelect = selected + 4 ; selectNext(newSelect) ; end)
575-
		oTurtles[i].finalHeight = height-1
575+
		ifKey(events,28,function() bRunning = false ; end)
576-
		oTurtles[i].finalWidth = oTurtles[i].startWidth + oTurtles[i].responsibleLength - 1
576+
        ifKey(events,45,function() bNothing = true ; bRunning = false ; end)
577-
		oTurtles[i].finalLength = length-1
577+
 		ifKey(events,15,function() bNothing = true ; bRunning = false; end)
578-
		instructions[i] = {}
578+
579
        for i = 2,13 do
580
            ifKey(events,i,function() selectNext(i-1) end)
581
        end
582
        for i = 26,27 do
583-
		for i = 1,nTurtles do
583+
            ifKey(events,i,function() selectNext(i-13) end)
584-
			x,y,z = startx,starty,startz
584+
585-
			
585+
        for i = 39,40 do
586-
			
586+
            ifKey(events,i,function() selectNext(i-24) end)
587-
			while true do
587+
588-
				local n = #instructions[i]+1
588+
589-
				instructions[i][n]={}
589+
    if bNothing then
590-
				instructions[i][n].x,instructions[1][n].y,instructions[1][n].z = x,y,z
590+
    	return nil
591-
				instructions[i][n].placeMode = placeMode
591+
592-
				instructions[i][n].id = getBlockId(x,y,z)
592+
    	return turtle.getSelectedSlot()
593-
				instructions[i][n].data = getData(x,y,z)
593+
594-
				x,y,z = iterate(x,y,z,
594+
595-
					oTurtles[i].startHeight, oTurtles[i].startWidth, oTurtles[i].startLength,
595+
596-
					oTurtles[i].finalHeight, oTurtles[i].finalWidth, oTurtles[i].finalLength
596+
597-
				)
597+
598-
				--attach methods here
598+
599
	--finds the location to place the next block
600-
			
600+
601-
			
601+
602
		--makes the turtle build faster by having to travel less
603
        blockID2 = getBlockId(x,y,z)	-- temporary variable 
604
        blockData2 = getData(x,y,z) 	-- temporary variable
605
        if slots[blockID2] then
606-
local ins = blueprint()
606+
607-
save("instructions",ins)
607+
608
            if slot_2nd then
609-
--[[
609+
610-
print("Press key to start building...")
610+
611-
read()
611+
612
                end
613-
up()
613+
614-
n = 1
614+
615-
turtle.select(n)
615+
616
end
617-
for x=1,height do
617+
618-
  for y=1,width do
618+
619-
    for z=1,length do
619+
620-
      blockID = getBlockId(x-1,y-1,z-1)
620+
621-
      blockData = getData(x-1,y-1,z-1)
621+
622-
      forward()
622+
623-
      turtle.digDown()
623+
624-
      slot_lst = slots[blockID][blockData]
624+
625-
      if(slot_lst ~= nil) then
625+
626-
        if(#slot_lst > 0) then
626+
627-
          local found=false
627+
628-
          for i,v in ipairs(slot_lst) do
628+
629-
            if(turtle.getItemCount(v) > 0) then
629+
630-
              found=true
630+
631-
              turtle.select(v)
631+
632-
              break
632+
633
    end
634-
          end
634+
635-
          if not found then
635+
636-
            print("Not enough " .. getBlockName(blockID, blockData) .. ". Please refill...")
636+
637-
            read()
637+
638-
          end
638+
639-
          place()
639+
640
	local height = finalx
641
	local width = finaly
642
	local length = finalz
643-
    turtle.turnLeft()
643+
644-
    forward()
644+
645-
    turtle.turnLeft()
645+
646-
    for i=1,length do
646+
647-
      forward()
647+
648
            if x < height then
649-
    turtle.turnRight()
649+
650-
    turtle.turnRight()
650+
651
                --x,y,z = "max","max","max"
652-
  turtle.turnRight()
652+
653-
  for i=1,width do
653+
654-
    forward()
654+
655
        if y <= starty then
656-
  turtle.turnLeft()
656+
657-
  up()
657+
658
			elseif x == height then
659
				x = "max"
660-
for i=1,height+1 do
660+
661-
  down()
661+
662-
end]]
662+
663
        else
664
            y=y-1
665
        end
666
    end
667
	return x,y,z
668
end
669
670
function iterate(x,y,z,startx,starty,startz,finalx,finaly,finalz) 
671
	
672
	local height = finalx
673
	local width = finaly
674
	local length = finalz
675
	
676
	
677
    local oddx,oddy = check(x,y,z,startx,starty,startz)
678
    if z == length and oddy then
679
        x,y,z = Yiterate(x,y,z,startx,starty,startz,finalx,finaly,finalz)    
680
    elseif z == startz and oddy then
681
        z = z + 1
682
    elseif z == startz and (not oddy) then
683
        x,y,z = Yiterate(x,y,z,startx,starty,startz,finalx,finaly,finalz)
684
    elseif z==length and (not oddy) then
685
        z = z - 1
686
687
    elseif z < length then
688
        if oddy then
689
            z = z + 1
690
        else
691
            z = z - 1
692
        end
693
    end
694
	return x,y,z
695
 end
696
697
-- [[ TSP_algorithm API ]] --
698
699
local w,h = term.getSize()
700
 
701
local function calculateDistance(tNode1,tNode2)
702
	local turnCost = 0
703
	local deltaY,deltaZ
704
	local y1 = tNode1[2]
705
	local z1 = tNode1[3]
706
	local y2 = tNode2[2]
707
	local z2 = tNode2[3] 
708
	
709
	deltaZ = z2-z1
710
	deltaY = y2-y1
711
	
712
	if deltaZ == 0 or deltaY == 0 then
713
		turnCost = 0
714
	else
715
		turnCost = 1
716
	end
717
	
718
	return math.abs(deltaZ) + math.abs(deltaY) + turnCost
719
	--return math.sqrt( (z2-z1)^2 + (y2-y1)^2 )
720
end
721
 
722
local function twoOptSwap(route, i, k)
723
    local new_route = {}
724
    for c = 1,i-1 do
725
        table.insert(new_route,route[c])
726
    end
727
    for c = k,i,-1 do
728
        table.insert(new_route,route[c])
729
    end
730
    for c = k+1,#route do
731
        table.insert(new_route,route[c])   
732
    end
733
    return new_route
734
end
735
 
736
local function calculateTotalDistance(route)
737
	local total = 0
738
	for i = 1,#route-1 do
739
		total = total + calculateDistance(route[i],route[i+1])
740
	end
741
	return total
742
end
743
 
744
local function display(route,distance)
745
    local l,h = term.getSize()
746
    shell.run("clear")
747
 
748
    for i = 1,#route-1 do
749
        paintutils.drawLine(route[i][2],route[i][3],route[i+1][2],route[i+1][3],colors.lime)
750
    end
751
    for i,coord in pairs(route) do
752
        term.setBackgroundColor(colors.yellow)
753
        term.setTextColor(colors.magenta)
754
        term.setCursorPos(coord[2],coord[3])
755
        term.write(string.char(i+64))
756
    end
757
    term.setBackgroundColor(colors.black)
758
    term.setTextColor(colors.white)
759
    term.setCursorPos(1,h)
760
    term.write(distance)
761
end
762
 
763
local route = {}
764
route[1] = {1,28,3}
765
route[2] = {1,36,13}
766
route[3] = {1,20,8}
767
route[4] = {1,8,8}
768
route[5] = {1,44,5}
769
route[6] = {1,32,13}
770
route[7] = {1,20,17}
771
--route[8] = {1,28,3}
772
773
function tsp_algorithm(existing_route)
774
	local improve = 0 
775
	while improve < 3 do
776
		local best_distance = calculateTotalDistance(existing_route)
777
		for i = 2,#existing_route-1 do
778
			for k = i + 1, #existing_route do
779
				new_route = twoOptSwap(existing_route, i, k)
780
				new_distance = calculateTotalDistance(new_route)
781
				if new_distance < best_distance then
782
					improve = 0
783
					existing_route = new_route
784
					best_distance = calculateTotalDistance(existing_route)
785
					display(existing_route,best_distance)
786
					sleep(0)
787
				end
788
			end
789
		end
790
		improve = improve + 1
791
	end
792
	return existing_route, best_distance
793
end
794
795
-- [[ schematic --> blueprint ]] --
796
797
--turtles[i].instructions[n] = {x,y,z,id,data}
798
--i = multiturtle ie 1,2,3,4 ; n = step ie 1 - 256 (no air) 
799
800
--fn splits 16x16 grid between 4 turtles returning startx,y,z and endx,y,z of 4 4x4 grids
801
--fn takes each 4x4 grid and turns them into instructions[n] = {x,y,z,id,data}
802
--fn for master turtle to setup all slave turtles with the instructions[n] table and goto/find/place functions
803
804
function blueprint(startx,starty,startz,finalx,finaly,finalz)
805
	--uses iterator to make instructions[n] table
806
	local x,y,z = startx,starty,startz
807
	local instructions = {}
808
	local nTimes = (finalx+1-startx)*(finaly+1-starty)*(finalz+1-startz)
809
	for i=1,nTimes do
810
		if x == "max" then
811
			break
812
		end
813
		local id = getBlockId(x,y,z)
814
		local data = getData(x,y,z)
815
		if id > 0 then
816
			table.insert(instructions,{x,y,z,id,data})
817
		end
818
		x,y,z = iterate(x,y,z,startx,starty,startz,finalx,finaly,finalz)
819
	end
820
	return instructions
821
end
822
823
function improveBlueprint(instructions,startx,starty,startz,finalx,finaly,finalz)
824
	local function instructions2layers(instructions)
825
    	local layers = {}
826
   		for x = startx,finalx do
827
        	layers[x] = {}
828
        	for n=1,#instructions do
829
            	if instructions[n][1] == x then
830
                	table.insert(layers[x],{unpack(instructions[n],1,3)})
831
            	end
832
        	end
833
    	end
834
    	return layers
835
	end
836
	local function organize(layers)
837
    	local startingPosition = {startx,starty,startz}
838
    	for x = startx,finalx do
839
       		table.insert(layers[x],1,startingPosition)
840
        	layers[x] = tsp_algorithm(layers[x])
841
        	startingPosition = layers[x][#layers[x]]
842
    	end
843
    	return layers
844
	end
845
 
846
	local function layers2instructions(layers)
847
   		local instructions = {}
848
    	--organizedlayers only
849
    	for x = startx,finalx do
850
        	for i = 2,#layers[x] do
851
            	table.insert(instructions,layers[x][i])
852
        	end
853
    	end
854
    	return instructions
855
	end
856
 
857
	local function add_id_and_data(instructions)
858
    	for n = 1,#instructions do
859
        	instructions[n][4] = getBlockId(unpack(instructions[n],1,3))
860
        	instructions[n][5] = getData(unpack(instructions[n],1,3))
861
    	end
862
    	return instructions
863
	end
864
865
	local layers = instructions2layers(instructions)
866
	layers = organize(layers)
867
	local new_instructions = layers2instructions(layers)
868
	new_instructions = add_id_and_data(new_instructions)
869
	return new_instructions
870
end
871
872
function simulateIns(instructions)
873
    local lastx = 0
874
    shell.run("clr")
875
    for n = 1,#instructions do
876
        if lastx~=instructions[n][1] then
877
            term.setBackgroundColor(colors.black)
878
            shell.run("clr")
879
        end
880
        term.setCursorPos(instructions[n][2]+1,instructions[n][3]+1)
881
        term.setBackgroundColor(2^instructions[n][5])
882
        term.write(" ")
883
        lastx = instructions[n][1]
884
        sleep(0)
885
    end
886
end
887
888
function orientation_check(reference,slots)
889
	for id,table in pairs(slots) do
890
		for data,table2 in pairs(table) do
891
			if table2 and table2[1] then
892
				if (table2[1]:find("stairs") or table2[1]:find("chest") or table2[1]:find("furnace")) then
893
					for n = 1,5 do
894
						term.scroll(1)
895
						sleep(0)
896
					end
897
					print("orientation required")
898
					print("what direction is the turtle facing?")
899
					local r
900
					while true do
901
						write("    ")
902
						if term.isColor() then
903
							term.setTextColor(colors.yellow)
904
						end
905
						r = read()
906
						term.setTextColor(colors.white)
907
						if r ~= "south" and r~= "north" and r~= "west" and r~= "east" then
908
							print(r.. " not recognized, north/south/east/west?")
909
						else
910
							break
911
						end
912
					end
913
				
914
					reference.relativeDirection = r
915
					print("don't forget to include wrench in turtle!")
916
					reference.wrench = true
917
					return reference
918
				end
919
			end
920
		end
921
	end
922
	return reference
923
end
924
925
local function Main()
926
	setup(filename)
927
928
	--save("blocks",blocks)
929
	--save("data",data)
930
	--save("uniqueblocks",uniqueblocks)
931
932
	local reference = {
933
		startx = 0,
934
		starty = 0,
935
		startz = 0,
936
		finalx = height-1,
937
		finaly = width-1,
938
		finalz = length-1,
939
		height = height,
940
		width = width,
941
		length = length,
942
		wrench = false,
943
		multiturtle = false, -- otherwise its a number (1,2,4,8,12,etc),
944
		relativeDirection = "south",
945
		numChests = false,
946
		filename = false,
947
	}
948
	
949
	if not slots then
950
		slots = textutils.unserialize( fs.open("slots","r").readAll() )
951
	end
952
953
	reference = orientation_check(reference,slots)
954
955
	local ins = blueprint(reference.startx,reference.starty,reference.startz,reference.finalx,reference.finaly,reference.finalz)
956
	if tArgs[2] == "tsp" then
957
		ins = improveBlueprint(ins,reference.startx,reference.starty,reference.startz,reference.finalx,reference.finaly,reference.finalz)
958
	end
959
	
960
	--textutils.pagedPrint(textutils.serialize(ins))
961
	--saveIns("instructions",ins)
962
	local fname = saveBlueprint(reference,slots,ins,uniqueblocks)
963
	print(fname," saved")
964
	--delete slots,reference,ins,uniqueblocks files
965
end
966
967
Main()