# Category Logo Programming Examples

#### One-a-Day: Space Tube Ride using TUBE and TUBEARC

Myrtle creates a 3D space tube ride for her to fly through…

Sometimes Myrtle needs to take a break and have a little fun! One of the things she can do is make a space tube and fly through it, using the TUBE and TUBEARC primitives:

TUBE makes a straight tube, and takes the parameters <radius> <depth> and <sides>. So, tube 20 10 10 makes a tube with a radius of 20 turtle units, a depth of 10 turtle units and 10 sides.

TUBEARC creates a curved tube, and takes the parameters <thickness> (the radius of the tube itself) <radius> (the radius of the arc itself) <sides> <totalsegments> and <arcsegments> – the last two are the total segments that would make up a complete torus, or donut, and the number of segments we actually want to create. So values of 20 and 10 will create a half-donut: tubearc 10 20 20 20 10

There are four procedures to our space tube program: createcourse, drawcourse, followcourse and spacetube.

createcourse generates the data that represents the tube’s course. It creates a course made up of 100 segments, represented by a word made up of a series of numbers between 0 and 4, where 0 represents a straight section of tube, and 1 to 4 represent four directions of turn. We use dountil to ensure we don’t repeat the same direction of turn more than once and end up looping back on ourself. Although, createcourse is not perfect and it is still possible for the course to cross over itself – but it’s a good thing tube walls aren’t solid!

drawcourse creates the graphical representation of the contents of the :course container we generated using createcourse. We use the twosided primitive to generate reflective “normals” on both sides of the shapes we generate from that point forward, and we use randfc to set a random ‘fill color’ or shape color for each segment as we create them.

We use foreach to step through each segment listed in the :course container, creating either a tube or a tubearc where appropriate.

While tubes are created directly under Myrtle, tubearcs are created around her, and so this means we need to do a bit of calisthenics to position the tubearcs where they need to go. Follow them through one command at a time to see how they work! We wait 2 / 60ths of a second between each segment creation so we can follow it.

followcourse causes Myrtle to fly through the created course, once again iterating through the :course container using foreach. fluid causes Myrtle to move forward smoothly, and to turn through the arcs we use a repeat. sleep is another form of wait, which takes milliseconds as a parameter instead of wait‘s 60ths of a second.

setpremodel allows us to ‘prepend’ commands to the turtle’s model, allowing us to make Myrtle look like she’s turning the appropriate way as she moves through the course.

Finally, spacetube puts it all together and is the procedure we execute to create the maze and fly through it. spacetube performs a reset, turns off the text layer, tells Snappy (the camera turtle) to pull away from Myrtle 1000 turtle units, tells Snappy to ‘follow’ Myrtle (turn to face her when she disappears from his view), then executes the createcourse procedure, the drawcourse procedure, sets the view (camera) turtle to Myrtle, turns Myrtle’s ‘light’ on (so we can see properly inside the tubes), turns Snappy’s light off, sets the camera ‘view point’ of Myrtle a bit up and behind her, and then executes followcourse.

```TO spacetube
reset
fullscreen
snappy:pullout 1000
createcourse
drawcourse
setview "myrtle
setlight 1
snappy:setlight 0
setviewpoint [0 10 -30]
followcourse
END

TO createcourse
make "course empty
make "last 5
repeat 100 [

dountil :last != :segment [make "segment random 5]

make "course word :course :segment
if :segment != 0 [make "last :segment]
]
END

TO drawcourse
nofluid
cs
pu twosided
foreach "segment :course [
randfc
if :segment = 0 [tube 50 200 20 lo 200]
else [rt :segment * 90
dn 90 rr 90 sl 100 tubearc 50 100 20 20 5 fd 100 rr 90 lt 180 + :segment * 90]
wait 2
]
home
END

TO followcourse
dn 90
fluid
foreach "segment :course [
if :segment = 0 [fd 200]
if :segment = 1 [setpremodel [rt 22.5] repeat 90 [fd 1.75 rt 1 sleep 1] setpremodel []]
if :segment = 2 [setpremodel [dn 22.5] repeat 90 [fd 1.75 dn 1 sleep 1] setpremodel []]
if :segment = 3 [setpremodel [lt 22.5] repeat 90 [fd 1.75 lt 1 sleep 1] setpremodel []]
if :segment = 4 [setpremodel [up 22.5] repeat 90 [fd 1.75 up 1 sleep 1] setpremodel []]
]
END

```

#### One-a-Day: Amiga Ball Bounce

The Commodore Amiga computer had a famous ‘bouncing ball’ demonstration program, a checkered bouncing ball. It was a bit different than this, but this is certainly reminiscent of it.

We love the Amiga demo so much that we created a special checkered ball primitive, AMIGABALL, and a second ‘oid’ primitive, AMIGABALLOID, which is used to create the ‘compressed’ ball.

Rather than turning the turtle into a ball (one method), this method ‘cleans’ the ‘turtle track’ after rendering each frame of the animation (which we wait for using the NEXTFRAME primitive).

The background voxel is actually an ‘inverted’ voxel, a voxel that is created using a negative size value. Due to the nature of OpenGL, only the insides of negative voxels are visible, which is why we can see inside it, and not see the face directly in front of us. Because we clean the ball each frame, we need to use a HATCHLING to create and hold the voxel in place. The hatchling just sleeps while the program runs.

The CAM: prefix directs the current view turtle (usually ‘Snappy’) to do things. You could also use SNAPPY: in this case but CAM: is shorter.

DOUNTIL PENCOLOR != FILLCOLOR [RANDFC] ensures that the ball has two different colors. The Amigaball(oid) uses both the pen and the fill colors in its construction, the only 3D primitive to do so.

To stop the ball from bouncing, press the Escape key.

