WebMaze

Summary

HJG 2013-02-22 - A WebMaze is a maze of webpages, with links pointing to other pages of the maze.

The userinterface looks like an old-fashioned text-adventure, with commands like "Go north", "Go west" etc. Except, there are no objects, no inventory, no enemies, no actions etc. beside walking around:


 Maze

 You are in a maze of twisty little passages, all alike.

 The floor is solid stone.

 Exits:
 * North  another part of the maze
 * South  the entrance
 * West   a trap for webcrawlers and spammers

 © 2012-12-22                   Contact: Webmaster

Each such page is quite simple, but creating/maintaining all the links by hand would be errorprone and boring.

So I wrote a program that creates such a set of webpages. (Does that make me a html-programmer ? :)

This one is really simple, as it uses a hardcoded 3x3 maze:

      7 - 6 - 5
      !   !   !
 X <- 8 - 9 - 4
      -   !   !
      3 - 2 - 1 <- 0

  0: Entry=index.html  1: first room  2,3: dead end
  4,5,6,7: correct path  8: last room  X: Exit=index2.html 
  9: Trap (can be reached from rooms 2,4,6,8)

The entry- and exit-pages (here 0 and X) are 'outside', i.e. not part of the maze. The generated files index1- and index2.html are just meant as an example.

The trap is a set of rooms with links that only point to other traps. Anybody that visits more than 3-4 such trap-pages is most likely a bot / webcrawler.

One way to use this, is to 'hide' some part of a website (or all of it :)

E.g. all the maze-pages go into a subdirectory "webmaze", the standard startpage index.html redirects to the first maze-page, and the exit-page of the maze points to the renamed homepage, e.g. /index3.html.

To specify a redirection, just put a line like this at the top of the startpage (after "<head>"):

 <meta http-equiv="refresh" content="0; URL=webmaze/maze1.html">

To prevent cheating/guessing, we also need to catch 404-errors (i.e. redirect them to our trap-page :). Such a custom local ErrorDocument is specified with an entry in the file .htaccess, e.g. :

 ErrorDocument 404 /webmaze/maze9.html

Before using this script, you might want to customize it a bit (scheme for roomnames, messages, contact-eMail, index1/2/3-files etc.).

