// File: game.cxx

#include <cassert>    // Provides assert
#include <climits>    // Provides INT_MAX and INT_MIN
#include <iostream>   // Provides cin, cout
#include <queue>      // Provides queue<string>
#include <string>     // Provides string
#include "game.h"     // Provides definition of game class
using namespace std;

namespace main_savitch_14
{
const int game::SEARCH_LEVELS;
//i have only the functions i needed for the first assignment
//i'll put the rest in when i need them
game::who game::play( )
{
   restart( );

   while (!is_game_over( ))
   {
      display_status( );
      if (last_mover( ) == COMPUTER)
         make_human_move( );
      else
         make_computer_move( );
   }
   display_status( );
   return last_mover();
}

void game::display_message(const string& message) const
{
   cout << message;
}

string game::get_user_move( ) const
{
   string answer;
	
   display_message("Your move, please: ");
   getline(cin, answer);
   return answer;
}

game::who game::winning( ) const
{
   int value = evaluate( ); // Evaluate based on move that was just made.

   if (value > 0)
      return last_mover( );
   else if (value < 0)
      return next_mover( );
   else
      return NEUTRAL;
}

int game::eval_with_lookahead(int look_ahead, int beat_this)
{
   queue<string> moves;   // All possible opponent moves
   int value;             // Value of a board position after opponent moves
   int best_value;        // Evaluation of best opponent move
   game* future;          // Pointer to a future version of this game

   if (look_ahead == 0 || is_game_over( ))
   {
      if (last_mover( ) == COMPUTER)
         return evaluate( );
      else
         return -evaluate( );
   }
   compute_moves(moves);
   best_value = INT_MIN;
   while (!moves.empty( ))
   {
      future = clone( );
      future->make_move(moves.front( ));
      value = future->eval_with_lookahead(look_ahead-1, best_value);
      delete future;
      if (value > best_value)
      {
         if (-value <= beat_this)
            return INT_MIN + 1; // Alpha-beta pruning
         best_value = value;
      }
      moves.pop( );
   }
   return -best_value;
}

void game::make_computer_move( )
{
   queue<string> moves;
   int value;
   int best_value;
   string best_move;
   game* future;

   // Compute all legal moves that the computer could make.
   compute_moves(moves);
   assert(!moves.empty( ));

	// Evaluate each possible legal move, saving the index of the best
	// in best_index and saving its value in best_value.
   best_value = INT_MIN;
   while (!moves.empty( ))
   {
      future = clone( );
      future->make_move(moves.front( ));
      value = future->eval_with_lookahead(SEARCH_LEVELS, best_value);
      delete future;
      if (value >= best_value)
      {
         best_value = value;
         best_move = moves.front( );
      }
      moves.pop( );
   }
	// Make the best move.
   make_move(best_move);
}

void game::make_human_move( )
{
   string move;

   move = get_user_move( );
   while (!is_legal(move))
   {
      display_message("Illegal move.\n");
      move = get_user_move( );
   }
   make_move(move);
}

}  //end of namespace main_savitch_14