clix-game_2009


Information

Created with NetLogo version NetLogo 4.1beta3
Running with NetLogoLite.jar version 411.


WHAT IS IT?


A half-completed block-clicking game.

HOW TO USE IT


Click New Game to reset the field and score.
Click Play to activate the game.
Click on blocks to try to bust them. Only groups of 3 or more of the same color will break.
If you can't find any to break, click TUMBLE!
If you tumble 5 times in a row, GAME-OVER!

EXTENDING THE MODEL


Add more rules. Make it so that levels advance! Make it so that auto-tumble is possible (same rules the auto-play rules use to detect auto-tumble.) Make the auto-player smarter--clicking larger groups first, or planning ahead to create larger groups.
Add "special" blocks (use turtles for special block shapes), like one that removes an entire row or column, or a "wild-card" block, or a block that matches all the blocks around it, when it is clicked...

NETLOGO FEATURES


For the blocks, just patches and patch variables are used. The Mouse features are used (of course). The sparks that occur when a block is removed are turtles! This game uses the "every" command to control game timing.
The floating scores are also turtles... the number is converted to a series of turtles that look like numbers. they have an "index" variable that tells them what order to appear in.
There are sound features in this model, but they are disabled for posting to the web. Remove comments from PLAY-NOTE and extensions commands!

XML TAGS


<info>
<summary>A block-busting game!</summary>
<copy>Copyright (C) 2005,2009 James P. Steiner</copy>
</info>

Procedures

NetLogo Version: NetLogo 4.1beta3


 ;; remove comment symbols below and at bottom (on "to noise") to enable sounds
 ;; extensions [ Sound ]

globals
[ click?      ;; used by the mouse handler to tell if the mouse is down
  click       ;; 
  click-start ;; 
  click-list ;; list of locations that the mouse has been clicked
             ;; in other words, the input buffer
  game-area  ;; agentset of patches in the play area
  top-row    ;; agentset of top row of play area
  bottom-row ;; agentset of bottom row of play area
  left-most  ;; xcor of the left most col in the play area
  right-most ;; xcor of the right most col in the play area
  top-most   ;; ycor of the top most row in the play area
  bottom-most  ;; ycor of the top most row in the play area
  block-fade-time ;; how long for clicked groups to fade to black and vanish
  score      ;; current score
  tumble!    ;; flag that tells the game to tumble the blocks
  next-click ;; holds the time that the auto-player will click again.
  tumble-count ;; holds count of number of consecutive tubles
  tumble-limit ;; holds the limit of tumbles before game over
  game-over?  ;; flag that tells the game that the game is over
  level       ;; the current difficulty
  tumbling?   ;; true when a tumble happens, affects the way things fall
] 

patches-own
[ timeout     ;; 
  color-group ;; used when testing clicks
  mode ; 0 = normal, 1 = clicked / needs testing, 2 = vanishing, 3 = falling, 4 = new
  game-area? ;; is this patch in the game area
  temp       ;; temporary--various uses
  my-column  ;; contains the patch that is at the base of this patch's column
]

breed [ sparks ]
breed [ scores ]
breed [ blocks ]

sparks-own
[ lifespan ;; sparks go out when lifespan reaches 0
  ddx      ;; acceleration in x
  ddy      ;; acceleration in y
]

scores-own
[ my-group ;; group the numbers together (not really used yet)
  lifespan ;; when this reaches 0, scores disappear
  my-index ;; position of the number in the group
]

to startup
   setup
end   

to setup
  ca
  setup-sparks
  set level difficulty
  ask patches [ set color-group -1 set game-area? false set my-column nobody ]
  set left-most min-pxcor + 1
  set right-most (max-pxcor) - 1
  set top-most max-pycor - 1
  set bottom-most min-pycor  + 1
  set game-area patches with [ pxcor >= left-most and pxcor <= right-most and pycor >= bottom-most and pycor <= top-most ]
  set bottom-row game-area with [ pycor = bottom-most ]
  ask bottom-row [ set my-column game-area with [ pxcor = [pxcor] of myself ] ]
  set top-row game-area with [ pycor = top-most ]
  set block-fade-time .25
  
  ask game-area
  [ set game-area? true
    initialize-patch
    ; set mode 4
  ]
  ask bottom-row
  [ let eat random 5 
    ask my-column with [ pycor > top-most - eat ] [ set pcolor black ]
  ]
  set click 0
  set click? false
  set click-list []
  set tumble-count 0
  set tumble-limit 5
  set game-over? false
  set level difficulty
  let colors remove-duplicates [ pcolor ] of patches 
  print (word "There are " (length colors - 1) " unique colors")
