#!/usr/bin/perl -w

use strict;
use CGI qw(:standard);
use CGI::Carp qw(fatalsToBrowser);
use HTTP::Date;
use POSIX;

######################################################
#
#	Author: Beau Holder
#	Created: October 8, 2003 13:47 EST
#	Last-Modified: December 3, 2003 21:24 EST
#
#	For further information see my documentation:
#	http://cs.marlboro.edu/~eholder/cgi/ex/ex-pod.html
#
######################################################

## DEBUGGING SWITCH
my $DEBUG = 0;

## Print all parameters to a log file
test_incoming_parameters() if ($DEBUG == 1);

## Hash all the globals go into
my %globals;

## Initiate Parameters and Define Globals
init();
test_init() if ($DEBUG == 1);

## Get info from current room
Get_Info();
test_Get_Info() if ($DEBUG == 1);

## See if player won or lost with last move
Win_or_Lose();
test_Win_or_Lose() if ($DEBUG == 1);

## Print HTML
print header("text/html");
Print_Start();
#print start_html( -title => "Ex- Maze");
Print_Board();
test_Print_Board() if ($DEBUG == 1);
#Print_Controls();
#test_Print_Controls() if ($DEBUG == 1);
Print_Status();
#test_Print_Status() if ($DEBUG == 1);
print end_html;

## define subroutines
sub init {
 # Initialize Params and set globals
 if (not defined param('now_playing')) {
	param("locale" => 0);
	param("direction" => "New");
	param("movenum" => 0);
	param("pass" => 0);
	param("start_time" => time);
 }
 my $room = param('locale');
 %globals = (
	room => param('locale'),	dir => param('direction'),
	to_open => "rooms/room_$room\.txt",
	num_move => param('movenum'),	max_moves => 50,
	moves_left => (50 - param('movenum')),
	new_room => '',	pass => param('pass'),
	start_time => param('start_time'),
 );
 my @room_info;
 open(ROOM, $globals{to_open}); ## or die "Can't find $globals{to_open}: $!\n";
	while ( <ROOM> ) {
	 @room_info = <ROOM>;
	}
 close ROOM;
 $globals{"room_info"} = \@room_info;
}

sub Get_Info {
 # do all the $room/$new_room stuff
 ## display system used to allocate directions in the room files
 my %dir_to_num = (
	North => 9,
	East => 10,
	South => 11,
	West => 12,
 );
 ## if it isn't a new game, figure out where we moved otherwise give back same room
 if (not $globals{dir} eq "New") {
	$globals{new_room} = $globals{room_info}[$dir_to_num{$globals{dir}}];
	$globals{new_room} -= "\n";
 } else {
	$globals{new_room} = $globals{room};
 }

 ## make sure legal move was made before adding a move
	## NOT NEEDED DUE TO NEW NAVIGATION ##
	## Can't click an illegal move now ##
# if ($globals{new_room} == -1) { 
# $globals{new_room} = $globals{room}; 
# } else { 
 $globals{num_move}++; 
# }

 ## get stuff about new room
 $globals{to_open} = "rooms/room_$globals{new_room}.txt";
 my @new_room;
 open(NEWROOM, $globals{to_open});
 while ( <NEWROOM> ) {
	@new_room = <NEWROOM>;
 }
 close NEWROOM;
 my $loop = 0;
 while ($new_room[$loop]) {
	$new_room[$loop] =~ s/\n//g;
	$loop++;
 }
 $globals{new_info} = \@new_room;
}

sub Win_or_Lose {
 # check for and deal with winners and losers
 chomp($globals{new_room});
 if ($globals{room} == 12 && $globals{dir} eq "North") {
# if($globals{new_room} == 16) {
	my $end_time = time;
	my $play_time = floor($end_time - $globals{start_time});
	print redirect("get_name.cgi?moves=$globals{moves_left}&time=$play_time&why=win");
	exit;
 }
 if ($globals{num_move}-1 == $globals{max_moves}) {
	print redirect("highs.cgi");
	exit;
 }
}

sub Print_Start {
	## to keep track of starting time for JavaScript Timers
	my $now = time;
	my $play_time = $now - $globals{start_time};

#	print "Direction = $globals{dir}\n";	## Debugging
#	print "play_time = $play_time\n";	## Debugging

	print << "	END_OF_HTML";
	
	<html>
	<head>
	<title>Ex- Maze: The Recoding</title>
	<script language='JavaScript' src='timer.js'></script>
	</head>

	END_OF_HTML

	## need to keep track of original start time for the JavaScript Timers
	if ($globals{dir} eq "New") {
		print "<body onload=\"init(0)\">";
	} else {
		print "<body onload=\"init($play_time)\">";
	}
}

