GNU Info

Info Node: (gawkinet.info)MAZE

(gawkinet.info)MAZE


Next: MOBAGWHO Prev: STATIST Up: Some Applications and Techniques
Enter node , (file) or (file)node

MAZE: Walking Through a Maze In Virtual Reality
===============================================

     In the long run, every program becomes rococo, and then rubble.
     Alan Perlis

   By now, we know how to present arbitrary `Content-type's to a
browser.  In this node, our server will present a 3D world to our
browser.  The 3D world is described in a scene description language
(VRML, Virtual Reality Modeling Language) that allows us to travel
through a perspective view of a 2D maze with our browser. Browsers with
a VRML plugin enable exploration of this technology. We could do one of
those boring `Hello world' examples here, that are usually presented
when introducing novices to VRML. If you have never written any VRML
code, have a look at the VRML FAQ.  Presenting a static VRML scene is a
bit trivial; in order to expose `gawk''s new capabilities, we will
present a dynamically generated VRML scene. The function `SetUpServer'
is very simple because it only sets the default HTML page and
initializes the random number generator. As usual, the surrounding
server lets you browse the maze.

     function SetUpServer() {
       TopHeader = "<HTML><title>Walk through a maze</title>"
       TopDoc = "\
         <h2>Please choose one of the following actions:</h2>\
         <UL>\
           <LI><A HREF=" MyPrefix "/AboutServer>About this server</A>\
           <LI><A HREF=" MyPrefix "/VRMLtest>Watch a simple VRML scene</A>\
         </UL>"
       TopFooter  = "</HTML>"
       srand()
     }

   The function `HandleGET' is a bit longer because it first computes
the maze and afterwards generates the VRML code that is sent across the
network. As shown in the STATIST example (Note: STATIST), we set the
type of the content to VRML and then store the VRML representation of
the maze as the page content. We assume that the maze is stored in a 2D
array. Initially, the maze consists of walls only. Then, we add an
entry and an exit to the maze and let the rest of the work be done by
the function `MakeMaze'.  Now, only the wall fields are left in the
maze. By iterating over the these fields, we generate one line of VRML
code for each wall field.

     function HandleGET() {
       if (MENU[2] == "AboutServer") {
         Document  = "If your browser has a VRML 2 plugin,\
           this server shows you a simple VRML scene."
       } else if (MENU[2] == "VRMLtest") {
         XSIZE = YSIZE = 11              # initially, everything is wall
         for (y = 0; y < YSIZE; y++)
            for (x = 0; x < XSIZE; x++)
               Maze[x, y] = "#"
         delete Maze[0, 1]              # entry is not wall
         delete Maze[XSIZE-1, YSIZE-2]  # exit  is not wall
         MakeMaze(1, 1)
         Document = "\
     #VRML V2.0 utf8\n\
     Group {\n\
       children [\n\
         PointLight {\n\
           ambientIntensity 0.2\n\
           color 0.7 0.7 0.7\n\
           location 0.0 8.0 10.0\n\
         }\n\
         DEF B1 Background {\n\
           skyColor [0 0 0, 1.0 1.0 1.0 ]\n\
           skyAngle 1.6\n\
           groundColor [1 1 1, 0.8 0.8 0.8, 0.2 0.2 0.2 ]\n\
           groundAngle [ 1.2 1.57 ]\n\
         }\n\
         DEF Wall Shape {\n\
           geometry Box {size 1 1 1}\n\
           appearance Appearance { material Material { diffuseColor 0 0 1 } }\n\
         }\n\
         DEF Entry Viewpoint {\n\
           position 0.5 1.0 5.0\n\
           orientation 0.0 0.0 -1.0 0.52\n\
         }\n"
         for (i in Maze) {
           split(i, t, SUBSEP)
           Document = Document "    Transform { translation "
           Document = Document t[1] " 0 -" t[2] " children USE Wall }\n"
         }
         Document = Document "  ] # end of group for world\n}"
         Reason = "OK" ORS "Content-type: model/vrml"
         Header = Footer = ""
       }
     }

   Finally, we have a look at `MakeMaze', the function that generates
the `Maze' array. When entered, this function assumes that the array
has been initialized so that each element represents a wall element and
the maze is initially full of wall elements. Only the entrance and the
exit of the maze should have been left free. The parameters of the
function tell us which element must be marked as not being a wall.
After this, we take a look at the four neighbouring elements and
remember which we have already treated. Of all the neighbouring
elements, we take one at random and walk in that direction. Therefore,
the wall element in that direction has to be removed and then, we call
the function recursively for that element.  The maze is only completed
if we iterate the above procedure for _all_ neighbouring elements (in
random order) and for our present element by recursively calling the
function for the present element. This last iteration could have been
done in a loop, but it is done much simpler recursively.

   Notice that elements with coordinates that are both odd are assumed
to be on our way through the maze and the generating process cannot
terminate as long as there is such an element not being `delete'd. All
other elements are potentially part of the wall.

     function MakeMaze(x, y) {
       delete Maze[x, y]     # here we are, we have no wall here
       p = 0                 # count unvisited fields in all directions
       if (x-2 SUBSEP y   in Maze) d[p++] = "-x"
       if (x   SUBSEP y-2 in Maze) d[p++] = "-y"
       if (x+2 SUBSEP y   in Maze) d[p++] = "+x"
       if (x   SUBSEP y+2 in Maze) d[p++] = "+y"
       if (p>0) {            # if there are univisited fields, go there
         p = int(p*rand())   # choose one unvisited field at random
         if        (d[p] == "-x") { delete Maze[x - 1, y]; MakeMaze(x - 2, y)
         } else if (d[p] == "-y") { delete Maze[x, y - 1]; MakeMaze(x, y - 2)
         } else if (d[p] == "+x") { delete Maze[x + 1, y]; MakeMaze(x + 2, y)
         } else if (d[p] == "+y") { delete Maze[x, y + 1]; MakeMaze(x, y + 2)
         }                   # we are back from recursion
         MakeMaze(x, y);     # try again while there are unvisited fields
       }
     }


automatically generated by info2www version 1.2.2.9