#!/usr/bin/perl -w
use strict;
use POSIX 'floor';
use constant { TRUE => 1, FALSE => 0 };
# set stdout to autoflush
select((select(STDOUT), $| = 1)[0]);
# give the $f value real meaning
my @direction = ("north", "east", "south", "west");
# read the maze data
my ($width, $height) = map { chomp; $_ } split / /, <>;
my @maze = <>;
# clear the screen
print "\e[2J\e[H";
print @maze;
sub exit_handler {
# turn the cursor back on and restore cursor position
print "\e[?25h\e[u";
exit;
}
use sigtrap 'handler', \&exit_handler, 'normal-signals';
# turn off the cursor and save cursor position for later
print "\e[?25l\e[s";
# clean up the maze data
@maze = split //, join '', map { chomp; $_ } @maze;
# find the maze entrance
sub find_entrance {
for (0 .. $height * $width) {
return ($_ % $width, floor($_ / $width)) if 'S' eq $maze[$_];
}
die "failed to find entrance\n";
}
my ($x, $y) = find_entrance;
sub print_at { print "\e[".($_[0]+1).";".($_[1]+1)."H".$_[2]; }
print_at $y, $x, '@';
# define the automaton
my $f = 0;
sub turn_left { $f = ($f + 3) % 4; }
sub turn_right { $f = ($f + 1) % 4; }
# fucking perl's modulo is unsigned. piece of shit.
my @modulo = (0, 1, 0, -1);
sub step {
my $next_y = $y + $modulo[($f + 3) % 4];
my $next_x = $x + $modulo[$f];
my $next_square = $maze[$next_y * $width + $next_x];
return FALSE if ($next_x < 0 or $next_x >= $width);
return FALSE if ($next_y < 0 or $next_y >= $height);
return FALSE if 'X' eq $maze[$next_y * $width + $next_x];
# select '', '', '', .1;
print_at $y, $x, 'o';
$y = $next_y;
$x = $next_x;
print_at $y, $x, '@';
# print "went $direction[$f], now at $x, $y\n";
return TRUE;
}
sub solved { return 'E' eq $maze[$y * $width + $x]; }
# solve the maze
until (solved) {
turn_right;
until (step) { turn_left }
}
exit_handler