Code


 # https://wiki.tcl-lang.org/37725
 # webmaze08.tcl - HaJo Gurt - 2013-02-18

 #: Generate a set of webpages that form an text-adventure-type maze.
 # Contains a trap for webcrawlers.
 # Simple, static version

 # Now also generates example-files index1.html + index2.html.
 # index1.html is to be moved into the document-root of the webspace,
 # as a replacement for the default index.html.
 # All the maze*.html - files go into a subdir "webmaze".

 # Installation - at your workstation:
 # * Create subdir "webmaze" 
 # * Copy this script into this directory and run it there --> files are generated.
 # To run just the maze locally, drag+drop maze1.html into your browser.
 #
 # To see the redirection working, move index1.html one level up from webmaze,
 # then drop it into your browser.

 # Installation - at the webserver:
 # * Rename index.html --> index3.html
 # * Create subdir "webmaze" 
 # * Transfer all files maze* from subdir "webmaze" at the workstation
 #   to the subdir "webmaze" at the webserver.
 #   (Depending on your ftp-client, you might want to zip the files first)
 # * Transfer the file index1.html from subdir "webmaze" at the workstation
 #   to the webroot "/" at the webserver.
 # * Rename index1.html --> index.html
 #
 # Entering your website, the new index.html should redirect to webmaze/maze1.html.
 # After running thru the maze,  the last mazepage webmaze/maze8.html 
 # leads to the exitpage webmaze/index2.html, and this 
 # webmaze/index2.html redirects to index3.html, which is the old index.html.
 #
 # The examplefiles wait 5 seconds before redirecting, so you can see 
 # what is going on, but you can set that time to 0.

 # Todo:
 # * Generate a maze, like [maze generator] or [maze generator2],
 #   or import a maze-description in a suitable format.
 # * Simpler way to generate the set of trap-pages.
 # * Tweak page-layout, meta-entries etc.
 # * Options: Switch entry+exit / Disable trap (replace with deadend)

 set Hdr "WebMaze v0.8"

 ####+####1####+####2####+####3####+####4####+####5####+####6####+####7####+###
 ## Console-settings, to allow running in wish as well as in tclsh:
   catch { console show }
   catch { wm withdraw . }
 # catch { console eval { .console config -bg grey -fg blue } }
 # Resize & put at top-right corner on 1024x768:
 ##catch { console eval { wm geometry . 56x12+550+0 } }
   catch { console title "$Hdr" }

   proc q {} { exit }


   proc put1 {s} {
   #: Output to screen or file
     global fp
   # puts $s
     puts $::fp $s
   }

 ####+####1####+####2####+####3####+####4####+####5####+####6####+####7####+###

 if 0 {

 Simple 3x3 - Maze:

  N
 W+E
  S
      7 - 6 - 5
      !   !   !
 X <- 8 - 9 - 4
      -   !   !
      3 - 2 - 1 <- 0

  0: Entry=index.html   1: first room  2,3: dead end
  4,5,6,7: correct path  8: last room  X: Exit=index2.html
  9: Trap (can be reached from rooms 2,4,6,8)
 }


 # Hardcoded maze-layout:

   set Loc1   1   ;# First room
   set LocL   8   ;# Last  room
   set LocX   X   ;# Exit - redirecting examplefile is generated / see RoomName(), ExitPage()
   set LocT   9   ;# Trap

  #             Pg Ty  N  E  S  W
   set Links   " 1 R1  4  -  -  2
                 2 ..  9  1  -  3
                 3 DE  -  2  -  -
                 4 ..  5  -  1  9
                 5 ..  -  -  4  6
                 6 ..  -  5  9  7
                 7 ..  -  6  8  -
                 8 RL  7  9  -  X
                 9  T  9a 9b 9c 9d
                 9a T  9b 9c 9d 9e
                 9b T  9c 9d 9e 9f
                 9c T  9d 9e 9f 9g
                 9d T  9e 9f 9g 9h
                 9e t  9f 9g 9h 9i
                 9f T  9g 9h 9i 9
                 9g T  9h 9i 9  9
                 9h T  9i 9  9  9
                 9i T  9  9  9  9 "

   proc RoomName {N} {
   # set Name "http://example.com/maze$N.html"
     set Name "maze$N.html"
     if {$N == $::LocX} { set Name "index2.html" }

     return $Name
   }

 ####+####1####+####2####+####3####+####4####+####5####+####6####+####7####+###

   proc RoomText {Ty} {
                        set Msg "The floor is solid stone."
     if {$Ty == "R1"} { set Msg "You entered the maze here." }
     if {$Ty == "RL"} { set Msg "You can leave the maze from here." }
     if {$Ty == "X" } { set Msg "You have reached the exit." }
     if {$Ty == "DE"} { set Msg "This is a dead end." }
     if {$Ty == "D2"} { set Msg "Turn back!  The end is here!" }
     if {$Ty == "T" } { set Msg "You fell into this trap for webcrawlers and spammers." }
     if {$Ty == "t" } { set Msg "You are still falling down this trap." }
     return $Msg
   }

   proc LinkText {N} {
     global Loc1 LocL LocX LocT
                        set Msg "another part of the maze"
     if {$N == $Loc1} { set Msg "the entrance" }
     if {$N == $LocL} { set Msg "you see light from that part of the maze" }
     if {$N == $LocX} { set Msg "the exit" }
     if {$N == $LocT} { set Msg "a trap for webcrawlers and spammers" }
     return $Msg
   }

   proc RoomLink {Dir N} {
   # put1 "  <li> <a href=\"maze$N.html\">$Dir</a> [LinkText $N] </li>"
     put1 "  <li> <a href=\"[RoomName $N]\">$Dir</a> [LinkText $N] </li>"
   }

   proc TrapLink {Dir N} {
     put1 "  <li> <a href=\"[RoomName $N]\">$Dir</a> </li>"
   }

 ####+####1####+####2####+####3####+####4####+####5####+####6####+####7####+###

   proc Header {Pg Ty} {
     put1 "<html>"
     put1 "<head>"
   # put1 "<title>$::Hdr</title>"
     put1 "<title>WebMaze: $Pg</title>"          ;# for history & bookmarks
     put1 "</head>\n"
   }

   proc Body1 {Pg Ty} {
     put1 "<body>"
     put1 "<h1>Maze</h1><hr>"
     put1 "<br>"
     put1 "<p>You are in a maze of twisty little passages, all alike.</p>"
     put1 "<p>[RoomText $Ty]</p>"
     put1 "<p><b>Exits:</b>"
     put1 "<ul>"
   }

   proc RoomLinks {N E S W} {
     if {$N ne "-"} { RoomLink North $N }
     if {$E ne "-"} { RoomLink East  $E }
     if {$S ne "-"} { RoomLink South $S }
     if {$W ne "-"} { RoomLink West  $W }
   }
   proc TrapLinks {N E S W} {
     if {$N ne "-"} { TrapLink "Down - normal speed" $N }
     if {$S ne "-"} { TrapLink "Down (slower)" $S }
     if {$W ne "-"} { TrapLink "Down (faster)" $W }
     if {$E ne "-"} { TrapLink "Down (extra quick)" $E }
   }

   proc Body2 {} {
     put1 "</ul> </p>"
     put1 "<hr noshade>"
     put1 "<!-- Footer: -->"
     put1 "&copy; 2012-12-23 &nbsp; "
     put1 "Contact: <a href=mailto:[email protected]>Webmaster</a>"
     put1 "</body>"
   }

   proc Footer {} {
     put1 "</html>\n"
   }

 ####+####1####+####2####+####3####+####4####+####5####+####6####+####7####+###

   proc StartPage {File Txt To} {
   # Replacement for index.html, it redirects to the first maze-page.
   # The original index.html would be placed after the exit-page of the maze.
     puts "# File $File"
     set ::fp [open $File w]

     put1 "<html>"
     put1 "<head>"
     put1 "<meta http-equiv=\"refresh\" content=\"5; URL=$To\">"  ;# seconds until redirect
     put1 "<title>$Txt</title>"        
     put1 "</head>\n"
     put1 "<body bgcolor=cyan>"
     put1 "<h1>$Txt</h1><hr>"
     put1 " $Txt: <a href=\"$To\">$To</a>"
     put1 "</body>"
     put1 "</html>\n"

     close $::fp
   }

   proc ExitPage {File Txt To} {
   # Page after the maze is completed, it shows a short message,
   # and redirects to the old index.html (renamed "index3.html")
     set ::fp [open $File w]
     puts "# File $File"

     put1 "<html>"
     put1 "<head>"
     put1 "<meta http-equiv=\"refresh\" content=\"5; URL=$To\">"  ;# seconds until redirect
     put1 "<title>$Txt</title>"        
     put1 "</head>\n"
     put1 "<body bgcolor=lime>"                ;# light green
     put1 "<h1>$Txt</h1><hr>"
     put1 "<p>You have reached the exit.</p>"
     put1 "<p>Congratulations !</p>"
     put1 "<p>And now, for something completely different: <a href=\"$To\">$To</a></p>"
     put1 "</body>"
     put1 "</html>\n"

     close $::fp
   }

 ####+####1####+####2####+####3####+####4####+####5####+####6####+####7####+###

   puts "# $Hdr :"

   foreach {Pg Ty N E S W} $Links {

     set pgFile [RoomName $Pg]
     puts "# Page $Pg : $N $E $S $W - $pgFile"

     set fp [open $pgFile w]

     Header $Pg $Ty
     Body1  $Pg $Ty
     if {$Ty=="T" || $Ty=="t"} {
       TrapLinks $N $E $S $W
     } else {
       RoomLinks $N $E $S $W
     }
     Body2
     Footer

     close $fp
   }

   StartPage  index1.html       Redirect "webmaze/[RoomName $Loc1]"
   ExitPage   [RoomName $LocX]  Done     "../index3.html"

   puts "# done."

 #.

Comments

See also: