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

#include "../utils/file.h"

#include "party.h"
#include "../ui/ui.h"
#include "../misc/setting.h"
#include "../basistypes.h"


// number of the Type
unsigned const Rule::BOOL_NUMBER = (Rule::BOOL_LAST
				    - Rule::BOOL_FIRST + 1);
unsigned const Rule::UNSIGNED_NUMBER = (Rule::UNSIGNED_LAST
					- Rule::UNSIGNED_FIRST + 1);

unsigned const Rule::MIN_NUMBER_OF_THROWING_NINES = 5;
unsigned const Rule::MIN_NUMBER_OF_THROWING_KINGS = 6;
unsigned const Rule::MAX_NUMBER_OF_POVERTY_TRUMPS = 3;

/**********************************************************************
 *
 ** Rule::Rule()
 *
 ** Parameters:	none
 *
 ** Result:	none
 *
 ** Version:	0.4.1
 *
 ** Description:	Constructor
 *
 **********************************************************************/
Rule::Rule() :
bool_p(BOOL_NUMBER),
unsigned_p(UNSIGNED_NUMBER)
{
  DEBUG_CALLING(INFO_RULE && INFO_INIT,
		"Rule::Rule()");

  this->set(SHOW_IF_VALID,			true);
#ifdef POSTPHONED
  this->set(SHOW_ALL_HANDS,			false);
  this->set(SHOW_TRICKS_NUMBER,			1);
#else
  this->set(SHOW_ALL_HANDS,			true);
  this->set(SHOW_TRICKS_NUMBER,			12);
#endif
  this->set(SHOW_TRICKS_IN_TRICKPILES,		true);
  this->set(SHOW_TRICKPILES_POINTS,		true);
  this->set(SHOW_KNOWN_TEAMS_IN_GAME,		true);
  this->set(SHOW_SOLOPLAYER_IN_GAME,		true);

  this->set(CARD_HINT,				true);
  this->set(TAKE_BACK_TRICKS,			false);

  this->set(WITH_NINES,				true);
  this->set(THROW_WITH_FIVE_NINES,		true);
  this->set(THROW_WITH_SIX_KINGS,		false);

  this->set(POVERTY,				true);
  this->set(POVERTY_SHIFT,			true);

  this->set(POVERTY_SHIFT_ONLY_TRUMP,		false);
  this->set(THROW_WITH_ONE_TRUMP,		false);

  this->set(THROW_WHEN_FOX_HIGHEST_TRUMP,	false);

  this->set(MARRIAGE_DETERMINATION,		12);
  this->set(MARRIAGE_FIRST_FOREIGN,		true);
  this->set(MARRIAGE_FIRST_COLOR,		true);
  this->set(MARRIAGE_FIRST_SINGLE_COLOR,	true);
  this->set(MARRIAGE_FIRST_TRUMP,		true);

  this->set(GENSCHER,				false);

  this->set(SOLO,				true);
  this->set(SOLO_COLOR,				true);
  this->set(SOLO_MEATLESS,			true);
  this->set(SOLO_JACK,				true);
  this->set(SOLO_QUEEN,				true);
  this->set(SOLO_KING,				true);
  this->set(SOLO_QUEEN_JACK,			true);
  this->set(SOLO_KING_JACK,			true);
  this->set(SOLO_KING_QUEEN,			true);
  this->set(SOLO_KOEHLER,			true);

  this->set(DOLLEN,				true);
  this->set(DOLLEN_SECOND_OVER_FIRST,		true);
  this->set(DOLLEN_CONTRARY_IN_LAST_TRICK,	false);

  this->set(SWINES,				true);
  this->set(SWINES_ANNOUNCEMENT_BEGIN,		true);
  this->set(SWINE_ONLY_SECOND,			false);
  this->set(SWINES_IN_SOLO,			true);
  this->set(HYPERSWINES,			false);
  this->set(HYPERSWINES_ANNOUNCEMENT_BEGIN,	true);
  this->set(HYPERSWINES_IN_SOLO,		false);

  this->set(EXTRAPOINT_CATCH_FOX,		true);
  this->set(EXTRAPOINT_FOX_LAST_TRICK,		true);
  this->set(EXTRAPOINT_DOUBLE_FOX_LAST_TRICK,	false);

  this->set(EXTRAPOINT_CHARLIE,			true);
  this->set(EXTRAPOINT_CATCH_CHARLIE,		true);
  this->set(EXTRAPOINT_DOUBLE_CHARLIE,		false);
  this->set(EXTRAPOINT_CATCH_DOUBLE_CHARLIE,	false);

  this->set(EXTRAPOINT_DOLLE_JABS_DOLLE,	false);
  this->set(EXTRAPOINT_HEART_TRICK,		false);

  this->set(ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS,	true);
  this->set(ANNOUNCEMENT_NO_120,		11);
  this->set(ANNOUNCEMENT_NO_90,			 9);
  this->set(ANNOUNCEMENT_NO_60,			 6);
  this->set(ANNOUNCEMENT_NO_30,			 3);
  this->set(ANNOUNCEMENT_NO_0,			 3);
  this->set(ANNOUNCEMENT_LAST,			 3);
  this->set(ANNOUNCEMENT_REPLY,			true);
  this->set(ANNOUNCEMENT_RE_DOUBLES,		true);

  this->set(NUMBER_OF_ROUNDS_LIMITED,		true);
  this->set(NUMBER_OF_ROUNDS,			20);
  this->set(POINTS_LIMITED,			false);
  this->set(POINTS,				40);
  this->set(NUMBER_OF_DUTY_SOLI,		0);
  this->set(NUMBER_OF_DUTY_COLOR_SOLI,		0);
  this->set(NUMBER_OF_DUTY_PICTURE_SOLI,	0);
  this->set(LUSTSOLO_PLAYER_LEADS,		true);

  // *** this->set(PARTY_POINTS_SUMMING,	"plus");

  this->set(NUMBER_OF_PLAYERS,			4);
  this->set(NUMBER_OF_PLAYERS_IN_GAME,		4);

  DEBUG_RETURNING(VOID,
		  INFO_RULE && INFO_INIT,
		  "Rule::Rule()");
} // Rule::Rule()

/**********************************************************************
 *
 ** Rule::Rule(Rule const& rule)
 *
 ** Parameters:	rule	- rule to set equal
 *
 ** Result:	-
 *
 ** Version:	0.4.2
 *
 ** Description:	constructor
 *
 **********************************************************************/
Rule::Rule(Rule const& rule):
bool_p(rule.bool_p),
unsigned_p(rule.unsigned_p)
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::Rule(Rule)");

  DEBUG_RETURNING(VOID,
		  INFO_RULE && INFO_VALUE,
		  "Rule::Rule(Rule)");
} // Rule::Rule(Rule const& rule) const

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

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

  DEBUG_RETURNING(*this,
		  INFO_RULE && INFO_VALUE,
		  "Rule::operator=(Rule)");
} // bool Rule::operator=(Rule const& rule) const