sub Print_Board {
 # print game board
 $globals{pass}++;
 print "<form action=\"ex.cgi\" method=\"POST\">\n";    
 print "<table cellpadding=\"0\" cellspacing=\"0\" border=\"0\" align=\"center\" width=\"450\" height=\"450\">\n";
 foreach my $tile (0..8) {
        my $tile_pic = $globals{new_info}->[$tile];
        my $is_exit = check_tile($tile_pic);
        my $direct = get_direct($tile_pic);
        print "<tr>" if ($tile == 0);
        print "</tr>\n<tr>" if ($tile%3 == 0 && $tile !=0);
        if ($is_exit) {
                ## print input image instead of image
                print "<td><input type=\"image\" src=\"$tile_pic\" name=\"direction\" value=\"$direct\"></td>\n";
        } else {
                ## print normal image
                print "<td><img src=\"$tile_pic\" height=\"150\" width=\"150\"></td>\n";
        }
 }
 print "</tr></table>\n";
 print "<input type=\"hidden\" name=\"locale\" value=\"$globals{new_room}\" OVERRIDE=\"1\">\n";
 print "<input type=\"hidden\" name=\"movenum\" value=\"$globals{num_move}\" OVERRIDE=\"1\">\n";
 print "<input type=\"hidden\" name=\"now_playing\" value=\"1\" OVERRIDE=\"1\">\n";
 print "<input type=\"hidden\" name=\"pass\" value=\"$globals{pass}\" OVERRIDE=\"1\">\n";
 print "<input type=\"hidden\" name=\"start_time\" value=\"$globals{start_time}\" OVERRIDE=\"1\">\n";
 print "</form>";
}

sub Print_Controls {
 # temporarily print controls below board
 ## I need to keep each button its own form
 ## because I can't send new direction accurately
 ## will be changed, because I know how to now ==> Give each submit the same name
 $globals{pass}++;
 print << "CONTROLS";
 <form action="ex.cgi" method="POST">
	<input type="hidden" name="locale" value="$globals{new_room}" OVERRIDE="1">
	<input type="hidden" name="movenum" value="$globals{num_move}" OVERRIDE="1">
	<input type="hidden" name="now_playing" value="1" OVERRIDE="1">
	<input type="hidden" name="pass" value="$globals{pass}" OVERRIDE="1">
	<input type="hidden" name="start_time" value="$globals{start_time}" OVERRIDE="1">
 <table align=center>
	<tr valign="center">
	<td> Pick the direction you wish to move: </td>
	<td> <input type="submit" name="direction" value="North"></td>
	<td> \|\| </td>
	<td> <input type="submit" name="direction" value="East"></td>
	<td> \|\| </td>
	<td> <input type="submit" name="direction" value="South"></td>
	<td> \|\| </td>
	<td> <input type="submit" name="direction" value="West"></td>
	</tr>
	<tr><td> <a href="ex.cgi">Click here</a> to reset the maze, and start anew. </td></tr>
 </table>
 </form>
CONTROLS
}

sub Print_Status {
 # print player status
 my $temp_time = time;
 my $time = $temp_time - $globals{start_time};
 my $time_left = 600 - $time;
 if ($time_left < 0) {
	$time_left = 0;
 }
 print << " STATUS";
 <table align="center" width="450">
  <tr>
	<td>You only have <u>$globals{moves_left} moves</u> before you become lost forever in 
the Ex-maze!</td>
  </tr>
  <tr>
	<td>
	<table align="center"><tr>
		<td width="150">
		Total play time : <td id="timer"></td>
		</td>
		<td width="150"> </td>
		<td width="150">
		Bonus time left : <td id="counter"></td>
		</td>
	</tr></table>
	</td>
  </tr>
  <tr>
	<td><a href="ex.cgi">Click here</a> to reset the maze, and start anew. </td>
  </tr>
 <tr>
	<td><b>How to play:</b> Click on the doorways to move about the Ex-Maze. Each move will teleport 
you to a different room. You can only win if you find out the correct path that starts at the first room. If you 
ever leave the "path" then you must figure out how to get back to the starting room in order to get back 
on the path. You are timed (more points awarded to those who figure it out in under 10 minutes) and only 
have 50 moves before you lose. Points are awarded based on bonus time left and number of moves left. You 
only set a high score if you complete the maze.<br>
	<b>NOTE:</b> This maze takes a good amount of problem solving and effort to solve! This is more 
for those of you who enjoy one large challenge more than racking up points by solving/beating many little 
"challenges." I recommend having something to keep your own map to help you figure out the maze.<br>
	<b>For a little extra help:</b> The maze is set in a 4x4 grid. The only exit to the outside is in 
the North-Western corner room, going North. The exit is clearly marked in the room the has the exit ("Exit" in 
big red letters in the doorway). There is only one path, and only one way to get on it (the first room) 
and only one move from each room on the path will keep you on it. Try wanding around a while and getting 
used to returning to the first room... it helps a lot.</td>
 </tr>
 </table>
 STATUS
}

