#!/usr/athena/bin/perl
#
#  This is an Augustus cipher decoder for the 1996 IAP Mystery Hunt 
#  puzzle 13a

use Getopt::Std; &getopt('kKtT');

if( $opt_h ) {
    print "Usage: augustus [-x] [ -k <key> | -K <keyfile> "
	. "| -t <keysrc> -T <keysrcfile> ] [crypt text file]\n";
    exit( 0 );
}

%value 
    = (
       0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
       'a', 10, 'b', 11, 'c', 12, 'd', 13, 'e', 14, 'f', 15, 'g', 16,
       'h', 17, 'i', 18, 'j', 19, 'k', 20, 'l', 21, 'm', 22, 'n', 23,
       'o', 24, 'p', 25, 'q', 26, 'r', 27, 's', 28, 't', 29, 'u', 30,
       'v', 31, 'w', 32, 'x', 33, 'y', 34, 'z', 35 );

%devalue
    = (
       0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
       10, 'a', 11, 'b', 12, 'c', 13, 'd', 14, 'e', 15, 'f', 16, 'g',
       17, 'h', 18, 'i', 19, 'j', 20, 'k', 21, 'l', 22, 'm', 23, 'n',
       24, 'o', 25, 'p', 26, 'q', 27, 'r', 28, 's', 29, 't', 30, 'u',
       31, 'v', 32, 'w', 33, 'x', 34, 'y', 35, 'z' );

if( $opt_K ) {
    open( KEY, "<$opt_k" );
    @lines = <KEY>;
    $key_text = join( '', @lines );
    $key_text =~ s/\s*//g;
    $key_text =~ tr/A-Z/a-z/;	# downcase
    @key = split( //, $key_text );
} elsif( $opt_k ) {
    $opt_k =~ tr/A-Z/a-z/;	# downcase
    @key = split( //, $opt_k );
} elsif ( $opt_T ) {
    open( KEY, "<$opt_k" );
    @lines = <KEY>;
    $key_text = join( '', @lines );
    $key_text =~ tr/A-Z/a-z/;	# downcase
    $key_text =~ s/\s*//g;
    @notkey = split( //, $key_text );
    for( $i=0; $i<=$#notkey; $i+=3 ) {
	push( @key, $notkey[$i] );
    }
} elsif ( $opt_t ) {
    $opt_t =~ tr/A-Z/a-z/;	# downcase
    @notkey = split( //, $opt_t );
    for( $i=0; $i<=$#notkey; $i+=3 ) {
	push( @key, $notkey[$i] );
    }
}

$/ = "\n\n";
@inputs = <>;		# stdin or filename on command line
$/ = "\n";
for( @inputs ) { 
    s/^[\s\-]*//;
    s/[\s\-]*$//;
    next if length( $_ ) < 2;
    @crypt_text = split( //, $_ );
    @clear_text = ();
    for( $i=0, $j=0; $i<=$#crypt_text && $j<=$#key; $i++, $j++ ) {
	$space = '';
	while( $crypt_text[$i]=~/\s/ && $i<=$#crypt_text ) {
	    $space .= $crypt_text[$i];
	    $i++;
	}
	while( $key[$j]=~/\s/  && $j<=$#key ) { $j++; }
	$base = $value{ $crypt_text[$i] };
	$offset = $value{ $key[$j] };
	# either a one or an el
	if( $base == 1 || $base == 21 && ! $opt_x ) {
	    $base == 1;
	    $new = $space . '('
		. $devalue{ &wrap(1-$offset) }
		. $devalue{ &wrap(21-$offset) }
	    . ')';
	} else {
	    $new = $space
		. $devalue{ &wrap($base-$offset) };
	}
	push( @clear_text, $new );
    }
    print @clear_text, "\n";
    print "\n" if $#key > 78;
}

sub wrap {
    my( $num ) = @_;
    $num = $num - 36 if $num > 35;
    $num = $num + 36 if $num < 0;
    return( $num );
}
