; extensions [ sound ]

globals
[
  pixel
  keypress
  the-ship
  the-reticule
  click
  num-rocks
  active-reticule
  score
  credits
  reset-pressed
  rock-color
  setup-finished
  rock-info
]

patches-own
[ rr gg bb
]

breed [ rocks rock ]
breed [ ships ship ]
breed [ bullets bullet ]
breed [ fragments fragment ]
breed [ messengers messenger ]
breed [ reticules reticule ]
breed [ letters letter ]
breed [ clocks clock ]
breed [ HS-effects hs-effect ]

clocks-own
[ current-time
  elapsed-time
  start-time
  cumulative-time
  pause-until
  clock-on
]

letters-own
[ base-size
  base-color
  base-xcor
  base-heading
]

reticules-own
[
  timeout
]

hs-effects-own
[ effect-direction ]

ships-own
[
  vx vy vv
  ax ay av
  gun-temp
  gun-limit
  gun-cooldown
  max-temp
  bullet-speed;
  bullet-burnout
  max-burnout
]

rocks-own
[
  rock-type
  vx vy vv
  av
  exploding
]

bullets-own
[
  vx vy vv
  bullet-burnout
  bullet-speed
  max-burnout
  seeker?
  target-rock
]

fragments-own
[ vv vx vy av burnout max-burnout kind ]

messengers-own
[
  text ;; the message to ;display
  caret ;; position within the text
  cursor ;; patch offset of the caret
  window ;; the set of patches under the message
  window# ;; the line on which to ;display the message
  show-cursor? ;; show the simulated blinking curtor
]

to ? [ thing ]
  (
    ifelse
    ( is-list? thing )
    [
      output-print " [ "
      foreach thing [ ?? -> ? ?? ] output-print " ] "
    ]
    [
      output-print thing
    ]
  )
end

to-report plus-or-minus [ value ]
  report value * ( random 2 * 2 - 1 )
end

to x_set-line-thickness [ width ]
  ;; __set-line-thickness width
end

to setup-rock
  let rock-start-size 1.5 ^ 5
  let rock-start-av .1 + random-float 0.75
  let rock-start-v .1 + random-float .1
  set rock-info
  [
    [ "rock-1" 0 1 22 ]
    [ "rock-2" 0 1 22 ]
    [ "rock-3" 0 1 22 ]
    [ "rock-4" 0 1 22 ]
    [ "rock-5" 1 2 12 ]
  ]

  create-rocks 1
  [
    home
    x_set-line-thickness pixel * 2
    let side plus-or-minus 1
    let startx side * ( max-pxcor - random ( world-width / 4 ) )
    let starty random-ycor
    setxy startx starty
    let endx side * ( max-pxcor - random ( world-width / 4 ) )
    set heading towardsxy endx plus-or-minus max-pycor
    set vx dx * rock-start-v
    set vy dy * rock-start-v
    set av rock-start-av
    set color white
    set rock-type item ( roulette rock-info 3 ) rock-info
    set shape item 0 rock-type
    set size rock-start-size / item 2 rock-type
  ]
end

to-report roulette [ $layout $bias-index ]
  ;; the layout are the values being selected from
  ;; the canoes are widths of each pocket the tendency of each value to be selected
  let canoes map [ $bias -> item $bias-index $bias ] $layout
  let total sum canoes
  let fall random-float total
  let pocket 0
  ;; intial value of canoe = inside the first pocket
  let canoe item pocket canoes
  while [ fall > canoe ]
  [ set pocket pocket + 1
    set canoe canoe + item pocket canoes
  ]
  report pocket
end

to rock-explode
  ;; sound:play-note-later delay instrument keynumber velocity duration
  sfx "explode-rock" size

  set heading atan vx vy
  set vv sqrt ( vx * vx + vy * vy )
  if ( size > 4 )
  [
    set size size * 2 / 3
    if vv < .9 [ set vv vv * 1.1 ]

    let a -1
    repeat (1 + random 2)
    [
      hatch 1
      [
        rt 90 * a
        set a a + 2
        set vx dx * vv
        set vy dy * vv
        jump size / 2
        set shape one-of [ "rock-1" "rock-2" "rock-2" ]
        x_set-line-thickness pixel * 2
      ]
    ]
  ]
  fragment-setup white 0 size
  die
end

to fragment-setup [ hue direction radius ]
  let xx xcor
  let yy ycor
  let $extra max list 0 (count fragments - 100)
  ask n-of $extra fragments [ die ]
  hatch-fragments ifelse-value ( direction = 0 ) [ 5 ] [ 1 ]
  [ set color hue
    set heading random 360
    x_set-line-thickness pixel * 2
    set vv .1 + random-float .2
    set vx dx * vv
    set vy dy * vv
    set max-burnout 40
    ifelse direction != 0
    [ jump 2
      rt 180
      set size 2
      set av 0
    ]
    [
      jump ( .5 * random-float radius )
      rt 90
      set size ( size + random-float 2 )
      set av 20 * ( random 2 * 2 - 1 )
    ]
  ]
end

to game-clear
  ;; setup a game
  clear-drawing
  clear-patches
  clear-turtles
  clear-links
  set num-rocks 0
end

to ship-setup
  create-ships 1
  [ set color magenta + 2
    set heading 0
    set shape "_ship-000"
    x_set-line-thickness pixel * 2
    set size 2
    set bullet-speed 1
    set bullet-burnout max-pxcor / bullet-speed
    set max-burnout bullet-burnout
    set gun-limit 5
    set gun-temp 0
    set max-temp 4 / bullet-speed
    ;; floor ( 30 / 2 / pixel )
    set the-ship self
  ]
  inspect the-ship
end

to reticule-setup
  ask patch min-pxcor min-pycor
  [ sprout-reticules 1
    [ hide-turtle
      setxy max-pxcor max-pycor
      set heading 0
      set shape "reticule"
      set color red
      x_set-line-thickness pixel * 3
      set size 2
      set active-reticule self
      set timeout 0
    ]
  ]
end

to reticules-go
  if self != active-reticule
  [ if timeout = 0 [ set timeout timer + 2 ]
    ifelse timer < timeout
    [ set color scale-color red ( timeout - timer ) -3 8 ]
    [ die ]
  ]

