COMPUTE!'s Gazette October 1984 Issue 16 Vol. 2, No. 10 pages 90-94:

Turtle Graphics Interpreter
Full turtle graphics capabilities without LOGO? Try this three-program package for the Commodore 64.


Turtle Graphics Interpreter
For The 64
Irwin Tillman
This comprehensive three-program package gives your 64 full turtle graphics capabilities. It's an excellent learning tool for children, and it offers a new graphics capacity for all ages. For disk or tape users.
-----------

	Turtle geometry is fast becoming the first exposure to computers for many children. Instead of printing their names on the screen, they are more likely drawing squares and triangles. While such facilities are generally found with specific languages (such as PILOT and Logo), the concept of turtle geometry is not unique to any single language. One of the reasons for its popularity is that it's not only a natural introduction to computing, but also an excellent tool to teach thinking (see Seymour Papert's Mindstorms).

	If you're not familiar with turtle graphics, the basic concept involves moving a turtle around the screen, leaving a trail as it goes. This is accomplished through a series of English commands, such as FORWARD and RIGHT. Other commands control the color scheme, define loops, and allow you to assemble a series of commands into procedures.

Coordinating The Turtle Programs

	"Turtle Graphics Interpreter" consists of three programs designed originally for use with a disk drive; if you are using a tape drive, be sure to read the appropriate section elsewhere in this article.

	The first program, "Interpreter," does most of the work. It accepts and executes the commands you enter. Program 2, "Turtle Data," POKEs in the shape tables for the turtle sprites and a number of machine language routines. Finally, "Turtle Boot" (Program 3) runs the whole thing.

	It is very important that you type the DATA in Program 2 correctly; otherwise the machine language routines may crash the machine when the Interpreter is run. Also, you should leave out the CHR$(31) in line 140 of Program 3 until you're sure everything is working right. This will make the operation of the Boot program visible. When you are sure that the Boot is loading and running Turtle Data and Interpreter, reinsert the CHR$(31). Then, to run the whole package, just load and run the Boot program.

Turtle Commands

	The Interpreter recognizes 30 commands, some of which can be abbreviated. In addition, the CLR/HOME key will clear the text portion of the screen and home the cursor (regardless of whether the SHIFT key is pressed). Pressing the f1 function key will change the border color; f3 handles the text-background color. In addition, trying to move from the text window into the hires screen will be treated as a CLR/HOME.

The commands are as follows:

FORWARD x (can be abbreviated as FD) - moves the turtle a distance of x in the direction it is pointing. The value of x must be greater than zero. The turtle will normally leave a trail as it moves (see PENUP, PENDOWN, PENDRAW, and PENERASE). You cannot leave the screen.

RIGHT x (RT), LEFT x (LT) - turns the turtle right (clockwise) or left (counterclockwise) x degrees (x is at least zero). Because there are only eight turtle sprites, the turtle will not always seem to be pointing in exactly the direction it should, but it will still draw and move properly.

SETHEADING x (SETH), PRINTHEADING - Setting the heading to x will turn the turtle without changing its position. Headings range from 0 to 360. Straight up is 0 degrees, and the values increase clockwise. PRINTHEADING returns the current value of the turtle's heading.

SETPOSITION x y (SETP), PRINTPOSITION - Setting the position to (x,y) moves the turtle without changing its heading. The value of x should be between -159 and 160, and y values range from -106 to 106. Note that the range of y will change if you change the "crunch factor" (see "Crunching the Screen"). The turtle starts at (0,0), the center of the screen. PRINTPOSITION returns (x,y).

PENERASE (PE), PENDRAW (PW) - These commands control whether the turtle will leave a trail or erase one. The program starts in draw mode.

PENDOWN (PD), PENUP (PU) - Normally the turtle's pen is down. Penup raises it so the turtle cannot leave or erase a trail. You may still set draw or erase modes, but you will not see any effect until after you have lowered the pen and moved forward.

PENCOLOR x (PC), BACKGROUNDCOLOR x (BC), TURTLECOLOR x (TC) - Each of these changes the color to x, where x is between 0 and 15. The first two will also perform a CLR/HOME. (It's not a bug, it's a feature.) There can only be one pen color on the screen at any time, so executing the PENCOLOR command will recolor all the lines that have already been drawn on the screen. Try a number of combinations of background and pen colors. Because of the hardware problems in displaying isolated pixels on the screen, the same pen color will appear as different hues at different points on the screen. Experiment- you may like the effect, which is known as "artifacting."

SHOWTURTLE (ST), HIDETURTLE (HT) - Hiding the turtle is useful when you want to view a finished design. These commands have no effect on the turtle's color, movement, position, etc.

HOME - moves the turtle to (0,0) and sets the heading to 0 degrees.

CLEAN - erases the hi-res screen. Note that pressing CLR/HOME will not disturb the hi-res drawings.

CLEARSCREEN (CS) - performs a CLEAN and HOME.

Combining Commands

	The Interpreter will accept lines of up to 78 characters, and you may include numerous commands on each line-just be sure to use spaces between commands (no commas or colons). Here's a simple demonstration to animate the turtle:

FORWARD 100 RIGHT 90 FORWARD 100 RIGHT 90 FORWARD 100 RIGHT 90 FORWARD 100

	These commands cause the turtle to draw a square. Because the Interpreter is in BASIC, the turtle won't move at breakneck speed. (If you are extremely ambitious, you could convert the plotting routine to machine language.)

	If you are willing to give up a little more time in interpretive overhead, you can use the powerful REPEAT (RP) command. We can rewrite the commands to draw a square as:

REPEAT 4 [FORWARD 100 RIGHT 90]

	The statements you want to be repeated should be enclosed in square brackets and preceded by REPEAT x, where x is the number of times they should be repeated. REPEATS may be nested to a depth of 255 (although procedure calls will decrease this, as detailed below). For example, try the following commands:

CS REPEAT 8 [REPEAT 4 [FORWARD 100 RIGHT 90] RIGHT 45]

Using Procedures

	The full power of turtle graphics is realized with procedures. A procedure is like a program; it's just a series of commands given a specific name. That name is added to the commands that the interpreter will recognize.

	To make up a new procedure, use the DEFINE command. For example, type DEFINE BOX. You will be prompted with BOX?, after which you should type REPEAT 4 [FORWARD 100 RIGHT 90]. The interpreter will respond with BOX DEFINED. From now on, whenever you type BOX (either from the keyboard or from within another procedure) the commands REPEAT 4 [FORWARD 100 RIGHT 90] will be executed. We could define the design above as 8BOXES: CS REPEAT 8 [BOX RIGHT 45].

	Each time you call a procedure counts as a level of nesting (just as a repeat loop does). One very important warning: Don't allow a procedure to call itself (or to call another procedure that may eventually call the first). This will result in a loop that you will have to break by pressing the STOP key. When you restart the program by typing RUN, you will lose your procedure definitions and any designs on the screen.

	There are a number of commands which facilitate working with procedures. NAMES will print the names of all the current procedures (limit of 255). PRINTPROCEDURE x (PPROC) will print the commands associated with the procedure named x. ERASE x will erase the procedure x, and RENAME x y will change the name of procedure x to y. ERASEALL will erase all the current procedure definitions.

Saving And Loading Procedures

	Procedures may also be saved to and loaded from disk or tape. SAVE x will save all the current procedures (a "workspace") to a file named "x.turtle"; LOAD x will copy the procedures in "x.turtle" into memory. These will be added to those already defined, so you can merge workspaces. Files may be erased from the disk with SCRATCH x, which will erase "x.turtle." While these commands are operating, the screen will seem to go awry; ignore this as it will be restored when the operations are complete.

	QUIT will exit the program, but leave the machine in an unusual state. The screen will still be split, but this may be corrected with RUN/STOP-RESTORE. Since memory is reconfigured, you'll want to return it to its normal state. If you don't want to power off and back on again, type

POKE 2048,0: POKE 44,8: NEW

Crunching The Screen

	Because each brand of TV and computer monitor has a different vertical aspect ratio, you may notice that your squares aren't square, circles look like eggs, etc. If so, type

REPEAT 180 [FORWARD 2 RIGHT 2]

	If your design isn't a circle, take a centimeter ruler and measure the diameter along the x and y axes. (These should be easy to identify; just slide the ruler along the screen until you get the maximum measurements in the horizontal and vertical directions.) Divide the x value by the y value. This is the "crunch factor." Change line 50 of Program 1 to set CR to this value. If you are using a Commodore color monitor, the value I've supplied in the program (.74) is appropriate. Note that changing this value changes the scaling on the y axis. The new limits will be  79/CR.

For Tape Users

	You can modify the package to use a tape drive with the following changes:

1. Change the device numbers in lines 150 and 170 of Program 3 from 8 to 1.
2. Change the word DISK to TAPE in line 80.
3. Delete lines 7000-7100, 25000-25060, and line 1280 in Program 1.
4. Change these lines in Program 1:
23010 GOSUB 5000:IF WD$<>""THEN23018
23014 ER=-1:PRINT"YOU MUST SUPPLY A NAME" :RETURN
23018 OPEN2,1,0,WD$+".TURTLE" 23060 CLOSE2 : RETURN
24010 GOSUB 5000:IF WD$<>""THEN24018
24014 ER=-1:PRINT"YOU MUST SUPPLY A NAME":RETURN
24018 OPEN2,1,1,WD$+".TURTLE" 24040 CLOSE2:RETURN

	Program 3 should be saved first on the tape, followed by Program 2, and then Program 1. When Program 3 is loaded and run, it will then load and run the other two programs. For this autoload feature to work properly, you must save the programs with the names shown in lines 150 and 170- TURTLE GRAPHIC 2 for Program 2 and TURTLE GRAPHIC 1 for Program 1. Alternately, you could change the names in those lines to match the names under which you saved the programs.

	There is one additional requirement for the autoload feature to operate properly. You must leave the PLAY button depressed after Program 3 finishes loading. If you release the button, the PRESS PLAY message will be printed to the screen when Program 2 is loaded, which will prevent the loading of Program 1.

How It Works

	Short of rewriting the Interpreter in machine language, there are still a number of modifications you may wish to make to customize the program. I've included these details to briefly give you an idea of how the package functions.

	Program 3 reconfigures memory to start loading programs at $4000, leaving $0800-$03FF free for turtle sprite data. Only the last 512 locations are used, so you could put additional sprites below them. The LOADs and RUNs are accomplished by printing the appropriate commands on the screen and filling the keyboard buffer with RETURNs.

	Program 2 POKEs in the 512 bytes of sprite data below $0400, and then puts a number of machine language routines in memory beginning at $C000. The first routine is an interrupt-driven split screen routine. It also takes care of checking for fl, f2, CLR/HOME, and keeps text from scrolling onto the hi-res screen. This routine is initialed with SYS 49322. To clean the hi-res screen, use SYS 49295. SYS 49235 will clean under the hi-res screen (1024-1823) and erase the text screen (1824-2023). The hi-res bitmap is stored beginning at 8192.

	Here are the important sections of the Interpreter (Program 1):

	10-170: Initialization. Frequently used variables and constants are created first to improve speed. Here are most of the variables' functions:

