/**********************************************************************
 *
 *   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 "aiconfig.h"

#include "../party/party.h"
#include "../party/rule.h"
#include "../misc/setting.h"



unsigned const Aiconfig::BOOL_NUMBER = (Aiconfig::BOOL_LAST
					- Aiconfig::BOOL_FIRST + 1);
unsigned const Aiconfig::UNSIGNED_NUMBER = (Aiconfig::UNSIGNED_LAST
					    - Aiconfig::UNSIGNED_FIRST + 1);
unsigned const Aiconfig::CARD_NUMBER = (Aiconfig::CARD_LAST
					- Aiconfig::CARD_FIRST + 1);


/**
 **
 ** constructor
 **
 ** @param	-
 **
 ** @result	-
 **
 ** @author	Borg Enders
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
Aiconfig::Aiconfig() :
aitype_p(AITYPE::VIRTUAL_GAMES),
  bool_p(BOOL_NUMBER),
  unsigned_p(UNSIGNED_NUMBER),
card_p(CARD_NUMBER)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_INIT,
		"Aiconfig::Aiconfig()");

  this->reset_to_hardcoded();

  DEBUG_RETURNING(VOID,
		  INFO_AICONFIG && INFO_INIT,
		  "Aiconfig::Aiconfig()");
} // Aiconfig::Aiconfig()

/**
 **
 ** Konstruktor
 **
 ** @param	istr	stream with the infos
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.2
 **
 **/
Aiconfig::Aiconfig(istream& istr)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_INIT,
		"Aiconfig::Aiconfig(istr)");

  this->load(istr);

  DEBUG_RETURNING(VOID,
		  INFO_AICONFIG && INFO_INIT,
		  "Aiconfig::Aiconfig(istr)");
} // Aiconfig::Aiconfig(istream& istr)

/**********************************************************************
 *
 ** Aiconfig::Aiconfig(Aiconfig const& aiconfig)
 *
 ** Parameters:  aiconfig        - aiconfig to set equal
 *
 ** Result:      -
 *
 ** Version:     0.4.2
 *
 ** Description: constructor
 *
 **********************************************************************/
Aiconfig::Aiconfig(Aiconfig const& aiconfig) :
aitype_p(aiconfig.aitype_p),
  bool_p(aiconfig.bool_p),
  unsigned_p(aiconfig.unsigned_p),
card_p(aiconfig.card_p)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::Aiconfig(Aiconfig)");

  DEBUG_RETURNING(VOID,
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::Aiconfig(Aiconfig)");
} // Aiconfig::Aiconfig(Aiconfig const& aiconfig) const

/**********************************************************************
 *
 ** Aiconfig& Aiconfig::operator=(Aiconfig const& aiconfig)
 *
 ** Parameters:  aiconfig        - aiconfig to set equal
 *
 ** Result:      new aiconfig
 *
 ** Version:     0.4.2
 *
 ** Description: sets the aiconfig '*this' equal 'aiconfig'
 *
 **********************************************************************/
Aiconfig&
Aiconfig::operator=(Aiconfig const& aiconfig)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::operator=(Aiconfig)");

  if (this == &aiconfig)
    DEBUG_RETURNING(*this,
		    INFO_AICONFIG && INFO_VALUE,
		    "Aiconfig::operator=(Aiconfig)");

  this->aitype_set(aiconfig.aitype());

  unsigned i;
  for (i = BOOL_FIRST; i <= BOOL_LAST; i++)
    this->set(TypeBool(i), aiconfig.value(TypeBool(i)));
  for (i = UNSIGNED_FIRST; i <= UNSIGNED_LAST; i++)
    this->set(TypeUnsigned(i), aiconfig.value(TypeUnsigned(i)));
  for (i = CARD_FIRST; i <= CARD_LAST; i++)
    this->set(TypeCard(i), aiconfig.value(TypeCard(i)));

  DEBUG_RETURNING(*this,
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::operator=(Aiconfig)");
} // bool Aiconfig::operator=(Aiconfig const& aiconfig) const

/**********************************************************************
 *
 ** Aiconfig::~Aiconfig()
 *
 ** Parameters:  -
 *
 ** Result:      -
 *
 ** Version:     0.4.2
 *
 ** Description: destructor - nothing to do
 *
 **********************************************************************/
Aiconfig::~Aiconfig()
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::~Aiconfig()");

  DEBUG_RETURNING(VOID,
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::~Aiconfig()");
} // Aiconfig::~Aiconfig() const


