minos-plumber_2.2


Information

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


WHAT IS IT?


-------
The Plumber of Minos, a game where scattered pipes are rotated until the are fully connected, forming a single-path maze.

HOW IT WORKS


--------
First, a maze is constructed. Then the maze is converted to pipes, and the pipes rotated randomly.

HOW TO USE IT


---------
Clicking the mouse on a pipe rotates the pipe 90 degrees clockwise.

Procedures

NetLogo Version: NetLogo 3.1.1

;;;; SUMMARY
;; Fix the Minotaur's plumbing!
;;;; COPYRIGHT
;; Minos Plumber Copyright (C) 2006 James P. Steiner
;;
;;
;;
globals
[ mx
  my
  click?
  hovered
  cursor
  stack
  traveller
  last-click
  this-click
  dbl-click?
  pipe-shapes
  pipe-ports
  pipe-port-coords

  pipe-port-map-ports
  pipe-port-map-shape
  pipe-port-map-rotation
  
  pipes-min-pxcor
  pipes-min-pycor
  pipes-max-pxcor
  pipes-max-pycor
  
  pipe-patches
  
  stop?
  
  game-time
  clock-running?
  game-over?
  best-time
  fill-color
  connected-color
  open-color
  turn-color
]

breed [ pipes pipe ]
breed [ mazers mazer ]
breed [ logos logo ]
breed [ cursors a-cursor ]

pipes-own
[ turning?
  new-heading
  ports
  touching-source?
]

to startup
   setup
end
   
to setup
   let temp-bt best-time
   ca
   set best-time temp-bt
   set pipe-shapes [ ["pipe-0-null"] 
                     ["pipe-1-end" "pipe-1-drain" ]
                     [ "pipe-bend" "pipe-bend-loop" "pipe-bend-oxbow" ]
                     [ "pipe-2-thru" "pipe-2-wide" "pipe-2-valve" "pipe-2-ess" "pipe-2-thin" ]
                     [ "pipe-3-tee" "pipe-3-why" "pipe-3-vee" "pipe-3-arr" ]
                     [ "pipe-4-cross" "pipe-4-ex" "pipe-4-lap" ]
                   ]
   set pipe-ports   [ []           [ 0 ]      [ 0 2 ]                       [ 0 1 ]     [ 0 1 3 ]  [ 0 1 2 3 ]  ]
   ;; map port configurations to shapes

   set pipe-port-map-ports    [ [ ] [0] [1] [2] [3]   [0 1] [1 2] [2 3] [0 3]   [0 2] [1 3]  [0 1 2] [1 2 3] [0 2 3] [ 0 1 3 ] [0 1 2 3 ] ]
   set pipe-port-map-shape    [ 0    1   1   1   1      2     2     2     2       3     3       4       4       4        4         5      ]
   set pipe-port-map-rotation [  0   0   1   2   3      0     1     2     3       0     1       1       2       3        0         0      ] 
   set pipe-port-coords [ [ 0 1 ] [ 1 0 ] [ 0 -1 ] [ -1 0 ] ]

   
   set connected-color white
   set open-color green 
   set turn-color lime

   cct-logos 1
   [ set shape "Logo-Minos"
     set color yellow
     set size 3.001
     setxy (min-pxcor + 2)
           ( max-pycor - 1)
   ]
   cct-logos 1
   [ set shape "Logo-Plumber"
     set color green
     set size 3.001
     setxy (min-pxcor + 5)
           ( max-pycor - 1)
   ]
   cct-logos 1
   [ set shape "figure-plumber"
     set color brown
     set size 1.5001
     setxy (min-pxcor + 8)
           ( max-pycor - 1)
   ]
   set-default-shape cursors "cursor"
   cct-cursors 1
   [ set cursor self
     set size 2.1
     hide-turtle
     set heading 0
     set color gray
     setxy 0 0
   ]
   reset-game
end

