// meadow — a tour of the modern NeedleScript syntax.
//
// let / assignment / +=, call parens & commas, def/return, recursion,
// else-if, keyword for (with and without step), %, !, ==, true/false,
// closed strings, and // and # comments — freely mixed with classic
// Logo style, which is the intended idiom: prefix words for movement,
// call syntax for expressions.

fabric "knit"            // preset: pull comp, auto underlay, density cap
seed 11                  # same seed, same meadow — # comments work too
stitchlen 2.2
autotrim 6

let debug = 0            // [switch:no,yes] show pins + console output

// helper reporters:

def clamp(v, lo, hi) [
  return min(hi, max(lo, v))
]

def len2(x, y) [         // distance of a *point* from the origin
  return sqrt(x * x + y * y)
]

def inside(x, y) [       // call parens end the old "trailing operator
  return len2(x, y) < 31 // gets absorbed" footgun
]

// procedures:

// recursive grass sprig — bare `return` is `exit`
def sprig(depth, seg) [  // nb: "step" is reserved, hence "seg"
  if depth == 0 [ return ]
  fd seg
  push
    lt 35
    sprig(depth - 1, seg * 0.62)
  pop
  push
    rt 30
    sprig(depth - 1, seg * 0.62)
  pop
  bk seg                 // sew back down the trunk
]

def leaf(size) [         // tatami-filled leaf
  beginfill
    repeat 2 [ arc 90 size rt 90 ]
  endfill
]

def bloom(size, kind) [
  if kind == 0 [
    // daisy: six petal outlines around a center ring.
    // the small fd spreads the petal bases so no
    // hole at the hub is punched twice
    repeat 6 [
      repeat 2 [ arc 90 size rt 90 ]
      rt 60 fd 0.9
    ]
    arc 360 clamp(size / 3, 1, 1.8)
  ] else if kind == 1 [
    // unfurling spiral
    bean 3
    for t = 1 to 4 [ arc 130 t * 0.7 ]
    bean 1
  ] else [
    // seed-head burst — spokes drift around the hub
    repeat 8 [ fd size + 1.5  bk size + 1.5  rt 45 fd 0.8 ]
  ]
]

// ground:

color 1
fillangle 20
up setxy(-8, -33) seth -25 down
leaf(8)
up setxy(8, -34) seth 20 down
leaf(7)
trim

for gx = -20 to 20 step 10 [             // keyword for, explicit step
  up
  setxy(gx, -33 + random(3))
  seth (noise(gx / 9) - 0.5) * 40        // space before ( = grouping
  down
  sprig(3, 3.5)
  trim
]

// flowers:

for i = 1 to 7 [                         // default step = 1
  // rejection-sample a position inside the meadow
  let x = random(64) - 32
  let y = random(44) - 14
  let tries = 0
  while !inside(x, y) [                  // ! on a reporter call
    x = random(64) - 32                  // bare reassignment
    y = random(44) - 14
    tries += 1
    assert tries < 99                    // geometric invariant guard
  ]

  color 2 + i % 3                        // cycle threads 2, 3, 4
  up setxy(x, y) seth random(360) down

  let kind = floor(random(3))
  if debug [ mark  print "flower" kind ] // closed-quote print label
  bloom(clamp(2.5 + random(3), 2.5, 5), kind)
  trim
]

// border:

color 5
satin 2.2
up setxy(0, 42) seth 90 down
arc 360 42                               // classic Logo, untouched
satin 0
trim
