# All posts by auntiemyrtle

#### 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

#### Control turtleSpaces from other applications with its API

You can communicate with turtleSpaces over a socket (telnet) connection to port 1967.

First you need to issue the API command inside of turtleSpaces to enable API connections, or use the -enable-api flag when starting up.

Then connect to turtleSpaces from an external application or terminal. You can issue instructions to affect turtles and the environment just like you would do inside the turtleSpaces application.

The API connection executes as its own worker. You can also redirect input and output to the API instance by using setread “api and setwrite “api – but these must be issued by the API worker itself to redirect to that worker (if you use another API connection, reading and writing will be redirected to that API instance, for example).

Using the API, you can use turtleSpaces as a visualiser for another application, and have it act as a light organ, or create charts and graphs.

#### ‘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!

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

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

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

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

#### Filled triangles

TO tree
clearscreen penup
setpos [0 80] setfillcolor 4
repeat 6 [
setfillshade -6 + 3 * repcount
;repcount returns the current iteration
back 4 * repcount
fiso 8 * repcount 5 * repcount
;fiso = filled iso triangle
lower 0.1
]
back 50 slideleft 10
;trunk
END

#### ‘Tents’ – fiso prisms

TO tree3d
cs pu setpos [0 80]
;cs = clearscreen
;pu = penup
setfc 4
;setfc = setfillcolor
repeat 6 [
setfs -6 + 3 * repcount
bk 4 * repcount
;bk = back
tent 8 * repcount 5 * repcount 10
lo 0.1
;lo = lower
]
setfc 8 setfs 5
bk 50 sl 10
;sl = slideleft
voxeloid 20 50 10
;voxeloids are stretched cubes
END

#### Cones

TO conetree
cs pu setpos [0 80]
setfc 4 up 90
repeat 6 [
setfs -6 + 3 * repcount
ra 4 * repcount
cone 8 * repcount 5 * repcount 20
]
setfc 8 setfs 5 ra 50
cylinder 8 50 20
END

#### Pyramids (5-sided ‘cones’)

TO pyramidtree
cs pu setpos [0 80]
setfc 4 up 90
repeat 6 [
setfs -6 + 3 * repcount ra 4 * repcount
cone 8 * repcount 5 * repcount 4
;while there is also a pyramid primitive, you can
;also create a pyramid by creating a 4-sided cone
]
setfc 8 setfs 5 ra 50
cylinder 8 50 4
END

#### 4-sided cones

TO tetratree
cs pu setpos [0 80] setfc 4 up 90
repeat 6 [setfs -6 + 3 * repcount
ra 4 * repcount
cone 8 * repcount 5 * repcount 3]
setfc 8 setfs 5 ra 50
cylinder 8 50 3
END

#### Example: Sierpinski’s Turtles

These routines use recursion (they repeatedly call themselves) to realise different Sierpinski algorithms. Logo’s recursion capabilities and relational turtle make it excellent for the task of rendering these algorithms! They’re also very pretty.

TO half_s :size :level
if :level = 0 [fd :size stop]
half_s :size :level - 1
lt 45 fd :size * sqrt 2 lt 45
half_s :size :level - 1
rt 90 fd :size rt 90
half_s :size :level - 1
lt 45 fd :size * sqrt 2 lt 45
half_s :size :level - 1
END

TO sierpinski :size :level
repeat 2 [
half_s :size :level
rt 90 fd :size rt 90
]
END

TO sierp
cs pu back 180 pd sierpinski 3 5
END

sierp

Instead of drawing lines, we can construct triangles out of ‘pins’ dropped at appropriate points:

TO half_s :size :level
penup
if :level = 0 [fd :size stop]

pin
;pin marks a point for use with pinfrag

half_s :size :level - 1
lt 45 fd :size * sqrt 2 lt 45
half_s :size :level - 1
rt 90 fd :size rt 90
half_s :size :level - 1
lt 45 fd :size * sqrt 2 lt 45
half_s :size :level - 1

