#!/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";
