View difference between Paste ID: k9RUH1pw and jj1V1d7n
SHOW: | | - or go back to the newest paste.
1
-- Variable Setup
2
-- Command Line input Table
3
local argTable = {...}
4
5
-- Flag Variables: These are conditions for different features (all flags are named foo_bar, all other variables are named fooBar)
6
local cmd_line = false
7
local cmd_line_resume = false
8
local cmd_line_cost_only = false
9
local chain_next_shape = false -- This tells goHome() where to end, if true it goes to (0, 0, positionZ) if false it goes to (-1, -1, 0)
10
local special_chain = false -- For certain shapes that finish where the next chained shape should start, goHome() will  only turn to face 0 if true
11
local cost_only = false
12
local sim_mode = false
13-
local stepUp = true
13+
local stepUp = false
14
15
-- Record Keeping Variables: These are for recoding the blocks and fuel used
16
local blocks = 0
17
local fuel = 0
18
local crescentSlot = 15
19
20
-- Position Tracking Variables: These are for keeping track of the turtle's position
21
local positionX = 0
22
local positionY = 0
23
local positionZ = 0
24
local facing = 0
25
local gpsPositionX = 0
26
local gpsPositionY = 0
27
local gpsPositionZ = 0
28
local gpsFacing = 0
29
30
-- General Variables: Other variables that don't fit in the other categories
31
local resupply = false
32
local enderchestRefilling = false
33
local can_use_gps = false
34
local returntohome = false -- whether the turtle shall return to start after build
35
local choice = ""
36
37
-- Progress Table: These variables are the tables that the turtle's progress is tracked in
38
local tempProgTable = {}
39
local progTable = {} --This is the LOCAL table!  used for local stuff only, and is ONLY EVER WRITTEN when sim_mode is FALSE
40
local progFileName = "ShapesProgressFile"
41
42
-- Utility functions
43
44
function writeOut(...) -- ... lets writeOut() pass any arguments to print(). so writeOut(1,2,3) is the same as print(1,2,3). previously writeOut(1,2,3) would have been the same as print(1)
45
	for i, v in ipairs(arg) do
46
		print(v)
47
	end
48
end
49
50
function getInput(inputtype, message, option1, option2)
51
	local input = ""
52
	if inputtype == "string" then
53
		writeOut(message.. "(" ..option1 .. " or "..option2..")" )
54
		while true do
55
			input = io.read()
56
			input = string.lower(input)
57
			if input ~= option1 and input ~= option2 then
58
				writeOut("You didn't enter a valid option. Please try again.")
59
			else
60
				return input
61
			end
62
		end
63
	end
64
	if inputtype == "int" then
65
		writeOut(message)
66
		while true do
67
			input = io.read()
68
			if tonumber(input) ~= nil then
69
				return tonumber(input)
70
			else
71
				writeOut("Need a number. Please try again")
72
			end
73
		end
74
	end	
75
end
76
77
function wrapmodules() -- checks for and wraps turtle modules
78
	local test = 0
79
	if peripheral.getType("left" )== "resupply" then 
80
		resupplymodule=peripheral.wrap("left")
81
		resupply = true
82
	elseif peripheral.getType("right") == "resupply" then
83
		resupplymodule=peripheral.wrap("right")
84
		resupply = true
85
	end
86
	if peripheral.getType("left") == "modem" then
87
		modem=peripheral.wrap("left")
88
		test, _, _ = gps.locate(1)
89
		if test ~= nil then
90
			can_use_gps = true
91
		end
92
	elseif peripheral.getType("right") == "modem" then
93
		modem=peripheral.wrap("right")
94
		test, _, _ = gps.locate(1)
95
		if test ~= nil then
96
			can_use_gps = true
97
		end
98
	end
99
	if resupply then
100
		return "resupply"
101
	end
102
end
103
104
function linkToRSStation() -- Links to resupply station
105
	if resupplymodule.link() then
106
		return true
107
	else
108
		writeOut("Please put Resupply Station to the left of the turtle and press Enter to continue")
109
		io.read()
110
		linkToRSStation()
111
	end
112
end
113
114
function compareResources()
115
	if (turtle.compareTo(1) == false) then
116
		turtle.drop()
117
	end
118
end
119
120
function checkResources()
121
	if resupply then
122
		if turtle.getItemCount(activeslot) <= 1 then
123
			while not(resupplymodule.resupply(1)) do
124
				os.sleep(0.5)
125
			end
126
		end
127
	elseif enderchestRefilling then
128
		compareResources()
129
		while (turtle.getItemCount(activeslot) <= 1) do
130
			if (activeslot == 15) and (turtle.getItemCount(activeslot)<=1) then
131
				turtle.select(16)
132
				turtle.digUp()
133
				for i = 1, 15 do
134
					turtle.select(i)
135
					turtle.drop()
136
				end
137
				turtle.select(16)
138
				turtle.placeUp()
139
				turtle.select(1)				
140
				for i = 1, 15 do
141
					turtle.suckUp()
142
				end
143
				turtle.select(16)
144
				turtle.digUp()
145
				activeslot = 1
146
				turtle.select(activeslot)
147
			else
148
				activeslot = activeslot+1
149
				-- writeOut("Turtle slot empty, trying slot "..activeslot)
150
				turtle.select(activeslot)
151
			end
152
			compareResources()
153
			os.sleep(0.2)
154
		end
155
	else
156
		compareResources()
157
		while (turtle.getItemCount(activeslot) <= 1) do
158
			if (activeslot == 16) and (turtle.getItemCount(activeslot)<=1) then
159
				writeOut("Turtle is empty, please put building block in slots and press enter to continue")
160
				io.read()
161
				activeslot = 1
162
				turtle.select(activeslot)
163
			else
164
				activeslot = activeslot+1
165
				-- writeOut("Turtle slot almost empty, trying slot "..activeslot)
166
				turtle.select(activeslot)
167
			end
168
			compareResources()
169
			os.sleep(0.2)
170
		end
171
	end
172
end
173
174
function checkFuel()
175
	if (not(tonumber(turtle.getFuelLevel()) == nil)) then
176
		while turtle.getFuelLevel() < 50 do
177
			writeOut("Turtle almost out of fuel, pausing. Please drop fuel in inventory. And press enter.")
178
			io.read()
179
			turtle.refuel()
180
		end
181
	end
182
end
183
184
function placeBlock()
185
	blocks = blocks + 1
186
	simulationCheck()
187
	if cost_only then
188
		return
189
	end
190
	if turtle.detectDown() and not turtle.compareDown() then
191
		turtle.digDown()
192
	end
193
	checkResources()
194
	turtle.placeDown()
195
	progressUpdate()
196
end
197
198
function round(toBeRounded, decimalPlace) -- Needed for hexagon and octagon
199
	local multiplier = 10^(decimalPlace or 0)