```TO bounce
reset fs
penup lower 120 slideright 120 fd 120

hatch [randomfillcolor voxel -240 forever [wait 10]]
;create the cube, using a hatchling so it persists

cam:run [oup 10 ra 5]

home
setspheroidaxis 1
;stretch the spheroid on the vertical, default is horizontal
dn 90 rr 10
randpc dountil pencolor != fillcolor [randfc]
;set random pen and fill colors

forever [

repeat 14 [
amigaball 50 10 20
setx xpos - 1 lo 4 lt 2
nextframe clean
]
;move down

repeat 11 [
amigaballoid 50 10 20 1 - repcount / 20
lo 2 lt 2 nextframe clean
]
;compress ball

randpc dountil pencolor != fillcolor [randfc]
;change colors

repeat 11 [
amigaballoid 50 10 20 0.375 + repcount / 20
ra 2 lt 2 nextframe clean
]
;expand ball

repeat 28 [
amigaball 50 10 20
setx xpos + 1 ra 4 lt 2
nextframe clean
]
;move up

repeat 11 [
amigaballoid 50 10 20 1 - repcount / 20
ra 2 lt 2 nextframe clean
]
;compress ball

randpc dountil pencolor != fillcolor [randfc]
;change colors

repeat 11 [
amigaballoid 50 10 20 0.375 + repcount / 20
lo 2 lt 2 nextframe clean
]
;expand ball

repeat 14 [
amigaball 50 10 20 setx xpos - 1
lo 4 lt 2 nextframe clean
]
;move back to center
]
END

```

#### One-a-Day: FRAG

The FRAG primitive creates a filled shape out of the current turtle position and her last two positions. For example:

FD 100 RT 90 FD 100 FRAG

will create a triangle.

While turtleSpaces has a variety of shape primitives, sometimes you need to create an arbitrary shape, and FRAG aids you in this.

Take this example, which draws a star:

```TO star
repeat 4 [
forward 100
right 170
forward 86
frag
left 70
forward 86
right 170
forward 100
frag
right 180
]
```

We can change the number of sides the star has by changing the number of repeats and fiddling with the values a bit:

```TO star2
repeat 5 [
fd 100 rt 170
fd 86 frag
lt 88 fd 86
rt 170 fd 100
frag rt 180
]
END
```

First, let’s change our star procedures so they can take a :size parameter, like so:

```TO star1 :size
repeat 4 [
fd 100 * :size
rt 170
fd 86 * :size
frag
lt 70
fd 86 * :size
rt 170
fd 100 * :size
frag
rt 180
]
END
```

In this case, :size is a ratio, that is, 0.5 will make a star half the size, and 2 will make a star twice the size of the default.

You can change the color of the star using the SETFILLCOLOR primitive, or set a random fill color with RANDFC.

The following procedures create a sky full of stars:

```TO star1 :size
repeat 4 [
fd 100 * :size
rt 170
fd 86 * :size
frag
lt 70
fd 86 * :size
rt 170
fd 100 * :size
frag
rt 180
]
END

TO star2 :size
repeat 5 [fd 100 * :size rt 170 fd 86 * :size frag lt 88 fd 86 * :size rt 170 fd 100 * :size frag rt 180]
END

TO star3 :size
repeat 6 [fd 100 * :size rt 170 fd 86 * :size frag lt 100 fd 86 * :size rt 170 fd 100 * :size frag rt 180]
END

TO star4 :size
repeat 7 [fd 100 * :size rt 170 fd 86 * :size frag lt 108.625 fd 86 * :size rt 170 fd 100 * :size frag rt 180]
END

TO star5 :size
repeat 8 [fd 100 * :size rt 170 fd 86 * :size frag lt 115 fd 86 * :size rt 170 fd 100 * :size frag rt 180]
END

TO stars
reset cam:setposition [0 0 0]
cam:fixate [0 0 0]
cam:setviewpoint [0 0 0]
cam:newworker [forever [up 0.1 lt 0.1 rr 0.1 wait 1]]
repeat 200 [
pu home randori fd 400 + random 1000 up 90
lt random 60 pd randpc randfc randfs randps
make "size (10 + random 90) / 100
run {pick [star1 star2 star3 star4 star5] :size}
]

END

```

Type STARS and press Enter to see the stars!

FRAG’s sister, SHARD creates a three-dimensional FRAG with depth beneath it. This depth is supplied as a parameter, in turtle-units, eg. SHARD 5. Try replacing FRAG with SHARD 5 in one of your star procedures and see what happens! (You’ll need to drag the camera around to see the sides of the star)

#### Quick Play: Warped Logo Spirals

One of the best things about turtleSpaces is its capacity for discovery through play.

Today I was playing with spirals:

I started off by creating a simple spiral using the RARC primitive and a simple REPEAT loop. This loop uses REPCOUNT (the current repeat loop iteration) to define the radius of the arc, resulting in an ever-growing spiral.

I clicked and dragged on the window to rotate the camera around the spiral. But let’s make the spiral itself three-dimensional:

I’ve ‘warped’ the spiral by placing three rarcs inside of the repeat loop, along with a ROLLLEFT (rl) and a ROLLRIGHT (rr). With the twisting and turning, the turtle ends up roughly halfway around a somewhat distorted circle, which you can see if you type:

```cs rarc 90 20 rr 90 rarc 90 20 rl 90 rarc 90 20

cs repeat 2 [rarc 90 20 rr 90 rarc 90 20 rl 90 rarc 90 20]```

If we orbit the camera (by clicking and dragging) around our spiral, we can see just how warped it is!

What else can we do with it?

Whoa! What happened there? I added a dn (down) 10 to the end of the loop. Let’s take a look from another vantage point:

That’s pretty distorted. Let’s try a smaller value, say 2:

Okay, pretty neat. How about if at the end of each loop we also roll left (rl) a little?

Another angle:

Let’s play around with the values of down (dn) and rollleft (rl) a bit:

What if we do a right turn (rt) instead of a roll right (rr)?

And what if we add the roll back in?

Let’s play around with the values a bit:

All right, that’s enough from me! But you can play around with the different values and see what happens. That’s all part of the fun of turtleSpaces!

#### Make it Rain!

```TO rain

reset

penup hideturtle
fullscreen
make "count 0

forever [

inc "count
setposition {-300 + random 600 300 -300 + random 600}
make "size 0.25 + ((1 + random 20) / 20)

begintag "teardrop
setfillcolor pick [2 3 6 7 14]

up 90
cutsphere 10 * :size 20 20 1 13
lower 4.5 * :size
cone 8.9 * :size 18 * :size 20
down 90
;raindrop

endtag

newmodel :count "teardrop
clean

hatch [
setmodel :count
showturtle
make "speed (5 + random 10) / 10
while ypos > -300 [
back :speed rollright 0.25
]
]

wait 5 + random 25
]

END
```