/**
 **
 ** resets the aiconfig to the hardcoded
 **
 ** @param	-
 **
 ** @return	-
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
void
Aiconfig::reset_to_hardcoded()
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_INIT,
		"Aiconfig::reset_to_hardcoded()");

  this->set(TRUSTING,           false);
#ifndef RELEASE
  this->set(FAIRPLAYHANDS,      false);
#else
  this->set(FAIRPLAYHANDS,      false);
#endif
  this->set(FAIRPLAYTEAMS,		true);

  this->set(CHOOSE_ACE,			true);     
  this->set(CHOOSE_FOR_COLOR_TRICK,	true);
  this->set(CHOOSE_PFUND,		true);
  this->set(JAB_FOR_ACE,		true);
  this->set(CREATE_FEHL,		true);
  this->set(BEST_WINNING,		true);
  this->set(LOW_HIGH,			true);
  this->set(PLAY_FOR_TEAM,		true);
  this->set(JAB_FOX,			true);
  this->set(DRAW_TRUMP,		true);
  

  this->set(MEATLESS_PLAYHIGHESTCOLOR,	true);
  this->set(PICTURE_SECONDBESTTRUMP,	true);

  this->set(COLOR_CHOOSE_ACE,		true);
  this->set(COLOR_BEST_WINNING,		true);
  this->set(COLOR_JAB_FOR_ACE,		true);
  this->set(COLOR_LOW_HIGH,		true);
  this->set(FEHLCREATIONONFIRSTCARD,	true);

  this->set(REMEMBERTRICKS,     ::party.rule()(Rule::NUMBER_OF_TRICKS_IN_GAME));
  this->set(LIMITQUEEN,         10);
  this->set(LIMITDOLLE,         19);

  this->set(LASTFEHLCREATION,    4);
  this->set(LASTHEURISTICTRICK,  9);

  this->set(ANNOUNCELIMIT,      10);
  this->set(ANNOUNCELIMITDEC,    1);
  this->set(ANNOUNCECONFIG,      1);

  this->set(ANNOUNCELIMITREPLY,       8);
  this->set(ANNOUNCECONFIGREPLY,      1);


  this->set(TAKEPOVERTY,        13);

  this->set(SINGLESOLO,         18);
  this->set(DOUBLESOLO,         50);
  this->set(TRIPLESOLO,         100);
  this->set(COLORSOLO,          28);
  this->set(MEATLESS,           26);

  this->set(FUTURE_LIMIT,       10000);

  this->set(LIMITTHROWING,      Card(Card::DIAMOND,Card::QUEEN));
  this->set(LIMITHIGH,          Card(Card::HEART,Card::QUEEN));

  this->set(TRUMPLIMIT_SOLOCOLOR,     Card(Card::HEART,Card::QUEEN));
  this->set(TRUMPLIMIT_SOLOJACK,      Card(Card::DIAMOND,Card::JACK));
  this->set(TRUMPLIMIT_SOLOQUEEN,     Card(Card::DIAMOND,Card::QUEEN));
  this->set(TRUMPLIMIT_SOLOKING,      Card(Card::DIAMOND,Card::KING));
  this->set(TRUMPLIMIT_SOLOJACKKING,  Card(Card::CLUB,Card::JACK));
  this->set(TRUMPLIMIT_SOLOJACKQUEEN, Card(Card::CLUB,Card::JACK));
  this->set(TRUMPLIMIT_SOLOQUEENKING, Card(Card::CLUB,Card::QUEEN));
  this->set(TRUMPLIMIT_SOLOKOEHLER,   Card(Card::CLUB,Card::QUEEN));
  this->set(TRUMPLIMIT_MEATLESS,      Card(Card::DIAMOND,Card::TEN));
  this->set(TRUMPLIMIT_NORMAL,        Card(Card::HEART,Card::QUEEN));

  this->set(LOWEST_TRUMPLIMIT_SOLOCOLOR,     Card(Card::HEART,Card::JACK));
  this->set(LOWEST_TRUMPLIMIT_SOLOJACK,      Card(Card::HEART,Card::JACK));
  this->set(LOWEST_TRUMPLIMIT_SOLOQUEEN,     Card(Card::HEART,Card::QUEEN));
  this->set(LOWEST_TRUMPLIMIT_SOLOKING,      Card(Card::HEART,Card::KING));
  this->set(LOWEST_TRUMPLIMIT_SOLOJACKKING,  Card(Card::SPADE,Card::JACK));
  this->set(LOWEST_TRUMPLIMIT_SOLOJACKQUEEN, Card(Card::SPADE,Card::JACK));
  this->set(LOWEST_TRUMPLIMIT_SOLOQUEENKING, Card(Card::SPADE,Card::QUEEN));
  this->set(LOWEST_TRUMPLIMIT_SOLOKOEHLER,   Card(Card::SPADE,Card::QUEEN));
  this->set(LOWEST_TRUMPLIMIT_MEATLESS,      Card(Card::DIAMOND,Card::QUEEN));
  this->set(LOWEST_TRUMPLIMIT_NORMAL,        Card(Card::DIAMOND,Card::JACK));

  this->aitype_set(AITYPE::VIRTUAL_GAMES);

  DEBUG_RETURNING(VOID,
		  INFO_AICONFIG && INFO_INIT,
		  "Aiconfig::reset_to_hardcoded()");
} // void Aiconfig::reset_to_hardcoded()

/**********************************************************************
 *
 ** AiType const& aitype() const
 *
 ** Parameters:  -
 *
 ** Result:      the aitype
 *
 ** Version:     0.4.2
 *
 ** Description: -> result
 *
 **********************************************************************/
AiType const&
Aiconfig::aitype() const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::aitype()");

  DEBUG_RETURNING(this->aitype_p,
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::aitype()");
} // AiType const& Aiconfig::aitye() const;

/**********************************************************************
 *
 ** AiType const& aitype_set(AiType const& aitype)
 *
 ** Parameters:  aitype - the new aitype
 *
 ** Result:      the aitype
 *
 ** Version:     0.4.2
 *
 ** Description: sets the aitype
 *
 **********************************************************************/
AiType const&
Aiconfig::aitype_set(AiType const& aitype)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::aitype_set(AiType)");

  this->aitype_p = aitype;

  DEBUG_RETURNING(this->aitype(),
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::aitype_set(AiType)");
} // AiType const& Aiconfig::aitye_set(AiType const& aitype) const;

/**********************************************************************
 *
 ** bool value(TypeBool const& type) const
 *
 ** Parameters:  Aiconfigtype
 *
 ** Result:      the value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: The number of cards is calculated,
 **              the other values are taken from the variable
 **   
 *
 **********************************************************************/
bool
Aiconfig::value(TypeBool const& type) const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::value(TypeBool)");

  DEBUG_RETURNING(this->bool_p[type - BOOL_FIRST],
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::value(TypeBool)");
} // bool Aiconfig::value(TypeBool) const;