/**********************************************************************
 *
 ** bool operator()(TypeBool const& type)
 *
 ** Parameters:	Ruletype
 *
 ** Result:	whether the rule 'type' is active
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
bool
Rule::operator()(TypeBool const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::operator()(TypeBool)");

  DEBUG_RETURNING(this->dependencies(type) && this->value(type),
		  INFO_RULE && INFO_VALUE,
		  "Rule::operator()(TypeBool)");
} // bool Rule::operator()(TypeBool const& type) const

/**********************************************************************
 *
 ** unsigned operator()(TypeUnsigned const& type)
 *
 ** Parameters:	Ruletype
 *
 ** Result:	whether the rule 'type' is active
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Rule::operator()(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::operator()(TypeUnsigned)");

  DEBUG_RETURNING(this->value(type),
		  INFO_RULE && INFO_VALUE,
		  "Rule::operator()(TypeUnsigned)");
} // unsigned Rule::operator()(TypeUnsigned const& type) const

/**********************************************************************
 *
 ** unsigned operator()(const TypeUnsignedExtra& type)
 *
 ** Parameters:	Ruletype
 *
 ** Result:	value of the rule 'type'
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Rule::operator()(const TypeUnsignedExtra& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::operator()(TypeUnsignedExtra)");

  unsigned value = UINT_MAX;

  switch(type) {
  case Rule::NUMBER_OF_SAME_CARDS:
    value = ((*this)(NUMBER_OF_PLAYERS_IN_GAME) / 2);
    break;
  case Rule::NUMBER_OF_CARD_COLORS:
    value = Card::NUMBER_OF_COLORS;
    break;
  case Rule::NUMBER_OF_CARD_TCOLORS:
    value = Card::NUMBER_OF_TCOLORS;
    break;
  case Rule::NUMBER_OF_CARD_VALUES:
    value = Card::NUMBER_OF_VALUES + ((*this)(WITH_NINES) ? 0 : -1);
    break;
  case Rule::NUMBER_OF_CARDS:
    value = ((*this)(NUMBER_OF_SAME_CARDS)
	     * (*this)(NUMBER_OF_CARD_COLORS) * (*this)(NUMBER_OF_CARD_VALUES));
    break;
  case Rule::NUMBER_OF_TEAMS:
    value = 2;
    break;
  case Rule::NUMBER_OF_PLAYERS_PER_TEAM:
    value = (*this)(NUMBER_OF_PLAYERS_IN_GAME) / (*this)(NUMBER_OF_TEAMS);
    break;
  case Rule::NUMBER_OF_TRICKS_IN_GAME:
    value = (*this)(NUMBER_OF_CARDS) / (*this)(NUMBER_OF_PLAYERS_IN_GAME);
    break;
  } // switch(type)

  DEBUG_RETURNING(value,
		  INFO_RULE && INFO_VALUE,
		  "Rule::operator()(TypeUnsignedExtra)");
} // unsigned Rule::operator()(const TypeUnsignedExtra& type) const

/**********************************************************************
 *
 ** bool Rule::operator()(GameType const& game_type) const
 *
 ** Parameters:	Ruletype
 *
 ** Result:	whether the rule 'game_type' is valid
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
bool
Rule::operator()(GameType const& game_type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::operator()(GameType)");

  bool value = false;

  switch(game_type) {
  case GAMETYPE::NORMAL:
    value = true;
    break; 
  case GAMETYPE::FIVE_NINES:
    value = (*this)(THROW_WITH_FIVE_NINES);
    break;
  case GAMETYPE::SIX_KINGS:
    value = (*this)(THROW_WITH_SIX_KINGS);
    break;
  case GAMETYPE::FOX_HIGHEST_TRUMP:
    value = (*this)(THROW_WHEN_FOX_HIGHEST_TRUMP);
    break;
  case GAMETYPE::POVERTY:
    value = (*this)(POVERTY);
    break;
  case GAMETYPE::GENSCHER:
    value = (*this)(GENSCHER);
    break;
  case GAMETYPE::MARRIAGE:
  case GAMETYPE::MARRIAGE_SOLO:
  case GAMETYPE::MARRIAGE_SILENT:
    value = true;
    break;
  case GAMETYPE::SOLO_JACK:
    value = (*this)(SOLO_JACK);
    break;
  case GAMETYPE::SOLO_QUEEN:
    value = (*this)(SOLO_QUEEN);
    break;
  case GAMETYPE::SOLO_KING:
    value = (*this)(SOLO_KING);
    break;
  case GAMETYPE::SOLO_QUEEN_JACK:
    value = (*this)(SOLO_QUEEN_JACK);
    break;
  case GAMETYPE::SOLO_KING_JACK:
    value = (*this)(SOLO_KING_JACK);
    break;
  case GAMETYPE::SOLO_KING_QUEEN:
    value = (*this)(SOLO_KING_QUEEN);
    break;
  case GAMETYPE::SOLO_KOEHLER:
    value = (*this)(SOLO_KOEHLER);
    break;
  case GAMETYPE::SOLO_CLUB:
  case GAMETYPE::SOLO_SPADE:
  case GAMETYPE::SOLO_HEART:
  case GAMETYPE::SOLO_DIAMOND:
    value = (*this)(SOLO_COLOR);
    break; 
  case GAMETYPE::SOLO_MEATLESS:
    value = (*this)(SOLO_MEATLESS);
    break;
  } // switch(game_type)

  DEBUG_RETURNING(value,
		  INFO_RULE && INFO_VALUE,
		  "Rule::operator()(GameType)");
} // bool Rule::operator()(GameType const& game_type) const

/**********************************************************************
 *
 ** bool Rule::operator()(MarriageSelector const& marriage_selector) const
 *
 ** Parameters:	Ruletype
 *
 ** Result:	whether the rule 'marriage_selector' is valid
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
bool
Rule::operator()(MarriageSelector const& marriage_selector) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::operator()(MarriageSelector)");

  bool value = false;

  switch(marriage_selector) {
  case MARRIAGE_SELECTOR::TEAM_SET:
    value = false;
    break;
  case MARRIAGE_SELECTOR::FIRST_FOREIGN:
    value = (*this)(MARRIAGE_FIRST_FOREIGN);
    break;
  case MARRIAGE_SELECTOR::FIRST_TRUMP:
    value = (*this)(MARRIAGE_FIRST_TRUMP);
    break;
  case MARRIAGE_SELECTOR::FIRST_COLOR:
    value = (*this)(MARRIAGE_FIRST_COLOR);
    break;
  case MARRIAGE_SELECTOR::FIRST_CLUB:
  case MARRIAGE_SELECTOR::FIRST_SPADE:
  case MARRIAGE_SELECTOR::FIRST_HEART:
    value = (*this)(MARRIAGE_FIRST_SINGLE_COLOR);
    break;
  } // switch(marriage_selector)

  DEBUG_RETURNING(value,
		  INFO_RULE && INFO_VALUE,
		  "Rule::operator()(MarriageSelector)");
} // bool Rule::operator()(MarriageSelector const& marriage_selector) const

/**********************************************************************
 *
 ** bool Rule::operator()(Specialpoint const& special_point) const
 *
 ** Parameters:	Ruletype
 *
 ** Result:	whether the rule 'special_point' is valid
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
bool
Rule::operator()(Specialpoint const& special_point) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::operator()(Specialpoint)");

  bool value = false;

  switch(special_point) {
  case SPECIALPOINT::NOSPECIALPOINT:
    value = true;
    break;
  case SPECIALPOINT::CAUGHT_FOX:
    value = (*this)(EXTRAPOINT_CATCH_FOX);
    break;
  case SPECIALPOINT::FOX_LAST_TRICK:
    value = (*this)(EXTRAPOINT_FOX_LAST_TRICK);
    break;
  case SPECIALPOINT::CHARLIE:
    value = (*this)(EXTRAPOINT_CHARLIE);
    break;
  case SPECIALPOINT::CAUGHT_CHARLIE:
    value = (*this)(EXTRAPOINT_CATCH_CHARLIE);
    break;
  case SPECIALPOINT::DOLLE_CAUGHT_DOLLE:
    value = (*this)(EXTRAPOINT_DOLLE_JABS_DOLLE);
    break;
  case SPECIALPOINT::HEART_TRICK:
    value = (*this)(EXTRAPOINT_HEART_TRICK);
    break;
  case SPECIALPOINT::DOPPELKOPF:
    value = true;
    break;

  case SPECIALPOINT::NO120:
  case SPECIALPOINT::NO90:
  case SPECIALPOINT::NO60:
  case SPECIALPOINT::NO30:
  case SPECIALPOINT::NO0:
  case SPECIALPOINT::NO90_WON:
  case SPECIALPOINT::NO60_WON:
  case SPECIALPOINT::NO30_WON:
  case SPECIALPOINT::NO0_WON:
  case SPECIALPOINT::NO120_SAID:
  case SPECIALPOINT::NO90_SAID:
  case SPECIALPOINT::NO60_SAID:
  case SPECIALPOINT::NO30_SAID:
  case SPECIALPOINT::NO0_SAID:
  case SPECIALPOINT::CONTRA_WON:
  case SPECIALPOINT::SOLO:
  case SPECIALPOINT::NO120_REPLY:
  case SPECIALPOINT::NO90_REPLY:
  case SPECIALPOINT::NO60_REPLY:
  case SPECIALPOINT::NO30_REPLY:
  case SPECIALPOINT::NO0_REPLY:
    value = true;
    break;
  } // switch(special_point)

  DEBUG_RETURNING(value,
		  INFO_RULE && INFO_VALUE,
		  "Rule::operator()(Specialpoint)");
} // bool Rule::operator()(Specialpoint const& special_point) const

/**********************************************************************
 *
 ** unsigned Rule::remaining_tricks(Announcement const& announcement) const
 *
 ** Parameters:	announcement - the announcement
 *
 ** Result:	how many remaining tricks there must be
 *		to make the announcement
 *
 ** Version:	0.4.4
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Rule::remaining_tricks(Announcement const& announcement) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::remaining_tricks(Specialpoint)");

  unsigned value = UINT_MAX;

  switch(announcement) {
  case ANNOUNCEMENT::NOANNOUNCEMENT:
  case ANNOUNCEMENT::REPLY:
  case ANNOUNCEMENT::NO120_REPLY:
  case ANNOUNCEMENT::NO90_REPLY:
  case ANNOUNCEMENT::NO60_REPLY:
  case ANNOUNCEMENT::NO30_REPLY:
  case ANNOUNCEMENT::NO0_REPLY:
    break;
  case ANNOUNCEMENT::NO120:
    value = (*this)(Rule::ANNOUNCEMENT_NO_120);
    break;
  case ANNOUNCEMENT::NO90:
    value = (*this)(Rule::ANNOUNCEMENT_NO_90);
    break;
  case ANNOUNCEMENT::NO60:
    value = (*this)(Rule::ANNOUNCEMENT_NO_60);
    break;
  case ANNOUNCEMENT::NO30:
    value = (*this)(Rule::ANNOUNCEMENT_NO_30);
    break;
  case ANNOUNCEMENT::NO0:
    value = (*this)(Rule::ANNOUNCEMENT_NO_0);
    break;
  } // switch(announcement)

  DEBUG_RETURNING(value,
		  INFO_RULE && INFO_VALUE,
		  "Rule::remaining_tricks(Specialpoint)");
} // unsigned Rule::remaining_tricks(Announcement const& announcement) const

/**********************************************************************
 *
 ** bool dependencies(TypeBool const& type) const
 *
 ** Parameters:	Ruletype
 *
 ** Result:	whether the dependencies of the rule 'type' are met
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
bool
Rule::dependencies(TypeBool const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::dependencies(TypeBool)");


  bool value = false;

  switch(type) {

  case SHOW_IF_VALID:
  case SHOW_ALL_HANDS:
  case SHOW_TRICKS_IN_TRICKPILES:
  case SHOW_TRICKPILES_POINTS:
  case SHOW_KNOWN_TEAMS_IN_GAME:
  case SHOW_SOLOPLAYER_IN_GAME:
    value = true;
    break;

  case CARD_HINT:
    value = true;
    break;
  case TAKE_BACK_TRICKS:
    value = true;
    break;

  case WITH_NINES:
    value = true;
    break;
  case THROW_WITH_FIVE_NINES:
    value = (*this)(WITH_NINES);
    break;
  case THROW_WITH_SIX_KINGS:
    value = true;
    break;

  case POVERTY:
    value = true;
    break;
  case POVERTY_SHIFT:
    value = (*this)(POVERTY);
    break;
  case POVERTY_SHIFT_ONLY_TRUMP:
  case THROW_WITH_ONE_TRUMP:
    value = ((*this)(POVERTY)
	     && (*this)(POVERTY_SHIFT));
    break;

  case THROW_WHEN_FOX_HIGHEST_TRUMP:
    value = true;
    break;

  case MARRIAGE_FIRST_FOREIGN:
  case MARRIAGE_FIRST_COLOR:
  case MARRIAGE_FIRST_SINGLE_COLOR:
  case MARRIAGE_FIRST_TRUMP:
    value = true;
    break;

  case GENSCHER:
    value = true;
    break;

  case SOLO:
    value = true;
    break;
  case SOLO_JACK:
  case SOLO_QUEEN:
  case SOLO_KING:
  case SOLO_QUEEN_JACK:
  case SOLO_KING_JACK:
  case SOLO_KING_QUEEN:
  case SOLO_KOEHLER:
  case SOLO_COLOR:
  case SOLO_MEATLESS:
    value = (*this)(SOLO);
    break;

  case DOLLEN:
    value = true;
    break;
  case DOLLEN_SECOND_OVER_FIRST:
    value = (*this)(DOLLEN);
    break;
  case DOLLEN_CONTRARY_IN_LAST_TRICK:
    value = (*this)(DOLLEN);
    break;

  case SWINES:
    value = true;
    break;
  case SWINES_ANNOUNCEMENT_BEGIN:
    value = ((*this)(SWINES)
	     && !(this->value(SWINE_ONLY_SECOND)));
    break;
  case SWINE_ONLY_SECOND:
    value = ((*this)(SWINES)
	     && !(this->value(SWINES_ANNOUNCEMENT_BEGIN))
	     && !(this->value(HYPERSWINES)));
    break;
  case SWINES_IN_SOLO:
    value = ((*this)(SWINES)
	     && (*this)(SOLO));
    break;
  case HYPERSWINES:
    value = ((*this)(SWINES)
	     && !(*this)(SWINE_ONLY_SECOND));
    break;
  case HYPERSWINES_ANNOUNCEMENT_BEGIN:
    value = ((*this)(HYPERSWINES)
	     && (*this)(SWINES_ANNOUNCEMENT_BEGIN));
    break;
  case HYPERSWINES_IN_SOLO:
    value = ((*this)(HYPERSWINES)
	     && (*this)(SWINES_IN_SOLO));
    break;

  case EXTRAPOINT_CATCH_FOX:
  case EXTRAPOINT_FOX_LAST_TRICK:
    value = true;
    break;

  case EXTRAPOINT_DOUBLE_FOX_LAST_TRICK:
    value = (*this)(EXTRAPOINT_FOX_LAST_TRICK);
    break;

  case EXTRAPOINT_CHARLIE:
    value = true;
    break;
  case EXTRAPOINT_CATCH_CHARLIE:
  case EXTRAPOINT_DOUBLE_CHARLIE:
    value = (*this)(EXTRAPOINT_CHARLIE);
    break;
  case EXTRAPOINT_CATCH_DOUBLE_CHARLIE:
    value = (*this)(EXTRAPOINT_DOUBLE_CHARLIE);
    break;

  case EXTRAPOINT_DOLLE_JABS_DOLLE:
    value = ((*this)(DOLLEN)
	     && ( (*this)(DOLLEN_SECOND_OVER_FIRST)
		  || (*this)(DOLLEN_CONTRARY_IN_LAST_TRICK) ));
    break;
  case EXTRAPOINT_HEART_TRICK:
    value = ((*this)(DOLLEN)
	     && !(*this)(WITH_NINES));
    break;

  case ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS:
  case ANNOUNCEMENT_REPLY:
    value = true;
    break;

  case ANNOUNCEMENT_RE_DOUBLES:
    value = true;
    break;

  case NUMBER_OF_ROUNDS_LIMITED:
  case POINTS_LIMITED:
    value = true;
    break;

  case LUSTSOLO_PLAYER_LEADS:
    value = true;
    break;
  } // switch(type)

  DEBUG_RETURNING(value,
		  INFO_RULE && INFO_VALUE,
		  "Rule::dependencies(TypeBool)");
} // bool Rule::dependencies(TypeBool) const;

/**********************************************************************
 *
 ** bool dependencies(TypeUnsigned const& type) const
 *
 ** Parameters:	Ruletype
 *
 ** Result:	whether the dependencies of the rule 'type' are met
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
bool
Rule::dependencies(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::dependencies(TypeUnsigned)");

  bool value = true;

  switch(type) {
  case SHOW_TRICKS_NUMBER:
  case Rule::MARRIAGE_DETERMINATION:
  case Rule::ANNOUNCEMENT_NO_120:
  case Rule::ANNOUNCEMENT_NO_90:
  case Rule::ANNOUNCEMENT_NO_60:
  case Rule::ANNOUNCEMENT_NO_30:
  case Rule::ANNOUNCEMENT_NO_0:
  case Rule::ANNOUNCEMENT_LAST:
    value = true;
    break;

  case Rule::NUMBER_OF_ROUNDS:
    value = (*this)(NUMBER_OF_ROUNDS_LIMITED);
    break;
  case Rule::POINTS:
    value = (*this)(POINTS_LIMITED);
    break;

  case Rule::NUMBER_OF_DUTY_SOLI:
    value = true;
    break;
  case Rule::NUMBER_OF_DUTY_COLOR_SOLI:
    value = ((*this)(NUMBER_OF_DUTY_SOLI) > 0);
    break;

  case Rule::NUMBER_OF_DUTY_PICTURE_SOLI:
    value = ((*this)(NUMBER_OF_DUTY_SOLI) > 0);
    break;

  case Rule::NUMBER_OF_PLAYERS:
  case Rule::NUMBER_OF_PLAYERS_IN_GAME:
    value = true;
    break;
  } // switch(type)

  DEBUG_RETURNING(value,
		  INFO_RULE && INFO_VALUE,
		  "Rule::dependencies(TypeUnsigned)");
} // bool Rule::dependencies(TypeUnsigned const& type) const

/**********************************************************************
 *
 ** bool value(TypeBool const& type)
 *
 ** Parameters:	Ruletype
 *
 ** Result:	the value of the rule 'type'
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
bool
Rule::value(TypeBool const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::value(TypeBool)");

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


/**********************************************************************
 *
 ** unsigned value(TypeUnsigned const& type)
 *
 ** Parameters:	Ruletype
 *
 ** Result:	the value of the rule 'type'
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Rule::value(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::value(TypeUnsigned)");

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

/**********************************************************************
 *
 ** unsigned min(TypeUnsigned const& type)
 *
 ** Parameters:	type	- Ruletype
 *
 ** Result:	the minimal value of the rule 'type'
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Rule::min(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::min(TypeUnsigned)");

  unsigned value = UINT_MAX;

  switch(type) {
  case SHOW_TRICKS_NUMBER:
    value = 1;
    break;
  case Rule::MARRIAGE_DETERMINATION:
    value = 1;
    break;

  case Rule::ANNOUNCEMENT_NO_120:
  case Rule::ANNOUNCEMENT_NO_90:
  case Rule::ANNOUNCEMENT_NO_60:
  case Rule::ANNOUNCEMENT_NO_30:
  case Rule::ANNOUNCEMENT_NO_0:
  case Rule::ANNOUNCEMENT_LAST:
    value = 1;
    break;

  case Rule::NUMBER_OF_ROUNDS:
    value = 1;
    break;
  case Rule::POINTS:
    value = 1;
    break;
  case Rule::NUMBER_OF_DUTY_SOLI:
    value = ((*this)(NUMBER_OF_DUTY_COLOR_SOLI)
	     + (*this)(NUMBER_OF_DUTY_PICTURE_SOLI));
    break;
  case Rule::NUMBER_OF_DUTY_COLOR_SOLI:
    value = 0;
    break;
  case Rule::NUMBER_OF_DUTY_PICTURE_SOLI:
    value = 0;
    break;

  case Rule::NUMBER_OF_PLAYERS:
    value = 4;
    break;
  case Rule::NUMBER_OF_PLAYERS_IN_GAME:
    value = 4;
    break;
  } // switch(type)

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

/**********************************************************************
 *
 ** unsigned max(TypeUnsigned const& type)
 *
 ** Parameters:	type	- Ruletype
 *
 ** Result:	the maximal value of the rule 'type'
 *
 ** Version:	0.4.2
 *
 ** Description:	-> result
 *
 **********************************************************************/