PE	-1 = penup, 0 = pendown
DR	-1 = pendraw, 0 = penerase
C	conversion from degrees to radians
SC	screen base
BL	bytes REMARK hi-res screen line 
BB	bytes REMARK hi-res screen block
MX	MSB of sprite x location 
PX	LSB of sprite 0 x location  
PY	sprite 0 y location  
BG	used for sprite x seam  
CR	screen crunch factor 
MA	mask  
BA	base in computer  
Cl-C7	constants used in determining sprite position   
SP	sprite image number (0-7) 
H	heading 
CI	degrees in circle 
XH, XL	x-hi, lo values 
YH, YL	y-hi, lo values 
IX, IY	initial x,y coordinates in FORWARD command 
X,Y	current coordinates 
SS	sprite spacing (45) 
HA	one-half 
FF	used as a mask 
PC	procedure counter 
DH	delta heading 
K, QQ ZZ temporary numeric storage 
T$, ZZ$	temporary string storage 
SE	sprite enable 
PT	sprite 0 pointer 
D	distance traveled 
ER	-1 = error, 0 = ok 
BY	byte to be POKEd 
BI	bit to be POKEd 
RO, CO 	row, column for upper-left corner of sprite  
XS, YS	coordinates for turtle sprite 
WD$	current word 
NU	numeric input value 
PN	procedure number temp 
MD$	disk read/write mode 
NP	number of procedures in disk file

	200-620: The parser routine is the most complicated part of the program. NE keeps track of the nesting level. The command line typed at the keyboard is assigned to ST$(0). This serves as a permanent copy of the command line. ST(0) is an index into this string (how much has been processed). These are copied into IN$ and IN, which is what we actually work from. Commands are read off (and removed) from the left end of IN$ and executed in 1000-1300; IN and ST(0) are constantly updated.

	Whenever a repeat command is found, the nesting level is incremented, the repetition factor is put in RP(NE), and the contents of the loop are put in a new command line, ST$(NE). The parser then executes ST$(NE) as already described. When we reach the end of a command line, we "pop" up by decrementing NE and continuing where we left off in the previous command line. Advanced programmers may recognize this as a stack used to simulate recursion.

	Procedures are implemented in the same way. Whenever a procedure name is encountered, we drop down a nesting level, and treat the procedure's commands as the contents of a repeat loop with a repetition factor of 1.

	1000-1300: Identifies and executes commands. If you choose to permanently change the name (or abbreviation) of a command, do it here. This section also clears the error flag to 0 (false) before each command. Any command that fails will set the error flag to -1 (true). The parser keeps track of the flag, and aborts all pending commands when the flag is set true. The individual commands all have good diagnostics, and you may assume that your commands have been successfully executed if no message to the contrary is printed.

	2000-8000: These subroutines are used by the Interpreter in executing various commands.

	9000-22000: Each of these subroutines corresponds to a single command; consulting the variable list should help clarify them.

Sample Designs

	Here are some simple designs to get you started:

RECTANGLE: RP 2 [FD 80 RT 90 FD 30 RT 90]
HEXAGON: RP 6 [FD 100 RT 60]
PENTAGON: RP 5 [FD 100 LT 72]
PENTAGRAM: RP 5[FD 161.8 LT 144] 
TWOPENTAS: SETP -60 -80 SETH 90 PENTAGON LT 36 PENTAGRAM
ARROW: RECTANGLE LT 90 FD 15 LT 135 RP 2 [FD 42.4 LT 90] LT 45 FD 15 PE FD 28 PW 
HONEYCOMB: SETP -30 30 SETH 330 RP 6 [RP 6 [FD RT 60] RT 120 PU FD 25 LT 60 PD]

Above article captured by OCR with OmniPage SE

----------------------------------------------------------------------------

COMPUTE!'s Gazette October 1984 Issue 16 Vol. 2, No. 10 pages 167-171:
Turtle Graphics Interpreter
(Article on page 90.)

BEFORE TYPING...
Before typing in programs, please refer to "How To Type COMPUTE!'s Gazette Programs," "A Beginner's Guide To Typing In Programs," and "The Automatic Proofreader" that appear before the Program Listings.

Program 1: The Interpreter
{Save last on tape. Save as "TURTLE GRAPHIC 1"}