/**********************************************************************
 *
 ** unsigned value(TypeUnsigned const& type) const
 *
 ** Parameters:  Aiconfigtype
 *
 ** Result:      the value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: The number of cards is calculated,
 **              the other values are taken from the variable
 **   
 *
 **********************************************************************/
unsigned
Aiconfig::value(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::value(TypeUnsigned)");

  DEBUG_RETURNING(this->unsigned_p[type - UNSIGNED_FIRST],
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::value(TypeUnsigned)");
} // unsigned Aiconfig::value(TypeUnsigned) const;

/**********************************************************************
 *
 ** Card value(TypeCard const& type) const
 *
 ** Parameters:  Aiconfigtype
 *
 ** Result:      the value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: The number of cards is calculated,
 **              the other values are taken from the variable
 **   
 *
 **********************************************************************/
Card
Aiconfig::value(TypeCard const& type) const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::value(TypeCard)");

  DEBUG_RETURNING(this->card_p[type - CARD_FIRST],
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::value(TypeCard)");
} // Card Aiconfig::value(TypeCard) const;

/**********************************************************************
 *
 ** unsigned min(TypeUnsigned const& type)
 *
 ** Parameters:  type    - Aiconfigtype
 *
 ** Result:      the minimal value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: -> result
 *
 **********************************************************************/
unsigned
Aiconfig::min(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::min(TypeUnsigned)");

  unsigned value = UINT_MAX;

  switch(type) {
  case REMEMBERTRICKS:
  case LASTFEHLCREATION:
  case LASTHEURISTICTRICK:
    value = 0;
    break;

  case LIMITQUEEN:
  case LIMITDOLLE:
    value = 0;
    break;

  case ANNOUNCELIMIT:
  case ANNOUNCELIMITDEC:
  case ANNOUNCECONFIG:
  case ANNOUNCELIMITREPLY:
  case ANNOUNCECONFIGREPLY:
  
    value = 0;
    break;

  case TAKEPOVERTY:
    value = 0;
    break;

  case SINGLESOLO:
  case DOUBLESOLO:
  case TRIPLESOLO:
  case COLORSOLO:
  case MEATLESS:
    value = 0;
    break;

  case FUTURE_LIMIT:
    value = 1;
    break;
  } // switch(type)

  DEBUG_RETURNING(value,
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::min(TypeUnsigned)");
} // unsigned Aiconfig::min(TypeUnsigned const& type) const

/**********************************************************************
 *
 ** unsigned max(TypeUnsigned const& type)
 *
 ** Parameters:  type    - Aiconfigtype
 *
 ** Result:      the maximal value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: -> result
 *
 **********************************************************************/
unsigned
Aiconfig::max(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::max(TypeUnsigned)");

  unsigned value = UINT_MAX;

  switch(type) {
  case REMEMBERTRICKS:
  case LASTFEHLCREATION:
  case LASTHEURISTICTRICK:
    value = ::party.rule()(Rule::NUMBER_OF_TRICKS_IN_GAME);
    break;

  case LIMITQUEEN:
  case LIMITDOLLE:
    value = 1000;
    break;

  case ANNOUNCELIMIT:
  case ANNOUNCELIMITDEC:
  case ANNOUNCECONFIG:
  case ANNOUNCELIMITREPLY:
  case ANNOUNCECONFIGREPLY:
  
    value = 1000;
    break;

  case TAKEPOVERTY:
    value = 1000;
    break;

  case SINGLESOLO:
  case DOUBLESOLO:
  case TRIPLESOLO:
  case COLORSOLO:
  case MEATLESS:
    value = 1000;
    break;

  case FUTURE_LIMIT:
    value = static_cast<unsigned const>(1e9);
    break;
  } // switch(type)

  DEBUG_RETURNING(value,
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::max(TypeUnsigned)");
} // unsigned Aiconfig::max(TypeUnsigned const& type) const

/**
 **
 ** sets 'type' to 'value'
 **
 ** @param	type	Aiconfigtype
 ** @param	value	new value
 **
 ** @return	'true', if the type is valid, otherwise 'false'
 **
 ** @version	0.5.2
 **
 ** @author	Diether Knof
 **   
 **/
bool
Aiconfig::set(string const& type, string const& value)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::set(string type, string value)");

  unsigned i;

  for (i = Aiconfig::BOOL_FIRST; i <= Aiconfig::BOOL_LAST; i++) {
    if (type == name(Aiconfig::TypeBool(i))) {
      this->set(Aiconfig::TypeBool(i), value);
      DEBUG_RETURNING(true,
		      INFO_AICONFIG && INFO_VALUE,
		      "Aiconfig::set(string type, string value)");
    } // if (type == name(Aiconfig::TypeBool(i)))
  } // (i \in BOOL)
  for (i = Aiconfig::UNSIGNED_FIRST; i <= Aiconfig::UNSIGNED_LAST; i++) {
    if (type == name(Aiconfig::TypeUnsigned(i))) {
      this->set(Aiconfig::TypeUnsigned(i), value);
      DEBUG_RETURNING(true,
		      INFO_AICONFIG && INFO_VALUE,
		      "Aiconfig::set(string type, string value)");
    } // if (type == name(Aiconfig::TypeUnsigned(i)))
  } // (i \in UNSIGNED)
  for (i = Aiconfig::CARD_FIRST; i <= Aiconfig::CARD_LAST; i++) {
    if (type == name(Aiconfig::TypeCard(i))) {
      this->set(Aiconfig::TypeCard(i), value);
      DEBUG_RETURNING(true,
		      INFO_AICONFIG && INFO_VALUE,
		      "Aiconfig::set(string type, string value)");
    } // if (type == name(Aiconfig::TypeCard(i)))
  } // (i \in CARD)

  DEBUG_RETURNING(false,
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::set(string type, string value)");
} // bool Aiconfig::set(string const& type, string const& value)

/**
 **
 ** sets 'type' to 'value'
 **
 ** @param	type	Aiconfigtype
 ** @param	value	new value
 **
 ** @return	the value of the rule 'type'
 **
 ** @version	0.5.2
 **
 ** @author	Diether Knof
 **   
 **/
bool
Aiconfig::set(TypeBool const type, string const& value)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::set(TypeBool, string)");

  if ((value != "true")
      && (value != "false")
      && (value != "yes")
      && (value != "no")
      && (value != "0")
      && (value != "1")) {
    cerr << "Aiconfig::set(TypeBool, value):\n"
      << "illegal value '" << value << "' for '" << type << "', "
      << "must be a boolean ('true' or 'false' or 'yes' or 'no' or '1' or '0'. "
      << "Taking 'false'."
      << endl;
  }
  DEBUG_RETURNING(this->set(type, (((value == "false")
				    || (value == "no")
				    || (value == "0"))
				   ? false :	true)),
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::set(TypeBool, string)");
} // bool Aiconfig::set(const TypeBool type, string const& value)

/**
 **
 ** sets 'type' to 'value'
 **
 ** @param	type	Aiconfigtype
 ** @param	value	new value
 **
 ** @return	the value of the rule 'type'
 **
 ** @version	0.5.2
 **
 ** @author	Diether Knof
 **   
 **/
unsigned
Aiconfig::set(TypeUnsigned const type, string const& value)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::set(TypeUnsigned, string)");

  char* end_ptr;
  unsigned number = strtoul(value.c_str(), &end_ptr, 0);
  if (*end_ptr != '\0') {
    cerr << "Aiconfig::set(TypeUnsigned, value):\n"
      << "illegal value '" << value << "' for '" << type << "', "
      << "must be a digit. "
      << "Taking " << number << "."
      << endl;
  }


  DEBUG_RETURNING(this->set(type, number),
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::set(TypeUnsigned, string)");
} // unsigned Aiconfig::set(const TypeUnsigned type, string const& value)

/**
 **
 ** sets 'type' to 'value'
 **
 ** @param	type	Aiconfigtype
 ** @param	value	new value
 **
 ** @return	the value of the rule 'type'
 **
 ** @version	0.5.2
 **
 ** @author	Diether Knof
 **   
 **/
Card
Aiconfig::set(TypeCard const type, string const& value)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::set(TypeCard, string)");

  DEBUG_RETURNING(this->set(type, Card(value)),
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::set(TypeCard, string)");
} // C Aiconfig::set(const TypeCard type, string const& value)

/**********************************************************************
 *
 ** bool set(TypeBool const& type, bool const& value)
 *
 ** Parameters:  type - Aiconfig-type
 **              value - new value
 *
 ** Result:      the value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: sets the aiconfig 'type' to the value 'value'
 *
 **********************************************************************/
bool
Aiconfig::set(TypeBool const& type, bool const& value)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::set(TypeBool)");

  this->bool_p[type - BOOL_FIRST] = value;

  DEBUG_RETURNING(this->value(type),
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::set(TypeBool)");
} // bool Aiconfig::set(TypeBool, bool);

/**********************************************************************
 *
 ** unsigned set(TypeUnsigned const& type, unsigned const& value)
 *
 ** Parameters:  type - Aiconfig-type
 **              value - new value
 *
 ** Result:      the value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: sets the aiconfig 'type' to the value 'value'
 *
 **********************************************************************/
unsigned
Aiconfig::set(TypeUnsigned const& type, unsigned const& value)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::set(TypeUnsigned)");

  this->unsigned_p[type - UNSIGNED_FIRST] = value;

  DEBUG_RETURNING(this->value(type),
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::set(TypeUnsigned)");
} // unsigned Aiconfig::set(TypeUnsigned, unsigned);

/**********************************************************************
 *
 ** Card set(TypeCard const& type, Card const& value)
 *
 ** Parameters:  type - Aiconfig-type
 **              value - new value
 *
 ** Result:      the value of the aiconfig 'type'
 *
 ** Version:     0.4.2
 *
 ** Description: sets the aiconfig 'type' to the value 'value'
 *
 **********************************************************************/
Card
Aiconfig::set(TypeCard const& type, Card const& value)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"Aiconfig::set(TypeCard)");

  this->card_p[type - CARD_FIRST] = value;

  DEBUG_RETURNING(this->value(type),
		  INFO_AICONFIG && INFO_VALUE,
		  "Aiconfig::set(TypeCard)");
} // Card Aiconfig::set(TypeCard, card);

/**********************************************************************
 *
 ** ostream& Aiconfig::out(ostream& ostr) const
 *
 ** Parameters:  ostr - ouput stream
 *
 ** Result:      output stream
 *
 ** Version:     0.4.2
 *
 ** Description: prints the aitypes in the ouput stream
 *
 **********************************************************************/
ostream&
Aiconfig::out(ostream& ostr) const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_IO,
		"Aiconfig::out(ostream)");

  ostr << "# Aiconfig\n"
    << "{\n"
    << "type" << " = "
    << this->aitype() << '\n'
    << '\n'
    << TRUSTING << " = "
    << this->value(TRUSTING) << '\n'
    << FAIRPLAYHANDS << " = "
    << this->value(FAIRPLAYHANDS) << '\n'
    << FAIRPLAYTEAMS << " = "
    << this->value(FAIRPLAYTEAMS) << '\n'
    << '\n'
    << CHOOSE_ACE << " = "
    << this->value(CHOOSE_ACE) << '\n' 
    << CHOOSE_FOR_COLOR_TRICK  << " = "
    << this->value(CHOOSE_FOR_COLOR_TRICK) << '\n'
    << CHOOSE_PFUND            << " = "
    << this->value(CHOOSE_PFUND) << '\n'
    << JAB_FOR_ACE             << " = "
    << this->value(JAB_FOR_ACE ) << '\n'
    << CREATE_FEHL             << " = "
    << this->value(CREATE_FEHL ) << '\n'
    << BEST_WINNING           << " = "
    << this->value(BEST_WINNING) << '\n'
    << LOW_HIGH                << " = "
    << this->value(LOW_HIGH ) << '\n'
    << PLAY_FOR_TEAM           << " = "
    << this->value(PLAY_FOR_TEAM) << '\n'
    << JAB_FOX                << " = "
    << this->value(JAB_FOX) << '\n'
    << DRAW_TRUMP                << " = "
    << this->value(DRAW_TRUMP) << '\n'
    << MEATLESS_PLAYHIGHESTCOLOR      << " = "
    << this->value(MEATLESS_PLAYHIGHESTCOLOR) << '\n'
    << PICTURE_SECONDBESTTRUMP<< " = "
    << this->value(PICTURE_SECONDBESTTRUMP) << '\n'
    << COLOR_CHOOSE_ACE<< " = "
    << this->value(COLOR_CHOOSE_ACE)<< '\n'
    << COLOR_BEST_WINNING<< " = "
    << this->value(COLOR_BEST_WINNING) << '\n'
    << COLOR_JAB_FOR_ACE<< " = "
    << this->value(COLOR_JAB_FOR_ACE) << '\n'
    << COLOR_LOW_HIGH  << " = "
    << this->value(COLOR_LOW_HIGH) << '\n'
    << '\n'
    << FEHLCREATIONONFIRSTCARD  << " = "
    << this->value(FEHLCREATIONONFIRSTCARD) << '\n'
    << '\n'
    << REMEMBERTRICKS << " = "
    << this->value(REMEMBERTRICKS) << '\n'
    << '\n'
    << LIMITQUEEN << " = "
    << this->value(LIMITQUEEN) << '\n'
    << LIMITDOLLE << " = "
    << this->value(LIMITDOLLE) << '\n'
    << '\n'
    << LASTFEHLCREATION << " = "
    << this->value(LASTFEHLCREATION) << '\n'
    << '\n'
    << LASTHEURISTICTRICK << " = "
    << this->value(LASTHEURISTICTRICK) << '\n'
    << '\n'
    << ANNOUNCELIMIT << " = "
    << this->value(ANNOUNCELIMIT) << '\n'
    << ANNOUNCELIMITDEC << " = "
    << this->value(ANNOUNCELIMITDEC) << '\n'
    << '\n'
    << ANNOUNCECONFIG << " = "
    << this->value(ANNOUNCECONFIG) << '\n'
    << '\n'
    << ANNOUNCELIMITREPLY << " = "
    << this->value(ANNOUNCELIMITREPLY) << '\n'
    << ANNOUNCECONFIGREPLY << " = "
    << this->value(ANNOUNCECONFIGREPLY) << '\n'
    << '\n'
    << TAKEPOVERTY << " = "
    << this->value(TAKEPOVERTY) << '\n'
    << '\n'
    << SINGLESOLO << " = "
    << this->value(SINGLESOLO) << '\n'
    << DOUBLESOLO << " = "
    << this->value(DOUBLESOLO) << '\n'
    << TRIPLESOLO << " = "
    << this->value(TRIPLESOLO) << '\n'
    << COLORSOLO << " = "
    << this->value(COLORSOLO) << '\n'
    << MEATLESS << " = "
    << this->value(MEATLESS) << '\n'
    << '\n'
    << FUTURE_LIMIT << " = "
    << this->value(FUTURE_LIMIT) << '\n'
    << '\n'
    << LIMITTHROWING << " = "
    << this->value(LIMITTHROWING) << '\n'
    << '\n'
    << LIMITHIGH << " = "
    << this->value(LIMITHIGH) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOCOLOR << " = "
    << this->value(TRUMPLIMIT_SOLOCOLOR) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOJACK << " = "
    << this->value(TRUMPLIMIT_SOLOJACK) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOQUEEN << " = "
    << this->value(TRUMPLIMIT_SOLOQUEEN) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOKING << " = "
    << this->value(TRUMPLIMIT_SOLOKING) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOJACKKING << " = "
    << this->value(TRUMPLIMIT_SOLOJACKKING) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOJACKQUEEN << " = "
    << this->value(TRUMPLIMIT_SOLOJACKQUEEN) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOQUEENKING << " = "
    << this->value(TRUMPLIMIT_SOLOQUEENKING) << '\n'
    << '\n'
    << TRUMPLIMIT_SOLOKOEHLER << " = "
    << this->value(TRUMPLIMIT_SOLOKOEHLER) << '\n'
    << '\n'
    << TRUMPLIMIT_MEATLESS << " = "
    << this->value(TRUMPLIMIT_MEATLESS) << '\n'
    << '\n'
    << TRUMPLIMIT_NORMAL << " = "
    << this->value(TRUMPLIMIT_NORMAL) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOCOLOR << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOCOLOR) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOJACK << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOJACK) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOQUEEN << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOQUEEN) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOKING << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOKING) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOJACKKING << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOJACKKING) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOJACKQUEEN << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOJACKQUEEN) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOQUEENKING << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOQUEENKING) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_SOLOKOEHLER << " = "
    << this->value(LOWEST_TRUMPLIMIT_SOLOKOEHLER) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_MEATLESS << " = "
    << this->value(LOWEST_TRUMPLIMIT_MEATLESS) << '\n'
    << '\n'
    << LOWEST_TRUMPLIMIT_NORMAL << " = "
    << this->value(LOWEST_TRUMPLIMIT_NORMAL) << '\n'
    << "}\n";

  DEBUG_RETURNING(ostr,
		  INFO_AICONFIG && INFO_IO,
		  "Aiconfig::out(ostream)");
} // ostream& Aiconfig::out(ostream& ostr) const

