#!/usr/local/bin/perl
$| = 1;
srand;

# Perl script practice!

$dir = "/users/rei/Random/Foobar";
$subdir = "/users/rei/Random/Foobar/Sessions";
$Mapname = "mapone";

$Numchars = 4;			# This system to be changed!
				# (Number of badguys in combat)
# Other things to do: stop using the really opaque "ME[#]" notation.
# Change to an associative array, maybe.
# Other: Make each game a directory
# Each dir contains copies of the original files, with the newer versions
# (update hit point count, etc).
# Each dir also contains a date file, so that the oldest dirs
# can be periodically purged.

$datafile = "datafile";

$passwordfile = "passwordfile";

$rdx_width = 11; #set size of grid x
$rdy_height = 11; #set size of grid y
$rdy_min = 8; # minimum y distance from entrance to destination
$mapx_width = 21;
$mapy_height = 21;

@alltraits = ("NAME", "STR", "INT", "DEX", "SPD", "HP", "ARM", "WPN", "CURHP", "CURLOC", "CURMAP");
@temp = @alltraits;

while ($temp = shift(@temp))
{
    $Z++;
}

# Need to set current location and current map as well.  (CURLOC, CURMAP).
# Then a separate items list.

# These are the selectable traits:
$traits{"1"} = "strength";
$traits{"2"} = "intelligence";
$traits{"3"} = "agility";
$traits{"4"} = "quickness";

#include ("$dir/Gameginedata"); eventually make the above a file.


#&dungeon_maker;
#&print_dungeon;
#exit;

&initial;
&loadchars;
&load_map;
&load_map_key;
&movement;


# -------------------------- END OF MAIN -------------------------



sub initial
{

    open (PASS, "$dir/$passwordfile") ||
	die "$0: $!: Couldn't open $dir/$passwordfile for reading.\n" ;
    while ($name = <PASS>)
    {
	chop ($name);
	$pword = <PASS>;
	chop ($pword);
	$pwordlist{$name} = $pword;
    }
    close (PASS);

    print ("Your game name: ");
    $Gamename = <STDIN>;
    chop $Gamename;
    $Gamename =~ tr/A-Z/a-z/;
# print("$Gamename lowercaseified.\n");
    $Gamename = $Gamename . ".game";
    
    if ($pwordlist{$Gamename})
    {
				# ask for password of existing game
	
	print ("Password required for $Gamename: ");
	$Password = <STDIN>;
	chop $Password;
	if ($Password ne $pwordlist{$Gamename}) 
	{
	    die "Wrong password; try again.\n";
	}
	else
	{
	    print("Using Game $Gamename\n");
	    open (DATA, "$dir/$Gamename");
	    for ($i = 0; $i <= $Z; $i++)
	    {
		$ME[$i] = <DATA>;
		chop $ME[$i];
		@vars = split(/ /,$ME[$i]);
		$ME[$i] = $vars[1];
		print ("$i: $alltraits[$i]: @ME[$i]\n");
	    }
	    close (DATA);
	    
	}			# 

    }
    else
    {
				# ask for new game
	print ("New Game by the name of $Gamename ? (Y/N) ");
	$newgame = <STDIN>;	# 
	if (!($newgame =~ /^y/i)) { die "Exiting: No game specified\n"; }
	else			# 
	{			# 
	    print ("Password for the new game: ");
	    $Password = <STDIN>;
	    chop $Password; 

# MAKE NEW CHARACTER HERE
	    print ("Character Generation\n");
	    print ("Character name: ");
	    $ME[0] = <STDIN>;
	    chop $ME[0];
	    print ("Now, you have a total of 100 points to distribute among the four ");	
	    print ("attributes\n of Strength, Intelligence, Agility, and Quickness.\n");
	    print ("After assigning these characteristics, you will be asked to confirm\n");
	    print ("the numbers.  You can type q at the end to exit the game.\n");
	    while (($Exit !~ /^y/i) && ($Exit !~ /^q/i))
	    {
# Prevent them from going over point total at some point		
		$Totalpoints = 100;
		foreach $key (sort keys %traits)
		{
		    while ($ME[$key] !~ /^\d+$/)
		    {
			print ("You have $Totalpoints pts.  $traits{$key}? ");
			$ME[$key] = <STDIN>;
			chop $ME[$key];
			if (($Totalpoints - $ME[$key]) < 0)
			{
			    $ME[$key] = "invalid";
			}
		    }
		    $Totalpoints = $Totalpoints - $ME[$key];
		}

		print ("Are these stats what you want (y/n/q)? ");
		$Exit = <STDIN>;
	    }
	    if ($Exit =~ /^q/i) { die "OK, bye!\n"; }

	    $ME[5] = int (($ME[1] + $ME[2] + $ME[3] + $ME[4])/4) ;
# Change this section later!!

	    $ME[6] = 5 ; # starting DB
	    $ME[7] = 5 ; # starting OB
	    $ME[8] = $ME[5]; #current HP
	    $ME[9] = "10,3";
	    $ME[10] = $Mapname;
	    
	}	
    }
    
}

