Every program on this page has been tested and works. Copy them into the editor (EDIT), validate with Ctrl+S, then call the procedure from the REPL. Do not hesitate to change the numbers to see what happens, it is the best way to learn.

Contents: basic shapes · rosettes & spirals · the house project · colours · fractals (recursion) · text & computation · arrays & slices · files · music

Basic shapes

The universal polygon

A single procedure for every regular polygon : you give the number of sides and their length. The turn is always 360 divided by the number of sides.

TO POLYGON :N :SIDE
  REPEAT :N [ FD :SIDE RT 360 / :N ]
END

Try : POLYGON 3 100 (triangle), POLYGON 5 80 (pentagon), POLYGON 8 60 (octagon), POLYGON 36 12 (almost a circle).

octagon

POLYGON 8 70 : a regular octagon.

The star

By turning through a larger angle than for a polygon, the path crosses itself and forms a star :

TO STAR :SIDE
  REPEAT 5 [ FD :SIDE RT 144 ]
END
five-pointed star

REPEAT 5 [ FD 150 RT 144 ] : the five-pointed star.

The staircase

TO STEP :H
  FD :H RT 90 FD :H LT 90
END

TO STAIRS :N :H
  REPEAT :N [ STEP :H ]
END

Call STAIRS 6 30. Notice how STAIRS relies on STEP : you build a big program out of small bricks. That is the whole art of Logo programming.

staircase

STAIRS 6 30 : six steps.

Rosettes & spirals

The rosette of squares

You repeat a figure while turning it a little each time. Here, 12 squares spaced by 30 degrees (12 × 30 = 360, a full turn) :

TO SQUARE :C
  REPEAT 4 [ FD :C RT 90 ]
END

TO ROSETTE
  CS
  REPEAT 12 [ SQUARE 80 RT 30 ]
END
rosette of squares

ROSETTE : twelve squares turned by 30°.

The square spiral

On each turn, the side grows. We use REPCOUNT, which gives the number of the current iteration :

TO SPIRAL
  CS
  REPEAT 40 [ FD REPCOUNT * 5 RT 90 ]
END
square spiral

SPIRAL : the side grows on every turn.

The smooth spiral

By turning through an angle that is not a divisor of 360, you get a rounded spiral :

TO SPIRO
  CS
  REPEAT 100 [ FD REPCOUNT RT 59 ]
END
smooth spiral

SPIRO : a rosette made with a 59° angle.

The project: drawing a house

Here is a complete project, in the spirit of the Logo primer : you draw a house by assembling it from simple bricks, a square for the wall, a triangle for the roof.

TO WALL
  REPEAT 4 [ FD 80 RT 90 ]
END

TO ROOF
  REPEAT 3 [ FD 80 RT 120 ]
END

TO HOUSE
  CS
  WALL
  FD 80        ; go up to the top of the wall
  RT 30        ; orient for the roof
  ROOF
END

Call HOUSE. The secret is in the placement : after drawing the wall, the turtle is back at its start ; we send it up along the wall, tilt it by 30 degrees, and the roof lands right on top.

house

HOUSE : a square wall topped by a triangular roof.

Your turn : add a DOOR procedure and a WINDOW procedure, then call them from HOUSE. Remember to lift the pen (PU) to move the turtle without drawing, and to lower it (PD) before drawing.

A village

Once the wall and the roof are defined, you can line up several houses to make a row. For each house we draw the wall then the roof, come back to the foot of the wall, then lift the pen to shift to the right. We start far enough to the left so the whole row fits on screen :

TO VILLAGE :N
  CS
  PU LT 90 FD 220 RT 90 PD                 ; place the turtle on the left
  REPEAT :N [
    WALL  FD 80 RT 30 ROOF  LT 30 BK 80     ; one house (wall + roof)
    PU RT 90 FD 90 LT 90 PD                ; shift to the right
  ]
END

Call VILLAGE 5 for five houses side by side (up to five fit on screen).

row of houses

VILLAGE 5 : a row of houses with roofs.

Playing with colours

The rainbow fan

We change the pen colour on each spoke by using REPCOUNT as the colour code :

TO FAN
  CS
  REPEAT 15 [ SETPC REPCOUNT FD 120 BK 120 RT 24 ]
END
fan of colours

FAN : one spoke per palette colour.

The filled square

We draw a square, then fill it. SETFC chooses a fill colour distinct from the outline. FILL fills the area that contains the turtle : after drawing the square the turtle is back on a corner, that is on the line. So we must first bring it inside the square, otherwise the fill spills out instead of colouring the inside :

