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 cct 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-at3d 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-at3d 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 ] ] cct 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 [ observe setxyz 0 0 screen-edge-x * 3 watch walker setxyz 0 0 screen-edge-x * 3 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 random-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 random-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 random-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 (screen-edge-x / 6) * 6 - 3 ) ;; within the boundries, not on or overlapping the edge and abs pycor <= (int (screen-edge-y / 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 (screen-edge-x / dist) * dist - path ) ;; within the boundries, not on or overlapping the edge and abs pycor <= (int (screen-edge-y / 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 value-from walker [ patch-here = goal and continuously? ] [ wait 5 setup ] [ ifelse value-from walker [ patch-here != goal ] [ 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 (screen-edge-y / dist) * dist ) - path let col-edge-x ( int (screen-edge-x / 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 (screen-edge-y / dist) * dist ) - path let col-edge-x (int (screen-edge-x / 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 ] [ 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 ] [ observe setxyz 0 0 (screen-size-x * 3) set-gaze-xyz 0 0 0 ] end to in-maze-view ifelse is-living-turtle? walker [ zoom-in-on-walker ] [ overhead-view ] end @#$#@#$#@ GRAPHICS-WINDOW 444 10 620 207 12 12 6.64 1 10 1 1 1 0 1 CC-WINDOW 5 274 629 369 Command Center BUTTON 25 137 131 170 setup-new-maze setup NIL 1 T OBSERVER T NIL BUTTON 83 191 188 224 NIL in-maze-view NIL 1 T OBSERVER T 1 SWITCH 235 117 379 150 smooth-movement? smooth-movement? 1 1 -1000 BUTTON 83 227 188 260 NIL overhead-view NIL 1 T OBSERVER T 2 BUTTON 278 10 333 43 //\\ stop-auto-mode\nmove-walker 1 NIL 1 T OBSERVER T W BUTTON 222 44 277 77 <<= stop-auto-mode\nturn-walker -1 NIL 1 T OBSERVER T A BUTTON 278 44 333 77 \\// stop-auto-mode\nreverse-walker NIL 1 T OBSERVER T S BUTTON 334 44 389 77 =>> stop-auto-mode\nturn-walker 1 NIL 1 T OBSERVER T D CHOOSER 10 10 148 55 maze-style maze-style "random" "direct" "diagonal" "garden" 2 BUTTON 207 81 302 114 NIL auto-navigate T 1 T OBSERVER NIL A SWITCH 304 81 420 114 continuously? continuously? 0 1 -1000 SLIDER 235 149 379 182 move-delay move-delay 0 0.1 0.08 0.01 1 NIL BUTTON 198 211 253 244 watch if is-living-turtle? walker [ watch walker ] NIL 1 T OBSERVER T NIL BUTTON 310 211 365 244 NIL observe NIL 1 T OBSERVER T NIL BUTTON 366 211 421 244 home set-gaze-xyz 0 .1 0\nsetxyz 0 -.1 screen-edge-x * 3\n NIL 1 T OBSERVER T NIL SLIDER 14 61 139 94 maze-path maze-path 1 7 1 2 1 NIL SLIDER 15 98 139 131 maze-gap maze-gap 1 7 3 2 1 NIL BUTTON 254 211 309 244 follow if is-living-turtle? walker [ follow walker ] NIL 1 T OBSERVER T NIL @#$#@#$#@ 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. @#$#@#$#@ default true 0 Polygon -7566196 true true 150 5 40 250 150 205 260 250 @#$#@#$#@ NetLogo 3-D Preview 1 @#$#@#$#@ @#$#@#$#@ @#$#@#$#@