/**********************************************************************
 *
 *   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
 *
 **********************************************************************/

#ifndef CLASS_AICONFIG_HEADER
#define CLASS_AICONFIG_HEADER

#include "../card/card.h"

namespace AITYPE {
  enum AiType {
    AITYPE_FIRST = 0,

    NO_CHOOSEBESTCARD = AITYPE_FIRST,
    RANDOM,
    VIRTUAL_GAMES,
    GAMETREE,
    GAMETREE_WITH_HEURISTICS,
    MONTE_CARLO,

    AITYPE_LAST = MONTE_CARLO
  }; // enum AiType
} // namespace AITYPE
using AITYPE::AiType;
extern AiType aitype;

string name(const AiType& aitype);
ostream& operator<<(ostream& ostr, const AiType& t);


class Aiconfig {
  public:
    enum TypeBool {
      BOOL_FIRST,

      TRUSTING = BOOL_FIRST, // whether the ai is trusting

      NO_HEURISTIC,
      ONLY_VALID_CARD,
      CHOOSE_ACE,              // Heuristics::choose_ace
      CHOOSE_FOR_COLOR_TRICK,  // Heuristics::choose_for_color_trick
      CHOOSE_PFUND,            // Heuristics::choose_pfund 
      JAB_FOR_ACE,             // Heuristics::jab_for-ace
      CREATE_FEHL,             // Heuristics::create_fehl
      BEST_WINNING,            // Heuristics::best_winning_card
      LOW_HIGH,                // Heuristics::play_low_high    
      PLAY_FOR_TEAM,           // Heuristics::play_for_team
      JAB_FOX,                 // Heuristics::jab_fox
      DRAW_TRUMP,             

      MEATLESS_PLAYHIGHESTCOLOR,        // Meatless: Heuristics::play_highest_color
      PICTURE_SECONDBESTTRUMP,

      COLOR_CHOOSE_ACE,
      COLOR_BEST_WINNING,
      COLOR_JAB_FOR_ACE,
      COLOR_LOW_HIGH,

      FAIRPLAYHANDS, // whether the ai takes the current hands of the players
      FAIRPLAYTEAMS, // whether the ai knows the team of the other players

      FEHLCREATIONONFIRSTCARD,
      CHOOSE_BEST_CARD, // for the database

      BOOL_LAST = CHOOSE_BEST_CARD
    }; // enum TypeBool
    static unsigned const BOOL_NUMBER;

    enum TypeUnsigned {
      UNSIGNED_FIRST = BOOL_LAST + 1,

      REMEMBERTRICKS = UNSIGNED_FIRST, // how many tricks are remembered

      LIMITQUEEN, // mininum points per trick for jabbing with a queen
      LIMITDOLLE, // minimum points per trick for jabbing with dollen or higher

      LASTFEHLCREATION, // last trick to create a fehl color
      LASTHEURISTICTRICK,

      ANNOUNCELIMIT, // points of hand for first announcement 
      ANNOUNCELIMITDEC, // points of hand you can lose between two announcements
      ANNOUNCECONFIG, // Parameter for Playerconfiguration of announcements
      ANNOUNCELIMITREPLY, // points of hand for first Reply
      ANNOUNCECONFIGREPLY, // Decrement for each announcment made, when replying 

      TAKEPOVERTY,

      SINGLESOLO, // minimum cardvalue for a solo with only one picture trump
      DOUBLESOLO, // minimum cardvalue for a solo with two pictures trump
      TRIPLESOLO, // minimum cardvalue for a solo with three pictures trump
      COLORSOLO, // minimun cardvalue for playing a colorsolo
      MEATLESS, // minimun cardvalue for playing a fleischlosen

      FUTURE_LIMIT, // number of tricks calculated into the future

      UNSIGNED_LAST = FUTURE_LIMIT
    }; // enum TypeUnsigned
    static unsigned const UNSIGNED_NUMBER;

    enum TypeCard {
      CARD_FIRST = UNSIGNED_LAST + 1,

      LIMITTHROWING = CARD_FIRST, // minimum team mate card for not over jabbing

      TRUMPLIMIT_SOLOCOLOR,
      TRUMPLIMIT_SOLOJACK,
      TRUMPLIMIT_SOLOQUEEN,
      TRUMPLIMIT_SOLOKING,
      TRUMPLIMIT_SOLOJACKKING,
      TRUMPLIMIT_SOLOJACKQUEEN,
      TRUMPLIMIT_SOLOQUEENKING,
      TRUMPLIMIT_SOLOKOEHLER,
      TRUMPLIMIT_MEATLESS,
      TRUMPLIMIT_NORMAL,

      LOWEST_TRUMPLIMIT_SOLOCOLOR,
      LOWEST_TRUMPLIMIT_SOLOJACK,
      LOWEST_TRUMPLIMIT_SOLOQUEEN,
      LOWEST_TRUMPLIMIT_SOLOKING,
      LOWEST_TRUMPLIMIT_SOLOJACKKING,
      LOWEST_TRUMPLIMIT_SOLOJACKQUEEN,
      LOWEST_TRUMPLIMIT_SOLOQUEENKING,
      LOWEST_TRUMPLIMIT_SOLOKOEHLER,
      LOWEST_TRUMPLIMIT_MEATLESS,
      LOWEST_TRUMPLIMIT_NORMAL,

      LIMITHIGH, // minimum team mate card for throwing a ten or ace unsignedo this trick

      CARD_LAST = LIMITHIGH
    }; // enum TypeCard
    static unsigned const CARD_NUMBER;



  public:
    friend class Ai;

  public:
    Aiconfig();
    Aiconfig(istream& istr);
    Aiconfig(Aiconfig const& aiconfig);
    Aiconfig& operator=(Aiconfig const& aiconfig);
    ~Aiconfig();

    void reset_to_hardcoded();

    AiType const& aitype() const;
    AiType const& aitype_set(AiType const& aitype);

    // returns the value
    bool value(const TypeBool& type) const;
    unsigned value(const TypeUnsigned& type) const;
    Card value(const TypeCard& type) const;

    // the minimum and maximum value
    unsigned min(const TypeUnsigned& type) const;
    unsigned max(const TypeUnsigned& type) const;

    // sets the value
    bool set(string const& type, string const& value);
    bool set(TypeBool const type, string const& value);
    unsigned set(TypeUnsigned const type, string const& value);
    Card set(TypeCard const type, string const& value);
    bool set(const TypeBool& type, bool const& value);
    unsigned set(const TypeUnsigned& type, unsigned const& value);
    Card set(const TypeCard& type, Card const& value);

    bool load(string const& filename);
    bool load(istream& istr);
    bool save(string const& filename) const;

    // output of the settings
    ostream& out(ostream& ostr) const;
  private:
    AiType aitype_p;

    vector<bool> bool_p;
    vector<unsigned> unsigned_p;
    vector<Card> card_p;
}; // class Aiconfig

// conversion in a string
string name(const Aiconfig::TypeBool& type);
string name(const Aiconfig::TypeUnsigned& type);
string name(const Aiconfig::TypeCard& type);

// output of the name
ostream& operator<<(ostream& ostr, const Aiconfig::TypeBool& type);
ostream& operator<<(ostream& ostr, const Aiconfig::TypeUnsigned& type);
ostream& operator<<(ostream& ostr, const Aiconfig::TypeCard& type);

// output of the Aiconfig
ostream& operator<<(ostream& ostr, const Aiconfig& aiconfig);

#endif // #ifndef CLASS_AICONFIG_HEADER
