#!/usr/bin/perl -w

# Warren's Wood - A mini text adventure game.
# (c) 2003 CyrekSoft - Coder: Carl R. White

# Reading this source will spoil the game! Read at your own risk!

@map = ( 
  "-  | ", "--   ", "- B x", "- BB ", "- |B ", "-  |x", "--| 8",
  "  ||Q", "-  |x", " -| 8", "  ||+", "  || ", "  || ", "- ||+",
  "  || ", " - | ", "--| B", "  || ", " - | ", " -  Q", "  |  ",
  "  ||+", "-- |!", "--   ", "    #", "--   ", "--| +", "  ||Q",
  "   | ", "--   ", "- | x", "  || ", "-- | ", "--  +", "  | x",
  "  ||x", "-  |x", " -| 8", "  ||+", "-  |x", "--| S", "  ||8",
  " -||8", " - | ", "--  Q", " -|  ", " - |8", "--  x", " -| x",
);

@visited = split('',"1"x50);

$px = 3; $py = 3;
$inventory = "";
$score = 0;
$health = 5;
$turns = 0;
$move = -1;

$separator = "---------- --- - -- -- - - -  -    -      -\n";

sub get_input { my($prompt) = @_;
  my $input = "";
  until($input) {
    #print "\nWhat now?> ";
    print $prompt;
    $input = <>;
    chomp $input;
  }
  return($input);  
}

sub wait_for_user {
  print "\nPress Enter to return to prompt...";
  my $input = <>;
  print "\n";
}

sub save {
  my($name) = lc(get_input(
    "\n  The bard asks thee thy name that he may record thy tale in lore.".
    "\n  > "
  ));
  print "\n".$separator;

  open SAVE, ">$ENV{HOME}/.warrenswood.$name.sav" or return 0;
  print SAVE
   "$inventory/$px/$py/$score/$health/$turns/".
   join('/',@map).
   "\n";
  close SAVE;
  return 1;
}

sub load {
  my($name) = lc(get_input(
    "\n  The bard asks thee thy name that he may find thy tale among his scrolls.".
    "\n  > "
  ));
  print "\n".$separator;

  open LOAD, "<$ENV{HOME}/.warrenswood.$name.sav" or return 0;
  my @all = split('/',<LOAD>);
  close LOAD;
  return 0 if (@all < 6);
  ($inventory,$px,$py,$score,$health,$turns,@map) = @all;
  return 1;
}

sub vocab { print<<EOV ;
Vocabulary:
  N[orth]    F[ight]      H[ealth]
  S[outh]    T[ake]       Z( Score)    <( Load)
  E[ast]     I[nventory]  U( Wait)     >( Save)
  W[est]     V[ocab]      Q[uit]
EOV
}

sub haveBluekey   { return $inventory =~ /B/ ? 1 : 0 ; }
sub haveSilverkey { return $inventory =~ /S/ ? 1 : 0 ; }
sub haveSword     { return $inventory =~ /!/ ? 1 : 0 ; }

sub inventory {
  print "You are carrying";
  if ($inventory) {
    print ":\n";
    print "  the Blue key\n"              if haveBluekey();
    print "  the Silver key\n"            if haveSilverkey();
    print "  the Sword of Hassenfeffer\n" if haveSword();
  } else {
    print " nothing.\n";
  }
}

sub exits { my($x)= @_;
    my(@x) = ();
    push @x, "North" if $x !~ /^\-/;
    push @x, "South" if $x !~ /^.\-/;
    push @x, "East"  if $x !~ /^..\|/;
    push @x, "West"  if $x !~ /^...\|/;

    #print "Boxed in? This can't be good." if (@x == 0);

    print "There is an exit to the $x[0].\n"                 if (@x == 1);
    print "There are exits to the $x[0] and $x[1].\n"        if (@x == 2);
    print "There are exits to the $x[0], $x[1] and $x[2].\n" if (@x == 3);
    print "You are in a clearing with exits all around.\n"   if (@x == 4);
}      