end

to setup-sparks
   set-default-shape sparks "spark"
end

to watch-click
  if mouse-down? and click = 0
  [ set click 1 
    set click-start patch (round mouse-xcor) (round mouse-ycor)
  ]
  if (not mouse-down? ) and click = 1
  [ if     click-start = patch (round mouse-xcor) (round mouse-ycor)
    [ set click-list lput click-start click-list
    ]
    set click 0
  ]
end
   
   
to-report get-clicked [ check-or-get ]
    let clicked-item 0
  
    ifelse check-or-get = 0
    [ report (length click-list > 0) ]
    [ set clicked-item first click-list
      set click-list but-first click-list
      report clicked-item
    ]
end
              


to go
  let xclick 0
  let yclick 0
  let clicked 0
  
  if game-over? = 2 [ setup ]
  every .05
  [
    ifelse game-over? != false
    [ go-game-over
      if game-over? = 2 [ stop ]
    ]
   [
      ;; always watch for click-events
      ;; check for click event
      if not auto-play? [ watch-click ]
      
      ;; always do sparks
      go-sparks
      ;; always do scores
      go-scores
      
      ;; any open blocks? let blocks fall in, set as needing testing,
      ;; unless these are add-in blocks
      ifelse any?  game-area with [ pcolor = black and [pcolor] of patch-at 0 1 > white ]
      [ noise 1 (20 + random 40) .5
        let index min-pycor + 1
        ifelse tumbling?
        [ ;; fall slightly differently after a tumble
        repeat world-height - 1
        [ ask game-area with [ pycor = index and pcolor != black and any? game-area at-points [ [ -1 -1 ] [ 0 -1][1 -1]] with [ pcolor = black ] ]
          [ let below one-of game-area at-points [ [ -1 -1 ] [ 0 -1][1 -1]] with [ pcolor = black ]
            if is-patch? below
            [ ask below
              [ set pcolor [ pcolor ] of myself
                set mode [ mode ] of myself
              ]
              set pcolor black
              set mode 0
            ]
          ]
          set index index + 1
        ]
        ][ 
        repeat world-height
        [ ask game-area with [ pycor = index and pcolor = black and [pcolor] of patch-at 0 1 > white ]
          [ set pcolor [pcolor] of patch-at 0 1
            set mode [mode] of patch-at 0 1
            ask patch-at 0 1
            [ set pcolor black
              set mode 0
            ]
          ]
          set index index + 1
        ]
        ]
      ] [
      ;; above will continue until all falling blocks have fallen
       
         set tumbling? false       
         ;; now, if there are any empty columns (bottom row cell is black),
         ;; slide columns left or right, toward center column
         ;; find left-most non-empty column
         let left-x 0
         let right-x 0
         if any? (bottom-row with [ pcolor != black ])
         [ set left-x min [ pxcor ] of (bottom-row with [ pcolor != black ])
           set right-x max [ pxcor ] of (bottom-row with [ pcolor != black ])
         ]
         ;; find center-most empty column
         let empty-column max-one-of (bottom-row with [ pxcor > left-x and pxcor < right-x and pcolor = black  ]) [ abs pxcor ]
         ifelse is-patch? empty-column
         [ let direction 1
           ask empty-column [ set pcolor white ]
           ifelse [pxcor] of empty-column = 0
           [ set direction (((random 2) * 2) - 1)
           ]
           [ if [pxcor] of empty-column < 0
             [ set direction -1 ]
           ]
           ask [my-column] of empty-column
           [ set pcolor [pcolor] of patch-at direction 0
             ask patch-at direction 0 [ set pcolor black ]
           ]
         ][
       
      ;; now that all falling blocks have settled      
      ;; examine blocks marked to be tested (mode = 3)
      ifelse any? game-area with [ mode = 3 ]
      [ ask game-area with [ mode = 3 ]
        [ test-block ]
      ] [
      
      ;; now that all blockes have been tested
      ;; (and now that any cascading fall / test cycles have ended)
      ;; unmark fall-only blocks (change 4 to 0)
      ask game-area with [ mode = 4 ]
      [ set mode 0 ]
      
      ;; there's probably some blocks to fade.
      ;; fade them
      ifelse any? game-area with [ mode = 2 ]
      [ ask game-area with [ mode = 2 ]
        [ set pcolor scale-color pcolor (timeout - timer) (0) (block-fade-time)
          if timer > timeout 
          [ make-spark
            set pcolor black
            set mode 0
            set timeout 0
            
          ]
        ]
      ] [ ;; see if there's any tumbling to do
            ;;
      ifelse tumble! = true
      [ tumble 
        
      ]
      [
  
      
    
      
      ;; finally, things have settled down
      ;; so lets check for auto-play or user input
      ;; that is, a click event.
      

      ifelse auto-play?
      [ ;; auto-play is on, so get a click from the selectect
        ;; auto-player
        set clicked auto-player-click
      ]
      [ ;; otherwise, pull click events off click stack
        ;; from the human player
        if get-clicked 0 = true
        [ set clicked (get-clicked 1)   
          
        ]
        ;; make sure the clicked patch in in the game area
        if any? game-area with [ self = clicked and mode = 0 ]       
        [ ask clicked [ set mode 3 ]
        ]
       
       ]
      ]
     ]
    ]
   ]
  ]
 ]
]
tick
end