end

to ship-explode
  sfx "ship-explode" 0
  die
end

to-report ship-fire
  ;; SETUP-bullet
  let fire! false
  ask the-ship
  [
    if gun-temp <= 0 and count bullets < gun-limit
    [
      sfx "pew" 0
      hatch-bullets 1
      [
        x_set-line-thickness pixel * 4
        set size max list .5 ( pixel * 3 )
        set color white
        set vx dx * ( bullet-speed )
        set vy dy * ( bullet-speed )
        jump .5
        set fire! true
        set seeker? false
        let vary random 100
        ( ifelse
          ( vary > 90 )
          ;; hunter missle
          [
            set seeker? true
            set size .5
            set shape "missle"
            set target-rock one-of rocks
            set color yellow
            set bullet-burnout 200
          ]
          ( vary > 80 )
          ;; triple shot
          [ hatch 1 [ rt 90 jump .5 lt 90 ]
            hatch 1 [ lt 90 jump .5 rt 90 ]
          ]
          ( vary > 70 )
          ;; to left, right, and center
          [ hatch 1 [ rt 90 ]
            hatch 1 [ lt 90 ]
          ]
          ( vary > 60 )
          ;; four-way shot
          [ hatch 1 [ rt 90 ]
            hatch 1 [ lt 90 ]
            hatch 1 [ rt 180 jump 1 ]
          ]
          ( vary > 55 )
          ;; circle of pebbles
          [ let a heading
            setxy [ xcor ] of myself [ ycor ] of myself
            repeat ( 360 / 5 )
            [ hatch 1 [ rt a jump .5 ]
              set a a + 5
            ] jump .5
          ]
          ;; no specialization
          [ ]
        )
      ]
      set gun-temp max-temp
    ]
  ]
  report fire!
end

to rock-go

  ;  if count rocks < 5 and any? ships
  ;  [
  ;    let hh towards one-of ships
  ;    set vx .5 * sin hh
  ;    set vy .5 * cos hh
  ;  ]
  set vv ( vx * vx + vy * vy )
  ifelse ( vv > 1 )
  [
    rock-explode
  ]
  [
    let trail-color red + 10 * int min list 120 ( 10 * size )
    setxy ( xcor + vx ) ( ycor + vy )
    rt av
    ask patches in-radius (round (.3 * size)) [set pcolor trail-color ]
    set color rock-color
    if ( any? ships in-radius ( size / 2 + .5 ) )
    [
      ask ships [ ship-explode ]
    ]
    if ( true )
    [ let close min-one-of ( other rocks ) [ distance myself ]
      let overlap -1 * boundary-distance close
      if
      ( overlap > 2 * pixel )
      [
        if ( overlap > 4 * pixel )
        [ ;; too close! force them away
          face close rt 180 jump overlap / 2
          ask close [ face myself rt 180 jump overlap / 2 ]
        ]
        collide-with close
      ]
    ]
  ]
end

to collide-with [ other-particle ] ;; particle procedure
  let recovery .99
  ;;; PHASE 1: initial setup

  ;; for convenience, grab some quantities from other-particle

  let h ifelse-value ( vx != 0 or vy != 0 ) [ atan vx vy ] [ 0 ]
  let mass size ^ 3
  let speed sqrt ( vx * vx + vy * vy )
  let mass2 [ size ^ 3 ] of other-particle
  let speed2 [ sqrt ( vx * vx + vy * vy ) ] of other-particle
  let h2 [ ifelse-value ( vx != 0 or vy != 0 ) [ atan vx vy ] [ 0 ] ] of other-particle

  ;;modified so that theta is heading toward other particle
  let theta towards other-particle

  ;;; PHASE 2: convert velocities to theta-based vector representation

  ;; now convert my velocity from speed/heading representation to components
  ;; along theta and perpendicular to theta
  let v1t ( speed * cos ( theta - h ) )
  let v1l ( speed * sin ( theta - h ) )

  ;; do the same for other-particle
  let v2t ( speed2 * cos ( theta - h2 ) )
  let v2l ( speed2 * sin ( theta - h2 ) )

  ;;; PHASE 3: manipulate vectors to implement collision

  ;; compute the velocity of the system's center of mass along theta
  let vcm ( ( ( mass * v1t ) + ( mass2 * v2t ) ) / ( mass + mass2 ) )

  ;; now compute the new velocity for each particle along direction theta.
  ;; velocity perpendicular to theta is unaffected by a collision along theta,
  ;; so the next two lines actually implement the collision itself, in the
  ;; sense that the effects of the collision are exactly the following changes
  ;; in particle velocity.
  set v1t ( 2 * vcm - v1t )
  set v2t ( 2 * vcm - v2t )

  let d distance other-particle - ( size + [ size ] of other-particle ) / 2
  ;;; PHASE 4: convert back to normal speed/heading

  ;; now convert my velocity vector into my new speed and heading
  set speed recovery * sqrt ( ( v1t * v1t ) + ( v1l * v1l ) )
  ;; if the magnitude of the velocity vector is 0, atan is undefined. but
  ;; speed will be 0, so heading is irrelevant anyway. therefore, in that
  ;; case we'll just leave it unmodified.
  if v1l != 0 or v1t != 0
  [ let new-h ( theta - ( atan v1l v1t ) )
    set vx sin new-h * speed
    set vy cos new-h * speed
    setxy xcor + vx ycor + vy
  ]

  ;; and do the same for other-particle
  set speed2 recovery * sqrt ( ( v2t ^ 2 ) + ( v2l ^ 2 ) )
  if v2l != 0 or v2t != 0
  [ let new-h ( theta - ( atan v2l v2t ) )
    ask other-particle [
      set vx sin new-h * speed2
      set vy cos new-h * speed2
      setxy xcor + vx ycor + vy
    ]
  ]
end

to fragment-go
  setxy xcor + vx ycor + vy
  rt av
  if random 10 = 1
  [
    set av av * 2
    set size size / 2
    set burnout burnout * 1.5
    rt 90
    hatch 1 [ rt 180 ]
  ]
  set max-burnout max-burnout - 1

  ifelse max-burnout > 0
  [ if max-burnout < 10
    [ set color max-burnout ]
  ]
  [ die ]
