#include <stdio.h>
#include "genlib.h"


#define MAX_OBJS 100
#define CRAB_RAGE_THRESHOLD 3


/*   Enumeration to keep track of the locations.   */
typedef enum {
   OCTOPUS_LAND,
   OCTOPUS_LAND_SMASHED,
   EEL_LAND,
   CRAB_LAND,
   SUBMARINE,
   RINGO_HAND,
} Location;

/*   Enumeration for game objects.   */
typedef enum {
   OBJ_RINGO,
   OBJ_OCTOPUS,
   OBJ_EEL,
   OBJ_CRAB,
   OBJ_DRUM_START,
} GameObj;
   


string DirectionStr(char act)
{
   string dirstr = "";

   /*   Find out the string corresponding to the direction.   */
   switch(act)
   {
   case 'n': dirstr = "north"; break;
   case 's': dirstr = "south"; break;
   case 'e': dirstr = "east"; break;
   case 'w': dirstr = "west"; break;
   }
   return dirstr;
}


Location Move(Location current, char act)
{
   Location next = OCTOPUS_LAND;

   /*   Branch out for the location.   */
   switch(current)
   {
   case OCTOPUS_LAND:
      if(act != 'e')
      {
         printf("Nothing interesting in this direction.\n");
         printf("Let's go to the east.\n");
      }
      next = EEL_LAND;
      break;

   case EEL_LAND:
      if(act == 'w')
      {
         printf("You don't want to go back to the octopus' garden...\n");
         printf("Let's go to the north.\n");
      }
      else if(act == 'e')
      {
         printf("Nothing interesting in this drection.\n");
         printf("Let's go to the north.\n");
      }
      if(act == 's')
      {
         next = SUBMARINE;
         printf("You swim south, away from the electric eels.\n");
      }
      else
      {
         next = CRAB_LAND;
         printf("You swim north, away from the electric eels.\n");
      }
      break;

   case CRAB_LAND:
      if(act != 's')
      {
         printf("Nothing interesting in this drection.\n");
         printf("Let's go to the south.\n");
      }
      printf("You swim south.\n");
      next = EEL_LAND;
      break;

   case SUBMARINE:
      if(act != 'n')
      {
         printf("Nothing interesting in this drection.\n");
         printf("Let's go to the north.\n");
      }
      printf("You swim north.\n");
      next = EEL_LAND;
      break;
         
   default:
      /*   Shouldn't happen.   */
      printf("Unknown situation: %d\n", current);
      exit(1);
      break;
   }

   switch(next)
   {
   case EEL_LAND:
      printf("This area is packed full of electric eels.\n");
      break;

   case CRAB_LAND:
      printf("There is a crab here.\n");
      break;

   case SUBMARINE:
      printf("There is a submarine refinery here, with ");
      printf("plenty of liquid waste.\n");
      break;

   default:
      /*   Shouldn't happen.   */
      printf("Unknown next situation: %d\n", next);
      exit(1);
      break;
   }

   return next;
}


void Grab(Location locations[MAX_OBJS])
{
   int i;

   /*   Check if ringo has anything.   */
   for(i = 0; i < MAX_OBJS; i++)
   {
      if(locations[i] == RINGO_HAND)
      {
         printf("You alraedy have something in your hand.\n");
         return;
      }
   }

   /*  Find an object where ringo is.   */
   for(i = 0; i < MAX_OBJS; i++)
   {
      if(locations[i] == locations[OBJ_RINGO] && i != OBJ_RINGO)
      {
         switch(i)
         {
         case OBJ_RINGO:
            /*   just skip.   */
            break;

         case OBJ_OCTOPUS:
            printf("You grab an octopus.\n");
            break;

         case OBJ_EEL:
            printf("You grab an eel.\n");
            break;

         case OBJ_CRAB:
            printf("You grab a crab.\n");
            break;

         default:
            /*   should be a drum.   */
            printf("You grab a drum of liquid waste.\n");
            break;
         }
         locations[i] = RINGO_HAND;
         return;
      }
   }

   printf("Nothing here.\n");
}


void Throw(Location locations[MAX_OBJS])
{
   int i, crab_drum;
   bool found;

   /*   Find the one in ringo's hand.   */
   found = FALSE;
   for(i = 0; i < MAX_OBJS; i++)
   {
      if(locations[i] == RINGO_HAND)
      {
         switch(i)
         {
         case OBJ_RINGO:
            /*   shouldn't happen.   */
            printf("Ringo holding Ringo???\n");
            exit(1);
            break;

         case OBJ_OCTOPUS:
            printf("You throw an octopus onto the ground.\n");
            break;

         case OBJ_CRAB:
            printf("You throw a crab onto the ground.\n");
            break;

         case OBJ_EEL:
            printf("You throw an eel onto the ground.\n");
            break;

         default:
            /*   should be one of the drums.   */
            printf("You throw a drum of liquid waste onto the ground.\n");
            break;
         }
         locations[i] = locations[OBJ_RINGO];
         found = TRUE;
         break;
      }
   }
   if(!found)
   {
      printf("You try to throw something, but you have nothing ");
      printf("in your hands.\n");
   }
   else if(locations[OBJ_RINGO] == CRAB_LAND)
   {
      /*   Check if we have three drums in crab land.   */
      for(i = OBJ_DRUM_START, crab_drum = 0; i < MAX_OBJS; i++)
      {
         if(locations[i] == CRAB_LAND)
         {
            crab_drum++;
         }
      }
      if(crab_drum >= CRAB_RAGE_THRESHOLD)
      {
         printf("Three drums of liquid waste -- the crab becomes \n");
         printf("furious and OPEC pulls you out.  Well done.\n");
         exit(0);
      }
   }
}