to find-same-colors [ the-color the-group ]
    let new-members 0
  
    without-interruption
    [ set new-members neighbors4 with [ pcolor = the-color and color-group = -1 ]
      if any? new-members
      [ ask new-members [ set color-group the-group ]
        ask new-members [ find-same-colors pcolor the-group ]
      ]
    ]
end

to initialize-patch
  let colors [ 15 45 75 105 135 25 55 85 115 35 65 95 125 ]
  set pcolor item (random (1 + level)) colors
  set mode 4
  set color-group -1
end

to test-block
    let selected-group 0
  
    ifelse pcolor = black
    [ set mode 0
      show "empty"
    ]
    [ without-interruption
      [ ; if mode != 3 [ stop ]
        set color-group abs (pxcor * pycor)
        find-same-colors pcolor color-group
        
        set selected-group game-area with [ color-group = [color-group] of myself ]
        show (word pcolor " " selected-group)
        ifelse count selected-group >= 3
        [ set tumble-count 0
          ask selected-group
          [ set mode 2 ; fading
    
            set timeout timer + block-fade-time
            set color-group -1
          ]
          let group-size count selected-group
          let new-score group-size * group-size * level * level
          set score score + new-score
          num-to-turtles new-score self (world-width / 15) gray
          noise 1 (30 + 3 * ((group-size + pycor) mod 12) ) .5
          
          
        ]
        [ show "not enough"
          ask selected-group
          [ set mode 0 
            set color-group -1
          ]
        ]
      ]
    ]
   
 end
 
to tumble
   set tumble! false set tumbling? true
   set score score - 10
   if score < 0 [ set score 0 ]
   set tumble-count tumble-count + 1
   if tumble-count > tumble-limit
   [ set game-over? true
   ]
   
   ask game-area
   [ set temp [pcolor] of patch (- pycor) ( pxcor)
   ]
   ask game-area
   [ set pcolor temp ]
   
end 

to make-spark
   ;; make sparks!
   let index -45
   sprout 1
   [ set breed sparks
     set color pcolor + 8
     set size 1
     set lifespan 15
     set heading -45 + (22.5 * (who mod 6)); index
     let spark-speed 1 + random-float .5
     set ddx dx * spark-speed
     set ddy dy * spark-speed
     set index index + 45
   ]
end

to go-sparks
   ask sparks
   [ if lifespan < 1 [ die ]
     if size * .99 < .1 [ die ]
     if size < .1 [ die ]
     
     set ddy ddy - .075
     if (ycor + ddy ) > max-pycor [ set ddy 0 ] 
     if abs (xcor + ddx ) > max-pxcor [ set ddx (- ddx) * .85 ]
     if abs (ycor + ddy ) > max-pycor [ set ddy (- ddy) * .85 ]
     if abs (ycor + ddy)  < min-pycor
        or abs (xcor + ddx ) > max-pxcor
        [ die ]
     set color 139.99 - color ;; white ; 15 + random 5 + 10 * random 13
     set size size * .99
     set lifespan lifespan - 1
     setxy (xcor + ddx) (ycor + ddy)
   ]
