/*!
*  @file Dice.h
*  @brief Diceクラスとその他付随要素の定義
*  @date 2014/01/19
*  @author Deskull
*  2014 Sikabane Works.
*/

#pragma once

#include "Deeangband.h"

namespace Deeangband
{

	/*!
	* @class Dice
	* @brief ゲーム中のダイス処理
	* @details
	* <H1>概要</H1>
	* <p>Diceクラスはゲーム中に存在するあらゆるランダム性を持つパラメータのインスタンスとなり、その乱数処理も実装される。
	* また静的なクラス関数上では、Boost(or C++11)で実装されたメルセンヌツイスタ乱数生成器を保持し、直接正規乱数を受け取る機能も実装される。
	* </p>
	*/
	class Dice
	{
	private:

		int num; //!< ダイスの数
		int side; //!< ダイスの面数

		friend class boost::serialization::access;

		/*!
		* @brief クラスのシリアライズを設定する
		* @param archive アーカイブ化するクラスのアドレス
		* @param version ファイルバージョン
		* @return XMLSerializeテンプレート
		*/
		template<class Archive> void serialize(Archive &archive, const unsigned int version) 
		{
			if(version >= 0)
			{
				archive & boost::serialization::make_nvp("Num", num);
				archive & boost::serialization::make_nvp("Side", side);
			}
		}

		template<class Archive> friend void save_construct_data(Archive & archive, const Dice *ptr, const unsigned int version)
		{
			archive & boost::serialization::make_nvp("num", ptr->GetNum());
			archive & boost::serialization::make_nvp("side", ptr->GetSide());
		}

		template<class Archive> friend void load_construct_data(Archive & archive, Dice *ptr, const unsigned int version)
		{
			int n, s;
			archive & boost::serialization::make_nvp("num", n);
			archive & boost::serialization::make_nvp("side", s);
			::new(ptr) Dice(num, side);
		}

	public:

		static std::mt19937 Dice::mt; //!< メルセンヌツイスタによる乱数生成エンジン

		/*!
		* @brief コンストラクタ
		*/
		Dice::Dice(void);

		/*!
		* @brief コンストラクタ
		* @brief ダイスの数
		* @brief ダイスの面
		*/
		Dice::Dice(int num, int side);

		/*!
		* @brief デストラクタ
		*/
		Dice::~Dice(void);

		/*!
		* @brief ダイスの数値設定を行う。
		* @return なし
		*/
		void Dice::Set(int num, int side);

		/*!
		* @brief 乱数初期化関数
		* @return なし
		*/
		static void Dice::Initialize(void);

		/*!
		* @brief ダイスの数を返す
		* @return ダイスの数
		*/
		int Dice::GetNum(void);

		/*!
		* @brief ダイスの面数を返す
		* @return ダイスの面数
		*/
		int Dice::GetSide(void);

		/*!
		* @brief ダイスを振る
		* @return ダイスの総計値
		*/
		int Dice::Cast(void);

		/*!
		* @brief ダイスを振る
		* @param num ダイスの数
		* @param side ダイスの面数
		* @return ダイスの総計値
		*/
		static int Dice::Cast(int num, int side);

		/*!
		* @brief ダイスの取り得る最大値を返す
		* @return ダイスの最大値
		*/
		int Dice::MaxCast(void);

		/*!
		* @brief ダイスの取り得る最大値を返す
		* @param num ダイスの数
		* @param side ダイスの面数
		* @return ダイスの最大値
		*/
		static int Dice::MaxCast(int num, int side);

		/*!
		* @brief 0を最小値とした乱数を返す
		* @param max 乱数の範囲(0〜max-1)
		* @return 乱数の値
		*/
		static int Dice::Rand0(int max);

		/*!
		* @brief 1を最小値とした乱数を返す
		* @param max 乱数の最大値(1〜max)
		* @return 乱数の値
		*/
		static int Dice::Rand1(int max);

		/*!
		* @brief セービング判定
		* @param diff セービング難度-セービング値差分
		* @return セービング成功ならば true を返す。
		*/
		static bool Dice::Saving(int diff);

	};

}

BOOST_CLASS_VERSION(Deeangband::Dice, 10);