sub loadchars
{
# Load nastybads from the initial file from char dir.

    print ("--------------------------------------------------------\n");
    $c = 0; $d = 0;    
    open (DATA, "$dir/$datafile");
    while ($line = <DATA>)
    {
#	print "Line: $line\n";
	if ($line =~ /^\*\s*$/)
	{
	    last;
	}
	if ($line =~ /^\.\s*$/)
	{
	    $c++;
	    $d=0;
	    next;
	}
	if ($line =~ /^\s*$/)
	{
	    next;
	}
	$THEM{$c, $d} = $line;	# This area will need more work to allow
				# for multiple items.
	chop $THEM{$c, $d};
#	print ("$c, $d, $THEM{$c, $d}\n");
	@vars = split(/ /, $THEM{$c, $d});
	$THEM{$c, $d} = $vars[1];
	$d++;
    }
    close (DATA);
}



sub movement
{
# ----------------------GAME STARTS HERE -----------------------------
# finish combat system.

# Generate map
# Place baddies on map
# let character go explore

    &print_map;
    unless (!($ME[9]))
    {
	@temp = split (",",$ME[9]);
	$curr_x = $temp[0];
	$curr_y = $temp[1];
    }

# Town, dungeon or outdoor wandering section..... ************

    while (1)
    {
	print("You are standing upon $Map($curr_x, $curr_y).\n");
	$curr_n = $curr_y - 1;
	$curr_s = $curr_y + 1;
	$curr_e = $curr_x + 1;
	$curr_w = $curr_x - 1;
	$curr_nn = $curr_n - 1;
	$curr_ee = $curr_e + 1;	
	$curr_ss = $curr_s + 1;
	$curr_ww = $curr_w - 1;

	print("\n");

	print("$Map{$curr_ww, $curr_nn} $Map{$curr_w, $curr_nn} $Map{$curr_x,
$curr_nn} $Map{$curr_e, $curr_nn} $Map{$curr_ee, $curr_nn}\n");

	print("$Map{$curr_ww, $curr_n} $Map{$curr_w, $curr_n} $Map{$curr_x,
$curr_n} $Map{$curr_e, $curr_n} $Map{$curr_ee, $curr_n}\n"); # 

	print("$Map{$curr_ww, $curr_y} $Map{$curr_w, $curr_y} Me $Map{$curr_e,
$curr_y} $Map{$curr_ee, $curr_y}\n");
	
	print("$Map{$curr_ww, $curr_s} $Map{$curr_w, $curr_s} $Map{$curr_x,
$curr_s} $Map{$curr_e, $curr_s} $Map{$curr_ee, $curr_s}\n");

	print("$Map{$curr_ww, $curr_s} $Map{$curr_w, $curr_ss} $Map{$curr_x,
$curr_ss} $Map{$curr_e, $curr_ss} $Map{$curr_ee, $curr_ss}\n");

	$ME[9] = "$curr_x,$curr_y";

	print("\n");
	print("> ");
	$Input = <STDIN>;
	chop $Input;
	$Input =~ tr/A-Z/a-z/;
	if (($Input =~ /^\s*n\s*$/) || ($Input =~ /^\s*8\s*$/))
	{
# Check the $Map{new value}
#	    $curr_y = $curr_y - 1; 
	    $tempy = $curr_n;	# $curr_n is same as $curr_y-1;
	    &checknew($curr_x,$tempy);
	}
	elsif (($Input =~ /^\s*e\s*$/) || ($Input =~ /^\s*6\s*$/))
	{
# Check the $Map{new value}
#	    $curr_x = $curr_x + 1;
	    $tempx = $curr_e;
	    &checknew($tempx,$curr_y);
	}
	elsif (($Input =~ /^\s*s\s*$/) || ($Input =~ /^\s*2\s*$/))
	{			# 
# Check the $Map{new value}
#	    $curr_y = $curr_y + 1;
	    $tempy = $curr_s;	# $curr_n is same as $curr_y-1;
	    &checknew($curr_x,$tempy);
	}
	elsif (($Input =~ /^\s*w\s*$/) || ($Input =~ /^\s*4\s*$/))
	{
# Check the $Map{new value}
#	    $curr_x = $curr_x - 1;
	    $tempx = $curr_w;
	    &checknew($tempx,$curr_y);
	}
	elsif (($Input =~ /^\s*ne\s*$/) || ($Input =~ /^\s*9\s*$/))
	{
# Check the $Map{new value}
#	    $curr_y = $curr_y - 1; 
#	    $curr_x = $curr_x + 1;
	    $tempx = $curr_e;
	    $tempy = $curr_n;	# $curr_n is same as $curr_y-1;
	    &checknew($tempx,$tempy);
	}
	elsif (($Input =~ /^\s*se\s*$/) || ($Input =~ /^\s*3\s*$/))
	{
# Check the $Map{new value}
#	    $curr_y = $curr_y + 1;
	    $tempy = $curr_s;	# $curr_n is same as $curr_y-1;
#	    $curr_x = $curr_x + 1;
	    $tempx = $curr_e;
	    &checknew($tempx,$tempy);
	}
	elsif (($Input =~ /^\s*sw\s*$/) || ($Input =~ /^\s*1\s*$/))
	{			# 
# Check the $Map{new value}
#	    $curr_y = $curr_y + 1;
	    $tempy = $curr_s;	# $curr_n is same as $curr_y-1;
#	    $curr_x = $curr_x - 1;
	    $tempx = $curr_w;
	    &checknew($tempx,$tempy);
	}
	elsif (($Input =~ /^\s*nw\s*$/) || ($Input =~ /^\s*7\s*$/))
	{
# Check the $Map{new value}
#	    $curr_y = $curr_y - 1; 
	    $tempy = $curr_n;	# $curr_n is same as $curr_y-1;
#	    $curr_x = $curr_x - 1;
	    $tempx = $curr_w;
	    &checknew($tempx,$tempy);
	}
	elsif ($Input eq "fight")
	{
	    &entercombat;
	}
	elsif (($Input =~ /^\s*q\s*$/i) || ($Input =~ /^\s*quit\s*$/i))
	{
	    print "Save your game?  ";
	    $yesno = <STDIN>;
	    if ($yesno =~ /^\s*y/i)
	    {
		print "\n";
		&savegame;
		exit;
	    }
	    else
	    {
		exit;
	    }
	}
	elsif ($Input =~ /^\s*save\s*$/i)
	{
	    &savegame;
	}
	else
	{
	    print "Sorry, I'm stupid.\n";
	}
    }
#    &checklocal;
}


