adding initial scripts

This commit is contained in:
Matt Nish-Lapidus 2024-06-11 17:37:04 -04:00
commit 50eb33a7f2
21 changed files with 867 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Ludus Scripts
For now this is a place to put our collective Ludus sketches and scripts. Some sort of structure or organization might emerge...

15
annoying_box.ld Normal file
View File

@ -0,0 +1,15 @@
& Lesson 2: Repeating things, labouriously
& Let's draw a box!
& How do we start?
forward! (100)
& We move forward.
& Now we turn right:
right! (100)
& How many more times should we do that?
& How many total times do we do that?
& Finish the code to finish drawing the box.

39
arguments.ld Normal file
View File

@ -0,0 +1,39 @@
& Lesson 5: Passing arguments
& Recall our last function:
& fn box! () -> repeat 4 { fd! (100); rt! (0.25) }
& This function can only draw a box with a side of `100`
& To make our function more flexible, we can add an argument:
fn box! (size) -> repeat 4 {
& ^^^^ This is our size parameter
fd! (size)
& ^^^^ Which we use here: the parameter is a name.
& This name only lasts as long as our function.
rt! (0.25)
}
& How do you call out new `box!` function?
& A note:
& * a *parameter* is the name for a thing we _don't yet know the value of_
& * an *argument* is the name for a parameter _when it is given a concrete value_
& fn box! (size) ...
& ^^^^ This is a parameter: in the function definition
& box! (50)
& ^^ This is an argument: in the function call
& It's a subtle difference, and not especially important
& Plenty of programmers use these words interchangeably
& I just wanted to alert you to these words, their difference, their use.
& In all Ludus documentation, we'll be using them correctly.

41
cngon.ld Normal file
View File

@ -0,0 +1,41 @@
& Lesson 12: c_ngon
& Clayson walks you through this step by step
& It's just high school trigonometry
& But that probably strikes terror into the hearts of PhD students in the humanities
& So I've adapted his solution.
& He walks you carefully through it on pp. 24-31.
fn ngon! (sides, size) -> repeat sides {
fd! (size)
rt! (inv (sides))
}
fn c_ngon! (sides, radius) -> {
& first, some fancy trigonometry
& don't read this if you don't want to
& but: there are two hard problems here
& how far to turn before drawing the ngon
& and how long each side should be to fit inside the radius
let entry_turn = sub (
0.5
mult (
0.25
sub (sides, 2)
inv (sides)))
let side_length = mult (
2
radius
sin (div (0.5, sides)))
& now that we have the math: what do we need the turtle to do
pu! ()
fd! (radius)
pd! ()
rt! (entry_turn)
ngon! (sides, side_length)
lt! (entry_turn)
pu! ()
bk! (radius)
pd! ()
}

19
demo_1.ld Normal file
View File

@ -0,0 +1,19 @@
& Lesson 6: A first demo
& Source: _Visual Modeling with Logo_, 14.
fn box! (size) -> repeat 4 { fd! (size); rt! (0.25) }
fn demo! () -> repeat 4 {
box! (100)
box! (98)
box! (96)
box! (75)
box! (40)
box! (35)
box! (30)
rt! (0.25)
}
& How can you make this box more interesting?
& Consider `pc!` and `pw!`

37
drawing.ld Normal file
View File

@ -0,0 +1,37 @@
& Lesson 1: The World of the Turtle
& Ludus is a Logo: it leads with turtle graphics
& There are two panes on the right:
& * the turtle
& * the console
& You saw the console in Lesson 0: Hello World!
& `print!`ing things is very useful; remember you can do that.
& Now, we're going to give the turtle some functions.
forward! (100)
& let's dissect that
& forward! (100)
& ^^^^^^^^ `forward!` is is the name of the function
& ^^^^ `100` is how far the turtle should walk
& (...) notice that we have to put 100 in parens
& Uncomment the line below, and re-run the script:
& right! (0.25)
& right! (0.25)
& ^^^^^^ `right!` is the name of this function
& ^^^^ 0.25 is how far the turtle should turn
& (....) notice again, we put the amount in parens
& What is the unit of 0.25?
& Try out some other turtle functions. Here are a few:
& `left!`, `back!`, `penup!`, `pendown!`, `pencolor!`, `penwidth!`
& `home!`
& Note they all end with `!`. What happens if you forget the bang?
& There are abbreviations: `fd!`, `rt!`, `lt!`, `bk!`, etc.
& The turtle graphics functions (and abbreviations!) are listed at https://alea.ludus.dev/twc/ludus/src/branch/main/prelude.md#turtle-graphics