end

to-report boundary-distance [ obj ]
  if not is-turtle? obj [ report world-width ]
  report ( distance obj - ( size / 2 ) - [ size / 2 ] of obj )
end

to ship-go
  set xcor xcor + vx
  set ycor ycor + vy
  ;; ask patches in-radius size [ set pcolor 9.9 ]
  if gun-temp > 0
  [ set gun-temp gun-temp - 1 ]
  let crowd rocks in-radius 20
  if any? crowd
  [ let close min-one-of crowd [ boundary-distance myself ]
    let dc abs boundary-distance close
    if dc <= 2 and dc >= 1
    [ fragment-setup turquoise 1 1 ]
    if ( dc < .5 ) [ ship-teleport ]
  ]
end

to bullet-go
  if seeker? and is-rock? target-rock
  [ lt .05 * subtract-headings heading towards target-rock ]
  jump bullet-speed
  let hits rocks with [ distance myself < size / 2 ]
  if any? hits [
    ask hits [ rock-explode ]
    set bullet-burnout -1

  ]
  set bullet-burnout bullet-burnout - 1
  if bullet-burnout <= 0 [ die ]
end

to ship-spin-ws
  ask the-ship [ set shape "_ship-001" lt 15 ]
end

to ship-spin-cw
  ask the-ship [ set shape "_ship-100" rt 15 ]
end

to ship-thrust
  ask the-ship
  [
    ;; get components of thrust vector
    let am pixel / 2
    set ax am * sin heading
    set ay am * cos heading

    ;; add to current velocity vector components
    let nvx vx + ax
    let nvy vy + ay

    ;; calculate new velocity magnitude
    let maxvm 1.00
    let nvm sqrt ( nvx * nvx + nvy * nvy )
    let svm ifelse-value ( nvm <= maxvm ) [ 1 ] [ nvm / maxvm ]

    set vx nvx / svm
    set vy nvy / svm

    ;; output-print " xcor ycor heading ax ay am vx vy vm"
    ;; foreach ( list xcor ycor heading ax ay am vx vy vm ) [ n -> output-type fixed n output-type " " ] output-print ""
    set shape "_ship-010"
  ]
end


to-report fixed [ n ]
  let m ifelse-value n < 0 [ "-" ] [ " " ]

  let ns ( word " " ( int n ) "." int ( 100 * ( ( abs n ) - ( abs int n ) ) ) "0" )
  set ns reverse substring reverse ns 0 7
  report ns
end

to ship-nothing
  ask the-ship
  [ set shape "_ship-000" ]
end


to message-go
  ;; draw character, if appropriate
  ;; at end of message, die
  let font-size 36
  let pix 1 / patch-size
  let char-width ceiling (font-size / patch-size / 1.5)
  let char-height font-size / patch-size * 2
  ifelse ( caret >= length text )
  [ die ]
  [
    let new-x pxcor
    if ( pxcor >= cursor )
    [
      let c item caret text
      if c = "W" or c = "m" or c = "M"
      [
        set new-x new-x + 1
        if new-x > max-pxcor - 1 [ set new-x min-pxcor ]
        set xcor new-x
        set cursor new-x
      ]
      if c = "i" or c = "l"
      [ set new-x new-x - 1
        set xcor new-x
        set cursor new-x
      ]
      set plabel c
      set caret caret + 1
      set cursor cursor + char-width
    ]
    ;; advance cursor
    set new-x new-x + 1
    if new-x > max-pxcor - 1 [ set new-x min-pxcor ]
    set xcor new-x
  ]
end

to message-setup [ $window# $text ]
  let this nobody
  let font-size 36
  let pix 1 / patch-size
  let char-width ceiling (font-size / patch-size / 1.5)
  let line-height ceiling(font-size / patch-size * 1.4)
  ;; get or create the indicated message line
  ifelse ( any? messengers with [ window# = $window# ] )
  [ ;; use existing messenger
    set this one-of messengers with [ window# = $window# ]
  ]
  [ ;; make a new messenger
    ;; since we can't be sure what is making the message,
    ;; ask a patch to do it, so we can use SPROUT with certainty.
    ask patch min-pxcor min-pycor
    [ sprout-messengers 1
      [ set this self ]
    ]
  ]
  ;; now work with the messenger
  ask this
  [
    set shape "cursor"
    set size 8
    set color black
    set text $text
    set window# $window#
    set show-cursor? false
    setxy ( min-pxcor + ceiling (char-width / 2) ) ( max-pycor - line-height * window# )
    let min-py pycor - ( line-height / 2 ) + 1
    let max-py pycor + ( line-height / 2 ) - 1
    set window patches with [ pycor >= min-py and pycor <= max-py ]
    ask window [ set plabel "" set pcolor white set plabel-color black ]
    set caret 0
    set cursor pxcor
    set hidden? true ;; not show-cursor?
  ]
end

to write-message
  let expiration timer + 10
  while [ any? messengers and timer < expiration ]
  [ repeat 5 [ ask messengers
    [ message-go
    ]]
    tick
  ]
  ask messengers [ die ]
end

to mouse-mode
  if ( mouse-inside? )
  [
    let diff [ -1 * subtract-headings towardsxy mouse-xcor mouse-ycor heading ] of the-ship
    let turn 0
    (
      ifelse
      ( diff > 0 )
      [ set turn 1 ]
      ( diff < 0 )
      [ set turn -1 ]
      ;; otherwise
      [ set turn 0 ]
    )
    ask the-ship [ lt diff / 2 ]
  ]
  ifelse ( mouse-down? )
  [ ifelse click = 0
    [ let void ship-fire
      set click 1
    ]
    [ ship-thrust

    ]
  ] [ set click 0 ]
end

to auto-pilot
  ask the-ship
  [ let diff 0
    let close rocks in-radius 20
    ifelse ( any? close )
    [
      set close min-one-of close [ distance myself ]
      ;if ( not member? close link-neighbors )
      ; [ ask my-links [ die ]
      ; create-link-with close
      ; ]
      let dd [ distance myself ] of close
      let rockspeed [ sqrt ( vx * vx + vy * vy ) ] of close
      let bullspeed bullet-speed
      let bx dx * bullspeed
      let by dy * bullspeed
      let frx [ xcor + vx * dd / bullspeed ] of close
      let fry [ ycor + vy * dd / bullspeed ] of close
      let frh towardsxy frx fry
      let fdist distancexy frx fry

      let fhdiff subtract-headings frh heading
      ;; let dist boundary-distance close

      ifelse ( abs fhdiff > 2 )
      [
        ifelse ( fhdiff < 0 )
        [ lt 5 ]
        [ rt 5 ]
      ]
      [
        ifelse ( fdist > 2 * ( bullet-speed * bullet-burnout ) )
        [ ship-thrust ]
        [
          if ship-fire
          [ if not any? reticules
            [ reticule-setup
            ]
            ask active-reticule
            [ set timeout timer + 2
              setxy frx fry
              show-turtle
              ; create-link-with close
              ; [ set thickness 2 * pixel
              ; set color violet
              ; ]

              hatch 1
              [ hide-turtle
                set active-reticule self
                set timeout 0
              ]
            ]
          ]
        ]
      ]
    ]
    [ let rnd random 100
      ( ifelse
        ( rnd < 5 ) [ ship-spin-ws ]
        ( rnd >= 40 and rnd < 55 ) [ ship-thrust ]
        ( rnd >= 90 and rnd < 95 ) [ ship-spin-cw ]
        [ let void ship-fire ]
      )
    ]
  ]
end

to GET-input
  if ( any? ships )
  [ ship-nothing
    ifelse ( full-auto? )
    [
      auto-pilot

    ]
    [
      if ( mouse-mode? )
      [
        mouse-mode
      ]
      ( ifelse
        ( keypress = "fire" ) [ let void ship-fire ]
        ( keypress = "ws" ) [ ship-spin-ws ]
        ( keypress = "cw" ) [ ship-spin-cw ]
        ( keypress = "t" ) [ ship-thrust ]
        [ ship-nothing ]
      )
      set keypress ""
    ]
  ]
end

to shapes-setup
  set-default-shape ships "_ship-000"
  set-default-shape rocks "rock-1"
  set-default-shape bullets "bullet"
  set-default-shape fragments "fragment"
  set-default-shape messengers "cursor"
end

to startup
  clear-all
  reset-ticks
  message-setup 1 "Please press RUN"
  write-message
  tick
end

to globals-setup
  set pixel 1 / patch-size
  set active-reticule nobody

end

to rocks-setup
  if num-rocks = false or num-rocks < 5 [ set num-rocks 5 ]
  repeat num-rocks [ setup-rock ]
  let retry-limit 50
  let too-many-rocks true
  while [ too-many-rocks and retry-limit > 0 ]
  [
    set too-many-rocks false
    ASK ROCKS
    [ LET too-close OTHER ROCKS IN-RADIUS (SIZE * 2)
      LET is-too-close? ANY? too-close
      SET too-many-rocks too-many-rocks OR is-too-close?
      IF is-too-close?
      [
        RT RANDOM 360
        JUMP 1
      ]

      SET retry-limit retry-limit - 1
    ]
  ]
end

to ship-teleport
  let max-jumps 100
  let crowd rocks in-radius 20
  hatch-HS-effects 1
  [ set size 3
    set color violet
    set effect-direction 1
    set shape "circle"
  ]
  while
  [
    max-jumps > 0
    and
    any? crowd with [ boundary-distance myself < 2 ]
  ]
  [
    fragment-setup green 0 1
    setxy random-xcor random-ycor
    set vx 0
    set vy 0
    set crowd rocks in-radius 10
    set max-jumps max-jumps - 1
    ;display
  ]
  hatch-HS-effects 1
  [ set color red
    set size 20
    set effect-direction -1
    set shape "circle"
  ]
  fragment-setup lime 1 2
end



to clock-setup
  create-clocks 1
  [ set shape "clock"
    set start-time 0
    set current-time 0
    set elapsed-time 0
    set cumulative-time 0
    set pause-until 0
    set clock-on false
    set size 3
    setxy 0 max-pycor - size / 2 - pixel
  ]
end

to game-setup
  set score 0
  globals-setup
  shapes-setup
  game-clear
  rocks-setup
  logo-display
  directions-display
  write-message
  clock-setup
  stop-inspecting-dead-agents
  set setup-finished true
  reset-ticks
end


to new-game
  set score 0
  game-clear
  rocks-setup
  ship-setup
  set setup-finished true
end




to directions-display
  message-setup 5 "THE MISSION:"
  write-message
  message-setup 6 "DESTROY RUBBLE."
  write-message
  message-setup 7 "-PRESS START-"
end

to game-go
  ifelse ( setup-finished = 0 ) [ game-setup ]
  [ get-input
    ask ships [ ship-go ]
    ask bullets [ bullet-go ]
    set rock-color white
    ;; ifelse-value ( random 100 < 10 ) [ 1 + random-float 1 + 2.9 * random 2 ] [ white ]
    ask rocks [ rock-go ]
    ask fragments [ fragment-go ]
    ask messengers [ message-go ]
    ask reticules [ reticules-go ]
    ask HS-effects
    [
      ifelse ( size < 3 or size > 20 )
      [ die ]
      [ set size size + effect-direction ]
    ]
    ;; ask aliens [ GO-alien ]
    ;; if ( not ( any? ships or any? messengers ) ) [ messenger-setup 1 "PRESS PLAY" ]
    if ( not ( any? rocks ) )
    [ set num-rocks num-rocks * 1.25 rocks-setup
      ask ships [ home set vx 0 set vy 0 ]
    ]
    ask patches
    [ let hue ifelse-value (is-list? pcolor) [pcolor ][ extract-rgb pcolor ]
      set rr item 0 hue ^ 2 * .95
      set gg item 1 hue ^ 2 * .95
      set bb item 2 hue ^ 2 * .95
    ]
    diffuse rr .2
    diffuse gg .2
    diffuse bb .2
    ask patches
    [ set pcolor rgb sqrt rr sqrt gg sqrt bb
    ]
  ]
  tick
end

to logo-display
  clear-patches
  ask letters [ die ]
  tick
  ;; ask patches with [ ( pxcor + pycor ) mod 2 = 0 ] [ set pcolor ( 2.5 + black ) ]
  let logo0 "RUBBLE"
  let logo1 "TROUBLE"
  logo-animate logo0 0
  logo-animate logo1 1
  ;display
end

to logo-animate [ logo line ]
  let len length logo
  let letter-size ( world-width ) / ( len )
  let start-x min-pxcor + ( world-width - 1 ) / 2 - ( ( len * letter-size ) / 2 ) + .5 * letter-size
  let line-height 1.5
  let these-letters no-turtles
  foreach range len
  [
    [ t ] ->
    create-letters 1
    [
      let c item t logo
      let pos-x letter-size * t
      setxy ( start-x + pos-x ) max-pxcor - letter-size * line * line-height
      if ( c = " " ) [ set c "space" ]
      set shape word "logo-" c
      set size letter-size
      set color base-color
      set heading 0
      set base-xcor xcor
      set base-size size
      set base-color white
      set color base-color
      set base-heading heading
      setxy 0 min-pycor
      set size 0
      set these-letters ( turtle-set these-letters self )
    ]
  ]
  let top-y ( world-height - 1 ) - ( .5 * letter-size ) - line * letter-size * line-height
  (
    foreach ( range 0 1.0 ( 2 / 30 ) )
    [
      [ ratio ] ->
      let y min-pycor + top-y * ratio
      let m2 ratio * letter-size
      ask these-letters
      [
        set size m2
        set ycor y
        set xcor base-xcor * ratio
      ]
      tick
      wait 1 / 30
    ]
  )
  set pixel 1 / patch-size
  let thick PIXEL * 16
  let lcolor lime - 3.5
  ask letters
  [ let mythick thick
    LET MYCOLOR LCOLOR
    repeat 4
    [ hatch 1
      [ set color MYCOLOR
        x_set-line-thickness mythick
        set mythick mythick / 2
        SET MYCOLOR MYCOLOR + 2
      ]
    ]
    DIE
  ]
  ;
end

to play-note [ $inst $key $vel $dur ]
  ;; sound:play-note $inst $key $vel $dur
end

to play-note-later [ $delay $inst $key $vel $dur ]
  ;; sound:play-note-later $delay $inst $key $vel $dur
end

to play-drum [ $inst $vel ]
  ;; sound:play-drum $inst $vel
end
to stop-music
  ;; sound:stop-music
end

to sfx [ fx option ]

  (
    ifelse
    ( fx = "explode-rock" )
    [
      play-drum "CRASH CYMBAL 2" 12
      play-note-later .10 "timpani" ( 45 - option * 4 ) 64 + option .3
      play-note "timpani"
      ( 42 - option * 2 ) 64 + option .1
    ]
    ( fx = "ship-explode" )
    [
      play-drum "CRASH CYMBAL 2" 127
      play-note-later .20 "timpani" 42 100 .1
      play-note-later .10 "timpani" 42 100 .1
      play-note "timpani" 40 64 .1
    ]
    ( fx = "pew" )
    [
      let fxarppegio-steps 5
      let fxkeys map [ r -> 42 - r * 3 ] ( range fxarppegio-steps )
      let fxvelocity 48
      let fxduration .02 * fxarppegio-steps
      let fxdelay-step fxduration / fxarppegio-steps
      foreach ( range fxarppegio-steps )
      [ [ i ] ->
        play-note-later ( i * fxdelay-step ) "SYNTH BRASS 1" ( item i fxkeys ) fxvelocity fxdelay-step
      ]
    ]
    [
      stop-music
    ]
  )
end

;; The following code was publsihed by and released to the Public Domain by Uri Wilensky,
;; and was obtained from the NetLogo v 6.3 Model Library.
;; note that the 6.2.2 version used TAN 90, which is mathematically undefined, but
;; netlogo used to incorrectly report as a value

;; reports a two-item list of x and y coordinates, or an empty
;; list if no intersection is found
to-report intersection [ t1 t2 ]
  let is-t1-vertical? ( [ heading ] of t1 = 0 or [ heading ] of t1 = 180 )
  let is-t2-vertical? ( [ heading ] of t2 = 0 or [ heading ] of t2 = 180 )

  ;; is t1 vertical? if so, swap the two turtles, and run again.
  ;; ( unless both are vertical, i.e. they are parallel--report an empty list )
  ifelse ( is-t1-vertical? )
  [
    ifelse ( is-t2-vertical? )
    [ report [ ]
    ]
    [ report intersection t2 t1
    ]
    ;; report ends the procedure immediately
  ]
  [
    let m1 [ tan ( 90 - heading ) ] of t1

    ;; is t2 vertical? if so, handle specially
    ifelse ( is-t2-vertical? )
    [
      ;; represent t1 line in slope-intercept form ( y=mx+c )
      let c1 [ ycor - xcor * m1 ] of t1
      ;; t2 is vertical so we know x already
      let x [ xcor ] of t2
      ;; solve for y
      let y m1 * x + c1
      ;; check if intersection point lies on both segments
      ifelse [ not x-within? x ] of t1 or [ not y-within? y ] of t2
      [
        report [ ]
      ]
      [
        report list x y
      ]
    ]
    [
      let m2 [ tan ( 90 - heading ) ] of t2

      ;; treat parallel/collinear lines as non-intersecting
      ifelse m1 = m2
      [
        report [ ]
      ]
      [

        ;; now handle the normal case where neither turtle is vertical;
        ;; start by representing lines in slope-intercept form ( y=mx+c )
        let c1 [ ycor - xcor * m1 ] of t1
        let c2 [ ycor - xcor * m2 ] of t2
        ;; now solve for x
        let x ( c2 - c1 ) / ( m1 - m2 )
        ;; check if intersection point lies on both segments
        ifelse [ not x-within? x ] of t1 or [ not x-within? x ] of t2
        [
          report [ ]
        ]
        [
          report list x ( m1 * x + c1 ) ]
      ]
    ]
  ]
end

to-report x-within? [ x ] ;; turtle procedure
  report abs ( xcor - x ) <= abs ( size / 2 * dx )
end

to-report y-within? [ y ] ;; turtle procedure
  report abs ( ycor - y ) <= abs ( size / 2 * dy )
end

;; below only for when generating a new thumbnail image for the commons
;to setup
; clear-all
; startup
; new-game
; set num-rocks 15
; rocks-setup
;end
;to go
; repeat 15 [ game-go wait 1 / 30 ]
;end
@#$#@#$#@
GRAPHICS-WINDOW
5
10
472
478
-1
-1
9.0
1
36
1
1
1
0
1
1
1
-25
25
-25
25
1
1
1
ticks
30.0

BUTTON
520
55
645
88
RUN
every ( 1 / 30 ) [ game-go ]
T
1
T
OBSERVER
NIL
O
NIL
NIL
1

BUTTON
585
300
640
333
:' ' ''v
set keypress \"cw\"
NIL
1
T
OBSERVER
NIL
D
NIL
NIL
1

BUTTON
525
300
580
333
v' ' ':
set keypress \"ws\"
NIL
1
T
OBSERVER
NIL
A
NIL
NIL
1

BUTTON
555
265
610
298
\V/
set keypress \"t\"
NIL
1
T
OBSERVER
NIL
W
NIL
NIL
1

BUTTON
525
345
580
378
fire
set keypress \"fire\"
NIL
1
T
OBSERVER
NIL
\
NIL
NIL
1

SWITCH
520
210
645
243
mouse-mode?
mouse-mode?
0
1
-1000

BUTTON
585
345
640
378
fire
set keypress \"fire\"
NIL
1
T
OBSERVER
NIL
5
NIL
NIL
1

BUTTON
520
100
645
133
START
new-game
NIL
1
T
OBSERVER
NIL
T
NIL
NIL
1

SWITCH
520
160
645
193
full-auto?
full-auto?
0
1
-1000

BUTTON
520
10
645
43
RESET
startup
NIL
1
T
OBSERVER
NIL
R
NIL
NIL
1

@#$#@#$#@
digit excluding zero ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
digit                ::= "0" | digit excluding zero ;
alpha upper case           ::= "A" | "B" | "C" | "D" | "E" | "F" | "G"
                      | "H" | "I" | "J" | "K" | "L" | "M" | "N"
                      | "O" | "P" | "Q" | "R" | "S" | "T" | "U"
                      | "V" | "W" | "X" | "Y" | "Z" ;
alpha lower case ::=  "a" | "b"
       | "c" | "d" | "e" | "f" | "g" | "h" | "i"
       | "j" | "k" | "l" | "m" | "n" | "o" | "p"
       | "q" | "r" | "s" | "t" | "u" | "v" | "w"
       | "x" | "y" | "z" ;

alpha  ::= alpha upper case | alpha lower case ;

alpha numeric ::= alpha | digit ;

symbol ::= "#", "$", "%" ... ;

space ::= " " ;

crlf ::= "\n" ;

song ::= { [line, { crlf, line} ] ;

line number ::= digt excluding zero, { digit }, space ;

data statement ::= "DATA", {space} ;

music string ::=  { { command }, {note}, {label} } ;

command letter ::= "O" | "V" | "L" ;

command parameter ::= digit;

command ::= command letter, command parameter;

label ::= "{" , alphanumeric, "}";

note ::= note value, [ octave value ], [ accidental ], [note length character ], [dot] ;

note value ::= "c" | "d" | "e" | "f" | "g" | "a" | "b" ;

octave value ::= digit;

accidental ::= sharp | flat

sharp ::= "#" ;

flat ::= "p" ;

note length character ::= "w" | "h" | "q" | "i" | "x" ;

dot ::= "." | ":"
@#$#@#$#@
default
true
0
Polygon -7500403 true true 150 5 40 250 150 205 260 250

0
false
0
Polygon -16777216 true false 60 45 75 30 90 15 105 15 120 30 210 30 255 75 255 240 270 270 240 300 75 300 45 270 30 165 45 60
Polygon -7500403 true true 60 77 93 76 93 242 119 257 185 255 193 282 120 285 64 260
Polygon -7500403 true true 74 41 213 281 243 262 96 25
Polygon -7500403 true true 127 59 182 60 200 76 204 185 226 218 229 77 201 36 111 35

1
false
0
Polygon -16777216 true false 45 60 105 0 195 0 195 210 225 210 240 285 210 300 75 300 45 270 60 210 75 210 75 90
Polygon -7500403 true true 76 272 78 237 119 236 121 59 73 61 116 15 167 15 166 243 216 237 206 287

10
false
0
Polygon -7500403 true true 41 88 62 109 98 72 95 255 47 254 50 282 150 285 159 253 129 249 135 53 109 26
Polygon -7500403 true true 168 77 191 52 264 50 293 82 290 241 265 275 229 279 228 243 265 235 267 88 210 88 195 233 215 246 214 279 179 269 164 240

2
false
0
Polygon -16777216 true false 45 135 15 75 60 15 105 0 150 0 225 0 270 75 270 135 195 195 270 195 285 285 150 300 15 285 30 210 105 150
Rectangle -7500403 true true 223 223 223 225
Polygon -7500403 true true 254 242 229 277 53 268 63 226 146 152 177 116 174 37 127 35 122 91 103 117 59 106 53 73 100 22 151 9 218 27 237 82 233 118 145 192 97 228 230 208

3
false
0
Polygon -16777216 true false 90 105 30 60 60 0 150 0 225 0 255 60 240 135 270 225 240 300 150 300 60 300 15 240 75 180
Polygon -7500403 true true 108 87 132 53 176 57 191 88 160 125 113 130 112 169 163 171 191 209 190 227 152 257 124 254 91 212 53 228 91 282 150 297 217 275 244 216 228 162 191 147 229 115 231 68 207 30 163 9 107 7 56 50

4
false
0
Polygon -16777216 true false 15 135 105 0 255 0 225 105 270 120 285 195 210 210 255 255 255 300 60 300 60 255 90 225 15 195
Polygon -7500403 true true 139 16 47 142 49 176 144 176 137 253 108 255 106 285 226 283 232 249 181 248 189 178 250 177 256 135 193 141 213 13 176 12 144 148 91 140 162 13

5
false
0
Polygon -16777216 true false 15 180 60 15 120 0 270 15 225 90 120 60 120 105 210 105 270 165 255 255 210 300 75 300 0 225 30 180
Polygon -7500403 true true 245 24 213 70 106 36 91 135 137 121 189 122 226 161 233 196 225 246 174 282 105 288 54 242 29 220 75 196 115 268 161 259 178 206 173 144 127 148 85 173 39 160 96 15

6
false
0
Polygon -16777216 true false 30 60 75 0 240 0 285 60 270 120 240 120 285 180 285 255 225 300 75 300 15 255 0 120
Polygon -7500403 true true 254 97 260 67 216 27 174 12 101 17 57 65 24 156 44 229 92 276 170 288 227 259 271 220 254 158 197 122 131 113 99 124 95 138 121 169 143 136 199 149 211 217 168 268 102 258 84 166 91 112 115 38 178 37 193 74 226 97

7
false
0
Polygon -16777216 true false 45 15 270 15 270 60 165 300 45 300 150 105 15 105
Polygon -7500403 true true 81 27 242 35 131 286 88 284 188 68 58 76

8
false
0
Polygon -16777216 true false 60 105 45 45 75 0 225 0 270 45 270 120 225 150 255 210 255 270 210 300 75 300 15 255 15 180
Polygon -7500403 true true 99 84 177 215 181 258 147 260 105 240 101 180 117 164 92 127 63 153 38 197 88 276 159 296 232 269 218 195 183 146 142 74 140 31 185 35 196 85 179 94 194 133 229 102 243 51 188 7 121 0 85 25 81 63

9
false
0
Polygon -16777216 true false 30 180 15 135 15 45 60 0 240 0 285 45 285 240 255 285 195 300 90 300 30 270 30 225 90 195 135 225 135 195
Polygon -7500403 true true 180 134 123 133 96 114 95 58 129 34 185 35 205 55 205 212 168 260 106 258 85 231 56 242 72 266 94 278 155 291 224 266 254 211 251 47 221 23 169 1 122 4 83 21 49 52 50 100 57 129 78 153 141 170 186 171

_ship-000
true
4
Polygon -1184463 false true 150 210 90 225 45 255 30 240 150 0 270 240 255 255 210 225
Circle -1 true false 90 90 120

_ship-001
true
4
Polygon -1184463 false true 150 210 90 225 45 255 30 240 150 0 270 240 255 255 210 225
Polygon -1184463 false true 210 225 255 255 195 300
Circle -1 true false 90 90 120

_ship-010
true
4
Polygon -1184463 false true 150 210 90 225 45 255 30 240 150 0 270 240 255 255 210 225
Polygon -1184463 false true 210 225 150 300 90 225 150 210
Circle -1 true false 88 88 124

_ship-011
true
4
Polygon -1184463 false true 150 210 210 225 255 255 270 240 150 0 30 240 45 255 90 225
Polygon -1184463 false true 210 225 255 255 195 300
Polygon -1184463 false true 90 225 150 300 210 225 150 210
Circle -1 true false 90 90 120

_ship-100
true
4
Polygon -1184463 false true 150 210 90 225 45 255 30 240 150 0 270 240 255 255 210 225
Polygon -1184463 false true 90 225 45 255 105 300
Circle -1 true false 90 90 120

_ship-110
true
4
Polygon -1184463 false true 150 210 90 225 45 255 30 240 150 0 270 240 255 255 210 225
Polygon -1184463 false true 90 225 45 255 105 300
Polygon -1184463 false true 210 225 150 300 90 225 150 210
Circle -1 true false 90 90 120

bullet
true
0
Line -7500403 true 150 0 150 300

burst
true
0
Line -7500403 true 146 16 150 36
Line -7500403 true 191 23 184 41
Line -7500403 true 240 52 215 73
Line -7500403 true 270 101 229 119
Line -7500403 true 259 152 276 147
Line -7500403 true 252 180 285 199
Line -7500403 true 239 211 250 219
Line -7500403 true 202 237 223 261
Line -7500403 true 184 255 184 260
Line -7500403 true 143 259 156 300
Line -7500403 true 118 247 89 285
Line -7500403 true 86 230 77 235
Line -7500403 true 72 207 34 220
Line -7500403 true 56 162 46 160
Line -7500403 true 58 134 3 130
Line -7500403 true 21 183 43 177
Line -7500403 true 61 195 57 198
Line -7500403 true 38 109 46 112
Line -7500403 true 24 77 62 93
Line -7500403 true 62 62 67 66
Line -7500403 true 62 28 117 66
Line -7500403 true 116 12 128 41
Line -7500403 true 124 93 126 125
Line -7500403 true 186 97 178 106
Line -7500403 true 107 194 124 181
Line -7500403 true 202 203 189 191

circle
false
11
Circle -8630108 false true 13 13 272

clock
true
6
Circle -13840069 false true 0 0 300
Circle -13840069 false true 30 30 240
Polygon -13840069 false true 135 165 150 30 165 165

cursor
false
0
Rectangle -7500403 true true 105 30 195 270

explosion
true
0
Polygon -7500403 true true 105 164 73 151 104 139 85 110 133 127 128 88 148 105 170 90 174 117 206 119 179 140 209 155 157 158 178 179 148 175 148 206 127 181 84 200 86 173 1 165 56 136 26 83 96 89 105 15 145 63 204 14 196 79 281 70 245 105 296 129 223 143 295 175 210 184 244 262 196 209 182 285 167 209 100 283 115 224 31 234

fragment
true
0
Line -7500403 true 135 165 195 120

logo-b
true
6
Polygon -13840069 false true 15 0 240 0 285 60 270 135 210 180 255 225 240 270 195 300 90 300
Polygon -13840069 false true 120 195 180 195 210 225 195 255 180 270 135 270
Polygon -13840069 false true 90 60 195 60 225 90 225 120 195 150 105 150

logo-e
true
6
Polygon -13840069 false true -46 0 254 0 239 60 38 60 49 151 161 151 155 195 52 196 64 270 186 270 179 300 29 300

logo-l
true
6
Polygon -13840069 false true 105 300 30 15 105 0 150 255 255 255 255 300

logo-o
true
6
Polygon -13840069 false true 270 105 225 270 180 300 120 300 75 270 30 105 45 45 75 15 120 0 180 0 225 15 255 45
Polygon -13840069 false true 210 105 195 180 180 255 165 270 135 270 120 255 105 180 90 105 105 75 135 60 165 60 195 75

logo-r
true
6
Polygon -13840069 false true 75 300 15 0 240 0 284 54 270 135 210 180 180 180 255 300 210 300 135 180 105 180 120 300
Polygon -13840069 false true 85 46 221 46 214 121 95 121

logo-space
true
6

logo-t
true
6
Polygon -13840069 false true 15 75 0 0 300 0 285 75 195 75 180 300 120 300 105 75

logo-template
true
6
Polygon -1184463 false false 2 8 75 300 120 300 75 0 225 0 180 300 225 300 300 0 300 60 0 60 0 150 300 150 300 195 0 195 0 270 300 270 300 300 0 300

logo-u
true
6
Polygon -13840069 false true 255 195 225 270 180 300 120 300 75 270 45 195 0 15 15 0 60 0 75 15 120 255 120 255 135 270 165 270 180 255 225 15 240 0 285 0 300 15

meteor0
true
0
Polygon -2674135 true false 75 195 120 225 180 225 225 195 255 255 255 300 210 345 195 390 210 450 240 480 195 450 165 390 165 345 195 300 180 270 150 285 150 375 150 435 120 345 120 300 105 345 75 405 90 345 90 285 45 315 30 375 45 435 60 480 30 435 0 360 15 285 60 225
Circle -7500403 true true 60 60 180

meteor1
true
0
Polygon -2674135 true false 225 195 180 225 120 225 75 195 45 255 45 300 90 345 105 390 90 450 60 480 105 450 135 390 135 345 105 300 120 270 150 285 150 375 150 435 180 345 180 300 195 345 225 405 210 345 210 285 255 315 270 375 255 435 240 480 270 435 300 360 285 285 240 225
Circle -7500403 true true 59 59 182

meteor2
true
0
Circle -7500403 true true 73 -1 153
Polygon -2674135 true false 75 90 30 225 90 150 60 255 120 165 105 285 150 165 165 300 180 165 225 270 210 135 270 225 225 90 195 105 180 135 150 120 135 135 105 120

meteor3
true
0
Circle -7500403 true true 74 -1 153
Polygon -2674135 true false 225 90 255 165 210 150 225 210 180 165 180 255 150 165 120 240 120 165 75 210 90 135 30 180 75 90 90 120 120 120 150 135 180 135 210 120

missle
true
4
Polygon -1184463 false true 105 285 150 0 195 285 150 210

reticule
true
0
Circle -7500403 false true 30 30 240
Line -7500403 true 0 150 300 150
Line -7500403 true 150 0 150 300

rock-1
true
0
Polygon -7500403 false true 150 0 255 30 300 135 255 270 120 300 30 240 0 150 45 30

rock-2
true
0
Polygon -7500403 false true 75 15 195 0 300 120 270 270 105 300 15 225 0 90 60 75

rock-3
true
0
Polygon -7500403 false true 45 270 60 195 0 105 75 0 225 0 300 150 270 255 150 300

rock-4
true
0
Polygon -7500403 false true 30 270 45 150 0 120 75 0 255 60 300 150 270 255 150 300

rock-5
true
6
Rectangle -13840069 false true 105 195 195 240
Polygon -13840069 false true -15 150 0 165 45 180 120 195 180 195 225 180 255 165 300 150
Polygon -13840069 false true 105 150 150 0 195 150
Line -13840069 true 75 300 150 165
Line -13840069 true 165 225 285 285

skull0
false
0
Polygon -16777216 true false 75 0 45 45 30 90 45 135 75 180 75 240 120 270 180 270 225 240 225 180 255 135 270 90 255 45 225 0 180 -15 120 -15
Polygon -1 true false 90 165 90 225 135 255 165 255 210 225 210 165
Circle -1 true false 54 -6 192
Circle -16777216 true false 75 45 60
Circle -16777216 true false 165 45 60
Polygon -16777216 true false 141 76 150 90 157 74 165 150 150 120 135 150
Line -16777216 false 105 195 195 195
Line -16777216 false 90 165 105 195
Line -16777216 false 195 195 210 165
Line -16777216 false 105 210 105 165
Line -16777216 false 150 210 150 165
Line -16777216 false 195 210 195 165
Line -16777216 false 120 210 135 165
Line -16777216 false 180 210 165 165

skull1
false
0
Polygon -16777216 true false 75 0 45 45 30 90 45 135 75 180 75 255 120 285 180 285 225 255 225 180 255 135 270 90 255 45 225 0 180 -15 120 -15
Polygon -1 true false 90 180 90 240 135 270 165 270 210 240 210 180
Circle -1 true false 54 -6 192
Circle -16777216 true false 75 45 60
Circle -16777216 true false 165 45 60
Polygon -16777216 true false 141 76 150 90 157 74 165 150 150 120 135 150
Line -16777216 false 105 195 195 195
Line -16777216 false 90 165 105 195
Line -16777216 false 195 195 210 165
Line -16777216 false 105 210 105 165
Line -16777216 false 150 210 150 165
Line -16777216 false 195 210 195 165
Line -16777216 false 120 210 135 165
Line -16777216 false 180 210 165 165
Line -16777216 false 105 240 105 195
Line -16777216 false 120 240 135 195
Line -16777216 false 150 240 150 195
Line -16777216 false 180 240 165 195
Line -16777216 false 195 240 195 195
Polygon -16777216 true false 90 165 105 195 195 195 210 165 225 195 195 225 105 225 75 195

ufo
false
4
Rectangle -1184463 false true 15 135 285 180
Rectangle -1184463 false true 60 120 239 194
Rectangle -1184463 false true 104 104 197 211

x
false
0
Polygon -7500403 true true 270 75 225 30 30 225 75 270
Polygon -7500403 true true 30 75 75 30 270 225 225 270
@#$#@#$#@
NetLogo 6.3.0
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
@#$#@#$#@
default
0.0
-0.2 0 0.0 1.0
0.0 1 1.0 0.0
0.2 0 0.0 1.0
link direction
true
0
Line -7500403 true 150 150 90 180
Line -7500403 true 150 150 210 180
@#$#@#$#@
1
@#$#@#$#@
