3d-maze

No preview image

1 collaborator

Uri_dolphin3 Uri Wilensky (Author)

Tags

3d 

Tagged by Reuven M. Lerner over 11 years ago

3d-maze 

Tagged by Qian li about 10 years ago

maze 

Tagged by Reuven M. Lerner over 11 years ago

Model group CCL | Visible to everyone | Changeable by group members (CCL)
Model was written in NetLogo 3D Preview 4 • Viewed 1261 times • Downloaded 69 times • Run 6 times
Download the '3d-maze' modelDownload this modelEmbed this model

Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)


WHAT IS IT?

A model to demonstrate / work with netlogo 3d programming

A model to demonstrate creating basic mazes in netlogo

A model to demonstrate a simple maze-traversing algorithm

A model to demonstrate smooth vs coarse movement of turtles in a model.

HOW IT WORKS

A recursive routine creates a maze.

The maze routine shown here seems more complex than it is because it allows for varying path widths and wall (gap between paths) widths.

For many uses, an simply 1 unit maze routine will do as well.

THINGS TO NOTICE

If the maze paths are more than 3 units wide, the auto-navigate routine will never find the goal, because the routing only checks the current patch and the path to the immediate left of the walker.

THINGS TO TRY

EXTENDING THE MODEL

This section could give some ideas of things to add or change in the procedures tab to make the model more complicated, detailed, accurate, etc.

RELATED MODELS

This model is kin to maze-maker-2004.nlogo.

Comments and Questions

Click to Run Model

globals
[ start
  goal
  walker
  auto-mode
]

to setup
   ca
   let path maze-path
   let gap  maze-gap
   set goal set-goal path gap
   set start set-start path gap
   set auto-mode 0

   ask patches with [ pzcor <= 0 ]
   [ set pcolor gray - 10 * pzcor - 2 + 2 * pzcor + ((pycor + pxcor) mod 2) ]

   ;; create a turtle
   ;; toss in the center.
   ;; clear space around it
   ;; start carving maze from surface
   crt 1
   [ setxyz 0 0 0
     set pcolor 0
     big-stamp path 0
     ; make-maze
     ; make-maze-2
     make-maze-3 path gap (timer + 2)

     die
   ]

   ;; create, label, and clear goal block
   ask goal
   [ big-stamp path 0
     set plabel "XX"
     ask patch-at 0 0 -1 [ set pcolor green ]
     ifelse maze-style = "garden"
     [ big-stamp (1 + 2 * int ((path + gap) / 2)) 0
     ]
     [sprout 1
       [ set heading 180
       fd int( path / 2) + 1
       while [ pcolor != 0 ]
       [ big-stamp path 0
         fd path
       ]
       die
      ]
    ]

   ]

   ;; create, label, and clear start block
   ask start
   [ big-stamp path 0
     set plabel "SS"
     ask patch-at 0 0 -1 [ set pcolor blue ]
     sprout 1
     [ set heading 0
       fd int( path / 2) + 1
       while [ pcolor != 0 ]
       [ big-stamp path 0
         fd path
       ]
       die
     ]
   ]

   crt 1
   [ set walker self
     set xcor [pxcor] of start
     set ycor [pycor] of start
     set heading 0
     set color yellow
   ]
end 

to zoom-in-on-walker
   if is-living-turtle? walker
   [ ask walker [ hide-turtle ]
     ride walker
   ]
end 

to zoom-out-from-walker
   if is-living-turtle? walker
   [
     reset-perspective
     watch walker
     ask walker [ show-turtle ]
   ]
end 

to make-maze
   ;; recursive maze making procedure.
   ;; uses multiple turtles to carve the maze
   ;; could be made more memory efficient by using only one turtle
   ;; that keeps a "stack" in list, and uses the stack
   ;; to retrace back to junction points.
   ;; but using turtles is easier
   ;; could also make this a reporter, and pass the current location is and out,
   ;; so that the turtle
   ;; pops back to the spot reported.. oo i like that... see make-maze-2
   let unused-paths wall-blocks-in-neighborhood-nowrap

   ;; while any unused-paths in the neighborhood
   ;; dig maze paths though the blocks
   while [ any? unused-paths ]
   [ let selected one-of unused-paths
     set heading towards selected
     ;; carve patch to new spot
     jump 3 big-stamp 3 0 jump 3 big-stamp 3  0
     ;; hatch new turtle to continue maze making from here
     hatch 1 [ make-maze ]
     ;; update unused-pathsopen blocks
     set unused-paths wall-blocks-in-neighborhood-nowrap
   ]
   ;; can't go any father, die
   die
end 

