/********************************************************************** * * FreeDoko a Doppelkopf-Game * * Copyright (C) 2001-2007 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::MAX_NUMBER_OF_POVERTY_TRUMPS = 3; /** ** constructor ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.3 **/ Rule::Rule() : bool_p(BOOL_NUMBER), unsigned_p(UNSIGNED_NUMBER), counting_(COUNTING_NS::PLUS) { this->reset_to_hardcoded(); return ; } // Rule::Rule() /** ** resets the rules to the default values ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.3 **/ void Rule::reset_to_hardcoded() { this->set(UNSUPPORTED, 0); this->set(MUTATE, false); 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(BOCK, true); this->set(BOCK_APPEND, false); this->set(BOCK_120, true); this->set(BOCK_SOLO_LOST, false); this->set(BOCK_RE_LOST, false); this->set(BOCK_HEART_TRICK, false); this->set(BOCK_BLACK, false); this->set(THROW_WITH_NINES, true); this->set(MIN_NUMBER_OF_THROWING_NINES, 5); this->set(THROW_WITH_KINGS, false); this->set(MIN_NUMBER_OF_THROWING_KINGS, 5); this->set(THROW_WITH_NINES_AND_KINGS, false); this->set(MIN_NUMBER_OF_THROWING_NINES_AND_KINGS, 7); this->set(POVERTY, true); this->set(POVERTY_SHIFT, true); this->set(POVERTY_SHIFT_ONLY_TRUMP, false); this->set(POVERTY_FOX_DO_NOT_COUNT, false); this->set(POVERTY_FOX_SHIFT_EXTRA, false); this->set(POVERTY_FOX_SHIFT_OPEN, 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(DOLLEN_FIRST_OVER_SECOND_WITH_SWINES, 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(SWINES_AND_HYPERSWINES_JOINT, 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_TILL_FULL_TRICK, false); this->set(ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS, true); this->set(ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS_ONLY_FIRST, false); 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(ANNOUNCEMENT_CONTRA_DOUBLES_AGAINST_RE, false); 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); this->set(COUNTING, COUNTING_NS::PLUS); return ; } // void Rule::reset_to_hardcoded() /** ** resets the rules to the values for the seed statistics ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.3 **/ void Rule::reset_to_seed_statistics() { this->set(THROW_WITH_NINES, true); this->set(MIN_NUMBER_OF_THROWING_NINES, 5); this->set(THROW_WITH_KINGS, true); this->set(MIN_NUMBER_OF_THROWING_KINGS, 5); this->set(THROW_WITH_NINES_AND_KINGS, true); this->set(MIN_NUMBER_OF_THROWING_NINES_AND_KINGS, 7); this->set(POVERTY, true); this->set(POVERTY_SHIFT, true); this->set(POVERTY_FOX_DO_NOT_COUNT, true); this->set(POVERTY_FOX_SHIFT_EXTRA, true); this->set(THROW_WHEN_FOX_HIGHEST_TRUMP, true); 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(SWINES, true); this->set(HYPERSWINES, true); return ; } // void Rule::reset_to_seed_statistics() /** ** copy constructor ** ** @param rule rule to copy ** ** @return - ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ Rule::Rule(Rule const& rule): bool_p(rule.bool_p), unsigned_p(rule.unsigned_p), counting_(rule.counting_) { return ; } // Rule::Rule(Rule const& rule) const /** ** copy operator ** ** @param rule rule to copy ** ** @return rule ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ Rule& Rule::operator=(Rule const& 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))); this->set(COUNTING, this->counting()); return *this; } // bool Rule::operator=(Rule const& rule) const /** ** -> result ** ** @param type rule type ** ** @return the value of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ bool Rule::operator()(TypeBool const& type) const { return (this->dependencies(type) && this->value(type)); } // bool Rule::operator()(TypeBool const& type) const /** ** -> result ** ** @param type rule type ** ** @return the value of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ unsigned Rule::operator()(TypeUnsigned const& type) const { switch(type) { case NUMBER_OF_DUTY_SOLI: if (this->dependencies(type)) return this->value(type); else return 0; default: return this->value(type); } // switch(type) DEBUG_ASSERT(false); return 0; } // unsigned Rule::operator()(TypeUnsigned const& type) const /** ** -> result ** ** @param type rule type ** ** @return the value of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ unsigned Rule::operator()(TypeUnsignedExtra const& type) const { switch(type) { case Rule::NUMBER_OF_SAME_CARDS: return ((*this)(NUMBER_OF_PLAYERS_IN_GAME) / 2); case Rule::NUMBER_OF_CARD_COLORS: return Card::NUMBER_OF_COLORS; case Rule::NUMBER_OF_CARD_TCOLORS: return Card::NUMBER_OF_TCOLORS; case Rule::NUMBER_OF_CARD_VALUES: return Card::NUMBER_OF_VALUES + ((*this)(WITH_NINES) ? 0 : -1); case Rule::NUMBER_OF_CARDS: return ((*this)(NUMBER_OF_SAME_CARDS) * (*this)(NUMBER_OF_CARD_COLORS) * (*this)(NUMBER_OF_CARD_VALUES)); case Rule::NUMBER_OF_TEAMS: return 2; case Rule::NUMBER_OF_PLAYERS_PER_TEAM: return (*this)(NUMBER_OF_PLAYERS_IN_GAME) / (*this)(NUMBER_OF_TEAMS); case Rule::MAX_NUMBER_OF_TRICKS_IN_GAME: return 2 * Card::NUMBER_OF_VALUES * Card::NUMBER_OF_COLORS / 4; case Rule::NUMBER_OF_TRICKS_IN_GAME: return (*this)(NUMBER_OF_CARDS) / (*this)(NUMBER_OF_PLAYERS_IN_GAME); case Rule::POINTS_FOR_DOPPELKOPF: return 40; } // switch(type) DEBUG_ASSERT(false); return 0; } // unsigned Rule::operator()(TypeUnsignedExtra const& type) const /** ** -> result ** ** @param type rule type ** ** @return the value of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ Counting Rule::operator()(TypeCounting const& type) const { return this->counting(); } // Counting Rule::operator()(TypeCounting const& type) const /** ** -> result ** ** @param game_type gametype ** ** @return whether the rule 'game_typ' is valid ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ bool Rule::operator()(GameType const& game_type) const { switch(game_type) { case GAMETYPE::NORMAL: return true; case GAMETYPE::THROWN_NINES: return (*this)(THROW_WITH_NINES); case GAMETYPE::THROWN_KINGS: return (*this)(THROW_WITH_KINGS); case GAMETYPE::THROWN_NINES_AND_KINGS: return (*this)(THROW_WITH_NINES_AND_KINGS); case GAMETYPE::FOX_HIGHEST_TRUMP: return (*this)(THROW_WHEN_FOX_HIGHEST_TRUMP); case GAMETYPE::POVERTY: return (*this)(POVERTY); case GAMETYPE::GENSCHER: return (*this)(GENSCHER); case GAMETYPE::MARRIAGE: case GAMETYPE::MARRIAGE_SOLO: case GAMETYPE::MARRIAGE_SILENT: return true; case GAMETYPE::SOLO_JACK: return (*this)(SOLO_JACK); case GAMETYPE::SOLO_QUEEN: return (*this)(SOLO_QUEEN); case GAMETYPE::SOLO_KING: return (*this)(SOLO_KING); case GAMETYPE::SOLO_QUEEN_JACK: return (*this)(SOLO_QUEEN_JACK); case GAMETYPE::SOLO_KING_JACK: return (*this)(SOLO_KING_JACK); case GAMETYPE::SOLO_KING_QUEEN: return (*this)(SOLO_KING_QUEEN); case GAMETYPE::SOLO_KOEHLER: return (*this)(SOLO_KOEHLER); case GAMETYPE::SOLO_CLUB: case GAMETYPE::SOLO_SPADE: case GAMETYPE::SOLO_HEART: case GAMETYPE::SOLO_DIAMOND: return (*this)(SOLO_COLOR); case GAMETYPE::SOLO_MEATLESS: return (*this)(SOLO_MEATLESS); } // switch(game_type) DEBUG_ASSERT(false); return false; } // bool Rule::operator()(GameType const& game_type) const /** ** -> result ** ** @param marriage_selector ** ** @return whether the 'marriage_selector' is valid ** ** @author Diether Knof ** ** @version 0.6.7 **/ bool Rule::operator()(MarriageSelector const& marriage_selector) const { switch(marriage_selector) { case MARRIAGE_SELECTOR::SILENT: case MARRIAGE_SELECTOR::TEAM_SET: return false; case MARRIAGE_SELECTOR::FIRST_FOREIGN: return (*this)(MARRIAGE_FIRST_FOREIGN); case MARRIAGE_SELECTOR::FIRST_TRUMP: return (*this)(MARRIAGE_FIRST_TRUMP); case MARRIAGE_SELECTOR::FIRST_COLOR: return (*this)(MARRIAGE_FIRST_COLOR); case MARRIAGE_SELECTOR::FIRST_CLUB: case MARRIAGE_SELECTOR::FIRST_SPADE: case MARRIAGE_SELECTOR::FIRST_HEART: return (*this)(MARRIAGE_FIRST_SINGLE_COLOR); } // switch(marriage_selector) DEBUG_ASSERT(false); return false; } // bool Rule::operator()(MarriageSelector const& marriage_selector) const /** ** -> result ** ** @param special_point specialpoint ** ** @return whether the rule 'special_point' is valid ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ bool Rule::operator()(Specialpoint const& special_point) const { switch(special_point) { case SPECIALPOINT::NOSPECIALPOINT: return true; case SPECIALPOINT::CAUGHT_FOX: return (*this)(EXTRAPOINT_CATCH_FOX); case SPECIALPOINT::FOX_LAST_TRICK: return (*this)(EXTRAPOINT_FOX_LAST_TRICK); case SPECIALPOINT::CHARLIE: return (*this)(EXTRAPOINT_CHARLIE); case SPECIALPOINT::CAUGHT_CHARLIE: return (*this)(EXTRAPOINT_CATCH_CHARLIE); case SPECIALPOINT::DOLLE_CAUGHT_DOLLE: return (*this)(EXTRAPOINT_DOLLE_JABS_DOLLE); case SPECIALPOINT::HEART_TRICK: return (*this)(EXTRAPOINT_HEART_TRICK); case SPECIALPOINT::DOPPELKOPF: return true; 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: return true; } // switch(special_point) DEBUG_ASSERT(false); return false; } // bool Rule::operator()(Specialpoint const& special_point) const /** ** -> result ** ** @param announcement ** ** @return how many remaining cards there must be to make the announcement ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ unsigned Rule::remaining_cards(Announcement const& announcement) const { 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: return UINT_MAX; case ANNOUNCEMENT::NO120: return (*this)(Rule::ANNOUNCEMENT_NO_120); case ANNOUNCEMENT::NO90: return (*this)(Rule::ANNOUNCEMENT_NO_90); case ANNOUNCEMENT::NO60: return (*this)(Rule::ANNOUNCEMENT_NO_60); case ANNOUNCEMENT::NO30: return (*this)(Rule::ANNOUNCEMENT_NO_30); case ANNOUNCEMENT::NO0: return (*this)(Rule::ANNOUNCEMENT_NO_0); } // switch(announcement) DEBUG_ASSERT(false); return 0; } // unsigned Rule::remaining_cards(Announcement const& announcement) const /** ** -> result ** ** @param type type ** ** @return whether the dependencies of 'type' are met ** ** @author Diether Knof ** ** @version 0.7.0 **/ bool Rule::dependencies(TypeBool const& type) const { switch(type) { case MUTATE: #ifdef RELEASE return false; #else return true; #endif 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: return true; case CARD_HINT: return true; case TAKE_BACK_TRICKS: return true; case WITH_NINES: return true; case BOCK: return true; case BOCK_APPEND: return (*this)(BOCK); case BOCK_120: return (*this)(BOCK); case BOCK_SOLO_LOST: return (*this)(BOCK); case BOCK_RE_LOST: return (*this)(BOCK); case BOCK_HEART_TRICK: return (*this)(BOCK); case BOCK_BLACK: return (*this)(BOCK); case THROW_WITH_NINES: return (*this)(WITH_NINES); case THROW_WITH_KINGS: return true; case THROW_WITH_NINES_AND_KINGS: return (*this)(WITH_NINES); case POVERTY: return true; case POVERTY_SHIFT: return (*this)(POVERTY); case POVERTY_SHIFT_ONLY_TRUMP: case POVERTY_FOX_SHIFT_OPEN: case THROW_WITH_ONE_TRUMP: return (*this)(POVERTY_SHIFT); case POVERTY_FOX_DO_NOT_COUNT: return (*this)(POVERTY); case POVERTY_FOX_SHIFT_EXTRA: return ( (*this)(POVERTY_FOX_DO_NOT_COUNT) && !(*this)(POVERTY_SHIFT_ONLY_TRUMP) ); case THROW_WHEN_FOX_HIGHEST_TRUMP: return true; case MARRIAGE_FIRST_FOREIGN: case MARRIAGE_FIRST_COLOR: case MARRIAGE_FIRST_SINGLE_COLOR: case MARRIAGE_FIRST_TRUMP: return true; case GENSCHER: return !(!(*this)(WITH_NINES) && (*this)(HYPERSWINES)); case SOLO: return true; 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: return (*this)(SOLO); case DOLLEN: return true; case DOLLEN_SECOND_OVER_FIRST: return (*this)(DOLLEN); case DOLLEN_CONTRARY_IN_LAST_TRICK: return (*this)(DOLLEN); case DOLLEN_FIRST_OVER_SECOND_WITH_SWINES: return ((*this)(DOLLEN) && (*this)(SWINES) && ( (*this)(DOLLEN_SECOND_OVER_FIRST) || (*this)(DOLLEN_CONTRARY_IN_LAST_TRICK))); case SWINES: return true; case SWINES_ANNOUNCEMENT_BEGIN: return ((*this)(SWINES) && !(this->value(SWINE_ONLY_SECOND))); case SWINE_ONLY_SECOND: return ((*this)(SWINES) && !(this->value(SWINES_ANNOUNCEMENT_BEGIN)) && !(this->value(HYPERSWINES))); case SWINES_IN_SOLO: return ((*this)(SWINES) && (*this)(SOLO_COLOR)); case HYPERSWINES: return ((*this)(SWINES) && !(*this)(SWINE_ONLY_SECOND)); #ifdef WORKAROUND // this activated leads to an infinte recursion // && !(!(*this)(WITH_NINES) // && (*this)(GENSCHER))); #endif case HYPERSWINES_ANNOUNCEMENT_BEGIN: return ((*this)(HYPERSWINES) && (*this)(SWINES_ANNOUNCEMENT_BEGIN)); case HYPERSWINES_IN_SOLO: return ((*this)(HYPERSWINES) && (*this)(SWINES_IN_SOLO)); case SWINES_AND_HYPERSWINES_JOINT: return (*this)(HYPERSWINES); case EXTRAPOINT_CATCH_FOX: case EXTRAPOINT_FOX_LAST_TRICK: return true; case EXTRAPOINT_DOUBLE_FOX_LAST_TRICK: return (*this)(EXTRAPOINT_FOX_LAST_TRICK); case EXTRAPOINT_CHARLIE: return true; case EXTRAPOINT_CATCH_CHARLIE: case EXTRAPOINT_DOUBLE_CHARLIE: return (*this)(EXTRAPOINT_CHARLIE); case EXTRAPOINT_CATCH_DOUBLE_CHARLIE: return (*this)(EXTRAPOINT_DOUBLE_CHARLIE); case EXTRAPOINT_DOLLE_JABS_DOLLE: return ((*this)(DOLLEN) && ( (*this)(DOLLEN_SECOND_OVER_FIRST) || (*this)(DOLLEN_CONTRARY_IN_LAST_TRICK) )); case EXTRAPOINT_HEART_TRICK: return ((*this)(DOLLEN) && !(*this)(WITH_NINES)); case ANNOUNCEMENT_TILL_FULL_TRICK: case ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS: case ANNOUNCEMENT_REPLY: return true; case ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS_ONLY_FIRST: return (*this)(ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS); case ANNOUNCEMENT_RE_DOUBLES: return true; case ANNOUNCEMENT_CONTRA_DOUBLES_AGAINST_RE: return (*this)(ANNOUNCEMENT_RE_DOUBLES); case NUMBER_OF_ROUNDS_LIMITED: return true; case POINTS_LIMITED: return ((*this)(COUNTING) != COUNTING_NS::PLUSMINUS); case LUSTSOLO_PLAYER_LEADS: return (*this)(SOLO); } // switch(type) DEBUG_ASSERT(false); return false; } // bool Rule::dependencies(TypeBool) const; /** ** -> result ** ** @param type type ** ** @return whether the dependencies of 'type' are met ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ bool Rule::dependencies(TypeUnsigned const& type) const { switch(type) { case UNSUPPORTED: return true; case MIN_NUMBER_OF_THROWING_NINES: return (*this)(THROW_WITH_NINES); case MIN_NUMBER_OF_THROWING_KINGS: return (*this)(THROW_WITH_KINGS); case MIN_NUMBER_OF_THROWING_NINES_AND_KINGS: return (*this)(THROW_WITH_NINES_AND_KINGS); case SHOW_TRICKS_NUMBER: case MARRIAGE_DETERMINATION: case ANNOUNCEMENT_NO_120: case ANNOUNCEMENT_NO_90: case ANNOUNCEMENT_NO_60: case ANNOUNCEMENT_NO_30: case ANNOUNCEMENT_NO_0: case ANNOUNCEMENT_LAST: return true; case NUMBER_OF_ROUNDS: return (*this)(NUMBER_OF_ROUNDS_LIMITED); case POINTS: return (*this)(POINTS_LIMITED); case NUMBER_OF_DUTY_SOLI: return ((*this)(SOLO) && ((*this)(NUMBER_OF_ROUNDS_LIMITED) || (*this)(POINTS_LIMITED))); case NUMBER_OF_DUTY_COLOR_SOLI: return ((*this)(NUMBER_OF_DUTY_SOLI) > 0); case NUMBER_OF_DUTY_PICTURE_SOLI: return ((*this)(NUMBER_OF_DUTY_SOLI) > 0); case NUMBER_OF_PLAYERS: case NUMBER_OF_PLAYERS_IN_GAME: return true; } // switch(type) DEBUG_ASSERT(false); return false; } // bool Rule::dependencies(TypeUnsigned const& type) const /** ** -> result ** ** @param type type ** ** @return the value of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ bool Rule::value(TypeBool const& type) const { return this->bool_p[type - BOOL_FIRST]; } // bool Rule::value(TypeBool) const; /** ** -> result ** ** @param type type ** ** @return the value of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ unsigned Rule::value(TypeUnsigned const& type) const { return this->unsigned_p[type - UNSIGNED_FIRST]; } // unsigned Rule::value(TypeUnsigned const& type) const /** ** -> result ** ** @param type type ** ** @return the value of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ Counting Rule::value(TypeCounting const& type) const { return this->counting_; } // Counting Rule::value(TypeCounting const& type) const /** ** -> result ** ** @param - ** ** @return the counting ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ Counting const& Rule::counting() const { return this->counting_; } // Counting const& Rule::counting() const /** ** -> result ** ** @param type type ** ** @return the minimal value for 'type' ** ** @author Diether Knof ** ** @version 0.6.7 **/ unsigned Rule::min(TypeUnsigned const& type) const { switch(type) { case UNSUPPORTED: return 0; case SHOW_TRICKS_NUMBER: return 1; case MIN_NUMBER_OF_THROWING_NINES: case MIN_NUMBER_OF_THROWING_KINGS: return ( ( ((*this)(NUMBER_OF_SAME_CARDS) * (*this)(NUMBER_OF_CARD_COLORS)) / (*this)(NUMBER_OF_PLAYERS_IN_GAME)) + 1); case MIN_NUMBER_OF_THROWING_NINES_AND_KINGS: return ( ( 2 * ((*this)(NUMBER_OF_SAME_CARDS) * (*this)(NUMBER_OF_CARD_COLORS)) / (*this)(NUMBER_OF_PLAYERS_IN_GAME)) + 1); case Rule::MARRIAGE_DETERMINATION: return 1; 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: return 1; case Rule::NUMBER_OF_ROUNDS: return 1; case Rule::POINTS: return 1; case Rule::NUMBER_OF_DUTY_SOLI: return ((*this)(NUMBER_OF_DUTY_COLOR_SOLI) + (*this)(NUMBER_OF_DUTY_PICTURE_SOLI)); case Rule::NUMBER_OF_DUTY_COLOR_SOLI: return 0; case Rule::NUMBER_OF_DUTY_PICTURE_SOLI: return 0; case Rule::NUMBER_OF_PLAYERS: return 4; case Rule::NUMBER_OF_PLAYERS_IN_GAME: return 4; } // switch(type) DEBUG_ASSERT(false); return 0; } // unsigned Rule::min(TypeUnsigned const& type) const /** ** -> result ** ** @param type type ** ** @return the maximal value for 'type' ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ unsigned Rule::max(TypeUnsigned const& type) const { switch(type) { case UNSUPPORTED: return UINT_MAX - 1; case SHOW_TRICKS_NUMBER: return (*this)(MAX_NUMBER_OF_TRICKS_IN_GAME); case MIN_NUMBER_OF_THROWING_NINES: case MIN_NUMBER_OF_THROWING_KINGS: return ((*this)(NUMBER_OF_SAME_CARDS) * (*this)(NUMBER_OF_CARD_COLORS)); case MIN_NUMBER_OF_THROWING_NINES_AND_KINGS: return 2 * ((*this)(NUMBER_OF_SAME_CARDS) * (*this)(NUMBER_OF_CARD_COLORS)); case Rule::MARRIAGE_DETERMINATION: return (*this)(MAX_NUMBER_OF_TRICKS_IN_GAME); 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: return (*this)(MAX_NUMBER_OF_TRICKS_IN_GAME); case Rule::NUMBER_OF_ROUNDS: return UINT_MAX - 1; case Rule::POINTS: return UINT_MAX - 1; case Rule::NUMBER_OF_DUTY_SOLI: return ((*this)(NUMBER_OF_ROUNDS) * (*this)(NUMBER_OF_PLAYERS)); case Rule::NUMBER_OF_DUTY_COLOR_SOLI: return ((*this)(NUMBER_OF_DUTY_SOLI) - (*this)(NUMBER_OF_DUTY_PICTURE_SOLI)); case Rule::NUMBER_OF_DUTY_PICTURE_SOLI: return ((*this)(NUMBER_OF_DUTY_SOLI) - (*this)(NUMBER_OF_DUTY_COLOR_SOLI)); case Rule::NUMBER_OF_PLAYERS: return 4; case Rule::NUMBER_OF_PLAYERS_IN_GAME: return (((*this)(NUMBER_OF_PLAYERS) / 2) * 2); } // switch(type) DEBUG_ASSERT(false); return 0; } // unsigned Rule::max(TypeUnsigned const& type) const /** ** -> result ** ** @param - ** ** @return all card colors ** ** @author Diether Knof ** ** @version 0.6.6 ** **/ vector const& Rule::card_colors() const { static vector colors; if (colors.empty()) { colors.push_back(Card::CLUB); colors.push_back(Card::SPADE); colors.push_back(Card::HEART); colors.push_back(Card::DIAMOND); } // if (colors.empty()) DEBUG_ASSERTION((colors.size() == (*this)(NUMBER_OF_CARD_COLORS)), "Rule::cards():\n" " Number of cards is not valid"); return colors; } // vector const& Rule::card_colors() const /** ** -> result ** ** @param - ** ** @return all card values (depending on rule 'with nines') ** ** @author Diether Knof ** ** @version 0.6.6 ** **/ vector const& Rule::card_values() const { static vector values_without_nines; static vector values_with_nines; if (values_without_nines.empty()) { values_without_nines.push_back(Card::ACE); values_without_nines.push_back(Card::KING); values_without_nines.push_back(Card::QUEEN); values_without_nines.push_back(Card::JACK); values_without_nines.push_back(Card::TEN); } // if (values_without_nines.empty()) if (values_with_nines.empty()) { values_with_nines = values_without_nines; values_with_nines.push_back(Card::NINE); } // if (values_with_nines.empty()) vector const& values = ( (*this)(WITH_NINES) ? values_with_nines : values_without_nines ); DEBUG_ASSERTION((values.size() == (*this)(NUMBER_OF_CARD_VALUES)), "Rule::cards():\n" " Number of cards is not valid"); return values; } // vector const& Rule::card_values() const /** ** -> result ** ** @param - ** ** @return all cards (depending on rule 'with nines') ** ** @author Diether Knof ** ** @version 0.6.6 ** **/ vector const& Rule::cards() const { static vector cards_without_nines; static vector cards_with_nines; if (cards_without_nines.empty()) { vector colors; colors.push_back(Card::CLUB); colors.push_back(Card::SPADE); colors.push_back(Card::HEART); colors.push_back(Card::DIAMOND); vector values; values.push_back(Card::ACE); values.push_back(Card::KING); values.push_back(Card::QUEEN); values.push_back(Card::JACK); values.push_back(Card::TEN); for (vector::const_iterator c = colors.begin(); c != colors.end(); ++c) for (vector::const_iterator v = values.begin(); v != values.end(); ++v) cards_without_nines.push_back(Card(*c, *v)); } // if (cards_without_nines.empty()) if (cards_with_nines.empty()) { cards_with_nines = cards_without_nines; vector colors; colors.push_back(Card::CLUB); colors.push_back(Card::SPADE); colors.push_back(Card::HEART); colors.push_back(Card::DIAMOND); for (vector::const_iterator c = colors.begin(); c != colors.end(); ++c) cards_with_nines.push_back(Card(*c, Card::NINE)); } // if (cards_with_nines.empty()) vector const& cards = ( (*this)(WITH_NINES) ? cards_with_nines : cards_without_nines ); DEBUG_ASSERTION((cards.size() == ( (*this)(NUMBER_OF_CARD_COLORS) * (*this)(NUMBER_OF_CARD_VALUES) ) ), "Rule::cards():\n" " Number of cards is not valid:\n" " 'cards.size() = " << cards.size() << " != " << (*this)(NUMBER_OF_CARD_COLORS) << " * " << (*this)(NUMBER_OF_CARD_VALUES) ); return cards; } // vector const& Rule::cards() const /** ** ** sets the rule 'type' to the value 'value' ** ** @param type type ** @param value value ** ** @return - ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ void Rule::set(TypeBool const& type, bool const& value) { if (this->value(type) == value) return ; #ifdef OUTDATED // loading in a game leads now to problems #ifdef RELEASE DEBUG_ASSERTION((::game_status < GAMESTATUS::PARTY_PLAY), "Rule::set(TypeBool, value):\n" " 'game_status' is not valid: " << ::game_status); #endif #endif bool const old_value = this->bool_p[type - BOOL_FIRST]; this->bool_p[type - BOOL_FIRST] = value; switch (type) { case WITH_NINES: #ifdef OUTDATED // DK 2005-02-13 // I think this is a bad idea: // when changing 'with nines' -> 'without nines' -> 'with nines' // it should keep '12' // 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)); #endif 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_changed(type, &old_value); return ; } // void Rule::set(TypeBool, bool); /** ** ** sets the rule 'type' to the value 'value' ** ** @param type type ** @param value value in text form ** ** @return - ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ void Rule::set(TypeBool const& type, string const& value) { 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'. " << "Ignoring" << endl; else this->set(type, (((value == "false") || (value == "no") || (value == "0")) ? false : true)); return ; } // void Rule::set(TypeBool const& type, string const& value) /** ** ** sets the rule 'type' to the value 'value' ** ** @param type type ** @param value value ** ** @return - ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ void Rule::set(TypeUnsigned const& type, unsigned const& value) { if (this->value(type) == value) return ; #ifdef OUTDATED // loading in a game leads now to problems #ifdef RELEASE DEBUG_ASSERTION((::game_status < GAMESTATUS::PARTY_PLAY), "Rule::set(TypeUnsigned, value):\n" " 'game_status' is not valid: " << ::game_status); #endif #endif 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_changed(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) return ; } // void Rule::set(TypeUnsigned const& type, unsigned const& value) /** ** ** sets the rule 'type' to the value 'value' ** ** @param type type ** @param value value in text form ** ** @return - ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ void Rule::set(TypeUnsigned const& type, string const& value) { 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.\n" << "Ignoring" << endl; else this->set(type, number); return ; } // void Rule::set(const TypeUnsigned type, string const& value) /** ** ** sets the rule 'type' to the value 'value' ** ** @param type type ** @param value counting ** ** @return - ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ void Rule::set(TypeCounting const& type, Counting const& value) { if (this->counting_ == value) return ; Counting const old_value = this->counting(); this->counting_ = value; if ( (ui != NULL) && (this == &::party.rule())) { ::ui->rule_changed(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) return ; } // void Rule::set(const TypeCounting type, Counting const& value) /** ** ** sets the rule 'type' to the value 'value' ** ** @param type type ** @param value value in text form ** ** @return - ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ void Rule::set(TypeCounting const& type, string const& value) { if (value == ::name(COUNTING_NS::PLUS)) this->set(type, COUNTING_NS::PLUS); else if (value == ::name(COUNTING_NS::MINUS)) this->set(type, COUNTING_NS::MINUS); else if (value == ::name(COUNTING_NS::PLUSMINUS)) this->set(type, COUNTING_NS::PLUSMINUS); #ifdef WORKAROUND // 0.7.0 name changed else if (value == ::name_old(COUNTING_NS::PLUS)) this->set(type, COUNTING_NS::PLUS); else if (value == ::name_old(COUNTING_NS::MINUS)) this->set(type, COUNTING_NS::MINUS); else if (value == ::name_old(COUNTING_NS::PLUSMINUS)) this->set(type, COUNTING_NS::PLUSMINUS); #endif else cerr << "illegal value '" << value << "' for '" << type << "', " << "must be " << "'" << ::name(COUNTING_NS::PLUS) << "', " << "'" << ::name(COUNTING_NS::MINUS) << "' or " << "'" << ::name(COUNTING_NS::PLUSMINUS) << ".\n" << "Ignoring" << endl; return ; } // void Rule::set(const TypeCounting type, string const& value) /** ** sets the rule 'type' to the value 'value' ** ** @param type name of the type ** @param value value in text form ** ** @return whether the type was found ** ** @version 0.7.3 ** ** @author Diether Knof **/ bool Rule::set(string const& type, string const& 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); return true; } } for (i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; i++) { if (type == name(Rule::TypeUnsigned(i))) { this->set(Rule::TypeUnsigned(i), value); return true; } } if (type == name(COUNTING)) { this->set(Rule::COUNTING, value); return true; } #ifndef OUTDATED // 0.7.2b -> 0.7.3 if (type == "throw with five nines") { this->set(Rule::THROW_WITH_NINES, value); this->set(Rule::MIN_NUMBER_OF_THROWING_NINES, 5); return true; } if (type == "throw with six kings") { this->set(Rule::THROW_WITH_KINGS, value); this->set(Rule::MIN_NUMBER_OF_THROWING_KINGS, 6); return true; } #endif return false; } // bool Rule::set(string const& type, string const& value) /** ** mutate the rule ** change one rule (bool: flip; unsigned: increase/decrease) ** ** @param - ** ** @return - ** ** @author Diether Knof ** ** @version 0.7.0 **/ void Rule::mutate() { int const r = rand() % (UNSIGNED_LAST + 1); // do not mutate all rules if ( (r == NUMBER_OF_PLAYERS) || (r == NUMBER_OF_PLAYERS_IN_GAME) || (r == NUMBER_OF_ROUNDS_LIMITED) || (r == POINTS_LIMITED) || ( (r >= SOLO) && (r <= SOLO_MEATLESS)) ) return ; if ( (r >= BOOL_FIRST) && (r <= BOOL_LAST) ) { TypeBool const type = static_cast(r); cout << "mutate " << type << ": " << this->value(type) << " (" << (*this)(type) << ")" << endl; this->set(type, !this->value(type)); } else if ( (r >= UNSIGNED_FIRST) && (r <= UNSIGNED_LAST) ) { TypeUnsigned const type = static_cast(r); cout << "mutate " << type << ": " << this->value(type) << " (" << (*this)(type) << ")" << endl; unsigned value = this->value(type); if (value != UINT_MAX) { if (rand() % 2 == 0) { if (value > this->min(type)) value -= 1; } else { if (value < this->max(type)) value += 1; } } this->set(type, value); cout << "new value " << type << ": " << this->value(type) << " (" << (*this)(type) << ")" << endl; } else { cout << "mutate " << r << endl; } return ; } // void Rule::mutate() /** ** ** 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.6.7 ** ** @author Diether Knof ** **/ bool Rule::load(string const& file) { { ifstream istr(file.c_str()); if (istr.good()) return this->read(istr); } { ifstream istr((::setting(Setting::PRIVATE_DATA_DIRECTORY) + "/" + ::setting(Setting::RULES_DIRECTORY) + "/" + file).c_str()); if (istr.good()) return this->read(istr); } { ifstream istr((::setting(Setting::PUBLIC_DATA_DIRECTORY) + "/" + ::setting(Setting::RULES_DIRECTORY) + "/" + file).c_str()); if (istr.good()) return this->read(istr); } return false; } // bool Rule::load(string const& file) /** ** load the rules from the given stream ** ** @param istr stream to load the rules from ** ** @return whether the rules could be loaded ** ** @author Diether Knof ** ** @version 0.6.7 **/ bool Rule::read(istream& istr) { this->reset_to_hardcoded(); 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()) return true; } // bool Rule::read(istream& istr) /** ** ** saves the rules in the given file ** ** @param file file to save the rules in ** ** @return whether the rules could be saved ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ bool Rule::save(string const& file) const { ofstream ostr(file.c_str()); if (ostr.good()) { ostr << "# FreeDoko rules (version " << ::version << ")\n" << '\n'; this->write(ostr); } return ostr.good(); } // bool Rule::save(string const& file) const /** ** ** puts the rules in the ouput stream ** ** @param ostr output stream ** ** @return - ** ** @version 0.6.7 ** ** @author Diether Knof ** **/ void Rule::write(ostream& ostr) const { ios_base::fmtflags const flags = ostr.flags(); ostr << boolalpha; if (this->value(MUTATE)) ostr << MUTATE << " = " << this->value(MUTATE) << "\n" << '\n'; ostr << 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" << "\n" << BOCK << " = " << this->value(BOCK) << "\n" << " " << BOCK_APPEND << " = " << this->value(BOCK_APPEND) << "\n" << " " << BOCK_120 << " = " << this->value(BOCK_120) << "\n" << " " << BOCK_SOLO_LOST << " = " << this->value(BOCK_SOLO_LOST) << "\n" << " " << BOCK_RE_LOST << " = " << this->value(BOCK_RE_LOST) << "\n" << " " << BOCK_HEART_TRICK << " = " << this->value(BOCK_HEART_TRICK) << "\n" << " " << BOCK_BLACK << " = " << this->value(BOCK_BLACK) << "\n" << "\n" << THROW_WITH_NINES << " = " << this->value(THROW_WITH_NINES) << "\n" << MIN_NUMBER_OF_THROWING_NINES << " = " << this->value(MIN_NUMBER_OF_THROWING_NINES) << "\n" << THROW_WITH_KINGS << " = " << this->value(THROW_WITH_KINGS) << "\n" << MIN_NUMBER_OF_THROWING_KINGS << " = " << this->value(MIN_NUMBER_OF_THROWING_KINGS) << "\n" << THROW_WITH_NINES_AND_KINGS << " = " << this->value(THROW_WITH_NINES_AND_KINGS) << "\n" << MIN_NUMBER_OF_THROWING_NINES_AND_KINGS << " = " << this->value(MIN_NUMBER_OF_THROWING_NINES_AND_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" << " " << POVERTY_FOX_DO_NOT_COUNT << " = " << this->value(POVERTY_FOX_DO_NOT_COUNT) << "\n" << " " << POVERTY_FOX_SHIFT_EXTRA << " = " << this->value(POVERTY_FOX_SHIFT_EXTRA) << "\n" << " " << POVERTY_FOX_SHIFT_OPEN << " = " << this->value(POVERTY_FOX_SHIFT_OPEN) << "\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" << " " << DOLLEN_FIRST_OVER_SECOND_WITH_SWINES << " = " << this->value(DOLLEN_FIRST_OVER_SECOND_WITH_SWINES) << "\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" << " " << SWINES_AND_HYPERSWINES_JOINT << " = " << this->value(SWINES_AND_HYPERSWINES_JOINT) << "\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_FIRST_TRICK_THIRTY_POINTS_ONLY_FIRST << " = " << this->value(ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS_ONLY_FIRST) << "\n" << ANNOUNCEMENT_RE_DOUBLES << " = " << this->value(ANNOUNCEMENT_RE_DOUBLES) << "\n" << ANNOUNCEMENT_CONTRA_DOUBLES_AGAINST_RE << " = " << this->value(ANNOUNCEMENT_CONTRA_DOUBLES_AGAINST_RE) << "\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_TILL_FULL_TRICK << " = " << this->value(ANNOUNCEMENT_TILL_FULL_TRICK) << "\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_LIMITED << " = " << this->value(POINTS_LIMITED) << "\n" << " " << POINTS << " = " << this->value(POINTS) << "\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" << "\n" << COUNTING << " = " << (*this)(COUNTING) << "\n" ; ostr.flags(flags); return ; } // void Rule::write(ostream& ostr) const /** ** -> result ** ** @param type rule type ** ** @return the name of 'type' ** ** @author Diether Knof ** ** @version 0.7.3 **/ string name(Rule::TypeBool const& type) { switch(type) { case Rule::MUTATE: return "mutate"; case Rule::SHOW_IF_VALID: return "show if valid"; case Rule::SHOW_ALL_HANDS: return "show all hands"; case Rule::SHOW_TRICKS_IN_TRICKPILES: return "show tricks in trickpiles"; case Rule::SHOW_TRICKPILES_POINTS: return "show trickpiles points"; case Rule::SHOW_KNOWN_TEAMS_IN_GAME: return "show known teams in game"; case Rule::SHOW_SOLOPLAYER_IN_GAME: return "show soloplayer in game"; case Rule::CARD_HINT: return "card hint"; case Rule::TAKE_BACK_TRICKS: return "take back tricks"; case Rule::WITH_NINES: return "with nines"; case Rule::BOCK: return "bock"; case Rule::BOCK_APPEND: return "append bock"; case Rule::BOCK_120: return "bock after 120-120"; case Rule::BOCK_SOLO_LOST: return "bock after lost solo"; case Rule::BOCK_RE_LOST: return "bock after lost re/contra"; case Rule::BOCK_HEART_TRICK: return "bock after heart trick"; case Rule::BOCK_BLACK: return "bock after black game"; case Rule::THROW_WITH_NINES: return "throw with nines"; case Rule::THROW_WITH_KINGS: return "throw with kings"; case Rule::THROW_WITH_NINES_AND_KINGS: return "throw with nines and kings"; case Rule::POVERTY: return "poverty"; case Rule::POVERTY_SHIFT: return "poverty shift"; case Rule::POVERTY_SHIFT_ONLY_TRUMP: return "poverty shift only trump"; case Rule::POVERTY_FOX_DO_NOT_COUNT: return "poverty fox do not count"; case Rule::POVERTY_FOX_SHIFT_EXTRA: return "poverty fox shift extra"; case Rule::POVERTY_FOX_SHIFT_OPEN: return "poverty fox shift open"; case Rule::THROW_WITH_ONE_TRUMP: return "throw with one trump"; case Rule::THROW_WHEN_FOX_HIGHEST_TRUMP: return "throw when fox highest trump"; case Rule::MARRIAGE_FIRST_FOREIGN: return "marriage first foreign"; case Rule::MARRIAGE_FIRST_COLOR: return "marriage first color"; case Rule::MARRIAGE_FIRST_SINGLE_COLOR: return "marriage first single color"; case Rule::MARRIAGE_FIRST_TRUMP: return "marriage first trump"; case Rule::GENSCHER: return "genscher"; case Rule::SOLO: return "solo"; case Rule::SOLO_JACK: return "solo jack"; case Rule::SOLO_QUEEN: return "solo queen"; case Rule::SOLO_KING: return "solo king"; case Rule::SOLO_QUEEN_JACK: return "solo queen jack"; case Rule::SOLO_KING_JACK: return "solo king jack"; case Rule::SOLO_KING_QUEEN: return "solo king queen"; case Rule::SOLO_KOEHLER: return "solo koehler"; case Rule::SOLO_COLOR: return "solo color"; case Rule::SOLO_MEATLESS: return "solo meatless"; case Rule::DOLLEN: return "dollen"; case Rule::DOLLEN_SECOND_OVER_FIRST: return "dollen second over first"; case Rule::DOLLEN_CONTRARY_IN_LAST_TRICK: return "dollen contrary in last trick"; case Rule::DOLLEN_FIRST_OVER_SECOND_WITH_SWINES: return "dollen first over second with swines"; case Rule::SWINES: return "swines"; case Rule::SWINES_ANNOUNCEMENT_BEGIN: return "swines announcement begin"; case Rule::SWINE_ONLY_SECOND: return "swine only second"; case Rule::SWINES_IN_SOLO: return "swines in solo"; case Rule::HYPERSWINES: return "hyperswines"; case Rule::HYPERSWINES_ANNOUNCEMENT_BEGIN: return "hyperswines announcement begin"; case Rule::HYPERSWINES_IN_SOLO: return "hyperswines in solo"; case Rule::SWINES_AND_HYPERSWINES_JOINT: return "swines and hyperswines joint"; case Rule::EXTRAPOINT_CATCH_FOX: return "extrapoint catch fox"; case Rule::EXTRAPOINT_FOX_LAST_TRICK: return "extrapoint fox last trick"; case Rule::EXTRAPOINT_DOUBLE_FOX_LAST_TRICK: return "extrapoint double fox last trick"; case Rule::EXTRAPOINT_DOLLE_JABS_DOLLE: return "extrapoint dolle jabs dolle"; case Rule::EXTRAPOINT_HEART_TRICK: return "extrapoint heart trick"; case Rule::EXTRAPOINT_CHARLIE: return "extrapoint charlie"; case Rule::EXTRAPOINT_CATCH_CHARLIE: return "extrapoint catch charlie"; case Rule::EXTRAPOINT_DOUBLE_CHARLIE: return "extrapoint double charlie"; case Rule::EXTRAPOINT_CATCH_DOUBLE_CHARLIE: return "extrapoint catch double charlie"; case Rule::ANNOUNCEMENT_TILL_FULL_TRICK: return "announcement till full trick"; case Rule::ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS: return "announcement first trick thirty points"; case Rule::ANNOUNCEMENT_FIRST_TRICK_THIRTY_POINTS_ONLY_FIRST: return "announcement first trick thirty points only first"; case Rule::ANNOUNCEMENT_REPLY: return "announcement reply"; case Rule::ANNOUNCEMENT_RE_DOUBLES: return "announcement re/contra doubles"; case Rule::ANNOUNCEMENT_CONTRA_DOUBLES_AGAINST_RE: return "announcement contra doubles against re"; case Rule::NUMBER_OF_ROUNDS_LIMITED: return "number of rounds limited"; case Rule::POINTS_LIMITED: return "points limited"; case Rule::LUSTSOLO_PLAYER_LEADS: return "lustsolo player leads"; } // switch(type) DEBUG_ASSERT(false); return ""; } // string name(Rule::TypeBool const& type) /** ** -> result ** ** @param type rule type ** ** @return the name of 'type' ** ** @author Diether Knof ** ** @version 0.7.3 **/ string name(Rule::TypeUnsigned const& type) { switch(type) { case Rule::UNSUPPORTED: return "unsupported"; case Rule::SHOW_TRICKS_NUMBER: return "show tricks number"; case Rule::MIN_NUMBER_OF_THROWING_NINES: return "min number of throwing nines"; case Rule::MIN_NUMBER_OF_THROWING_KINGS: return "min number of throwing kings"; case Rule::MIN_NUMBER_OF_THROWING_NINES_AND_KINGS: return "min number of throwing nines and kings"; case Rule::MARRIAGE_DETERMINATION: return "marriage determination"; case Rule::ANNOUNCEMENT_NO_120: return "announcement no 120"; case Rule::ANNOUNCEMENT_NO_90: return "announcement no 90"; case Rule::ANNOUNCEMENT_NO_60: return "announcement no 60"; case Rule::ANNOUNCEMENT_NO_30: return "announcement no 30"; case Rule::ANNOUNCEMENT_NO_0: return "announcement no 0"; case Rule::ANNOUNCEMENT_LAST: return "last announcement"; case Rule::NUMBER_OF_ROUNDS: return "number of rounds"; case Rule::POINTS: return "points"; case Rule::NUMBER_OF_DUTY_SOLI: return "number of duty soli"; case Rule::NUMBER_OF_DUTY_COLOR_SOLI: return "number of duty color soli"; case Rule::NUMBER_OF_DUTY_PICTURE_SOLI: return "number of duty picture soli"; case Rule::NUMBER_OF_PLAYERS: return "number of players"; case Rule::NUMBER_OF_PLAYERS_IN_GAME: return "number of players in game"; } // switch(type) DEBUG_ASSERT(false); return ""; } // string name(Rule::TypeUnsigned const& type) /** ** -> result ** ** @param type rule type ** ** @return the name of 'type' ** ** @author Diether Knof ** ** @version 0.7.3 **/ string name(Rule::TypeUnsignedExtra const& type) { switch(type) { case Rule::NUMBER_OF_SAME_CARDS: return "number of same cards"; case Rule::NUMBER_OF_CARD_COLORS: return "number of card colors"; case Rule::NUMBER_OF_CARD_TCOLORS: return "number of card tcolors"; case Rule::NUMBER_OF_CARD_VALUES: return "number of card values"; case Rule::NUMBER_OF_CARDS: return "number of cards"; case Rule::NUMBER_OF_TEAMS: return "number of teams"; case Rule::NUMBER_OF_PLAYERS_PER_TEAM: return "number of players per team"; case Rule::MAX_NUMBER_OF_TRICKS_IN_GAME: return "maximal number of tricks in game"; case Rule::NUMBER_OF_TRICKS_IN_GAME: return "number of tricks in game"; case Rule::POINTS_FOR_DOPPELKOPF: return "points for doppelkopf"; } // switch(type) DEBUG_ASSERT(false); return ""; } // string name(Rule::TypeUnsignedExtra const& type) /** ** -> result ** ** @param type rule type ** ** @return the name of 'type' ** ** @author Diether Knof ** ** @version 0.6.7 **/ string name(Rule::TypeCounting const& type) { return "counting"; } // string name(Rule::TypeUnsignedExtra const& type) /** ** -> result ** ** @param counting the counting ** ** @return the name of 'counting' ** ** @author Diether Knof ** ** @version 0.6.7 **/ string name(Counting const& counting) { using namespace COUNTING_NS; switch(counting) { case PLUS: return "plus"; case MINUS: return "minus"; case PLUSMINUS: return "plus-minus"; } // switch(counting) DEBUG_ASSERT(false); return ""; } // string name(Counting const& counting) #ifdef WORKAROUND // 0.7.0 name changed /** ** -> result ** ** @param counting the counting ** ** @return the name of 'counting' ** ** @author Diether Knof ** ** @version 0.6.7 **/ string name_old(Counting const& counting) { using namespace COUNTING_NS; switch(counting) { case PLUS: return "counting: plus"; case MINUS: return "counting: minus"; case PLUSMINUS: return "counting: plus-minus"; } // switch(counting) DEBUG_ASSERT(false); return ""; } // string name(Counting const& counting) #endif // #ifdef WORKAROUND /** ** prints the name of 'type' ** ** @param ostr output stream ** @param type type to print the name of ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.6.7 **/ ostream& operator<<(ostream& ostr, Rule::TypeBool const& type) { ostr << name(type); return ostr; } // ostream& operator<<(ostream& ostr, Rule::TypeBool const& type) /** ** ** prints the name of 'type' ** ** @param ostr output stream ** @param type type to print the name of ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ ostream& operator<<(ostream& ostr, Rule::TypeUnsigned const& type) { ostr << name(type); return ostr; } // ostream& operator<<(ostream& ostr, Rule::TypeUnsigned const& type) /** ** ** prints the name of 'type' ** ** @param ostr output stream ** @param type type to print the name of ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ ostream& operator<<(ostream& ostr, Rule::TypeUnsignedExtra const& type) { ostr << name(type); return ostr; } // ostream& operator<<(ostream& ostr, Rule::TypeUnsignedExtra const& type) /** ** ** prints the name of 'type' ** ** @param ostr output stream ** @param type type to print the name of ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ ostream& operator<<(ostream& ostr, Rule::TypeCounting const& type) { ostr << name(type); return ostr; } // ostream& operator<<(ostream& ostr, Rule::TypeCounting const& type) /** ** ** prints the name of 'counting' ** ** @param ostr output stream ** @param counting counting to print ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ ostream& operator<<(ostream& ostr, Counting const& counting) { ostr << name(counting); return ostr; } // ostream& operator<<(ostream& ostr, Counting const& counting) /** ** ** prints the rule in 'ostr' ** ** @param ostr output stream ** @param rule rule to print ** ** @return output stream ** ** @author Diether Knof ** ** @version 0.6.7 ** **/ ostream& operator<<(ostream& ostr, Rule const& rule) { rule.write(ostr); return ostr; } // ostream& operator<<(ostream& ostr, Rule const& rule) /** ** ** -> result ** ** @param rule1 first rule that is compared ** @param rule2 second rule that is compared ** ** @return whether the two rules are equal (according to value) ** ** @author Diether Knof ** ** @version 0.6.6 ** **/ bool operator==(Rule const& rule1, Rule const& rule2) { for (int i = Rule::BOOL_FIRST; i <= Rule::BOOL_LAST; ++i) if (rule1.value(static_cast(i)) != rule2.value(static_cast(i))) return false; for (int i = Rule::UNSIGNED_FIRST; i <= Rule::UNSIGNED_LAST; ++i) if (rule1.value(static_cast(i)) != rule2.value(static_cast(i))) return false; return true; } // bool operator==(Rule const& rule1, Rule const& rule2) /** ** ** -> result ** ** @param rule1 first rule that is compared ** @param rule2 second rule that is compared ** ** @return whether the two rules are different (according to value) ** ** @author Diether Knof ** ** @version 0.6.6 ** **/ bool operator!=(Rule const& rule1, Rule const& rule2) { return !(rule1 == rule2); } // bool operator!=(Rule const& rule1, Rule const& rule2)