/**********************************************************************
 *
 *   FreeDoko a Doppelkopf-Game
 *    
 *   Copyright (C) 2001-2004  by Diether Knof and Borg Enders
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License as
 *   published by the Free Software Foundation; either version 2 of
 *   the License, or (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *   You can find this license in the file 'gpl.txt'.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *   MA  02111-1307  USA
 *
 *  Contact:
 *    Diether Knof dknof@gmx.de
 *    Borg Enders  borg@borgsoft.de
 *
 ********************************************************************/

#include "constants.h"

#include "weighting.h"

#include "w_virtual_games.h"
#include "gametree.h"
#include "w_monte_carlo.h"

/**********************************************************************
 *
 ** Weighting::Weighting(const AiType t = AITYPE::VIRTUAL,
 *			const long int fl = 1000)
 *
 ** Parameters:	t - aitype
 *		fl - future limit
 *
 ** Result:	-
 *
 ** Version:	0.4.2
 *
 ** Description:	constructur
 *
 *
 **********************************************************************/

Weighting::Weighting(AiType t) :
choose_ai_p(t)
{
  DEBUG_CALLING(INFO_WEIGHTING && INFO_INIT,
		"Weighting::Weighting()");

  DEBUG_RETURNING(VOID,
		  INFO_WEIGHTING && INFO_INIT,
		  "Weighting::Weighting()");
} // Weighting::Weighting()

/**********************************************************************
 *
 ** Weighting::~Weighting()
 *
 ** Parameters:	-
 *
 ** Result:	-
 *
 ** Version:	0.4.2
 *
 ** Description:	destructor -- nothing to do
 *
 **********************************************************************/

Weighting::~Weighting()
{
  DEBUG_CALLING(INFO_WEIGHTING && INFO_INIT,
		"Weighting::~Weighting()");

  DEBUG_RETURNING(VOID,
		  INFO_WEIGHTING && INFO_INIT,
		  "Weighting::~Weighting()");
} // Weighting::~Weighting()

/**********************************************************************
 *
 ** Card Weighting::choosebestcard(const Ai& ai, Trick T, int pl, bool future)
 *
 ** Parameters:	ai	- the ai
 *		t	- actual played trick
 *		pl	- number of player
 *		future	- ?
 *
 ** Result:	card with which the player wins over all possible tricks
 *		the most points
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
Card
Weighting::choosebestcard(const Ai& ai,Trick const& T,
			  int const pl, bool const future)
{
  DEBUG_CALLING(INFO_WEIGHTING && INFO_OTHER_FUNCTION,
		"Weighting::choosebestcard(Ai, Trick, pl, future)");

  (void)T;
  (void)pl;
  (void)future;

  Card c=Card();
#ifndef RELEASE
  Ai* ai_bak = ai.clone();
#endif

  switch(this->choose_ai_p) {
  case AITYPE::NO_CHOOSEBESTCARD:
    c = Card();
    break;
  case AITYPE::RANDOM:
    {
    Hand validcards = ai.hand().validcards(ai.game().trick_current());
    c = validcards.card(RAND(validcards.cardsnumber() - 1));
    }
    break;
  case AITYPE::VIRTUAL_GAMES:
    c = WVirtualGames(ai, ai.value(Aiconfig::FUTURE_LIMIT)).best_card();
    break;
  case AITYPE::GAMETREE:
    c = Gametree(ai, ai.value(Aiconfig::FUTURE_LIMIT), false).best_card();
    break;
  case AITYPE::GAMETREE_WITH_HEURISTICS:
    c = Gametree(ai, ai.value(Aiconfig::FUTURE_LIMIT), true).best_card();
    break;
  case AITYPE::MONTE_CARLO:
    c = WMonteCarlo(ai, ai.value(Aiconfig::FUTURE_LIMIT)).best_card();
    break;

  default:
    DEBUG_ASSERTION(false,
		    "Weighting::choosebestcard():\n"
		    "  no aitype"
		   );
    break;
  } // switch(choose_ai_p)

  DEBUG_ASSERTION( (this->choose_ai_p == AITYPE::NO_CHOOSEBESTCARD)
		   || c,
		   "Weighting::choosebestcard():\n"
		   "  '" << this->choose_ai_p << "' returns no card");

#ifndef RELEASE
  DEBUG_ASSERTION(ai.isequal(*ai_bak),
		  "Weighting::choosebestcard():\n"
		  "  ai has changed!\n");
  delete ai_bak;
#endif

  DEBUG_RETURNING(c,
		  INFO_WEIGHTING && INFO_OTHER_FUNCTION,
		  "Weighting::choosebestcard(Ai, Trick, pl, future)");
} // Card Weighting::choosebestcard(const Ai& ai,Trick T,int pl,bool future)
