/**********************************************************************
 *
 *   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_AI_HEADER
#define CLASS_AI_HEADER

#include "aiDb.h"
#include "VirtualGamesInterface.h"
#include "HeuristicInterface.h"

#include "../player.h"
#include "../aiconfig.h"
#include "../../game/game.h"
#include "../../game/exception.h"
#include "../../card/cardvector.h"

#include "../../basistypes.h"

class VirtualGamesAi;

class Ai: public Player, public Aiconfig
{
  friend class WVirtualGames;
  friend class Gametree;
  friend class Heuristics;
  friend class TrickWeighting;
  
  friend class VirtualGamesAi;
  friend class HeuristicAi;
  public:

  Ai(istream& istr);
  Ai( const Aiconfig aic=Aiconfig() );
  Ai(Player const& player);
  Ai(Ai const&);
  Ai& operator=(Ai const&);
  // clone the player
  virtual Ai* clone() const;

  virtual ~Ai();

  virtual operator HeuristicInterface const&() const;
  virtual operator VirtualGamesInterface const&() const;

  // output of the ai
  virtual ostream& out(ostream& ostr) const;

  // compares the ai
  virtual bool isequal(Ai const& ai) const;


  virtual Hand const& hand_set(const Hand& h);
  virtual Hand const& hand_set(const Hand& h,
			       bool const playedcards_update);

  // h hands of players 0 till number_of_players number of player for Weighting
  virtual void new_game(Game& game);
  virtual Reservation reservation_get( bool isDuty = false );
  virtual Card card_get();
  virtual void card_played(Card const& card, Player const& player);
  virtual Card nextcard(const Trick& t);

  virtual void teaminfo_update();

  // the trick is full
  virtual void trick_full(Trick const& trick);

  Announcement announcement_request() const;

  unsigned playedcard(Card const& c) const;

  bool colorjabbed(const Card::Color c) const;

  unsigned color_runs(const Card::Color c) const;

  bool jabbedbyownteam(const Card::Color c) const;
  
  bool jabbedbyotherteam(const Card::Color c) const;

  bool next_low() const;

  void check_low_high(Card c);

  unsigned remaining_trumps() const;

  unsigned number_of_single_tens(const GameType t) const; 
  unsigned number_of_fehl(const GameType t) const;

  bool single_ace() const;

  protected:
  unsigned const& last_trick_to_calculate() const;
  unsigned const& last_trick_to_calculate_set(unsigned const last_trick_to_calculate);

  // 'player' shifts cards
  virtual Hand poverty_shift();
  // returns whether 'player' accepts the poverty
  virtual bool poverty_take_accept(unsigned const cardno);
  // the player changes the cards of the poverty
  virtual Hand poverty_cards_change(Hand const& cards);
  // the poverty player gets 'cards'
  virtual void poverty_cards_get_back(Hand const& cards);

  Card trump_card_limit() const;
  Card lowest_trump_card_limit() const;
  private:

  MarriageSelector get_Marriage() const;

  virtual Player const* genscher_partner();

  virtual void updateplayedcards(const Trick& t) throw(InvalidGameException);

  int Ai::calculate_meatless_color( Card::Color co );

  Card nextcard_colorsolo(const Trick& t, bool output);
  Card nextcard_meatless(const Trick& t, bool output);
  Card nextcard_picturesolo(const Trick& t, bool output);

  int checksolo(const Card::Value c, const GameType t) const;
  int checksolo(const Card::Value c1, const Card::Value c2,
		const GameType t) const;
  int checksolo(const Card::Value c1, const Card::Value c2,
		const Card::Value c3, GameType t) const;
  int checksolo(const Card::Color c, const GameType t) const; 
  int checksolo() const;

  CardVector<unsigned> playedcards_p;
  vector<Trick> trick_p; // last played tricks
  unsigned trickno_p;  
  vector<vector<bool> > colorjabbed_p; // remembering for each player if he has jabbed this color
  vector<unsigned> color_runs_p;
  bool low_p; // next card should be low or high trump
  Card::Color meatlesscolor_p;
  vector<bool> trumpless_; // players has no trumps

  unsigned last_trick_to_calculate_p;

#ifdef WORKAROUND
  public:
#endif
  Aiconfig::TypeBool lastHeuristic_;
#ifdef WORKAROUND
  private:
#endif

  AiDb* db(){ return static_cast<AiDb*>(db_); }

  protected:
  Card nextcard(const Trick& t, const bool output);

  Hand handofplayer( Player const& player ) const throw(InvalidGameException);
  Team teamofplayer( Player const& player ) const; 
  
  VirtualGamesInterface* vgi_;
  HeuristicInterface* hi_;
  
  bool silentMarriage_;
}; // class Ai

class VirtualGamesAi: public VirtualGamesInterface {
public:	
 VirtualGamesAi( Ai const& a ): VirtualGamesInterface(), ai_( &a ){}
 virtual ~VirtualGamesAi() {}

 virtual Hand handofplayer( Player const& player ) const 
 { return this->ai_->handofplayer( player ); };
 virtual Team teamofplayer( Player const& player ) const 
 { return this->ai_->teamofplayer( player ); };
  
 virtual Hand const& hand() const
 { return this->ai_->hand(); };
 virtual Team team() const 
 { return this->ai_->team(); };
 virtual unsigned no() const 
 { return this->ai_->no(); };
 virtual Game const& game() const
 { return this->ai_->game(); };
 virtual unsigned const last_trick_to_calculate() const 
 { return this->ai_->last_trick_to_calculate(); };

 virtual bool value(const Aiconfig::TypeBool& type) const
 { return this->ai_->value( type ); };
 virtual unsigned value(const Aiconfig::TypeUnsigned& type) const 
 { return this->ai_->value( type ); };
 virtual Card value(const Aiconfig::TypeCard& type) const
 { return this->ai_->value( type ); };
 virtual unsigned color_runs(const Card::Color c) const
 { return this->ai_->color_runs( c ); };
private:
 Ai const* ai_;	
}; // class VirtualGamesAi : public VirtualGameInterface

class HeuristicAi: public HeuristicInterface {
  public:	
  HeuristicAi( Ai const& a ): HeuristicInterface(), ai_(&a ) { };
  virtual ~HeuristicAi() { };

  virtual Hand handofplayer( Player const& player ) const 
  { return this->ai_->handofplayer( player ); };
  virtual Team teamofplayer( Player const& player ) const 
  { return this->ai_->teamofplayer( player ); };

  virtual Hand const& hand() const
  { return this->ai_->hand(); };
  virtual Team team() const 
  { return this->ai_->team(); };
  virtual unsigned no() const 
  { return this->ai_->no(); };
  virtual Game const& game() const
  { return this->ai_->game(); };
  virtual unsigned const last_trick_to_calculate() const 
  { return this->ai_->last_trick_to_calculate(); };

  virtual bool value(const Aiconfig::TypeBool& type) const
  { return this->ai_->value( type ); };
  virtual unsigned value(const Aiconfig::TypeUnsigned& type) const 
  { return this->ai_->value( type ); };
  virtual Card value(const Aiconfig::TypeCard& type) const
  { return this->ai_->value( type ); };

  virtual unsigned playedcard(Card const& c) const 
  { return this->ai_->playedcard( c ); };

  virtual bool colorjabbed(const Card::Color c) const 
  { return this->ai_->colorjabbed( c ); };

  virtual unsigned color_runs(const Card::Color c) const 
  { return this->ai_->color_runs( c ); };

  virtual bool jabbedbyownteam(const Card::Color c) const
  { return this->ai_->jabbedbyownteam( c ); };
  
  virtual bool jabbedbyotherteam(const Card::Color c) const
  { return this->ai_->jabbedbyotherteam( c ); };
  

  virtual bool next_low() const
  { return this->ai_->next_low() ; };

  virtual Card trump_card_limit() const 
  { return this->ai_->trump_card_limit(); };

  virtual Card lowest_trump_card_limit() const 
  { return this->ai_->lowest_trump_card_limit(); };

  virtual Team const& teaminfo(Player const& player) const
  { return this->ai_->teaminfo( player ); }; 
  
  virtual unsigned remaining_trumps() const
  { return this->ai_->remaining_trumps(); };

  private:
  Ai const* ai_;	
  private:
  HeuristicAi();
  HeuristicAi(HeuristicAi const&);
  HeuristicAi& operator=(HeuristicAi const&);
}; // class HeuristicAi

#endif // #ifndef CLASS_AI_HEADER