/**
 **
 ** loads the infos from the file
 **
 ** @param	filename	file to load the aiconfig from
 **
 ** @return	whether the loading was successful
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
bool
Aiconfig::load(string const& filename)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_INIT,
		"Aiconfig::load(filename)");

  ifstream istr(filename.c_str());
  if (istr.fail())
    DEBUG_RETURNING(false,
		    INFO_AICONFIG && INFO_INIT,
		    "Aiconfig::load(filename)");

  DEBUG_RETURNING(this->load(istr),
		  INFO_AICONFIG && INFO_INIT,
		  "Aiconfig::load(filename)");
} // bool Aiconfig::load(string const& filename)

/**
 **
 ** loads the infos from the stream
 **
 ** @param	istr	stream with the infos
 **
 ** @return	whether the loading was successful
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
bool
Aiconfig::load(istream& istr)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_INIT,
		"Aiconfig::load(istr)");

#ifndef POSTPHONED
  // if the following is an empty line, ignore it
  if ((istr.peek() == '\n')
      || (istr.peek() == '\r'))
    DEBUG_RETURNING(true,
		    INFO_AICONFIG && INFO_INIT,
		    "Aiconfig::load(istr)");
#endif

  unsigned depth = 0;

  // load the configuration
  while (istr.good()) {
    Config config;
    istr >> config;

    // finished with the config file
    if ((config.name == "") && (config.value == ""))
      break;

    if (config.separator) {
      // a setting
      if (config.name == "type") {
	int t;
	for (t = AITYPE::AITYPE_FIRST; t <= AITYPE::AITYPE_LAST; t++)
	  if (config.value == ::name(AiType(t))) {
	    this->aitype_set(AiType(t));
	    break;
	  }
	if (t > AITYPE::AITYPE_LAST)
	  cerr << "aiconfig: "
	    << "illegal aitype '" << config.value << "'."
	    << endl;
      } else {
	if (!this->set(config.name, config.value)) {
	  cerr << "aiconfig: "
	    << "illegal config '" << config.name << "'."
	    << endl;
	}
      } // if (config.name == "type")
    } else { // if (config.separator)
      // a setting
      // if the value is in parentencies, remove both
      if(config.name == "!end") {
	// ignore the rest of the file
	break;
      } else if(config.name == "!stdout") {
	// output of the data to 'stdout'
	cout << config.value << endl;
      } else if(config.name == "!stderr") {
	// output of the data to 'stderr'
	cerr << config.value << endl;
      } else if(config.name == "{") {
	depth += 1;
      } else if(config.name == "}") {
	if (depth == 0) {
	  cerr << "Aiconfig: found a '}' without a '{' before.\n"
	    << "Finish reading the the file."
	    << endl;
	  break;
	} // if (depth == 0)
	depth -= 1;
	if (depth == 0)
	  break;
      } else if(config.name == "") {
	cerr << "Aiconfig: "
	  << "Ignoring line \'" << config.value << "\'.\n";
      } else {
	cerr << "Aiconfig: "
	  << "type '" << config.name << "' unknown.\n"
	  << "Ignoring it.\n";
      } // if (config.name == .)
    } // config.separator
  } // while (istr.good())

  DEBUG_RETURNING(istr.good(),
		  INFO_AICONFIG && INFO_INIT,
		  "Aiconfig::load(istr)");
} // bool Aiconfig::load(istream& istr)

/**
 **
 ** save the infos in the file
 **
 ** @param	filename	file to save the aiconfig
 **
 ** @return	whether the saving was successful
 **
 ** @author	Diether Knof
 **
 ** @version	0.5.4
 **
 **/