sub check_tile {
        my $is_exit;
        my $tile = shift;
#       print "tile = $tile ==== ";
        $tile =~ s/tiles\///g;
#       print "tile = $tile ==== ";
	my $copy = $tile;
        $tile =~ s/[^ex]*//g;
#       print "tile = $tile<p>";
        $tile =~ s/ee//g;
        $tile =~ s/exe/ex/g;
#       print "tile = $tile<p>";
        if ($tile eq "ex" || $copy eq "exit.gif") {
                $is_exit = 1;
        } else {   
                $is_exit = 0;
        }
#       print "is_exit = $is_exit<p>";
        return $is_exit;
}

sub get_direct {
        my $direct;
        my $tile = shift;
#       print "tile = $tile ====";
        $tile =~ s/tiles\///g;
#       print "tile = $tile ====";
	if ($tile eq "exit.gif") {
		$direct = "North";
	} else {
	        $tile =~ s/.gif//g;
	        $tile =~ s/\w\wwall//g;
		$tile =~ s/\wwall//g;
	        $tile =~ s/center//g;
	        $tile =~ s/ex*//g;
	        $tile =~ s/\s//g;
	#       print "tile = $tile<p>";
	        if ($tile eq "up") {
	                $direct = "North";
	        }
	        if ($tile eq "right") {
	                $direct = "East";
	        }
	        if ($tile eq "down") {
	                $direct = "South";
	        }
	        if ($tile eq "lft") {
	                $direct = "West";
		}
	}
#       print "$direct";
        return $direct;
}  

############################
## START TESTING ROUTINES ##
############################

sub test_incoming_parameters {
 # print name-value pairs of all incoming parameters
 my $log = "logs/params.log";
 open (LOG, ">>$log");
 my $time = time2str();
 print LOG "Date: $time\n";

 my $dir = param('direction') || "undefined";
 my $loc = param('locale') || "undefined";
 my $num = param('movenum') || "undefined";
 my $now = param('now_playing') || "undefined";
 my $tim = param('start_time') || "undefined";

 print LOG "now_playing parameter = $now\n";
 print LOG "locale parameter = $loc\n";
 print LOG "direction parameter = $dir\n";
 print LOG "num_move parameter = $num\n";
 print LOG "start_time parameter = $tim\n";

 my $pass = param('pass') || "0";
 print LOG "That's all of the parameters for $pass";
 print LOG "\n\n";
 close LOG;
}

sub test_init {
 # test init() to see if there are any failures in this subroutine
# print "you're in test_init\n";
 my $logfile = "logs/init.log";
 open(LOG, ">>$logfile");

# print "printing to log now...\n\n";
# print LOG "Look, a line!";

 my $time = time2str();
 print LOG "Date: $time\n";
 my $num = param('movenum');
 if (not defined param('now_playing') && not defined param('pass')) {
	print LOG "1	PASS	#now_playing parameter undefined, new game started\n";
 } elsif (not defined param('now_playing') || not defined param('pass')) {
	print LOG "1	FAIL	#now_playing undefined, not a new game\n";
 } else {
	print LOG "1	PASS	#now_playing defined, game in progress\n";
 }
 if (defined param('locale')) {
	print LOG "2	PASS	#locale parameter defined as $globals{room}\n";
 } else {
	print LOG "2	FAIL	#locale parameter undefined\n";
 }
 if (defined param('direction')) {
	print LOG "3	PASS	#direction parameter defined as $globals{dir}\n";
 } else {
	print LOG "3	FAIL	#direction parameter undefined\n";
 }
 if (defined param('movenum')) {
	print LOG "4	PASS	#movenum parameter defined as $num\n";
 } else {
	print LOG "4	FAIL	#movenum parameter undefined\n";
 }

 # loop through %globals hash keys and make sure all are defined
 my $count = 4;
 for my $keys (keys(%globals)) {
	$count++;
	print LOG "$count	";
	if (defined $globals{$keys}) {
		print LOG "PASS	#$keys is defined as $globals{$keys}\n";
	} else {
		print LOG "FAIL	#$keys is undefined\n";
	}
 }
 print LOG "testing of init subroutine complete"; 
 print LOG "\n\n";
 close LOG;
# print "log closed\n";
}