#### ‘Snake’ written in turtleSpaces Logo

```TO snake

;setup:

reset
;empties (erases) all containers (variables),
;returns the turtles to their default positions,
;restores their states to defaults

release
;sets all the turtles, except for the default ones
;(myrtle, snappy, libby) 'free' - erasing them

penup
;don't draw

setbackgroundcolor lightblue

hideturtle
;don't show the executing turtle (typically myrtle)

stealth
;don't show up in output from the near primitive

noaudiowait
;don't delay when playing sounds (the default)

print |Use keys J and K to turn snake, eat apples!|
;print instructions to the screen

;create the 'ground'
setfillcolor brown
setpos [-185 -115]
lower 5
quad 185 * 2 115 * 2

make "score 0
make "length 8
;the default snake length, in segments

make "queue empty
;this snake implementation uses a push / pull queue
;to keep track of the snake's turns

repeat :length [push "fd "queue]
;all segments start moving forward

newmodel "ball [setfillcolor 12 icosphere 5]
newmodel "head [setfillcolor 4 icosphere 6]
newmodel "apple [setfillcolor red icosphere 4]
;create turtle models, where ball is a non-head segment

;create the turtles that make up the starting snake:
repeat :length [
nameturtle repcount
;create a new turtle
;each segment has the number of its segment as its name

control repcount {"wrap "penup "back repcount "* 10 "showturtle}
;initialize the new turtle and move it into position
;{} denotes a 'softlist', a list whose contents are evaluated
;at execution

control repcount [
setbounds [-185 -115 185 115]
]
;sets the bounds used for wrapping. [] denotes a 'hardlist', a
;list whose contents are fixed and not evaluated

if repcount = 1 [control 1 [setmodel "head]]
;if this is the first segment, give it the 'head' model
else [control repcount [setmodel "ball]]
;otherwise, give it the 'ball' (segment) model
]

;set up the 'apple' turtle:
nameturtle "apple
control "apple [
penup setmodel "apple showturtle

dountil (count near position 5) = 1 [
setpos {-180 + (10 * random 36) -100 + (10 * random 20)}
]
]
;set a random position until such times as the apple is not near
;any snake segments (turtles)

;leading parameters used in comparison operators (=, >, < etc)
;must be enclosed in {}'s if more than a single value or primitive
;because the parser evaluates right to left

;the main loop:

forever [
norender
;don't render while we shuffle the snake forward

for {"i 1 :length} [
make "move item :i :queue
;set the move variable to the :i item in the :queue

switch "move
case "fd [ask :i [forward 10]]
case "rt [ask :i [right 90 forward 10]]
case "lt [ask :i [left 90 forward 10]]
;switch / case statements execute instructions based on the
;contents of the container (variable) provided to switch

;ask creates a new worker that executes the commands using
;the specified turtle (the turtle named by :i)
;so, in this for loop we are iterating through the :queue,
;moving the turtle segments based on the item present in
;each space in the queue (fd, rt or lt)
]
while workers != [] [sleep 1]
;sleep execution until the ask workers finish moving their
;turtles (the snake). This way, when we enable the render,
;we won't catch the snake mid-move.

render
;enable rendering again

wait 40 - :score
;wait units are 60ths of a second. The higher the score, the
;shorter the wait will be

;user control:
if keyp [
;did the user press a key? If so, do this stuff:

;take the output from the readchar primitive and place it
;into the input container. keyp indicates if there is a character
;is no character in the buffer, it waits.

switch "input
case "j [push "lt "queue]
;if the user pressed the j key, push lt to the front of the queue
case "k [push "rt "queue]
;if the user pressed the k key, push rt to the front of the queue
otherwise [push "fd "queue]
;if no case has been satisfied since switch (the user pressed a key
;other than j or k), push fd to the front of the queue
]
else [push "fd "queue]
;similarly, if the user hasn't pressed any key, push fd to the front
;of the queue

ignore dequeue "queue
;ignore (drop) the last value off the end of the :queue
;dequeue would ordinarily return this value, ignore sends it into
;the ether

;is there something occupying the same space as the head of the snake?
if (count (near 1:position 5)) > 1 [
;near returns the names of the turtles within the specified distance (5)
;count returns the count of the number of turtles returned by near
;if there is more than one (the head itself), we will execute the following:

if memberp "apple near 1:position 5 [
;is it an apple?

playsound "chomp
inc "score
;increment the value in the score container by one

(print |Yum! Score:| :score)
;to pass more than the default number of parameters to a primitive, wrap
;it in parentheses (round brackets)

dountil (count near apple:position 5) = 1 [
control "apple [setpos {-180 + (10 * random 36) -100 + (10 * random 20)}]
]
;place a new apple

repeat 2 + int (:score / 10) [

queue "pa "queue
;a pa or 'pass' will cause these new segments not to move on the next
;iteration, until movement commands are 'shuffled' on to their places
;in the queue

inc "length
;increment the value of the length container by one

nameturtle :length
;create a new turtle with the name contained in :length (the new length)

(control :length {"hideturtle "setmodel ""ball "wrap "penup "setpos
"query :length - 1 leftbracket "position rightbracket "setvectors
"query :length - 1 leftbracket "vectors rightbracket})
;set up the new turtle and make sure it's positioned next to the
;previously last turtle, and is facing in the same direction

control :length [setbounds [-185 -115 185 115] showturtle]
;set the bounds of the new turtle and show it

wait 10
]
;add new segment to the snake

]

;and if it's not an apple?
else [
print "crash! playsound "crash finish
]
;game over, man! game over!
]
]
END
```

#### Example: Spiral Tunnels

```TO spiraltunnelanimation
reset fullscreen
setbackgroundcolor 0
dropanchor penup
raise 190 pullout 50

repeat 2100 [
setfillshade -15 + int (repcount / 65)

setfillcolor (item 1 + remainder int (repcount / 2.35) 8
{red orange yellow green lightgreen cyan blue magenta})

voxeloid 7 12 20

orbitleft 10.1 lower 0.6
]

home lower 3000
setmodelscale 2.5
down 90 right 180
make "dir 0
snappy:setanchor [0 0 -1050]

forever [
forward 2 rollright 0.1
if zpos > 1500 [setz -3000]
snappy:rollleft 0.05 snappy:pullin 0.1

if and :dir = 0 snappy:orbitdistance = 0 [
make "dir 1
snappy:right 180
setbackgroundcolor 15
snappy:setanchor [0 0 180]
]

if and :dir = 1 snappy:orbitdistance = 0 [
make "dir 0
snappy:right 180
setbackgroundcolor 0
snappy:setanchor [0 0 -1050]
]
]
END
```