10 REM TURTLE GRAPHICS INTERPRETER
30 IF PEEK(49152)<>173 THEN PRINT CHR$(150) "TURTLE DATA DID NOT LOAD": END
40 X=0: Y=0: IX=0: IY=0: D=0: NU=0: BY=0: BI=0: XH=160: XL=-159: C=/180
50 CR=.74: YH=INT(79/CR): YL=-YH: BA=2: BB=8: BL=320: SC=8192: PE=0: DR=-1
60 MA=7: H=0: PX=53248: BB=8: BL=320: SC=8192: PE=0: DR=-1: MA=7: H=0: PX=53248
70 PY=53249: BG=256: RO=0: CO=0: XS=0: YS=0: SP=0: PT=2040: SE=53269: HA=.5
80 C1=12: C2=40: C3=50: C4=28: C5=24: C6=3: C7=5: CI=360: MX=53264: PC=0
90 FF=255: SS=45: SB=56: YM=79
100 DIM ST$(255),ST(255),RP(255),PR$(255),PN$(255)
110 DEF FNR(X)=INT((X+.005)*100)/100
120 REM INITIALIZE SCREEN AND TURTLE
130 GOSUB 3000: POKE 2, 110: POKE 53277, 0: POKE 53271, 0: POKE 53287,0
140 SYS 49295: SYS 49235: SYS 49322: POKE SE, 1: POKE 53280,2: POKE53281,11
150 PRINT CHR$(129) "TURTLE GRAPHICS INTERPRETER"
170 PRINT CHR$(30)
200 REM MAIN LOOP - GET A LINE OF COMMANDS AND PROCESS IT
210 ST$(0)="": INPUT ST$(0)
220 NE=0: ST(0)=0: RP(0)=0: ER=0
230 IF ST$(0)="" THEN 210
240 REM COPY UNEXECUTED PART OF CURRENT COMMAND STRING (NESTING LEVEL = NE)
250 REM INTO IN$ TO BE PROCESSED
260 IN$=RIGHT$(ST$(NE), LEN(ST$(NE))-ST(NE)): IN=0
270 GOSUB 5000  FILL WD$ WITH NEXT WORD FROM IN$
280 IF WD$<>"" THEN 350
290 REM IN$ IS EMPTY; WE ARE DONE WITH ALL COMMANDS IF NESTING LEVEL IS 0
300 IF NE=0 THEN 200
310 REM WE HAVE COMPLETED A REPETITION OF THE CURRENT COMMAND STRING ST$(NE)
320 REM IF NEEDED, REPEAT.  ELSE, POP NESTING LEVEL
330 RP(NE)=RP(NE)-1: IF RP(NE)>0 THEN ST(NE)=0: GOTO 240
340 NE=NE-1: GOTO 240
350 IF (WD$="REPEAT")OR(WD$="RP") THEN 440
360 REM CHECK IF COMMAND IS A PROCEDURE NAME
370 GOSUB 6000: IF PN=0 THEN 410
380 REM STUFF IN$ WITH PROC STRING AS IF IT WERE A REPEAT LOOP
390 IN$= "[" + PR$(PN) + "]" + RIGHT$(IN$, LEN(IN$)-IN): IN=0: NU=1
400 ST(NE)=ST(NE)-LEN(PR$(PN))-2: GOTO 480
410 REM IDENTIFY AND EXECUTE WD$ AS A COMMAND
420 GOSUB 1000: IF ER THEN 200
430 GOTO 270: REM WE ARE DONE CURRENT COMMAND
440 REM GET REPETITION FACTOR FOR REPEAT LOOP
450 GOSUB 4000: IN$=RIGHT$(IN$, LEN(IN$)-IN): IN=0
460 IF (NOT ER)AND(NU>0)AND(INT(NU)=NU) THEN 480
470 PRINT "I CAN'T REPEAT SOMETHING " WD$ " TIMES" :IN$="": GOTO 200
480 REM PUSH THE COMMAND STRING STACK (INCREMENT NESTING LEVEL)
490 NE=NE+1: IF NE=256 THEN PRINT "NESTING TOO DEEP": GOTO 200
495 RP(NE)=NU: ST(NE)=1: K=0
500 REM FILL ST$(NE) WITH CONTENTS OF REPEAT BRACKETS
510 ST$(NE)="": QQ=0: K=0
520 T$=MID$(IN$, ST(NE), 1)
530 IF T$="]" THEN K=K-1
540 IF K>0 THEN ST$(NE)=ST$(NE)+T$
550 IF T$="[" THEN K=K+1: QQ=-1
560 IF K<=0 THEN 600
570 ST(NE)=ST(NE)+1
580 IF ST(NE)<=LEN(IN$) THEN 520
590 PRINT "MISMATCHED BRACKETS IN REPEAT": IN$="": GOTO 200
600 IF (K<0) OR ((K=0)AND(NOTQQ)) THEN 590
610 ST(NE-1)=ST(NE)+ST(NE-1): ST(NE)=0
620 GOTO 240: REM EXECUTE THE NEW COMMAND STRING
1000 REM IDENTIFY AND EXECUTE COMMAND
1005 ER=0
1010 IF (WD$="FORWARD")OR(WD$="FD") THEN GOSUB 9000: RETURN
1020 IF (WD$="RIGHT")OR(WD$="RT") THEN GOSUB 10000: RETURN
1030 IF (WD$="LEFT")OR(WD$="LT") THEN GOSUB 11000: RETURN
1040 IF (WD$="PENUP")OR(WD$="PU") THEN PE=-1: RETURN
1050 IF (WD$="PENDOWN")OR(WD$="PD") THEN PE=0: RETURN
1060 IF WD$="HOME" THEN GOSUB 12000: RETURN
1070 IF WD$="CLEAN" THEN SYS 49295: RETURN
1080 IF (WD$="CLEARSCREEN")OR(WD$="CS") THEN GOSUB 12000: SYS 49295: RETURN
1090 IF (WD$="SETHEADING")OR(WD$="SETH") THEN GOSUB 13000: RETURN
1100 IF (WD$="SETPOSITION")OR(WD$="SETP") THEN GOSUB 14000: RETURN
1110 IF (WD$="PENERASE")OR(WD$="PE") THEN DR=0: RETURN
1120 IF (WD$="PENDRAW")OR(WD$="PW") THEN DR=-1: RETURN
1130 IF (WD$="ST")OR(WD$="SHOWTURTLE") THEN POKE SE, 1: RETURN
1140 IF (WD$="HIDETURTLE")OR(WD$="HT") THEN POKE SE, 0: RETURN
1150 IF (WD$="PENCOLOR")OR(WD$="PC") THEN GOSUB 15000: RETURN
1160 IF (WD$="BACKGROUNDCOLOR")OR(WD$="BC") THEN GOSUB 16000: RETURN
1170 IF (WD$="TURTLECOLOR")OR(WD$="TC") THEN GOSUB 17000: RETURN
1180 IF WD$="PRINTHEADING" THEN PRINT FNR(H): RETURN
1190 IF WD$="PRINTPOSITION" THEN PRINT "(" FNR(X) "," FNR(Y) ")": RETURN
1200 IF WD$="DEFINE" THEN GOSUB 18000: RETURN
1210 IF WD$="NAMES" THEN GOSUB 19000: RETURN
1220 IF (WD$="PRINTPROCEDURE")OR(WD$="PPROC") THEN GOSUB 20000: RETURN
1230 IF WD$="ERASE" THEN GOSUB 21000: RETURN
1240 IF WD$="ERASEALL" THEN PC=0: PRINT "ALL PROCEDURES ERASED": RETURN
1250 IF WD$="RENAME" THEN GOSUB 22000: RETURN
1260 IF WD$="LOAD" THEN GOSUB 23000: RETURN
1270 IF WD$="SAVE" THEN GOSUB 24000: RETURN
1280 IF WD$="SCRATCH" THEN GOSUB 25000: RETURN
1290 IF WD$="QUIT" THEN PRINT "BYE": END
1300 ER=-1: PRINT "I DON'T UNDERSTAND " WD$: RETURN
2000 REM MOVE TURTLE
2010 RO=YM-(Y*CR): CO=X-XL
2020 IF (SP/BA)=INT(SP/BA) THEN XS=CO+C1: YS=RO+C2: GOTO 2200
2030 XS=CO: IF SP>C6 THEN XS=XS+C5
2050 IF (SP=C6)OR(SP=C7) THEN YS=RO+C4: GOTO 2200
2060 YS=RO+C3
2200 IF XS<BG THEN POKE PX, XS: POKE MX, 0: GOTO 2220
2210 POKE PX, XS-BG: POKE MX, 1
2220 POKE PY, YS
2230 RETURN
3000 REM CHANGE HEADING
3010 H=H+DH
3020 IF H>=CI THEN H=H-CI: GOTO 3020
3030 IF H<0 THEN H=H+CI: GOTO 3030
3040 SP=(INT(H/SS+HA)) AND MA:
3050 QQ=PEEK(SE): POKE SE, 0: POKE PT, SB+SP: GOSUB 2000
3065 POKE SE, QQ
3070 RETURN
4000 REM NUMERIC INPUT
4010 REM GETS NEXT WORD FROM IN$ AS A NUMBER (NU).  CHECKS FOR ERROR
4020 GOSUB 5000: ER=0: NU=0: IF WD$="" THEN ER=-1: RETURN
4030 FOR K= 1 TO LEN(WD$): T$=MID$(WD$, K, 1)
4040 IF ((T$<"0")OR(T$>"9")) AND (T$<>"-")AND(T$<>"+")AND(T$<>".") THEN ER=-1
4050 NEXT: NU=VAL(WD$): RETURN
5000 REM FILL WD$ WITH NEXT WORD FROM IN$
5010 WD$="": IF IN$="" THEN 5070
5020 IN$=RIGHT$(IN$, LEN(IN$)-IN): IN=0
5030 ST(NE)=ST(NE)+1: IN=IN+1
5040 IF IN>LEN(IN$) THEN IN=IN-1: ST(NE)=ST(NE)-1: GOTO 5070
5050 IF MID$(IN$, IN, 1)<>" " THEN WD$=WD$ + MID$(IN$, IN, 1): GOTO 5030
5060 IF (WD$="")AND(IN$<>"") THEN 5020
5070 RETURN
6000 REM IDENTIFY PROCEDURE
6010 REM RETURNS INDEX (PN) OF PROCNAME IN WD$; 0 IF NOT A PROCNAME
6020 K=0: PN=0
6030 K=K+1: IF K>PC THEN RETURN
6040 IF WD$<>PN$(K) THEN 6030
6050 PN=K: RETURN
7000 REM OPEN DISK FILE
7010 ER=0: GOSUB 5000: IF WD$<>"" THEN 7030
7020 ER=-1: PRINT "YOU MUST SUPPLY A FILENAME": RETURN
7030 OPEN 15,8,15
7040 OPEN 2,8,2, "0:" + WD$ + ".TURTLE,S," + MD$: INPUT#15, QQ,T$,K,ZZ
7050 IF (QQ=26)AND(MD$="W") THEN PRINT "WRITE-PROTECTED DISK": ER=-1: RETURN
7060 IF (QQ=67)AND(MD$="W")AND(K=36) THEN PRINT "DISK IS FULL.": ER=-1: RETURN
7070 IF (QQ=63)AND(MD$="W") THEN PRINT "FILENAME IS USED": ER=-1: RETURN
7080 IF (QQ=62)AND(MD$="R") THEN PRINT "NO SUCH FILE ON DISK": ER=-1: RETURN
7090 IF QQ>19 THEN PRINT "I'M HAVING TROUBLE WITH THE DISK": ER=-1
7100 RETURN
8000 REM GET VALID COLOR NUMBER
8010 GOSUB 4000 NUMERIC INPUT
8020 IF ER OR (NU>15)OR(NU<0) THEN ER=-1
8030 RETURN
9000 REM FORWARD COMMAND
9010 GOSUB 4000: IF ER OR (NU<=0) THEN PRINT "I CAN'T GO FORWARD " WD$: RETURN
9020 IX=X: IY=Y: FOR D= 0 TO NU: X=FNR(D*SIN(H*C)+IX): Y=FNR(D*COS(H*C)+IY)
9030 IF X>XH THEN X=XH
9040 IF X<XL THEN X=XL
9050 IF Y>YH THEN Y=YH
9060 IF Y<YL THEN Y=YL
9070 IF PE THEN 9120
9080 BY=SC + BL*INT((YM-(Y*CR))/BB) +BB*INT((X-XL)/BB) + ((YM-(Y*CR)) AND MA)
9090 BI=MA - ((X-XL) AND MA)
9100 IF DR THEN POKE BY, PEEK(BY) OR BA^BI: GOTO 9120
9110 POKE BY, PEEK(BY) AND (FF-BA^BI)
9120 GOSUB 2000: NEXT: RETURN
10000 REM RIGHT COMMAND
10010 GOSUB 4000: IF ER OR (NU<0) THEN PRINT "I CAN'T TURN RIGHT " WD$: RETURN
10020 DH=NU: GOSUB 3000: RETURN
11000 REM LEFT COMMAND
11010 GOSUB 4000: IF ER OR (NU<0) THEN PRINT "I CAN'T GO LEFT " WD$: RETURN
11020 DH=-NU: GOSUB 3000: RETURN
12000 REM HOME COMMAND
12010 X=0: Y=0: H=0: DH=0: GOSUB 3000: RETURN
13000 REM SETHEADING COMMAND
13010 GOSUB 4000: IF (NOT ER)AND(H<=360) THEN 13030
13020 ER=-1: PRINT "I CAN'T SET A HEADING OF " WD$: RETURN
13030 H=NU: DH=0: GOSUB 3000: RETURN
14000 REM SETPOSITION COMMAND
14010 GOSUB 4000: IF (NOT ER)AND(NU>=XL)AND(NU<=XH) THEN 14030
14020 ER=-1: PRINT "I CAN'T SET AN X-VALUE OF "WD$: RETURN
14030 QQ=NU: GOSUB 4000
14040 IF (NOT ER)AND(NU>=YL)AND(NU<=YH) THEN X=QQ: Y=NU: GOSUB 2000: RETURN
14050 ER=-1: PRINT "I CAN'T SET A Y-VALUE OF "WD$: RETURN
15000 REM PENCOLOR COMMAND
15010 GOSUB 8000: IF ER THEN PRINT WD$ " IS NOT A PENCOLOR": RETURN
15020 POKE 2, (PEEK(2)AND15)+16*NU: SYS 49235: RETURN
16000 REM BACKGROUNDCOLOR COMMAND
16010 GOSUB 8000: IF ER THEN PRINT WD$ " IS NOT A BACKGROUNDCOLOR": RETURN
16020 POKE 2, (PEEK(2)AND240)+NU: SYS 49235: RETURN
17000 REM TURTLECOLOR COMMAND
17020 GOSUB 8000: IF ER THEN PRINT WD$ " IS NOT A TURLTECOLOR": RETURN
17030 POKE 53287, NU: RETURN
18000 REM DEFINE NEW PROCEDURE
18010 GOSUB 5000:IF WD$<>"" THEN 18030
18020 PRINT "I NEED A PROCEDURE NAME": ER=-1: RETURN
18030 IF PC=FF THEN PRINT"I CAN'T REMEMBER ANY MORE PROCEDURES": ER=-1: RETURN
18040 GOSUB 6000: IF PN<>0 THEN PRINT WD$ " ALREADY EXISTS": ER=-1: RETURN
18050 PC=PC+1: PN$(PC)=WD$: PRINT WD$;: INPUT PR$(PC)
18060 PRINT WD$ " IS NOW DEFINED": RETURN
19000 REM PRINTNAMES COMMAND
19010 PRINT "NUMBER OF PROCEDURES:" PC
19020 IF PC=0 THEN RETURN
19030 FOR K= 1 TO PC: PRINT PN$(K): NEXT: RETURN
20000 REM PRINTPROCEDURE COMMAND
20010 GOSUB 5000: IF WD$<>"" THEN 20030
20020 ER=-1: PRINT "I NEED A PROCEDURE NAME": RETURN
20030 GOSUB 6000: IF PN<>0 THEN PRINT PR$(PN): RETURN
20040 ER=-1: PRINT "THERE IS NO PROCEDURE " WD$: RETURN
21000 REM ERASE COMMAND
21010 GOSUB 5000: IF WD$<>"" THEN 21030
21020 ER=-1: PRINT "I NEED A PROCEDURE NAME": RETURN
21030 GOSUB6000: IF PN<>0 THEN 21050
21040 ER=-1: PRINT "THERE IS NO PROCEDURE " WD$: RETURN
21050 PR$(PN)=PR$(PC): PN$(PN)=PN$(PC): PC=PC-1:PRINT WD$ " IS ERASED": RETURN
22000 REM RENAME COMMAND
22010 GOSUB 5000: IF WD$<>"" THEN 22030
22020 ER=-1: PRINT "I NEED TO KNOW THE OLD NAME": RETURN
22030 GOSUB 6000
22040 IF PN=0 THEN PRINT "PROCEDURE " WD$ " DOESN'T EXIST": ER=-1: RETURN
22050 QQ=PN
22060 GOSUB 5000: IF WD$<>"" THEN22080
22070 PRINT "I NEED TO KNOW THE NEW NAME": ER=-1: RETURN
22080 GOSUB 6000
22090 IF PN<>0 THEN PRINT "YOU HAVE ALREADY USED THAT NAME": ER=-1: RETURN
22100 PN$(QQ)=WD$: PRINT "RENAMING OK": RETURN
23000 REM LOAD COMMAND
23010 MD$="R": GOSUB 7000: IF ER THEN 23060
23020 INPUT#2, NP
23030 IF (NP+PC)>FF THEN PRINT "TOO MANY PROCEDURES": ER=-1: GOTO 23060
23040 FOR K= 1 TO NP: INPUT#2, PN$(PC+K), PR$(PC+K): NEXT: PC=PC+NP
23050 PRINT NP "PROCEDURES LOADED"
23060 CLOSE 2: CLOSE 15: RETURN
24000 REM SAVE COMMAND
24010 MD$="W": GOSUB 7000: IF ER THEN 24040
24020 PRINT#2, PC: FOR K= 1 TO PC: PRINT#2, PN$(K): PRINT#2, PR$(K): NEXT
24030 PRINT PC "PROCEDURES SAVED"
24040 CLOSE 2: CLOSE 15: RETURN
25000 REM SCRATCHFILE COMMAND
25010 ER=0: GOSUB 5000: IF WD$<>"" THEN 25030
25020 PRINT "YOU MUST SUPPLY A FILENAME": ER=-1: RETURN
25030 OPEN 15,8,15
25040 PRINT#15, "S0:" + WD$ + ".TURTLE": INPUT#15, QQ,T$,ZZ,ZZ
25050 IF (QQ>19)AND(QQ<>62) THEN PRINT "I'M HAVING TROUBLE WITH THE DISK":ER=-1
25060 CLOSE 15: RETURN

