/**********************************************************************
 *
 *   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_GAME_HEADER
#define CLASS_GAME_HEADER

#include "../card/trick.h"
class Player;
class Hand;

class Game {
  friend class Party;
  friend class WVirtualGames;
  friend class Gametree;
  friend class WMonteCarlo;
  public:
  // constructor
  Game(class Party& party, Player& startplayer);
  // constructor
  Game(Game const& game);
  // destructor
  ~Game();

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

  // whether this is a virtual game
  bool isvirtual() const;

  // the party, the game is part of
  class Party const& party() const;
  // the rule of the game/party
  class Rule const& rule() const;
  // the start seed
  unsigned seed() const;


  // players

  // number of players
  unsigned playerno() const;
  unsigned number_of_players() const;
  // number of human players
  unsigned humanno() const;
  // number of the player
  unsigned no_of_player(Player const& player) const;
  // the player
  Player const& player(unsigned const& p) const;
  // the player
  Player& player(unsigned const& p);
  // set the players
  void players_set(vector<Player*>& players);
  // the following player
  Player const& player_following(Player const& player) const;
  // the following player
  Player& player_following(Player& player);
  // for iterating over the players
  vector<Player*>::const_iterator player_begin() const;
  // for iterating over the players
  vector<Player*>::const_iterator player_end() const;
  // sort the hand of the players
  void players_hands_sort();
  // mix the hand of the players
  void players_hands_mix();
  // the startplayer
  Player const& startplayer() const;
  // the player whose turn it is
  Player const& player_current() const;
  // the player whose turn it is
  Player& player_current();



  // gametype

  // the gametype
  GameType const& type() const;
  // set the gametype
  GameType const& type_set(GameType const& type);
  // the soloplayer
  Player const& soloplayer() const;
  Player& soloplayer();
  /// the player woh takes the poverty
  Player const& povertyPartner() const;


  // the number of cards shifted in the poverty
  unsigned poverty_cardno() const;
  // the cards that are shifted
  Hand const* poverty_cards() const;

  // infos of the gameplay

  // the number of trumps
  unsigned trumps_no() const;
  // the number of played trumps
  unsigned trumps_played_no() const;
  // the trumpcolor
  Card::Color trumpcolor() const;
  // whether the team has get a trick
  bool hastrick(TEAM::Team const& team) const;
  // the number of tricks the player has got
  unsigned numberoftricks_of_player(Player const& player) const;
  // the number of tricks the player til the trick 'trickno' has got
  unsigned numberoftricks_of_player(Player const& player,
				    unsigned trickno) const;
  // the number of tricks the team has gotumber
  unsigned numberoftricks_of_team(Team const& team) const;
  // the number of points the player has got
  unsigned points_of_player(Player const& player) const;
  // the number of points the player til the trick 'trickno' has got
  unsigned points_of_player(Player const& player,
			    unsigned trickno) const;
  // the points, the team has got
  unsigned points_of_team(Team const& team) const;
  // the winnerteam
  Team winnerteam() const;


  // marriage

  // how the partner is determined
  MarriageSelector const& marriage_selector() const;
  // in which trick the marriage has been determined
  unsigned marriage_determination_trickno() const;

  // announcements

  // the announcement of the team
  Announcement const& announcement_of_team(Team const& team) const;
  // the announcement of the player
  Announcement const& announcement_of_player(Player const& player) const;
  // set the announcement of the player
  Announcement const& announcement_make(Announcement const& announcement,
					Player const& player);
  // test, whether the announcement is valid
  bool announcement_valid(Announcement const& announcement,
			  Player const& player);


  // tricks

  // the number of tricks in the game
  unsigned trickno() const;
  // the trick nmber 'i'
  Trick const& trick(unsigned const& i) const;
  // the current trick
  Trick const& trick_current() const;
  // the current trick
  Trick& trick_current();
  // the number of the current trick
  unsigned trick_current_no() const;
  // the number of remaining tricks
  unsigned tricks_remaining_no() const;
  // for iterating over the trick
  vector<Trick>::const_iterator trick_begin() const;
  // for iterating over the trick
  vector<Trick>::const_iterator trick_end() const;


  // teaminfo (known to all

  // the global known team of the player
  Team teaminfo(Player const& player) const;
  // set the teaminfo of 'player' to 'team'
  void teaminfo_set(Player const& player, Team const& team);

  // set the teaminfo for the gamestart
  void teaminfo_set_at_gamestart();
  // update the team info
  void teaminfo_update();

  // team (real team)

  // the team of the player
  Team team(Player const& player) const;



  // swines and hyperswines

  // whether swines exists
  Player const* swines_owner() const;
  // the player, who has caught the first fox
  Player const* first_fox_catcher() const;
  // whether the swines are valid
  bool swines_valid() const;
  // announce swines
  bool swines_announce();
  // whether the swines have been announced
  bool swines_announced() const;
  // whether hyperswines exists
  Player const* hyperswines_owner() const;
  // whether the hyperswines are valid
  bool hyperswines_valid() const;
  // announce hyperswines
  bool hyperswines_announce();
  // whether the hyperswines have been announced
  bool hyperswines_announced() const;


  // gameplay

  // play the game
  void play();
  private:
  // the party, the game is part of
  class Party& party();

  // set the start seed
  unsigned seed_set(unsigned const& seed);
  // request announcements from the players
  void announcements_request();
  // check, whether the partner is now found
  void determine_marriage();

  // init the game
  void init();
  // make the shifting of the poverty cards
  void poverty_shift();
  // distribute the cards
  void distributecards();
  protected:
  // the next player has to play a card
  void nextplayer();
  // evaluate the full trick
  void evaluatetrick();
  private:
  // finish the game
  void finish();

  private:
  // party, the game belongs to
  class Party* const party_p;

  // players in this game 
  vector<Player*> player_p;
  // the startplayer of the game
  Player const* startplayer_p;
  // the player whose turn it is
  Player* player_current_p;

  // Seed for the distribution of the cards
  unsigned seed_p;
  // type of the game
  GameType type_p;
  // player, who is playing a solo (NULL, if no one)
  Player* soloplayer_p;
  // which trick selects the team
  MarriageSelector marriage_selector_p;
  // in which trick the marriage has been determined
  unsigned marriage_determination_trickno_p;

  // the shifted cards in the poverty;
  Hand* poverty_cards_p;
  // the number of shifted cards
  unsigned poverty_cardno_p;


  // tricks in this game
  vector<Trick> trick_p;

  // Team of the players (information, known to all)
  vector<Team> teaminfo_p;
  // Announcement of the players (information, known to all)
  vector<Announcement> announcement_p;

  //card::is... 

  // the player who has two fox and has made the reservation (for game)
  Player* swines_owner_p;
  // the player, who has caught the first fox
  Player const* first_fox_catcher_p;
  // whether the swines has been announced
  bool swines_announced_p;

  // the player who has two trump nines and has made the reservation (for game)
  Player* hyperswines_owner_p;
  // whether the swines has been announced
  bool hyperswines_announced_p;

  private: // not to be used  
  Game();
  Game& operator=(Game const& g);
  Game(class Player** players);
  Game& create(class Player** players);
}; // class Game

// output of the game
ostream& operator<<(ostream& ostr, Game const& game);

// comparison
bool operator==(Game const& game1, Game const& game2);
bool operator!=(Game const& game1, Game const& game2);

#endif // #ifndef CLASS_GAME_HEADER
