by Gordon Smith
This is the first of two articles on implementing a Turtle Graphics system in FORTH.
Let me make two quick points about FORTH:
-Doing this project in any other computer language would have been so involved that I would never have done it, and so lengthy that this magazine would never have published it.
-Doing it in FORTH was so easy it took me considerably longer to write the English for this article than the FORTH!
Those of you who have Pink Noise Studios' pns-FORTH (I use version 1.4) can edit the screens accompanying these articles "as is" and start turtle-ing. If you have another implementation of FORTH for the ATARI, some revisions are inevitable. I have used words like PLOT and DRAWTO, that pns-FORTH provides for making graphics calls to the ATARI's operating system. Your system may already have similar words. In Part 2 (next issue), I'll discuss the functions of any non-fig-FORTH words that I've used.
Turtle Graphics Versus Coordinate Graphics"Turtle Graphics" is a simple but powerful approach to creating graphic designs with a computer. It was originally developed in the 1960's at MIT-primarily by computer scientist, child psychologist, and educator Seymour Papert -as part of the LOGO system.
Let me give you a very simple example of how it works. Suppose we want to draw a square on the screen, 10 units on a side. The sequence of commands
10 DRAW 90 TURN 10 DRAW 90 TURN 10 DRAW 90 TURN 10 DRAW 90 TURNor, in a shorter form,
4 ( 10 DRAW 90 TURN )requests an imaginary turtle on the screen to crawl 10 units forward, draw a line as it goes, turn 90 degrees clockwise, repeat four times. The turtle will leave behind a square.
DEFINE SQUARE AS A ( 10 MOVE 90 TURN ) ENDwe can add the new command SQUARE to our turtle's graphics repertoire. Then typing the single command SQUARE will have the same effect as our previous sequence of commands. For example, to draw a square tilted by thirty degrees, we need only to type
30 TURNThe conventional approach to graphics, in which one must specify fixed screen coordinates and the endpoints of each line is much more complicated.
The principle advantage of Turtle Graphics is that it describes shapes in an intrinsic way, without referring to where they are or how they're oriented. The numbers used in Turtle Graphics represent easily visualizable things, like lengths of lines, or angles.
A further important aspect of a Turtle Graphics system is the nature of the programming it encourages: structured, modular, and hierarchichal. The DEFINE . . . AS . . . END construct shown above is the key to this. Basic subdesigns can be made into new turtle commands which are then as much a part of the turtle's language as the predefined system commands. These higher-level commands can then be used to define still higher ones, and so on.
For example, a simple picture of a house like that in Figure 1 could be drawn with a long sequence of DRAWs and TURNs (along with another command for the turtle to move without drawing). But the structure of the design cries out for the programmer to instead first enrich the turtle's vocabulary by defining commands such as, perhaps, RECTANGLE, WINDOW, DOOR, FRONT, AND ROOF, before using these higher-level command to define on called HOUSE.
The FORTH AdvantageFORTH is so ideally suited to Turtle Graphics that, in a sense, implementing it is a trivial exercise.
The most complicated aspect of Turtle Graphics is the problem of providing a programming environment in which turtle commands can be executed. Such a capability is already intrinsic to FORTH, while it is quite foreign to conventional languages like BASIC.
The point here is that the turtle's language can be just an extension of the FORTH language-turtle commands are simply FORTH words. There is no need to write an extensible command language processor. That's what a FORTH system already is!
What the Screens ContainThe ten screens of FORTH listed in this article lay the necessary foundations for us to build a Turtle Graphics system in Part 2 (next issue). The words here are not specifically turtle-oriented. Rather, they extend FORTH's capabilities in directions particularly useful to the application.
Screens 1, 2, and 3 add some trigonometric capability to FORTH. If the turtle is to move 10 units forward at 30 degrees from the vertical, we need to compute how far up and how far over she goes. For this we use a lookup-table approach. Scaling the values by 10000 enables us to store them as single-precision integers. The words SIN~~ and COS* are the result of this. For example,
10 30 SIN
leaves 5, or 10 times the sine of 30 degrees, on the stack; and this is how far over the turtle would move.
Screen 4a makes available a defining word, VALUE, for a new data type. An alternative to CONSTANT and VARIABLE, VALUE words tend to make FORTH code more readable. They are best explained by the following example:
VALUE A VALUE B VALUE C ok 2 TO A 3 TO B ok A . B . 2 3 ok AB + TO C C . 5 okVALUE words return their value when executed, except when they are preceded by TO; in which case they store the top of the stack into themselves. (This idea has been discussed in the FORTH DIMENSIONS newsletter of the Forth Interest Group.)
In screen 4a the words TO and VALUE are defined in assembly language, rather than FORTH, so that they will execute as fast as CONSTANTs and VARIABLEs. If you don't have an assembler, use the alternate FORTH code on screen 4b.
Screens 5 through 8, culminating in the word CLIP, implement a line-dipping algorithm. We want the turtle to be able to cross the edge of the screen, so that if we execute SQUARE when she is near the top we'll get a clipped box. But the opearing system will refuse to draw a line whose endpoints aren't both within the screen boundaries. Therefore, we must be able to calculate the endpoints of the portion of the line which lies on the screen. If we give CLIP the coordinates of two points, it first determines whether any part of the line between them lies within a "dipping rectangle" whose extent we can specify by setting the values of LEFT, RIGHT, TOP, and BOTTOM. (Note that these words are in the vocabulary CLIPPING). If so, it returns the coordinates of the endpoints of the portion within the dipping rectangle, and a true flag. If not, it returns only a false flag.
For example, suppose we set the dipping rectangle to be the size of the mode-7 graphics screen with
CLIPPING 0 TO LEFT 159 TO RIGHT 0 TO TOP 79 TO BOTTOMThen
30 30 50 50 CLIP
leaves 30 30 50 50 1 on the stack because the line between (30,30) and (50,50) is completely within the dipping rectangle. But
80 100 200 40 CLIP
leaves 122 79 159 61 1 because only the portion between (122,79) and (159,61) of the specified line lies inside the dipping rectangle. And
200 200 300 300 CLIP
leaves 0 because no part of the line lies inside. The Cohen-Sutherland algorithm that CLIP uses is described in detail in Chapter 5, "Clipping and Windowing", of Newman and Sproull's Principles of Interactive Computer Graphics.
The last screen, number 9, defines the word GRAPHICS for opening the screen in the graphics mode specified by the top the stack, and LINE, which takes the coordinates of two endpoints and draws the clipped part of it on the screen.
If you want to see the dipping in action, before the rest of the code is given in Part 2, try the following: Define the words BORDER, RANDOM_LINE, and RANDOM_ LINES as
: BORDER CLIPPING 1 COLOR LEFT BOTTOM PLOT LEFT TOP DRAWTO RIGHT TOP DRAWTO RIGHT BOTTOM DRAWTO LEFT BOTTOM DRAWTO ; : RANDOM LINE 4 0 DO CRANDOM LOOP LINE ; : RANDOM_LINES 0 DO RANDOM_LINE LOOP ;and then type
CLIPPING 20 TO LEFT 140 TO RIGHT 20 TO TOP 60 TO BOTTOM 7 GRAPHICS BORDER 100 RANDOM_LINESSee you next issue!