/* This file is part of cardwords
   (c) 1999 2000 Tobias Peters
   see file COPYING for the copyright terms.
   
   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 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
*/

// cardwords_game.hh

// This file defines the main game engin.
// It keeps track of the participants and handles moves, trades and passes.

#ifndef CARDWORDS_GAME_HH
#define CARDWORDS_GAME_HH

#include <vector>
#include "config.hh"
#include "cardwords_move.hh"
#include "cardwords_selectiblechild.hh"
namespace CardWords {

class CardTable;
class Pile;
class BonusTable;
class Participant;


class Game :
  public SelectibleChildLocker
{
public:
  // Every word a player lays in the game is forwarded to DicBot.
  // Here we receive DicBot's answer:
  virtual void
  child_answers(const string & answer);
  
  // Get told about a new Connection. Will send info about registering
  // possibilities and if there are none, will send "BYE".
  // the latter case is indicated by return value -1
  int
  new_connection(Participant *);

  // called by the destructor of Participant:
  void
  deregister(Participant *);

  // called when a request was received completely:
  // returns 0 on normal operation. returns -1 if the request was invalid
  // or illegal for that participant. The participant has then already
  // been deleted or robotized. This means for the calling function:
  // if request_from returns -1, do not touch any data members, because
  // they may have been deleted, and return immediately.
  int
  request_from(const string & request, Participant *);

  Game(size_t set_max_remote_players,
                 size_t set_initial_no_of_robots,
                 size_t set_max_watchers,
                 CardTable * set_table,
                 Pile * set_pile,
                 const BonusTable * set_bonus,
                 bool set_reserve_player_place_for_owner = true);

  // Who's the lazy one:
  Participant *
  whose_turn(void);

  // the requests from the players:
  int
  pass(Participant *); // will also be called from
  //                     Participant::robotize()

  // After he logged successfully on, send the remaining info to
  // this Participant:
  void
  send_after_log_info(Participant *);

private:
  // the istream in these functions will be constructed by request_from()
  int
  registering(Participant *, istream &);

  int
  trade(Participant *, istream &);

public: // will be called dircectly by the robots:
  int
  move(Participant *, istream &);

private:
  int
  quit(Participant *);

  int
  kick(Participant *, istream &);

  int
  add_word(Participant *, istream &);

  int
  remove_word(Participant *, istream &);

  int
  start(Participant *);
  
  void
  next_players_go(void);

  void
  broadcast_message(const string & message);
  
  void
  broadcast_logged_players(void);

  void
  broadcast_cards_left(void);
  
  void
  start_game(void);

  void
  end_game(void);
  
public:
  // This player mutated into a robot:
  int
  robotized(Participant *); // Result is an info to all
  //                                     remaining remote_patricipant-s.


  // info about the game:
  size_t
  get_hand_capacity(void) const;

  bool
  is_game_running(void) const;

  bool
  is_game_over(void) const;

  Pile *
  get_pile(void);

  const BonusTable *
  get_bonus(void) const;

  size_t
  get_no_of_robots(void) const;

  size_t
  get_no_of_remote_players(void) const;

  size_t
  get_no_of_players(void) const;
  
private:
  // every participant is in exactly one set:
  set<Participant *> new_participants;
  set<Participant *> players;
  set<Participant *> watchers;

  // an enum to describe which set a participant is in:
  enum E_In_Set {new_set, play_set, watch_set};
  
  Participant * owner;

  size_t max_players, max_watchers;

  bool owner_is_present;
  bool owner_is_player;
  bool reserve_player_place_for_owner;

  bool game_running;
  bool game_over;

  // The order of the participants in the game:
  vector<Participant *> ordered_players;

  // The player whose turn it is:
  vector<Participant *>::iterator active_player;

  size_t number_of_consecuting_passes;

  CardTable *        table;
  Pile *             pile;
  const BonusTable * bonus;

  // Wether we expect an answer from DicBot regarding a move:
  bool asked_dicbot;
  size_t expect_ok_from_dicbot; // number of confirmation expected
  // This player's move has been asked:
  Participant * asked_for_player;
  // This is the move that we ask:
  Move current_move;
public:
  virtual ~Game(){}
};
}

#endif