sub savegame
{
    if ($newgame =~ /^y/i)
    {
	open (PASSADD, ">>$dir/$passwordfile") ||
	    die "Couldn't open $dir/$passwordfile for appending\n";
	print PASSADD "$Gamename\n";
	print PASSADD "$Password\n";
	close (PASSADD);
	print ("$Gamename with password $Password has been added.\n");
	$newgame = "no";
    }
# Someday needs to include location and states of badguys.
    open (SAVE, "> $dir/$Gamename") || die "$0: $!: can't save in $dir/$Gamename!\n";
    for ($i = 0; $i <= $Z; $i++)
    {
	print SAVE "$alltraits[$i] $ME[$i]\n";
    }
    close (SAVE);
    print "Game for game $Gamename, character $ME[0] saved in $dir/$Gamename.\n\n";


}

sub checknew
{
    @foo = @_;
    local($tempx, $tempy);
    $tempx = $foo[0];
    $tempy = $foo[1];
#    print "Trying to get to $tempx, $tempy!\n";
    if ($mapkey{$Map{$tempx, $tempy}} =~ /impenetrable/)
    {
	print "Sorry, you can't go that way!\n";
	return;
    }
    elsif (!($Map{$tempx, $tempy}))
    {
	print "Sorry, you can't go that way!\n";
	return;
    }
    else
    {
	$curr_x = $tempx;
	$curr_y = $tempy;
	return;
    }
}
    