#### Examples: Turtle Art

Logo is great for creating art! And 3D Logo makes it even better.

Many of these Logo artworks were inspired by examples created by Seymour Papert’s daughter Artemis Papert using the two-dimensional block-based TurtleArt application developed by LCSI Logo developer Brian Silverman. We’re grateful for both of their efforts in advancing Logo over the past several decades!

```TO adobo
reset setpenwidth 5 definecolor 16 [0 0 0]
setpc 16 setbg 1 setbs 12 pu
repeat 9 [
repeat 10 [
setpos {-120 + 20 * repcount -120 + 20 * repabove 1}
setz -2 + 0.01 * random 400
setfc pick [8 9 13]
setfs -13 + random 10
square 40 box 40
]
]
END
```

```TO brush
reset setbg 8
setpenwidth 5 setbs 11

repeat 300 [
setpc pick [1 8 9 11]
setps -10 + random 20
pu
setpos {-200 + random 400 -100 + random 200}
rt random 360 pd
repeat 20 + random 50 [
make "stroke 30 + random 150
fd :stroke rt -0.5 + 0.1 * random 10
bk :stroke + random 2 lt -0.5 + 0.1 * random 10
]
ra 0.01
]
END
```

```TO bundles
reset randbg
repeat 40 [
pu setpos {-200 + random 400 -100 + random 200}
setpenwidth 4  pd
lt random 360
repeat 2 [
randpc
repeat 90 [
make "stroke 50 + random 5
setps -10 + random 20
fd :stroke
bk 2 * :stroke
fd :stroke
rt 0.1 * random 20
up -2 + (0.1 * random 40)]
]
]
END
```

```TO burst
reset  pu
make "colors {yellow orange red magenta blue}
repeat 5 [
setpc item repcount :colors
setmarkerwidth repcount
make "count repcount
repeat 50 [
rt random 360 mark :count * (20 + random 10)
setpos [0 0]] lo repcount
]
END
```

```TO caduceus
reset  setpenwidth 5 pu
repeat 4 [
setpc item repcount [13 9 1 8]
ra repcount * 2
bk 120 pd
repeat 100 [
fd 1.4 + 0.1 * repabove 1
rt 7.5 * sin 270 + 10 * repcount
]
repeat 75 [
fd 2.5 + 0.5 * repabove 1
lt 0.5 * repcount
]
pu home rr 180 * repcount
]
END
```

```TO cards
reset  pu
repeat 1000 [
setpos {-200 + random 400 -100 + random 200}
rt random 360
make "sizex 10 + random 20
make "sizey 10 + random 20
setfc 2 setfs 13
quad :sizex + 2 :sizey + 2
sr 1 fd 1 ra 0.01
setfc pick [2 3 7 14]
setfs -5 + random 10
ra 0.01
]
END
```

```TO citylights
reset pu  setbg 2 setbs 10
repeat 200 [
setpos {-200 + random 400 -100 + random 200}
rt random 360 make "size 20 + random 50
setfc pick [1 9 13 7] lo 0.01
until :size = 0 [
randfs spot 0.05 * :size
fd 5 lo 0.01 dec "size
]
]
END
```

```TO dotcube
cs seticosphereiterations 1 pu
repeat 9 [
repeat 9 [
repeat 9 [
setposition {-100 + 20 * repabove 2 -100 + 20 * repabove 1 -100 + 20 * repcount}
setfc repabove 1 setfs repcount ico 2
]
]
]
END
```

```TO dotspiral
Reset setbg 13 setfc 9 cs
repeat 1400 [
pu fd repcount / 10
spot repcount / 250
rt 35
]
END
```

```TO fireworks
cs setpenwidth 5
repeat 60 [
pu home
rt random 360
randpc pd
fd 30 + random 50
repeat 50 [
run pick [[pu][pd]]
fd 2]
]
END
```

```TO fish
reset wrap
setbounds [-180 -120 180 120]
setbg 1 setbs 12
pu setpos [-170 75]
repeat 12 [
setpenwidth 4 rt 44.5
repeat 10 [
sl 1
repeat 3 [
setpc item repcount [13 1 13]
if repcount = 2 [ra 0.2]
if repcount = 3 [lo 0.2]
pd fd 50 pu bk 50 pu sr 1
]
sl 2 rt 10
]
setfc 1 ico 1 st
lt 54.5 sr 13 fd 60
lt 90
]
END
```

```TO gaia
reset setbg 2 setpenwidth 5  setpc 1
repeat 5 [
setpc item repcount [8 1 9 13 15]
setorigin {0 0 2 * repcount}
repeat 20 [
pu home pd rt repcount * 18
repeat 80 [
fd 0.9 + ((repabove 2) * 0.1)
rt 8 * sin (repcount * 8)
]
lt 7.5
repeat 5 [
fd 20 pu bk 20 rt 15 pd
]
]
]
END
```

```TO gradient
cs pu
repeat 30 [
setfs -15 + repcount quad repcount 200 lo 0.01 sl 0.5
]
END
```

```TO gridart
reset
randbg
randfc
pu

setpos [-210 113]
repeat 31 [
for [i 1 57] [
spot 3.5 * sin ((:i + repcount) * 2)
sr 7.5
]
sl 57 * 7.5
bk 7.5
]
END
```

```TO gridartico
cs
seticosphereiterations 1
pu

setpos [-210 113]
repeat 31 [
for [i 1 57] [
ico 3.5 * sin ((:i + repcount) * 2)
sr 7.5
]
sl 57 * 7.5
bk 7.5
]
END
```

```TO gridartshade
reset randbg randfc pu
setpos [-210 113]
repeat 31 [
for [i 1 57] [
setfs int (10 * (sin ((:i + repcount) * 2)))
spot 3.5
sr 7.5
]
sl 57 * 7.5 bk 7.5
]
END
```