unsigned
Rule::max(TypeUnsigned const& type) const
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::max(TypeUnsigned)");

  unsigned value = UINT_MAX - 1;

  switch(type) {
  case SHOW_TRICKS_NUMBER:
    value = (*this)(NUMBER_OF_TRICKS_IN_GAME);
    break;
  case Rule::MARRIAGE_DETERMINATION:
    value = (*this)(NUMBER_OF_TRICKS_IN_GAME);
    break;

  case Rule::ANNOUNCEMENT_NO_120:
  case Rule::ANNOUNCEMENT_NO_90:
  case Rule::ANNOUNCEMENT_NO_60:
  case Rule::ANNOUNCEMENT_NO_30:
  case Rule::ANNOUNCEMENT_NO_0:
  case Rule::ANNOUNCEMENT_LAST:
    value = (*this)(NUMBER_OF_TRICKS_IN_GAME);
    break;

  case Rule::NUMBER_OF_ROUNDS:
    value = UINT_MAX - 1;
    break;
  case Rule::POINTS:
    value = UINT_MAX - 1;
    break;
  case Rule::NUMBER_OF_DUTY_SOLI:
    value = UINT_MAX - 1;
    break;
  case Rule::NUMBER_OF_DUTY_COLOR_SOLI:
    value = ((*this)(NUMBER_OF_DUTY_SOLI)
	     - (*this)(NUMBER_OF_DUTY_PICTURE_SOLI));
    break;
  case Rule::NUMBER_OF_DUTY_PICTURE_SOLI:
    value = ((*this)(NUMBER_OF_DUTY_SOLI)
	     - (*this)(NUMBER_OF_DUTY_COLOR_SOLI));
    break;

  case Rule::NUMBER_OF_PLAYERS:
    value = 4;
    break;
  case Rule::NUMBER_OF_PLAYERS_IN_GAME:
    value = (((*this)(NUMBER_OF_PLAYERS) / 2) * 2);
    break;
  } // switch(type)

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