bool
Aiconfig::save(string const& filename) const
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_INIT,
		"Aiconfig::save(filename)");

  ofstream ostr(filename.c_str());
  if (ostr.fail())
    DEBUG_RETURNING(false,
		    INFO_AICONFIG && INFO_INIT,
		    "Aiconfig::save(filename)");

  ostr << *this;

  DEBUG_RETURNING(ostr.good(),
		  INFO_AICONFIG && INFO_INIT,
		  "Aiconfig::save(filename)");
} // bool Aiconfig::save(string const& filename) const

/**********************************************************************
 *
 ** string name(const Aiconfig::TypeBool& type)
 *
 ** Parameters:  type - the type
 *
 ** Result:      name of the type
 *
 ** Version:     0.4.2
 *
 ** Description: -> result
 *
 **********************************************************************/
string
name(const Aiconfig::TypeBool& type)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"string name(Aiconfig::TypeBool)");

  string name;

  switch(type) {
  case Aiconfig::TRUSTING:
    name = "trusting";
    break;
  case Aiconfig::NO_HEURISTIC:
    name = "no heuristic";
    break;
  case Aiconfig::ONLY_VALID_CARD:
    name = "Heuristics::only valid card";
    break;
  case Aiconfig::CHOOSE_ACE:
    name = "Heuristics::choose_ace";
    break;              
  case Aiconfig::CHOOSE_FOR_COLOR_TRICK:
    name = "Heuristics::choose_for_color_trick";
    break;  
  case Aiconfig::CHOOSE_PFUND:
    name = "Heuristics::choose_pfund";
    break;           
  case Aiconfig::JAB_FOR_ACE:
    name = "Heuristics::jab_for_ace";
    break;             
  case Aiconfig::CREATE_FEHL:
    name = "Heuristics::create_fehl";
    break;             
  case Aiconfig::BEST_WINNING:
    name = "Heuristics::best_winning_card";
    break;            
  case Aiconfig::LOW_HIGH:
    name = "Heuristics::play_low_high";
    break;                     
  case Aiconfig::PLAY_FOR_TEAM:
    name = "Heuristics::play_for_team";
    break;           
  case Aiconfig::JAB_FOX:
    name = "Heuristics::jab_fox";
    break;                 
  case Aiconfig::DRAW_TRUMP:
    name = "Heuristics::draw_trump";
    break;                 
    
  case Aiconfig::MEATLESS_PLAYHIGHESTCOLOR:
    name = "Meatless: Heuristics::play_highest_color";
    break;        
  case Aiconfig::PICTURE_SECONDBESTTRUMP:
    name = "picture: Heuristics::second_best_trump";
    break;
  case Aiconfig::COLOR_CHOOSE_ACE:
    name = "color: Heuristics::choose_ace";
    break;
  case Aiconfig::COLOR_BEST_WINNING:
    name = "color: Heuristics::Best_Winning";
    break;
  case Aiconfig::COLOR_JAB_FOR_ACE:
    name = "color: Heuristics::jab_for_ace";
    break;
  case Aiconfig::COLOR_LOW_HIGH:
    name = "color: Heuristics::play_low_high";
    break;
  case Aiconfig::FEHLCREATIONONFIRSTCARD:
    name = "first card fehl creation";
    break;
  case Aiconfig::FAIRPLAYHANDS:
    name = "fairplay hands";
    break;
  case Aiconfig::FAIRPLAYTEAMS:
    name = "fairplay teams";
    break;
  case Aiconfig::CHOOSE_BEST_CARD:
    name = "choose best card";
    break;
  } // switch(type)

  DEBUG_RETURNING(name,
		  INFO_AICONFIG && INFO_VALUE,
		  "string name(Aiconfig::TypeBool)");
} // string name(const Aiconfig::TypeBool& type)

