aHarvester.lua

737 lines · 21.8 KB

Open raw

{program="aHarvester",version="1.10",date="2024-10-30"}

Copy & run

wget https://perlytiara.github.io/turtles.tips/raw/programs/Kaikaku/aHarvester.lua
1--{program="aHarvester",version="1.10",date="2024-10-30"}
2---------------------------------------
3-- aHarvester by Kaikaku
4-- 2024-10-30, v1.10 UI fix
5-- 2021-03-05, v1.02c info clar. + gfs()
6-- 2021-02-28, v1.01 info clarification
7-- 2021-02-28, v1.00 initial
8---------------------------------------
9
10---------------------------------------
11---- DESCRIPTION ----------------------
12---------------------------------------
13-- This program automates the farming
14-- of many different plants like
15-- sugarcane, melons, bamboo. Those
16-- plants must grow from a source
17-- block, that is not to be harvested.
18-- Harvested material is droped into
19-- chest. Fuel is taken from another.
20-- For more feature details see info
21-- screens or YouTube.
22
23
24---------------------------------------
25---- ASSUMPTIONS ----------------------
26---------------------------------------
27-- Turtle is a mining turtle and a
28-- sample of its landmark block in
29-- slot 1.
30
31
32---------------------------------------
33---- PARAMETERS -----------------------
34---------------------------------------
35local cVersion ="v1.02c"
36local cPrgName ="aHarvester"
37local cCritFuel =800 -- stops at fuel station / home if lower than this
38local cMinFuel =2000 -- refuels at fuel station if lower than this
39local slotFuel=16
40local cSleepTime=60
41local cMaxTurns =-1
42local turnCounter =0
43local turnsRemaining =cMaxTurns
44local blnCreateStartup=false
45local createStartup = "shell.run('"..cPrgName.." "
46local blnNoCannibalism=false -- no checks for other turtles (a bit slower)
47local blnDetectedTurtle=false
48local cNoCannibalism={}
49-- Hint: in case of new botonia versions this might need an update!
50cNoCannibalism[0]="computercraft:turtle_normal"
51cNoCannibalism[1]="computercraft:turtle_advanced"
52
53local harvestedStuff=0
54local harvestedStuffTotal=0
55
56---------------------------------------
57---- VARIABLES ------------------------
58---------------------------------------
59local blnAskForParameters =true
60
61local blnDown = true
62local blnUp = true
63
64local landmarkU -- up
65local landmarkF --forward
66local landmarkD --down
67
68local nextTrunRight = true
69local nextTrunTurn = false
70local blnGoOn = true
71
72
73---------------------------------------
74---- Early UI functions ---------------
75---------------------------------------
76local function swapColors() -- <<-- put into template
77local backColor=term.getBackgroundColor()
78local textColor=term.getTextColor()
79
80term.setBackgroundColor(textColor)
81term.setTextColor(backColor)
82end
83
84local function printUI(strInput)
85if strInput==ni then strInput="" end
86
87 if strInput=="header" then
88 term.write("+-------------------------------------") print("+")
89 elseif strInput=="line" then
90 term.write("+-------------------------------------") print("+")
91 elseif strInput=="footer" then
92 term.write("+-------------------------------------") print("+")
93 else
94 term.write("|")
95 strInput=strInput.." "
96 term.write(string.sub(strInput,1,37))
97 print("|")
98 end
99end
100
101---------------------------------------
102---- tArgs ----------------------------
103---------------------------------------
104local tArgs = {...} -- <<-- transfere concept to template
105local paraIdentified=false
106local paraNumberCount=0
107term.clear() term.setCursorPos(1,1)
108
109-- header
110if #tArgs~=0 then
111 printUI("header")
112 printUI(""..cPrgName..", "..cVersion..", by Kaikaku. Enjoy!")
113 printUI("line")
114 print("Starting...")
115end
116
117-- check parameters
118for i=1,#tArgs do
119 blnAskForParameters=false
120 paraIdentified=false
121 -- tet parameters
122 if string.lower(tArgs[i])=="notdown" then
123 paraIdentified=true blnDown=false
124 createStartup=createStartup..tArgs[i].." "
125 print("Option: not dig down!")
126 end
127 if string.lower(tArgs[i])=="notup" then
128 paraIdentified=true blnUp=false
129 createStartup=createStartup..tArgs[i].." "
130 print("Option: not dig up!")
131 end
132 if string.lower(tArgs[i])=="nocannibalism" then
133 paraIdentified=true blnNoCannibalism=true
134 createStartup=createStartup..tArgs[i].." "
135 print("Option: no cannibalism!")
136 end
137 if string.lower(tArgs[i])=="startup" then
138 paraIdentified=true blnCreateStartup=true
139 print("Option: creating startup")
140 end
141 -- text+number parameters
142 if string.sub(string.lower(tArgs[i]),1,7)=="minfuel" then
143 term.write("Option: minFuel "..cMinFuel.."->")
144 paraIdentified=true
145 createStartup=createStartup..tArgs[i].." "
146 cMinFuel=tonumber(string.sub(string.lower(tArgs[i]),8))
147 print(cMinFuel)
148 end
149 if string.sub(string.lower(tArgs[i]),1,8)=="critfuel" then
150 term.write("Option: critFuel "..cCritFuel.."->")
151 paraIdentified=true
152 createStartup=createStartup..tArgs[i].." "
153 cCritFuel=tonumber(string.sub(string.lower(tArgs[i]),9))
154 print(cCritFuel)
155 end
156 -- number parameters
157 if not paraIdentified then
158 if paraNumberCount==0 then
159 cSleepTime=tonumber(tArgs[i]) -- no error handling for text
160 paraIdentified=true
161 createStartup=createStartup..tArgs[i].." "
162 paraNumberCount=paraNumberCount+1
163 print("Option: sleep time = "..cSleepTime)
164 elseif paraNumberCount==1 then
165 cMaxTurns=tonumber(tArgs[i]) -- no error handling for text
166 turnsRemaining=cMaxTurns
167 paraIdentified=true
168 createStartup=createStartup..tArgs[i].." "
169 paraNumberCount=paraNumberCount+1
170 print("Option: fixed number of turns = "..cMaxTurns)
171 end
172 end
173 if not paraIdentified then
174 error("Error: Unknown parameter "..i..":'"..tArgs[i].."'")
175 end
176sleep(0.3)
177end
178
179--------------------------------------- -- <<--- put in template
180---- startup generation ---------------
181---------------------------------------
182if blnCreateStartup then
183local newFileName
184 createStartup=createStartup.."')"
185 print("Creating a startup file with: "..createStartup)
186
187 -- is there already one?
188 if fs.exists("startup.lua") then
189 print(" '".."startup.lua".."' already exists.")
190 newFileName="startup_old_"..os.date("%Y-%m-%d_%H:%M")
191 print(" Renaming to '".."startup.lua".."'")
192 shell.run("rename startup.lua "..newFileName)
193 end
194 if fs.exists("startup") then
195 print(" '".."startup".."' already exists.")
196 newFileName="startup_old_"..os.date("%Y-%m-%d_%H:%M")
197 print(" Renaming to '"..newFileName.."'")
198 shell.run("rename startup "..newFileName)
199 end
200
201 print("Saving new startup...")
202
203
204local h = fs.open("startup", "w")
205h.writeLine("-- Automatically created startup by:")
206h.writeLine("-- "..cPrgName..", "..cVersion..", by Kaikaku")
207h.writeLine("-- If you are looking for another")
208h.writeLine("-- startup file, check files like:")
209h.writeLine("-- 'startup_old_yyyy-mm-dd-tttt'")
210h.writeLine(createStartup)
211h.close()
212
213end
214
215---------------------------------------
216-- basic functions for turtle control -
217---------------------------------------
218local function gf() while not turtle.forward() do end end
219local function gb() while not turtle.back() do end end
220local function gu() while not turtle.up() do end end
221local function gd() while not turtle.down() do end end
222local function gl() while not turtle.turnLeft() do end end
223local function gr() while not turtle.turnRight() do end end
224local function df() local returnValue = turtle.dig() turtle.suck() return returnValue end
225local function gfs(n) if n==nil then n=1 end for i=1,n,1 do while not turtle.forward() do df() end end end
226local function du() turtle.digUp() turtle.suckUp() end
227local function dd() turtle.digDown() turtle.suckDown() end
228local function pf() turtle.place() end
229local function pu() turtle.placeUp() end
230local function pd() return turtle.placeDown() end
231local function sf() turtle.suck() end
232local function su() turtle.suckUp() end
233local function sd() turtle.suckDown() end
234local function Df() turtle.drop() end
235local function Du(n) turtle.dropUp(n) end
236local function Dd() turtle.dropDown() end
237local function ss(s) turtle.select(s) end
238local function gic(s) return turtle.getItemCount(s) end
239
240
241
242local function waitKey(strText)
243 local event, scancode
244 write(strText)
245 event, scancode = os.pullEvent("key")
246 print()
247end
248
249local function askForInputText(textt)
250 local at=""
251 -- check prompting texts
252 if textt==nil then textt="Enter text:" end
253
254 -- ask for input
255 write(textt)
256 at=read()
257 return at
258end
259
260local function checkFuel()
261 local tmp=turtle.getFuelLevel()
262 return tmp
263end
264
265local function checkTurtle()
266-- turtle?
267 local turtleOk, turtleVal = pcall(checkFuel)
268 if not turtleOk then
269 term.clear() term.setCursorPos(1,1)
270 print("+-------------------------------------+")
271 print(" ",cPrgName,", by Kaikaku")
272 print("+-------------------------------------+")
273 print("| This is a turtle program. |")
274 print("| Please, execute it with a turtle! |")
275 print("+-------------------------------------+")
276 return
277 end
278end
279
280
281local function sleepDots(sec)
282if sec==nil then sec=10 end
283if sec<1 then return end
284local sleepDotsCounter=0
285
286 for i=1,sec-1 do
287 sleepDotsCounter=sleepDotsCounter+1
288 sleep(1)
289 if sleepDotsCounter<31 then
290 term.write(".")
291 else
292 sleepDotsCounter=1
293 print()
294 term.write(".")
295 end
296 end
297
298 sleep(1)
299 print(".")
300end
301
302
303---------------------------------------
304-- additional functions -
305---------------------------------------
306
307
308local function dropInventory()
309 for i=2,16 do
310 if gic(i)>0 then
311 ss(i)
312 harvestedStuff=harvestedStuff+gic()
313 Dd()
314 end
315 end
316 ss(1)
317end
318
319local function doCompares()
320 landmarkU=turtle.compareUp()
321 landmarkF=turtle.compare()
322 landmarkD=turtle.compareDown()
323end
324
325local function doRefuel()
326local fuelAtStart=turtle.getFuelLevel()
327
328 -- call this only at fuel station
329 if turtle.getFuelLevel() < cMinFuel then
330 -- need to refuel
331 term.write(" Refueling:"..turtle.getFuelLevel())
332 if gic(slotFuel)==0 then
333 ss(slotFuel)
334 su()
335 turtle.refuel()
336 ss(1)
337 end
338 print(""..turtle.getFuelLevel())
339 else
340 print(" Fuel is okay.")
341 end
342 return fuelAtStart<turtle.getFuelLevel()
343end
344
345local function checkCritFuel()
346local currentSlot = turtle.getSelectedSlot()
347 while turtle.getFuelLevel()<cCritFuel do
348 ss(slotFuel)
349 print("Critical fuel level ("..turtle.getFuelLevel().."/"..cCritFuel..")!")
350 term.write(" Please, provide fuel in slot "..slotFuel.."!")
351 while gic(slotFuel)==0 do
352 term.write(".")
353 sleep(1)
354 end
355 turtle.refuel()
356 end
357 ss(currentSlot)
358end
359
360
361local function suckAll()
362 while turtle.suck() do end
363 while turtle.suckUp() do end
364 while turtle.suckDOwn() do end
365end
366
367local function debugPrint(str)
368 if false then print(str) end
369end
370
371local function inspectFor(blockArray, strDirection)
372if strDirection==nil then strDirection="f" end
373local blnOk, data
374
375 -- inspect
376 if strDirection=="d" then blnOk, data = turtle.inspectDown()
377 elseif strDirection=="u" then blnOk, data = turtle.inspectUp()
378 elseif strDirection=="f" then blnOk, data = turtle.inspect()
379 else
380 print("Warning: Unknown direction '",strDirection,"' in inspectFor, taking (f)orward instead.")
381 strDirection="f"
382 blnOk, data = turtle.inspect()
383 end
384 if data.name~=nil then debugPrint("Found:"..string.lower(data.name)) end
385 -- compare
386 local i=1
387 while blockArray[i]~=nil do
388 debugPrint("Compare to:"..string.lower(blockArray[i]))
389 if data.name~=nil then
390 if string.lower(data.name) == string.lower(blockArray[i]) then return true end
391 end
392 i=i+1
393 end
394
395 return false -- reached a nil value
396end
397
398local function evadeStrategy()
399local cTurnProbablity=20
400local tmpRnd = math.random(0,100)
401 term.write("")
402 if tmpRnd<=cTurnProbablity then
403 gr() term.write("r")
404 elseif tmpRnd<=cTurnProbablity*2 then
405 gl() term.write("l")
406 else
407 term.write("s") sleep(0.8)
408 end
409end
410
411local function handleReport()
412 print(" Harvested items this turn: "..harvestedStuff)
413 harvestedStuffTotal=harvestedStuffTotal+harvestedStuff
414 harvestedStuff=0
415 print(" Harvested items total: "..harvestedStuffTotal)
416end
417
418local function handleTurnCounter()
419-- return true if cMaxTurns is reached, else false
420 handleReport()
421 if turnsRemaining==0 then return true end
422 turnCounter=turnCounter+1
423 if cMaxTurns>=0 then
424 turnsRemaining=turnsRemaining-1
425 term.write("Turn "..turnCounter.."/"..cMaxTurns..":")
426 else
427 term.write("Turn "..turnCounter..":")
428 end
429 return false
430end
431
432------------------------------------------------------------------------------
433-- main ----------------------------------------------------------------------
434------------------------------------------------------------------------------
435checkTurtle()
436
437if blnAskForParameters then
438term.clear() term.setCursorPos(1,1)
439local iPage=0
440local iPageMax=10
441term.clear() term.setCursorPos(1,1) iPage=iPage+1
442repeat
443printUI("header")
444printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
445printUI("line")
446-- 1234567890123456789012345678901234567
447printUI("This program automates the farming")
448printUI(" of many different plants like")
449printUI(" sugar cane, melons, mushrooms,")
450printUI(" bamboo, kelp and many more. These")
451printUI(" plants typically grow or spread")
452printUI(" from a source block. ")
453printUI("Starting it w/o parameter (as now)")
454printUI(" shows this info and uses defaults.")
455printUI("footer")
456until askForInputText("Press enter when ready:")==""
457
458term.clear() term.setCursorPos(1,1) iPage=iPage+1
459repeat
460printUI("header")
461printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
462printUI("line")
463-- 1234567890123456789012345678901234567
464printUI("Determine a landmark block (not dirt)")
465printUI(" and frame the area in where to har-")
466printUI(" vest. Place this frame at y level")
467printUI(" of the turtle is. Put 1 in slot 1.")
468printUI("The turtle will allways move forward")
469printUI(" until it hits this block. Then it")
470printUI(" makes a u-turn right then left...")
471printUI(" In corners it changes the orient.")
472printUI("footer")
473until askForInputText("Press enter when ready:")==""
474
475term.clear() term.setCursorPos(1,1) iPage=iPage+1
476repeat
477printUI("header")
478printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
479printUI("line")
480-- 1234567890123456789012345678901234567
481printUI("Put a chest below the turtle level")
482printUI(" with a landmark block two blocks")
483printUI(" above, this is the home position.")
484printUI("Place a chest above the turtle level")
485printUI(" with a landmark block two blocks")
486printUI(" below, this is the refuel chest.")
487printUI("You can have as many home and fuel")
488printUI(" stations as you like.")
489printUI("footer")
490until askForInputText("Press enter when ready:")==""
491
492term.clear() term.setCursorPos(1,1) iPage=iPage+1
493repeat
494printUI("header")
495printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
496printUI("line")
497-- 1234567890123456789012345678901234567
498printUI("Side view example:")
499printUI(" ")
500printUI(" L c T=turtle")
501printUI(" Lssssss T L L=landmark block")
502printUI(" ssssss C L s=sugar cane")
503printUI(" ssssss C=home chest")
504printUI(" XXXXXXXXXXXX c=fuel chest")
505printUI(" XXXXXXXXXXXX X=dirt/etc.")
506printUI("footer")
507until askForInputText("Press enter when ready:")==""
508
509term.clear() term.setCursorPos(1,1) iPage=iPage+1
510repeat
511printUI("header")
512printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
513printUI("line")
514-- 1234567890123456789012345678901234567
515printUI("Number parameters: ")
516printUI(" The first number parameter you use")
517printUI(" determines the waiting time at ")
518printUI(" the home position (default=60).")
519printUI(" A second number parameter deter-")
520printUI(" mines the number of turns ")
521printUI(" (=reaching home position) if you")
522printUI(" want to limit the runs.")
523printUI("footer")
524until askForInputText("Press enter when ready:")==""
525term.clear() term.setCursorPos(1,1) iPage=iPage+1
526
527repeat
528printUI("header")
529printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
530printUI("line")
531-- 1234567890123456789012345678901234567
532printUI("Harvest options: ")
533printUI(" Turtle will harvest allways blocks ")
534printUI(" in front of it and by default all")
535printUI(" blocks above and below it. ")
536printUI(" To disable harvesting of blocks you")
537printUI(" use one or both of the following ")
538printUI(" not case sensitive parameters: ")
539printUI(" notUp and/or notDown")
540printUI("footer")
541until askForInputText("Press enter when ready:")==""
542
543term.clear() term.setCursorPos(1,1) iPage=iPage+1
544repeat
545printUI("header")
546printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
547printUI("line")
548-- 1234567890123456789012345678901234567
549printUI("Fuel parameters: At min fuel level")
550printUI(" (2000) the turtle refuels. With")
551printUI(" the parameter minFuelxxxx you cust-")
552printUI(" omize this value to 'xxxx'.")
553printUI("At crit fuel level (800) the turtle")
554printUI(" won't move from home or (empty?)")
555printUI(" fuel stations: Use parameter ")
556printUI(" critFuelxxxx to change this.")
557printUI("footer")
558until askForInputText("Press enter when ready:")==""
559
560term.clear() term.setCursorPos(1,1) iPage=iPage+1
561repeat
562printUI("header")
563printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
564printUI("line")
565-- 1234567890123456789012345678901234567
566printUI("Auto startup:")
567printUI(" If you want the turtle to allways")
568printUI(" start the program when the world or")
569printUI(" chunk is loaded, use the parameter:")
570printUI(" startup")
571printUI(" This will create a startup pro-")
572printUI(" gram using the same parameters")
573printUI(" as the current call.")
574printUI("footer")
575until askForInputText("Press enter when ready:")==""
576
577term.clear() term.setCursorPos(1,1) iPage=iPage+1
578repeat
579printUI("header")
580printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
581printUI("line")
582-- 1234567890123456789012345678901234567
583printUI("Example calls:")
584printUI("aHarvester notDown")
585printUI("->Turtle starts w/ default values, ")
586printUI(" but no harvesting down.")
587printUI("aHarvester 120 2 minFuel1000 startup")
588printUI("->Creates a startup program, 120 sec")
589printUI(" waiting at home, only 2 runs, min")
590printUI(" fuel is set to 1000. Turtle starts.")
591printUI("footer")
592until askForInputText("Press enter when ready:")==""
593
594term.clear() term.setCursorPos(1,1) iPage=iPage+1
595repeat
596printUI("header")
597printUI(""..cPrgName..", "..cVersion..", by Kaikaku ("..iPage.."/"..iPageMax..")")
598printUI("line")
599-- 1234567890123456789012345678901234567
600printUI("Parameter: noCannibalsm")
601printUI(" You can use multiple turtles in one")
602printUI(" farm w/o them eating each other.")
603printUI(" In very rare cases, the hungry ")
604printUI(" turtle will stop until solved.")
605printUI("Sorry for this long description, as")
606printUI(" fall back you can watch the YouTube")
607printUI(" video. Enjoy!")
608printUI("footer")
609until askForInputText("Press enter to START! (stop w/ ctrl+t)")==""
610end
611
612
613---------------------------------------
614-- main loop -
615---------------------------------------
616
617-- step 1: check starting stuff
618ss(1)
619local tmpSleep=1
620while turtle.getItemCount()==0 do
621 print("Put 1 landmark block in slot 1!")
622 print("Sleeping",tmpSleep,"seconds")
623 sleepDots(tmpSleep)
624 tmpSleep=tmpSleep+1
625 ss(1)
626end
627
628
629-- step 2: program loop
630term.write("Inital turn 0:")
631
632while blnGoOn do
633
634
635 -- step 2.0: need to turn once more?
636 if nextTrunTurn then
637 -- need to turn once more, because of wall last turn
638 nextTrunTurn=false
639 if nextTrunRight then
640 gr() print("r") nextTrunRight=false
641 else
642 gl() print("l") nextTrunRight=true
643 end
644 end
645
646 -- step 2.1: check for landmarks
647 doCompares()
648
649 -- step 2.2: handle home base
650 if landmarkU then
651 -- at my base
652 if math.random()<0.95 then
653 print() term.write("Home. ")
654 else
655 print() term.write("I'm home, honey! ")
656 end
657 print("Fuel:",turtle.getFuelLevel().."/"..cMinFuel)
658 print("Dropping inventory:")
659 dropInventory()
660 if handleTurnCounter() then print("Finished all "..cMaxTurns.." turns.") break end
661 print(" Sleeping for "..cSleepTime.." seconds")
662 sleepDots(cSleepTime)
663 checkCritFuel()
664
665 end
666
667 -- step 2.3: handle fuel station
668 if landmarkD then
669 -- at fuel station
670 print() print("Fuel station. Fuel:",turtle.getFuelLevel().."/"..cMinFuel)
671 while doRefuel() do end
672 checkCritFuel()
673 end
674
675 -- step 2.4: handle wall/corner
676 if landmarkF then
677 -- found wall
678 nextTrunTurn=true
679 if nextTrunRight then
680 gr() term.write("r")
681 if turtle.compare() then
682 print() term.write("Changing orientation:")
683 gl() term.write("l") gl() print("l")
684 nextTrunTurn=false
685 nextTrunRight=false
686 end
687 else
688 gl() term.write("l")
689 if turtle.compare() then
690 print() term.write("Changing orientation:")
691 gr() term.write("r") gr() print("r")
692 nextTrunTurn=false
693 nextTrunRight=true
694 end
695 end
696 landmarkF=turtle.compare()
697 end
698
699 -- step 2.5: dig'n move
700 if blnNoCannibalism then blnDetectedTurtle=inspectFor(cNoCannibalism,"f") end
701 if blnDetectedTurtle then
702 -- found a turtle!!
703 evadeStrategy()
704 else
705 -- regular move
706 if not landmarkF then
707 df() while turtle.suck() do end
708 end
709 if not landmarkU and not landmarkD then
710 if blnUp then du() end while turtle.suckUp() do end
711 if blnDown then dd() end while turtle.suckDown() do end
712 end
713 if not landmarkF then
714 if not landmarkD then while turtle.suckUp() do end end
715 if blnNoCannibalism then blnDetectedTurtle=inspectFor(cNoCannibalism,"f") end
716 if not blnDetectedTurtle then gfs() term.write("") end
717 end
718 end
719
720 -- step 2.6: safety check
721 while gic(1)~=1 do
722 print()
723 print("Safety violation!")
724 print(" I need exactly 1 landmark block in")
725 print(" slot 1 (currently: "..gic(1)..")!")
726 term.write("Sleeping for 10 sec ")
727 sleepDots(10)
728 end
729end
730
731
732print("That was quite a bit of work :)")
733 os.sleep(0.4)
734 print("***************************************")
735 print("* Check out YouTube for more videos *")
736 print("* and turtle programs by Kaikaku :) *")
737 print("***************************************")