/************************************
 ** File: proj2.c
 ** Author: D. Frey
 ** Date: 3/5/00
 **
 ** Description
 **    This program simulates playing the child's
 ** game of Rock, Paper, Scissors, as described in the
 ** CMSC201 Project 2 specificiation.
 **
 **    This simulation presents the user with a menu
 ** of choices and uses the random number generator to play
 ** against the user.
 **
 ** Notes:
 **   This program does not use the "priming read" technique
 ** Instead, it initializes "playerChoice" to something
 ** artificial (other than "quit") so the while loop will
 ** be enetered
 **   The player enters menu choices as single characters,
 ** which are immediately translated into integers which
 ** seem to be easier to handle
 **********************************************/
#include <stdio.h>


/* player menu choices */
#define PAPER        1        /* P or p */
#define ROCK         2        /* R or r */
#define SCISSORS     3        /* S or s */
#define STATUS       4        /* G or g */
#define HELP         5        /* H or h */
#define QUIT         6        /* Q or q */
#define INVALID    (-1)

/* game comparison results */
#define PLAYER_WINS  1
#define PLAYER_LOSES 2
#define TIE          3

/* function prototypes */
void PrintGreeting ( void );
void GetSeed ( );
void PrintHelp ( void );
int  GetPlayerSelection ( void );
int  GetSystemSelection ( void );
int  CompareChoices ( int playerChoice, int systemChoice );
void ReportOutcome ( int result );
void PrintGameStatus ( int wins, int loses, int ties );
void PrintFinalStatus ( int wins, int loses, int ties );

main  ( )
{
   int wins = 0;
   int losses = 0; 
   int ties = 0;
   int playerChoice = INVALID;  /* not QUIT  */
   int systemChoice;
   int result;

   /* initialize game by printing greeting,
   ** seeding random number generator and
   ** displaying help
   */
   PrintGreeting ( );
   GetSeed ( );
   PrintHelp ( );

   /* process menu choices until the
   ** user enters "quit"
   */
   while (playerChoice != QUIT)
   {
      /* get player's menu choice, then switch
      ** to the code to handle it.
      ** the default case catches all invalid input
      */
      playerChoice = GetPlayerSelection ( );
      switch (playerChoice)
      {
	 case ROCK:
	 case PAPER:
	 case SCISSORS:

	    /* play the game
	    ** choose for system and decide if the
	    ** player wins, loses or ties
	    */
	    systemChoice = GetSystemSelection ( );
	    result = CompareChoices (playerChoice, systemChoice);
	    switch (result)
	    {
	       case PLAYER_LOSES: ++losses; break;
	       case PLAYER_WINS:  ++wins;   break;
	       case TIE:          ++ties;   break;
	    }

	    /* tell the user the result */
	    ReportOutcome (result);
	    break;

	 case HELP:

	    /* print the help menu */
	    PrintHelp ( );
	    break;

	 case STATUS:

	    /* display current number of wins, losses, ties */
	    PrintGameStatus (wins, losses, ties);
	    break;

	 case QUIT:

	    /* display final wins, losses and ties
	    ** while-loop condition will fail, causing
	    ** program to teminate
	    */
	    PrintFinalStatus (wins, losses, ties);
	    break;

	 default:

	    /* handle all invalid input */
	    printf ("Invalid Choice\n");
	    PrintHelp ( );
	    break;
      }
   }
}

/******************************
 ** Function ReportOutcome
 **
 ** Input -- integer result which is
 **  assumed to be one of the #defines
 ** Ouput -- message displayed to user
 **       -- no return value
 ***********************************/
void ReportOutcome (int result)
{
   switch (result)
   {
      case PLAYER_WINS: 
	 printf ("YOU WIN!!\n"); 
	 break;
      case PLAYER_LOSES:
	 printf ("Sorry, you lose\n"); 
	 break;
      case TIE:
	 printf ("It's a Tie\n");
	 break;
      default: /* shouldn't happen */
	 printf ("Invalid result in ReportOutcom\n");
	 exit (1);
   }

}

/***********************************
 ** Function PrintHelp
 **
 ** Inputs - none
 ** Output - help menu displayed on screen
 **          no return value
 ***********************************/

void PrintHelp ( void )
{
   printf ("\n");
   printf ("Rock - Paper - Scissors\n");
   printf ("\tR = Choose Rock\n");
   printf ("\tP = Choose Paper\n");
   printf ("\tS = Choose Scissors\n");
   printf ("\tG = Current Game Status\n");
   printf ("\tH = Display this Help Menu\n");
   printf ("\tQ = Quit\n");
   printf ("\n");
}

