/*!
*  @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:

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


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

		template<class Archive> friend void save_construct_data(Archive & archive, const Dice *ptr, const unsigned int version)
		{
		}

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

	public:

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

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

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

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

		/*!
		 * @brief ダイスの数値設定を行う。
		 * @param num ダイスの数
		 * @param side ダイスの面
		 * @return なし
		 */
		void Dice::Set(DICE_NUMBER num, DICE_SIDE 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(DICE_NUMBER num, DICE_SIDE side);

		/*!
		 * @brief 正規乱数を振る
		 * @param ave 平均
		 * @param dic 分散
		 * @return 乱数値
		 */
		static int Dice::CastNormalRand(int ave, int div);

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

		/*!
		 * @brief ダイスの取り得る最大値を返す
		 * @param num ダイスの数
		 * @param side ダイスの面数
		 * @return ダイスの最大値
		 */
		static int Dice::MaxCast(DICE_NUMBER num, DICE_SIDE 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);

	};

}