200
	return math.floor(toBeRounded * multiplier + 0.5) / multiplier
201
end
202
203
-- Navigation functions
204
-- Allow the turtle to move while tracking its position
205
-- This allows us to just give a destination point and have it go there
206
207
function turnRightTrack()
208
	simulationCheck()
209
	facing = facing + 1
210
	if facing >= 4 then
211
		facing = 0
212
	end
213
	progressUpdate()
214
	if cost_only then
215
		return
216
	end
217
	turtle.turnRight()
218
end
219
220
function turnLeftTrack()
221
	simulationCheck()
222
	facing = facing - 1
223
	if facing < 0 then
224
		facing = 3
225
	end
226
	progressUpdate()
227
	if cost_only then
228
		return
229
	end
230
	turtle.turnLeft()
231
end
232
233
function turnAroundTrack()
234
	turnLeftTrack()
235
	turnLeftTrack()
236
end
237
238
function turnToFace(direction)
239
	if direction >= 4 or direction < 0 then
240
		return false
241
	end
242
	while facing ~= direction do
243
		turnLeftTrack()
244
	end
245
	return true
246
end
247
248
function safeForward()
249
	simulationCheck()
250
	if facing == 0 then
251
		positionY = positionY + 1
252
	elseif facing == 1 then
253
		positionX = positionX + 1
254
	elseif facing == 2 then
255
		positionY = positionY - 1
256
	elseif facing == 3 then
257
		positionX = positionX - 1
258
	end
259
	fuel = fuel + 1
260
	progressUpdate()
261
	if cost_only then
262
		return
263
	end
264
	checkFuel()
265
	local success = false
266
	local tries = 0
267
	while not success do
268
		success = turtle.forward()
269
		if not success then
270
			while (not success) and tries < 6 do
271
				tries = tries + 1
272
				turtle.dig() 
273
				success = turtle.forward()
274
				sleep(0.3)
275
			end
276
			if not success then
277
				writeOut("Blocked attempting to move forward.")
278
				writeOut("Please clear and press enter to continue.")
279
				io.read()
280
			end
281
		end
282
	end
283
end
284
285
function safeBack()
286
	simulationCheck()
287
	if facing == 0 then
288
		positionY = positionY - 1
289
	elseif facing == 1 then
290
		positionX = positionX - 1
291
	elseif facing == 2 then
292
		positionY = positionY + 1
293
	elseif facing == 3 then
294
		positionX = positionX + 1
295
	end
296
	fuel = fuel + 1
297
	progressUpdate()
298
	if cost_only then
299
		return
300
	end
301
	checkFuel()
302
	local success = false
303
	local tries = 0
304
	while not success do
305
		success = turtle.back()
306
		if not success then
307
			turnAroundTrack()
308
			while turtle.detect() and tries < 6 do
309
				tries = tries + 1
310
				if turtle.dig() then
311
					break
312
				end
313
				sleep(0.3)
314
			end
315
			turnAroundTrack()
316
			success = turtle.back()
317
			if not success then
318
				writeOut("Blocked attempting to move back.")
319
				writeOut("Please clear and press enter to continue.")
320
				io.read()
321
			end
322
		end
323
	end
324
end
325
326
function safeUp()
327
	simulationCheck()
328
	positionZ = positionZ + 1
329
	fuel = fuel + 1	
330
	progressUpdate()
331
	if cost_only then
332
		return
333
	end
334
	checkFuel()
335
	local success = false
336
	while not success do
337
		success = turtle.up()
338
		if not success then
339
			while turtle.detectUp() do
340
				if not turtle.digUp() then
341
					writeOut("Blocked attempting to move up.")
342
					writeOut("Please clear and press enter to continue.")
343
					io.read()
344
				end
345
			end
346
		end
347
	end
348
end
349
350
function safeDown()
351
	simulationCheck()
352
	positionZ = positionZ - 1
353
	fuel = fuel + 1
354
	progressUpdate()
355
	if cost_only then
356
		return
357
	end
358
	checkFuel()
359
	local success = false
360
	while not success do
361
		success = turtle.down()
362
		if not success then
363
			while turtle.detectDown() do
364
				if not turtle.digDown() then
365
					writeOut("Blocked attempting to move down.")
366
					writeOut("Please clear and press enter to continue.")
367
					io.read()
368
				end
369
			end
370
		end
371
	end
372
end
373
374
function moveY(targetY)
375
	if targetY == positionY then
376
		return
377
	end
378
	if (facing ~= 0 and facing ~= 2) then -- Check axis
379
		turnRightTrack()
380
	end
381
	while targetY > positionY do
382
		if facing == 0 then
383
			safeForward()
384
		else
385
			safeBack()
386
		end
387
	end
388
	while targetY < positionY do
389
		if facing == 2 then
390
			safeForward()
391
		else
392
			safeBack()
393
		end
394
	end
395
end
396
397
function moveX(targetX)
398
	if targetX == positionX then
399
		return
400
	end
401
	if (facing ~= 1 and facing ~= 3) then -- Check axis
402
		turnRightTrack()
403
	end
404
	while targetX > positionX do
405
		if facing == 1 then
406
			safeForward()
407
		else
408
			safeBack()
409
		end
410
	end
411
	while targetX < positionX do
412
		if facing == 3 then
413
			safeForward()
414
		else
415
			safeBack()
416
		end
417
	end
418
end
419
420
function moveZ(targetZ)
421
	if targetZ == positionZ then
422
		return
423
	end
424
	while targetZ < positionZ do
425
		safeDown()
426
	end
427
	while targetZ > positionZ do
428
		safeUp()
429
	end
430
end
431
432
-- I *HIGHLY* suggest formatting all shape subroutines to use the format that dome() uses;  specifically, navigateTo(x,y,[z]) then placeBlock().  This should ensure proper "data recording" and also makes readability better
433
function navigateTo(targetX, targetY, targetZ, move_z_first)
434
	targetZ = targetZ or positionZ -- If targetZ isn't used in the function call, it defaults to its current z position, this should make it compatible with all previous implementations of navigateTo()
435
	move_z_first = move_z_first or false -- Defaults to moving z last, if true is passed as 4th argument, it moves vertically first
436
	
437
	if move_z_first then
438
		moveZ(targetZ)
439
	end
440
	
441
	if facing == 0 or facing == 2 then -- Y axis
442
		moveY(targetY)
443
		moveX(targetX)
444
	else
445
		moveX(targetX)
446
		moveY(targetY)
447
	end
448
	
449
	if not move_z_first then
450
		moveZ(targetZ)
451
	end
452
end
453
454
function goHome()
455
	if chain_next_shape then
456
		if not special_chain then
457
			navigateTo(0, 0) -- So another program can chain multiple shapes together to create bigger structures
458
		end
459
	else
460
		navigateTo(-1, -1, 0) -- So the user can collect the turtle when it is done -- also not 0,0,0 because some shapes use the 0,0 column
461
	end
462
	turnToFace(0)
463
end
464
465
-- Shape Building functions
466
467
function line(length)
468
	if length <= 0 then
469
		error("Error, length can not be 0")
470
	end
471
	local i
472
	for i = 1, length do
473
		placeBlock()
474
		if i ~= length then
475
			safeForward()
476
		end
477
	end
478
end
479
480
function rectangle(depth, width)
481
	if depth <= 0 then
482
		error("Error, depth can not be 0")
483
	end
484
	if width <= 0 then
485
		error("Error, width can not be 0")
486
	end
487
	local lengths = {depth, width, depth, width }
488
	local j
489
	for j=1,4 do
490
		line(lengths[j])
491
		turnRightTrack()
492
	end
493
end
494
495
function square(width)
496
	rectangle(width, width)
497
end
498
499
function wall(length, height)
500
	local i
501
	local j
502
	for i = 1, length do
503
		for j = 1, height do
504
			placeBlock()
505
			if j < height then
506
				safeUp()
507
			end
508
		end
509
		safeForward()
510
		for j = 1, height - 1 do
511
			safeDown()
512
		end
513
	end
514
	turnLeftTrack()
515
end
516
517
function platform(x, y)
518
	local forward = true
519
	for counterY = 0, y - 1 do
520
		for counterX = 0, x - 1 do
521
			if forward then
522
				navigateTo(counterX, counterY)
523
			else
524
				navigateTo(x - counterX - 1, counterY)
525
			end
526
			placeBlock()
527
		end
528
		if forward then
529
			forward = false
530
		else
531
			forward = true
532
		end
533
	end
534
end
535
536
function cuboid(depth, width, height, hollow)
537
	platform(depth, width)
538
	while (facing > 0) do
539
		turnLeftTrack()
540
	end
541
	turnAroundTrack()
542
	if ((width % 2) == 0) then -- This is for reorienting the turtle to build the walls correct in relation to the floor and ceiling
543
		turnLeftTrack()
544
	end
545
	if not(hollow == "n") then
546
		for i = 1, height - 2 do
547
			safeUp()
548
			if ((width % 2) == 0) then -- This as well
549
			rectangle(depth, width)
550
			else
551
			rectangle(width, depth)
552
			end
553
		end
554
	else
555
		for i = 1, height - 2 do
556
			safeUp()
557
			platform(depth,width)
558
		end
559
	end
560
	safeUp()
561
	platform(depth, width)
562
end
563
564
function pyramid(length, hollow)
565
	height = math.ceil(length / 2)
566
	for i = 1, height do
567
		if hollow=="y" then
568
			rectangle(length, length)
569
		else
570
			platform(length, length)
571
			navigateTo(0,0)
572
			while facing ~= 0 do
573
				turnRightTrack()
574
			end
575
		end
576
		if i ~= height then
577
			safeUp()
578
			safeForward()
579
			turnRightTrack()
580
			safeForward()
581
			turnLeftTrack()
582
			length = length - 2
583
		end
584
	end
585
end
586
587
function stair(width, height)
588
	turnRightTrack()
589
	local counterX = 1
590
	local counterY = 0.0
591
	local goForward = 0
592
	while counterY < height do
593
		while counterX < width do
594
			placeBlock()
595
			safeForward()
596
			counterX = counterX + 1
597
		end		
598
		placeBlock()
599-
		if stepUp == true then
599+
600
		counterY = counterY + 0.5
601
		if counterY < height then
602
			if goForward == 1 and stepUp == true then  --gofw 1; stU 1
603
				turnRightTrack()
604
				safeForward()
605
				turnRightTrack()				
606
				goForward = 0
607-
			if goForward == 1 and stepUp == true then
607+
608
			end
609
			if goForward == 1 and stepUp == false then		--gofw 1; stU 0
610
				turnRightTrack()
611
				safeUp()
612
				safeForward()
613-
			else if goForward == 1 then
613+
614
				goForward = 0
615
				stepUp = true
616
			end
617
			if goForward == 0 and stepUp == true then		--gofw 0; stU 1
618
				turnLeftTrack()
619
				safeUp()
620
				safeForward()
621
				turnLeftTrack()
622
				goForward = 1
623
				stepUp = true
624
				end
625
			if goForward == 0 and stepUp == false then		--gofw 0; stU 0
626
				turnLeftTrack()
627
				safeUp()
628
				turtle.select(15)
629
				turtle.placeDown()
630
				turtle.select(1)
631
				safeForward()
632
				turnLeftTrack()
633
				goForward = 1
634
				stepUp = true
635
				end
636
			end
637
		end
638
	end
639
end
640
641
function circle(diameter)
642
	odd = not (math.fmod(diameter, 2) == 0)
643
	radius = diameter / 2;
644
	if odd then
645
		width = (2 * math.ceil(radius)) + 1;
646
		offset = math.floor(width/2);
647
	else
648
		width = (2 * math.ceil(radius)) + 2;
649
		offset = math.floor(width/2) - 0.5;		
650
	end
651
	--diameter --radius * 2 + 1
652
	sqrt3 = 3 ^ 0.5
653
	boundaryRadius = radius + 1.0
654
	boundary2 = boundaryRadius ^ 2
655
	radius2 = radius ^ 2
656
	z = math.floor(radius)
657
	cz2 = (radius - z) ^ 2
658
	limitOffsetY = (boundary2 - cz2) ^ 0.5
659
	maxOffsetY = math.ceil(limitOffsetY)
660
	-- We do first the +x side, then the -x side to make movement efficient
661
	for side = 0,1 do
662
			-- On the right we go from small y to large y, on the left reversed
663
			-- This makes us travel clockwise (from below) around each layer
664
			if (side == 0) then
665
				yStart = math.floor(radius) - maxOffsetY
666
				yEnd = math.floor(radius) + maxOffsetY
667
				yStep = 1
668
			else
669
				yStart = math.floor(radius) + maxOffsetY
670
				yEnd = math.floor(radius) - maxOffsetY
671
				yStep = -1
672
			end
673
			for y = yStart,yEnd,yStep do
674
				cy2 = (radius - y) ^ 2
675
				remainder2 = (boundary2 - cz2 - cy2)
676
				if remainder2 >= 0 then
677
					-- This is the maximum difference in x from the centre we can be without definitely being outside the radius
678
					maxOffsetX = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
679
					-- Only do either the +x or -x side
680
					if (side == 0) then
681
						-- +x side
682
						xStart = math.floor(radius)
683
						xEnd = math.floor(radius) + maxOffsetX
684
					else
685
						-- -x side
686
						xStart = math.floor(radius) - maxOffsetX
687
						xEnd = math.floor(radius) - 1
688
					end
689
					-- Reverse direction we traverse xs when in -y side
690
					if y > math.floor(radius) then
691
						temp = xStart
692
						xStart = xEnd
693
						xEnd = temp
694
						xStep = -1
695
					else
696
						xStep = 1
697
					end
698
699
					for x = xStart,xEnd,xStep do
700
						-- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
701
						if isSphereBorder(offset, x, y, z, radius2) then
702
							navigateTo(x, y)
703
							placeBlock()
704
						end
705
					end
706
				end
707
			end
708
		end
709
end
710
711
function blockInSphereIsFull(offset, x, y, z, radiusSq)
712
	x = x - offset
713
	y = y - offset
714
	z = z - offset
715
	x = x ^ 2
716
	y = y ^ 2
717
	z = z ^ 2
718
	return x + y + z <= radiusSq
719
end
720
721
function isSphereBorder(offset, x, y, z, radiusSq)
722
	spot = blockInSphereIsFull(offset, x, y, z, radiusSq)
723
	if spot then
724
		spot = not blockInSphereIsFull(offset, x, y - 1, z, radiusSq) or
725
			not blockInSphereIsFull(offset, x, y + 1, z, radiusSq) or
726
			not blockInSphereIsFull(offset, x - 1, y, z, radiusSq) or
727
			not blockInSphereIsFull(offset, x + 1, y, z, radiusSq) or
728
			not blockInSphereIsFull(offset, x, y, z - 1, radiusSq) or
729
			not blockInSphereIsFull(offset, x, y, z + 1, radiusSq)
730
	end
731
	return spot
732
end
733
734
function dome(typus, diameter)
735
	-- Main dome and sphere building routine
736
	odd = not (math.fmod(diameter, 2) == 0)
737
	radius = diameter / 2;
738
	if odd then
739
		width = (2 * math.ceil(radius)) + 1;
740
		offset = math.floor(width/2);
741
	else
742
		width = (2 * math.ceil(radius)) + 2;
743
		offset = math.floor(width/2) - 0.5;		
744
	end
745
	--diameter --radius * 2 + 1
746
	sqrt3 = 3 ^ 0.5
747
	boundaryRadius = radius + 1.0
748
	boundary2 = boundaryRadius ^ 2
749
	radius2 = radius ^ 2
750
	
751
	if typus == "dome" then
752
		zstart = math.ceil(radius)
753
	elseif typus == "sphere" then
754
		zstart = 1
755
	elseif typus == "bowl" then
756
		zstart = 1
757
	end
758
	if typus == "bowl" then
759
		zend = math.floor(radius)
760
	else
761
		zend = width - 1
762
	end
763
764
	-- This loop is for each vertical layer through the sphere or dome.
765
	for z = zstart,zend do
766
		if not cost_only and z ~= zstart then
767
			safeUp()
768
		end
769
		--writeOut("Layer " .. z)
770
		cz2 = (radius - z) ^ 2
771
		limitOffsetY = (boundary2 - cz2) ^ 0.5
772
		maxOffsetY = math.ceil(limitOffsetY)
773
		-- We do first the +x side, then the -x side to make movement efficient
774
		for side = 0,1 do
775
			-- On the right we go from small y to large y, on the left reversed
776
			-- This makes us travel clockwise (from below) around each layer
777
			if (side == 0) then
778
				yStart = math.floor(radius) - maxOffsetY
779
				yEnd = math.floor(radius) + maxOffsetY
780
				yStep = 1
781
			else
782
				yStart = math.floor(radius) + maxOffsetY
783
				yEnd = math.floor(radius) - maxOffsetY
784
				yStep = -1
785
			end
786
			for y = yStart,yEnd,yStep do
787
				cy2 = (radius - y) ^ 2
788
				remainder2 = (boundary2 - cz2 - cy2)
789
				if remainder2 >= 0 then
790
					-- This is the maximum difference in x from the centre we can be without definitely being outside the radius
791
					maxOffsetX = math.ceil((boundary2 - cz2 - cy2) ^ 0.5)
792
					-- Only do either the +x or -x side
793
					if (side == 0) then
794
						-- +x side
795
						xStart = math.floor(radius)
796
						xEnd = math.floor(radius) + maxOffsetX
797
					else
798
						-- -x side
799
						xStart = math.floor(radius) - maxOffsetX
800
						xEnd = math.floor(radius) - 1
801
					end
802
					-- Reverse direction we traverse xs when in -y side
803
					if y > math.floor(radius) then
804
						temp = xStart
805
						xStart = xEnd
806
						xEnd = temp
807
						xStep = -1
808
					else
809
						xStep = 1
810
					end
811
812
					for x = xStart,xEnd,xStep do
813
						-- Only blocks within the radius but still within 1 3d-diagonal block of the edge are eligible
814
						if isSphereBorder(offset, x, y, z, radius2) then
815
							navigateTo(x, y)
816
							placeBlock()
817
						end
818
					end
819
				end
820
			end
821
		end
822
	end
823
end
824
825
function cylinder(diameter, height)
826
	for i = 1, height do
827
		circle(diameter)
828
		safeUp()
829
	end
830
end
831
832
function hexagon(sideLength)
833
	local changeX = sideLength / 2
834
	local changeY = round(math.sqrt(3) * changeX, 0)
835
	changeX = round(changeX, 0)
836
	local counter = 0
837
838
	navigateTo(changeX, 0)
839
840
	for currentSide = 1, 6 do
841
		counter = 0
842
843
		if currentSide == 1 then
844
			for placed = 1, sideLength do
845
				navigateTo(positionX + 1, positionY)
846
				placeBlock()
847
			end
848
		elseif currentSide == 2 then
849
			navigateTo(positionX, positionY + 1)
850
			while positionY <= changeY do
851
				if counter == 0 or counter == 2 or counter == 4 then
852
					navigateTo(positionX + 1, positionY)
853
				end
854
				placeBlock()
855
				navigateTo(positionX, positionY + 1)
856
				counter = counter + 1
857
				if counter == 5 then
858
					counter = 0
859
				end
860
			end
861
		elseif currentSide == 3 then
862
			while positionY <= (2 * changeY) do
863
				if counter == 0 or counter == 2 or counter == 4 then
864
					navigateTo(positionX - 1, positionY)
865
				end
866
				placeBlock()
867
				navigateTo(positionX, positionY + 1)
868
				counter = counter + 1
869
				if counter == 5 then
870
					counter = 0
871
				end
872
			end
873
		elseif currentSide == 4 then
874
			for placed = 1, sideLength do
875
				navigateTo(positionX - 1, positionY)
876
				placeBlock()
877
			end
878
		elseif currentSide == 5 then
879
			navigateTo(positionX, positionY - 1)
880
			while positionY >= changeY do