/**********************************************************************
 *
 ** string name(const Aiconfig::TypeUnsigned& type)
 *
 ** Parameters:  type - the type
 *
 ** Result:      name of the type
 *
 ** Version:     0.4.2
 *
 ** Description: -> result
 *
 **********************************************************************/
string
name(const Aiconfig::TypeUnsigned& type)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"string name(Aiconfig::TypeUnsigned)");

  string name;

  switch(type) {
  case Aiconfig::REMEMBERTRICKS:
    name = "remember tricks";
    break;
  case Aiconfig::LIMITQUEEN:
    name = "limit queen";
    break;
  case Aiconfig::LIMITDOLLE:
    name = "limit dolle";
    break;
  case Aiconfig::LASTFEHLCREATION:
    name = "last fehlcreation";
    break;
  case Aiconfig::LASTHEURISTICTRICK:
    name = "last trick with heuristics";
    break;
  case Aiconfig::ANNOUNCELIMIT:
    name = "announce limit";
    break;
  case Aiconfig::ANNOUNCELIMITDEC:
    name = "announce limit decrement";
    break;
  case Aiconfig::ANNOUNCECONFIG:
    name = "announce config";
    break;  
  case Aiconfig::ANNOUNCELIMITREPLY:
    name = "announce limit reply";
    break;
  case Aiconfig::ANNOUNCECONFIGREPLY:
    name = "announce config reply";
    break;  
  
  case Aiconfig::TAKEPOVERTY:
    name = "take poverty";
    break;
  case Aiconfig::SINGLESOLO:
    name = "handvalue single solo";
    break;
  case Aiconfig::DOUBLESOLO:
    name = "handvalue double solo";
    break;
  case Aiconfig::TRIPLESOLO:
    name = "handvalue trible solo";
    break;
  case Aiconfig::COLORSOLO:
    name = "handvalue color solo";
    break;
  case Aiconfig::MEATLESS:
    name = "handvalue meatless";
    break;
  case Aiconfig::FUTURE_LIMIT:
    name = "future calculating limit";
    break;
  } // switch(type)

  DEBUG_RETURNING(name,
		  INFO_AICONFIG && INFO_VALUE,
		  "string name(Aiconfig::TypeUnsigned)");
} // string name(const Aiconfig::TypeUnsigned& type)