end      

to go-scores
   ask scores
   [ if lifespan < 1 [ die ]
     ;; if size * .98 < .1 [ die ]
     if size < .1 [ die ]
     if pycor + .1 > max-pycor [ die ]
     set ycor ycor + .2
     ;; set xcor xcor + random-float .01
     set size size * 0.98
     set lifespan lifespan - 1
     set color color + 10
   ]     
end

to num-to-turtles [ num location scale hue ]
   ;; converts a number to a series of turtles of breed "scores" that look like the number
   ;; convert num to string of numbers
   ;; only positive integerts here!
   set num (word abs int num)
   let index 0
   ask location
   [ sprout 1
     [ set breed scores
       let char substring num index (index + 1)
       set shape char
       set my-group self
       set my-index index
       set lifespan 20
       set size scale
       set color hue
       set ycor ycor + 3
       hatch ((length num) - 1)
       [ set index index + 1
         set char substring num index (index + 1)
         set shape char
         set my-index index
         set xcor xcor + index * size * .66
         set size size * (1 + .25 * (index mod 2))
         
       ]
     ]
   ]
end   

to-report auto-player-click
   let clicked 0
  
   set clicked nobody 
   if next-click < timer
   [ set next-click timer + auto-play-speed * .25
     ifelse auto-player = "Randomia"
     [ set clicked auto-player-random ][
     ifelse auto-player = "Centrella"
     [ set clicked auto-player-center ][
     ifelse auto-player = "Specificious"
     [ set clicked auto-player-color-killer ][
     ]]]
     ifelse clicked = nobody
     [ set tumble! true ]
     [ ask clicked [ set mode 3 ] ]
   
   ]
   report clicked
   
end

to-report auto-player-random
   ;; randomly clicks a block of three or more
    report (one-of 
                        game-area with 
                        [     pcolor != black 
                          and count 
                               ( neighbors4 with 
                                 [ pcolor = [pcolor] of myself ] 
                               ) > 1
                        ]
            )
end
  
to-report auto-player-center
   ;; prefers to click blocks in the center nearest the bottom,
   ;; always clicking a group of three or more, 
   ;; with no preference for size
   report (min-one-of 
                        game-area with 
                        [     pcolor != black 
                          and count 
                               ( neighbors4 with 
                                 [ pcolor = [pcolor] of myself ] 
                               ) > 1
                        ]
                        [ pycor + abs (pxcor)]
          )
end                        

to-report auto-player-color-killer
   ;; prefers to click blocks of groups of three or more
   ;; trying to eliminate one color before doing the next color
   report (min-one-of 
                        game-area with 
                        [     pcolor != black 
                          and count 
                               ( neighbors4 with 
                                 [ pcolor = [pcolor] of myself ] 
                               ) > 1
                        ]
                        [ pcolor]
          )
end

to-report auto-player-bottom
   ;; prefers to click blocks on the bottom
   ;; always clicking a group of three or more, 
   ;; with no preference for size
   report (min-one-of 
                        game-area with 
                        [     pcolor != black 
                          and count 
                               ( neighbors4 with 
                                 [ pcolor = [pcolor] of myself ] 
                               ) > 1
                        ]
                        [ pycor ]
          )
end 

to go-game-over
ifelse game-over? = true
[ ask patch 15 10 [ set plabel "* GAME OVER *" ]
  ask patch 15 13 [ set plabel (word "SCORE: " score) ]
  ask patch 15 7  [ set plabel "Click PLAY    " ]
  ask patch 15 4  [ set plabel "to try again." ]
  ask game-area with [ pcolor != black ] 
  [ make-spark ]
    set game-over? 1
   ]
      [ if game-over? = 1
        [ ifelse any? sparks
          [ go-sparks ] 
          [ set game-over? 2
          ]
        ]
      ]

end

to noise [ sfx input1 input2 ]
     ;; remove comment symbols below and at top (on __extensions) to enable sounds
     ;;   ifelse sfx = 1
     ;;   [ ;; input1 = group-size, input2 = pcolor
     ;;     play-note (random-one-of ["WOODBLOCK" ]) input1 volume input2
     ;;   ][
     ;;   ]
   
end
             

                    


Download Link

View or download the complete model file (to download: right-click, save-link-as):
-- Download clix-game_2009 --