881
				if counter == 0 or counter == 2 or counter == 4 then
882
					navigateTo(positionX - 1, positionY)
883
				end
884
				placeBlock()
885
				navigateTo(positionX, positionY - 1)
886
				counter = counter + 1
887
				if counter == 5 then
888
					counter = 0
889
				end
890
			end
891
		elseif currentSide == 6 then
892
			while positionY >= 0 do
893
				if counter == 0 or counter == 2 or counter == 4 then
894
					navigateTo(positionX + 1, positionY)
895
				end
896
				placeBlock()
897
				navigateTo(positionX, positionY - 1)
898
				counter = counter + 1
899
				if counter == 5 then
900
					counter = 0
901
				end
902
			end
903
		end
904
	end
905
end
906
907
function octagon(sideLength)
908
	local sideLength2 = sideLength - 1
909
	local change = round(sideLength2 / math.sqrt(2), 0)
910
911
	navigateTo(change, 0)
912
913
	for currentSide = 1, 8 do
914
		if currentSide == 1 then
915
			for placed = 1, sideLength2 do
916
				navigateTo(positionX + 1, positionY)
917
				placeBlock()
918
			end
919
		elseif currentSide == 2 then
920
			for placed = 1, change do
921
				navigateTo(positionX + 1, positionY + 1)
922
				placeBlock()
923
			end
924
		elseif currentSide == 3 then
925
			for placed = 1, sideLength2 do
926
				navigateTo(positionX, positionY + 1)
927
				placeBlock()
928
			end
929
		elseif currentSide == 4 then
930
			for placed = 1, change do
931
				navigateTo(positionX - 1, positionY + 1)
932
				placeBlock()
933
			end
934
		elseif currentSide == 5 then
935
			for placed = 1, sideLength2 do
936
				navigateTo(positionX - 1, positionY)
937
				placeBlock()
938
			end
939
		elseif currentSide == 6 then
940
			for placed = 1, change do
941
				navigateTo(positionX - 1, positionY - 1)
942
				placeBlock()
943
			end
944
		elseif currentSide == 7 then
945
		for placed = 1, sideLength2 do
946
				navigateTo(positionX, positionY - 1)
947
				placeBlock()
948
			end
949
		elseif currentSide == 8 then
950
			for placed = 1, change do
951
				navigateTo(positionX + 1, positionY - 1)
952
				placeBlock()
953
			end
954
		end
955
	end
956
end
957
958
function sixprism(length, height)
959
	for i = 1, height do
960
		hexagon(length)
961
		safeUp()
962
	end
963
end
964
965
function eigthprism(length, height)
966
	for i = 1, height do
967
		octagon(length)
968
		safeUp()
969
	end
970
end
971
972
-- Previous Progress Resuming, Simulation functions, Command Line, and File Backend
973
-- Will check for a "progress" file.
974
function CheckForPrevious() 
975
	if fs.exists(progFileName) then
976
		return true
977
	else
978
		return false
979
	end
980
end
981
982
-- Creates a progress file, containing a serialized table consisting of the shape type, shape input params, and the last known x, y, and z coords of the turtle (beginning of build project)
983
function ProgressFileCreate() 
984
	if not CheckForPrevious() then
985
		fs.makeDir(progFileName)
986
		return true
987
	else
988
		return false
989
	end
990
end
991
992
-- Deletes the progress file (at the end of the project, also at beginning if user chooses to delete old progress)
993
function ProgressFileDelete() 
994
	if fs.exists(progFileName) then
995
		fs.delete(progFileName)
996
		return true
997
	else 
998
		return false
999
	end
1000
end
1001
1002
-- To read the shape params from the file.  Shape type, and input params (e.g. "dome" and radius)
1003
function ReadShapeParams()
1004
	-- TODO. Unneeded for now, can just use the table elements directly
1005
end
1006
1007
function WriteShapeParams(...) -- The ... lets it take any number of arguments and stores it to the table arg{} | This is still unused anywhere
1008
	local paramTable = arg
1009
	local paramName = "param"
1010
	local paramName2 = paramName
1011
	for i, v in ipairs(paramTable) do -- Iterates through the args passed to the function, ex. paramTable[1] i = 1 so paramName2 should be "param1", tested and works!
1012
		paramName2 = paramName .. i
1013
		tempProgTable[paramName2] = v
1014
		progTable[paramName2] = v
1015
	end
1016
end
1017
1018
-- function to write the progress to the file (x, y, z)
1019
function writeProgress()
1020
	local progFile
1021
	local progString = ""
1022
	if not (sim_mode or cost_only) then
1023
		progString = textutils.serialize(progTable) -- Put in here to save processing time when in cost_only
1024
		progFile = fs.open(progFileName, "w")
1025
		progFile.write(progString)
1026
		progFile.close()
1027
	end
1028
1029
end
1030
1031
-- Reads progress from file (shape, x, y, z, facing, blocks, param1, param2, param3)
1032
function readProgress()
1033
	local progFile = fs.open(progFileName, "r")
1034
	local readProgTable = textutils.unserialize(progFile.readAll())
1035
	progFile.close()
1036
	return readProgTable
1037
end
1038
1039
-- compares the progress read from the file to the current sim progress.  needs all four params 
1040
function compareProgress()
1041
	local progTableIn = progTable
1042
	local readProgTable = readProgress()
1043
	if (progTableIn.shape == readProgTable.shape and progTableIn.x == readProgTable.x and progTableIn.y == readProgTable.y and progTableIn.blocks == readProgTable.blocks and progTableIn.facing == readProgTable.facing) then
1044
		writeOut("All caught up!")
1045
		return true -- We're caught up!
1046
	else
1047
		return false -- Not there yet...
1048
	end
1049
end
1050
1051
function getGPSInfo() -- TODO: finish this
1052
	position = gps.locate()
1053
	gpsPositionX = position.x
1054
	gpsPositionZ = position.y
1055
	gpsPositionY = position.z
1056
	
1057
end
1058
1059
function setSimFlags(b)
1060
	sim_mode = b
1061
	cost_only = b
1062
	if cmd_line_cost_only then
1063
		cost_only = true
1064
	end
1065
end
1066
1067
function simulationCheck() -- checks state of the simulation
1068
	if sim_mode then
1069
		if compareProgress() then
1070
			setSimFlags(false) -- If we're caught up, un-set flags
1071
		else
1072
			setSimFlags(true)  -- If not caught up, just re-affirm that the flags are set
1073
		end
1074
	end
1075
end
1076
1077
function continueQuery()
1078
	if cmd_line_resume then
1079
		 return true
1080
	else
1081
		 if not cmd_line then
1082
			 writeOut("Do you want to continue the last job?")
1083
			 local yes = io.read()
1084
			 if yes == "y" then
1085
				 return true
1086
			 else