pinfrag
;creates a triangle out of the last three 'pins'

END

sierp

We could drop twice as many pins and then select a color for each ‘frag’ (fragment) triangle from a list:

TO half_s :size :level
pu
if :level = 0 [fd :size stop]

pin
;drop pin

half_s :size :level - 1
lt 45 fd :size * sqrt 2 lt 45
half_s :size :level - 1

pin
;drop another pin

rt 90 fd :size rt 90
half_s :size :level - 1
lt 45 fd :size * sqrt 2 lt 45
half_s :size :level - 1

setfc item :level [9 8 1 13] pinfrag
;pick a color from a list based on the current level and create the fragment

END

sierp

#### Sierpinski’s Triangle

It’s triangles all the way down!

TO sierpinski :size :level
if :level > 0 [
rt 30
repeat 3 [
fd :size
rt 120
]
left 30
sierpinski :size / 2 :level - 1
rt 30
fd :size / 2
left 30
sierpinski :size / 2 :level - 1
rt 30
back :size / 2
left 30
rt 90
fd :size / 2
left 90
sierpinski :size / 2 :level - 1
left 90
fd :size / 2
rt 90
]
END

TO sierpinskiexample
sierpinski 500 8
END

sierpinskiexample

Neat but a bit plain. We could use frag to create filled triangles, but we need to avoid z-fighting by adding a little bit of code to change the elevation of each ‘level’:

TO sierpinski :size :level
if :level > 0 [

pu setz 0 lower 0.1 * :level
;add above line to avoid z-fighting

rt 30
repeat [
fd :size
rt 120
]

setfc :level
;set the fill color to the current 'level'
frag
;create a filled triangle from the last three points (triangle)

left 30
sierpinski :size / 2 :level - 1
rt 30
fd :size / 2
left 30
sierpinski :size / 2 :level - 1
rt 30
back :size / 2
left 30
rt 90
fd :size / 2
left 90
sierpinski :size / 2 :level - 1
left 90
fd :size / 2
rt 90
]
END

sierpinskiexample

If you seperate the layers more, and use shard instead of frag

#### Sierpinski’s Tree

Trees are also a lot of fun, with the potential for so many variations!

TO tree :s :a :frac :depth
fd :s / 2
if :s >= 1 [
local "p
local "h
make "p pos
left :a
tree :s * 2 / 3 :frac * :a :frac :depth + 1
pu setpos :p pd
seth :h + :a
tree :s * 2 / 3 :frac * :a :frac :depth + 1
]
END

TO drawtree
reset
cs pu bk 250 pd
tree 350 25 1.1 4
END

Note that this takes quite some time to render!

tree 350 60 1.1 4

TO tree :s :a :frac :depth
fd :s / 2
if :s >= 1 [
setpc :s
;set the pen color to the current 'size'
;which is fractional number truncated to an integer for use by setpc
local "p
local "h
make "p pos
left :a
tree :s * 2 / 3 :frac * :a :frac :depth + 1
pu setpos :p pd
seth :h + :a
tree :s * 2 / 3 :frac * :a :frac :depth + 1
]
END

tree 350 180 1.1 4

setpc 12 - :s

tree 350 280 1 4

Play with tree’s parameters and the colors and see what you can come up with! Logo is all about exploration, tweaking and tinkering. By seeing how altering the parameters can change the end result, you can learn to better understand the underlying mathematics.

You can also change how the trees are rendered, for example using mark instead of forward and by setting the width of the mark using setmarkerwidth depending on the current ‘size’ of the segment being rendered:

TO tree :s :a :frac :depth
penup
setpc item (remainder int :s 7) [11 9 4 12 14 8 13]
if pencolor = 0 [setpc 8]
setmarkerwidth 1 + :s / 20
bk :s / 20
mark :s / 2
if :s >= 1 [
local "p
local "h
make "p pos