to make-maze-2
   ;; recursive maze making procedure.
   ;; remembers the current location
   ;; so that the turtle
   ;; pops back to the spot

   ;; remember where I am now
   let location patch-here

   ;; are there any possible paths out of here?
   let unused-paths wall-blocks-in-neighborhood-nowrap

   ;; while there are unused-paths from here,
   ;; dig maze paths though the blocks
   while [ any? unused-paths ]
   [ let selected one-of unused-paths
     set heading towards selected
     ;; carve patch to new spot
     jump 3 big-stamp 3 0 jump 3 big-stamp 3 0
     ;; hatch new turtle to continue maze making from here
     make-maze-2

     ;; update unused-paths
     set unused-paths wall-blocks-in-neighborhood-nowrap
   ]
   ;; can't go any father, and since I probably moved around in that while loop,
   ;; I have to jump back to my starting location
   setxy [pxcor] of location [pycor] of location
end 

to make-maze-3 [ path gap timeout ]
   ;; recursive maze making procedure.
   ;; remembers the current location
   ;; so that the turtle
   ;; pops back to the spot

   let dist path + gap

   ;; remember where I am now
   let location patch-here

   ;; while there are unused-paths from here,
   ;; dig maze paths though the blocks
   ;; There are at most 4 paths
   repeat 4
   [ ;; are there any possible paths out of here?
     let unused-paths wall-blocks-in-neighborhood-nowrap-3 path gap
     if any? unused-paths and timer < timeout
     [ let selected one-of unused-paths
       set heading towards selected
       ;; carve patch to new spot
       repeat (path + gap )
       [ jump 1 big-stamp path 0 ]
       ;  jump ((gap + path) / 2) big-stamp path 0 jump ((gap + path) / 2) big-stamp path 0
       ;; hatch new turtle to continue maze making from here
       make-maze-3 path gap timeout
     ]
     ;; update unused-paths
     set unused-paths wall-blocks-in-neighborhood-nowrap-3 path gap   ]
   ;; can't go any father, and since I probably moved around in that while loop,
   ;; I have to jump back to my starting location
   setxy [pxcor] of location [pycor] of location
end 

to-report wall-blocks-in-neighborhood-nowrap
   report far-neighbors-nowrap with
   [     pcolor != 0 ;; a wall, not carved yet
     and abs pxcor <= (int (max-pxcor / 6) * 6 - 3 ) ;; within the boundries, not on or overlapping the edge
     and abs pycor <= (int (max-pycor / 6) * 6 - 3 ) ;; within the boundries, not on or overlapping the edge
   ]
end 

to-report far-neighbors-nowrap
   let points [[0 -6][0 6][6 0][-6 0]]
   report (patches at-points points ) ;; the 4 patches, path + gap units away
           with
           [     pxcor - [pxcor] of myself <= 6  ;; not wrapped, ie, dist or less units away
             and pycor - [pycor] of myself <= 6  ;; not wrapped
           ]
end 

to-report wall-blocks-in-neighborhood-nowrap-3 [ path gap ]
   let dist gap + path
   report (far-neighbors-nowrap-3 dist) with
   [     pcolor != 0 ;; a wall, not carved yet
     and abs pxcor <= (int (max-pxcor / dist) * dist - path ) ;; within the boundries, not on or overlapping the edge
     and abs pycor <= (int (max-pycor / dist) * dist - path ) ;; within the boundries, not on or overlapping the edge
   ]
end 

to-report far-neighbors-nowrap-3 [ dist ]
   let points (list list 0 (- dist)
                    list 0 dist
                    list dist 0
                    list (- dist) 0
               )
   report (patches at-points points ) ;; the 4 patches, path + gap units away
           with
           [     pxcor - [pxcor] of myself <= dist  ;; not wrapped, ie, dist or less units away
             and pycor - [pycor] of myself <= dist  ;; not wrapped
           ]
end 

to big-stamp [ side hue ]
   let edge (side - 1) / 2

   let points n-values (side * side) [ list ((? mod side) - edge) (int (? / side) - edge) ]
   ask patches at-points points
   [ set pcolor 0 ]
end 

to move-walker [ dir ]
   if not is-living-turtle? walker [ stop ]

   ask walker
     [ if path-ahead-clear?
       [ ifelse smooth-movement?
         [ repeat 5 [ jump .2 * dir wait move-delay ] ]
         [ jump 1 * dir wait move-delay ]
       ]
    ]
end 

to turn-walker [ dir ]
   ;; dir = -1 (left) or +1 (right)
   if not is-living-turtle? walker [ stop ]
   ;; if required, walker will move forward, then turn
   ;; otherwise, walker will just turn
   ask walker
   [ if not path-turn-clear? dir and path-turn-ahead-clear? dir
     [ move-walker 1 ]
     ifelse smooth-movement?
     [ repeat 5 [ rt 18 * dir wait move-delay ] ]
     [ rt 90 * dir wait move-delay ]
   ]
end 

to reverse-walker
   if not is-living-turtle? walker [ stop ]

   ask walker
   [ let dir -1
     repeat 2
     [ ifelse smooth-movement?
       [ repeat 5 [ rt 18 * dir wait move-delay ] ]
       [ rt 90 * dir wait move-delay ]
     ]
   ]
end 