Program 2: Turtle Data
{Save second on tape. Save as "TURTLE GRAPHIC 2"}

100 REM TURTLE DATA, FOR USE WITH TURTLE GRAPHICS INTERPRETER. USE TURTLE BOOT
110 REM TO LOAD.
120 FOR K= 3584 TO 4095: READ J: POKE K, J: NEXT
200 REM HEADING 0
210 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,0,0
220 DATA 60,0,0,126,0,0,255,0,1,255,128,3,255,192,7,255,224,15,255,240,31,255
230 DATA 248,0,0,0,0,0,0,0
240 REM HEADING 45
250 DATA 0,63,255,0,31,255,0,15,255,0,7,255,0,3,255,0,1,255,0,0,127,0,0,63,0
260 DATA 0,31,0,0,7,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
270 DATA 0,0,0,0,0
280 REM HEADING 90
290 DATA 0,0,0,0,0,0,224,0,0,240,0,0,248,0,0,254,0,0,255,0,0,255,128,0,255,192
300 DATA 0,255,224,0,255,224,0,255,192,0,255,128,0,255,0,0,254,0,0,248,0,0,240
310 DATA 0,0,224,0,0,0,0,0,0,0,0,0,0,0,0
320 REM HEADING 135
330 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0
340 DATA 7,0,0,31,0,0,63,0,0,127,0,1,255,0,3,255,0,7,255,0,15,255,0,31,255,0
350 DATA 63,255,0
360 REM HEADING 180
370 DATA 0,0,0,31,255,248,15,255,240,7,255,224,3,255,192,1,255,128,0,255,0,0
380 DATA 126,0,0,60,0,0,24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
390 DATA 0,0,0,0,0,0,0,0,0
400 REM HEADING 235
410 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,0
420 DATA 224,0,0,248,0,0,252,0,0,254,0,0,255,128,0,255,192,0,255,224,0,255,240
430 DATA 0,255,248,0,255,252,0,0
440 REM HEADING 270
450 DATA 0,0,0,0,0,0,0,0,14,0,0,30,0,0,62,0,0,254,0,1,254,0,3,254,0,7,254,0,15
460 DATA 254,0,15,254,0,7,254,0,3,254,0,1,254,0,0,254,0,0,62,0,0,30,0,0,14,0,0
470 DATA 0,0,0,0,0,0,0,0
480 REM HEADING 315
490 DATA 255,252,0,255,248,0,255,240,0,255,224,0,255,192,0,255,128,0,254,0,0
500 DATA 252,0,0,248,0,0,224,0,0,192,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
510 DATA 0,0,0,0,0,0,0,0,0,0,0,0
600 REM SPLITSCREEN ROUTINE
610 FOR K= 49152 TO 49349: READ J: POKE K, J: NEXT
620 DATA 173,25,208,141,25,208,41,1,208,3,76,188,254,173,18,208,16,18,169,21
630 DATA 141,24,208,169,27,141,17,208,169,1,141,18,208,76,188,254,169,25,141
640 DATA 24,208,169,59,141,17,208,169,209,141,18,208,24,165,214,105,236,16
650 DATA 3,32,83,192,165,197,201,4,208,3,238,32,208,201,5,208,3,238,33,208,32
660 DATA 132,192,76,49,234,165,2,162,0,157,0,4,232,208,250,157,0,5,232,208,250
670 DATA 157,0,6,232,208,250,162,31,157,0,7,202,16,250,169,32,162,201,157,31,7
680 DATA 202,208,250,24,160,0,162,20,32,240,255,96,162,39,165,2,157,248,6,202
690 DATA 16,250,96,24,169,32,133,252,169,0,133,251,168,145,251,200,208,251,230
700 DATA 252,165,252,201,64,208,1,96,152,240,239,120,169,127,141,13,220,169,1
710 DATA 141,26,208,169,192,141,21,3,169,0,141,20,3,169,1,141,18,208,88,96

