#!/usr/local/bin/perl
#
# infocom-inv-xlat.perl
#
# Perl script copyright (C) 1996 by James Hulsey.  All Rights Reserved
#
# This script is freeware.
#
# This script converts the invisiclues files found at the int-fiction
# archive site into a format similar to the Scott Adams hints format
# so you can decode answers one at a time instead of reading all the
# hints at one.
#
# To use the script, type (on UNIX)
#
# infocom-inv-xlat.perl <invisiclues file name> > <new file name>
#
# infocom-inv-xlat.perl must have the x bit set and /usr/local/bin/perl
# must exist on your system.
#

@lines = <>;
@savedLines = @lines;

# Pass 1, find the answer words that need to be encoded

$startToc = 0;
$inToc = 0;
$startHier = 0;
$inHier = 0;
$addSpace = 0;
$needSpace = 0;
$numWords = 0;
foreach $_ (@lines) {
 if (/TREASURE             VALUE  WHERE FOUND/) {
   $addSpace = 1; # Add spaces to this line
   $needSpace = 1;
 }
 if (/^For Your Amusement$/) {
   $addSpace = 0;
 }
 if ($addSpace && /^[A-Za-z0-9.]/) {
   s/^/  /;
 }
 if ($needSpace && /Have you tried:/) {
   $addSpace = 1; # Add spaces to next line
   $needSpace = 0;
 }
 if (/^\S/ || /^\s*$/) { # Match non-white space at start of line or
                         # line of all white space
   if (/Table of Contents/ || /TABLE OF CONTENTS/) {
     $startToc = 1;
   }
   elsif ($startToc && /^\s*$/) {
     $startToc = 0;
     $inToc = 1;
   }
   elsif ($inToc && /^\s*$/) {
     $inToc = 0;
   }
   elsif (!$inToc && /Hieroglyphic Dictionary/) {
     $startHier = 1;
   }
   elsif ($startHier && /^\s*$/) {
     $startHier = 0;
     $inHier = 1;
   }
   elsif ($inHier && /How Points Are Scored/) {
     $inHier = 0;
   }
   ; # skip the line
 }
 else {
   if ($inToc) {
     ; # skip the line
   }
   else {
     chop;
     if ($inHier) {
       if (!s/[^a-zA-Z0-9]+(\w)/$1/) { # Try to remove punct chars before
         $_ = ""; # No match, remove the line
       }
     }
     s/^\s+([A-Z0-9]{1,2}\.|-) +//; # Remove new answer character
     @words = split;
     foreach $word (@words) {
       if ($wordList{$word} eq "") {
         $wordList{$word} = ++$numWords;
       }
     }
   }
 }
}

# Create a sorted word list
$wordNum = 0;
foreach $word (sort keys(%wordList)) {
 $wordList{$word} = ++$wordNum;
 $listWords{$wordNum} = $word;
}
$numLen = length(sprintf("%d", $wordNum));