to reset-game
   if not any? logos [ setup ]
   clear-patches
   setup-pipe-patches
   setup-maze
   ask pipes [ twist ]
   ask pipes [ color-full-connection ]
   set clock-running? false
   set game-over? false
   if best-time != 0
   [ set plabel-of patch max-pxcor min-pycor (Word "Best Time:" best-time)]
end   

to xxx-make-random-pipes
   ask pipe-patches
   [ sprout-pipes 1
     [ set color turn-color 
       let shape# random 4
       set shape item shape# pipe-shapes
       set ports item shape# pipe-ports
       let rotations random 4
       set ports map [ ((? + rotations) mod 4) ] ports
       set heading rotations * 90
       set new-heading heading
     ]
   ]
   ask pipes
   [ color-full-connection ]
end

to go
   every .05
   [ ifelse game-over? = false
     [ monitor-mouse
       do-turning
     ]
     [ do-game-over-business
     ]
   ]
   every .25 [ check-game-over ]
end


to monitor-mouse
   ifelse mouse-down?
   [ if is-turtle? hovered
     [ ask hovered [ setxy pxcor pycor ]
       set hovered nobody
     ]
     if click? != true
     [ set click? true
       set mx mouse-xcor
       set my mouse-ycor
     ]
   ]
   [ ifelse click? = true
     [ set click? false
       
       if abs (mouse-xcor - mx) <= .5 and abs (mouse-ycor - my) <= .5
       [ set last-click this-click
         set this-click timer 
         set mx round mx
         set my round my
         restore-hovered
         set hovered nobody
         ;; hide-cursor
         rotate-pipe mx my
       ]
     ]
     [ ;; mouse-up and click is false--HOVER
       let under one-of pipes-on patch-at mouse-xcor mouse-ycor
       ifelse is-turtle? under 
       [ if under != hovered
         [ restore-hovered
           set hovered under
           move-cursor-to-hovered
         ]
         ask hovered
         [ 
         ]
         ask cursor [ rt 5 ]
       ]
       [ restore-hovered
         set hovered nobody
         hide-cursor 
       ]
     ]
   ]
end     

to restore-hovered
   if is-turtle? hovered
   [ ask hovered
     [ set pcolor black
     ]
   ]
end

to move-cursor-to-hovered
   ask cursor
   [ setxy pxcor-of hovered pycor-of hovered
     show-turtle
   ]
end

to hide-cursor
   ask cursor
   [ hide-turtle ]
end   

to do-turning
   ask pipes with [ turning? = true ]
   [ set heading int heading + max (list 5 (int (.5 + .5 * abs subtract-headings new-heading heading)) )
     ;; set label int heading
     if abs subtract-headings heading new-heading < 5
     [ set heading new-heading
       set turning? false 
       set color orange 
       rotate-ports      
       test-full-connection
       
     ]
   ]
end

to test-full-connection
   color-full-connection
   ask pipes-on neighbors4
   [  color-full-connection ]

end

to color-full-connection
   ifelse fully-connected?
   [ set color connected-color ]
   [ set color open-color ]
end       
   
to-report connection-to? [ port ]
   ;; if this agents ((port + 2) mod 4)
   ;; has a matching port among the given
   ;; agent's connections, then the 
   ;; two agents connect
   let agent agent-at-port port
   ifelse is-turtle? agent
   [ report member? 
          ((port + 2) mod 4)
          ( ports-of agent)
   ]
   [ report false ]
end
   
to-report agent-at-port [ port ]
   let coords item port pipe-port-coords
   let portx first coords
   let porty last coords
   let off-edge? false
   ifelse porty = 0 
   [ if xcor + portx < pipes-min-pxcor
        or xcor + portx > pipes-max-pxcor
     [ set off-edge? true ]
   ]
   [ ;; portx = 0 
     if ycor + porty < pipes-min-pycor
        or ycor + porty > pipes-max-pycor
     [ set off-edge? true ]
   ]
   ifelse off-edge?
   [ report nobody ]
   [ report one-of pipes-at portx porty ]
end

to-report fully-connected?
   setxy pxcor pycor
   let connected? true
   foreach ports
   [ if not connection-to? ? [ set connected? false ]
   ]
   report connected?