Program 3: Turtle Boot 
{Save first on tape. Save as anything you like.}

10 REM TURTLE BOOT
20 POKE 53281, 6
30 PRINT CHR$(147); CHR$(154) TAB(10) "TURTLE GRAPHICS BOOT": PRINT: PRINT
40 PRINT "THIS PROGRAM WILL LOAD AND RUN THE"
50 PRINT "TURTLE DATA AND INTERPRETER PROGRAMS.": PRINT
60 PRINT "WHILE THEY ARE LOADING THE SCREEN WILL"
70 PRINT "BLANK.": PRINT
80 PRINT "DO NOT REMOVE THE DISK UNTIL THE"
90 PRINT "INTERPRETER PROMPTS YOU FOR YOUR FIRST"
100 PRINT "COMMAND.": PRINT: PRINT: POKE 198, 0
110 PRINT "PRESS " CHR$(18) "SPACE" CHR$(146) " WHEN READY"
120 GETA$: IF A$="" THEN 120
130 Q$=CHR$(34): D$=CHR$(17)
140 PRINT CHR$(147); CHR$(31); D$; D$; D$ "POKE 16384, 0: POKE 44, 64: NEW"
150 PRINT D$; D$ "LOAD" Q$ "TURTLE GRAPHIC 2" Q$ ",8"
160 PRINT D$; D$; D$; D$; D$ "RUN"
170 PRINT D$; D$ "LOAD" Q$ "TURTLE GRAPHIC 1" Q$ ",8"
180 PRINT D$; D$; D$; D$; D$ "RUN" CHR$(19)
190 FOR K= 1 TO 7: POKE 630+K, 13: NEXT: POKE 198, 7
 
