sargesorter


Information

Created with NetLogo version NetLogo 3.1.1
Running with NetLogoLite.jar version 314.


WHAT IS IT?


-------
This is a game modeled after "bejeweled" by PopCap Games

HOW DOES IT WORK?


-------------
RESET sets up a new game.
PLAY runs the game.
Click on two adjacent "gems" to swap places.
If three or more gems line up vertically or horizontally, they vanish.
If not, the two gems switch back to their original places
When gems vanish, the gems above fall into the empty spaces, possibly making more combinations.
Finally, the empty spaces are filled in with more gems!
If you get stumped, after a while, the game will suggest a play for you!

NETLOGO FEATURES


------------
This model is a conucopia of useful programming techniques.
The mouse handler is a basic one that can handle events at mouse-button-down, mouse-drag, and mouse-button-up.
Lots of custom shapes here.

NOTES


-
any more move detection...
how to detect if any gem can be used in a valid move?
for any gem, look to see if there are two other gems of the same shape in the right positions to make it possible for this gem to swap into a valid move...
e.g. in the below charts, 0 doesn't matter... if 1 and 3 are the same color, then 1 can swap with 2 to make group with 3-- 0 doesn't matter
wil be encoded with 2 lists-- patch coords for 3's relative to 1, and patch coord of 2 relative to 1. E.g: 1233 --> [ "match" [ [ 2 0] [ 3 0 ] ] "swap" [ 1 0 ] ]
1233 [ [ 2 0 ] [ 3 0 ] ] [ 1 0 ] ;; arrangement: . ..
3321 [ [ -3 0 ] [ -2 0 ] ] [ -1 0 ] ;; transform: negative of x
3 [ [ 0 2 ] [ 0 3 ] ] [ 0 1 ] ... transform, flip x and y
3
2
1
1 .. transform, negative y, flip x and y
2
3
3
03 [[1 1][1 -1]] [1 0] ;; arrangement: <
12
03
30 [[-1 1][-1 -1]] [-1 0] ;; arrangement: > trandform: negative of x
21
30
010 [[-1 -1][1 -1]] [0 -1] ;; arrangement: ^ transform: flip x and y
323
323 [[-1 1][1 1]] [0 1] ;; arrangement: v transform: negative x, flip x,y
010
233 [[1 1][2 1]] [0 1] ;; arrangement: F
100
332 [[-2 1][-1 1]] [ 0 1] ;; transform: negative x
001
100 [[1 -1][2 -1] [ 0 -1] ;; transform: negative y
233
001 [[-1 -1][-2 -1]] [0 -1] ;; trandform: negative x, negative y
332
03 [[ ]] [ ] ;; transform: flip x, y of arragement F
03
12
12 negative x, flip x,y
03
03
30 negative y, flip x,y
30
21
21 negative x, negative y, flip x,y
30
30

Procedures

NetLogo Version: NetLogo 3.1.1

;;;; SUMMARY
;; A game of clicking and sorting
;;;; COPYRIGHT
;; Copyright (C) 2006, James P. Steiner
;;
;;

;; __extensions [ "sound.jar" ] 
;; to activate sound effects, remove uncomment the previous line

globals
[ click?
  click-start
  click-end
  selected1
  selected2
  patch1
  patch2
  game-mode
  high-score
  goal-score
  score
  last-swap-time ;; the time of the last successful swap (or rather, the last explode from that swap)
  suggested ;; a thing that the computer suggests you might like to click
  
  cascade-counter ;; counts the number of continuous test/explode/drop cycles before going normal again
  message-patch ;; patch that is the target of messages to player
  message-text ;; the text of the message
  message-index ;;
  message-length
  playfield ;; patches in the play field
  combo-list
  
  pixels-per-patch ;; set to match view settings, to enable accurate single-pixel movement
  one-pixel ;; 1 / pixels-per-patch -- the increment that moves a coordinate one pixel  
  play-height ;; height, in patches of the playfield
  play-width ;; height, in patches, of the playfield
  play-min-pycor ;; bottom row of the playfield
  play-max-pycor ;; top-row of the playfield
  play-min-pxcor ;; left-most column of the playfield
  play-max-pxcor ;; right-most column of the play-field
  
  sound-on?
  sound-q ;; contains the sound playing instructions to run
]

breed [ things thing ]
breed [ logos logo ]

things-own
[ index ;; what shape and color?
  selected? ;; deprectated
  dir ;; the direction of the color pulse
  me-mode ;; the current mode of this thing
]

to startup
   setup
 end
   
to setup
   global-safe-clear-all
   setup-constants
   setup-playfield
   set sound-q ""
   set sound-on? false
   carefully
   [ run " set sound-on? is-list? instruments "]
   [ ]   ;; setup-items
   update-score 0
   send-message "Get Ready!"
   set click? false
   set game-mode "f"
   while [ game-mode = "f" ] [ go set plabel-of message-patch "" set message-text "" set message-index 0 set score 0 update-score 0] ;; go once to make the first fill happen
   let matched! things with [ count ((things at-points [[ -1 0 ][ 1 0 ]]) with [index = index-of myself ]) = 2
                           or count ((things at-points [[ 0 -1 ][ 0 1 ]]) with [index = index-of myself ]) = 2  
                           ]
   while [ any? matched! ]
   [ ask matched!
     [ set-shape-and-color ]
     set matched! things with [ count ((things at-points [[ -1 0 ][ 1 0 ]]) with [index = index-of myself ]) = 2
                           or count ((things at-points [[ 0 -1 ][ 0 1 ]]) with [index = index-of myself ]) = 2  
                           ]
   ] 
   set game-mode "n"
   send-message "Click PLAY to begin!"
   set message-index message-length - 1
   update-messages
   ;; carefully (and in a way that will compile if the 
   ;; sound.jar extension is not installed )
   ;; see if sounds are available

end

to global-safe-clear-all
   ;; saves the state of some variables in local variables
   ;; then uses clear-all
   ;; then restores those variables from the local variables
   let save-high-score high-score
   ca
   set high-score save-high-score
end

to setup-constants
   set pixels-per-patch 25  ;; set to match view settings, to enable accurate single-pixel movement
   set one-pixel 1 / pixels-per-patch ;; 1 / pixels-per-patch -- the increment that moves a coordinate one pixel  
   
  
   set play-min-pycor min-pycor + 1 ;; bottom row of the playfield
   set play-max-pycor max-pycor - 1 - 3 - 1 ;; top-row of the playfield
   
   set play-min-pxcor min-pxcor + 1 ;; left-most column of the playfield
   set play-max-pxcor max-pxcor - 1 - 3 - 1 ;; right-most column of the play-field   

   set play-height play-max-pycor - play-min-pycor  ;; height, in patches, of the playfield
   set play-width  play-max-pxcor - play-min-pxcor  ;; width,  in patches, of the playfield
  
   set message-patch patch-at (play-max-pxcor ) (play-max-pycor + 1)
   set playfield patches with [     pxcor >= play-min-pxcor and pxcor <= play-max-pxcor 
                                and pycor >= play-min-pycor and pycor <= play-max-pxcor ]
   set combo-list generate-valid-combos
  
end   

to setup-playfield
   
   ;; draw background-color (borders)
   ask patches
   [ set pcolor brown - 4 + .5 * scale-color gray pycor min-pycor max-pycor  ]
   
   ;; draw top / logo area
   ask patches with [ pycor < max-pycor and pycor > play-max-pycor + 1 
                      and pxcor > min-pxcor and pxcor < max-pxcor ]
   [ set pcolor sky - 2 ]

     ;; draw score area
   ask patches with [ pxcor > play-max-pxcor + 1 and pxcor < max-pxcor
                    and pycor > play-max-pycor - 2 and pycor <= play-max-pycor ]
   [ set pcolor lime - 2 
   ]

   ;; draw (clear) playfield
   ask playfield
  [ set pcolor 1 + 1 * ((pxcor + pycor) mod 2) ]

  ;; create logo turtle
  cct-logos 1
  [ set shape "logo1"
    setxy (min-pxcor + .30 * world-width) ( max-pycor - .5 * (max-pxcor - (play-max-pxcor + 1) ))
    set size world-width * .45
    set color yellow
    set heading -5
  ]
  ;; create logo turtle
  cct-logos 1
  [ set shape "logo2"
    setxy (min-pxcor + .66 * world-width) ( max-pycor - .5 * (max-pxcor - (play-max-pxcor + 1) ))
    set size world-width * .45
    set color orange + 2
    set heading -5
  ]

  ;; copyright
  ask patch max-pxcor min-pycor
  [ set plabel-color brown
    set plabel "Copyright (C) 2006 James P. Steiner  "
  ]
end

to setup-items
   ;; deprecated
   ;; fills the playfield with items
   ask playfield
   [ fill-me
   ]
end 

to go
   ;; the main program loop runs the game.
   ;; all game activities are coded iterively,
   ;; so the ifelse chain below makes sure the right 
   ;; iterated procedure occurs at the right time.
   ;; each procedure changes the mode to
   ;; the correct subsequent mode
   every 1 / 10
   [ no-display
     update-messages
     ifelse game-mode = "s" ;; swap
     [ swap 
     ][
     ifelse game-mode = "ts" or game-mode = "ta" or game-mode = "taf";; test selected, test all
     [ test game-mode
     ][
     ifelse game-mode = "u" ;; unswap (no match)
     [ swap
     ][
     ifelse game-mode = "e" ;; explode
     [ explode
     ][ 
     ifelse game-mode = "d" ;; drop
     [ drop "ta"
     ][
     ifelse game-mode = "f" ;; fill
     [ fill
     ][]]]]]]
   ]
   ifelse game-mode = "n" ;; normal
   [ ifelse auto-play?
     [ auto-play
     ]
     [ mouse
       pulse-pick
     ]
     ifelse timer - last-swap-time >= hint-speed and timer - last-swap-time < hint-speed + 5
     [ ;; some seconds after last move, suggest a move for some seconds
       ifelse is-agentset? suggested
       [ ;;  if suggestion exists, just display it
         ask suggested [ pulse-me ]
       ]
       [ ;; otherwise, create a suggestion
         make-suggestion 
       ]
     ]
     [ if is-agentset? suggested
       [ ;; not time for suggestion, but a suggestion exists, means the end of suggestion time.
         ;; so clear suggestion and reset timer
         clear-suggestion
         ;;reset timer, so another hint appears in a few seconds
         set last-swap-time timer 
       ]
     ]
   ][ if game-mode = "x"
      [ ;; if game-mode = "x" ;; game-over
       ask message-patch [ set plabel-color white set plabel "No more moves! Click RESET to restart." ]
       stop
     ]
   ]
     if sound-on? = true 
     [ if sound-q != ""
       [ carefully [ run sound-q ] [] 
         set sound-q ""
       ]
     ]
   display
end

to mouse   
   ;; handles all mouse events
   ifelse mouse-down? [ mouse-down ] [ mouse-up ]
end

to mouse-down
   ;; handles events that happen when the mouse is down
   ifelse click?
   [
   ]
   [ set click? true 
     set click-start patch-at mouse-xcor mouse-ycor
   ]
end

to mouse-up
   ;; handles events that happen when the mouse is up
   
   ifelse click?
   [ ;; mouse click / drag complete
     let drag? false
     set click? false
     set click-end patch-at mouse-xcor mouse-ycor
     ifelse is-turtle? selected1 and click-end = click-start
     [ ;; click 2 of 2 click sequence\
       ;; selected 1 are turtle from last click,
       ;; and start turtle from this click
       set selected2 one-of turtles-on click-start
       set patch2 click-start
     ]
     [ ;; either single click, or click-n-drag
       ;; either way, selected1 is from the start patch of this click
       if is-turtle? selected1 [ ask selected1 [ fix-color] ]
       set selected1 one-of turtles-on click-start
       set patch1 click-start
       ifelse click-end = click-start 
       [ ;; click in place, just a selection
       ]
       [ ;; drag, set selection2 from direction
         set drag? true
         let xdrag pxcor-of click-end - pxcor-of click-start
         let ydrag pycor-of click-end - pycor-of click-start
         ifelse abs xdrag > abs ydrag [ set ydrag 0 ] [ set xdrag 0 ]
         set xdrag sign xdrag
         set ydrag sign ydrag
         set patch2 value-from patch1 [ patch-at xdrag ydrag ]
         set selected2 one-of turtles-on patch2
       ]
     ]
     if is-turtle? selected1 [ queue-sound (one-of ["LOW WOOD BLOCK" "HI WOOD BLOCK"]) volume ]
     if is-turtle? selected2
     [ ifelse value-from patch1 [ any? neighbors4 with [ self = patch2 ] ]
       [ ask selected1 [ face patch2 ]
         ask selected2 [ face patch1 ]
         set game-mode "s" ;; swap
         if is-agentset? suggested [ clear-suggestion ]
       ]
       [ ;; if a drag, clear selections
         ifelse drag?
         [ clear-selection ]
         [ ;; otherwise, set selected1 to selected2
           ;; i.e. second click becomes new first click
           ask selected1 [ fix-color ]
           set selected1 selected2
           set patch1 patch2
           set selected2 nobody
           set patch2 nobody
         ]
       ]
     ]
   ]
   [ ;; mouse-down, drag, etc in progress
     ;; nothing at the moment
   ]
end

to fix-color
   ;; returns the color of the calling item to
   ;; the center tint of that HUE
   set color color - ( color mod 10 ) + 5
end


to-report sign [ value ]
   ;; reports the sign of the given number
   ifelse value = 0
   [ report 0
   ]
   [ ifelse value < 0
     [ report -1]
     [ report 1 ]
   ]
end   


to swap
   ;; causes the things stored in selection1 and selection2
   ;; to swap positions
   
   let swap-done? false
   let step-size .25
   ask selected1
   [ pulse-me 
     face patch2 jump step-size 
     ;; rather than assume that 
     if abs (xcor - pxcor-of patch2) < step-size and abs (ycor - pycor-of patch2) < 5 * one-pixel
     [ set swap-done? true ]
   ]
   ask selected2
   [ pulse-me
     face patch1 jump step-size
     if abs (xcor - pxcor-of patch1) < step-size and abs (ycor - pycor-of patch1) < 5 * one-pixel
     [ set swap-done? true ]
   ]
   if swap-done?
   [ ask selected1
     [ setxy pxcor pycor
       set heading 0
       fix-color
     ]
     ask selected2
     [ setxy pxcor pycor
       set heading 0
       fix-color
     ]
     if game-mode = "s"
     [  set game-mode "ts" ] ;; test after swap
     if game-mode = "u" 
     [  set game-mode "n"  ;; normal after unswap
        clear-selection
      ] 
   ]
end

to unswap-start
   ;; prepares for swap to do an unswap,
   ;; by reversing selection1 and 2 
   ;; (leaving patch1 and 2 alone)
   let temp-s1 selected1
   set selected1 selected2
   set selected2 temp-s1
   set game-mode "u"
   queue-sound "Long Guiro" volume
end

to clear-selection
   ;; clears the selected status of any selected turtles.
   ;; also fixes the colors, in case the items have been pulsed.
   if is-turtle? selected1 [ ask selected1 [ fix-color ] ]
   if is-turtle? selected2 [ ask selected2 [ fix-color ] ]
   set selected1 nobody
   set selected2 nobody
   set patch1 nobody
   set patch2 nobody
end        

to drop [ next-mode ]
   ;; causes all things that have space below them to fall
   ;; also used by fill to cause newly created things to fall into position
   ;; the "next-mode" indicates whether the next mode will be
   ;; "ta" (test all), as after an explode/drop,
   ;; or "f" again, as after a fill/drop
   let drop-step 1
   ask things with [ pycor > play-min-pycor and not any? turtles at-points [ [ 0 -1 ] ] ]
   [ set me-mode "d" ]
   ifelse any? things with [ me-mode = "d" ]
   [ ask things with [ me-mode = "d" ]
     [ set ycor ycor - drop-step
       ;if abs ( ycor - pycor) < drop-step
       ;[ setxy pxcor pycor
         if pycor = play-min-pycor or any? turtles at-points [ [ 0 -1 ] ]
         [ set me-mode "i" ]
       ;;]
     ]
   ]
   [ set game-mode next-mode ;; test or fill again when drops completed
   ]
end
  
to pulse-pick
   ;; causes the first selected thing to pulse,
   ;; showing that it is selected
   if is-turtle? selected1 [ ask selected1 [ pulse-me ] ]
end

to pulse-me
   ;; occilates the brightness of the calling turtle
   set color color + dir
   if (color * 10) mod 100 >= 90
     or (color * 10 ) mod 100 < 10
   [ set dir dir * -1 ]
end

to  test  [ who? ]
   ;; manages the test process
   ;; asks all things to test themselves.
   ;; if groups that need to explode are found, updates the cascade counter
   ;; and score based on the number of things exploding, and the cascade counter
   ;; if nothing needs to explode, then either goes into fill mode, or back to normal mode
   
   ;; either test all (after fill )
   ;; or test just the selected (swapped) items
   ifelse who? = "ta" or who? = "taf"
   [ ask things
     [ test-me [] ]
   ]
   [ ask selected1 [ test-me [] ]
     ask selected2 [ test-me [] ]
   ]
   
   ifelse any? things with [ me-mode = "e" ]
   [ clear-selection
     set last-swap-time timer
     set cascade-counter cascade-counter + 1
     update-score (10 * cascade-counter * count things with [ me-mode = "e" ])

     set game-mode "e"
     ask things with [ me-mode = "e" ]
     [ explode-me-start ]
   ]
   [ ;; nothing to explode
     ifelse is-turtle? selected1
     [ ;; if a selected turtle exists, here
       ;; this test is the result of a user swap,
       ;; so we need to unswap
       unswap-start
     ]
     [ ifelse game-mode = "taf"
       [ ;; this test was started by the fill function, 
         ;; and didn't cause any cascades. Go back to normal mode
         set game-mode "n"
       ]
       [ ;; this test is the result of a swap or cascade
         ;; (i.e. after swap, test, explode, drop, test cycle)  
         ;; which probably left open spaces
         ;; so we need to fill     
         set game-mode "f" ; fill if needed 
       ]
     ]
   ]
end   

to test-me [ queue ]
   ;; used recursively by the item to test whether the item is part of a shape group
   ;; the queue is used to prevent testing loops
   ;; looks to see if there are like-shaped items above (and below) the item,
   ;; or on both sides of the item.
   ;; uses the INDEX to compare, so that the actual shapes can be diffent (ie, a mix of animals and shapes)
   ;; If so, those matches are asked to test themselves, thus
   ;; ensuring that chains of like-colored items are properly detected.
   if member? self queue
   [ stop ]
   let above  ( turtles-on patches at-points [ [ 0 1 ] [  0 -1 ] ] ) with [ index = index-of myself ]
   let beside ( turtles-on patches at-points [ [ 1 0 ] [ -1  0 ] ] ) with [ index = index-of myself ]
   set queue lput self queue
   if any? beside
   [ ifelse count beside = 1 and me-mode != "e" ;; in an explode group
     [ ask beside [ test-me queue ] 
      ]
      [ if count beside = 2
        [ set me-mode "e" ;; in a group
          ask beside with [ me-mode != "e" ]
          [ set me-mode "e"
            test-me queue
          ]
        ]
      ]
    ]     

   if any? above
   [ ifelse count above = 1 and me-mode != "e" 
     [ ask above [ test-me queue ]
     ]
     [ if count above = 2
       [ set me-mode "e" 
         ask above with [ me-mode != "e" ]
         [ set me-mode "e"
           test-me queue
         ]
       ]
     ]
   ]
end

to explode
   ;; manages animation of all exploding items
   ;; when all exploding items have vanished, switches to DROP mode
   if any? things with [ me-mode = "e" ] [ queue-sound "VibraSlap" volume  ]
  
   ask things with [ me-mode = "e" ] [ explode-me ]
   if not any? things with [ me-mode = "e" ] [ set game-mode "d" ] ;; drop
end

to explode-me-start
   ;; prepares an exploded item for the explosion animation
   set color white
   set index 0
   set shape (word "explode" index)

end
   
to explode-me
   ;; animates an exploded item, then removes it
   ifelse index < 3
   [ set index index + 1
     set shape (word "explode" (int (index mod 2)))
   ]
   [ die ]
end   


to fill
   ;; this procedure looks for and fills empty spaces.
   ;; if empty spaces exist, then
   ;; empty spaces across the top are filled
   ;; and all are allowed to drop
   ;; this works because until the newly made and dropping items fall below
   ;; into the next row (if they need to), they make the top row not empty.
   set cascade-counter 0
   ifelse any? playfield with [ not any? turtles-here ]
   [ let spaces ( playfield with [ pycor = play-max-pycor and not any? turtles-here ] )
     if any? spaces
     [ ask spaces ;; one-of spaces
   
       [ fill-me ]
     ]
     drop "f"
   ]
   [ set game-mode "taf" ;; test all
   ]
   
end

to fill-me
   ;; creates a new item in the calling patch
   sprout 1
   [ set breed things
     set-shape-and-color     set heading 0
     set selected? false
     set dir 1
     set me-mode "i" ;; idle
   ]
end 

to set-shape-and-color
     set index random ( difficulty + 3)
     set shape (word theme (index + 1))
     set color item index  [ orange magenta blue green yellow red pink violet]
 end

  
to update-score [ amount ]
   ;; updates the score, and (fi the update is not 0)
   ;; delivers a message of support
   set score score + amount
   ask patch ( max-pxcor - 1 ) ( play-max-pycor - 1)
   [ set plabel (word score " ") 
     set plabel-of (patch-at 0 1) "Score:   "
   ]
   if amount > 0
   [ send-message (word
      one-of
       [ "Yahoo!" "Good --" "Diggum!" "By Gum," "Squee!" "Meep!" "Lawds!" ]
      " " amount " "
      one-of
       [ "points!" "big ones." "more reasons to live..." "clams!" ]
      )
   ]  
end

to send-message [ text ]
   ;; posts a message to the message area
   ask message-patch
   [ set message-text text
     set plabel-of message-patch ""
     set plabel-color pcolor + 4.9
     set message-index 0
     set message-length length message-text 
   ]
end
   
  
to update-messages
   ;; fades out any posted message
   ask message-patch 
   [ if message-text != ""
     [ ifelse abs (plabel-color - pcolor) < .2
       [ set plabel-color pcolor
         set plabel ""
         set message-text ""
       ]
       [ ifelse message-index < message-length
         [ set message-index message-index + 1 
           set plabel substring message-text 0 message-index
         ]
         [ set plabel-color plabel-color - .2 
         ]
       ]
     ]
     
   ]
end     




to-report generate-valid-combos
   let combo []
   let combos []
   
   set combo [  [[ 2 0 ] [ 3 0 ]]  "\n1233"  [[ 1 0 ]]  ]
   set combos lput combo combos


;;  1233  [ [ 2 0 ] [ 3 0 ] ]  [ 1 0 ]     ;; arrangement:  . ..


;;  
;;  3321  [ [ -3 0 ] [ -2 0 ] ] [ -1 0 ]   ;; transform: negative of x
;;  
;;  3    [ [ 0 2 ] [ 0 3 ] ]  [ 0 1 ]   ... transform, flip x and y 
;;  3
;;  2
;;  1
;;  
;;  1     .. transform, negative y, flip x and y
;;  2
;;  3
;;  3
;;  
;;  
;;  

    set combo [  [[ 1 1 ] [ 1 -1 ]] "\n03\n12\n03"  [[1 0]]  ]
    set combos lput combo combos

;;  03    [[1 1][1 -1]]   [1 0]  ;; arrangement:  <
;;  12
;;  03
;;  
;;  30    [[-1 1][-1 -1]]   [-1 0] ;; arrangement: >  trandform: negative of x
;;  21
;;  30
;;  
;;  010   [[-1 -1][1 -1]]   [0 -1] ;; arrangement: ^  transform: flip x and y
;;  323   
;;  
;;  323   [[-1 1][1 1]]   [0 1]  ;; arrangement: v  transform: negative x, flip x,y 
;;  010
;;  

    set combo [ [[ 1 1 ][ 1 2 ]] "\n03\n03\n12"  [[ 1 0 ]] ]
    set combos lput combo combos
    

;;  233   [[1 1][2 1]]   [0 1] ;; arrangement: F 
;;  100
;;  
;;  332   [[-2 1][-1 1]] [ 0 1] ;; transform: negative x
;;  001
;;  
;;  100   [[1 -1][2 -1]   [ 0 -1] ;; transform: negative y
;;  233
;;  
;;  001   [[-1 -1][-2 -1]]   [0 -1] ;; trandform: negative x, negative y
;;  332
;;  
;;  03    [[ ]] [ ] ;; transform: flip x, y of arragement F
;;  03
;;  12   
;;  
;;  12   negative x, flip x,y
;;  03
;;  03
;;  
;;  30   negative y, flip x,y
;;  30
;;  21
;;  
;;  21   negative x, negative y, flip x,y
;;  30
;;  30

  let new-combos []
  foreach combos
  [ ;; first, write this combo (?) to the lsit
    set new-combos lput ? new-combos
  
    let matches first ?
    let swapt last ?
    let new-combo []
    let new-matches matches
    let new-swapt swapt
    let text item 1 ?
    
         ;; now flip x and y of this version
         set new-matches map [ (list (last ?) (first ?) ) ] new-matches 
         set new-swapt   map [ (list (last ?) (first ?) ) ] new-swapt
         set new-combo (list new-matches (text + "-flip") new-swapt)
         set new-combos lput new-combo new-combos

    ;; next, generate negative x version 
    set new-matches map [ (list (-1 * first ?) ( last ?) ) ] matches 
    set new-swapt map [ (list (-1 * first ?) ( last ?) ) ] swapt
    set new-combo (list new-matches (text + "-neg-x")  new-swapt)
    set new-combos lput new-combo new-combos
    
         ;; now flip x and y of this version
         set new-matches map [ (list (last ?) (first ?) ) ] new-matches 
         set new-swapt map [ (list (last ?) (first ?) ) ] new-swapt
         set new-combo (list new-matches (text + "-neg-x-flip") new-swapt)
         set new-combos lput new-combo new-combos

    ;; now generate negative y version
    set new-matches map [ (list ( first ?) (-1 * last ?) ) ] matches 
    set new-swapt map [ (list ( first ?) (-1 * last ?) ) ] swapt
    set new-combo (list new-matches (text + "-neg-y") new-swapt)
    set new-combos lput new-combo new-combos
    
         ;; now flip x and y of this version
         set new-matches  map [ (list (last ?) (first ?) ) ] new-matches 
         set new-swapt map [ (list (last ?) (first ?) ) ] new-swapt
         set new-combo (list new-matches (text + "-neg-y-flip") new-swapt)
         set new-combos lput new-combo new-combos

    ;; now generate negative x and y version
    set new-matches map [ (list (-1 * first ?) (-1 * last ?) ) ] matches 
    set new-swapt map [ (list (-1 * first ?) (-1 * last ?) ) ] swapt 
    set new-combo (list new-matches (text + "-neg-xy") new-swapt)
    set new-combos lput new-combo new-combos
    
         ;; now flip x and y of this version
         set new-matches map [ (list (last ?) (first ?) ) ] new-matches 
         set new-swapt map [ (list (last ?) (first ?) ) ] new-swapt
         set new-combo (list new-matches (text + "-neg-xy-flip") new-swapt)
         set new-combos lput new-combo new-combos

   ;; all alternate versions created.
   ;; some transformations generate redundant versions
   ;; use remove duplicates to remove redundant versions
 ] 
 
 ;; sort the coordinates within the combos
 let sorted-combos []
 ;; repeat 10 [ print "" ]
 foreach new-combos
 [ let matches first ?
   let swapt last ?
   let text item 1 ?
   ;;print ?
   ;;print (word " ---- " matches " ---- " swapt )
   ;;print (word " ----  ---- " first matches )

   set matches sort-by [ first ?1 < first ?2 or last ?1 < last ?2 ] matches
   let new-combo (list matches text swapt)
   set sorted-combos lput new-combo sorted-combos
 ]
 
 report sorted-combos
end

to-report find-good-combos
   let successful-combos []
   foreach combo-list
   [ let match-points first ?
     let swap-points last ?
     let matches (things at-points match-points) with [ index = index-of myself ]
     if count matches = 2
     [ set successful-combos lput ? successful-combos ]
   ]
   report successful-combos
end

to show-good-combo
   let successful-combos find-good-combos
      
   if length successful-combos > 0
   [ let combo one-of successful-combos
     let match-points first combo
     let swapt-points last combo
     let matches (things at-points match-points) with [ index = index-of myself ]
     let swapt one-of (things at-points swapt-points)
     fix-color
     set color color + 2
     ask matches [ set size .5 ]
     ask swapt [ set size .5 ]
   ]
end

to make-suggestion
   let candidates things with [ find-good-combos != [] ]
   if any? candidates
   [ let swapt nobody
     set candidates one-of candidates
     ask candidates
     [ set swapt one-of (things at-points (last (one-of find-good-combos) ) )
     ]
     set dir-of candidates 1
     set dir-of swapt -1

     set candidates (list candidates swapt)
     set suggested things with [ member? self candidates ]
   ]
end

to clear-suggestion
   ask suggested [ fix-color ]
   set suggested nobody
end

to auto-play
   let candidate things with [ find-good-combos != [] ]
   ifelse any? candidate
   [ set candidate one-of candidate
     ask candidate
     [ let good-combos find-good-combos
       let combo one-of good-combos
       ;; type (word combo "\n\n")
       ;; let match-points first combo
       let swapt-points last combo
       ;; let matches (things at-points match-points) with [ index = index-of myself ]
       let swapt one-of (things at-points swapt-points)
       ;; ask matches [ set size .5 ]
       ;; ask swapt [ set size .5 ]
       
       set selected1 self
       set selected2 swapt
       set patch1 patch-here
       set patch2 value-from selected2 [ patch-here ]
       ;; solve that one
       set game-mode "s"
       queue-sound (one-of ["LOW WOOD BLOCK" "HI WOOD BLOCK"]) volume
     ]
    ]
    [ set game-mode "x" ;; game-over!
    ]
end
       
to queue-sound [ drum vel ]
   if sound-on? [ set sound-q (word sound-q " play-drum \"" drum "\" "  vel ) ]
end     

  ;;  35. Acoustic Bass Drum             59. Ride Cymbal 2
  ;;  36. Bass Drum 1                    60. Hi Bongo
  ;;  37. Side Stick                     61. Low Bongo
  ;;  38. Acoustic Snare                 62. Mute Hi Conga
  ;;  39. Hand Clap                      63. Open Hi Conga
  ;;  40. Electric Snare                 64. Low Conga
  ;;  41. Low Floor Tom                  65. Hi Timbale
  ;;  42. Closed Hi Hat                  66. Low Timbale
  ;;  43. Hi Floor Tom                   67. Hi Agogo
  ;;  44. Pedal Hi Hat                   68. Low Agogo
  ;;  45. Low Tom                        69. Cabasa
  ;;  47. Open Hi Hat                    70. Maracas
  ;;  47. Low Mid Tom                    71. Short Whistle
  ;;  48. Hi Mid Tom                     72. Long Whistle
  ;;  49. Crash Cymbal 1                 73. Short Guiro
  ;;  50. Hi Tom                         74. Long Guiro
  ;;  51. Ride Cymbal 1                  75. Claves
  ;;  52. Chinese Cymbal                 76. Hi Wood Block
  ;;  53. Ride Bell                      77. Low Wood Block
  ;;  54. Tambourine                     78. Mute Cuica
  ;;  55. Splash Cymbal                  79. Open Cuica
  ;;  56. Cowbell                        80. Mute Triangle
  ;;  57. Crash Cymbal 2                 81. Open Triangle
  ;;  58. Vibraslap       

                    


Download Link

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