end
        
to increment-shape
   let shape# position shape pipe-shapes
   set shape# (shape# + 1) mod length pipe-shapes
   set shape item shape# pipe-shapes
   set ports item shape# pipe-ports
   test-full-connection
end

to rotate-ports
   set ports map [ ((? + 1) mod 4) ] ports ;; rotate ports
end

to-report opposite-ports
   report map [ ((? + 1) mod 4) ] ports
end   
   
to rotate-pipe [ xx yy ]
   ask patch xx yy
   [ ask pipes-here with [ turning? != true ]
     [ set turning? true
       ifelse heading = new-heading
       [ set new-heading heading + 90 ]
       [ set new-heading new-heading + 90 ]
       if new-heading >= 360 [ set new-heading new-heading - 360 ] 
       set color turn-color
     ]
   ]
end  

to-report rotate-pipe-periodically
   ask one-of pipe-patches
   [ rotate-pipe pxcor pycor ]
   report ""
end


to setup-pipe-patches
  let field-width .5 * (world-width - 2 - (8 - difficulty * 2) )
  let half-width int (world-width * .5)

  let field-height .5 * (world-height - 4 - (8 - difficulty * 2) )
  let half-height int (world-height * .5)

  set pipes-min-pxcor min-pxcor + half-width - field-width 
  set pipes-max-pxcor max-pxcor - half-width + field-width 

  set pipes-min-pycor min-pycor + half-height - field-height 
  set pipes-max-pycor max-pycor - half-height + field-height 
   
  set pipe-patches patches with [ pxcor >= pipes-min-pxcor and pxcor <= pipes-max-pxcor and 
                                  pycor >= pipes-min-pycor and pycor <= pipes-max-pycor
                                ] 
end
    
    
to setup-maze
   ask pipes [ die ]
   ask pipe-patches
   [ set pcolor black
     sprout-pipes 1
     [ set color blue 
       let shape# 0
       set shape one-of item shape# pipe-shapes
       set ports item shape# pipe-ports
       let rotations 0
       set ports map [ ((? + rotations) mod 4) ] ports
       set heading rotations * 90
       set new-heading heading
       set size .999
     ]
   ]  
     
   cct-mazers 1
   [ let start one-of pipe-patches
     goto-agent start
     set heading 0
     maze-step
     die
   ]
end    


           
to  maze-step
   let location one-of pipes-here
   let open-directions value-from location [ unconnected-ports ]
   while [ length open-directions > 0 ]
   [ let new-direction 0
     ;; give straight-through connections preference
     ifelse length open-directions = 3 and 
        random 100 < 100
     [ ifelse not member? 0 open-directions
       [ set new-direction 2 ][
       ifelse not member? 1 open-directions
       [ set new-direction 3 ][
       ifelse not member? 2 open-directions
       [ set new-direction 0 ][
       ifelse not member? 3 open-directions
       [ set new-direction 1 ][
       ]]]]
       set new-direction item 1 sort open-directions
     ]
     [ set new-direction one-of open-directions
     ]
     
     
     ask location
     [ if not member? new-direction ports
       [ set ports fput new-direction ports ]
     ]
     goto-coords item new-direction pipe-port-coords
     ask one-of pipes-here
     [ set ports fput ((new-direction + 2) mod 4) ports 
     ]
     maze-step
     goto-agent location
     set open-directions value-from location [ unconnected-ports ]
   ]
   ask location [ set-shape-and-heading-from-ports ]
end   

to-report unconnected-ports
 let open-ports [ ]
     foreach [ 0 1 2 3 ]
     [ 
       
       let this-pipe pipe-at-port ?
       if not member? ? ports and is-turtle? this-pipe and ports-of this-pipe = []
       [ set open-ports lput ? open-ports
       ]
     ]
     report open-ports
end

to goto-agent [ agent ]
   setxy pxcor-of agent pycor-of agent
end   
   