1087
				 return false
1088
			 end
1089
		 end
1090
	end
1091
end
1092
1093
function progressUpdate()  -- This ONLY updates the local table variable.  Writing is handled above. -- I want to change this to allow for any number of params
1094
	progTable = {shape = choice, enderchestRefilling = tempProgTable.enderchestRefilling, param1 = tempProgTable.param1, param2 = tempProgTable.param2, param3 = tempProgTable.param3, param4 = tempProgTable.param4, x = positionX, y = positionY, z = positionZ, facing = facing, blocks = blocks}
1095
	if not sim_mode then 
1096
		writeProgress()
1097
	end
1098
end
1099
1100
 -- Command Line
1101
function checkCommandLine() --True if arguments were passed
1102
	if #argTable > 0 then
1103
		cmd_line = true
1104
		return true
1105
	else
1106
		cmd_line = false
1107
		return false
1108
	end
1109
end
1110
1111
function needsHelp() -- True if -h is passed
1112
	for i, v in pairs(argTable) do
1113
		if v == "-h" or v == "-help" or v == "--help" then
1114
			return true
1115
		else
1116
			return false
1117
		end
1118
	end
1119
end
1120
1121
function setFlagsFromCommandLine() -- Sets count_only, chain_next_shape, and sim_mode
1122
	for i, v in pairs(argTable) do
1123
		if v == "-c" or v == "-cost" or v == "--cost" then
1124
			cost_only = true
1125
			cmd_line_cost_only = true
1126
			writeOut("Cost only mode")
1127
		end
1128
		if v == "-z" or v == "-chain" or v == "--chain" then
1129
			chain_next_shape = true
1130
			writeOut("Chained shape mode")
1131
		end
1132
		if v == "-r" or v == "-resume" or v == "--resume" then
1133
			cmd_line_resume = true
1134
			writeOut("Resuming")
1135
		end
1136
	end
1137
end
1138
1139
function setTableFromCommandLine() -- Sets progTable and tempProgTable from command line arguments
1140
	progTable.shape = argTable[1]
1141
	tempProgTable.shape = argTable[1]
1142
	local paramName = "param"
1143
	local paramName2 = paramName
1144
	for i = 2, #argTable do
1145
		local addOn = tostring(i - 1)
1146
		paramName2 = paramName .. addOn
1147
		progTable[paramName2] = argTable[i]
1148
		tempProgTable[paramName2] = argTable[i]
1149
	end
1150
end
1151
1152
-- Menu, Drawing and Main functions
1153
1154
function choiceFunction()
1155
	if sim_mode == false and cmd_line == false then -- If we are NOT resuming progress
1156
		choice = io.read()
1157
		choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
1158
		tempProgTable = {shape = choice}
1159
		progTable = {shape = choice}
1160
		if choice == "next" then
1161
			WriteMenu2()
1162
			choice = io.read()
1163
			choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
1164
		end
1165
		if choice == "end" or choice == "exit" then
1166
			writeOut("Goodbye.")
1167
			return
1168
		end
1169
		if choice == "help" then
1170
			showHelp()
1171
			return
1172
		end
1173
		if choice == "credits" then
1174
			showCredits()
1175
			return
1176
		end
1177
		writeOut("Building a "..choice)
1178
		local yes = getInput("string","Want to just calculate the cost?","y","n")
1179
		if yes == 'y' then
1180
			cost_only = true
1181
		end
1182
		local yes = getInput("string","Want turtle to return to start after build?","y","n")
1183
		if yes == 'y' then
1184
			returntohome = true
1185
		end
1186
		local yes = getInput("string","Want the turtle to refill from enderchest (slot 16)?","y","n")
1187
		if yes == 'y' then
1188
			enderchestRefilling = true
1189
			tempProgTable.enderchestRefilling = true;
1190
		end
1191
	elseif sim_mode == true then -- If we ARE resuming progress
1192
		tempProgTable = readProgress()
1193
		choice = tempProgTable.shape
1194
		choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
1195
		enderchestRefilling =  tempProgTable.enderchestRefilling
1196
	elseif cmd_line == true then -- If running from command line
1197
		choice = tempProgTable.shape
1198
		choice = string.lower(choice) -- All checks are aginst lower case words so this is to ensure that
1199
		enderchestRefilling =  tempProgTable.enderchestRefilling
1200
		writeOut("Building a "..choice)
1201
	end	
1202
	if not cost_only then
1203
		turtle.select(1)
1204
		activeslot = 1
1205
		if turtle.getItemCount(activeslot) == 0 then
1206
			if resupply then
1207
				writeOut("Please put building blocks in the first slot.")
1208
			else
1209
				writeOut("Please put building blocks in the first slot (and more if you need them)")
1210
			end
1211
			while turtle.getItemCount(activeslot) == 0 do
1212
				os.sleep(2)
1213
			end
1214
		end
1215
	else
1216
		activeslot = 1
1217
	end
1218
	-- shape selection if cascade
1219
	if choice == "rectangle" then
1220
		local depth = 0
1221
		local width = 0
1222
		if sim_mode == false and cmd_line == false then
1223
			depth = getInput("int","How deep does it need to be?")
1224
			width = getInput("int","How wide does it need to be?")
1225
		elseif sim_mode == true or cmd_line == true then
1226
			depth = tempProgTable.param1
1227
			width = tempProgTable.param2
1228
		end
1229
		tempProgTable.param1 = depth
1230
		tempProgTable.param2 = width
1231
		progTable = {param1 = depth, param2 = width} -- THIS is here because we NEED to update the local table!
1232
		rectangle(depth, width)
1233
	end
1234
	if choice == "square" then
1235
		local sideLength
1236
		if sim_mode == false and cmd_line == false then
1237
			sideLength = getInput("int","What depth/width does it need to be?")
1238
		elseif sim_mode == true or cmd_line == true then
1239
			sideLength = tempProgTable.param1
1240
		end
1241
		tempProgTable.param1 = sideLength
1242
		progTable = {param1 = sideLength}
1243
		square(sideLength)
1244
	end
1245
	if choice == "line" then
1246
		local lineLength = 0
1247
		if sim_mode == false and cmd_line == false then
1248
			lineLength = getInput("int","How long does it need to be?")
1249
		elseif sim_mode == true or cmd_line == true then
1250
			lineLength = tempProgTable.param1
1251
		end
1252
		tempProgTable.param1 = lineLength
1253
		progTable = {param1 = lineLength}
1254
		line(lineLength)
1255
	end
1256
	if choice == "wall" then
1257
	local depth = 0
1258
	local height = 0
1259
		if sim_mode == false and cmd_line == false then
1260
			depth = getInput("int","How deep does it need to be?")
1261
			height = getInput("int","How high does it need to be?")
1262
		elseif sim_mode == true or cmd_line == true then