sub checklocal
{
# find out if badguys are next to you or not.

    if ( $curr_y - 1)
    {

	}
	if ($Input eq "e")
	{
	    $curr_x = $curr_x + 1;
	}
	if ($Input eq "s")
	{			# 
	    $curr_y = $curr_y + 1;
	}
	if ($Input eq "w")
	{
	    $curr_x = $curr_x - 1;
	}
}

sub entercombat
{

    print("\nYou run into several nasty people right here.\n");

    for ($N = 0; $N <= $Numchars ; $N++)
    {
	print ("Type anything to commence battle number $N (q to quit). ");
	$anything = <STDIN>;	# 
	chop $anything;
	if ($anything eq "q") { die "Quit!\n"; }

	$MYlevel = 0;
	$THlevel = 0;
	for ($lev = 1; $lev <=4 ; $lev++)
	{
	    $MYlevel = $ME[$lev] + $MYlevel;
	    $THlevel = $THEM{$N, $lev} + $THlevel;
	}

	$THlevel = int($THlevel/(4*5));
	$MYlevel = int($MYlevel/(4*5));

	print ("Your level: $MYlevel.  $THEM{$N, 0}'s level: $THlevel\n");

	while (($THEM{$N, 8} > -($THEM{$N, 5})) && ($ME[8] > -($ME[5])))
	{			# 
	    print ("Type anything to roll for initiative (q to quit). ");
	    $anything = <STDIN>;
	    chop $anything;
	    if ($anything eq "q") { die "Quit!\n"; }
# Other options: run away, parry, spell(?)
# But initiative still determines who goes first(?)
	    $IGofirst = int (rand(100)+1) + int ($ME[4]/4);
	    $Theyfirst = int (rand(100)+1) + int ($THEM{$N, 4}/4);
	    print ("You roll: $IGofirst.\n \n");
	    if ($IGofirst >= $Theyfirst)
	    {
		print ("You attack first!\n");
		&attack;	# 
		if ($THEM{$N, 8} <= -($THEM{$N, 5})) { next; }
		print ("\n");	# 
		&theyattack;	# 
	}
	    if ($IGofirst < $Theyfirst)
	{
	    print ("$THEM{$N, 0} attacks first!\n");
	    &theyattack;
	    if ($ME[8] <= -($ME[5])) { next; }
	    print ("\n");
	    &attack;
	}			# 
	    print ("\nCurrent stats: $ME[0] has $ME[8] hps.	 $THEM{$N, 0} has $THEM{$N, 8} hps.\n");
	}
	print ("\nNext combat!\n");
	print ("Resetting your HP.\n");
	$ME[8] = $ME[5];

    }

}