# Pass 2, print the codes
$chgWrap = 0;
$howPts = 0;
$secPsg = 0;
$cubeDet = 0;
$inAnswer = 0;
$addSpace = 0;
$needSpace = 0;
foreach $_ (@savedLines) {
 if (/TREASURE             VALUE  WHERE FOUND/) {
   $addSpace = 1; # Add spaces to this line
   $needSpace = 1;
 }
 if (/^For Your Amusement$/) {
   $addSpace = 0;
 }
 if ($addSpace && /^[A-Za-z0-9.]/) {
   s/^/  /;
 }
 if ($needSpace && /Have you tried:/) {
   $addSpace = 1; # Add spaces to next line
   $needSpace = 0;
 }
 if (/^\S+/ || /^\s*$/) {
   $haveAnsTag = 0;
   if (/Table of Contents/ || /TABLE OF CONTENTS/) {
     $startToc = 1;
   }
   elsif ($startToc && /^\s*$/) {
     $startToc = 0;
     $inToc = 1;
   }
   elsif ($inToc && /^\s*$/) {
     $inToc = 0;
   }
   elsif (/last resort/ || /That Which Can be Named/ || /seen everything/ ||
          /Things You Can Ask .../ ||
          /What things can I ask Belboz about?/ || /THE EVIDENCE: Part I/ ||
          /FOR YOUR AMUSEMENT/ || /^\(after you've finished the game\)$/ ||
          !$inToc && /How Points Are Scored/) {
     $chgWrap = 1;
   }
   elsif (/Magic Details/ || /FINAL COPY/) {
     $chgWrap = 0;
   }
   elsif (/How the Points Are Scored/) {
     if ($howPts) {
       $chgWrap = 1;
     }
     else {
       $howPts = 1;
     }
   }
   elsif (/Secret Passage Entrances/) {
     if ($secPsg) {
       $chgWrap = 1;
     }
     else {
       $secPsg = 1;
     }
   }
   elsif (/Details of Cubes' Effects on Spells/) {
     if ($cubeDet) {
       $chgWrap = 1;
     }
     else {
       $cubeDet = 1;
     }
   }
   elsif (!$inToc && /Hieroglyphic Dictionary/) {
     $startHier = 1;
   }
   elsif ($startHier && /^\s*$/) {
     $startHier = 0;
     $inHier = 1;
   }
   elsif ($inHier && /How Points Are Scored/) {
     $inHier = 0;
   }
   if ($inAnswer) { print "\n"; $inAnswer = 0; }
   print; # print the line exactly
 }
 else {
   if ($inToc) {
     print; # print the line exactly
   }
   else {
     chop;
     if ($inHier) {
       if (!/([^a-zA-Z0-9]+)(\w.*)/) { # Find lines with alphanum in them
         print $_; # No match, print the line
         @words = (); # empty array
       }
       else {
         print $1; # Print the punctuation exactly
         @words = split(/[ \t\n]+/, $2);
         $orgIndLen = length($1);
         $lnPos = $orgIndLen + 1;
       }
     }
     else {
       if (s/^(\s+)([A-Z0-9]{1,2}\. |- )( *)//) { # Remove & save new ans char
         print "\n";
         print $1, $2; # Print answer chars
         $orgIndLen = length($1) + length($2);
         $lnPos = $orgIndLen + 1;
         $haveAnsTag = 1;
       }
       else {
         s/^(\s+)//;
         if (!$inAnswer) {
           $orgIndLen = length($1);
           $curIndLen = $orgIndLen;
           $lnPos = 81;
           $haveAnsTag = 0;
         }
         else {
           $curIndLen = length($1);
           if (/[0-9]{1,2} /) {
             $curIndLen = $orgIndLen;
           }
           if ($chgWrap && !$haveAnsTag && $curIndLen == $orgIndLen) {
             printf("\n%${orgIndLen}.${orgIndLen}s", "");
             $lnPos = $orgIndLen + 1;
           }
         }
       }
       $inAnswer = 1;
       @words = split;
     }
     foreach $word (@words) {
       $codeLen = length($wordList{$word}) + 1;
       $lnPos += $codeLen;
       if ($lnPos > 80) {
         printf("\n%${orgIndLen}.${orgIndLen}s", "");
         $lnPos = $orgIndLen + $codeLen + 1;
       }
       print "$wordList{$word} ";
     }
     if ($inHier) { print "\n"; }
   }
 }
}

# Print list of numbers to decode words

print "\n\n\nWORD LIST\n\n";
print "Replace numeric code with the following text.\n";
print "Note that the punctuation is included.\n";
$lnPos = 81;
$fieldWidth = 16;
sub numerically { $a <=> $b; }
foreach $wordNum (sort numerically keys(%listWords)) {
 $wordOut = sprintf("%${numLen}d %s", $wordNum, $listWords{$wordNum});
 if ($lnPos + length($wordOut) > 80) { print "\n"; $lnPos = 1; }
 $width = (int(length($wordOut) / $fieldWidth) * $fieldWidth) + $fieldWidth;
 printf ("%-${width}.${width}s", $wordOut);
 $lnPos += $width;
}
print "\n\n[Invisiclues translated to codes by Perl script written by James Hulsey]\n";