//////////////////////////////////////////////////////////////////////////////
//
// File: player.cc
//
// Purpose: This is the implementation of the Player class.
//
// Authors:
//   txe  Travis Emmitt
//
// Modifications:
//   14-APR-1998  txe  Initial creation
//   15-APR-1998  txe  Added MOVE_* macros, added comments, alphabetized
//   16-APR-1998  txe  Added Feedback(), TakeTurn(), NewGame(), NewMatch()
//   18-APR-1998  txe  Inherits from Debugging; removed GetName(), SetDebug()
//   20-APR-1998  txe  Ported to UNIX
//   21-APR-1998  txe  Added num_draws, num_losses, ResetScores()
//   23-APR-1998  txe  Using static debug, changed constructor
//   24-APR-1998  txe  Removed ability
//
//////////////////////////////////////////////////////////////////////////////

#include <iostream.h>
#include "common.h"
#include "board.h"
#include "player.h"
#include "referee.h"

////////////////////////////////////////////////////////////////////////////

Player::Player (char *name, int color)
      : Debug  (name) {

  this->color         = color;
  this->board         = NULL;
  this->win_boards[0] = NULL;
  this->players[0]    = NULL;
  this->ref           = NULL;
  this->turn          = 0;
  this->game          = 0;
  this->match         = 0;
  this->num_draws     = 0;
  this->num_losses    = 0;
  this->num_wins      = 0;
}

//////////////////////////////////////////////////////////////////////////////

void Player::Feedback (int code) {
  switch (code) {
  case DRAW : num_draws++;  break;
  case LOSE : num_losses++; break;
  case WIN  : num_wins++;   break;
  }
}

////////////////////////////////////////////////////////////////////////////

int Player::GetNumDraws () {
  return num_draws;
}

////////////////////////////////////////////////////////////////////////////

int Player::GetNumLosses () {
  return num_losses;
}

////////////////////////////////////////////////////////////////////////////

int Player::GetNumWins () {
  return num_wins;
}

////////////////////////////////////////////////////////////////////////////

int Player::NewGame () {
  game++;
  turn = 0;
  DEBUG(3) << name << " getting ready for game #" << game << "\n";
  return 1;
}

////////////////////////////////////////////////////////////////////////////

int Player::NewMatch () {
  match++;
  game = 0;
  turn = 0;
  DEBUG(3) << name << " getting ready for match #" << match << "\n";
  return 1;
}

////////////////////////////////////////////////////////////////////////////

void Player::ResetScores () {
  DEBUG(3) << name << " resetting scores\n";
  num_draws  = 0;
  num_losses = 0;
  num_wins   = 0;
}

////////////////////////////////////////////////////////////////////////////

void Player::ShowRules (Board *board, Board **win_boards) {
  ASSERT (board      != NULL);
  ASSERT (win_boards != NULL);
  DEBUG(3) << "Showing " << name << " the rules...\n";

  this->board  = board;
  this->size_x = board->GetSizeX ();
  this->size_y = board->GetSizeY ();

  int i;
  for (i = 0; i < MAX_WIN_BOARDS && win_boards[i] != NULL; i++) {
    this->win_boards[i] = win_boards[i];
  }
  this->win_boards[i] = NULL;
  num_win_boards = i;
}

////////////////////////////////////////////////////////////////////////////

void Player::ShowPlayers (Player **players) {
  ASSERT (players != NULL);
  DEBUG(3) << "Showing " << name << " the players...\n";

  int i;
  for (i = 0; i < MAX_PLAYERS && players[i] != NULL; i++) {
    this->players[i] = players[i];
  }
  this->players[i] = NULL;
  num_players = i - 1;            // don't include referee in count of players
  ref = (Referee *) players[0];   // player 0 is really the referee
}

////////////////////////////////////////////////////////////////////////////

int Player::TakeTurn () {
  ASSERT (ref != NULL);

  DEBUG(3) << "\n" << name << " selecting next move...\n";

  int i, status = PASS;

  for (i = 0; i < MAX_ATTEMPTS && (status = GetMove()) > 0; i++) {
    if (ref->Move (move_x, move_y, color)) {
      DEBUG(2) << "\n" << name << " moved to ("
	       << move_x << "," << move_y << "):\n";
      turn++;
      return 1;
    }
    Feedback (INVALID);
  }

  DEBUG(2) << name << (status == QUIT ? " wants to quit\n"
		                      : " couldn't find a move, passing\n");
  return status;
}

//////////////////////////////////////////////////////////////////////////////