sub count_evil {
  my $j = 0;
  $j += (/8$/)?1:0 foreach (@map);
  return $j;
}

sub health { print "Health: ", 20 * $health, "%\n"; }

sub score { print "Your score: $score points in $turns turns.\n"; }

sub amIDead { unless ($health) {
    print "You have died!\n";
    score();
    wait_for_user();
    exit(0);
}}



until ( $px == 3 && $py == 3 && haveSilverkey() ) {
    $index = $py * 7 + $px;

    $_ = substr $map[$index], -1, 1;
    $score += $visited[$index];
    $visited[$index] = 0;

    $turns++;
    print $separator if ($move == -1);

    if (/#/ && ! haveSilverkey() ) { print<<SPIEL;
You are in Warren's Wood - Home to the Good Rabbits of Eternity
Your mission is to find the Silver key and return here to escape.
Along the way, you may choose to slay all Evils that cross you,
for they have driven Warren and the Good Rabbits away.

Type 'v' for a list of commands.

SPIEL
    }
    if (/ /) {
      print( (
        "Trees and more trees.\n",
        "The birds sing as the sun shines.\n",
        "You feel cheerful as the world smiles on you.\n",
        "A strange smell, a flicker in the shadows.\n",
        "Deja vu sweeps over you. This is all seems very familiar.\n",
        "You see two long ears. Upon closer inspection they are blades of grass.\n",
        "Midges dance in a shaft of sunlight.\n",
        "Carved in the bark of a tree: CTL4TTW\n",
        "A muffled thud startles you.\n"
      )[$index%9] );
    }
    if (/\+/) {
      print "There is a magic potion here\n";
    }
    if (/!/) {
      print "Glowing; Singing; Angelic Voices!\n";
      print "Behold The Sword of Hassenfeffer!\n";
    }
    if (/B/) {
      print "A key - at last! But it is Blue and so now are you.\n";
    }
    if (/S/) {
      print "Can it be? The Silver key? It is! It is! Joy is me!\n";
    }
    if (/x/) {
      print "A hole in the ground! There be rabbits here!\n";
    }
    if (/Q/) {
      print "The sun hides in clouds,\n";
      print "The wind whispers through the trees,\n";
      print "It is too quiet.\n";
    }
    if (/o/) {
      print "There is a dead rabbit here.\n"
    }
    if (/8/) {
      print "An Evil Rabbit of Eternity attacks you!\n";
      print "Fight or you will surely die!\n";
      $health--;
      health();
      amIDead();
    }

    exits($map[$index]);

    $canTake = $_;
    $_ = get_input("\nWhat now?> ");

    #print "DEBUG: got \"$_\" as input\n";

    print $separator;

    if (/help/||/\?/) {
       print "You need no help, rugged adventurer.\n";
       print "[Try typing 'v' for a list of keys.]\n";
       $_ = '?';
    }

    if (/MAP/) {
       print "Mungo draw map now.\n";
       for($y=0;$y<7;$y++) {
         for($i=0;$i<3;$i++) {
           for($x=0;$x<7;$x++) {
             $index = $y * 7 + $x;
             if ($i == 0) {
               print "+".substr($map[$index],0,1)."+";
             }
             if ($i == 1) {
               print substr($map[$index],3,1).
                     substr($map[$index],-1,1).
                     substr($map[$index],2,1);
             }
             if ($i == 2) {
               print "+".substr($map[$index],1,1)."+";
             } # x
           } # i
           print "\n";
         } # y
       }
       $score = int($score/2);
       $_ = 'z';
    }

    $_ = lc(substr $_, 0, 1);
    unless ( index("newsquiz\?\<fvth\>", $_)+1 ) {
        print "Your strange incantation causes nothing to happen.\n";
        next;
    }

    if (/q/) { $health = 0; amIDead(); }

    if (/v/) { vocab(); }
    if (/i/) { inventory(); }
    if (/h/) { health(); }
    if (/z/) { score(); }

    if (/u/) { print "You wait, but you know not for what.\n"; }

    if (/\>/) { 
      if (save()) {
        print "Your adventure to this point is recorded by the bard.\n";
      } else {
        print
          "The bard has no parchment nor ink to record your tale.\n".
          "He utters a strange curse: \"Save Error.\"\n";
      }
    }
    if (/\</) {
      if (load()) {
        print
          "The bard recants your last adventure and as if by magic\n".
          " you find yourself back where the story was wrote.\n";
      } else {
        print
          "The bard knows no tale of your last adventure.\n".
          "He utters a strange curse: \"Load Error.\"\n";
      }
    }

    $move = index "nsew", $_;
    #print "DEBUG: \$move is $move\n";
    if ($move >= 0) {
       $block = substr $map[$index], $move, 1;
       #print "DEBUG: \$block is $block\n";

       if ($block =~ /[\|\-]/) {
         print "You can't go that way.\n";
         $move=-1;
       }
       if ($block =~ /B/) {
         if ( haveBluekey() ) {
           print "The Blue key allows you to pass this way.\n";
         } else {
           print "You need the Blue key to go that way.\n";
           $move=-1;
         }
       }
       $py-- if $move == 0;
       $py++ if $move == 1;
       $px++ if $move == 2;
       $px-- if $move == 3;
    }

    if (/f/) {
       if ($canTake =~ /8/) {
          if (haveSword()) {
             print "You slay an Evil Rabbit of Eternity with the Sword of Hassenfeffer!\n";
             $score += 5;
             substr($map[$index], -1, 1) = "o";
          } else {
             print "You have no weapon with which to fight! Run!!!\n";
          }
       } else {
          if (haveSword()) {
             print "You swish your sword but no there are no invisible foes in this wood.\n";
          } else {
             print "There is nothing to fight here.\n";
          }
       }
    } # end 'fight'

    if (/t/) {
       $_ = $canTake;
       if (/#/||/ /||/Q/||/x/) { print "There is nothing to take.\n"; }
       if (/\+/) {
          if ($health < 5) {
             print "You drink the magic potion and feel better.\n";
             $health++;
             substr($map[$index], -1, 1) = " ";
          } else {
             print "You are in perfect health - you do not need the potion.\n";
          }
       }
       if (/8/) {
          print "You pick up the Evil Rabbit.\n";
          print "It bites you by the throat and will not let go.\n";
          print "The life drains from your body.......\n\n";
          $health = 0; amIDead();
       }
       if (/o/) {
          print "You light a fire, cook and eat the rabbit corpse.\n";
          if (int(rand(2))) {
             print "The meat is bad and you feel ill.\n";
             $health--;
             amIDead();
          } else {
             print "The meat is tasty and you feel refreshed.\n";
             $health++ if ($health < 5);
          }
          substr($map[$index], -1, 1) = " ";
       }
       if (/!/) {
          print "You have picked up the Sword of Hassenfeffer!\n";
          substr($map[$index], -1, 1) = " ";
          $inventory .= $_;
       }
       if (/B/) {
          print "You have picked up the Blue key.\n";
          $score += 3;
          substr($map[$index], -1, 1) = " ";
          $inventory .= $_;
       }
       if (/S/) {
          print "You have picked up the Silver key!\n";
          print "Now you must find your way out of the wood.\n";
          $score += 7;
          substr($map[$index], -1, 1) = " ";
          $inventory .= $_;
       }
    } # end 'take'

} # end main loop

$score++;
print "Congratulations! You have made it out of Warren's Wood!\n\n";
if (count_evil() == 0) {
  print "You also killed all of the Evil Rabbits of Eternity,\n";
  print "  freeing the wood from the grip of Evil!\n";
  print "Warren thanks you, weary traveller, and wishes you well in future!\n";
} else {
  print "Evil is still abound in the wood, but you made it out alive!\n";
  print "It may be many years before Warren and the Good Rabbits of Eternity\n";
  print "  restore the balance of power in Warren's Wood.\n";
}
score();
wait_for_user();
