// Purpose.  Memento design pattern lab
//
// Problem.  The GuessGame class expects multiple "clients" to "connect" to it
// with a call to join().  Each client has a different random number chosen
// for it by GuessGame.  In order to uniquely identify itself to the GuessGame
// server, each client passes a string identifier when it calls join() and
// when it calls evaluateGuess().  GuessGame remembers each string identifier
// in an internal table in the join() method, and then searches that table in
// the evaluateGuess() method.  If we put the information that is peculiar to
// each client into a "black box" object (a Memento), and make the client the
// "caretaker" of that object; then the implementation of the server (Guess-
// Game) is greatly simplified.
//
// Assignment.
// o Declare a class Memento
// o Make class GuessGame a "friend" of class Memento
// o Class Memento will have a single private int data member and a private
//   constructor that accepts an int and initializes the data member
// o GuessGame::join() doesn't need to accept a string identifier.  But, it
//   does need to: select a random number, "wrap" that number in a Memento
//   object, and return a pointer to that object.
// o GuessGame::evaluateGuess() will now accept a Memento object instead of
//   a string identifier.  It doesn't need to search its table of string
//   identifiers, and then access its table of random numbers.  Instead, it
//   simply references the Memento's private int data member.
// o All the private data members of class GuessGame can now be retired.
// o Add a Memento* member to struct Game
// o The call to guessServer.join() no longer requires a string argument,
//   and, the Memento* returned from join() needs to be remembered.
// o The call to guessServer.evaluateGuess() now requires a Memento* argument
//   instead of a string argument.
// o Be sure to clean-up the Memento* pointers when you are done

#include <iostream.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

class GuessGame {
private:
   int  numbers[10];
   char names[10][20];
   int  total;
public:
   GuessGame() {
      time_t  t;
      srand((unsigned) time(&t));
      total = 0;
   }
   void join( char* name ) {
      strcpy( names[total], name );
      numbers[total++] = rand() % 30 + 1;
   }
   int evaluateGuess( char* name, int guess ) {
      int i;
      for (i=0; i < total; i++)
         if ( ! strcmp( names[i], name )) break;
      if (guess == numbers[i]) return 0;
      return ((guess > numbers[i]) ? 1 : -1);
   }
};

struct Game {
   char name[20];
   int  min, max, done;
   Game() { min = 1;  max = 30;  done = 0; }
};

void main( void ) {
   GuessGame  guessServer;
   const int  MAX = 3;
   Game       games[MAX];
   int        gamesComplete = 0;
   int        guess, ret;

   for (int i=0; i < MAX; i++) {
      cout << "Enter name: " ;
      cin >> games[i].name;
      guessServer.join( games[i].name );
   }
   while (gamesComplete != MAX) {
      for (int j=0; j < MAX; j++) {
         if (games[j].done) continue;
         cout << games[j].name <<" ("<<games[j].min <<'-'<<games[j].max <<"): ";
         cin >> guess;
         ret = guessServer.evaluateGuess( games[j].name, guess );
         if (ret == 0) {
            cout << "   lights!!  sirens!!  balloons!!" << endl;
            games[j].done = 1;
            gamesComplete++;
         }
         else if (ret < 0) {
            cout << "   too low" << endl;
            games[j].min = guess;
         }
         else {
            cout << "   too high" << endl;
            games[j].max = guess;
}  }  }  }

// Enter name: Tom
// Enter name: Dick
// Enter name: Harry
// Tom (1-30): 10
//    too low
// Dick (1-30): 15
//    too high
// Harry (1-30): 20
//    too high
// Tom (10-30): 22
//    too high
// Dick (1-15): 8
//    lights!!  sirens!!  balloons!!
// Harry (1-20): 10
//    too low
// Tom (10-22): 16
//    too high
// Harry (10-20): 15
//    too low
// Tom (10-16): 13
//    too high
// Harry (15-20): 17
//    too low
// Tom (10-13): 11
//    lights!!  sirens!!  balloons!!
// Harry (17-20): 18
//    lights!!  sirens!!  balloons!!