to auto-navigate
   ifelse auto-mode = 1
   [ set auto-mode 0
     stop
   ]
   [ set auto-mode 2 ]
   ifelse auto-mode != 1
   [ set auto-mode 2 ]
   [ stop ]

   if not is-living-turtle? walker
   [ stop ]

   ifelse [ patch-here = goal and continuously? ] of walker
   [ wait 5
     setup
   ]
   [ ifelse [ patch-here != goal ] of walker
     [ ask walker
       [
         ifelse patch-left-and-ahead 90 1 = goal
         [ turn-walker -1
           move-walker 1
         ]
         [ ifelse not any? neighbors with [ pcolor != 0 ] ;; out in the open!
           [ ;; step sideways
             turn-walker 1
             move-walker 1
             turn-walker -1
           ]
           [ ifelse path-turn-ahead-clear? 1
             [ turn-walker 1 ]
             [ ifelse path-ahead-clear?
               [ move-walker 1 ]
               [ ifelse path-turn-clear? -1
                 [ turn-walker -1 ]
                 [ reverse-walker ]
               ]
             ]
           ]
         ]
       ]
     ]
     [ stop ]
   ]
end 

to stop-auto-mode
   if auto-mode != 0
   [ set auto-mode 1
     stop
   ]
end 

to-report is-living-turtle? [ variable]
   report (is-turtle? variable and variable != nobody )
end 

to-report path-ahead-clear?
   report [pcolor] of patch-ahead 1 = black
end 

to-report path-turn-clear? [ dir ]
   report [pcolor] of patch-right-and-ahead (90 * dir) 1 = black
end 

to-report path-turn-ahead-clear? [ dir ]
   report [pcolor] of patch-right-and-ahead (45 * dir) 1.41 = black
end 

to-report set-start [ path gap ]
   let dist gap + path
   let row-edge-y ( int (max-pycor / dist) * dist ) - path
   let col-edge-x ( int (max-pxcor / dist) * dist ) - dist
   let row patches with [ pzcor = 0 and pycor = (- row-edge-y) and abs pxcor <= col-edge-x and pxcor mod dist = 0 ]
   report
     (switch-hack maze-style row (- col-edge-x) ;; need to pass local variables values
       [ "random"      [ "random-one-of v1" ]  ; random bottom row
         "direct"      [ "one-of v1 with [ pxcor = 0 ]" ]  ;; center bottom
         "diagonal"    [ "one-of v1 with [ pxcor = v2 ]" ]  ;; bottom left
         "garden"      [ "one-of v1 with [ pxcor = 0 ]" ]  ;; center bottom
         []            []
       ]
     )
end 

to-report set-goal [ path gap ]
   let dist gap + path
   let row-edge-y (int (max-pycor / dist) * dist ) - path
   let col-edge-x (int (max-pxcor / dist) * dist ) - dist
   let row patches with [ pzcor = 0 and pycor = ( row-edge-y) and abs pxcor <= col-edge-x and pxcor mod dist = 0 ]
   report
     (switch-hack maze-style row col-edge-x ;; need to pass local variables values
         [ "random"      [ "random-one-of v1" ] ;; random top row
           "direct"      [ "one-of v1 with [ pxcor = 0 ]" ] ; center-top
           "diagonal"    [ "one-of v1 with [ pxcor = v2]" ] ; top right
           "garden"      [ "patch3d 0 0 0" ]  ;; center
           []            []
         ]
      )
end 

to-report switch-hack [ switch-value v1 v2 switch-array ]
   ;; see if value can be found in the switch-array
   ;; built short-list of values from array
   let switch-list (n-values (length switch-array / 2) [ item (? * 2) switch-array ])
   let selection position switch-value switch-list
   ;; was the value found?
   if is-boolean? selection
   [ ;; no. value not found in switch array,
     ;; so invoke the "otherwise" clause, the last row.
     ;; if no otherwise clause is desired,
     ;; enter an unlikely/impossible value.
     ;; for example, a blank "", 0, the empty list []
     ;; especially an entry of a type different from the type being switched.
     set selection (length switch-list )
   ]
   set switch-list (n-values (length switch-array / 2) [ item (? * 2 + 1) switch-array ])
   let reporter first item selection switch-list
   let result 0
   carefully
   [ set result run-result reporter ]
   [ user-message (word "The switch-array reporter in line # " selection ": '" reporter "' produced an error." error-message )
   ]
   report result
end 

to overhead-view
   ifelse is-living-turtle? walker
   [ zoom-out-from-walker ]
   [
     reset-perspective
     setxyz 0 0 (world-width * 3)
     face patch 0 0 0
   ]
end 

to in-maze-view
   ifelse is-living-turtle? walker
   [ zoom-in-on-walker
   ]
   [ overhead-view ]
end 

There are 2 versions of this model.

Uploaded by When Description Download
Uri Wilensky over 14 years ago Updated from NetLogo 4.1 Download this version
Uri Wilensky over 14 years ago 3d-maze Download this version

Attached files

No files

This model does not have any ancestors.

This model does not have any descendants.