Tutorial Project 5: An Object-Oriented Logo Programming Document
This project is focused principally on language-centric properties of Mathscript, and less so on screen design. In the project, we build a one-page Document called "Logo". The finished version of this Document appears at the New Mathwright Library and Cafe ( http://www.mathwright.com ) and you may compare your results with it.
This Document contains a small Command Language that you will create as you build the Document. Then your readers may use that to program environments that contain as many logo turtles as they like, each with their distinguished, and changeable attributes.
Along the way, you will learn the Command Protocol that creates new commands and the Program Protocol that creates new programs, and you will learn how to package new Command and Program definitions in File Scripts. In the Document, these commands that you create are executed on the built-in Command line.
Mathscript is an object-oriented language, and a logo turtle is an "object" for anyone's money. The structure of this Document makes use of MathScript's ability to build a functioning object hierarchy. You will learn how to define Classes, and how to instantiate (turtle) objects within those classes.
We make extensive use in this Document of graphical "polysprites." These are sprites defined by polygons (not bitmaps) that may be translated, rotated, and expanded or contracted under program control. The sprites you create are manipulated by Mathscript's built-in support for Logo in a simple and intuitive way.
Before beginning to build this Document, we give a description of the command language that we will create for it.
Mathscript Scripting (in general)
A sequence of commands (and protocols), each terminated with a semicolon is a Mathscript script. You may execute commands individually in any CommandLine by pressing Enter at the end of the command. You may execute entire scripts in any TextBox with the command: Enter in "textboxname";
If you want to place the commands in a file, press the right mouse button over any of the program buttons supplied with the Document, replace the text with your script, then press the compile button. Use the File menu to save it to disk. If you press Attach and Exit, then your script is temporarily associated with the button and will be run whenever you press the button. If you press Execute, you can test the script without attaching it to the button. To discard it, press Cancel.
If you save your script to disk, then to read it again later, open any button, and under File, choose Read Script. You will probably want to remove what was already in the button, first. This brings the script in, but does not execute it, yet. If you want to execute the script (without reading it), choose Load Script on the File Menu.
A program is a script that is "wrapped" by a program statement.
program progname <parameter list> { ... script of things to do ... }
When such a thing is executed, it simply defines the program: progname. It does not do the actions in the script. To perform the actions in progname, you must execute a statement like:
progname( arg1, ..., argn), in a script, where arg1, ..., argn are the arguments to the program, which will be evaluated, then substituted for the parameters in the parameter list of the definition. You will see many examples of such "program calls" in the blue command field for the five example programs provided under the buttons.
Interactive Commands:
In case your readers are not ready to write programs, don't worry. Logo is designed to support interactive exploration, one statement at a time. We will describe the interactive commands of our version of logo in a moment, but for now, we explain that you may simply type them into the blue command line, terminate with a semicolon, and press enter. You should see the result in most cases immediately.
Commands are subtly different from programs. With programs, the arguments appear in order in a comma-separated list enclosed in parentheses. For example, poly(10, 108, 10);
Programs "return" values which can, in principle, be used by other programs, or by commands.
On the other hand, commands do not place their arguments in parentheses, and needn't separate them with commas. In fact, Some arguments to commands are "optional" and need not be supplied at all, or may be supplied in any order. These optional arguments are indicated by square brackets [ ... ] in this tutorial. For example, in
Fwd n [ > name]; the "name" is optional. It may either precede or follow the required distance: n, but if it is supplied, it must be preceded by a > (then a space).
If we wrote:
Fwd > bill 10;
or
Fwd 10 > bill;
then we would be telling the turtle bill to move forward 10 units. If we just wrote: fwd 10, then we would be telling the current (or chosen) turtle, whoever that is, to move forward 10 units.
With that said, we list the logo commands that we will create for this Document. You will create these commands in MathScript, and needless to say, commands like these can be written for any Mathwright Document.
Logo Commands:
Choose turtlename;
This selects the turtle named turtlename as the "current" turtle. Later Commands that do not mention a name are directed to it.
Erase turtlename;
This removes the turtle named turtlename from the scene. After this, the turtle no longer exists.
Clear;
This standard Mathscript command clears the screen of all turtle paths, but does not remove turtles.
Showsprite "name" factor;
This standard Mathscript command expands, contracts, or inverts the turtle (polysprite) by the number: factor. For example, if factor = 2, the turtle will be twice as large as the original. You must place the name of the turtle in quotes here. If the factor is negative, the turtle is inverted (rotated by 180 degrees) as it is expanded or contracted. Use this command in scripts by getting the string name of the current turtle with: get(theTurtle, name);
Make variable name;
Turtle "name" name;
These two commands create a new turtle. Select a name for it, and make it a variable. Then supply the Turtle command with a string (in "quotes") of the same character sequence, followed by the name. Case does not matter. The new turtle acquires all of the attributes (except its name) of the current turtle. If you want to tune these attributes then you may supply any of a long sequence of optional arguments, as we do for Tom:
make variable tom;
turtle "tom" tom, position [0,0], angle 0, penstate true, outline color(0,0,0), body color(117, 171, 116), drawcolor blue, twidth 2, scale 1;
Position and angle are easy to understand. Initially, the screen extends from -20 to 20 in each direction. Angles are measured in degrees, with positive angles increasing from the East in the counterclockwise sense. Penstate, if true, causes the turtle to leave a "track" as it moves. If false, the turtle leaves no track. Outline is the outline color. It is an RGB color of the form color(r, g, b) where r, g, and b are integers between 0 and 255. Thus we have more than 16,000,000 choices! If that's too many, you may supply names for colors instead, like: red, lblue, magenta, and so on. Body is the color of the turtle body. Drawcolor is the color of the trail the turtle leaves. Twidth is the width of the trail. And Scale is a positive number. It gives the size of the turtle. The turtles: Bob, Bill, and Tom have size 1.
As we'll see below, all of these attributes except: Outline and Body may be changed, for each turtle separately, by Logo commands. You may, if you like, change the scale of a turtle by using the Mathscript command: Showsprite that is described above.
Fwd [> turtlename] length;
This moves the turtle forward at its present heading length units. Length may be positive or negative. If you type, say, Fwd > bill 10; then the command is directed to Bill. If you type: Fwd 10; it is directed to the current turtle.
Tby [> turtlename] angle;
This causes the turtle to rotate ("Turn by") angle degrees. It changes the heading but not the position. Positive angles increase in the counterclockwise sense.
Tto [> turtlename] angle;
This causes the turtle to rotate ("Turn to") to angle degrees. It changes the heading but not the position. Positive angles increase in the counterclockwise sense. If you type TTo > bob 45; then the command is directed to Bob. If you type: TTo 45; it is directed to the current turtle.
Mto [> turtlename] x, y;
This moves the turtle ("Move to") to the point [x,y]. If the pen is down, leaves a track, otherwise, does not
Pd [> turtlename];
This puts the pen down (sets penstate to true) for the named turtle. If you type: pd > bob; it puts Bob's pen down . If you just type: pd; it puts the pen for the current turtle down.
Pu [> turtlename];
This puts the pen up (sets penstate to false) for the named turtle. If you type: pu > bob; it puts Bob's pen up. If you just type: pu; it puts the pen for the current turtle up.
Pc [> turtlename], color;
This sets the pen color for the named turtle. If you type: pc > bob, lred; it makes Bob's pen light red. If you just type: pc, color(255,0,0); it makes the pen of the current turtle red.
Pw [> turtlename], width;
This sets the pen width for the named turtle. If you type: pw > bob, 3; it gives Bob's pen width 3. If you just type: pw, 3; it gives the pen of the current turtle width 3.
Ini [> turtlename];
This initializes the named turtle. The turtle is moved to the origin [0,0], given heading 0 degrees (Due East), and the pen is put down.
Before you begin, be sure that the screen resolution is 800x600 or 1024x768. The Documents that you create may be displayed on reader machines or browsers in any resolution. You have no control over that. But if you create them in 800x600 or 1024x768 resolution, then they will display properly in 640x480, 800x600, or 1024x768 resolutions in the reader's machine or browser. This is especially important because, in the browsers, you may shrink or enlarge the page as you like to fit your web page. Along these lines, we remind you that if you use wallpaper bitmaps (and hotspots) then you may use either bitmaps, GIFs, or JPGs. And these should be 800x600, or 1024x768 pixels to match your screen resolution. We will use the stock wallpaper that is supplied with the Author Program and it is 800x600 pixels in size.
Step 1: Document Directory
We begin, as usual, by creating the "Document Directory". As we mentioned in Project 4, each new Document should be placed in its own directory.
Therefore, the first step in creating the logo Document is to create a directory called logo (lowercase) that will hold it. We use lowercase for all file names and directories because some servers (notably Apache servers) are case sensitive, and may not find a file if the case is wrong. Of course, this is not an issue for Mathwright32 Author or Reader when they read Documents offline, but we follow the practice outlined above because most Documents will be served from web servers.
Another practice that we follow for reasons that will be clear when you read Project A on Packaging and Delivering your Document, is this: The name of the directory should be the same (lowercase) name as the name of your Document ( .lva file). We will create this Document in the C:\My Documents folder, because that is where Mathwright32 looks for them.
Thus, go to the Windows Explorer, select the C:\My Documents directory, then select File, New, Folder: and when asked for a name, type logo. This will create a directory: C:\My Documents\logo\ into which you will place the Document.
Step 2: Adding the "handcursor.cur" and the "wallpaper.bmp" resources
If you browse in Windows Explorer to the home directory: Program Files/Bluejay Lispware/Mathwright32 Author you will find a file called: handcursor.cur. Whenever you create a new Document, copy this file and paste it into your new directory. While it is not needed for offline reading in Mathwright32, it is a necessary resource for MathwrightWeb. Thus, highlight it, and select: Edit, Copy. Then browse to your new directory, and select Edit, Paste.
Next, locate the wallpaper: background.bmp in the Author directory, and copy that and paste it into your new directory.
Finally, go to the Program Files/Bluejay Lispware/Mathwright32 Author/Lisp directory and copy and paste the file: turtlevecs.lsp into your logo directory. Notice also that you have files: commands.lsp, programs.lsp, book.lsp, and objects.lsp. This is for insurance. We will build these files in the Project, but if for some reason your version of one of these four does not work, you will be able to copy the version from this directory into your logo directory.
The logo directory should now hold:
handcursor.cur
- background.bmp
- turtlevecs.lsp
Step 3: Creating the Document
Next, let's open Mathwright32 to create the logo Document. There are several ways to open Mathwright32 as we saw above. You may click on the Mathwright Author 32 icon above in the MWAuthor32 button on the Start Menu that was set up with the system, or you may go to Windows Explorer and click on mwauthor.exe in the Program Files/Bluejay Lispware/Mathwright32 Author subdirectory, or you may select Run..., then enter C:/Program Files/Bluejay Lispware/Mathwright32 Author\mwauthor.exe.
Any of these will open a blank copy of the program. Now, once the program is open, select WorkBook, New Document from the menu. The screen will turn white, and the page caption will change to: Untitled0: Page 1 of 1 This means that you have created a new Document. It has the temporary name: Untitled0.lva.
The next step is to save this (empty) book into the directory just created. Thus, Select WorkBook, Save As...
And type in the Dialog Box C:\My Documents\logo\logo or, select the C:\My Documents\logo directory, then type logo in the dialog box as below. Save the Document. It is saved as logo.lva.
Step 4: Setting the Wallpaper
Now, instead of setting a page color for the Document, we will add the stock wallpaper called background.bmp that was created by Mathwright Author Samad Mortabit. The important property of that wallpaper is that it has built-in Title bar (but no Navigation bar), and it is the required 800x600 pixels in size. You may of course create your own 800x600 wallpapers as you like in the future.
Select: Page, Wallpaper...
Browse for : background.bmp, and click OK.
Save the Document. Your page should now resemble:
Step 5: Add the graph2D, Command Line, and three Labels
We will step through a few details, but when you are finished, your page should roughly resemble this:
The graph2D gadget: graph
Beginning with the graph2D, switch to Design mode, and select Page, Snap to Grid. Now select Objects, Graph2D Gadget... and draw it on the right hand side of the screen to be as nearly square as you can. Name it graph, and return to Reader mode.
Now go to the menu and make the following choices:
Settings,
Coordinate System, Blank
Now, select
Actions,
Correct Aspect Ratio
When you show the Trace Bar, it uses the default page color (which is now white). We will select a new page color so that the trace bar blends into the background.
Select
Page, Page Background Color, Define Custom Colors, Red: 0, Green: 128, Blue: 128
Save the Document.
The Command Line, comma
Next, switch to Design mode, and select Objects, CommandField Object... and draw a Command Line on the lower left hand side of the screen. Name it comma, and return to Reader mode.
Now go to the menu and make the following choices:
Settings, Text, Set Font: Arial, Bold, 8 point
- Appearance, Background Color, Define Custom Colors, Red: 0, Green: 255, Blue: 255
- Appearance, Border Type, 3D Border
- Appearance, Scrollbars, Vertical
Save the Document.
The Title Label
Next, switch to Design mode, and select Objects, Label Object... and draw a Label in the center of the title bar, and return to Reader mode. Select Edit the Label
Now go to the menu and make the following choices:
Set Font: Arial, Bold, 20 point
- Set Background Color, Define Custom Colors, Red: 0, Green: 128, Blue: 128
Next type: Mathwright Logo Playground
Save the Document.
Instruction Labels
We create two columns of instructions in the upper-left corner of the screen. Each is, of course, a label, and we use Snap to grid to line them up. To create the first one, switch to Design mode, and select Objects, Label Object... and draw a Label and return to Reader mode. Select Edit the Label.
Now go to the menu and make the following choices:
Set Font: Arial, Bold, 8 point
- Appearance, Background Color, Define Custom Colors, Red: 0, Green: 128, Blue: 128
- Set Text Color: White
Now type the following:
Logo Commands:
________________
Choose name;
Fwd n [ name];
Tby ang [ name];
Tto ang [ name];
Mto x, y [ name];
Pd [ name];
Pu [ name];
Pc color [ name];
Pw width [ name];
Ini [ name];To create the second one, switch to Design mode, and select Objects, Label Object... and draw a Label to the right of the first, and return to Reader mode. Select Edit the Label.
Now go to the menu and make the following choices:
Set Font: Arial, Bold, 8 point
- Appearance, Background Color, Define Custom Colors, Red: 0, Green: 128, Blue: 128
- Set Text Color: White
Now type the following:
Clear;
Turtle "name" name;
Erase name;
Logo Functions:
_______________
Angle(name);
Position(name);
This finishes the "screen design" portion of the Project for now. Later, we'll add some buttons. But next, we develop and explain some Scripts.
Step 6: Add the WorkBook Script
As was mentioned in Project 4, sometimes it is necessary to initialize books when they first open by loading in File scripts, creating objects of various sorts, etc. The best place to do this is the WorkBook Script, because then the initializations are done just once, before anything else happens. If you want an initialization to affect a screen Display Object (such as draw a graph) then put that in the Page Script, because that is run after all display objects have been created.
When a File script, say Myfile, is created in a script window, Mathwright32 saves two files to disk: Myfile.lsp and Myfile.msp. The command:
load "myfile";
causes the contents of myfile.lsp to be brought into the Lexicon. This latter file has all of the executable content of the script: the command and program definitions, variable declarations, initializations, and so on. The other file is used for later editing and modifications.
We are going to create 4 File Scripts for this WorkBook:
objects.msp, book.msp, commands.msp, and programs.mspWe will write and discuss each one later, but we create a WorkBook Script that will be prepared to load those scripts once they are written (objects.msp will be loaded in the Page Script for reasons that we will explain later.) For now, we will comment out the load instructions, because they would cause an error if the script was not written, tested, and saved. We will remove the comments from the WorkBook Script, one at a time, as we write the corresponding File Script.
Now, to edit the WorkBook script, select (from any page) WorkBook, WorkBook Script... The Script window opens.
Type the lines: (notice that the last three lines are comments. They are enclosed in single quotes, and so they will be ignored by the compiler and will not be executed). They refer to files that we will build here. If for some reason, you are not able to get them to work, you can, as mentioned above, retrieve a working version of the .lsp file from the Program Files/Bluejay Lispware/Mathwright32 Author/Lisp directory
readfloat;
precision 6;
make turtlesin false;
make variable bob;
make variable bill;
make theturtle bob;
load "turtlevecs";
'load "book"; '
'load "commands";'
'load "programs";'
This script will be run once, when the book opens. Since the book is already open, we should execute it now so that we won't have to close and open the book. Thus click Execute. The script is run, the file is loaded into the Document, just as it will be whenever you open the Document. Now executing the script does not compile, attach, or save it. That must be done separately, since we might be executing it simply to test it. So now select Compile..., and Attach and Exit. The WorkBook Script is in place. This is a good time to Save the Document by selecting WorkBook, Save.
Step 7: What's in turtlevecs.lsp ?
The LISP file turtlevecs that was just loaded defined two vectors: v and w. These are each vectors of decimal numbers, and together, they provide the polygon that defines the shape of our turtles. Each vector has length 150, and you probably do not want to look at them. The turtles that will be defined as polysprites using them will look like:
Step 8: Create the "book" File Script
The File Script: book.msp defines a class called terrapin using the type command. This type will automatically have methods for getting and putting the properties of terrapin objects. In general, we could define other methods, but will not need to here, because the ones we need for logo are built into the MathScript language. It begins by initializing certain global variables that will be initial default values. To create the file script, get to Reader mode, and (for convenience) select: Page, Page Script... We will compile and save this script to disk, but will NOT attach it to the page. We are just using this script window as a scratchpad. Copy the Script below (or paste it) into the script window and select Compile. Then select File, Save Script As... and type book in the window and click Save. Finally, click Cancel since you do not want to attach it.
make xpos [0,0];
make xang 0;
make xpen true;
make xoutcolor color(0,128,0);
make xincolor color(117, 171, 116);
make xdrawcolor color(255,0,0);
make xdrawwidth 2;
make xsize 1;
type terrapin list(name, pos, ang, pen, outcolor, incolor, drawcolor, drawwidth, size) list();
command turtle (ST nam) (va na) [position ve #2 pp make xpos pp] [angle ex aa make xang aa] [penstate ex ppp make xpen ppp] [outline li oo make xoutcolor oo] [body li bb make xincolor bb] [drawcolor li dc make xdrawcolor dc] [twidth ex ww make xdrawwidth ww] [scale ex sc make xsize sc]
{
let lii false;
lisp (make lii (subst nam (quote nam) xpos (quote xpos) xang (quote xang) xpen (quote xpen) xoutcolor (quote xoutcolor) xdrawcolor (quote xdrawcolor) xincolor (quote xincolor) xdrawwidth (quote xdrawwidth) xsize (quote xsize){
list(name, nam, pos, xpos, ang, xang, pen, xpen, outcolor, xoutcolor, incolor, xincolor, drawcolor, xdrawcolor, drawwidth, xdrawwidth, size, xsize)
}));
object na terrapin lii;
let fillc be getfillcolor();
let penc be getpencolor();
let penw be getpenwidth();
polysprite nam xsize*[v,w] using fill xincolor, color xoutcolor, width xdrawwidth;
turnsprite nam to xang+1;
movesprite nam to xpos;
set fillcolor to fillc;
set pencolor to penc;
set penwidth to penw;
}
That's it! You have created the File Script: book.msp. Now let's see what you did.
The first thing to do is set default values, in case none are selected in the command.
make xpos [0,0]; 'Sets the initial position to [0,0]'
make xang 0; 'Sets the turtle angle to 0'
make xpen true; 'Puts the pen down'
make xoutcolor color(0,128,0); 'Sets the outline to green'
make xincolor color(117, 171, 116); 'Sets the body color to brown'
make xdrawcolor color(255,0,0); 'Sets the drawing color of the pen to red'
make xdrawwidth 2; 'Sets the width of the path to 2'
make xsize 1; 'Sets the scale to 1'Next, we define the terrapin class. This is done with:
type terrapin list(name, pos, ang, pen, outcolor, incolor, drawcolor, drawwidth, size) list();
The properties (member variables) of a terrapin object are:
name,
the name of the turtle, as string
The empty list ( list() ) at the end means that this class has no parent class.
The last thing you did was to define the turtle command, which actually creates an instance of the terrapin class, a turtle. The turtle command takes two mandatory arguments: a string representation of its name (nam) and the variable representation of its name. They must be supplied in this order. Thus if you typed:
Make variable Alice;
Turtle "Alice" Alice;You would create an object, a member of the terrapin class, (we will call it a turtle) named Alice with all of the default settings. We will try it momentarily, but we first have to modify the WorkBook Script to load "book" by removing the comment. First, let's study that command. It begins with the prologue:
command turtle (ST nam) (va na) [position ve #2 pp make xpos pp] [angle ex aa make xang aa] [penstate ex ppp make xpen ppp] [outline li oo make xoutcolor oo] [body li bb make xincolor bb] [drawcolor li dc make xdrawcolor dc] [twidth ex ww make xdrawwidth ww] [scale ex sc make xsize sc] ....
The mandatory arguments are (STRING nam) and (VARIABLE na), these are always enclosed in parentheses. Now, there are 8 Optional arguments which may or may not be included in any turtle command, and may appear in any order. Each of these has a "trigger": a word that must appear before it if it is included, and an "action": something to do if it appears. These are color coded below:
[position
ve #2 pp make xpos pp]
These actions just have the effect of setting the global defaults (variables beginning with "x" like "xpos" to whatever might have been supplied. But when you create a turtle with the turtle command you must precede each optional argument supplied by its trigger so that MathScript will know it's coming. Thus:
make
variable tom;
turtle
"tom" tom, position [0,0], angle 0, penstate true, outline
color(0,0,0), body color(117, 171, 116), drawcolor blue, twidth 2,
scale 1;
will work.
Now, let us consider the first part of the body of the command:
{
let lii false;
lisp (make lii (subst nam (quote nam) xpos (quote xpos) xang (quote xang) xpen (quote xpen) xoutcolor (quote xoutcolor) xdrawcolor (quote xdrawcolor) xincolor (quote xincolor) xdrawwidth (quote xdrawwidth) xsize (quote xsize){
list(name, nam, pos, xpos, ang, xang, pen, xpen, outcolor, xoutcolor, incolor, xincolor, drawcolor, xdrawcolor, drawwidth, xdrawwidth, size, xsize)
}));...}
It defines a local Mathscript variable: lii to be the empty list (false). This is so that we can reference it later with MathScript. The next step is to use the LISP protocol to redefine lii. We have to use LISP because we want to take the global values: xpos, xang, etc. and build a list from lii that can be called when we create the object with
object na terrapin lii;
below. LISP is good at that. The key LISP function here is subst which replaces: nam, xpos, xang, etc. with their actual values in the list:
{list(name, nam, pos, xpos, ang, xang, pen, xpen, outcolor, xoutcolor, incolor, xincolor, drawcolor, xdrawcolor, drawwidth, xdrawwidth, size, xsize)}
Do not worry if this doesn't make much sense at this stage. Read the Lisper Help documentation, and the discussion of Object Oriented Programming in this Help file to get a better idea what is going on. In any case, once lii is prepared with the proper values, it is handed to:
object na terrapin lii;
and a terrapin object is instantiated whose name is the variable which is the value of na. It has its properties assigned to the ones supplied in the turtle call, or to the defaults, if they were not used (as with Alice above). Now, the graphical object needs to be created as a polysprite. This polysprite has the string name: nam that was supplied along with na in the turtle call. Thus, the turtle command ties a variable (like Alice) with a string (like "Alice") and the value of the variable is the terrapin object, but that objects knows the string, because the string is its name property.
The next order of business is to store the current fillcolor, pencolor, and penwidth in local variables, because those will be changed by the polysprite command that creates the sprite. Then create the sprite, and move and turn it to its initial state.
let fillc be getfillcolor();
let penc be getpencolor();
let penw be getpenwidth();
polysprite nam xsize*[v,w] using fill xincolor, color xoutcolor, width xdrawwidth;
turnsprite nam to xang+1;
movesprite nam to xpos;
Finally, restore the values of fillcolor, pencolor, and penwidth to their original values, because we do not intend to change them permanently.
set fillcolor to fillc;
set pencolor to penc;
set penwidth to penw;
}And that's what the "book" file script does. Now to make it a part of your Document, open the WorkBook Script, remove the comment marks around load "book", and Compile it. Now test it by pressing Execute. You do not want to save a WorkBook Script with errors in it. If everything went well, Attach and Save the WorkBook Script. Remember, you have a copy of "book.lsp" in the Lisp directory if this simply does not compile.
This is a good time to Save the Document.
Step 9: Create the "commands" File Script
The "commands" File Script essentially defines our command language. To create the file script, get to Reader mode, and select: Page, Page Script... We will compile and save this script to disk, but will NOT attach it to the page. We are still using this script window as a scratchpad. Copy the Script below (or paste it) into the script window and select Compile. Then select File, Save Script As... and type commands in the window and click Save. Finally, click Cancel since you do not want to attach it.
command choose (Ex nm) { make theturtle nm; }
rem360(a) := a - quotient(a,360)*360;
command erase (Ex nm) {
let nam be get(nm, name);
removesprite nam;
lisp (set nm nm);
}command fwd (ex n) [ ex nm make theturtle nm] {
local (ve #2 po) {
let nam be get(theturtle, name);
let po be get(theturtle, pos);
penup;
move po;
let an be get(theturtle, ang);
turnto an;
let an be radian(an);
let st be get(theturtle, pen);
if st then {
pencolor get(theturtle, drawcolor);
penwidth get(theturtle, drawwidth);
pendown;
} else {penup;}
let newpo be po+n*[cos(an), sin(an)];
movesprite nam to newpo;
send theturtle putpos newpo;
forward n;
}
}command tby (ex n) [ ex nm make theturtle nm] {
let nam be get(theturtle, name);
let an be get(theturtle, ang);
let an be an+n;
let an be rem360(an);
turnto an;
turnsprite nam to an;
send theturtle putang an;
}command tto (ex n) [ ex nm make theturtle nm] {
let nam be get(theturtle, name);
let an be rem360(n);
turnto an;
turnsprite nam to an;
send theturtle putang an;
}command mto (ex x) (ex y) [ ex nm make theturtle nm] {
local (ve #2 po) {
let nam be get(theturtle, name);
let po be get(theturtle, pos);
let st be get(theturtle, pen);
penup;
move po;
if st then {
pencolor get(theturtle, drawcolor);
penwidth get(theturtle, drawwidth);
pendown;
} else {penup;}
let newpo be [x,y];
movesprite nam to newpo;
send theturtle putpos newpo;
move newpo;
}
}command pd [ ex nm make theturtle nm] {
let nam be get(theturtle, name);
send theturtle putpen true;
}command pu [ ex nm make theturtle nm] {
let nam be get(theturtle, name);
send theturtle putpen false;
}command pc (li col) [ ex nm make theturtle nm] {
let nam be get(theturtle, name);
send theturtle putdrawcolor col;
}command pw (ex wid) [ ex nm make theturtle nm] {
let nam be get(theturtle, name);
send theturtle putdrawwidth wid;
}
command ini [ ex nm make theturtle nm] {
clear;
let nam be get(theturtle, name);
send theturtle putpen true;
send theturtle putpos [0,0];
movesprite nam to [0,0];
turnsprite nam to 0;
send theturtle putang 0;
penup;
move [0,0];
turnto 0;
}program angle (ex nm) {
return get(nm, ang);
}program position (ex nm) {
return get(nm, pos);
}
These commands are described earlier in this Project. And they are essentially the ones you documented in the two labels on the page. We will make a few explanatory comments here as appropriate, rather than discussing them all in detail.
command choose (Ex nm) { make theturtle nm; }
At any moment, there is just one terrapin object "chosen." That is the "current" turtle. This is so that undirected commands (ones without the >) have some place to go. When the Document opens, the line in the WorkBook Script
make theturtle bob;
makes the "chosen" turtle bob. The choose command takes one mandatory object: the variable name of the turtle such as bob or bill, (not the string "bob" or "bill"). In general, when a name is required, supply the variable, not the string. The value of the variable is the object itself, and that object knows how to find its string name if it needs it using a line like:
let nam be get(theturtle, name);
rem360(a) := a - quotient(a,360)*360;
This function definition returns the remainder mod 360 of the angle. Since the angle will in general be a decimal, we could not use the remainder function directly.
We consider in detail the fwd (forward) command, which illustrates the code in commands.msp: What needs to be understood is that MathScript manages, for each graph2D, a single, invisible system "turtle." This is not a terrapin object, but remembers a pen state, a location, a direction, and does all system-level logo drawing. See the discussion of logo drawing elsewhere in this Help file.
command fwd (ex n) [ ex nm make theturtle nm] {
'The optional argument: [ ex nm make theturtle nm]
has trigger: > and action: make theturtle nm. Thus, if supplied, it sets the "current terrapin object" to that name'
local (ve #2 po) {
'The purpose of the local protocol is to inform the compiler that po is a 2-vector'
let nam be get(theturtle, name);
'The string form of this object name is the value of nam'
let po be get(theturtle, pos);
'Now the vector po is the current position of this terrapin object'
penup;
'Put the system pen up'
move po;
'Move the (single, invisible) system turtle to po with the (single) system pen up. The system turtle is NOT an object, but actually does all the logo drawing on behalf of our terrapin objects'
let an be get(theturtle, ang);
'Here an is set to the current terrapin direction'
turnto an;
'Turn the (single, invisible) system turtle to the direction an.'
let an be radian(an);
'Translate the degree angle an to radians.'
let st be get(theturtle, pen);
'Set the boolean variable st to the current terrapin pen state.'
if st then {
pencolor get(theturtle, drawcolor);
penwidth get(theturtle, drawwidth);
pendown;
} else {penup;}
'If the current terrapin pen is down, put the system turtle pen down, set the color and width, else put the system pen up'
let newpo be po+n*[cos(an), sin(an)];
'The vector newpo is the next position of this terrapin object'
movesprite nam to newpo;
'Now move the polysprite to that position for this terrapin object'
send theturtle putpos newpo;
'Inform the terrapin object of its new position'
forward n;
'Move the (single, invisible) system turtle to the new position'
}
}
We also consider the ini (init) command, that reinitializes a terrapin object. When a class is defined, and its properties declared with the type command, then for each property name, prop, two accessor methods are created: prop and putprop. The property is read by a call: get( name, prop) which is actually the message: send name prop; and the property is set to value by the message: send name putprop value;
command ini [ ex nm make theturtle nm] {
'The optional argument: [ ex nm make theturtle nm]
has trigger: > and action: make theturtle nm. Thus, if supplied, it sets the "current terrapin object" to that name'
clear;
'Remove all logo paths from the graph2D screen'
let nam be get(theturtle, name);
'The string form of this object name is the value of nam'
send theturtle putpen true;
'Put the current terrapin pen down'
send theturtle putpos [0,0];
'Inform the terrapin object that its new position is at the origin'
movesprite nam to [0,0];
'Now move the polysprite to the origin for this terrapin object'
turnsprite nam to 0;
'Turn the polysprite to angle 0 for this terrapin object'
send theturtle putang 0;
'Inform the terrapin object that its new direction is East'
penup;
'Put the system pen up'
move [0,0];
'Move the (single, invisible) system turtle to the origin'
turnto 0;
'Turn the (single, invisible) system turtle to the East'
}These are the commands defined in the "commands.msp" file script. Now add commands to your Document, open the WorkBook Script, remove the comment marks around load "commands", and Compile it. Now test it by pressing Execute. You do not want to save a WorkBook Script with errors in it. If everything went well, Attach and Save the WorkBook Script. Remember, you have a copy of "commands.lsp" in the Lisp directory if you have trouble with this.
Save the Document.
Step 10: Create the "programs" File Script
The "programs" File Script contains 4 logo programs that your reader can experiment with on the command line. To create the file script, get to Reader mode, and select: Page, Page Script... We will compile and save this script to disk, but will NOT attach it to the page. We are still using this script window as a scratchpad. Copy the Script below (or paste it) into the script window and select Compile. Then select File, Save Script As... and type programs in the window and click Save. Finally, click Cancel since you do not want to attach it.
program square (ex size) { repeat 4 { fwd size; tby 90; } }
program poly (ex len) (ex angle) (ex number) { repeat (number) { fwd len; tby angle; } } program podly (ex len) (ex angle) (ex number) { repeat (number) { fwd len; tby angle; forward len; tby 2*angle; } }
program inspi (ex len) (ex initangle) (ex increm) (ex number) { repeat (number) { fwd len; tby initangle; initangle := initangle+increm; } }
make sqrt2 sqrt(2);
program ccurve (ex len) (ex angl) (ex mini) { local (fn ccurve) { if len < mini then { tto angl; fwd len; } else { ccurve(len/sqrt2, angl+45, mini); ccurve(len/sqrt2, angl-45, mini); } } }
These
programs can be a starting point for logo experimentation. You will
shortly add some seed logo commands on the command line to get your
Reader started. Now add programs to your Document, open the
WorkBook Script, remove the comment marks around load "programs",
and Compile it. Now test it by pressing Execute. You
do not want to save a WorkBook Script with errors in it. If
everything went well, Attach and Save the WorkBook Script.
Remember, you have a copy of "programs.lsp" in the Lisp
directory if you have trouble with this.
Once again, Save the Document.
Step 11: Create the two turtles in the Page Script
Now we need some turtles to play with. We will create terrapin objects: bob and bill in the Page Script, and will leave the definition there. Why the page script and not the WorkBook Script? Because when we create these objects with the turtle command, there must be a graph2D to put them in. The WorkBook Script is run at the very beginning, before any Display Objects have been created, so the turtle command would not execute in the WorkBook Script. It is defined there, when "book" is loaded, but defining a command is not the same thing as executing it. The Page Script, on the other hand is run only after all Display Objects have been created. So we can define bob and bill there.
You may now be asking the following delicate question. What if I copy and paste this page into another book, one that has several pages? Would these turtles be re-created every time I returned to this page? That would not be a good thing, because they would be re-initialized to their start values each time, and I might want them to "remember" where they were. We solve that little problem with the global turtlesin variable, which is set to false in the WorkBook script. Bob and Bill will only be created in the page script if turtlesin is false. Once they are created, turtlesin is set to true, and they will not be created again, until the WorkBook Script is run again, at least.
Before you create Bob and Bill, you must create the "objects.msp" File Script. You can do that in the Page Script as before, and once you save it to disk, press Cancel so that you do not attach it. The Code for "objects.msp" is as follows:
turtle "bill" bill, position [5,0], angle 135, penstate true, outline color(0,128,0), body color(117, 171, 116), drawcolor color(0,128,0), twidth 2, scale 1;
turtle "bob" bob, position [-5,0], angle 45, penstate true, outline color(128,0,0), body color(127,127,0), drawcolor color(128,0,0), twidth 2, scale 1;
Create the File Script, objects.msp, and after you press Cancel, reopen the Page Script window and place the following script there:
if not(turtlesin) then {
load "objects";
turtlesin := true;
}
Now Compile this Page Script, and this time, Attach and Exit, and Save the Document.
Step 12: Finishing up. Add some example commands to the Command Line
The final step is to put some example commands in the Command Line so that your Reader can get started. First, add a pushbutton called My Programs, so that your reader can have access to a blank Script Window to read, write and save logo programs.
Next, paste the following text into the command line. This will get your Reader started. Of course, you must explain how to open the My Program button script and to write and save programs.
square(5);
square(10);
ini bill;
poly(6, 120, 3);
poly(10, 108, 10);
ini bill;
podly(4, 120, 4);
podly(6, 144, 5);
podly(6, 108, 10);
ini bill;
inspi(2, 50, 108, 90);
inspi(2, 50, 120, 40);
inspi(2, 110, 30, 80);
inspi(2, 100, 120, 80);
ini bill;
ccurve( 10, 0, 2);
ccurve(10, 90, 1);
ccurve(10,0,3);
ccurve(10,45,4);Save the Document.
When you finish, your Document should look like this:
![]()