/**********************************************************************
 *
 ** string name(const Aiconfig::TypeCard& type)
 *
 ** Parameters:  type - the type
 *
 ** Result:      name of the type
 *
 ** Version:     0.4.2
 *
 ** Description: -> result
 *
 **********************************************************************/
string
name(const Aiconfig::TypeCard& type)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_VALUE,
		"string name(Aiconfig::TypeCard)");

  string name;

  switch(type) {
  case Aiconfig::LIMITTHROWING:
    name = "limit throwing";
    break;
  case Aiconfig::LIMITHIGH:
    name = "limit high";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOCOLOR:
    name = "trump limit color";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOJACK:
    name = "trump limit jack";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOQUEEN:
    name = "trump limit queen";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOKING:
    name = "trump limit king";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOJACKKING:
    name = "trump limit jack king";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOJACKQUEEN:
    name = "trump limit jack queen";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOQUEENKING:
    name = "trump limit queen king";
    break;
  case Aiconfig::TRUMPLIMIT_SOLOKOEHLER:
    name = "trump limit koehler";
    break;
  case Aiconfig::TRUMPLIMIT_MEATLESS:
    name = "trump limit meatless";
    break;
  case Aiconfig::TRUMPLIMIT_NORMAL:
    name = "trump limit normal";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOCOLOR:
    name = "lowest trump limit color";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOJACK:
    name = "lowest trump limit jack";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOQUEEN:
    name = "lowest trump limit queen";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOKING:
    name = "lowest trump limit king";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOJACKKING:
    name = "lowest trump limit ajck king";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOJACKQUEEN:
    name = "lowest trump limit jack queen";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOQUEENKING:
    name = "lowest trump limit queen king";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_SOLOKOEHLER:
    name = "lowest trump limit koehler";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_MEATLESS:
    name = "lowest trump limit meatless";
    break;
  case Aiconfig::LOWEST_TRUMPLIMIT_NORMAL:
    name = "lowest trump limit normal";
    break;
  } // switch(type)

  DEBUG_RETURNING(name,
		  INFO_AICONFIG && INFO_VALUE,
		  "string name(Aiconfig::TypeCard)");
} // string name(const Aiconfig::TypeCard& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, const Aiconfig::TypeBool& type)
 *
 ** Parameters:  ostr - ouput stream
 **              type - the type
 *
 ** Result:      output stream
 *
 ** Version:     0.4.2
 *
 ** Description: prints the name of the type in the ouput stream
 *
 **********************************************************************/