TO FILLEDSQUARE
  CS
  SETPC 7     ; white outline
  SETFC 1     ; red fill
  REPEAT 4 [ FD 80 RT 90 ]
  PU FD 40 RT 90 FD 40 PD   ; move inside the square
  FILL
END

Fractals: the power of recursion

A recursive procedure calls itself. It is the perfect tool for drawings that repeat at every scale.

The tree

A trunk, then two smaller branches, which split in turn, until the branches grow too short to continue.

TO TREE :T
  IF :T < 5 [ STOP ]      ; stop when the branch is too small
  FD :T
  LT 30 TREE :T * 0.7   ; left branch
  RT 60 TREE :T * 0.7   ; right branch
  LT 30
  BK :T                  ; back to the foot of the branch
END

TO DRAWTREE
  CS
  SETH 0
  BK 100
  TREE 60
END
fractal tree

DRAWTREE : each branch splits into two smaller ones.

Change the 0.7 (the shrink rate) or the angles to get very different trees.

The Koch snowflake

Each side of the snowflake is replaced by a broken line, itself made of smaller broken lines :

TO KOCH :L :N
  IF :N = 0 [ FD :L STOP ]
  KOCH :L / 3 :N - 1
  LT 60
  KOCH :L / 3 :N - 1
  RT 120
  KOCH :L / 3 :N - 1
  LT 60
  KOCH :L / 3 :N - 1
END

TO SNOWFLAKE :N
  CS
  REPEAT 3 [ KOCH 150 :N RT 120 ]
END
Koch snowflake

SNOWFLAKE 3 : each side is split three times over.

Call SNOWFLAKE 3. Try SNOWFLAKE 1, SNOWFLAKE 2, SNOWFLAKE 4 to watch the detail grow at each level.

Text & computation

The times table

TO TIMESTABLE :N
  FOR [ I 1 10 ] [
    ( PRINT :N "x :I "= :N * :I )
  ]
END

Call TIMESTABLE 7. The parenthesised form ( PRINT … ) lets you print several items on the same line, separated by a space.

Recursive countdown