to goto-coords [ coord-pair ]   
   let xx first coord-pair
   let yy last coord-pair
   setxy ( xcor + xx ) ( ycor + yy )
end


to-report pipe-patch-at-port [ port# ]
   let coord-pair item port# pipe-port-coords 
   let xx pxcor + first coord-pair
   let yy pycor + last coord-pair
   let patches-there pipe-patches with [ pxcor = xx and pycor = yy ]
   ifelse any? patches-there
   [ report one-of patches-there ]
   [ report nobody ]
end

to-report pipe-at-port [ port# ]
   let coord-pair item port# pipe-port-coords 
   let xx pxcor + first coord-pair
   let yy pycor + last coord-pair
   let pipes-there pipes with [ pxcor = xx and pycor = yy ]
   ifelse any? pipes-there
   [ report one-of pipes-there ]
   [ report nobody ]
end 

to-report ports-at-port [ port# ]
   let the-pipe pipe-at-port port#
   ifelse is-turtle? the-pipe
   [ report ports-of the-pipe ]
   [ report [] ]
end   

to set-shape-and-heading-from-ports 
   ;; put the ports in order
   set ports sort ports
   ;; find the class of ports that matches these ports
   let port-config position ports pipe-port-map-ports
   ;; pick the port arrangement that goes with this port class
   let port-shape item port-config pipe-port-map-shape
   let port-rotation item port-config pipe-port-map-rotation
   ;; pick one of the shapes that goes with this port arrangement
   set shape one-of item port-shape pipe-shapes
   set heading port-rotation * 90
   set new-heading heading
end

to twist
   let new-rotation random 4
   set ports sort map [ ((? + new-rotation) mod 4) ] ports
   set-shape-and-heading-from-ports
end


to-report pipes-at-ports
   let port-coords map [ item ? pipe-port-coords  ] ports
   let port-pipes pipes-on patches at-points port-coords
   report port-pipes
end
 
to check-game-over
     if game-over? = false
     [ if clock-running? != true
       [ set clock-running? true
         set game-time timer
       ]
       if clock-running? = true
       [ ask patch max-pxcor max-pycor
         [ let time (int (timer - game-time ))
           set plabel (word "Time: " time)
         ]
       ]
       if any? pipes with [ color = connected-color ] and not any? pipes with [ shade-of? color open-color ]
       [ set game-over? true
         ask patch int (min-pxcor + world-width * .66) (min-pycor + 1)
         [ set plabel "YOU WIN!! Press reset to play again."
           set plabel-color orange
         ]

         ask pipes [ set color 5 + 10 * (pxcor mod 12) ]
         if clock-running? = true
         [ let time (int (timer - game-time ))
           if best-time = 0 or time < best-time
           [ set best-time  time
             set plabel-of patch max-pxcor min-pycor "BEST TIME!"
           ]
         ]
         if not is-turtle? hovered
         [ set hovered one-of pipes
         ]
         ask hovered [ set color white ]
         set stack []
         cct-mazers 1
         [ set shape "plumb-o-taur"
           set color white
           goto-agent hovered
           set traveller self
         ]
       ]
     ]
end        

to do-game-over-business
   ;; game-over business
      ifelse    value-from traveller [ patch-here ]
              != value-from hovered [ patch-here ]
       [ ask traveller
         [ face hovered
           jump .2
         ]
       ]
       [
         ask hovered
         [ let nextone one-of (pipes-at-ports with [ color != color-of myself ])
           ifelse is-turtle? nextone
           [ set color-of nextone color-of hovered
             ;; if any? (pipes-at-ports with [ color != color-of myself ])
             ;; [
                  set stack lput hovered stack
             ;; ]
             set hovered nextone
           ]
           [ ifelse length stack > 0
             [ set hovered last stack
               set stack but-last stack
             ]
             [ set hovered one-of pipes
               ask hovered [ set color 5 + 10 * random 14 ]
             ]
           ]
         ]
       ]
     
end     

                    


Download Link

View or download the complete model file (to download: right-click, save-link-as):
-- Download minos-plumber_2.2 --