/**********************************************************************
 *
 ** bool set(TypeBool const& type, bool const& value)
 *
 ** Parameters:	type - Rule-type
 *		value - new value
 *
 ** Result:	the value of the rule 'type'
 *
 ** Version:	0.4.1
 *
 ** Description:	sets the rule 'type' to the value 'value'
 *
 **********************************************************************/
bool
Rule::set(TypeBool const& type, bool const& value)
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::set(TypeBool)");

  if (this->value(type) == value)
    DEBUG_RETURNING(this->value(type),
		    INFO_RULE && INFO_VALUE,
		    "Rule::set(TypeBool, value)");

  DEBUG_ASSERTION((::game_status <= GAMESTATUS::PARTY_INIT),
		  "Rule::set(TypeBool, value):\n"
		  "  'game_status' is not valid: " << ::game_status);

  bool const old_value = this->bool_p[type - BOOL_FIRST];
  this->bool_p[type - BOOL_FIRST] = value;

  switch (type) {
  case WITH_NINES:
    // if all tricks could be shown set the number to the highest value
    // (normal game: 10 -> 12)
    if ((*this)(NUMBER_OF_PLAYERS_IN_GAME))
      if (this->value(SHOW_TRICKS_NUMBER)
	  == ((*this)(NUMBER_OF_TRICKS_IN_GAME)
	      - (((*this)(NUMBER_OF_CARD_COLORS)
		  * (*this)(NUMBER_OF_SAME_CARDS))
		 / (*this)(NUMBER_OF_PLAYERS_IN_GAME))))
	this->set(SHOW_TRICKS_NUMBER, (*this)(NUMBER_OF_TRICKS_IN_GAME));
    break;
  case MARRIAGE_FIRST_FOREIGN:
  case MARRIAGE_FIRST_COLOR:
  case MARRIAGE_FIRST_SINGLE_COLOR:
  case MARRIAGE_FIRST_TRUMP:
    // if none is set, set 'first color'
    if (!this->value(MARRIAGE_FIRST_FOREIGN)
	&& !this->value(MARRIAGE_FIRST_COLOR)
	&& !this->value(MARRIAGE_FIRST_SINGLE_COLOR)
	&& !this->value(MARRIAGE_FIRST_TRUMP))
      this->set(MARRIAGE_FIRST_COLOR, true);
      break;
  default:
    break;
  } // switch(type)

  if ((::ui != NULL) && (this == &(::party.rule())))
    ::ui->rule_update(type, &old_value);

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