Above program listings printed from COMPUTE!'s Gazette Disk October 1984 using WinVice 1.2. Miss-spelling of TURTLE in line 17020 is as originally published. Can be converted from text file to a PRG file using TOK64. Use Star Commander or your favorite transfer application to put the PRG files into a D64 image for use with emulators or transfer onto a real floppy. Both programs are free and available on the internet.

NOTES and PRIMITIVES:
This version of Logo is written almost entirely in BASIC and it is possible to alter, improve, and expand the program. It is quite slow and runs considerably better on an emulator in high-speed or warp mode. It could also be adapted to take advantage of the Commodore 128's powerful drawing commands. The article includes instructions for adapting this program to work with a tape drive. This version of Logo is in NOWRAP mode, also known as FENCEd mode, which prevents the turtle from leaving the screen. Instead the turtle will trail along the edge of the screen. Also, as computers of the 80's used TVs and monitor that did not have square pixels, drawing squares and circles would be stretched. In line 50 of "TURTLE GRAPHIC 1" you will see the variable CR=.74. CR "crunches" the scaling on the Y axis, creating correctly proportioned squares and circles on most TVs and monitors. However, on emulators, it reverses the effect, enlongating the shapes. Changing this value to 1 should solve the problem.

Command / Short Form / Examples with Inputs
Explanation or Notes

