Classic Computer Magazine Archive ANTIC VOL. 1, NO. 4 / OCTOBER 1982

Forth Factory
Turtle Graphics, Part 2

By Gordon Smith

This is the second of two articles on implementing a Turtle Graphics system in Forth. The first one appeared in ANTIC issue #3. It discussed Turtle Graphics in general, explained why Forth is a particularly hospitable environment for a Turtle Graphics system, and gave nine screens worth of "foundation" words.

With this artcle are 17 more screens of pns-Forth source code which complete the system. I'll give an overview of the system's features; a glossary of Turtle commands, and give a few suggestions on using the system.

The Inhabitants And Language Of Turtleland

Four independent turtles live in Turtleland. Multiple turtles open up interesting possibilities, like having turtles chase each other. With four turtles, each can draw in a different color (there are only four colors possible at one time). If you want a different number, you can change the value of the constant #TURTLES on screen 2 before loading. One turtle at a time can be designated the "active turtle" with the SET ACTIVE command. She is the one who will respond when we type a command like "10 DRAW."

Each turtle carries a pen. The active turtle's pen can be lowered with the PENDOWN command, leaving a trail when she moves, or raised with the PENUP command. The more general SET PEN command can be used to do either.

The SET INK command fills the active turtle's pen wtih various colors of ink, depending on the Graphics Mode used. (Modes 3 through 8 can be selected with the SET MODE command.) In all modes, ink of type 0 is erasing ink. It is black, the same color as the background, except in Mode 8 when it is light blue. The command, ERASING, is the same as 0 SET INK. Both choose erasing ink. In Modes 3, 5, and 7, there is also ink of type 1 (gold), type 2 (light green), and type 3 (dark blue). In Modes 4, 6, and 8, types 2 and 3 are not available. The number of ink types is determined by the color video capabilities of the CTIA or GTIA chip. The colors are established by the Operating System when it opens the screen. You can use pns-Forth SETCOLOR word to- change them.

Each turtle has a position and a heading. The heading is the number of degrees clockwise from the vertical that she is facing. The active turtle's heading can be changed directly to any value with SET HEADING, also known as TURNTO, or it can be changed incrementally by the commands RIGHT (or TURN) and LEFT.

The system keeps track of each turtle's position with X and Y coordinates. These are not the same as the screen column and row numbers. The SET MODE command arranges these coordinates so that the turtle's home al X=0 and Y=0 is the center of the screen, and so that there are one hundred X or Y units per pixel. This means that if a turtle is at X = 1000 and Y = 500 she will appear ten pixels to thl right and five pixels up from the center. You can arrange the coordinates differently if you wish.

The active turtle's coordinates can be individually or jointly set with the commands SET X, SET Y, or SET POSITION (also known as GOTO). They cause the turtle to leave a track only if her pen is down. MOVETO can be used to temporarily raise the pen, or DRAWTO to lower it, before changing position. The pen is restored to its original state after the change.

The most interesting way to move the active turtle is with FORWARD, BACKWARD, DRAW, and MOVE commands. These move her a specified number of steps in whatever direction she is currently heading. FORWARD and BACKWARD draw a line only it the pen is down; DRAW always draws; MOVE never does. Each step normally moves the turtle one pixel, a distance of 100 units in XY coordinates, unless you use the SET SIZE command to alter the step size. By changing the step size you can use the same word -to draw the same shape in different sizes.

A turtle's heading and her XY coordinates are always integers. The maximum range for X and Y is from -32768 to 32767. If you drive a turtle beyond this range you may see unwanted tracks as she "jumps" to the other edge of Turtleland.

Usually you can't see all of Turtleland on the screen. For example: in Mode 7 the screen displays only the part of Turtleland from X =15900 to X = 15800 and from Y = -7900 to Y = 7800. You can select your own "window" into Turtleland with SET WINDOW command. Any tracks beyond the edges of the window won't be visible. Changing the window will affect the number of X or Y units per pixel. An alternate way to set the window (and the step size) is with the PERPIXEL command.

The reason that the system defaults to 100 units per pixel is to let the turtle sit "between" pixels. If we used a coordinate system as coarse as the screen pixels, then every time we moved a turtle at some angle, her new position would get "rounded" to the nearest pixel. We wouldn't be able to do a series of moves without errors accumulating. Using one hundred XY units per pixel gives us increased precision.