1263
			depth = tempProgTable.param1
1264
			height = tempProgTable.param2
1265
		end			
1266
		tempProgTable.param1 = depth
1267
		tempProgTable.param2 = height
1268
		progTable = {param1 = depth, param2 = height}
1269
		wall(depth, height)
1270
	end
1271
	if choice == "platform" then
1272
		local depth = 0
1273
		local width = 0
1274
		if sim_mode == false and cmd_line == false then
1275
			depth = getInput("int","How deep does it need to be?")
1276
			width = getInput("int","How wide does it need to be?")
1277
		elseif sim_mode == true or cmd_line == true then
1278
			depth = tempProgTable.param1	
1279
			width = tempProgTable.param2		
1280
		end		
1281
		tempProgTable.param1 = depth
1282
		tempProgTable.param2 = width
1283
		progTable = {param1 = depth, param2 = width}
1284
		platform(width, depth)
1285
	end
1286
	if choice == "stair" then
1287
		local width = 0
1288
		local height = 0
1289
		if sim_mode == false and cmd_line == false then
1290
			width = getInput("int","How wide does it need to be?")
1291
			height = getInput("int","How high does it need to be?")
1292
		elseif sim_mode == true or cmd_line == true then
1293
			width = tempProgTable.param1
1294
			height = tempProgTable.param2
1295
		end
1296
		tempProgTable.param1 = width
1297
		tempProgTable.param2 = height
1298
		progTable = {param1 = width, param2 = height}
1299
		stair(width, height)
1300
		special_chain = true
1301
	end
1302
	if choice == "cuboid" then
1303
		local depth = 0
1304
		local width = 0
1305
		local height = 0
1306
		local hollow = ""
1307
		if sim_mode == false and cmd_line == false then
1308
			depth = getInput("int","How deep does it need to be?")
1309
			width = getInput("int","How wide does it need to be?")
1310
			height = getInput("int","How high does it need to be?")
1311
			hollow = getInput("string","Does it need to be hollow?","y","n")
1312
		elseif sim_mode == true or cmd_line == true then
1313
			depth = tempProgTable.param1
1314
			width = tempProgTable.param2
1315
			height = tempProgTable.param3
1316
			hollow = tempProgTable.param4
1317
		end
1318
		tempProgTable.param1 = depth
1319
		tempProgTable.param2 = width
1320
		tempProgTable.param3 = height
1321
		tempProgTable.param4 = hollow
1322
		if height < 3 then
1323
			height = 3
1324
		end
1325
		if depth < 3 then
1326
			depth = 3
1327
		end
1328
		if width < 3 then
1329
			width = 3
1330
		end	
1331
		progTable = {param1 = depth, param2 = width, param3 = height}
1332
		cuboid(depth, width, height, hollow)
1333
	end
1334
	if choice == "1/2-sphere" or choice == "1/2 sphere" then
1335
		local diameter = 0
1336
		local half = ""
1337
		if sim_mode == false and cmd_line == false then
1338
			diameter = getInput("int","What diameter does it need to be?")
1339
			half = getInput("string","What half of the sphere does it need to be?","bottom","top")
1340
		elseif sim_mode == true or cmd_line == true then
1341
			diameter = tempProgTable.param1
1342
			half = tempProgTable.param2
1343
		end	
1344
		tempProgTable.param1 = diameter
1345
		tempProgTable.param2 = half
1346
		progTable = {param1 = diameter, param2 = half}
1347
		if half == "bottom" then
1348
			dome("bowl", diameter)
1349
		else
1350
			dome("dome", diameter)
1351
		end
1352
	end
1353
	if choice == "dome" then
1354
		local diameter = 0
1355
		if sim_mode == false and cmd_line == false then
1356
			diameter = getInput("int","What diameter does it need to be?")
1357
		elseif sim_mode == true or cmd_line == true then
1358
			diameter = tempProgTable.param1
1359
		end	
1360
		tempProgTable.param1 = diameter
1361
		progTable = {param1 = diameter}
1362
		dome("dome", diameter)
1363
	end
1364
	if choice == "bowl" then
1365
		local diameter = 0
1366
		if sim_mode == false and cmd_line == false then
1367
			diameter = getInput("int","What diameter does it need to be?")
1368
		elseif sim_mode == true or cmd_line == true then
1369
			diameter = tempProgTable.param1
1370
		end	
1371
		tempProgTable.param1 = diameter
1372
		progTable = {param1 = diameter}
1373
		dome("bowl", diameter)
1374
	end
1375
	if choice == "circle" then
1376
		local diameter = 0
1377
		if sim_mode == false and cmd_line == false then
1378
			diameter = getInput("int","What diameter does it need to be?")
1379
		elseif sim_mode == true or cmd_line == true then
1380
			diameter = tempProgTable.param1
1381
		end
1382
		tempProgTable.param1 = diameter
1383
		progTable = {param1 = diameter}
1384
		circle(diameter)
1385
	end
1386
	if choice == "cylinder" then
1387
		local diameter = 0
1388
		local height = 0
1389
		if sim_mode == false and cmd_line == false then
1390
			diameter = getInput("int","What diameter does it need to be?")
1391
			height = getInput("int","How high does it need to be?")
1392
		elseif sim_mode == true or cmd_line == true then
1393
			diameter = tempProgTable.param1
1394
			height = tempProgTable.param2
1395
		end
1396
		tempProgTable.param1 = diameter
1397
		tempProgTable.param2 = height
1398
		progTable = {param1 = diameter, param2 = height}
1399
		cylinder(diameter, height)
1400
	end
1401
	if choice == "pyramid" then
1402
		local length = 0
1403
		local hollow = ""
1404
		if sim_mode == false and cmd_line == false then
1405
			length = getInput("int","What depth/width does it need to be?")
1406
			hollow = getInput("string","Does it need to be hollow?","y","n")
1407
		elseif sim_mode == true or cmd_line == true then
1408
			length = tempProgTable.param1
1409
			hollow = tempProgTable.param2
1410
		end
1411
		tempProgTable.param1 = length
1412
		tempProgTable.param2 = hollow
1413
		progTable = {param1 = length, param2 = hollow}
1414
		pyramid(length, hollow)
1415
	end
1416
	if choice == "sphere" then
1417
		local diameter = 0
1418
		if sim_mode == false and cmd_line == false then
1419
			diameter = getInput("int","What diameter does it need to be?")
1420
		elseif sim_mode == true or cmd_line == true then
1421
			diameter = tempProgTable.param1
1422
		end
1423
		tempProgTable.param1 = diameter
1424
		progTable = {param1 = diameter}
1425
		dome("sphere", diameter)
1426
	end
1427
	if choice == "hexagon" then
1428
		local length = 0
1429
		if sim_mode == false and cmd_line == false then