void main()
{
   char act;
   int i;
   Location lastOctopusLoc;

   /*   These keep track of locations of oil waste drums.   */
   Location objs[MAX_OBJS];

   /*   Initialize the location of game objects.   */
   objs[OBJ_RINGO] = OCTOPUS_LAND;
   objs[OBJ_OCTOPUS] = OCTOPUS_LAND;
   objs[OBJ_EEL] = EEL_LAND;
   objs[OBJ_CRAB] = CRAB_LAND;
   for(i = OBJ_DRUM_START; i < MAX_OBJS; i++)
   {
      objs[i] = SUBMARINE;
   }

   /*   Introductory text.   */
   printf("You're in an octopus' garden, just like in your ");
   printf("song, except the octopus is\nthrowing things at ");
   printf("you and frightening you.\n");

   while(1)
   {
      /*   Receive input from the user.   */
      printf("Your action: ");
      act = getchar();
      getchar();

      /*   Check for the quit command as a special case.   */
      if(act == 'q')
      {
         printf("You quit, weary of undersea life already.\n");
         break;
      }

      /*   Branch out depending on the user's input.   */
      lastOctopusLoc = objs[OBJ_OCTOPUS];
      switch(act)
      {
      case 'n':
      case 's':
      case 'e':
      case 'w':
         /*   Let's take care of all the cases for swiming in one shot.   */
         if(objs[OBJ_RINGO] == OCTOPUS_LAND && 
            objs[OBJ_OCTOPUS] != OCTOPUS_LAND_SMASHED)
         {
           printf("You try to swim %s, ", DirectionStr(act));
           printf("but the octopus gets in your way.\n");
         }
         else
         {
            if(objs[OBJ_RINGO] == OCTOPUS_LAND)
            {
               printf("You swim %s, ", DirectionStr(act));
               printf("finally free of the octopus' garden.\n");
            }
            objs[OBJ_RINGO] = Move(objs[OBJ_RINGO], act);
         }
         break;

      case 't':
         /*   Throw.   */
         if(objs[OBJ_RINGO] == OCTOPUS_LAND &&
            objs[OBJ_OCTOPUS] == RINGO_HAND)
         {
            printf("You throw the octopus onto the ground.  It is ");
            printf("momentarily dazed.\n");
            objs[OBJ_OCTOPUS] = OCTOPUS_LAND_SMASHED;
         }
         else
         {
            Throw(objs);
         }
         break;

      case 'g':
         /*   Grab.   */
         if(objs[OBJ_RINGO] == OCTOPUS_LAND &&
            objs[OBJ_OCTOPUS] == OCTOPUS_LAND)
         {
            printf("You grab the octopus with your mighty European ");
            printf("arms.\n");
            objs[OBJ_OCTOPUS] = RINGO_HAND;
         }
         else
         {
            Grab(objs);
         }
         break;

      case 'y':
         /*   Yell.   */
         if(objs[OBJ_RINGO] == OCTOPUS_LAND)
         {
             printf("You yell at the octopus, \"go watch TV!\"\n");
         }
         else
         {
             printf("You yell, \"I hate the ocean!\"\n");
             printf("Nothing happens.\n");
         }
         break;

      case 'h':
         /*   Hide.   */
         printf("You try to hide, but there is nothing to hide ");
         printf("behind.\n");
         break;

      default:
         /*   Error case.  Just let the user know.   */
         printf("Unknown action, type n, s, e, w, y, h, g, t, or q.\n");
         break;
         }


      /*   Set the situation variables to new values.   */
      if(lastOctopusLoc == RINGO_HAND &&
         objs[OBJ_OCTOPUS] != OCTOPUS_LAND_SMASHED)
      {
         printf("The octopus wriggles free of your grasp.\n");
         objs[OBJ_OCTOPUS] = objs[OBJ_RINGO];
      }
      if(lastOctopusLoc == OCTOPUS_LAND_SMASHED &&
         objs[OBJ_RINGO] == OCTOPUS_LAND)
      {
         printf("The octopus recovers from its fall.\n");
         objs[OBJ_OCTOPUS] = objs[OBJ_RINGO];
      }

      /*   Check if Ringo is still being harrased.   */
      if(objs[OBJ_RINGO] == OCTOPUS_LAND &&
         objs[OBJ_OCTOPUS] == OCTOPUS_LAND)
      {
         printf("The octopus keeps harassing you.\n");
      }
   }
}