--------
Turtle Commands and Primitives:

FORWARD		FD	FORWARD 50

RIGHT			RT	RIGHT 90

LEFT			LT	LEFT 90

REPEAT		RP	REPEAT 4 [FD 50 RT 90]

PENUP			PU	-
stops turtle from drawing

PENDOWN		PD	-
starts turtle drawing (default)

PENERASE		PE	-
turtle erases lines and dots if PENDOWN

PENDRAW		PW	-
turtle draws if PENDOWN (returns to current PENCOLOR) (default)

PENCOLOR		PC	PENCOLOR 0
				0 = black
				1 = white
				2 = red
				3 = cyan
				4 = purple
				5 = green
				6 = blue
				7 = yellow
				8 = orange
				9 = brown
				10 = light red
				11 = dark gray (gray 1)
				12 = medium gray (gray 2)
				13 = light green
				14 = light blue
				15 = light gray (gray 3)
pencolor changes the color of the entire picture, thereby avoiding Commodore color conflicts (where one color bleeds into another)

BACKGROUNDCOLOR	BC	BACKGROUNDCOLOR 0
				see color list above

TURTLECOLOR		TC	TURTLECOLOR 0
				see color list above

SHOWTURTLE		ST	-
(default)

HIDETURTLE		HT	-

CLEARSCREEN		CS	-
sets turtle position to 0,0 heading 0 (HOME) & clears graphics screen

HOME			-	-
sets PENUP mode, sends turtle to position 0,0 heading 0, then returns to whichever mode turtle was in before

CLEAN			-	-
clears graphics screen but does not send turtle HOME

SETHEADING		SETH	SETHEADING 0
				SETHEADING -90
sets turtle's heading

SETPOSITION		SETP	SETPOSITION 0 0
				SETPOSITION -50 -50
sets PENUP mode, sets turtle's X and Y coordinates, then returns to whichever mode turtle was in before

PRINTHEADING	-	-
prints turtle's heading

PRINTPOSITION	-	-
prints turtle's X and Y coordinates

QUIT			-	-
quits TGI but does not reset computer or erase program or procedures in memory. CONT will continue from where you were. RUN will clear memory and restart TGI for another user.

-----------
Editing Commands:

DEFINE		-	DEFINE PROCEDURENAME
enters input mode, displaying procedure name folled by a question mark and a space, allowing two lines of procedure to be input; 80 characters less the length of procedure name and less the question mark and space following it. Interestingly, it allows redefining of preset commands and primitives

ERASE			-	ERASE PROCEDURENAME
clears memory of specific procedures

ERASEALL		-	-
clears memory of all procedures

NAMES			-	-
lists names of all procedures in memory, will overrun text area

PRINTPROCEDURE	PPROC	PRINTPROCEDURE PROCEDURENAME
lists the contents of specific procedure, will overrun text area

RENAME		-	RENAME OLDPROCNAME NEWPROCNAME
renames a procedure

-----------
File Commands:

LOAD			-	LOAD FILENAME
				LOAD "FILENAME
				LOAD "FILENAME"
reads in a set of procedures from a file on disk, quotes MUST be consistent; if SAVEd with single or double quotes, can only be LOADed with single or double quotes

SAVE			-	SAVE FILENAME
				SAVE "FILENAME
				SAVE "FILENAME"
saves a set of procedures in a file on disk, quotes MUST be consistent; if SAVEd with single or double quotes, can only be LOADed or SCRATCHed with single or double quotes

SCRATCH		-	SCRATCH FILENAME
				SCRATCH "FILENAME
				SCRATCH "FILENAME"
erases a file on disk, quotes MUST be consistent; if SAVEd with single or double quotes, can only be SCRATCHed with single or double quotes

------------
Key Commands:

CLR/HOME	clears the text portion of the screen and homes the cursor (regardless of whether the SHIFT key is pressed)

f1 		changes the border color

f3		changes the text-background color

CRSR keys	trying to move from the text window into the hires screen will be 
treated as a CLR/HOME

------------
Note: CTRL-G on most Logo's will break the turtle out of a loop. In Turtle Graphics Interpreter, this option doesn't exist. However it can be replicated by pressing RUN/STOP and typing GOTO 150. This will not clear the memory and all your procedures will still exist. If you hit RUN/STOP and RESTORE, type GOTO 120 to bring back the drawing screen (the screen will be CLEANed, and the turtle will not be HOMEd.) Again, your procedures will be intact. It is recommended that you save your procedures and restart the program, as it can become unstable.