/**********************************************************************
 *
 ** bool Rule::set(const TypeBool type, string const& value)
 *
 ** Parameters:	type - Ruletype
 *		value - new value
 *
 ** Result:	the value of the rule 'type'
 *
 ** Version:	0.4.3
 *
 ** Description:	sets the rule 'type' to the value 'value'
 **   
 **********************************************************************/
bool
Rule::set(const TypeBool type, string const& value)
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::set(TypeBool, string)");

  if ((value != "true")
      && (value != "false")
      && (value != "yes")
      && (value != "no")
      && (value != "0")
      && (value != "1")) {
    cerr << "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_RULE && INFO_VALUE,
		  "Rule::set(TypeBool, string)");
} // bool Rule::set(const TypeBool type, string const& value)

/**********************************************************************
 *
 ** unsigned set(TypeUnsigned const& type, unsigned const& value)
 *
 ** Parameters:	type - Rule-type
 *		value - new value
 *
 ** Result:	the value of the rule 'type'
 *
 ** Version:	0.4.1
 *
 ** Description:	sets the rule 'type' to the value 'value'
 *
 **********************************************************************/
unsigned
Rule::set(TypeUnsigned const& type, unsigned const& value)
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::set(" << type << ", " << value << ")");

  if (this->value(type) == value)
    DEBUG_RETURNING(this->value(type),
		    INFO_RULE && INFO_VALUE,
		    "Rule::set(TypeUnsigned, value)");

  DEBUG_ASSERTION((::game_status <= GAMESTATUS::PARTY_INIT),
		  "Rule::set(TypeUnsigned, value):\n"
		  "  'game_status' is not valid: " << ::game_status);

  unsigned const old_value = this->unsigned_p[type - UNSIGNED_FIRST];
  this->unsigned_p[type - UNSIGNED_FIRST] = value;

  switch(type) {
  case ANNOUNCEMENT_NO_120:
    if (value < this->value(ANNOUNCEMENT_NO_90))
      this->set(ANNOUNCEMENT_NO_90, value);
    break;
  case ANNOUNCEMENT_NO_90:
    if (value > this->value(ANNOUNCEMENT_NO_120))
      this->set(ANNOUNCEMENT_NO_120, value);
    if (value < this->value(ANNOUNCEMENT_NO_60))
      this->set(ANNOUNCEMENT_NO_60, value);
    break;
  case ANNOUNCEMENT_NO_60:
    if (value > this->value(ANNOUNCEMENT_NO_90))
      this->set(ANNOUNCEMENT_NO_90, value);
    if (value < this->value(ANNOUNCEMENT_NO_30))
      this->set(ANNOUNCEMENT_NO_30, value);
    break;
  case ANNOUNCEMENT_NO_30:
    if (value > this->value(ANNOUNCEMENT_NO_60))
      this->set(ANNOUNCEMENT_NO_60, value);
    if (value < this->value(ANNOUNCEMENT_NO_0))
      this->set(ANNOUNCEMENT_NO_0, value);
    break;
  case ANNOUNCEMENT_NO_0:
    if (value > this->value(ANNOUNCEMENT_NO_30))
      this->set(ANNOUNCEMENT_NO_30, value);
    if (value < this->value(ANNOUNCEMENT_LAST))
      this->set(ANNOUNCEMENT_LAST, value);
    break;
  case ANNOUNCEMENT_LAST:
    if (value > this->value(ANNOUNCEMENT_NO_0))
      this->set(ANNOUNCEMENT_NO_0, value);
  default:
    break;
  } // switch(type)

  if ((ui != NULL)
      && (this == &::party.rule())) {
    ::ui->rule_update(type, &old_value);
    // the set-function has to be called again with the same values, 
    // because else the ui could change the values
    this->set(type, value);
  } // if (ui != NULL)

  DEBUG_RETURNING(this->value(type),
		  INFO_RULE && INFO_VALUE,
		  "Rule::set(TypeUnsigned)");
} // unsigned Rule::set(TypeUnsigned const& type, unsigned const& value)

/**********************************************************************
 *
 ** unsigned Rule::set(const TypeUnsigned type, string const& value)
 *
 ** Parameters:	type - Ruletype
 *		value - new value
 *
 ** Result:	the value of the rule 'type'
 *
 ** Version:	0.4.3
 *
 ** Description:	sets the rule 'type' to the value 'value'
 **   
 **********************************************************************/
unsigned
Rule::set(const TypeUnsigned type, string const& value)
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::set(TypeUnsigned, string)");

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

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

/**********************************************************************
 *
 ** void Rule::set(string const& type, string const& value)
 *
 ** Parameters:	type - Ruletype
 *		value - new value
 *
 ** Result:	'true', if rule is valid, otherwise 'false'
 *
 ** Version:	0.4.3
 *
 ** Description:	sets the rule 'type' to the value 'value'
 **   
 **********************************************************************/
bool
Rule::set(string const& type, string const& value)
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"Rule::set(string type, string value)");

  unsigned i;

  for (i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; i++) {
    if (type == name(Rule::TypeBool(i))) {
      this->set(Rule::TypeBool(i), value);
      DEBUG_RETURNING(true,
		      INFO_RULE && INFO_VALUE,
		      "Rule::set(string type, string value)");
    }
  }
  for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++) {
    if (type == name(Rule::TypeUnsigned(i))) {
      this->set(Rule::TypeUnsigned(i), value);
      DEBUG_RETURNING(true,
		      INFO_RULE && INFO_VALUE,
		      "Rule::set(string type, string value)");
    }
  }

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

/**
 **
 ** load the rules from the given stream
 **
 ** @param	istr	stream to load the rules from
 **
 ** @return	whether the rules could be loaded
 **
 ** @version	0.5.2
 **
 ** @author	Diether Knof
 **
 **/
bool
Rule::load(istream& istr)
{
  DEBUG_CALLING(INFO_RULE && INFO_IO,
		"Rule::load(istr)");

  unsigned depth = 0;

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

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

    if (config.separator) {
      // a setting
      if (!this->set(config.name, config.value)) {
	cerr << "rule file:	"
	  << "ignoring unknown rule '" << config.name << "'."
	  << endl;
      }
    } 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 << "Rulefile: 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 << "Rule file: "
	  << "Ignoring line \'" << config.value << "\'.\n";
      } else {
	cerr << "Rule file: "
	  << "Rule '" << config.name << "' unknown.\n"
	  << "Ignoring it.\n";
      } // if (config.name == .)
    } // config.separator
  } // while (istr.good())

  DEBUG_RETURNING(true,
		  INFO_RULE && INFO_IO,
		  "Rule::load(istr)");
} // bool Rule::load(istream& istr)

/**
 **
 ** load the rules from the given file
 ** (or the file in the rules directory)
 **
 ** @param	file	file to load the rules from
 **
 ** @return	whether the rules could be loaded
 **
 ** @version	0.4.5
 **
 ** @author	Diether Knof
 **
 **/
