#!/usr/bin/perl -w

# $Id: maze.pl,v 1.1 2004/06/29 21:20:36 mike Exp $
#
# This program is based on my no-doubt faulty recollection of an
# infinite maze generator from the (I think) March 1982 issue of
# Practical Computing magazine, which was dedicated entirely to
# Adventure games.

use strict;

my @dir = (
	   [ "North", 0,  1,  0 ],
	   [ "South", 0, -1,  0 ],
	   [ "East",  1,  0,  0 ],
	   [ "West", -1,  0,  0 ],
	   [ "Up",    0,  0, -1 ],
	   [ "Down",  0,  0,  1 ],
	   );

my($x, $y, $z) = (0, 0, 0);
while (!is_clear($x, $y, $z)) {
    $x++;
}

LOCATION: while (1) {
    if ($z == 0) {
	print "I'm in a rock-strewn wilderness.\n";
    } else {
	print "I'm in an underground cavern.\n";
    }

    my $nexits = 0;
    foreach my $dir (@dir) {
	my($name, $dx, $dy, $dz) = @$dir;
	next if $z == 0 && $name eq "Up";
	if (is_clear($x+$dx, $y+$dy, $z+$dz)) {
	    if ($nexits ==0) {
		print "I can go: $name";
	    } else {
		print ", $name";
	    }
	    $nexits++;
	}
    }

    if ($nexits == 0) {
	print "There's no way out!\n";
    } else {
	print "\n";
    }

    while (1) {
	$| = 1;
	print "Which way? ";
	$| = 0;
	my $cmd = <STDIN>;
	chomp($cmd);

	my $i;
	for ($i = 0; $i < @dir; $i++) {
	    my ($name, $dx, $dy, $dz) = @{ $dir[$i] };
	    last if (lc(substr($name, 0, length($cmd))) eq lc($cmd));
	}

	if ($i == @dir) {
	    print "I don't recognise that direction.\n";
	    next;
	}

	my ($name, $dx, $dy, $dz) = @{ $dir[$i] };
	if ($name eq "Up" && $z == 0) {
	    print "Surely you jest!\n";
	    next;
	}

	if (!is_clear($x+$dx, $y+$dy, $z+$dz)) {
	    print "There's no exit that way.\n";
	    next;
	}

	print "I go $name ...\n";
	$x += $dx; $y += $dy; $z += $dz;
	next LOCATION;
    }
}

sub is_clear {
    my($x, $y, $z) = @_;

    my $val = sqrt(abs($x + $y*$y + $z*$z*$z));
    $val = $val-int($val);
    #print "x=$x, y=$y, z=$z: val=$val\n";
    return $val < 0.3;
}