TO COUNTDOWN :N
  IF :N = 0 [ PRINT "GO STOP ]
  PRINT :N
  COUNTDOWN :N - 1
END

Computing a factorial

A recursive operation that returns a result with OUTPUT :

TO FACT :N
  IF :N < 2 [ OUTPUT 1 ]
  OUTPUT :N * FACT :N - 1
END

Test it with PRINT FACT 5 (which prints 120).

A little dialogue

We ask the user for their name, then greet them :

TO HELLO
  READ [ WHAT IS YOUR NAME ] "NAME
  ( PRINT "HELLO :NAME )
END

Taking a word apart and back together

A word (a character string) is handled with a few basic primitives. A literal word is written with a leading quote : "CAT. Careful : square brackets [ ] make a list, not a word.

PRINT FIRST "CAT
PRINT LAST "CAT
PRINT BUTFIRST "CAT
PRINT COUNT "CAT
PRINT WORD "GOOD "BYE
PRINT UPPERCASE "cat

Prints in turn C (first character), T (last), AT (but-first), 3 (the number of characters), GOODBYE (the two words joined) and CAT.

Reversing a word

By taking the word apart character by character, we reverse it with recursion : we put the last character in front of the reversed rest. The base case is the empty word (").

TO BACKWARDS :WORD
  IF EMPTY? :WORD [ OUTPUT " ]
  OUTPUT WORD LAST :WORD BACKWARDS BUTLAST :WORD
END

PRINT BACKWARDS "HELLO prints OLLEH. (The REVERSE primitive does this directly.)

Counting the vowels

We count the vowels in the rest of the word, then add 1 if the first character is one. MEMBER? tests membership of the list of vowels :

TO COUNTVOWELS :WORD
  IF EMPTY? :WORD [ OUTPUT 0 ]
  LOCAL "REST
  MAKE "REST COUNTVOWELS BUTFIRST :WORD
  IF MEMBER? UPPERCASE FIRST :WORD [ A E I O U Y ] [ OUTPUT :REST + 1 ]
  OUTPUT :REST
END

PRINT COUNTVOWELS "EXTRAORDINARY prints 6.

The recursion trap : remember LOCAL. The MAKE command writes a global variable. Without the LOCAL "REST line, each recursive call would overwrite the :REST of the calls still waiting : on the way back we would read a corrupted value and the count would be wrong. Golden rule : every working variable of a recursive procedure must be declared LOCAL. The parameter :WORD, on the other hand, is already private to each call automatically.

Recognising a palindrome

A predicate (it returns TRUE or FALSE) : is the word equal to its reverse, ignoring case thanks to UPPERCASE ? It reuses the BACKWARDS procedure above.

TO PALINDROME? :WORD
  OUTPUT EQUAL? UPPERCASE :WORD BACKWARDS UPPERCASE :WORD
END

IF PALINDROME? "Level [ PRINT [LEVEL is a palindrome] ] prints the message.

Arrays & slices

An array is a row of numbered cells, like a set of lockers side by side. Unlike a list, you read or change any cell directly by its number, without going through the others : fast and handy whenever you know the number of items in advance (a game grid, a list of scores…). The first cell is number 1.

A slice is a piece cut out of a word, a list or an array : you give the start and end positions and get just that stretch — a bit like cutting a slice from a loaf of bread.

An array of cells

An array has numbered cells you read and change directly (unlike a list). Create it with ARRAY, store a value with SETITEM, read it back with ITEM.

TO SQUARES
  MAKE "T ARRAY 5
  FOR [ I 1 5 ] [ SETITEM :I :T :I * :I ]
  FOR [ I 1 5 ] [ PRINT ITEM :I :T ]
END

SQUARES stores the squares 1, 4, 9, 16, 25 then prints them. An array is shared : MAKE "U :T does not copy it, both names refer to the same array (for a real copy : COPYARRAY).

A two-dimensional grid

MDARRAY builds a multi-dimensional array, perfect for a game grid. You reach a cell by its list of indices [ row column ].

MAKE "G MDARRAY [ 3 3 ]
MDSETITEM [ 2 2 ] :G "X
PRINT MDITEM [ 2 2 ] :G

Prints X : cell (2, 2) of the grid.

A stack

A stack pushes and pops from the top (last in, first out), handy for traversals. PUSH and POP work on a variable holding a list. (For a queue : QUEUE / DEQUEUE.)

MAKE "P [ ]
PUSH "P 1
PUSH "P 2
PRINT POP "P

Prints 2 (the last pushed) ; only 1 remains on the stack.

Taking a slice

SLICE takes a piece of a word, a list or an array, from position start to end inclusive (the first position is 1). With a single number in parentheses, it runs to the end.

PRINT SLICE "hello 1 3
SHOW SLICE [ A B C D E ] 2 4
PRINT ( SLICE "hello 4 )

Prints hel, then [B C D], then lo.

Files

GoLogo can read and write text files on disk (in the working directory). The idea is always the same : you open a file, make it the “current stream”, and from then on the usual commands work on it instead of the screen or keyboard (PRINT writes to the file, READRAWLINE reads a line from it). Always finish with CLOSE.

Writing to a file

Open a file for writing and make it the current stream : from then on, PRINT writes to the file instead of the screen. An empty list [ ] reconnects the screen. Finish with CLOSE.

TO SAVE_SCORES
  OPENWRITE "SCORES.TXT
  SETWRITE "SCORES.TXT
  PRINT [ Alice 100 ]
  PRINT [ Bob 80 ]
  SETWRITE [ ]
  CLOSE "SCORES.TXT
END

Reading a file line by line

READRAWLINE outputs the next line ; EOF? tells whether anything is left. WHILE repeats to the end.

TO READ_SCORES
  OPENREAD "SCORES.TXT
  SETREAD "SCORES.TXT
  WHILE [ NOT EOF? ] [ PRINT READRAWLINE ]
  SETREAD [ ]
  CLOSE "SCORES.TXT
END

Prints the two lines written above.

Loading a whole file at once

Simpler still : FILETOARRAY loads a whole text file into an array, one line per cell (no need to open or close). COUNT gives the number of lines to iterate over.

TO SHOW_FILE
  MAKE "L FILETOARRAY "SCORES.TXT
  FOR [ I 1 COUNT :L ] [ PRINT ITEM :I :L ]
END

The command refuses a binary file (image, executable…) : it only reads text, so it never prints garbage.

Music

The scale

TO DOREMI
  PLAY [ DO RE MI FA SOL LA SI ]
END

A short tune

TO TUNE
  TEMPO 8
  PLAY [ DO DO DO RE MI ]
  PLAY [ RE DO MI RE RE DO ]
END

Drawing in time to music

You can mix graphics and sound : on each side of the polygon, play a note.

TO MUSICSQUARE
  CS
  FOREACH [ DO MI SOL DO ] [
    PLAY :?
    FD 80
    RT 90
  ]
END

Beyond these small examples, GoLogo ships with more complete programs (figures, rendered images, real little games). To learn how to list, load and try them, head over to getting started, section “Exploring the bundled examples”.

And now, it is your turn to invent your own programs. Happy Logo !