bool
Rule::load(string const& file)
{
  DEBUG_CALLING(INFO_RULE && INFO_IO,
		"Rule::load(file)");

  {
    ifstream istr(file.c_str());
    if (istr.good())
      DEBUG_RETURNING(this->load(istr),
		      INFO_RULE && INFO_IO,
		      "Rule::load(file)");
  }
  {
    ifstream istr((::setting(Setting::PRIVATE_DATA_DIRECTORY)
		   + "/" + ::setting(Setting::RULES_DIRECTORY)
		   + "/" + file).c_str());
    if (istr.good())
      DEBUG_RETURNING(this->load(istr),
		      INFO_RULE && INFO_IO,
		      "Rule::load(file)");
  }
  {
    ifstream istr((::setting(Setting::PUBLIC_DATA_DIRECTORY)
		   + "/" + ::setting(Setting::RULES_DIRECTORY)
		   + "/" + file).c_str());
    if (istr.good())
      DEBUG_RETURNING(this->load(istr),
		      INFO_RULE && INFO_IO,
		      "Rule::load(file)");
  }

  DEBUG_RETURNING(false,
		  INFO_RULE && INFO_IO,
		  "Rule::load(file)");
} // bool Rule::load(string const& file)

/**
 **
 ** saves the rules in the given file
 **
 ** @param	file	file to save the rules in
 **
 ** @return	whether the rules could be saved
 **
 ** @version	0.4.5
 **
 ** @author	Diether Knof
 **
 **/
bool
Rule::save(string const& file) const
{
  DEBUG_CALLING(INFO_RULE && INFO_IO,
		"Rule::save(file)");

  ofstream ostr(file.c_str());
  if (ostr.good())
    this->out(ostr);

  DEBUG_RETURNING(ostr.good(),
		  INFO_RULE && INFO_IO,
		  "Rule::save(file)");
} // bool Rule::save(string const& file) const

/**
 **
 ** puts the rules in the ouput stream
 **
 ** @param	ostr	output stream
 **
 ** @return	output stream
 **
 ** @version	0.4.4
 **
 ** @author	Diether Knof
 **
 **/