sub attack
{
	print ("$ME[0]'s attack!\n");
	$MYROLL = int (rand(100) + 1);
	$THROLL = int (rand(100) + 1);

	print ("Your roll: $MYROLL.\n");
#	print ("Their roll: $THROLL\n");

	$MYattack = int (((2*$MYROLL) + $ME[3] + $ME[4] + $ME[6])/6);
	$THdefend = int (((2*$THROLL) + $THEM{$N, 3} + $THEM{$N, 4} + $THEM{$N, 6})/6);

	# print ("Your total attack: $MYattack.	 Their total defence: $THdefend.\n");

	$HITMISS = $MYattack - $THdefend;

	# print ("Difference: $HITMISS\n");

	if ($HITMISS <= 0) {print ("You miss!\n"); }
	else 
		{
		print ("You hit!\n");

		$MYOB = int ($ME[1] + (2 * $ME[7]));
		$THDB = int ($THEM{$N, 6});
		#print ("Your OB: $MYOB.  Their Defense: $THDB\n");

		$THpain = int (($HITMISS * $MYOB - $THDB)/100);
		if ($THpain < 0) {$THpain = 0;} 
		print ("$THEM{$N, 0} loses $THpain hit points\n");
		$THEM{$N, 8} = $THEM{$N, 8} - $THpain;
#		print ("They are down to $THnewhp.\n");
		if ($THEM{$N, 8} <= -($THEM{$N, 5})) {print ("$THEM{$N, 0} is dead!\n");}
		}


}



sub theyattack
{
	print ("$THEM{$N, 0}'s attack!\n");
	$MYROLL = int (rand(100) + 1);
	$THROLL = int (rand(100) + 1);

	print ("Your defense roll: $MYROLL.\n");
#	print ("Their attack roll: $THROLL\n");

	$THattack = int (((2*$THROLL) + $THEM{$N, 3} + $THEM{$N, 4} + $THEM{$N, 6})/6);
	$MYdefend = int (((2*$MYROLL) + $ME[3] + $ME[4] + $ME[6])/6);


	$HITMISS = $THattack - $MYdefend;

	# print ("Difference: $HITMISS\n");

	if ($HITMISS <= 0) {print ("$THEM{$N, 0} misses you!\n"); }
	else 
		{
		print ("You've been hit!\n");

		$THOB = int ($THEM{$N, 1} + (2 * $THEM{$N, 7}));
		$MYDB = int ($ME[6]);
		#print ("Your Defence: $MYDB.  Their OB: $THOB\n");

		$MYpain = int (($HITMISS * $THOB - $MYDB)/100);
		if ($MYpain < 0) { $MYpain = 0; }
		print ("You lose $MYpain hit points\n");
		$ME[8] = $ME[8] - $MYpain;
#		print ("You are down to $MYnewhp.\n");
		if ($ME[8] <= -($ME[5])) {print ("You're dead!\n");}
		}
# END THEIR ATTACK
}