/***********************************
 ** Function GetPlayerSelection
 **
 ** Input - none
 ** Output -- returns an int representing
 **   the user's input selection
 **   returns one of the #defines for the
 **   menu options
 **
 **  This function inputs a single character
 ** (throws away the NL) and translates it into
 ** the appropriate #define
 ***********************************/

int  GetPlayerSelection ( void )
{
   int selection;
   char input, newline;

   printf ("Please enter selection: ");
   scanf ("%c", &input); 
   fflush (stdin);
   
   /* translate char input to #define
   ** handle both upper- and lower-case
   */
   switch (input)
   {
      case 'P': case 'p': selection = PAPER;    break;
      case 'R': case 'r': selection = ROCK;     break;
      case 'S': case 's': selection = SCISSORS; break;
      case 'G': case 'g': selection = STATUS;   break;
      case 'H': case 'h': selection = HELP;     break;
      case 'Q': case 'q': selection = QUIT;     break;
      default :	
	 printf ("Invalid choice: %c %d", input, input);
	 selection = INVALID;            
	 break;
   }

   return selection;

}

/***********************************
 ** Function GetSystemSelection
 **
 ** Input - none
 ** Output - a random integer from 1 - 3
 **   representing PAPER, ROCK, SCISSORS, respectvely
 **   prints a message to the user telling what the
 ** system selected
 ***********************************/
int  GetSystemSelection ( void )
{
   int choice;

   /* random int from 1 - 3, inclusive */
   choice = (rand() % 3) + 1;

   printf ("System Chooses ");
   switch (choice)
   {
      case PAPER:    printf ("Paper");    break;
      case ROCK:     printf ("Rock");     break;
      case SCISSORS: printf ("Scissors"); break;
   }
   printf ("\n");

   return choice;
}

/***********************************
 ** Function CompareChoices
 **
 ** Inputs -- the player's choice and the
 **   system's choice as ints represented by the
 **   #defines for ROCK, PAPER & SCISSORS
 ** Output - one of the #defines indicating if the
 **   player won, lost or tied
 ***********************************/
int  CompareChoices ( int playerChoice, int systemChoice )
{
   int result;

   /* if both choose the same, its a tie */
   if ((playerChoice == ROCK     && systemChoice == ROCK)
   ||  (playerChoice == PAPER    && systemChoice == PAPER)
   ||  (playerChoice == SCISSORS && systemChoice == SCISSORS) )
   {
      result = TIE;
   }

   /* check if player wins */
   else if ((playerChoice == ROCK     && systemChoice == SCISSORS)
        ||  (playerChoice == PAPER    && systemChoice == ROCK)
        ||  (playerChoice == SCISSORS && systemChoice == PAPER) )
   {
      result = PLAYER_WINS;
   }
   
   /* must be player loses */
   else 
   {
      result = PLAYER_LOSES;
   }

   /* return result to user */
   return result;
}

/***********************************
 ** Function PrintGameStatus
 **
 ** Inputs -- the number of wins, losses and ties
 **   for the player
 ** Output -- the info is displayed on the screen
 **        -- no return value
 ***********************************/

void PrintGameStatus ( int wins, int losses, int ties )
{
   printf ("Player Wins: %d  Losses: %d  Ties: %d\n",
	   wins, losses, ties);
}

/***********************************
 ** Function PrintFinalStatus
 **
 ** Input -- number of wins, losses and ties
 ** Output - a goodbye message and win/loss/tie info
 **   is displayed on the screen
 **        - no return value
 ***********************************/

void PrintFinalStatus ( int wins, int losses, int ties)
{
   printf ("Thanks for Playing Rock-Paper-Scissors\n");
   printf ("Final Stats:\n");
   PrintGameStatus(wins, losses, ties);
}

/***********************************
 ** Function PrintGreeting
 **
 ** Input - none
 ** Ouput - greeting is displayed on the screen
 **       - no return value
 ***********************************/
void PrintGreeting ( void )
{
   int seed;
   char newline;

   printf ("Welcome to Rock-Paper-Scissors\n");

}

/***********************************
 ** Function GetSeed
 **
 ** Input - none
 ** Ouput - the random number generator is seeded
 **       - no return value
 ***********************************/

void GetSeed ( void )
{
   int seed;
   char newline;

   printf ("Please enter a random number seed: ");
   scanf ("%d%c", &seed, &newline);
   srand( seed);

}