279
eliza.ld Normal file
View File

@ -0,0 +1,279 @@
let input = *input*
print! (">>> ", input)
let sanitized = do input > trim > downcase
& ensuring we have spaces at the beginning and end
& this lets us match patterns as written below
let padded = " {sanitized} "
fn switch_persons {
("i") -> "you"
("you") -> "i"
("am") -> "are"
("me") -> "you"
("my") -> "your"
(x) -> x
}
fn repersonalize (x) -> do x >
trim >
split (_, " ") >
map (switch_persons, _) >
join (_, " ")
fn one_of {
(str as :string) -> str
(strs as :list) -> random (strs)
}
let output = match padded with {
"{x} hello {y}" -> "How do you do. Please state your problem"
"{x} hi {y}" -> "How do you do. Please state your problem"
"{x} computer {y}" -> [
"Do computers worry you"
"What do you think about machines"
"Why do you mention computers"
"What do you think machines have to do with your problem"
]
"{x} name {y}" -> "I am not interested in names"
"{x} sorry {y}" -> [
"Please don't apologize"
"Apologies are not necessary"
"What feelings do you have when you apologize"
]
"{x} i remember {y}" -> {
let switched = repersonalize (y)
[
"Do you often think of {switched}"
"Does thinking of {switched} bring anything else to mind"
"What else do you remember"
"Why do you recall {switched} right now"
"What in the present situation reminds you of {switched}"
"What is the connection between me and {switched}"
]
}
"{x} do you remember {y}" -> {
let switched = repersonalize (y)
[
"Did you think I would forget {switched}"
"Why do you think I should recall {switched} now"
"What about {switched}"
"You mentioned {switched}"
]
}
"{x} if {y}" -> {
let switched = repersonalize (y)
[
"Do you reall think that its likely that {switched}"
"Do you wish that {switched}"
"What do you think about {switched}"
"Really--if {switched}"
]
}
"{x} i dreamt {y}" -> {
let switched = repersonalize (y)
[
"Really--{switched}"
"Have you ever fantasized {switched} while you were awake"
"Have you dreamt {switched} before"
]
}
"{x} dream about {y}" -> {
let switched = repersonalize (y)
"How do you feel about {switched} in reality"
}
"{x} dream {y}" -> [
"What does this dream suggest to you"
"Do you dream often"
"What persons appear in your dreams"
"Don't you believe that dream has to do with your problem"
]
"{x} my mother {y}" -> {
let switched = repersonalize (y)
[
"Who else in your family {switched}"
"Tell me more about your family"
]
}
"{x} my father {y}" -> [
"Your father"
"Does he influence you strongly"
"What else comes to mind when you think of your father"
]
"{x} i want {y}" -> {
let switched = repersonalize (y)
[
"What would it mean if you got {switched}"
"Why do you want {switched}"
"Suppose you got {switched} soon"
]
}
"{x} i am glad {y}" -> {
let switched = repersonalize (y)
[
"How have I helped you to be {switched}"
"What makes you happy just now"
"Can you explain why you are suddenly {switched}"
]
}
"{x} i am sad {y}" -> [
"I am sorry to hear you are depressed"
"I'm sure it's not pleasant to be sad"
]
"{x} are like {y}" -> {
let switched_x = repersonalize (x)
let switched_y = repersonalize (y)
"What resemblance to you see between {switched_x} and {switched_y}"
}
"{x} is like {y}" -> {
let switched_x = repersonalize (x)
let switched_y = repersonalize (y)
[
"In what way is it that {switched_x} is like {switched_y}"
"What resemblance do you see"
"Could there really be some connection"
"How"
]
}
"{x} alike {y}" -> [
"In what way"
"What similarities are there"
]
"{x} same {y}" -> "What other connections do you see"
"{x} i was {y}" -> {
let switched = repersonalize (y)
[
"Were you really"
"Perhaps I already knew you were {switched}"
"Why do you tell me you were {switched} now"
]
}
"{x} was i {y}" -> {
let switched = repersonalize (y)
[
"What if you were {switched}"
"Do you think you were {switched}"
"What wouuld it mean if you were {switched}"
]
}
"{x} i am {y}" -> {
let switched = repersonalize (y)
[
"In what way are you {switched}"
"Do you want to be {switched}"
]
}
"{x} am i {y}" -> {
let switched = repersonalize (y)
[
"Do you believe you are {switched}"
"Would you want to be {switched}"
"You wish I would tell you you are {switched}"
"What would it mean if you were {switched}"
]
}
"{x} am {y}" -> [
"Why do you say *AM*"
"I don't understand that"
]
"{x} are you {y}" -> {
let switched = repersonalize (y)
[
"Why are you interested in whether I am {switched} or not"
"Would you prefer if I weren't {switched}"
"Perhaps I am {switched} in your fantasies"
]
}
"{x} you are {y}" -> {
let switched = repersonalize (y)
"What makes you think I am {y}"
}
"{x} because {y}" -> [
"Is that the real reason"
"What other reasons might there be"
"Does that reason seem to explain anything else"
]
"{x} were you {y}" -> {
let switched = repersonalize (y)
[
"Perhaps I was {switched}"
"What od you think"
"What if I had been {switched}"
]
}
"{x} i can't {y}" -> {
let switched = repersonalize (y)
[
"Maybe you could {switched} now"
"What if you could {switched}"
]
}
"{x} i feel {y}" -> {
let switched = repersonalize (y)
"Do you often feel {switched}"
}
"{x} i felt {y}" -> "What other feelings do you have"
"{x} i {y} you {z}" -> {
let switched = repersonalize (y)
"Perhaps in your fantasy we {switched} each other"
}
"{x} why don't you {y}" -> {
let switched = repersonalize (y)
[
"Should you {switched} yourself"
"Do you believe I don't {switched}"
"Perhaps I will {switched} in good time"
]
}
"{x} yes {y}" -> [
"You seem quite positive"
"You are sure"
"I understand"
]
"{x} no {y}" -> [
"Why not"
"You are being a bit negative"
"Are you saying *NO* just to be negative"
]
"{x} someone {y}" -> "Can you be more specific"
"{x} everyone {y}" -> [
"Surely not everyone"
"Can you think of anyone in particular"
"Who for example"
"You are thinking of a special person"
]
"{x} always {y}" -> [
"Can you think of a specific example"
"When"
"What incident are you thinking of"
"Really--always"
]
"{x} what {y}" -> [
"Why do you ask"
"Does that question interest you"
"What is it you really want to know"
"What do you think"
"What comes to your mind when you ask that"
]
"{x} perhaps {y}" -> "You do not seem quite certain"
"{x} are {y}" -> {
let switched = repersonalize (y)
[
"Did you think they might not be {switched}"
"Possibly they are {switched}"
]
}
_ -> [
"Very interesting"
"I am not sure I understand you fully"
"What does that suggest to you"
"Please continue"
"Go on"
"Do you feel strongly about discussing such things"
]
}
print! ("~> ", do output > one_of > upcase)