1430
			length = getInput("int","How long does each side need to be?")
1431
		elseif sim_mode == true or cmd_line == true then
1432
			length = tempProgTable.param1
1433
		end
1434
		tempProgTable.param1 = length
1435
		progTable = {param1 = length}
1436
		hexagon(length)
1437
	end
1438
	if choice == "octagon" then
1439
		local length = 0
1440
		if sim_mode == false and cmd_line == false then
1441
			length = getInput("int","How long does each side need to be?")
1442
		elseif sim_mode == true or cmd_line == true then
1443
			length = tempProgTable.param1
1444
		end
1445
		tempProgTable.param1 = length
1446
		progTable = {param1 = length}
1447
		octagon(length)
1448
	end
1449
	if choice == "6-prism" or choice == "6 prism" then
1450
		local length = 0
1451
		local height = 0
1452
		if sim_mode == false and cmd_line == false then
1453
			length = getInput("int","How long does each side need to be?")
1454
			height = getInput("int","What height does it need to be?")
1455
		elseif sim_mode == true or cmd_line == true then
1456
			length = tempProgTable.param1
1457
			height = tempProgTable.param2
1458
		end
1459
		tempProgTable.param1 = length
1460
		tempProgTable.param2 = height
1461
		progTable = {param1 = length, param2 = height}
1462
		sixprism(length, height)
1463
	end
1464
	if choice == "8-prism" or choice == "8 prism" then
1465
		local length = 0
1466
		local height = 0
1467
		if sim_mode == false and cmd_line == false then
1468
			length = getInput("int","How long does each side need to be?")
1469
			height = getInput("int","What height does it need to be?")
1470
		elseif sim_mode == true or cmd_line == true then
1471
			length = tempProgTable.param1
1472
			height = tempProgTable.param2
1473
		end
1474
		tempProgTable.param1 = length
1475
		tempProgTable.param2 = height
1476
		progTable = {param1 = length, param2 = height}
1477
		eightprism(length, height)
1478
	end
1479
	if returntohome then
1480
		goHome() -- After all shape building has finished
1481
	end
1482
	writeOut("Done") -- Saves a few lines when put here rather than in each if statement
1483
end
1484
1485
function WriteMenu()
1486
	term.clear()
1487
	term.setCursorPos(1, 1)
1488
	writeOut("Shape Maker 1.5 by Keridos/Happydude/pokemane")
1489
	if resupply then					-- Any ideas to make this more compact/betterlooking (in terms of code)?
1490
		writeOut("Resupply Mode Active")
1491
	elseif (resupply and can_use_gps) then
1492
		writeOut("Resupply and GPS Mode Active")
1493
	elseif can_use_gps then
1494
		writeOut("GPS Mode Active")
1495
	else
1496
		writeOut("")
1497
	end
1498
	if not cmd_line then
1499
		writeOut("What should be built? [page 1/2]");
1500
		writeOut("next for page 2")
1501
		writeOut("+---------+-----------+-------+-------+")
1502
		writeOut("| square  | rectangle | wall  | line  |")
1503
		writeOut("| cylinder| platform  | stair | cuboid|")
1504
		writeOut("| pyramid | 1/2-sphere| circle| next  |")
1505
		writeOut("+---------+-----------+-------+-------+")
1506
		writeOut("")
1507
	end
1508
end
1509
1510
function WriteMenu2()
1511
	term.clear()
1512
	term.setCursorPos(1, 1)
1513
	writeOut("Shape Maker 1.5 by Keridos/Happydude/pokemane")
1514
	if resupply then					-- Any ideas to make this more compact/betterlooking (in terms of code)?
1515
		writeOut("Resupply Mode Active")
1516
	elseif (resupply and can_use_gps) then
1517
		writeOut("Resupply and GPS Mode Active")
1518
	elseif can_use_gps then
1519
		writeOut("GPS Mode Active")
1520
	else
1521
		writeOut("")
1522
	end
1523
	writeOut("What should be built [page 2/2]?");
1524
	writeOut("")
1525
	writeOut("+---------+-----------+-------+-------+")
1526
	writeOut("| hexagon | octagon   | help  |       |")
1527
	writeOut("| 6-prism | 8-prism   | end   |       |")
1528
	writeOut("| sphere  | credits   |       |       |")
1529
	writeOut("+---------+-----------+-------+-------+")
1530
	writeOut("")
1531
end
1532
1533
function showHelp()
1534
	writeOut("Usage: shape [shape-type [param1 param2 param3 ...]] [-c] [-h] [-z] [-r]")
1535
	writeOut("-c: Activate cost only mode")
1536
	writeOut("-h: Show this page")
1537
	writeOut("-z: Set chain_next_shape to true, lets you chain together multiple shapes")
1538
	io.read() -- Pause here
1539
	writeOut("-r: Resume the last shape if there is a resume file")
1540
	writeOut("shape-type can be any of the shapes in the menu")
1541
	writeOut("After shape-type input all of the paramaters for the shape")
1542
	io.read() -- Pause here, too
1543
end
1544
1545
function showCredits()
1546
	writeOut("Credits for the shape builder:")
1547
	writeOut("Based on work by Michiel,Vliekkie, and Aeolun")
1548
	writeOut("Sphere/dome code by pruby")
1549
	writeOut("Additional improvements by Keridos,Happydude and pokemane")
1550
	io.read() -- Pause here, too
1551
end
1552
1553
function main()
1554
	if wrapmodules()=="resupply" then
1555
		linkToRSStation()
1556
	end
1557
	if checkCommandLine() then
1558
		if needsHelp() then
1559
			showHelp()
1560
			return -- Close the program after help info is shown
1561
		end
1562
		setFlagsFromCommandLine()
1563
		setTableFromCommandLine()
1564
	end
1565
	if (CheckForPrevious()) then  -- Will check to see if there was a previous job and gps is enabled, and if so, ask if the user would like to re-initialize to current progress status
1566
		if not continueQuery() then -- If the user doesn't want to continue
1567
			ProgressFileDelete()
1568
			setSimFlags(false) -- Just to be safe
1569
			WriteMenu()
1570
			choiceFunction()
1571
		else	-- If the user wants to continue
1572
			setSimFlags(true)
1573
			choiceFunction()
1574
		end
1575
	else
1576
		setSimFlags(false)
1577
		WriteMenu()
1578
		choiceFunction()
1579
	end
1580
	if (blocks ~= 0) and (fuel ~= 0) then -- Do not show on help or credits page or when selecting end
1581
		writeOut("Blocks used: " .. blocks)
1582
		writeOut("Fuel used: " .. fuel)
1583
	end
1584
	ProgressFileDelete() -- Removes file upon successful completion of a job, or completion of a previous job.
1585
	progTable = {}
1586
	tempProgTable = {}
1587
end
1588
1589
main()