sub dungeon_maker
{# Dungeon Generator (So it's not the most efficient in the world)

	for ($rdx = 0; $rdx <= ($rdx_width+1); $rdx++)
	{
		for ($rdy = 0; $rdy <= ($rdy_height+1); $rdy++) 
		{
		$RDungeon{$rdx, $rdy} = "S";
		}
	}
	$rdx_entrance = int (rand ($rdx_width));
	$rdy_entrance = 0;

# Entrance is somewhere along the y axis.  (0, 0) is at top left.
	$rdx_destination = int (rand($rdx_width - 1));
	$rdy_destination = int (rand($rdy_height - 1));
	if ($rdy_destination <= $rdy_min) { $rdy_destination = $rdy_min; }

	$curr_rdx = $rdx_entrance;
	$curr_rdy = $rdy_entrance;
# Now we connect the two with a semi-random path.
# LOOP BEGINS HERE
#&print_dungeon;
print ("\n");
# OH NO!  This can create corner-to-corner "squares"
# accidentally, or in sequence.	 **FIX THIS**!!!*****

$ack = 0;
until (($curr_rdx == $rdx_destination) && ($curr_rdy == $rdy_destination))
{

	$rdx_closeness = &absolute($rdx_destination - $curr_rdx);
	$rdy_closeness = &absolute($rdy_destination - $curr_rdy);
	$Next_rdx = int (rand(3)) - 1; #number of 1, 0, or -1 (W, same, or East)
# Next part says, if the new random place is further away from the destination
# Roll again.  Makes it just a little more likely to go toward the
# destination, rather than wander all over the screen.
	$newrdx_close = &absolute($rdx_destination - ($curr_rdx + $Next_rdx));
	if ($newrdx_close > $rdx_closeness)
		{
		 $Next_rdx = int (rand(3)) - 1;
		}
#	print ("X roll is $Next_rdx\n");
# Set bounds.
	$curr_rdx = $curr_rdx + $Next_rdx;
	if ($curr_rdx < 0) {$curr_rdx = 0;}
	if ($curr_rdx > $rdx_width) {$curr_rdx = $rdx_width;}
	
#	print ("New curr_rdx: $curr_rdx\n");
# Do the same for y.
	$Next_rdy = int (rand(3)) - 1;
	$newrdy_close = &absolute($rdy_destination - ($curr_rdy + $Next_rdy));
	if ($newrdy_close > $rdy_closeness)
		{
		 $Next_rdy = int (rand(3)) - 1;
		} 
#	print ("Y roll is $Next_rdy.\n");
	$curr_rdy = $curr_rdy + $Next_rdy;
	if ($curr_rdy < 0) {$curr_rdy = 0;}
	if ($curr_rdy > $rdy_height) {$curr_rdy = $rdy_height;}
#	print ("New curr_rdy: $curr_rdy\n");

# Now change the map.
	$RDungeon{$curr_rdx, $curr_rdy} = ".";
#print ("\n");
#&print_dungeon;
#print ("\n");
#	$ack++;
#	if ($ack == 10) { 
#		$ack = 0;
#		$answer = <STDIN>; }
#	chop $answer;
#	if ($answer eq "q") { die "ARGH!\n"; }
# Generate random dead ends here.

}
	$RDungeon{$rdx_entrance, $rdy_entrance} = "*";
	$RDungeon{$rdx_destination, $rdy_destination} = "?";
}

sub print_dungeon
{
for ($rdy = 0; $rdy <= ($rdy_height+1); $rdy++)
	{
	for ($rdx = 0; $rdx <= ($rdx_width+1); $rdx++)
		{
		print ("$RDungeon{$rdx, $rdy} ");
		}
	print ("\n");
	}
print ("********* That's it!! *********");
}

sub absolute
{
	($whatever_number) = @_;
	if ($whatever_number < 0) 
	{ 
		$whatever_number = -($whatever_number);
	}

return ($whatever_number);
}

sub load_map
{
#	print("Map name: ");
#	$Mapname = <STDIN>;
#	chop $Mapname;
    if (!($ME[10]))
    {
	$ME[10] = $Mapname;
    }
    $Mapname = $ME[10];

	open (MAP, "$dir/$Mapname")
		|| die "$0: $!: Couldn't open $dir/$Mapname!\n";
	
	for ($mapy = 0; $mapy <= ($mapy_height + 1); $mapy++)
	{
		$row = <MAP>;
		chop $row;
		@pieces = split (/ /, $row);
		for ($mapx = 0; $mapx <= ($mapx_width + 1); $mapx++)
		{
			$Map{$mapx, $mapy} = $pieces[$mapx];
#			print ("$mapx, $mapy = $pieces[$mapx]\n");
		}
	}
	close (MAP);
}

sub load_map_key
{
	open (MAP, "$dir/$Mapname.key")
		|| die "$0: $!: Couldn't open $dir/$Mapname.key!\n";
	while ($line = <MAP>)
	{
# Expect this format:
# MM = impenetrable,unviewable (etc)
	    if ($line =~ /\s*(\S+)\s+\=\s+(\S+)\s*$/)
	    {
		$mapkey{$1} = $2;
	    }
	}
}


sub print_map
{
for ($mapy = 0; $mapy <= ($mapy_height+1); $mapy++)
	{
	for ($mapx = 0; $mapx <= ($mapx_width+1); $mapx++)
		{
		print ("$Map{$mapx, $mapy} ");
		}
	print ("\n");
	}
print ("*********  *********");
}