sub test_Get_Info {
 # test Get_Info() to make sure there are no errors
 my $logfile = "logs/Get_Info.log";
 open(LOG, ">>$logfile");
 my $time = time2str();
 print LOG "Date: $time\n";
 my $count = 0;

 my %dir_to_num = (
	North => 9,
	East => 10,
	South => 11,
	West => 12,
 );

 for my $keys (keys(%dir_to_num)) {
	$count++;
	print LOG "$count	";
	if (defined $dir_to_num{$keys}) {
		print LOG "PASS	#$keys defined as $dir_to_num{$keys}\n";
	} else {
		print LOG "FAIL	#$keys undefined\n";
	}
 }
 $count++;
 if (defined $globals{'new_room'}) {
	print LOG "$count	PASS	#new_room is defined as $globals{'new_room'}\n";
 } else {
	print LOG "$count	FAIL	#new_room is undefined\n";
 }
 $count++;
 if (defined $globals{'to_open'}) {
	print LOG "$count	PASS	#to_open defined as $globals{'to_open'}\n";
 } else {
	print LOG "$count	FAIL	#to_open is undefined\n";
 }
 $count++;
 if (defined $globals{'new_info'}) {
	print LOG "$count	PASS	#new_info succesfully created\n";
 } else {
	print LOG "$count	FAIL	#failed to create new_info\n";
 }

 print LOG "testing of Get_Info subroutine complete";
 print LOG "\n\n";
 close LOG;
}

sub test_Win_or_Lose {
 # testing for Win_or_Lose subroutine
 my $logfile = "logs/Win_or_Lose.log";
 open(LOG, ">>$logfile");
 my $time = time2str();
 print LOG "Date: $time\n";
 print LOG "1	PASS	#globals{room} is defined as $globals{room}\n" if (defined $globals{room});
 print LOG "1	FAIL	#globals{room} is undefined\n" if (not defined $globals{room});
 print LOG "2	PASS	#globals{dir} is defined as $globals{dir}\n" if (defined $globals{dir});
 print LOG "2	FAIL	#globals{dir} is undefined\n" if (not defined $globals{dir});
 print LOG "3	PASS	#globals{start_time} is defined as $globals{start_time}\n" if (defined 
$globals{start_time});
 print LOG "3	FAIL	#globals{start_time} is undefined\n" if (not defined $globals{start_time});
 print LOG "4	PASS	#globals{moves_left} is defined as $globals{moves_left}\n" if (defined 
$globals{moves_left});
 print LOG "4	FAIL	#globals{moves_left} is undefined\n" if (not defined $globals{moves_left});
 print LOG "5	PASS	#globals{num_move} is defined as $globals{num_move}\n" if (defined 
$globals{num_move});
 print LOG "5	FAIL	#globals{num_move} is undefined\n" if (not defined $globals{num_move});
 print LOG "6	PASS	#globals{max_moves} is defined as $globals{max_moves}\n" if (defined 
$globals{max_moves});
 print LOG "6	FAIL	#globals{max_moves} is undefined\n" if (not defined $globals{max_moves});

 print LOG "testing of Win_or_Lose subroutine complete";
 print LOG "\n\n";
 close LOG;
}

sub test_Print_Board {
 #check for errors with printing the board
 my $log = "logs/Print_Board.log";
 open(LOG, ">>$log");
 my $time = time2str();
 print LOG "Date: $time\n";
 my $count = 0;
 foreach my $tile (0..8) {
	$count++;
	my $tile_pic = $globals{new_info}->[$tile];
	if (defined $tile_pic) {
		print LOG "$count	PASS	#tile $tile defined as $tile_pic";
	} else {
		print LOG "$count	FAIL	#tile $tile not defined\n";
	}
 }
 print LOG "testing of Print_Board complete";
 print LOG "\n\n"; 
 close LOG;
}

sub test_Print_Controls {
 #test Print_Controls()
 my $log = "logs/Print_Controls.log";
 open(LOG, ">>$log");
 my $time = time2str();
 print LOG "Date: $time\n";
 if (defined $globals{new_room}) {
	print LOG "1	PASS	#new_room is defined as $globals{new_room}\n";
 } else {
	print LOG "1	FAIL	#new_room is undefined\n";
 }
 if (defined $globals{num_move}) {
	print LOG "2	PASS	#num_move is defined as $globals{num_move}\n";
 } else {
	print LOG "2	FAIL	#num_move is undefined\n";
 }
 print LOG "testing of Print_Controls complete";
 print LOG "\n\n"; 
 close LOG;
}