```TO gridartwave :size
cs
seticosphereiterations 1
pu

setpos [-210 113]
repeat 31 [
for [i 1 57] [
make "sin 3.5 * sin ((:i + repcount) * 2)
ra :size * :sin
ico :sin
lo :size * :sin
sr 7.5]
sl 57 * 7.5
bk 7.5
]
END
```

```TO guessing
Reset setspeed 5 setbg 9 setbs 3 setpenwidth 5
repeat 8 [
pu home ra repcount rt repcount * 45 pd
repeat 22 [
if repcount < 4 [
setpc 8 setps 9 - (3 * repcount)] [
setpc 13 setps (penshade - 1) + random 3
]
repeat 360 [fd 1 - (0.015 * repabove 1) rt 1]
pu sr 0.02 pd
]
]
END
```

```TO heat
cs pu
repeat 10 [
setfc pick [1 9 13]
setpos {-170 + (repcount * 30) -120}
up 90
repeat 80 [
cylinder 0.1 * repcount 1.6 10
sr sin (repcount * 10)
lo 1.5
]
repeat 80 [
cylinder 0.1 * (80 - repcount) 1.6 10
sr sin ((80 + repcount) * 10)
lo 1.5
]
dn 90
]
END
```

```TO heat2
cs pu
repeat 10 [
setfc pick [1 9 13]
setpos {-170 + (repcount * 30) -120}
up 90
repeat 80 [
cylinder 0.1 * repcount 1.6 10
sr sin (repcount * 10)
lo 1.5
]
repeat 80 [
cylinder 0.1 * (80 - repcount) 1.6 10
sr sin ((80 + repcount) * 10)
lo 1.5
]
dn 90 rr 180
]
END
```

```TO hedgehog
reset  setfc 1 pu ra 1 spot 20 setpc 13
repeat 36 [
home dropanchor tether pullout 18
orbitleft repcount * 10 rt 225
setmarkerwidth 0.1 * random 20
mark 30 + random 80
]
END
```

```TO funnybird :col1 :col2
rl 90 setfc :col1 icospheroid 20 0.5
pu rr 90 fd 5 sr 12 lt 30
cylindroidarc 10 15 20 30 10 0.3
fd 10 sr 15 ra 2
setfc :col2 ico 3 lo 3.5 ico 3 ra 1.75
bk 10 dn 90 lt 90
domoid 10 8 20 0.3 fd 30 sl 7 rt 90
icospheroid 8 2 fd 14
icospheroid 8 2 bk 7 rr 30 rr 10 up 10
cylinder 2 35 20 lo 40 rr 180 lt 90 dn 10
domoid 7 10 10 0.5 oval 3.5 7 up 10 rt 90
rl 180 ra 35 dn 20 rl 20
cylinder 2 35 20 lo 40 rr 180 lt 90 up 10
domoid 7 10 10 0.5 oval 3.5 7
END

TO hiding
reset setpenwidth 5 pu
sl 30 funnybird 1 9 home
ra 20 rr 180 sl 30 up 10
funnybird 13 8 rl 180 fd 20
sr 20 spot 100 sl 40 up 90
rl 90 sl 60 pd setpc 13
pushturtle
repeat 50 [
popturtle
pushturtle
pu sr repcount * 2
pd lt -10 + random 30
setpc pick [8 9 13]
setfs -10 + random 20
raise -2 + random 6
repeat 70 + random 30 [fd 1 rt 0.7]
]
ht
END
```

```TO icicles
reset pu up 90
repeat 20 [
setpos {-210 + (20 * repcount) 115}
make "size 20 + random 15 randfc
repeat :size [
cylinder 0.2 * (:size - repcount) 0.6 + (:size / 5) 20
ra 0.5 + (:size / 5)
]
]
END
```

```TO moon
reset lt 120
repeat 180 [fd 1 rt 1]
rt 150
repeat 180 [fd 0.774 lt 0.676]
pu fd 30 pd
repeat 3 [
repeat 5 [
fd 20 bk 40 fd 20 rt 36
]
pu rt 180 sl 40 fd 40 pd
]
ht
END
```

```TO needles
reset
repeat 5 [
repeat 10 [
pu setpos {-240 + 80 * repabove 1 126 - repcount * 23}
pushturtle rr 90 up -15 + random 30 randfc
cylinder 1 30 10 rr 180 cylinder 1 30 10 popturtle
]
]
END
```

```TO nest
reset setspeed 1
repeat 3 [
setpc item repcount [9 8 4]
repeat 18 [
pu home raise 2 * repabove 1
rt 7 * repabove 1 rt repcount * 20
setps -5 up 10 pd
mark 50 + 2 * repabove 1
repeat 4 [
repeat 90 [
pu bk 0.1 pd mark 0.2 + 0.1 * repabove 1
rt 2 up 1
]
repeat 90 [
pu bk 0.1 pd
mark 0.2 + 0.1 * repabove 1
lt 2 up 1
]
]
]
]
setfc 7 pu home ra 17 icospheroid 10 2 ht
END
```

```TO notnot
reset pu sl 10 lt 40 setpc 15 setbg 1
setmarkerwidth 10 repeat 360 [
mark 1.1 bk 0.1 lt 1
]
lt 90 mark 115 home sr 90 fd 25 rt 40
repeat 360 [
mark 0.8 bk 0.1 lt 1
]
lt 90 mark 80
END
```

```TO orangepeel
reset setpenwidth 8 setbs 3
setbg 13 setpc 9 setps 0
repeat 5 [
pu home
setpos {-240 + repcount * 50 113}
rt 100
repeat 10 [
sr 1.5 fd 1 pd setps -5 + repcount
repeat 100 [
if divisorp 10 repcount [
]
fd 2.75 rt repcount
] lt 10
]
]
END
```

```TO patio
cs pu setpos [-87.5 85] setfc 13
repeat 5 [
repeat 6 [
make "offset random 10
lt 50 - :offset
polyspot 20 4
rt 50 - :offset
sr 35
]
sl 210 bk 35
]
END
```

```TO peaks
reset  ht pu bk 125 setbg 2
repeat 3 [
setfs 0 setfc 13
fiso 100 250
setfc 7 setfs repcount * 3
ra 0.1
fiso 75 200
sl 120 lo 50 bk 30
]
home bk 125 sr 120 lo 50 bk 30
repeat 2 [
setfc 13 setfs 0 fiso 100 250
setfs 3 + repcount * 3
setfc 7 ra 0.1 fiso 75 200
sr 120 lo 50 bk 30
]
setpenwidth 5 home setpos [140 80]
setpc 13
repeat 36 [
pd fd 35 pu bk 35 rt 10
]
END
```

```TO pinwheel
reset twosided
pu setbg 2
setfc 14 setpc 7
repeat 2 [
setpc item repcount [7 11]
setfc item repcount [14 13]
pu home rt repcount * 45
bk 10
repeat 100 [
fd 40 + repcount * 1.2
lt 90 fd 10 lt 92 fd 10
frag lt 90
]
]
END
```

```TO postits
reset pu
repeat 10 [
repeat 10 [
setpos {-120 + 20 * repcount -120 + 20 * repabove 1}
randfc
square 20 ra 0.1
]
]
END
```

```TO rainbow
reset setpenwidth 10  pu sl 225 bk 125 lt 10 pd
repeat 500 [
foreach "col {red orange yellow green blue lightblue magenta} [
setpc :col fd 0.5 * (0.1 * (10 + repcount))
]
pu bk (0.5 * (7 * (0.1 * (10 + repcount))))
sr 1 fd 0.2 * (sin (0.5 * (repcount + 100)))
pd
]
END
```

```TO redonpink
reset setpc 1 setbg 11 setbs -5
pu setfc 1
repeat 1000 [
setpos {-220 + random 440 -120 + random 240}
ra 0.001 setfo 50 setfs -15 + random 10
spot 5 + random 5
]
setorigin [-50 -30 2]
repeat 16 [
setmarkerwidth 3 home dropanchor
pullout 10 orbitleft repcount * 22.5
rt 180
repeat 70 [
setmarkerwidth markerwidth - 0.02
bk 0.1 mark 1 rt 2
]
repeat 70 [
setmarkerwidth markerwidth - 0.02
bk 0.1 mark 2 lt 2
]
]
END
```

```TO roses
reset setpenwidth 5
repeat 3 [
pu setpos {-190 + (repcount * repcount) * 30 -90 + repcount * 50}
pd make "size 0.05 * (repcount / 2)
setpc item repcount [1 9 13]
repeat 9 [
repeat 100 [
fd repcount *  :size rt 10
]
]
]
END
```

```TO slats
reset
setorigin [-260 -120]
repeat 23 [
pu setps -7 + repcount
home sr 20 * repcount
setmarkerwidth 18 rt 10
mark 250
]
END
```

```TO slats2
reset
setorigin [-260 -120]
repeat 23 [
pu setps -7 + repcount
home setpc pick [8 9 13]
sr 20 * repcount
setmarkerwidth 18 rt 10
mark 250
]
END
```

```TO snake
CS PU RANDFC
BK 110 UP 90
repeat 80 [
cylinder 0.1 * repcount 1.6 10
sr sin (repcount * 10)
lo 1.5
]
repeat 60 [
cylinder 0.1 * (80 - repcount) 1.6 10
sr sin ((80 + repcount) * 10)
lo 1.5
]
DN 90 RT 60 ICOSPHEROID 5 2 SL 7 FD 3
RANDFC ICO 1 BK 6 ICO 1 HT
END
```

```TO snakes
CS PU RANDFC
repeat 10 [
home setpos {-170 + (repcount * 30) -110}
up 90 repeat 80 [
cylinder 0.1 * repcount 1.6 10 sr sin (repcount * 10) lo 1.5
]
repeat 60 [
cylinder 0.1 * (80 - repcount) 1.6 10
sr sin ((80 + repcount) * 10) lo 1.5
]
DN 90 RT 60 ICOSPHEROID 5 2 SL 7 FD 3
RANDFC ICO 1 BK 6 ICO 1
]
HT
END
```

```TO solar
reset  repeat 5 [
setpc item repcount [1 8 9 13 15]
repeat 18 [
pu home raise 2 * repabove 1
rt repabove 1 rt repcount * 20
setps 0 pd mark 50
repeat 5 [
repeat 90 [
mark 0.2 + 0.1 * repabove 1 rt 2
]
repeat 90 [
mark 0.2 + 0.1 * repabove 1 lt 2
]
]
]
]
END
```

```TO solar2
reset setspeed 5
repeat 5 [
setpc item repcount [1 8 9 13 15]
repeat 18 [
pu home raise 2 * repabove 1
rt 3 * repabove 1
rt repcount * 20
setps 0 pd
mark 50
repeat 5 [
repeat 90 [
mark 0.2 + 0.1 * repabove 1 rt 2
]
repeat 90 [
mark 0.2 + 0.1 * repabove 1 lt 2
]
]
]
]
END
```

```TO solar3
reset           setspeed 5
repeat 5 [
setpc item repcount [1 8 9 13 15]
repeat 18 [
pu home raise 2 * repabove 1
rt 4 * repabove 1
rt repcount * 20 setps 0
pd mark 50
repeat 5 [
repeat 90 [
mark 0.2 + 0.1 * repabove 1
rt 2
]
repeat 90 [
mark 0.2 + 0.1 * repabove 1 lt 2
]
]
]
]
END
```

```TO sparks
reset setpenwidth random 10
randbs randbg
repeat 5 [
pu setposition {-200 + random 400 -100 + random 200 -100 + random 100}
setorigin position randpc randps
repeat 30 [
rt random 360 pd
while (and xpos < 300 xpos > -300 ypos < 180 ypos > -180) [fd 1 lt 0.2]
pu home
]
]
END
```

```TO spiralart
reset
snappy:pullin 100
pu
randbg
sl 40
rr 90
bk 10
repeat 2 [
randfc
repeat 2800 [
tube 2 repcount / 400 6
lo repcount / 500
up 2
]
pu home
fd 10 sr 40 rl 90
]
ht
END
```

```TO spirallights
reset  setpenwidth 5
repeat 5 [
make "ypos 130 - (40 * repcount)
randpc
repeat 10 [
pu setpos {-220 + (40 * repcount) :ypos}
pd
repeat 100 [
setps -10 + int (repcount / 5)
fd repcount / 10 rt 30
]
]
]
END
```

```TO spirallightsorange
reset  setbg 8
setbs 13 setpenwidth 5
repeat 5 [
make "ypos 130 - (40 * repcount)
repeat 10 [
pu setpc pick [1 8 9 13]
setpos {-220 + (40 * repcount) :ypos}
pd
repeat 100 [
setps -10 + int (repcount / 5)
fd repcount / 10
rt 30
]
]
]
END
```

```TO spirallightsorange3d
reset  setbg 8 setbs 13
setpenwidth 5
repeat 5 [
make "ypos 130 - (40 * repcount)
repeat 10 [
pu setpc pick [1 8 9 13]
setposition {-220 + (40 * repcount) :ypos 0}
pd
repeat 100 [
setps -10 + int (repcount / 5)
fd repcount / 10 rt 30 dn 2
]
]
]
END
```

```TO splash
reset setspeed 5 setpenwidth 5
repeat 144 [
pu home rt repcount * 2.5 dn 75 pd
repeat 400 [
up 5 * (sin (repcount * 4))
setps -15 + (repcount / 12)
fd .4
]
]
pu home
END
```

```TO splash2
reset setspeed 5 setpenwidth 5
repeat 144 [
pu home rt repcount * 2.5 dn 75 pd
repeat 400 [
up 5 * (sin (repcount * 4))
rt sin repcount
setps -15 + (repcount / 12)
fd .4
]
]
pu home
END
```

```TO splash3
reset setspeed 5 setpenwidth 5
repeat 144 [
pu home rt repcount * 2.5 dn 75 pd
repeat 400 [
up 5 * (sin (repcount * 4))
rt sin repcount
rr sin repcount
setps -15 + (repcount / 12)
fd .4]
]
pu home
END
```

```TO splash4
reset setspeed 5 setpenwidth 5 setpc 1
repeat 144 [
pu home rt repcount * 2.5 dn 75 pd
repeat 400 [
up 5 * (sin (repcount * 4))
rt sin repcount
rr sin repcount * 2
setps -15 + (repcount / 12)
fd .4]
]
pu home
END
```

```TO spotwave
cs  pu
repeat 32 [
setpos {-220 205 - (repcount * 10)}
repeat 45 [
setfc pick [2 3 5 6 7 10 14 15]
spot 5 sr 10
fd -2 + sin (repcount * 10)
]
]
END
```

```TO stickman :size
lt 45 setmarkerwidth :size / 3
repeat 2 [
lt 90 mark :size * 5 spot :size
bk :size * 5] lt 135 mark :size * 2
lt 45 repeat 2 [
mark :size * 5 spot :size bk :size * 5 rt 90
]
lt 135 mark :size * 5
spot :size * 2 pu bk :size * 10
END

TO stickmen
reset pu sl 80 fd 20
repeat 3 [
randfc setpc fillcolor
stickman repcount * 3
pu sr 80 ra 20
]
END
```

```TO stormy
reset  pu setpos [-230 -120]
repeat 8 [
setpc item repcount [2 6 7 14 1 8 9 13]
repeat 160 [
pushturtle rt 45 bk random 20
randps mark 50 + random 20
popturtle pu
sr 2.5 + random 5 ra 0.01
]
ra 0.1 pu
setpos {-230 -120 + repcount * 30}
]
END
```

```TO swirl
reset pu bk 20 sr 40 setpc 1
setbg 13 setbs -10 setorigin position pd
repeat 12 [
repeat 30 [
setropewidth 6.1 - (repcount / 5)
rope 4 bk 0.2 rt 6 bk 0.2
]
pu home rt repcount * 30 pd
]
ht
END
```

```TO thicket3
reset  setbg 2 setpenwidth 5  setpc 1
repeat 8 [
setpc item repcount [8 1 9 4 12 13 14 15]
repeat 20 [
pu setposition {-200 + (repcount * 20) 0 5 + repabove 1}
up 25 pd
repeat 80 [
fd 0.9 + ((repabove 2) * 0.1)
rt 8 * sin (repcount * 8)
]
lt 7.5
repeat 5 [
fd 20 pu bk 20 rt 15 pd
]
]
]
END
```

```TO twomoons
reset
setorigin [-23 -23 0]
repeat 2 [
setpc item repcount [7 2]
repeat 36 [
pu home dropanchor
pullout 10 * repabove 1
orbitleft repcount * 10
rt 180 pd
if oddp repcount [fd 40 * repabove 1] [fd 20 * repabove 1]
]
setorigin [30 30 -20]
]
END
```

```TO vase
reset setpenwidth 5  pu fd 50 sl 50 pd rt 135
repeat 40 [fd 1 rt 2]
repeat 125 [fd 1 lt 1]
lt 5 quad 80 220 rt 180 rr 180
quad 80 220 rr 180 rt 185
repeat 125 [fd 1 lt 1]
repeat 40 [fd 1 rt 2]
pu home bk 70 lt 15 setpc 15
repeat 6 [
pushturtle pd fd 150 + random 20
setfc pick [1 8 9 11] ra 0.1
spot 5 popturtle rt 6
]
END
```

```TO weave
reset  wrap
repeat 30000 [
fd 1 rt
sin repcount
if divisorp 1000 repcount [randpc]
]
END
```

```TO zig
reset  setbg pick [1 8 9 13]
setbs 10 setpenwidth 10
repeat 200 [
ra 0.1 pu
setpos {-220 + random 440 -120 + random 240}
rt random 360 setpc pick [1 8 9 13]
setps -15 + random 10
repeat 50 [
pd fd 50 + random 3 lt random 3 bk 50 + random 3
rt random 3 setps penshade + (-1 + random 3)
]
]
pu setpos [-100 -50]
setps 5 ra 1
repeat 15 [
bk 0.2 fd 20 rt 140
bk 0.2 fd 20 lt 132.5
]
END
```

```TO zigzag
reset setbg 8 setbs 0 setpenwidth 5

repeat 360 [
pu home pd rt repcount * 1 lt 45
setpc pick [1 5 7 9]
repeat 20 [
fd repcount rt 90
fd repcount lt 90
]
]
END
```

```TO zigzag3d
reset setbg 8 setbs 0 setpenwidth 5
repeat 360 [
pu home pd rt repcount * 1
lt 45 up 45 setpc pick [1 5 7 9]
repeat 20 [
fd repcount rt 90 fd repcount lt 90
]
]
END
```