24
functions.ld Normal file
View File

@ -0,0 +1,24 @@
& Lesson 4: Making functions and naming them
& It's tedious to type out the whole `repeat 4 {...}` scene.
& Let's give this set of commands a name:
fn box! () -> repeat 4 {
forward! (100)
right! (0.25)
}
& fn box! () -> repeat 4 {
& fn `fn` is a special form
& It creates a function.
& box! `box!` is the name of our new function
& Note that it ends with `!`: by convention,
& all commands end with a "bang" like this.
& () `box!` doesn't take arguments.
& This represents an empty list of args.
& -> This arrow is basically punctuation.
& repeat 4 { We already know what this is.
& Run this code. What happens?
& If you want to actually draw a box, what does that look like?

38
ifs.ld Normal file
View File

@ -0,0 +1,38 @@
& Lesson 9: Flipping coins
& Let's try a different version of this random walk. Instead of going an arbitrary amount forward, and an arbitrary amount left or right, let's turn left OR right, let's go forward OR backwards by a fixed amount.
& We need coin flips!
let coin = [true, false] & these are booleans: equivalent to heads and tails
& ^^^^^^^^^^^^^ this is a list with two members
& Lists are like parameters or arguments, but with square brackets
fn flip_coin () -> random (coin)
& ^^^^^^ `random` will pick a random element of a collection
& ^^^^ `coin` is a collection of two elements
let times = random (10, 30) & we'll do this a random number of times
repeat times {
pc! (random (colors))
& `if` is our first conditional form
if flip_coin ()
& ^^ the expression starts with `if`
& ^^^^^^^^^^^^ this is our *condition*
& if the condition is true, run the `then` branch
& if it is false, run the `else` branch
& in this case, our condition is the coin flip
then rt! (0.25)
& ^^^^ `then` gives us the branch to evaluate if true
& ^^^^^^^^^^ in this case, turn right 0.25 turns
else lt! (0.25)
& ^^^^ `else` gives us the branch to evaluate if false
& NB: Ludus requires you have a false branch
& ^^^^^^^^^^ in this case, turn left 0.25 turns
& This whole expression is:
& turn right 50% of the time, turn left 50% of the time
& we don't need newlines before `then` and `else`
& but you can include them!
if flip_coin () then fd! (5) else bk! (5)
}

20
koch.ld Normal file
View File

@ -0,0 +1,20 @@
& koch curve
let length = 10
fn koch! {
(0) -> fd! (length)
(n) -> {
koch! (dec (n))
lt! (0.25)
koch! (dec (n))
rt! (0.25)
koch! (dec (n))
rt! (0.25)
koch! (dec (n))
lt! (0.25)
koch! (dec (n))
}
}
& koch! (3)

13
lezertest.ld Normal file
View File

@ -0,0 +1,13 @@
print! ("Hello, world!")
fn box! (size) -> repeat 4 {
forward! (size)
right! (0.25)
}
:symbol
& This is a comment
& More comment
Not comment or anything else

33
ngon.ld Normal file
View File

@ -0,0 +1,33 @@
& Lesson 10: ngons
& Recall our first function:
fn simple_box! () -> { fd! (100); rt! (0.25) }
& Recall our second function:
fn box! (size) -> { fd! (size); rt! (0.25) }
& What haven't we "parameterized" yet?
fn ngon! (n, size) -> repeat n { fd! (size); rt! (div (1, n)) }
& ^ ^^^^^^^^^^
& Note n: what does this represent?
& What does `div (1, n)` mean here?
& Why is it here?
& Note: we could also have used `inv (n)`--inverse is 1/x
& What other math can we do?
& cf. https://alea.ludus.dev/twc/ludus/src/branch/main/prelude.md#math
& What happens when you pass in strange values? 0? 1? 2?
& Note `div` does not end in a bang.
& This differentiates between functions with side effects vs. return values.

44
random.ld Normal file
View File

@ -0,0 +1,44 @@
& Lesson 8: A random lesson.
& So far, everything we've done is deterministic.
& Let's let the computer make some decisions.
& We're going to introduce a few things here:
& * colors
& * random
& * dicts
& our friend box!
fn box! (size) -> repeat 4 { fd! (size); rt! (0.25) }
doc! (pencolor!)
print! ("These are Ludus's built-in colors: ", colors)
pencolor! (colors :maroon)
& ^^^^^^ This is a dict.
& ^^^^^^^ This is a keyword.
& We use <dict> <keyword> to get values out of dicts.
& Dict is short for "dictionary."
& pencolor! is also pc!
& Drawing some colourful boxes:
box! (100)
rt! (0.25)
pc! (colors :purple)
box! (100)
rt! (0.25)
pc! (colors :olive)
box! (100)
rt! (0.25)
pc! (colors :teal)
box! (100)
& We can also get a random colour using a handy-dandy function: random
repeat 4 {
pc! (random (color))
box! (75)
rt! (0.25)
}
& And we can also set the background to a random colour:
background! (random (color))

38
recursion.ld Normal file
View File

@ -0,0 +1,38 @@
& Lesson 11: `spingons` and recursion
& Here's our friend, the ngon
fn ngon! (n, size) -> repeat n { fd! (size); rt! (div (1, n)) }
& Here we're introducing one of the more important, and """difficult""" concepts in computer science, recursion
& Let's read this line-by-line
fn spin_gon! (n, size, angle, growth, times) -> if lte? (times, 0)
then :ok & this is the base case: what to do when we're done
& in this case, `:ok`--just a little signal all went well
else {
ngon! (n, size) & make an ngon
rt! (angle) & turn right
spin_gon! (n, mult (size, growth), angle, growth, sub (times, 1))
& ^^^^^^^^^ This is the recursive call
& `spin_gon!` calls itself!--make another spin_gon
& What does this change between invocations?
& * `mult (size, growth)`
& * `sub (times, 1)` (or we could use `dec (times)`)
& What would happen if we *didn't* make these changes?
}
}
& Play with `spin_gon!`: see what you can come up with.
& Also: see if you can't read what each call does.
& It's okay if you can't: 5 parameters is a lot.
& Clayson's examples:
& Example 1, p. 21
& spin_gon! (30, 2, 0.03, 1.02, 95)
& Example 2, p. 21
& repeat 3 {
& spin_gon! (4, 120, 0, 0.95, 50)
& rt! (0.25)
& }
& spin_gon! (4, 120, 0, 0.95, 19)

32
repeat.ld Normal file
View File

@ -0,0 +1,32 @@
& Lesson 3: Repeating things, simply
& Computers are good at repeating things:
repeat 4 {
forward! (100)
right! (0.25)
}
& let's take this line by line
& 5: repeat 4 {
& ^^^^^^ `repeat` is NOT a function, but a "special form"
& ^ this tells Ludus how many times to repeat a thing
& ^ this "curly brace" lets you group lines of code together
& we call this group a "block"
& 6: forward! (100)
& ^^ as a matter of style, we indent lines in a block
& ^^^^^^^^ we recognize this
& 7: right! (0.25)
& we recognize this, too
& but it has to be on its own line!
& (we could use a `;` instead of a newline)
& 8: }
& ^ We need to close the block we opened on line 5
& What happens if we forget it?
& What happens if you change the number of times it repeats?
& -- the distance the turtle goes forward?
& -- the amount we turn right?

54
sierp.ld Normal file
View File

@ -0,0 +1,54 @@
& Example Ludus implementation of the Sierpinski triangle.
& https://en.m.wikipedia.org/wiki/L-system#Example_5:_Sierpinski_triangle
& The Sierpinski triangle drawn using an L-system
& variables : F G
& constants : +
& start : FGG
& rules : (F → FG+F+GF), (G → GG)
& angle : 120°
& set a length for each segment
let length = 10
& set an angle for all turns, default to 1/3 for triangles
let angle = inv(1)
& define 'G' function from the grammaer
fn g! {
(0) -> fd!(length)
(n) -> {
g!(dec(n))
g!(dec(n))
}
}
& define 'F' function from the grammaer
fn f! {
(0) -> fd!(length)
(n) -> {
f!(dec(n))
rt!(angle)
g!(dec(n))
lt!(angle)
f!(dec(n))
lt!(angle)
g!(dec(n))
rt!(angle)
f!(dec(n))
}
}
& this function defines the starting pattern.
& each of the f! and g! calls expand based on the grammar at the top of this example
fn sierp! (times) -> {
f!(times)
rt!(angle)
g!(times)
rt!(angle)
g!(times)
}
& call the base function with a number of iterations
& remember, this is exponential! high numbers can freeze your browser.
sierp!(7)

46
spiralgon.ld Normal file
View File

@ -0,0 +1,46 @@
let gons = 10
let sides = 4
let size = 50
fn randcolor () -> (random(0,255), random(0,255), random(0,255))
fn ngon! (sides, size) -> {
repeat sides {
fd! (size)
rt! (inv(sides))
}
:gon!
}
fn spiralgon_recursive! (num, sides, size) -> {
pencolor!(randcolor())
ngon! (sides, size)
if gt? (num, 0) then {
rt!(inv(gons))
spiralgonr!(dec (num), sides, add(10,size))
} else {
:tired!
}
}
& Non recursive version using loop for reference/example
& fn spiralgon! (num, sides) -> {
& loop (15, 0) with (size, times) -> {
& if lt? (times, num) then {
& pencolor!(randcolor())
& ngon! (sides, size)
& rt! (0.2)
& if gt? (times, div (num, 2)) then {
& fd! (20)
& } else {
& back! (200)
& }
& recur (add (size, 1), inc (times))
& } else :dizzy
& }
& }
spiralgon_recursive!(gons, sides, size)

29
start.ld Normal file
View File

@ -0,0 +1,29 @@
& Welcome to Ludus!
& To run the code in this window, hit the RUN button.
& Ludus will evaluate this script and return its value.
& It will also perform "side effects": printing text to the screen,
& or making the "turtle" move (that's the little triangular guy).
& Lines that begin with an ampersand--&--are comments.
& Comments don't have any effect: they're for other people, not the machine.
& here's your usual first program:
print! ("Hello, world!")
& this is your first function call!
& notice a few things here:
& print! ("Hello, world!")
& ^^^^^^ This is the function name.
& Not `print` but `print!`
& ^^^^^^^^^^^^^^ This is what it prints.
& Note the quotation marks.
& Without them, Ludus would think this is code.
& ^ ^ Between parentheses!
& This is a "function argument."
& We need parens to send an arg to a function.
& Try printing other things--
& just delete the `&` at the start of these lines:
& print! ("Well, hello there!")
& print! ("Can", "we", "print", "multiple", "strings?")
& What do you notice?

28
tenprintmod.ld Normal file
View File

@ -0,0 +1,28 @@
& 10 print not quite working yet. need to wait for scott to fix mod
let gridsize = 20
let root2 = 1.414213562
let cellsize = 20
let linelength = mult (root2, cellsize)
fn tenprint! (times, width) -> {
pendown!()
rt!(0.125)
fd!(linelength)
penup!()
back!(linelength)
lt!(0.125)
penup!()
rt!(0.25)
fd!(cellsize)
lt!(0.25)
if eq? (0, mod(times, width)) then {
home!()
back!(gridsize)
} else nil
if gt? (times, 0) then tenprint!(dec (times), width) else :donezo
}
tenprint!(20, 200)

34
walk.ld Normal file
View File

@ -0,0 +1,34 @@
& Lesson 8: A random walk
& Besides colors, what can we get?
doc! (random) & Check the console to see the documentation
pc! (random (colors))
& * random distances
fd! (random (10, 50)) & walks forward a random amount between 10 and 50
& * random angles
rt! (random (-0.25, 0.25)) & turns a random amount between -0.25 and 0.25
& you can give turtle commands negative values!
& try giving `fd!` and `bk!` negative values.
& do it a random number of times:
let times = random (10, 30)
& `let` allows us to give names to values; so far we have only named functions
& let times = random (10, 30)
& ^^^ `let` is a special form; after
& ^^^^^ This is the name we're binding
& ^ `=` goes between the lhs and the rhs
& ^^^^^^^^^^^^^^^ The value of this expression is what's bound to the name
& (in this case, it's a random value between 10 and 30)
& here's our random walk:
repeat times { & repeat our random number of times
pc! (random (colors)) & a new random color
fd! (random (10, 50)) & a new random distance
rt! (random (-0.3, 0.3)) & a new random turn
}