TEACH TURTLE Updated A.Sloman Sept 1986 THE POP11 TURTLE ================ CONTENTS OF THIS FILE - (Put cursor at desired entry, use ' g' to access sections) -- INTRODUCTON -- MAKING THE TURTLE FACE IN DIFFERENT DIRECTIONS -- DEFINING A PROCEDURE -- BIGGER PICTURES -- CHANGING THE "PAINT" USED BY THE TURTLE -- USING DRAWTO -- USING TURNTO -- JUMPBY AND DRAWBY -- EXAMINING THE PICTURE -- INTRODUCTON -------------------------------------------------- This file introduces the POP-11 'turtle' library package, which enables you to draw pictures on a rectangular grid, using the procedures DRAW, JUMP, TURN, DRAWTO, JUMPTO, and more. This program simulates a turtle crawling around a rectangular picture, leaving a trail of paint. The picture can be printed on your terminal. Leave TEACH by pressing the ENTER key, then type X then press RETURN. Then, when you get the colon prompt from POP11, type the following to get the program ready: turtle(); newpicture(10,10); The first command gets the turtle ready. The second, makes it use a small enough picture to leave space on the screen for typing, etc. Type TEACH; afterwards, to get back here. Initially, you are provided with a (small) blank picture hidden in the computer. If you type: display(); you'll get the blank picture printed out. Leave VED (ENTER-X-RETURN) and try it. Type TEACH; to get back here. The "T" tells you where the turtle is imagined to be: i.e. in the bottom left of the picture, position 1.00 along and 1.00 up. The picture is made up of a rectangular grid of square locations. This is a representation of part of it. Notice that we count rows from the bottom up, and rows and columns start from 1. The lines surrounding the boxes are not drawn when you give the DISPLAY(); command. 5------------------------- | | | | | | | 4------------------------- | | | | | | | 3------------------------- | | | | | | | 2------------------------- | T | | | | | | 1------------------------- 1 2 3 4 5 6 7 Initially, the turtle is ready to draw to your right, i.e. (heading is "east"). Now leave VED and try: draw(4); display(); You'll see that the turtle has moved along in a horizontal direction (heading "east") leaving a trail of asterisks. The numbers printed alongside the picture are to help you count along and up. The "T" shows you that the turtle has moved. The draw command draws in the direction of the current heading. The TURN procedure can be used to change the heading. Turn (90) makes the heading swivel through 90 degrees ANTI-clockwise (i.e. it will then face NORTH, or up the screen). Go back to POP11 and try: turn(90); draw(3); display(); try: turn( -90 ); draw(5); display(); The picture can be thought of as made up of lots of imaginary squares. The turtle starts off in the middle of the bottom left square. After moving 7 units to the right, its position is (8, 1) Try the following: jumpto(1,5); draw(5); display(); The JUMPTO command put the turtle on the left of the picture, five rows up. It was still facing to your right (heading 0). the DRAW command told it to move a distance of five units, leaving a trail. Jumpto some other location, e.g. 2 along and 3 up, then display the picture. You may do this several times, if you wish, with different picture locations. The picture initially created by the NEWPICTURE(10,10); command, above is 10 units wide and 10 units high. To check this type: picture => If you draw beyond the edge of the picture, you'll get a 'mishap' message. Try the following sequence: turtle(); draw(99); You can now use DISPLAY, as before, to see how far the turtle got: display(); Then: xposition, yposition => Compare the line starting "involving" in the mishap message. The mishap occurred because the turtle was trying to "paint" an asterisk at a non-existent picture location. Further DRAW commands will again produce an error, since the turtle is at the edge of the picture, and facing off it. E.g. try: draw(2); But you can make the turtle turn and draw in another direction: turn(90); draw(5); display(); You can restart with the TURTLE(); command, to get a clean picture. turtle(); draw(7); display(); You can also use JUMP, to move the turtle in its current heading, e.g. turtle(); draw(5); turn(90); jump(3); draw(5); display(); You can jump either forwards or backwards, e.g. JUMP(3); JUMP(-3); Try drawing something using DRAW, TURN, JUMP, and DISPLAY. Can you draw a capital H ? If you've had enough for now, type ENTER-Q to abandon this TEACH file, then leave POP11. You can come back later and continue from this place if you note the line number in the status line, above. To jump to line 150, say, you can do teach turtle; then press ENTER, then type @150 (i.e. at location 150) then press RETURN. go back to POP11 and try that now, for practice. If you leave POP11 now and come back later, you'll have to type turtle(); to get the turtle ready again. The default picture size is 20 by 20. To get a smaller picture, to leave more space on the screen, do newpicture(20,10); This will make a picture which is 20 along and 10 up. You can experiment with different sizes. -- MAKING THE TURTLE FACE IN DIFFERENT DIRECTIONS --------------- The TURN command alters the way the turtle is facing. Try the following: newpicture(15,15); draw(5); display(); newpicture(15,15); The NEWPICTURE command creates a new picture of a different size. Now type: heading => turn(90); heading => draw(5); display(); Notice how position and heading change. The TURN(90) command said to the turtle: "turn left (counterclockwise) by 90 degrees". So having previously been facing to the right, it is now facing up (north). Turns like this alter the value of the variable "HEADING". Try: turn(90); heading => turn(-90); heading => turn(45); heading => The TURN command does not affect the position, only the heading. TURN applied to a negative number (e.g. -90 ) means "turn clockwise". (e.g. it is equivalent to "turn right".) Try the following, and see if you can guess what will happen: turtle(); draw(5); turn(90); draw(5); display(); turn(135); draw(7); display(); Notice that although the last command said "draw over a distance of 7 units," it did not produce 7 asterisks. This is because all the asterisks have to be lined up with rows of printing. You'll always find that when the turtle is drawing in a direction other than vertical or horizontal it doesn't produce exactly as many asterisks as the distance drawn. You'll also find that if you draw in other directions than the horizontal vertical or diagonal, the lines look very strange. try turtle(); turn(20); draw(9); display(); turtle(); turn(60); draw(10); display(); The TURTNASTY demo explains in more detail. For now it is simplest to stick to horizontal, vertical and diagonal lines. Give the TURTLE(); command to get a new picture, then draw some pictures, using DRAW, TURN, JUMP, DISPLAY. If you want a bigger picture again, use NEWPICTURE, e.g. NEWPICTURE(30,20) gets you a picture 30 characters wide and 20 high. If mishaps arise which you cannot understand, ask for help. When you want to find out where the turtle is and which way it is facing without giving a DISPLAY(); command, you can do this: xposition, yposition, heading => Try it. -- DEFINING A PROCEDURE ----------------------------------------- You may get tired of typing XPOSITION, YPOSITION, HEADING => every time you want the turtle to print out its current state. So you can define a procedure called WHERE which will do it all for you. define where(); [^xposition, ^yposition, ^heading] => enddefine; Type that, including the funny arrows. If you have learnt to use the editor, use it to put this in a file. It will save a lot of time if you make typing mistakes. Check that the procedure WHERE has been defined: where => If the computer does not print out ** procedure try typing in the definition of the procedure again. If you are not used to procedures, try TEACH DEFINE some time. You can execute the procedure just defined, by typing: where(); jumpto(4,7); where(); The procedure makes a three element list, using the "up arrow" ^ to include the VALUES of three variables, and prints out the list. If you keep forgetting which way TURN works, you may find it useful to define procedures called LEFT and RIGHT. If you put them on files they will be available for future use (using LOAD). Try: define left(angle); turn(angle); enddefine; define right(angle); turn( -angle); enddefine; heading => left(90); heading => right(45); heading => right(45); heading => Then test the procedures: turtle(); draw(3); display(); left(90); draw(3); display(); right(45); draw(5); display(); right(135); draw(5); display(); Use these to create a procedure to draw a "T". define tee(size); jump(size/2); turn(90); draw(size); turn(90); draw(size/2); turn(180); draw(size); display(); enddefine; then test it: turtle(); tee(5); turtle(); tee(8); If you wish to abbreviate DISPLAY, you can declare a new variable and assign DISPLAY to it, thus: vars dis; display -> dis; dis(); After that you can use DIS instead of DISPLAY. Try defining a procedure called CORNER, which makes the turtle DRAW(5); then TURN(90); then DRAW(5); then DISPLAY(); define corner(); < you fill in this bit > enddefine; try it then test the procedure by typing: corner(); Your procedure could have been: define corner(); draw(5); turn(90); draw(5); display(); enddefine; Try that if your definition did not work. Then try: turtle(); corner(); corner(); Could you define a procedure to draw a square? -- BIGGER PICTURES ---------------------------------------------- You can use the NEWPICTURE command to produce a bigger picture e.g. to get a picture 30 characters wide and 16 high type: newpicture(30,16); The turtle is always put at the bottom left, facing right, by NEWPICTURE. Check this: display(); xposition, yposition, heading => Try drawing a rectangle, 15 units wide and 10 high, then display it. E.g. you could have done something like: newpicture(18,18); repeat 2 times draw(15); turn(90); draw(10); turn(90); endrepeat; display(); The bit between "times" and "endrepeat" is obeyed the number of times specified by the number after "repeat", i.e. twice. Try drawing a rectangle of a different size, using a REPEAT command. Then DISPLAY it. Can you use REPEAT to draw a 5 by 5 square? Try it. If you didn't manage, try something like: turtle(); repeat 4 times draw(5); turn(90); endrepeat; display(); Try a bigger square, e.g. 15 by 15. One thing we can't help is the fact that teletypes stretch squares vertically because they type with bigger spaces between rows than between characters in rows. Can you predict what happens if you reverse the TURN and DRAW commands, thus: turtle(); repeat 4 times turn(90); draw(15); endrepeat; try it. This is what happened when the repeat command was obeyed. It tries to do TURN(90); then DRAW(5) four times. The turtle starts off facing to the right, so the first TURN(90) makes it face up (North: heading = 90). The first DRAW(5) takes it up the left of the picture. The next TURN makes it face to the left (WEST: heading = 270), i.e. facing off the edge of the picture, and the following DRAW causes a mishap. Type DISPLAY(); and make sure you understand what happened. -- CHANGING THE "PAINT" USED BY THE TURTLE ---------------------- To make sure the picture is clear, type: turtle(); You may wish to make the turtle leave a different sort of trail when it draws. You can do this by changing the "paint". E.g. if you wish to make it leave a trail of dots instead of asterisks do: "." -> paint; i.e. assign the word "." to be the value of the variable PAINT. Try it then draw something and display the picture. Now clear the picture, e.g. NEWPICTURE(15,15); and try to draw a square of side ten units long (using whatever paint you like). Try it then display the picture. The following should have worked: turtle(); "." -> paint; repeat 4 times draw(10); turn(90); endrepeat; Try that, followed by DISPLAY(); if yours didn't work. Can you guess how to make the turtle leave a trail of plus signs "+" for its paint? Change the paint thus: "+" -> paint; Then draw something, and display it. It is a bit tiresome having to type in the whole REPEAT instruction every time you want to draw a square. To avoid doing so, you can define a new procedure called SQUARE, thus: define square(size); repeat 4 times draw(size); turn(90); endrepeat; enddefine; This tells the computer to store a procedure called SQUARE which is to be executed with input, or "argument", temporarily named SIZE. When the procedure is executed, it will make the turtle draw and turn four times, the distance drawn depending on the value of SIZE. Make a new picture about 20 by 20. Then use the procedure SQUARE to draw a few squares, thus: square(15); display(); square(10); square(5); display(); Notice how the turtle always returns to the same place and heading after executing SQUARE. If you can't see why ask for help. SQUARE(15); means, roughly "obey the instructions in the definition of procedure SQUARE, with 15 as the value for the variable SIZE". Now try this: newpicture(20,20); 1 ->paint; ;;; prepare to leave a train of 1s jumpto(6,6); square(8); display(); 2 ->paint; jumpto(2,2); square(16); where(); display(); jumpto(10,4); 3 -> paint; turn(45); square(8); display(); where(); Notice that JUMPTO, unlike DRAW, requires two inputs, i.e. two numbers representing the desired XPOSITION and the YPOSITION of the location. JUMPTO does not alter the value of HEADING. -- USING DRAWTO ------------------------------------------------- Clear the picture: turtle(); Then draw a square: repeat 4 times draw(14); turn(90); endrepeat; display(); How could you draw a diagonal line across a square? You could try to TURN(45); then use DRAW. But you'd have to calculate the distance. Instead you can use the procedure DRAWTO. try: turtle(); drawto(15,15); display(); Try the following: true -> changepaint; ;;; prepare to alter paint. newpicture(20,20); "a" -> paint; drawto(15,1); drawto(15,15); drawto(5,15); drawto(5,5); drawto(10,5); drawto(10,10); display(); To avoid so much typing to draw that you can use a REPEAT instruction. newpicture(20,20); vars dist; ;;; declare a new variable 15 -> dist; ;;; assign 15 to be its value repeat 4 times draw(dist); turn(90); draw(dist); turn(90); dist - 3 -> dist; endrepeat; display(); try that, without the comments following ";;;". The line before ENDREPEAT says: subtract 3 from DIST and assign the result to be the new value of DIST. The whole REPEAT instruction, which starts with REPEAT and ends with ENDREPEAT, says "do everything between TIMES and ENDREPEAT four times". If you now want to draw a different squiral it will be rather tedious to have to retype all that. So define a procedure: define squiral(num, dist, sub); repeat num times draw(dist); turn(90); dist - sub -> dist; endrepeat; enddefine; If you've learnt how, use the editor to store this definition in a file for future use. This defines a procedure called SQUIRAL which will have to be given three arguments, to be called NUM DIST and SUB, when it is executed. Create a new picture and try executing it thus: turtle(); squiral(15, 17, 1); display(); This says, run SQUIRAL with 15 as the value for NUM, 17 as the value for DIST and 1 as the value for SUB, the amount to be subtracted each time. Try running SQUIRAL with different values, e.g. squiral(12,20,1); You could redefine SQUIRAL so that the DISPLAY command is included between ENDREPEAT and ENDDEFINE. What will the following do: squiral(5,5,2); This is what happened: If you subtract 2 from 5 more than twice you end up with a negative number. So DIST will become negative. That's alright: drawing a negative amount just means drawing backwards. Similarly, JUMP(-3); means "jump 3 backwards". Try to work out what the following will do, then do it. newpicture(20,20); jumpto(10,10); repeat 8 times draw(6); jump(-6); turn(45) endrepeat; display(); It should have made a star. If not, try again. Try to make a star of a different size, or a star using a different paint, e.g. ".", or "+", or "o". -- USING TURNTO ------------------------------------------------- Try the following: newpicture(10,10); jumpto(2,2); drawto(6,6); draw(3); display(); Notice that the DRAWTO command drew a line, but did not make the turtle face along that line. So the DRAW command used the original heading. The procedure TURNTO is available to make the turtle face in the direction of a specified point. TURNTO(X,Y) makes it face in the direction of the point with co-ordinates X,Y. Try the following, or some variation of it: newpicture(21,21); jumpto(11,11); turnto(21,1); draw(5); jumpto(11,11); turnto(11,1); draw(5); jumpto(11,11); turnto(21,1); draw(5); jumpto(11,11); turnto(21,21); draw(5); display(); You can't make the turtle TURNTO the point its already on. Try: jumpto(1,1); turnto(1,1); -- JUMPBY AND DRAWBY -------------------------------------------- See if you can guess what the following will do, then try it: newpicture(30,25); 1 -> paint; repeat 5 times draw(3); jumpby(2,2); paint + 1 -> paint; endrepeat; display(); JUMPBY(X,Y) means, "without leaving a trail, move X units to the right and Y units up". To move to the left, or down, you can use negative numbers, e.g. JUMPBY(-5, 0); to move left. Try the last lot again using DRAWBY instead of JUMPBY. The only difference is that DRAWBY leaves a trail of paint. Both require two arguments (inputs), like DRAWTO and JUMPTO, but the arguments are not taken to be co-ordinates of a point. -- EXAMINING THE PICTURE ---------------------------------------- Draw a little picture: newpicture(15,15); square(10); If you don't have a procedure SQUARE, use REPEAT instead. The picture inside the machine is really an "array" called "PICTURE". You can examine its contents without using DISPLAY to print it all out. For instance to find out what is at the location (1,3), type: picture(1,3) => This prints out two asterisks, followed by the paint at location (1,3). The paint may be blank, at the location, i.e. if it contains a space. Try this: "*" => "+" -> paint; paint => space => "SPACE" is a special POP11 variable, whose value is a word containing a space. You cannot type in such a word yourself. Try: " " => Some picture locations have a space, whilst others have the word corresponding to the paint used. You can look at several locations, thus: picture(3,1) => picture(3,3) => picture(1,3), picture(1,4), picture(2,4) => display(); If you want to know what is at the current turtle location type: picture(xposition,yposition) => This is a bit much to have to type each time, so you can define a procedure called COLHERE thus: define colhere; picture(xposition, yposition) => enddefine; colhere(); jump(1); colhere(); jumpby(2,2); colhere(); xposition, yposition => Try this: turtle(); jumpto(2,1); square(5); jumpto(1,1); 0 -> heading; repeat 8 times colhere(); jump(1); endrepeat; This prints out what is at 8 locations in a straight line starting at (1,1) and going to the right. Using procedures like COLHERE you can make the turtle move about the picture examining its contents and perhaps trying to recognise or interpret what has been drawn. What would it require in order to be able to recognise squares, as well as draw them? Don't try to answer now. HELP TURTLESUM gives a summary of turtle procedures. TEACH SEEPICTURE introduces further uses of the turtle. TEACH VTURTLE shows how to use a VED editor window as the picture into which the turtle draws. This presupposes familiarity with VED and the use of marked ranges in VED. See TEACH TEACHFILES for a more comprehensive list of available POP-11 TEACH files ------------