ostream&
operator<<(ostream& ostr, const Aiconfig::TypeBool& type)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_IO,
		"operator<<(ostream, Aiconfig::TypeBool)");

  ostr << name(type);

  DEBUG_RETURNING(ostr,
		  INFO_AICONFIG && INFO_IO,
		  "operator<<(ostream, Aiconfig::TypeBool)");
} // ostream& operator<<(ostream& ostr, const Aiconfig::TypeBool& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, const Aiconfig::TypeUnsigned& type)
 *
 ** Parameters:  ostr - ouput stream
 **              type - the type
 *
 ** Result:      output stream
 *
 ** Version:     0.4.2
 *
 ** Description: prints the name of the type in the ouput stream
 *
 **********************************************************************/
ostream&
operator<<(ostream& ostr, const Aiconfig::TypeUnsigned& type)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_IO,
		"operator<<(ostream, Aiconfig::TypeUnsigned)");

  ostr << name(type);

  DEBUG_RETURNING(ostr,
		  INFO_AICONFIG && INFO_IO,
		  "operator<<(ostream, Aiconfig::TypeUnsigned)");
} // ostream& operator<<(ostream& ostr, const Aiconfig::TypeUnsigned& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, const Aiconfig::TypeCard& type)
 *
 ** Parameters:  ostr - ouput stream
 **              type - the type
 *
 ** Result:      output stream
 *
 ** Version:     0.4.2
 *
 ** Description: prints the name of the type in the ouput stream
 *
 **********************************************************************/
ostream&
operator<<(ostream& ostr, const Aiconfig::TypeCard& type)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_IO,
		"operator<<(ostream, Aiconfig::TypeCard)");

  ostr << name(type);

  DEBUG_RETURNING(ostr,
		  INFO_AICONFIG && INFO_IO,
		  "operator<<(ostream, Aiconfig::TypeCard)");
} // ostream& operator<<(ostream& ostr, const Aiconfig::TypeCard& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, const Aiconfig& aiconfig)
 *
 ** Parameters:  ostr - ouput stream
 **              aiconfig - aiconfigs
 *
 ** Result:      output stream
 *
 ** Version:     0.4.2
 *
 ** Description: prints the aiconfigs in the ouput stream
 *
 **********************************************************************/

ostream&
operator<<(ostream& ostr, const Aiconfig& aiconfig)
{
  DEBUG_CALLING(INFO_AICONFIG && INFO_IO,
		"operator<<(ostream, aiconfig)");

  aiconfig.out(ostr);

  DEBUG_RETURNING(ostr,
		  INFO_AICONFIG && INFO_IO,
		  "operator<<(ostream, aiconfig)");
} // ostream& operator<<(ostream& ostr, const Aiconfig& aiconfig)


/**********************************************************************
 *
 ** string name(AiType const& type)
 *
 ** Parameters:  aitype - the aitype
 *
 ** Result:  name of the aitype
 *
 ** Version: 0.4.2
 *
 ** Description: -> result
 *
 **********************************************************************/
string
name(AiType const& aitype)
{
  DEBUG_CALLING(INFO_BASISTYPES && INFO_AICONFIG,
		"ostream& operator<<(ostream& ostr, AiType const& aitype)");

  using namespace AITYPE;

  string name;

  switch(aitype) {
  case NO_CHOOSEBESTCARD:
    name = "no choosebestcard";
    break;
  case RANDOM:
    name = "random";
    break;
  case VIRTUAL_GAMES:
    name = "virtual games";
    break;
  case GAMETREE:
    name = "gametree";
    break;
  case GAMETREE_WITH_HEURISTICS:
    name = "gametree with heuristics";
    break;
  case MONTE_CARLO:
    name = "monte carlo";
    break;

  } // switch(aitype)

  DEBUG_RETURNING(name,
		  INFO_BASISTYPES && INFO_AICONFIG,
		  "ostream& operator<<(ostream& ostr, AiType const& aitype)");
} // string name(AiType const& aitype)


/**********************************************************************
 *
 **    ostream& operator<<(ostream& ostr, AiType const& t)
 *
 **    Parameters:  output stream and AiType to be printed
 *
 **    Result: 
 *
 **    Version: Alpha
 *
 **    Description: 
 *
 **********************************************************************/
ostream&
operator<<(ostream& ostr, AiType const& aitype)
{
  DEBUG_CALLING(INFO_BASISTYPES && INFO_IO && INFO_AICONFIG,
		"ostream& operator<<(ostream& ostr, AiType const& aitype)");

  ostr << name(aitype);

  DEBUG_RETURNING(ostr,
		  INFO_BASISTYPES && INFO_IO && INFO_AICONFIG,
		  "ostream& operator<<(ostream& ostr, AiType const& aitype)");
} // ostream operator<<(ostream, aitype);