ostream&
Rule::out(ostream& ostr) const
{
  DEBUG_CALLING(INFO_RULE && INFO_IO,
		"Rule::out(ostream)");

  ostr << "# FreeDoko rules (version " << VERSION << ")\n"
    << '\n'

    << SHOW_IF_VALID << " = "
    << this->value(SHOW_IF_VALID) << "\n"

    << SHOW_ALL_HANDS << " = "
    << this->value(SHOW_ALL_HANDS) << "\n"

    << SHOW_TRICKS_NUMBER << " = "
    << this->value(SHOW_TRICKS_NUMBER) << "\n"

    << SHOW_TRICKS_IN_TRICKPILES << " = "
    << this->value(SHOW_TRICKS_IN_TRICKPILES) << "\n"

    << SHOW_TRICKPILES_POINTS << " = "
    << this->value(SHOW_TRICKPILES_POINTS) << "\n"

    << SHOW_KNOWN_TEAMS_IN_GAME << " = "
    << this->value(SHOW_KNOWN_TEAMS_IN_GAME) << "\n"

    << SHOW_SOLOPLAYER_IN_GAME << " = "
    << this->value(SHOW_SOLOPLAYER_IN_GAME) << "\n"

    << "\n"

    << CARD_HINT << " = "
    << this->value(CARD_HINT) << "\n"
    << TAKE_BACK_TRICKS << " = "
    << this->value(TAKE_BACK_TRICKS) << "\n"

    << "\n"

    << WITH_NINES << " = "
    << this->value(WITH_NINES) << "\n"

    << THROW_WITH_FIVE_NINES << " = "
    << this->value(THROW_WITH_FIVE_NINES) << "\n"

    << THROW_WITH_SIX_KINGS << " = "
    << this->value(THROW_WITH_SIX_KINGS) << "\n"

    << "\n"

    << POVERTY << " = "
    << this->value(POVERTY) << "\n"
    << POVERTY_SHIFT << " = "
    << this->value(POVERTY_SHIFT) << "\n"
    << POVERTY_SHIFT_ONLY_TRUMP << " = "
    << this->value(POVERTY_SHIFT_ONLY_TRUMP) << "\n"
    << THROW_WITH_ONE_TRUMP << " = "
    << this->value(THROW_WITH_ONE_TRUMP) << "\n"

    << THROW_WHEN_FOX_HIGHEST_TRUMP << " = "
    << this->value(THROW_WHEN_FOX_HIGHEST_TRUMP) << "\n"

    << "\n"

    << MARRIAGE_DETERMINATION << " = "
    << this->value(MARRIAGE_DETERMINATION) << "\n"
    << MARRIAGE_FIRST_FOREIGN << " = "
    << this->value(MARRIAGE_FIRST_FOREIGN) << "\n"
    << MARRIAGE_FIRST_COLOR << " = "
    << this->value(MARRIAGE_FIRST_COLOR) << "\n"
    << MARRIAGE_FIRST_SINGLE_COLOR << " = "
    << this->value(MARRIAGE_FIRST_SINGLE_COLOR) << "\n"
    << MARRIAGE_FIRST_TRUMP << " = "
    << this->value(MARRIAGE_FIRST_TRUMP) << "\n"

    << "\n"

    << GENSCHER << " = "
    << this->value(GENSCHER) << "\n"

    << "\n"

    << SOLO << " = "
    << this->value(SOLO) << "\n"
    << "  "
    << SOLO_JACK << " = "
    << this->value(SOLO_JACK) << "\n"
    << "  "
    << SOLO_QUEEN << " = "
    << this->value(SOLO_QUEEN) << "\n"
    << "  "
    << SOLO_KING << " = "
    << this->value(SOLO_KING) << "\n"
    << "  "
    << SOLO_QUEEN_JACK << " = "
    << this->value(SOLO_QUEEN_JACK) << "\n"
    << "  "
    << SOLO_KING_JACK << " = "
    << this->value(SOLO_KING_JACK) << "\n"
    << "  "
    << SOLO_KING_QUEEN << " = "
    << this->value(SOLO_KING_QUEEN) << "\n"
    << "  "
    << SOLO_KOEHLER << " = "
    << this->value(SOLO_KOEHLER) << "\n"
    << "  "
    << SOLO_COLOR << " = "
    << this->value(SOLO_COLOR) << "\n"
    << "  "
    << SOLO_MEATLESS << " = "
    << this->value(SOLO_MEATLESS) << "\n"

    << "\n"

    << DOLLEN << " = "
    << this->value(DOLLEN) << "\n"
    << "  "
    << DOLLEN_SECOND_OVER_FIRST << " = "
    << this->value(DOLLEN_SECOND_OVER_FIRST) << "\n"
    << "  "
    << DOLLEN_CONTRARY_IN_LAST_TRICK << " = "
    << this->value(DOLLEN_CONTRARY_IN_LAST_TRICK) << "\n"

    << "\n"

    << SWINES << " = "
    << this->value(SWINES) << "\n"
    << "  "
    << SWINES_IN_SOLO << " = "
    << this->value(SWINES_IN_SOLO) << "\n"
    << "  "
    << SWINES_ANNOUNCEMENT_BEGIN << " = "
    << this->value(SWINES_ANNOUNCEMENT_BEGIN) << "\n"
    << "  "
    << SWINE_ONLY_SECOND << " = "
    << this->value(SWINE_ONLY_SECOND) << "\n"

    << HYPERSWINES << " = "
    << this->value(HYPERSWINES) << "\n"
    << "  "
    << HYPERSWINES_IN_SOLO << " = "
    << this->value(HYPERSWINES_IN_SOLO) << "\n"
    << "  "
    << HYPERSWINES_ANNOUNCEMENT_BEGIN << " = "
    << this->value(HYPERSWINES_ANNOUNCEMENT_BEGIN) << "\n"

    << "\n"

    << "# Extrapoints:\n"

    << EXTRAPOINT_CATCH_FOX << " = "
    << this->value(EXTRAPOINT_CATCH_FOX) << "\n"
    << EXTRAPOINT_FOX_LAST_TRICK << " = "
    << this->value(EXTRAPOINT_FOX_LAST_TRICK) << "\n"
    << EXTRAPOINT_DOUBLE_FOX_LAST_TRICK << " = "
    << this->value(EXTRAPOINT_DOUBLE_FOX_LAST_TRICK) << "\n"

    << EXTRAPOINT_DOLLE_JABS_DOLLE << " = "
    << this->value(EXTRAPOINT_DOLLE_JABS_DOLLE) << "\n"
    << EXTRAPOINT_HEART_TRICK << " = "
    << this->value(EXTRAPOINT_HEART_TRICK) << "\n"

    << EXTRAPOINT_CHARLIE << " = "
    << this->value(EXTRAPOINT_CHARLIE) << "\n"
    << EXTRAPOINT_CATCH_CHARLIE << " = "
    << this->value(EXTRAPOINT_CATCH_CHARLIE) << "\n"
    << EXTRAPOINT_DOUBLE_CHARLIE << " = "
    << this->value(EXTRAPOINT_DOUBLE_CHARLIE) << "\n"
    << EXTRAPOINT_CATCH_DOUBLE_CHARLIE << " = "
    << this->value(EXTRAPOINT_CATCH_DOUBLE_CHARLIE) << "\n"


    << "\n"

    << ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS << " = "
    << this->value(ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS) << "\n"

    << ANNOUNCEMENT_RE_DOUBLES << " = "
    << this->value(ANNOUNCEMENT_RE_DOUBLES) << "\n"

    << "\n"

    << "# till when to make the announcements:\n"


    << ANNOUNCEMENT_NO_120 << " = "
    << this->value(ANNOUNCEMENT_NO_120) << "\n"
    << ANNOUNCEMENT_NO_90 << " = "
    << this->value(ANNOUNCEMENT_NO_90) << "\n"
    << ANNOUNCEMENT_NO_60 << " = "
    << this->value(ANNOUNCEMENT_NO_60) << "\n"
    << ANNOUNCEMENT_NO_30 << " = "
    << this->value(ANNOUNCEMENT_NO_30) << "\n"
    << ANNOUNCEMENT_NO_0 << " = "
    << this->value(ANNOUNCEMENT_NO_0) << "\n"
    << ANNOUNCEMENT_LAST << " = "
    << this->value(ANNOUNCEMENT_LAST) << "\n"

    << ANNOUNCEMENT_REPLY << " = "
    << this->value(ANNOUNCEMENT_REPLY) << "\n"

    << NUMBER_OF_ROUNDS_LIMITED << " = "
    << this->value(NUMBER_OF_ROUNDS_LIMITED) << "\n"
    << NUMBER_OF_ROUNDS << " = "
    << this->value(NUMBER_OF_ROUNDS) << "\n"
    << POINTS << " = "
    << this->value(POINTS) << "\n"
    << POINTS_LIMITED << " = "
    << this->value(POINTS_LIMITED) << "\n"
    << NUMBER_OF_DUTY_SOLI << " = "
    << this->value(NUMBER_OF_DUTY_SOLI) << "\n"
    << NUMBER_OF_DUTY_COLOR_SOLI << " = "
    << this->value(NUMBER_OF_DUTY_COLOR_SOLI) << "\n"
    << NUMBER_OF_DUTY_PICTURE_SOLI << " = "
    << this->value(NUMBER_OF_DUTY_PICTURE_SOLI) << "\n"
    << LUSTSOLO_PLAYER_LEADS << " = "
    << this->value(LUSTSOLO_PLAYER_LEADS) << "\n"

    // *** << PARTY_POINTS_SUMMING << " = "
    // *** << this->value(PARTY_POINTS_SUMMING) << "\n"

    << NUMBER_OF_PLAYERS << " = "
    << this->value(NUMBER_OF_PLAYERS) << "\n"

    << NUMBER_OF_PLAYERS_IN_GAME << " = "
    << this->value(NUMBER_OF_PLAYERS_IN_GAME) << "\n"

    << "\n"

    << "# "
    << NUMBER_OF_SAME_CARDS << " = "
    << (*this)(NUMBER_OF_SAME_CARDS) << "\n"
    << "# "
    << NUMBER_OF_CARD_COLORS << " = "
    << (*this)(NUMBER_OF_CARD_COLORS) << "\n"
    << "# "
    << NUMBER_OF_CARD_TCOLORS << " = "
    << (*this)(NUMBER_OF_CARD_TCOLORS) << "\n"
    << "# "
    << NUMBER_OF_CARD_VALUES << " = "
    << (*this)(NUMBER_OF_CARD_VALUES) << "\n"
    << "# "
    << NUMBER_OF_CARDS << " = "
    << (*this)(NUMBER_OF_CARDS) << "\n"
    << "# "
    << NUMBER_OF_TEAMS << " = "
    << (*this)(NUMBER_OF_TEAMS) << "\n"
    << "# "
    << NUMBER_OF_PLAYERS_PER_TEAM << " = "
    << (*this)(NUMBER_OF_PLAYERS_PER_TEAM) << "\n"
    << "# "
    << NUMBER_OF_TRICKS_IN_GAME << " = "
    << (*this)(NUMBER_OF_TRICKS_IN_GAME) << "\n"
    ;

  DEBUG_RETURNING(ostr,
		  INFO_RULE && INFO_IO,
		  "Rule::out(ostream)");
} // ostream& Rule::out(ostream& ostr) const

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

  string name;

  switch(type) {
  case Rule::SHOW_IF_VALID:
    name = "show if valid";
    break;
  case Rule::SHOW_ALL_HANDS:
    name = "show all hands";
    break;
  case Rule::SHOW_TRICKS_IN_TRICKPILES:
    name = "show tricks in trickpiles";
    break;
  case Rule::SHOW_TRICKPILES_POINTS:
    name = "show trickpiles points";
    break;
  case Rule::SHOW_KNOWN_TEAMS_IN_GAME:
    name = "show known teams in game";
    break;
  case Rule::SHOW_SOLOPLAYER_IN_GAME:
    name = "show soloplayer in game";
    break;

  case Rule::CARD_HINT:
    name = "card hint";
    break;
  case Rule::TAKE_BACK_TRICKS:
    name = "take back tricks";
    break;

  case Rule::WITH_NINES:
    name = "with nines";
    break;
  case Rule::THROW_WITH_FIVE_NINES:
    name = "throw with five nines";
    break;
  case Rule::THROW_WITH_SIX_KINGS:
    name = "throw with six kings";
    break;

  case Rule::POVERTY:
    name = "poverty";
    break;
  case Rule::POVERTY_SHIFT:
    name = "poverty shift";
    break;
  case Rule::POVERTY_SHIFT_ONLY_TRUMP:
    name = "poverty shift only trump";
    break;
  case Rule::THROW_WITH_ONE_TRUMP:
    name = "throw with one trump";
    break;

  case Rule::THROW_WHEN_FOX_HIGHEST_TRUMP:
    name = "throw when fox highest trump";
    break;

  case Rule::MARRIAGE_FIRST_FOREIGN:
    name = "marriage first foreign";
    break;
  case Rule::MARRIAGE_FIRST_COLOR:
    name = "marriage first color";
    break;
  case Rule::MARRIAGE_FIRST_SINGLE_COLOR:
    name = "marriage first single color";
    break;
  case Rule::MARRIAGE_FIRST_TRUMP:
    name = "marriage first trump";
    break;

  case Rule::GENSCHER:
    name = "genscher";
    break;

  case Rule::SOLO:
    name = "solo";
    break;
  case Rule::SOLO_JACK:
    name = "solo jack";
    break;
  case Rule::SOLO_QUEEN:
    name = "solo queen";
    break;
  case Rule::SOLO_KING:
    name = "solo king";
    break;
  case Rule::SOLO_QUEEN_JACK:
    name = "solo queen jack";
    break;
  case Rule::SOLO_KING_JACK:
    name = "solo king jack";
    break;
  case Rule::SOLO_KING_QUEEN:
    name = "solo king queen";
    break;
  case Rule::SOLO_KOEHLER:
    name = "solo koehler";
    break;
  case Rule::SOLO_COLOR:
    name = "solo color";
    break;
  case Rule::SOLO_MEATLESS:
    name = "solo meatless";
    break;

  case Rule::DOLLEN:
    name = "dollen";
    break;
  case Rule::DOLLEN_SECOND_OVER_FIRST:
    name = "dollen second over first";
    break;
  case Rule::DOLLEN_CONTRARY_IN_LAST_TRICK:
    name = "dollen contrary in last trick";
    break;

  case Rule::SWINES:
    name = "swines";
    break;
  case Rule::SWINES_ANNOUNCEMENT_BEGIN:
    name = "swines announcement begin";
    break;
  case Rule::SWINE_ONLY_SECOND:
    name = "swine only second";
    break;
  case Rule::SWINES_IN_SOLO:
    name = "swines in solo";
    break;
  case Rule::HYPERSWINES:
    name = "hyperswines";
    break;
  case Rule::HYPERSWINES_ANNOUNCEMENT_BEGIN:
    name = "hyperswines announcement begin";
    break;
  case Rule::HYPERSWINES_IN_SOLO:
    name = "hyperswines in solo";
    break;

  case Rule::EXTRAPOINT_CATCH_FOX:
    name = "extrapoint catch fox";
    break;
  case Rule::EXTRAPOINT_FOX_LAST_TRICK:
    name = "extrapoint fox last trick";
    break;
  case Rule::EXTRAPOINT_DOUBLE_FOX_LAST_TRICK:
    name = "extrapoint double fox last trick";
    break;

  case Rule::EXTRAPOINT_DOLLE_JABS_DOLLE:
    name = "extrapoint dolle jabs dolle";
    break;
  case Rule::EXTRAPOINT_HEART_TRICK:
    name = "extrapoint heart trick";
    break;

  case Rule::EXTRAPOINT_CHARLIE:
    name = "extrapoint charlie";
    break;
  case Rule::EXTRAPOINT_CATCH_CHARLIE:
    name = "extrapoint catch charlie";
    break;
  case Rule::EXTRAPOINT_DOUBLE_CHARLIE:
    name = "extrapoint double charlie";
    break;
  case Rule::EXTRAPOINT_CATCH_DOUBLE_CHARLIE:
    name = "extrapoint catch double charlie";
    break;

  case Rule::ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS:
    name = "announcement first trick thirty points";
    break;

  case Rule::ANNOUNCEMENT_REPLY:
    name = "announcement reply";
    break;
  case Rule::ANNOUNCEMENT_RE_DOUBLES:
    name = "announcement re/contra doubles";
    break;

  case Rule::NUMBER_OF_ROUNDS_LIMITED:
    name = "number of rounds limited";
    break;
  case Rule::POINTS_LIMITED:
    name = "points limited";
    break;

  case Rule::LUSTSOLO_PLAYER_LEADS:
    name = "lustsolo player leads";
    break;
  } // switch(type)

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

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

  string name;

  switch(type) {
  case Rule::SHOW_TRICKS_NUMBER:
    name = "show tricks number";
    break;

  case Rule::MARRIAGE_DETERMINATION:
    name = "marriage determination";
    break;

  case Rule::ANNOUNCEMENT_NO_120:
    name = "announcement no 120";
    break;
  case Rule::ANNOUNCEMENT_NO_90:
    name = "announcement no 90";
    break;
  case Rule::ANNOUNCEMENT_NO_60:
    name = "announcement no 60";
    break;
  case Rule::ANNOUNCEMENT_NO_30:
    name = "announcement no 30";
    break;
  case Rule::ANNOUNCEMENT_NO_0:
    name = "announcement no 0";
    break;
  case Rule::ANNOUNCEMENT_LAST:
    name = "last announcement";
    break;

  case Rule::NUMBER_OF_ROUNDS:
    name = "number of rounds";
    break;
  case Rule::POINTS:
    name = "points";
    break;
  case Rule::NUMBER_OF_DUTY_SOLI:
    name = "number of duty soli";
    break;
  case Rule::NUMBER_OF_DUTY_COLOR_SOLI:
    name = "number of duty color soli";
    break;
  case Rule::NUMBER_OF_DUTY_PICTURE_SOLI:
    name = "number of duty picture soli";
    break;

  case Rule::NUMBER_OF_PLAYERS:
    name = "number of players";
    break;
  case Rule::NUMBER_OF_PLAYERS_IN_GAME:
    name = "number of players in game";
    break;
  } // switch(type)

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

