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

// some enumerate:
// - GameStatus
// - Team
// - GameType
// - Announcement
// - MarriageSelector
// - Rotation
// - Position

// local macro
#define WRITE_NAME(Type) \
  inline ostream& operator<<(ostream& ostr, Type const& t) \
  { return (ostr << ::name(t)); }

#include "constants.h"


////////////////
// GAMESTATUS //
////////////////

namespace GAMESTATUS
{
  int const PARTY = 0x10;
  int const GAME = 0x100;
  enum GameStatus {
    PROGRAMSTART = 0,
    QUIT = 1,
    PARTY_NEW = PARTY,
    PARTY_INIT,
    PARTY_PLAY,
    PARTY_FINISHED,
    GAME_NEW = GAME,
    GAME_INIT,
    GAME_RESERVATION,
    GAME_REDISTRIBUTE,
    GAME_POVERTY_SHIFT,
    GAME_PLAY,
    GAME_FULL_TRICK,
    GAME_FINISHED
  }; // enum GameStatus
} // namespace GAMESTATUS
using GAMESTATUS::GameStatus;

bool in_running_game();

extern GameStatus game_status;

string name(GameStatus const& game_status);
WRITE_NAME(GameStatus);


//////////
// Team //
//////////

namespace TEAM
{
  enum Team {
    NOTEAM,
    RE,
    CONTRA, 
    UNKNOWN,
    MAYBE_RE,   // Team for AI-Heuristics
    MAYBE_CONTRA // Team for AI-Heuristics
  }; // enum Team
} // namespace TEAM
using TEAM::Team;

/// converts team MAYBE_X to X
Team maybe_to_team(Team const& t);
/// converts team X to MAYBE_X
Team team_to_maybe(Team const& t);
Team opposite(Team const& t);

string name(Team const& team);
string short_name(Team const& team);
WRITE_NAME(Team)



//////////////
// GAMETYPE //
//////////////

namespace GAMETYPE {
  enum GameType {
    FIRST,
    NORMAL = FIRST, 
    FIVE_NINES,
    SIX_KINGS,
    FOX_HIGHEST_TRUMP,
    POVERTY,
    GENSCHER,
    MARRIAGE,
    MARRIAGE_SOLO,
    MARRIAGE_SILENT,
    SOLO_MEATLESS,
    SOLO_JACK,
    SOLO_QUEEN,
    SOLO_KING,
    SOLO_QUEEN_JACK,
    SOLO_KING_JACK,
    SOLO_KING_QUEEN,
    SOLO_KOEHLER,
    SOLO_CLUB,
    SOLO_HEART,
    SOLO_SPADE,
    SOLO_DIAMOND,
    LAST = SOLO_DIAMOND
  }; // enum GameType
  unsigned const NUMBER = LAST - FIRST + 1;
  bool is_normal(GameType const game_type);
  bool is_poverty(GameType const game_type);
  bool is_marriage(GameType const game_type);
  bool is_solo(GameType const game_type);
  bool is_color_solo(GameType const game_type);
  bool is_picture_solo(GameType const game_type);
  bool is_single_picture_solo(GameType const game_type);
  bool is_double_picture_solo(GameType const game_type);
} // namespace GAMETYPE
using GAMETYPE::GameType;

string name(GameType const& game_type);
WRITE_NAME(GameType)



//////////////////
// ANNOUNCEMENT //
//////////////////

namespace ANNOUNCEMENT
{
  enum Announcement{
    NOANNOUNCEMENT,
    NO120, // means RE or CONTRA
    NO90,
    NO60,
    NO30,
    NO0,
    REPLY,
    NO120_REPLY,
    NO90_REPLY,
    NO60_REPLY,
    NO30_REPLY,
    NO0_REPLY
  }; // enum Announcement
  unsigned const NUMBER = NO0_REPLY - NOANNOUNCEMENT + 1;

  bool is_real(Announcement const& announcement);
  bool is_reply(Announcement const& announcement);
  Announcement to_reply(Announcement const& announcement);
  Announcement from_reply(Announcement const& announcement);
  Announcement from_name(string const& name);
} // namespace ANNOUNCEMENT
using ANNOUNCEMENT::Announcement;

string name(Announcement const& announcement);
WRITE_NAME(Announcement)



///////////////////////
// MARRIAGE_SELECTOR //
///////////////////////

namespace MARRIAGE_SELECTOR {
  enum MarriageSelector {
    FIRST,
    TEAM_SET = FIRST,
    FIRST_FOREIGN,
    FIRST_TRUMP,
    FIRST_COLOR,
    FIRST_CLUB,
    FIRST_SPADE,
    FIRST_HEART,
    LAST = FIRST_HEART
  }; // enum MarriageSelector
  unsigned const MARRIAGE_SELECTOR_NUMBER = 1 + 1 + 1 + 3;
} // namespace MARRIAGE_SELECTOR
using MARRIAGE_SELECTOR::MarriageSelector;

string name(MarriageSelector const& marriage_selector);
WRITE_NAME(MarriageSelector)




namespace ROTATION {
  enum Rotation {
    UP,
    DOWN,
    LEFT,
    RIGHT
  }; // enum ROTATION
  unsigned const ROTATION_NUMBER = RIGHT + 1;

  Rotation clockwise(Rotation const rotation);
  Rotation counterclockwise(Rotation const rotation);
} // namespace ROTATION
using ROTATION::Rotation;
using ROTATION::UP;
using ROTATION::DOWN;
using ROTATION::LEFT;
using ROTATION::RIGHT;

enum Position {
  NORTH,
  SOUTH,
  WEST,
  EAST
}; // enum Position

#undef WRITE_NAME

#endif // #ifndef BASISTYPES_HEADER