The SET MODE command establishes the whole screen as the "viewport" This means that the view of Turtleland visible through the window will be projected onto all of the screen. You can select any rectangular piece of the screen to be the viewport with the SET VIEWPORT command. When you experiment with this, use the FRAME or NEW commands to draw a frame around the new viewport so you can see where it is.

So far, four commands-MODE, SIZE, WINDOW, and VIEWPORT- relate to Turtleland as a whole, and seven of them-ACTIVE, PEN, INK, HEADING, X, Y, and POSITION- relate to the turtles. It is also possible for you to determine the current value of any of these parameters, by leaving out the word SET or by changing it to SHOW. For example, the command X by itself (i.e., not preceded by SET) leaves the active turtle's current X coordinate on the stack, where it can be used by any word for any purpose. So, the command SHOW X will display some message like "Turtle #1 is at X=300".

The system also has miscellaneous commands like CLEAR for clearing the screen, FRAME for drawing a frame around your picture, and HOME, START, and NEW for starting over. The command BYE leaves Turtleland and returns to pns-Forth.

Of course, all the usual Forth words are still available while you're in Turtleland, in case you need to do arithmetic, comparisons, branching, looping, or whatever. You can use the more compact loop syntax ( . . . ) and ( . . . + ) in place of the structures 0 DO . . . LOOP and 0 DO... + LOOP.

The important command DEFINE . . . AS . . . END allows you to add new words to the turtle's vocabulary. This makes it very easy to change any of my command names that you don't like.

As an interesting example, you might want to

DEFINE HILDA AS 1 SET ACTIVE END DEFINE GILDA AS 2 SET ACTIVE END DEFINE MATILDA AS 3 SET ACTIVE END

so that you can talk to a turtle simply by invoking her name.

Using the SystemW

To start turtle-in ,, just use the SET MODE command. If you want to have Turtleland displayed in Graphics Mode 7, for example, type 7 SET MODE. After this you can immediately move the turtles around with 10 DRAW, 45 TURN, etc. SET MODE initializes the system as follows:

-All four turtles are home at X=0 and Y = 0, with heading 0 degrees.
-They all have their pens down.
-Their pens are filled with various ink types as described under the START command in the glossary. -Turtle #1 is active.
-The window is such that X = 0, Y =0 is in the center of the screen and there are 100 X or Y units per pixel.
-The viewport is the whole screen.

After you get acquainted with the various commands, you'll want to start extending the system by defining your own. Here is an example of a new command:

VALUE STEPS VALUE INCREMENT VALUE ANGLE

DEFINE POLYSPI AS TO ANGLE TO INCREMENT 0 TO STEPS BEGIN STEPS INCREMENT + TO STEPS STEPS FORWARD ANGLE, TURN AGAIN END

POLYSPI can make all sorts of interesting polygonal spirals. It expects to find two numbers on the stack. It stores the top one in ANGLE; this will be how many degrees the turtle will turn between each move. The one below gets stored in INCREMENT; this will be how many more steps the turtle will take each time compared to the previous time. Next STEPS is initialized to 0 and we enter a Forth BEGIN . . . AGAIN loop. The words between BEGIN and AGAIN will be executed indefinitely. (You must press a yellow -console button to stop POLYSPI.) Each time through the loop, STEPS is incremented by INCREMENT, and the turtle takes the number of steps in STEPS and turns the number of degrees in ANGLE. Thus POLYSPI is just an automated sequence of FORWARDs and TURNs. For example, 2 90 POLYSPI is really the same as

2 FORWARD 90 TURN 4 FORWARD 90 TURN 6 FORWARD 90 TURN

and so on.

The three VALUE words POLYSPI uies make it easy to see what's going on. However, another definition of POLYSPI is possible which uses no variables at all:

DEFINE POLYSPI AS
BEGIN 3 PICK + DUP FORWARD OVER TURN AGAIN END

This version keeps everything on the stack, using the Forth words PICK, DUP, and OVER for stack manipulation. You can make a variety of patterns with this one command by changing its two parameters.

Pressing a yellow console button will break out of an indefinite loop of turtle moves. In fact, every time a turtle changes position, the system checks the console buttons and returns to command level if one is depressed. This makes it easy to regain control.

As mentioned in Part I, ten of the words used in my screens are pnsForth words which won't be available (at least not with the same meanings) in other Forth systems. Two of these, 1and TABLE, are common Forth extensions whose high-level definitions are

