(gawkinet.info.gz) MAZE

Info Catalog (gawkinet.info.gz) STATIST (gawkinet.info.gz) Some Applications and Techniques (gawkinet.info.gz) MOBAGWHO
 
 3.7 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 ( 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 neighboring elements and
 remember which we have already treated. Of all the neighboring
 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_ neighboring 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 unvisited 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
        }
      }
 
Info Catalog (gawkinet.info.gz) STATIST (gawkinet.info.gz) Some Applications and Techniques (gawkinet.info.gz) MOBAGWHO
automatically generated by info2html