#### Example: Fly Me to the Moon

Let’s make a rocket ship kind of like the Saturn V used in the moon landings!

```TO rocket

;step [rocket]

;uncomment step line above to 'step through'
;building the rocket. You will need to call
;rocket twice

clearscreen
penup

up 90

setfillcolor red
cone 10 30 12
;create the nose cone

;cone takes three parameters:
;radius, depth (or height) and sides

;So in this case, a radius of 10 turtle
;units, a depth of 30 turtle units, and
;12 sides.

;the cone is created under the turtle

down 180
;flip over

setfillcolor white
cylinder 10 50 12
;create the body

;cylinder takes three parameters:
;radius, depth and sides, like cone

;the cylinder is created under the turtle
;similarly to cone
lower 50
;lowers the turtle, like as if going
;down in an elevator

;same as: down 90 forward 50 up 90

setfillcolor blue
cutcone 10 15 20 12
;create the base

;cutcone creates a truncated cone
;cutcone takes four parameters:

;like cone, the cut cone is created under
;the turtle

;begin APOLLO inscription

up 90
raise 11
;going up! (like in an elevator)

settypedepth 5
settypesize 6
slideright 3
;same as right 90 forward 3 left 90

inscribe |  APOLLO|
;incribe prints text in front of the turtle
;without moving it.
;compare with typeset which prints to the right
;and moves the turtle.

slideleft 3
;same as left 90 forward 3 right 90

lower 11
;going down!

down 90
;not the same as lower, which lowers
;down tilts the turtle down

;end of APOLLO inscription

;begin fins:
lower 20
up 90
setfillcolor grey
twosided
;light both sides of surfaces

rat 40 lat 40
;create a triangle to the right,
;(Right Angle Triangle = rat)
;and a triangle to the left
;(Left-facing right Angle Triangle = lat)

rollright 90
setfillcolor lightblue
rat 40 lat 40
rollleft 90  down 90
;end fins

;begin rockets
forward 8
setfillcolor yellow
cylinder 5 5 10
back 16
cylinder 5 5 10
forward 8
slideleft 8
cylinder 5 5 10
slideright 16
cylinder 5 5 10
;end rockets

;begin fire
setfillcolor orange
lower 5
cutcone 3 2 3 10
slideleft 16
cutcone 3 2 3 10
slideright 8
forward 8
cutcone 3 2 3 10
back 16
cutcone 3 2 3 10
;end fire

END

```

#### Example: Random Solar System

Create a ‘random’ solar system and surrounding star field using these commented Logo procedures:

```TO solsys
reset
;reset the turtles and clear the environment

fullscreen
;don't display text

;ask the camera turtle to pull away from
;myrtle 1000 turtle units

penup
;raise the turtle's pen so she doesn't draw

hideturtle
;go incognito

stars
;a starfield around our solar system

setfillcolor yellow
icosphere 75
;make the sun, an icosphere 75 turtle units

dropanchor
;set Myrtle's 'anchor point' or the point
;she orbits around to her home position.
;By default it is somewhat in front of it.

pullout 100
;pull out from the anchor point 100 turtle units

repeat 10 [
;do the following ten times, to create ten planets

pullout 100
;pull out from the anchor point 100 more
;turtle units

orbitleft random 360
;orbit to the left between 0 and 360 degrees
;(up to one full orbit of the anchor point)

planet repcount
;the current iteration of the repeat loop
;as its parameter - the current planet number

]
;this is the end of the planet creation loop

snappy:forever [orbitdown 0.001]
;orbit around the scene
;snappy: is shorthand for 'ask "snappy []'

END

TO stars
;create a starfield

repeat 500 [

randomvectors
;points the turtle in a random 3D
;direction. 'Vectors' describe absolute
;directions in 3D space using numbers.
;We call them vectors so as to not confuse
;them with relative directions such as up,
;down, left or right. A turtle with certain
;vectors will always point a certain way.
;For now, that's all you need to know!

forward 1500 + random 500
;move forward 1500 turtle units plus
;between 0 and 499 turtle units in the
;turtle's forward direction - its forward
;'vector'

;Note: 'random' generates a number between
;0 and one less than the number you give it.
;The turtle knows what you mean when you say
;'random' because random is a primitive - a
;word the turtle knows.

up 90
;tilt the turtle up 90 degrees, one quarter of
;a circle or one quarter of a complete rotation.
;Like as if you leaned back so far you were
;staring up at the sky

randomfillcolor
;random means 'pick one at random', in this
;case a random fill color, numbered between 1
;and 15 (there are 16 default colors, but 0 is
;transparent and not typically a useful fill
;color!)

spot 5 + random 5
;make a 'star', a spot with a radius of 5
;turtle units plus 0 - 4 additional turtle units

home
;go back to the home position
]
;make 500 stars

END

TO planet :number
;make a planet. The number passed to
;planet is used to uniquely identify
;its 'model' - what it looks like

newmodel :number [
randomfillcolor
;Remember: not black!

icosphere 10 + random 25
;create a randomly-sized sphere

randomvectors

dountil fillcolor != yellow [randomfillcolor]
;not yellow!

spot 10 + random 30
;create a randomly-sizes spot.
;If it's bigger than the sphere
;then it will act as a ring

]
;make a random planet model with the
;name of the planet number stored
;in the :number container, which was
;created when the number was passed
;in to the planet procedure

;Models are not unique to turtles, and
;so they each need a unique name, regardless
;of whatever turtle 'wears' them. But that
;name can just be a number, as long as it
;is a unique number

hatch [
;hatch a new turtle from this spot

showturtle
;show the hatchling's model. Hatchlings
;models are hidden when they are hatched
;as are those of other turtles when they
;are newly created. Only Myrtle is shown
;by default

put 1 + random 10 in "speed
;generate a random number between
;0 and 9, add it to 1 and put it in
;a container named 'speed'

setmodel :number
;set the hatchling's 'model' or
;appearance to the name stored in
;the :number container

setanchor [0 0 0]
;set the 'anchor' or the point a turtle
;orbits around to [0 0 0], the location
;of the sun

forever [
orbitleft :speed * 0.001
]
;orbit around the sun 'forever'
]
;this is the end of the hatchling's code

END
```