#!/usr/bin/perl -w

use strict;
no warnings 'recursion';
use Time::HiRes qw(usleep);
use Getopt::Std;

my (%opts, $maze, $n, $i, $j, $M, $C);

%opts = (
    d => 50,			# delay
);

getopts('d:', \%opts);
open F, $ARGV[0] or die;
$i = $maze->{width} = 0;
while (<F>) {
    chomp;
    $n = length;
    $maze->{b}[$i] = [ split // ];
    $maze->{width} = $n if $n > $maze->{width};
    $n = index($_,'@');
    if ($n >= 0) {	# mouse
	$M->{r} = $i;
	$M->{c} = $n;
    }
    $n = index($_,'C');
    if ($n >= 0) {	# cheese
	$C->{r} = $i;
	$C->{c} = $n;
    }
    ++$i;
}
$maze->{height} = $i;

$| = 1;
clearscr();
for ($i=0; $i<$maze->{height}; ++$i) {
    gotorc(maze2scr($i,0));
    print join "", @{ $maze->{b}[$i] };
}

my ($delta);
$delta = [ [1,0], [0,1], [-1,0], [0,-1] ];

for ($i=0; $i<4; ++$i) {
    try_dir($i);
}

gotorc(24,1);
print "找不到起司!\n";

sub try_dir {
    my ($dir) = @_;
    my ($i, $next, $prev);
    %$next = %$M;
    $next->{r} += $delta->[$dir][0];
    $next->{c} += $delta->[$dir][1];
    return if ( $next->{r} < 0 || $next->{r} >= $maze->{height}
	     || $next->{c} < 0 || $next->{c} >= $maze->{width} );
    if ($maze->{b}[$next->{r}][$next->{c}] eq 'C') {
	gotorc(24,1);
	print "好吃好吃!\n";
	exit 0;
    } elsif ($maze->{b}[$next->{r}][$next->{c}] ne ' ') {
	return;
    }
    usleep($opts{d}*1000);
    setrc($M->{r}, $M->{c}, '.');
    %$prev = %$M;
    %$M = %$next;
    setrc($M->{r}, $M->{c}, '@');
    for ($i=0; $i<4; ++$i) {
	try_dir($i);
    }
    usleep($opts{d}*1000);
    setrc($M->{r}, $M->{c}, ' ', 1);
    %$M = %$prev;
    setrc($M->{r}, $M->{c}, '@');
}

sub gotorc {
    my ($row, $col) = @_;

    print "\x1b[${row};${col}H";
}

sub maze2scr {
    my ($r, $c) = @_;
    return( $r+int((24-$maze->{height})/2), $c+int((76-$maze->{width})/2) );
}

sub clearscr {
    print "\x1b[2J";
}

sub setrc {
    my ($r, $c, $v, $do_not_set_maze) = @_;
    gotorc(maze2scr($r, $c));
    print $v;
    $maze->{b}[$r][$c] = $v unless defined $do_not_set_maze;
}