:1- 1-; and

: TABLE OVER + + @;

The others are highly systemspecific. Four of them-SETUP S, CLOSE S, SPLIT-SCREEN, and GR. -were used in the word GRAPHICS in Part I. Their definitions are quite complex, as these words are part of pns-Forth's interface to the CIO routines in the Operating System. Their joint effect in the word GRAPHICS, however, is quite simple. Any Forth system sold for the ATARI will probably have words for opening the screen for graphics. Simply use whatever your system provides to define your own GRAPHICS, which takes one number from the stack and opens the screen in that mode, with a text window at the bottom.

The last four words specific to pnsForth are CL#, COLOR, PLOT, and DRAWTO. These are used by LINE (in Part I), FRAME, and POSITION. The first two are simple to define; just use

0 VARIABLE CL#

and

: COLOR DUP CL# ! PAD C!;

CL# is a variable which is used to keep track of the color data used to plot a pixel. COLOR takes a number from the stack and stores it both in CL# and at PAD, for later use by PLOT and DRAWTO. The definitions of PLOT and DRAWTO are complicated because these words result in calls to CIO. Again, however, their functions are simple and your system probably provides similar words. Define a PLOT which takes a column and a row number from the stack, moves the screen cursor to that position, and plots a pixel there using whatever byte is at PAD as the color data. Similarly, define a DRAWTO which takes a column and a row number from the stack, and draws a line from the current position of the screen cursor to this specified position, using the byte at PAD as color data.

I believe that all the other words I've used in this system are either standard fig-Forth words or new words that I've defined.

[CODE]

Glossary of Turtle Commands

MODE Commands

SET MODE [ mode --- ] Opens the screen in the Graphics Mode specified by mode, which should be 3-8. Sets up a default viewport, window, and step size by executing WHOILE SCREEN SET VIEWPORT and 100 PER-PIXEL. Draws a frame around the viewport with ink of type 1. Initializes the turtles by executing START.