/**********************************************************************
 *
 ** string name(Rule::TypeUnsignedExtra const& type)
 *
 ** Parameters:	type - the type
 *
 ** Result:	name of the type
 *
 ** Version:	0.4.1
 *
 ** Description:	-> result
 *
 **********************************************************************/
string
name(Rule::TypeUnsignedExtra const& type)
{
  DEBUG_CALLING(INFO_RULE && INFO_VALUE,
		"string name(Rule::TypeUnsignedExtra)");

  string name;

  switch(type) {
  case Rule::NUMBER_OF_SAME_CARDS:
    name = "number of same cards";
    break;

  case Rule::NUMBER_OF_CARD_COLORS:
    name = "number of card colors";
    break;
  case Rule::NUMBER_OF_CARD_TCOLORS:
    name = "number of card tcolors";
    break;
  case Rule::NUMBER_OF_CARD_VALUES:
    name = "number of card values";
    break;
  case Rule::NUMBER_OF_CARDS:
    name = "number of cards";
    break;
  case Rule::NUMBER_OF_TEAMS:
    name = "number of teams";
    break;
  case Rule::NUMBER_OF_PLAYERS_PER_TEAM:
    name = "number of players per team";
    break;
  case Rule::NUMBER_OF_TRICKS_IN_GAME:
    name = "number of tricks in game";
    break;
  } // switch(type)

  DEBUG_RETURNING(name,
		  INFO_RULE && INFO_VALUE,
		  "string name(Rule::TypeUnsignedExtra)");
} // string name(Rule::TypeUnsignedExtra const& type)

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

  ostr << name(type);

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

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

  ostr << name(type);

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

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Rule::TypeUnsignedExtra const& type)
 *
 ** Parameters:	ostr - ouput stream
 *		type - the type
 *
 ** Result:	output stream
 *
 ** Version:	0.4.1
 *
 ** Description:	prints the name of the type in the ouput stream
 *
 **********************************************************************/
ostream&
operator<<(ostream& ostr, Rule::TypeUnsignedExtra const& type)
{
  DEBUG_CALLING(INFO_RULE && INFO_IO,
		"operator<<(ostream, Rule::TypeUnsignedExtra)");

  ostr << name(type);

  DEBUG_RETURNING(ostr,
		  INFO_RULE && INFO_IO,
		  "operator<<(ostream, Rule::TypeUnsignedExtra)");
} // ostream& operator<<(ostream& ostr, Rule::TypeUnsignedExtra const& type)

/**********************************************************************
 *
 ** operator<<(ostream& ostr, Rule const& rule)
 *
 ** Parameters:	ostr - ouput stream
 *		rule - rules
 *
 ** Result:	output stream
 *
 ** Version:	0.4.1
 *
 ** Description:	prints the rules in the ouput stream
 *
 **********************************************************************/

ostream&
operator<<(ostream& ostr, Rule const& rule)
{
  DEBUG_CALLING(INFO_RULE && INFO_IO,
		"operator<<(ostream, rule)");

  rule.out(ostr);

  DEBUG_RETURNING(ostr,
		  INFO_RULE && INFO_IO,
		  "operator<<(ostream, rule)");
} // ostream& operator<<(ostream& ostr, Rule const& rule)