MODE [--- mode 1 I.eaves the number of the current Graphics Mode on the stack.

SHOW MODE [ --- ] Displays a message indicating the current Graphics Mode.

ACTIVE Commands

SET ACTIVE [ turtle# ---] Makes the turtle whose number is turtle# the active turtle. Future commands will be directed to her.

ACTIVE [--- turtle# ] I.eaves the number of the active turtle on the stack.

SHOW ACTIVE [ --- ] Displays a message indicating the currently active turtle.

PEN Commands

SET PEN [ state --- ] l.owers the active turtle's pen if state is nonzero and raises it if state is zero.

PEN [--- state 1 I.eaves I on the stack if the active turtle's pen is down and 0 if it is up.

SHOW PEN [ --- ] Displays a message indicating whether the active turtle's pen is up or down.

INK Commands

SET INK [ ink# ] Fills the active turtle's pen with ink of type ink# . Type () ink is erasing ink. Types 1, 2, and 3 are colored Typcs 2 alld 3 are not available in rnodes 4, 6, or S.

INK [--- illk# 1 I.eaves on thc stack the type of ink in the active turtle's pen .

SHOW INK [ --- ] Displays a message indicating the type of ink in the active turtle's pen.

HEADING Commands

SET HEADING [ degrees --- ] Makes the active turtle head in the direction specified by degrees . Directions are measured clockwise from the vertical.

HEADING [--- degrees 1 I.eaves the active turtle's headmg on the stack.

SHOW HEADING [ --- ] Displays a message indicating the active turtle's heading.

X Commands

SET X [ x --- ] Changes the active turtle's X coordinate to x . I)raws a line if her pen is down.

X [ x ] leaves the active turtle's X coordinate on the stack.

SHOW X [ --- ] Displays a message indicating the active turtle's X coordinate.

POSITION Commands

SET POSITION [ x y --- ] Changes the active turtle's coordmates to X = x and Y = y . Draws a line if her pen is down.

POSITION [--- x y ] I eaves the activc turtle's X and Y coordimltes on the stack.

SHOW POSITION [ --- ] Displays a message indicating the active turtle's X and Y coordinates.

SIZE Commands

SET SIZE [ distance steps --- ] Sets the step size so that the number of steps given by steps will cover a distance in XY coordinates given by distance

SIZE [--- distallce steps ] I.eaves the current size parameters on the steack.

SHOW SIZE [ --- ] Dispiays a message indicating the current step size.

WINDOW Commands

SET WINDOW [ xmin xmax ymin ymax ---] Sets the window to be the region from X = xmin to X = xmax and from Y = ymin to Y = ymax .

WINDOW [--- xmin xmax ymin ymax ] I.eaves the current window parameters on the stack.

SHOW WINDOW [ --- ] Displays a message indicating the current window.

VIEWPORT Commands

SET VIEWPORT [ left right top bottom --- ] Sets the viewport to extend from screen column left to screen column right and from screen row top to screen row bottom.

WHOLE-SCREEN SET VIEWPORT [ --- ] Sets the viewport to extend from column I to the next to the hlst column and from row :I to the next to the last row.

VIEWPORT [--- left right top bottom ] I.eaves the current viewport parameters on the stack.

SHOW VIEWPORT [ --- ] Displays a message indicating the current viewport.

Y Commands

Similar to X Commands

Other Commands

CLEAR [ --- ] Clears the graphics screen without affecting the turtles.

FRAME [ ink# --- ] Draw a frame ilround the viewport, using ink of type ink#

HOME [ --- ] Moves the active turtle to X = () and Y = () with heading (), without drawing a line, and then lowers her pen .

START [--- ] HOMEs all the turtles first. Then fills their pens with ink. (In mode 3, 5, or 7, the Nth turtle's pen is filled with ink of type N. In mode 2, 4, or 6, turtle's 0's pen is filled with type 0 ink while the pens of turtles I, 2, and 3 are filled with type ] ink, the only colored ink available in these modes.) Finally, makes turtle 1 the active turtle .

NEW [ --- ] Clears the screen, draws a frame with type 1 ink, and initializes the turtles by executing START.

PER-PIXEL [ distance --- ] Sets the window so that the point X = (), Y = 0 is the center of the viewport, and so that the distance in XY coordinates given by distance will be the size of one pixel. Also, sets the step size so that each step is distance units long.

FORWARD [ steps --- ] Moves the active turtle forward the number of steps specified by steps . The movement is in the direction she is currently heading if steps is positive and in the opposite direction if steps is negative. The turtle's heading is unaffected. A line is drawn if her pen is down.

BACKWARD [ steps --- ] Like FORWARD except in the opposite direction.

DRAW [ steps --- ] I owers the active turtle's pen so that a line will definitely be drawn as she moves forward the number of steps given by steps . Then her pen is returned to its prevlous state.

MOVE [ steps --- ] Raises the active turtle's pen so that a line will definitely not be drawn as she moves forward the number of steps given by steps . Then her pen is returned to its previous state.

RIGHT [ degrees --- ] Turns the active turtle the specifiefd number of degrees, to the right if degrees is positive and to the left if negatlve.

LEFT [ degrees --- ] I..ike RIGHT except in the opposite direction.

TURN [ degrees --- ] The same as RIGHT.

GOTO [ x y --- ] The same as SET POSITION.

DRAWTO [ x y --- ] I.owers the active turtle's pen so that a line will definitely be drawn as she moves toX= x andY= y . Then her pen is returned to its previous state.

MOVETO [ x y --- ] Raises the active turtle's pen so that a line will definitely not be drawn as she moves to X= x and Y= y . Then her pen is returned to its previous state.

TURNTO [ degrees --- ] The same as SET HEADING.

PENDOWN [ --- ] I.owers the active turtle's pen. This is the same as 1 SET PENSTATE.

PENUP [ --- ] Raises the active turtle's pen This is the same as 0 SET PENSTATE .

PENDOWN? [--- flaK ] I.eaves a 1 on the stack if the active turtle's pen is down and a 0 if it is up. This is the same as PEN.

PENUP? [--- flag ] Leaves a I on the stack if the active turtle's pen is up and a 0 if it is down. This is the opposite of PEN.

ERASING [ --- ] Fills the active turtle's pen with type 0 ink (the erasing type.) This is the same as 0 SET INK.

(...) [ #loops --- ] Executes the words between the left parenthesis and the right parenthesis the number of times given by #loops .

DEFINE...AS...END Defines the word between DEFINE and AS to be a new turtle command which will execute the words between AS and END.

BYE [---1 Ieaves Turtleland and returns to pns-Forth.