#include <clip.h>
#include <clipmisc.c>
#include <cliptlz.c>
#include <clipwell.c>
#include <clipslot.c>
//#include <clipsl1a.c>
#include <cliplot.c>
#include "SlotData.h"
//#include "LotTbl.h"
#include "LotTblNo.h"

//==============================================================================
//■絵柄
//==============================================================================
//絵柄名称を取得する。
//[in]
//	iOrder		絵柄番号	0~(Pict_Size-1)
//[out]
//	戻り値		絵柄名称
const char* GetPict_Name(int iPict) {
	if((unsigned)iPict >= Pict_Size) { DIE(); }
	return TBL_Pict_Name[iPict];
}

//==============================================================================
//■条件装置
//==============================================================================
//条件装置名称を取得する。
//[in]
//	iOrder		条件装置番号	0~(HitCd_Size-1)
//[out]
//	戻り値		条件装置名称
const char* GetHitCd_Name(int iHitCd) {
	if((unsigned)iHitCd >= HitCd_Size) { DIE(); }
	return TBL_HitCd_Name[iHitCd];
}
//------------------------------------------------------------------------------
//条件装置を抽選する。
//[in]
//	iRT		RT状態	0~1
//	iRndVal		乱数値	0~65535
//[out]
//	戻り値		条件装置番号	0~(HitCd_Size-1)
int LotHitCd(int iRT, int iRndVal) {
	int iHitCd, iWeight;
	if((unsigned)iRT > 1) { DIE(); }
	if((unsigned)iRndVal > 65535) { DIE(); }
	for(iHitCd = 0; iHitCd < HitCd_Size; iHitCd++) {
		iWeight = TBL_HitCd[iHitCd];
		iWeight = (unsigned short)(iWeight + 1);
		iRndVal -= iWeight;
		if(iRndVal < 0) {
			if(iRT && (iHitCd == HitCd_Bo)) { iHitCd = HitCd_Rp; }
			return iHitCd;
		}
	}
	DIE();
}
//------------------------------------------------------------------------------
//条件装置iHitCdが、絵柄組合せiHitFlgを含むか調べる。
//[in]
//	iHitCd		条件装置番号	0~(HitCd_Size-1)
//	iHitFlg		絵柄組合せ番号	0~(HitFlg_Size-1)
//[out]
//	戻り値		含むならば、0以外の値を返す。
int GetHitCd_HitFlg(int iHitCd, int iHitFlg) {
	if((unsigned)iHitCd >= HitCd_Size) { DIE(); }
	if((unsigned)iHitFlg >= HitFlg_Size) { DIE(); }
	return (TBL_HitCd_HitFlg[iHitCd][iHitFlg/8] >> (iHitFlg%8)) & 1;
}

//==============================================================================
//■絵柄組合せ
//==============================================================================
//絵柄組合せ名称を取得する。
//[in]
//	iOrder		絵柄組合せ番号	0~(HitFlg_Size-1)
//[out]
//	戻り値		絵柄組合せ名称
const char* GetHitFlg_Name(int iHitFlg) {
	if((unsigned)iHitFlg >= HitFlg_Size) { DIE(); }
	return TBL_HitFlg_Name[iHitFlg];
}
//------------------------------------------------------------------------------
//絵柄組合せiHitFlgの、払出枚数を取得する。
//[in]
//	iHitFlg		絵柄組合せ番号	0~(HitFlg_Size-1)
//[out]
//	戻り値		払出枚数	0~15
int GetHitFlg_Pay(int iHitFlg) {
	if((unsigned)iHitFlg >= HitFlg_Size) { DIE(); }
	return (TBL_HitFlg[iHitFlg] >> 12) & 15;
}

//==============================================================================
//■テスト
//==============================================================================
//停止テスト
void StpTst() {
	int aPushPos[3], aStopPos[3], iOrder, iReel1, iReel2, iReel3, iHitCd, iHitFlg, iLine, nPay, fBonus, fReplay;
	unsigned char aHitFlg[HitFlg_Size], aStopPict[3][3], aResult[7/*iLine*/];
	//各条件装置について…
	for(iHitCd = 0; iHitCd < HitCd_Size; iHitCd++) {
		memset(aHitFlg, 0, sizeof aHitFlg);	//表示された絵柄組合せをクリアしておく
		//各押順について…
		for(iOrder = 0; iOrder < 6; iOrder++) {
			iReel1 = Slot_GetOrderReel(iOrder, 0);	//第1停止リール
			iReel2 = Slot_GetOrderReel(iOrder, 1);	//第2停止リール
			iReel3 = Slot_GetOrderReel(iOrder, 2);	//第3停止リール
			//第1停止リールの各押下位置について…
			for(aPushPos[iReel1] = 0; aPushPos[iReel1] < 21; aPushPos[iReel1]++) {
				//第1停止リールの停止位置を取得する。
				aStopPos[iReel1] = aPushPos[iReel1] - Slot_GetStpCtl1(&stStpCtl, iHitCd, iReel1, aPushPos[iReel1]);
				if(aStopPos[iReel1] < 0) { aStopPos[iReel1] += 21; }
				//第1停止リールの停止絵柄を取得する。
				aStopPict[0][iReel1] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel1] + 0, iReel1);
				aStopPict[1][iReel1] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel1] + 1, iReel1);
				aStopPict[2][iReel1] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel1] + 2, iReel1);
				//第2停止リールの各押下位置について…
				for(aPushPos[iReel2] = 0; aPushPos[iReel2] < 21; aPushPos[iReel2]++) {
					//第2停止リールの停止位置を取得する。
					aStopPos[iReel2] = aPushPos[iReel2] - Slot_GetStpCtl2(&stStpCtl, iHitCd, iReel1, iReel2, aStopPos[iReel1], aPushPos[iReel2]);
					if(aStopPos[iReel2] < 0) { aStopPos[iReel2] += 21; }
					//第2停止リールの停止絵柄を取得する。
					aStopPict[0][iReel2] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel2] + 0, iReel2);
					aStopPict[1][iReel2] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel2] + 1, iReel2);
					aStopPict[2][iReel2] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel2] + 2, iReel2);
					//第3停止リールの各押下位置について…
					for(aPushPos[iReel3] = 0; aPushPos[iReel3] < 21; aPushPos[iReel3]++) {
						//第3停止リールの停止位置を取得する。
						aStopPos[iReel3] = aPushPos[iReel3] - Slot_GetStpCtl3(&stStpCtl, iHitCd, iReel1, iReel2, iReel3, aStopPos[iReel1], aStopPos[iReel2], aPushPos[iReel3]);
						if(aStopPos[iReel3] < 0) { aStopPos[iReel3] += 21; }
						//第3停止リールの停止絵柄を取得する。
						aStopPict[0][iReel3] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel3] + 0, iReel3);
						aStopPict[1][iReel3] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel3] + 1, iReel3);
						aStopPict[2][iReel3] = Slot_GetReelPict(TBL_Reel, aStopPos[iReel3] + 2, iReel3);
						//各ラインの絵柄組合せを検索する。
						Slot_CheckPrize(aStopPict, TBL_HitFlg, HitFlg_Size, aResult);
						//有効ラインについて…
						iHitFlg = aResult[Slot_Line_M];				//絵柄組合せを取得する
						if(!GetHitCd_HitFlg(iHitCd, iHitFlg)) { DIE(); }	//条件装置に含まれない絵柄組合せが表示されたらエラー
						nPay = GetHitFlg_Pay(iHitFlg);				//払出枚数を取得する
						aHitFlg[iHitFlg] = 1;					//表示された絵柄組合せを記憶する
						fBonus  = !!strstr(GetHitFlg_Name(iHitFlg), "ﾎﾞｰﾅｽ");	//ボーナスが作動したことを記憶する
						fReplay = !!strstr(GetHitFlg_Name(iHitFlg), "ﾘﾌﾟ"  );	//リプレイが作動したことを記憶する
//{{clipsl1a.cの優先度オフセット(-1)の効果を検査する
						/* 有効ラインの絵柄組合せがハズレで、条件装置がボーナス以外で、左第1停止ならば… */
						if(!iHitFlg && (iHitCd != HitCd_Bo) && (Slot_GetOrderReel(iOrder, 0) == 0)) {
							/* 上段〜昇斜ラインについて… */
							for(iLine = 0; iLine < 5; iLine++) {
								int iPict1 = aStopPict[Slot_GetLineRow(iLine, 0)][0];
								int iPict2 = aStopPict[Slot_GetLineRow(iLine, 1)][1];
								int iPict3 = aStopPict[Slot_GetLineRow(iLine, 2)][2];
								if(!strncmp(GetPict_Name(iPict1), GetPict_Name(iPict2), 3) &&		//任意のラインに絵柄揃い
								   !strncmp(GetPict_Name(iPict2), GetPict_Name(iPict3), 3)) { DIE(); }	//(ｽｲｶA~Cを同じと見なすために､名前の先頭三文字で比較する｡)
								if(iPict1 == Pict_Ch) { DIE(); }					//左リールにチェリー停止
								if((iPict3 == Pict_Ch) && (iLine == Slot_Line_M)) { DIE(); }		//右リール中段にチェリー停止
							}
						}
//}}clipsl1a.cの優先度オフセット(-1)の効果を検査する
						//条件装置がハズレ,ボーナス,リプレイならば、払出が無いことを確認する。
						if(!iHitCd ||
						   strstr(GetHitCd_Name(iHitCd), "ﾎﾞｰﾅｽ") ||
						   strstr(GetHitCd_Name(iHitCd), "ﾘﾌﾟ"  )) {
							if(nPay != 0) { DIE(); }
						//条件装置がハズレ,ボーナス,リプレイ以外ならば、払出が有ることを確認する。
						} else {
							if(nPay == 0) {
								/* 押順ベルの押順不正解時に自力ベルが取れなかった場合は、払出無しも有り得る。 */
								if(((iHitCd >= HitCd_Cr1) && (iHitCd <= HitCd_Cr9) && (iOrder != Slot_Order_CRL)) ||
								   ((iHitCd >= HitCd_Rl1) && (iHitCd <= HitCd_Rl9) && (iOrder != Slot_Order_RLC)) ||
								   ((iHitCd >= HitCd_Cl1) && (iHitCd <= HitCd_Cl9) && (iOrder != Slot_Order_CLR)) ||
								   ((iHitCd >= HitCd_Rc1) && (iHitCd <= HitCd_Rc9) && (iOrder != Slot_Order_RCL))) {
									/* ok */
								} else {
									DIE();
								}
							}
						}
//						//条件装置がボーナスならば、ボーナスが作動したことを確認する。
//						if(strstr(GetHitCd_Name(iHitCd), "ﾎﾞｰﾅｽ")) { if(!fBonus ) { DIE(); } }
//⇒ゼロボAT機なので、この検査は除外する。
						//条件装置がリプレイならば、リプレイが作動したことを確認する。
						if(strstr(GetHitCd_Name(iHitCd), "ﾘﾌﾟ"  )) { if(!fReplay) { DIE(); } }
					}
				}
			}
		}
		//各絵柄組合せについて…
		for(iHitFlg = 0; iHitFlg < HitFlg_Size; iHitFlg++) {
			//この条件装置に含まれる絵柄組合せならば…
			if(GetHitCd_HitFlg(iHitCd, iHitFlg)) {
				//この絵柄組合せが表示されたら正しい。
				if(aHitFlg[iHitFlg]) {
					/** no job **/
				//この絵柄組合せが表示されなければエラー。ただし条件装置がCT中全小役である場合のみ許容する。
				} else {
					if(strstr(GetHitCd_Name(iHitCd), "全小役")) {
						/** no job **/
					} else {
///						DIE();
///⇒払出の無いチェリーを、各条件装置で絞り込んでいないので、停止しない組み合わせも有り得る。ひとまず検査を止めることにした。仕様上はこのままで問題無い。
					}
				}
			} else {
				//この絵柄組合せが表示されたらエラー。
				if(aHitFlg[iHitFlg]) {
					DIE();
				//この絵柄組合せが表示されなければ正しい。
				} else {
					/** no job **/
				}
			}
		}
	}
}
//------------------------------------------------------------------------------
//シミュレーションテスト
void SimTst(int iRank, int nYuugiKaisuu, int nSikouDaisuu, int iSikenSyurui) {
	WELL well;	//乱数生成器
	FILE* fp;	//ログ出力ストリーム
	//--- 試験通算の変数 ---
	unsigned aTousenKaisuu[HitCd_Size];					//各条件装置の当選回数
	int Sum_In_RPincl, Sum_Ot_RPincl;					//RP込投入枚数,RP込払出枚数
	int Sum_In_RPexcl, Sum_Ot_RPexcl;					//RP抜投入枚数,RP抜払出枚数
	int                Sum_Ot_YKonly;					//役物払出枚数
	int ShortOver, MidOver, LongOver, YakuhiOver, TotalOver;		//短時間不適合台数,中時間不適合台数,長時間不適合台数,役物比率不適合台数,不適合台数
	double ShortBest, MidBest, LongBest, YakuhiBest;			//短時間最大出玉率,中時間最大出玉率,長時間最大出玉率,最大役物比率
	double LongWorst;							//長時間最小出玉率
	int iWin, iLose;							//勝ち台数,負け台数
	int iATHitCnt, iATSetMax;						//AT初当り回数,AT最大セット数
	int iATSetSum;								//ATセット数合計	…AT平均セット数を計算するため
	int iATKanGameSuuSum;							//AT間ゲーム数合計	…AT初当り当選率を計算するため
	int iSikouDaisuu;							//試行台数
	//--- 試験ごとの変数 ---
	ST_SlotDeritu stSlotDeritu_RPincl;					//RP込出玉率管理
	ST_SlotDeritu stSlotDeritu_RPexcl;					//RP抜出玉率管理
	ST_SlotYakuhi stSlotYakuhi;						//役物比率管理
	double ShortMax, MidMax, LongMax, YakuhiMax;				//短時間最大出玉率,中時間最大出玉率,長時間最大出玉率,最大役物比率
	double LongMin;								//長時間最小出玉率
	int iYuugiKaisuu;							//遊技回数
	int iRT, fReplay, iBonusNokoriGameSuu, iBonusKanGameSuu;		//RT状態,リプレイ作動,ボーナス残りG数,ボーナス間G数
	int iPoint, iATSet, iAT, iATKanGameSuu;					//ポイント,ATセット,AT残りG数,AT間G数
	//--- 遊技ごとの変数 ---
	int iHitCd;								//条件装置
	int In_RPincl, Ot_RPincl;						//RP込投入枚数,RP込払出枚数
	int In_RPexcl, Ot_RPexcl;						//RP抜投入枚数,RP抜払出枚数
	//乱数生成器を初期化する。
	WELL_init(&well, time(NULL));
	//ログ出力ストリームを開く。
	fp = fopen("log.txt", "wt");
	if(!fp) { DIE(); }
	//試験通算の変数をクリアする。
	memset(aTousenKaisuu, 0, sizeof aTousenKaisuu);
	Sum_In_RPincl = Sum_Ot_RPincl = 0;
	Sum_In_RPexcl = Sum_Ot_RPexcl = 0;
	                Sum_Ot_YKonly = 0;
	ShortOver = MidOver = LongOver = YakuhiOver = TotalOver = 0;
	ShortBest = MidBest = LongBest = YakuhiBest = DBL_MIN;
	LongWorst = DBL_MAX;
	iWin = iLose = 0;
	iATHitCnt = iATSetMax = 0;
	iATSetSum = 0;
	iATKanGameSuuSum = 0;
	//各試験について…
	for(iSikouDaisuu = 1; iSikouDaisuu <= nSikouDaisuu; iSikouDaisuu++) {
		int iHitVal;
		//試験ごとの変数をクリアする。
		SlotDeritu_Init(&stSlotDeritu_RPincl);
		SlotDeritu_Init(&stSlotDeritu_RPexcl);
		SlotYakuhi_Init(&stSlotYakuhi);
		ShortMax = MidMax = LongMax = YakuhiMax = DBL_MIN;
		LongMin = DBL_MAX;
		iRT = fReplay = iBonusNokoriGameSuu = iBonusKanGameSuu = 0;
		iPoint = iATSet = iAT = iATKanGameSuu = 0;
		//各遊技について…
		for(iYuugiKaisuu = 1; iYuugiKaisuu <= nYuugiKaisuu; iYuugiKaisuu++) {
			In_RPincl = iBonusNokoriGameSuu ? 2 : 3;			//RP込投入枚数
			In_RPexcl = fReplay ? 0 : In_RPincl;				//RP抜投入枚数
			iHitCd = iBonusNokoriGameSuu ? HitCd_Zk : LotHitCd(iRT, (unsigned short)WELL_next(&well));	//条件装置
			aTousenKaisuu[iHitCd]++;					//各条件装置の当選回数
			//(iSikenSyurui=1):試射試験
			if(iSikenSyurui) {
				//通常時
				if(!iAT) {
					//前Gがリプレイで、今Gがリプレイでなければ…
					// - 「AT最終Gがリプレイで、通常時1G目がリプレイでなかった」場合、AT終了時に抽選した初期ポイントが無駄になるが、動作上は問題無い。
					if(fReplay && (iHitCd != HitCd_Rp)) {
						//通常時初期ﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtIn]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						iPoint = iHitVal;
					}
				}
			}
			switch(iHitCd) {
			case HitCd_Hz ://ﾊｽﾞﾚ    
			case HitCd_Bo ://ﾎﾞｰﾅｽ   
				Ot_RPincl = 0;						//RP込払出枚数
				break;
			case HitCd_Rp ://ﾘﾌﾟﾚｲ   
				Ot_RPincl = 3;						//RP込払出枚数
				break;
			case HitCd_Js ://弱ｽｲｶ   
				Ot_RPincl = 8;						//RP込払出枚数
				//(iSikenSyurui=1):試射試験
				if(iSikenSyurui) {
					//通常時
					if(!iAT) {
						//通常時弱ｽｲｶﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtJs]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					//AT中
					} else {
						//AT中弱ｽｲｶﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaJs]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					}
				}
				break;
			case HitCd_Ks ://強ｽｲｶ   
				Ot_RPincl = 8;						//RP込払出枚数
				//(iSikenSyurui=1):試射試験
				if(iSikenSyurui) {
					//通常時
					if(!iAT) {
						//通常時強ｽｲｶﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtKs]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					//AT中
					} else {
						//AT中強ｽｲｶﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaKs]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					}
				}
				break;
			case HitCd_Cm ://ﾁｬﾝｽ目  
				Ot_RPincl = 1;						//RP込払出枚数
				//(iSikenSyurui=1):試射試験
				if(iSikenSyurui) {
					//通常時
					if(!iAT) {
						//通常時ﾁｬﾝｽ目ﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtCm]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					//AT中
					} else {
						//AT中ﾁｬﾝｽ目ﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaCm]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					}
				}
				break;
			case HitCd_Jc ://弱ﾁｪﾘｰ  
				Ot_RPincl = 1;						//RP込払出枚数
				//(iSikenSyurui=1):試射試験
				if(iSikenSyurui) {
					//通常時
					if(!iAT) {
						//通常時弱ﾁｪﾘｰﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtJc]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					//AT中
					} else {
						//AT中弱ﾁｪﾘｰﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaJc]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					}
				}
				break;
			case HitCd_Kc ://強ﾁｪﾘｰ  
				Ot_RPincl = 1;						//RP込払出枚数
				//(iSikenSyurui=1):試射試験
				if(iSikenSyurui) {
					//通常時
					if(!iAT) {
						//通常時強ﾁｪﾘｰﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtKc]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					//AT中
					} else {
						//AT中強ﾁｪﾘｰﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaKc]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					}
				}
				break;
			case HitCd_Mc ://中段ﾁｪﾘｰ
				Ot_RPincl = 1;						//RP込払出枚数
				//(iSikenSyurui=1):試射試験
				if(iSikenSyurui) {
					//通常時
					if(!iAT) {
						//通常時中段ﾁｪﾘｰﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtMc]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					//AT中
					} else {
						//AT中中段ﾁｪﾘｰﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaMc]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					}
				}
				break;
			case HitCd_Zk ://全小役  
				Ot_RPincl = 2;						//RP込払出枚数
				break;
			default:	//ﾍﾞﾙ
				//(iSikenSyurui=1):試射試験
				if(iSikenSyurui) {
					//通常時
					if(!iAT) {
						if((unsigned short)WELL_next(&well) < 14563/*=65536*2/9*/) {
							Ot_RPincl = 1;			//RP込払出枚数		副役
						} else {
							Ot_RPincl = 0;			//RP込払出枚数		零し
						}
						//通常時ﾍﾞﾙﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtBe]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint += iHitVal) > 100) { iPoint = 100; }
					//AT中
					} else {
						Ot_RPincl = 8;				//RP込払出枚数		ベル
						//AT中ﾍﾞﾙﾎﾟｲﾝﾄ抽選
						iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaBe]], (unsigned short)WELL_next(&well), iRank+1, -1);
						if(iHitVal < 0) { DIE(); }
						if((iPoint -= iHitVal) < 0) { iPoint = 0; }					//【注意】ここだけポイント減算です。
					}
				//(iSikenSyurui=0):シミュレーション試験
				} else {
					Ot_RPincl = 8;					//RP込払出枚数		ベル
				}
				break;
			}
			Ot_RPexcl = (iHitCd == HitCd_Rp) ? 0 : Ot_RPincl;			//RP抜払出枚数
			SlotDeritu_Update(&stSlotDeritu_RPincl, In_RPincl, Ot_RPincl);		//RP込出玉率管理
			SlotDeritu_Update(&stSlotDeritu_RPexcl, In_RPexcl, Ot_RPexcl);		//RP抜出玉率管理
			SlotYakuhi_Update(&stSlotYakuhi, iBonusNokoriGameSuu, Ot_RPexcl);	//役物比率管理
			Sum_In_RPincl += In_RPincl; Sum_Ot_RPincl += Ot_RPincl;			//RP込払出枚数(合計)
			Sum_In_RPexcl += In_RPexcl; Sum_Ot_RPexcl += Ot_RPexcl;			//RP抜払出枚数(合計)
			if(iBonusNokoriGameSuu) { Sum_Ot_YKonly += Ot_RPexcl; }			//役物払出枚数(合計)
			if((SlotDeritu_ShortTerm(&stSlotDeritu_RPexcl) != 0.0) && (SlotDeritu_ShortTerm(&stSlotDeritu_RPexcl) > ShortMax )) ShortMax  = SlotDeritu_ShortTerm(&stSlotDeritu_RPexcl);	//短時間最大出玉率
			if((SlotDeritu_MidTerm(  &stSlotDeritu_RPexcl) != 0.0) && (SlotDeritu_MidTerm(  &stSlotDeritu_RPexcl) > MidMax   )) MidMax    = SlotDeritu_MidTerm(  &stSlotDeritu_RPexcl);	//中時間最大出玉率
			if((SlotDeritu_LongTerm( &stSlotDeritu_RPexcl) != 0.0) && (SlotDeritu_LongTerm( &stSlotDeritu_RPexcl) > LongMax  )) LongMax   = SlotDeritu_LongTerm( &stSlotDeritu_RPexcl);	//長時間最大出玉率
			if((SlotYakuhi_MidTerm(  &stSlotYakuhi       ) != 0.0) && (SlotYakuhi_MidTerm(  &stSlotYakuhi       ) > YakuhiMax)) YakuhiMax = SlotYakuhi_MidTerm(  &stSlotYakuhi       );	//最大役物比率
			if((SlotDeritu_LongTerm( &stSlotDeritu_RPexcl) != 0.0) && (SlotDeritu_LongTerm( &stSlotDeritu_RPexcl) < LongMin  )) LongMin   = SlotDeritu_LongTerm( &stSlotDeritu_RPexcl);	//長時間最小出玉率
			if(!iBonusNokoriGameSuu) {					//ボーナス中でなければ…
				iBonusKanGameSuu++;					//ボーナス間G数を増やす(ボーナス当選Gも含む)
			}
			if(!iAT) {							//AT中でなければ…
				iATKanGameSuu++;					//AT間G数を増やす(AT当選Gも含む)
			}
			if(iSikouDaisuu == 1) { //1台目のみ、1Gログを出力する
				fprintf(fp, "%d\t", iYuugiKaisuu);			//遊技回数
				fprintf(fp, "%d\t", iBonusKanGameSuu);			//ボーナス間G数
				fprintf(fp, "%d\t", iRT);				//RT状態
				fprintf(fp, "%s\t", GetHitCd_Name(iHitCd));		//条件装置
				fprintf(fp, "%d\t", In_RPincl);				//投入枚数(RP込)
				fprintf(fp, "%d\t", Ot_RPincl);				//払出枚数(RP込)
				fprintf(fp, "%d\t", Sum_In_RPincl);			//累計投入枚数(RP込)
				fprintf(fp, "%d\t", Sum_Ot_RPincl);			//累計払出枚数(RP込)
				fprintf(fp, "%d\n", Sum_Ot_RPincl - Sum_In_RPincl);	//累計差枚数(RP込)
			}
			if(iBonusNokoriGameSuu) {					//ボーナス中ならば…
				iBonusNokoriGameSuu--;					//ボーナス残りG数を減らす
				if(!iBonusNokoriGameSuu) {				//ボーナス終了ならば…
					iBonusKanGameSuu = 0;				//ボーナス間G数をクリアする
					iRT = 0;					//非RTへ移行する
				}
			} else {							//ボーナス中でなければ…
				if(iHitCd == HitCd_Rp) {				//リプレイならば…
					fReplay = 1;					//リプレイ作動フラグをセットする
				} else {						//リプレイでなければ…
					fReplay = 0;					//リプレイ作動フラグをクリアする
					if(iHitCd == HitCd_Bo) {			//ボーナスならば…
						iRT = 1;				//RTへ移行する
						//(iSikenSyurui=1):試射試験
						if(iSikenSyurui) {
							/** no job **/
						//(iSikenSyurui=0):シミュレーション試験
						} else {
							iBonusNokoriGameSuu = 20;	//ボーナス残りG数をセットする
						}
					}
				}
			}
			//(iSikenSyurui=1):試射試験
			if(iSikenSyurui) {
				//通常時
				if(!iAT) {
					if(iHitCd == HitCd_Rp) {	//今Gがリプレイならば…(リプレイ連続ならば同じポイント数で複数回抽選する。)
						if(iPoint > (int)(WELL_next(&well) % 100)) {	//AT初当り当選ならば…
							iATKanGameSuuSum += iATKanGameSuu;	//AT間ゲーム数合計を加算する
							iATHitCnt++;				//AT初当り回数を増やす
							iATSetSum++;				//ATセット数合計を増やす
							iATSet = 1;				//ATセット1から開始する
							iAT = 30;				//AT残りG数をセットする
							//AT中初期ﾎﾟｲﾝﾄ抽選
							iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PaIn]], (unsigned short)WELL_next(&well), iRank+1, -1);
							if(iHitVal < 0) { DIE(); }
							iPoint = iHitVal;
						}
					}
				//AT中
				} else {
					if(!--iAT) {	//AT残りG数が無くなったら…
						if(iPoint > (int)(WELL_next(&well) % 100)) {	//AT継続当選ならば…
							iATSetSum++;				//ATセット数合計を増やす
							iATSet++;				//ATセットを進める
							iAT = 30;				//AT残りG数をセットする
							//ポイントは引き継ぐ。
						} else {
							iATKanGameSuu = 0;			//AT間ゲーム数をリセットする
							//通常時初期ﾎﾟｲﾝﾄ抽選
							iHitVal = LOT_draw_table_l(&TBL_LotTbl[TBL_LotTblNo[LotTblNo_PtIn]], (unsigned short)WELL_next(&well), iRank+1, -1);
							if(iHitVal < 0) { DIE(); }
							iPoint = iHitVal;
						}
					}
				}
			}
			if(iATSet > iATSetMax) { iATSetMax = iATSet; }	//AT最大セット数
		}
		if(ShortMax  >= 300.0) { ShortOver++;  }	//短時間不適合台数
		if(MidMax    >= 150.0) { MidOver++;    }	//中時間不適合台数
		if(LongMax   >= 120.0) { LongOver++;   }	//長時間不適合台数
		if(YakuhiMax >   70.0) { YakuhiOver++; }	//役物比率不適合台数
		if((ShortMax >= 300.0) || (MidMax >= 150.0) || (LongMax >= 120.0) || (YakuhiMax > 70.0)) { TotalOver++; }	//不適合台数
		if(ShortMax  > ShortBest ) { ShortBest  = ShortMax;  }	//短時間最大出玉率
		if(MidMax    > MidBest   ) { MidBest    = MidMax;    }	//中時間最大出玉率
		if(LongMax   > LongBest  ) { LongBest   = LongMax;   }	//長時間最大出玉率
		if(YakuhiMax > YakuhiBest) { YakuhiBest = YakuhiMax; }	//最大役物比率
		if(LongMin   < LongWorst ) { LongWorst  = LongMin;   }	//長時間最小出玉率
		if(stSlotDeritu_RPincl.TotalOut[2] >= stSlotDeritu_RPincl.TotalIn[2]) {
			iWin++;		//勝ち台数
		} else {
			iLose++;	//負け台数
		}
		if((iSikouDaisuu % 100) == 0) {
			printf(".");	//進捗表示
			fflush(stdout);
		}
	}
	printf("\n");
	printf("出率(RP込) 出率(RP抜) 役比\n");
	printf("%10.5f %10.5f %10.5f\n",
		((double)Sum_Ot_RPincl / (double)Sum_In_RPincl) * 100.0,	//RP込出玉率(合計)
		((double)Sum_Ot_RPexcl / (double)Sum_In_RPexcl) * 100.0,	//RP抜出玉率(合計)
		((double)Sum_Ot_YKonly / (double)Sum_Ot_RPexcl) * 100.0);	//役物比率(合計)
	if(nYuugiKaisuu <   400) { ShortBest            = 0; }	//短時間結果無効
	if(nYuugiKaisuu <  6000) { MidBest              = 0; }	//中時間結果無効
	if(nYuugiKaisuu < 17500) { LongBest = LongWorst = 0; }	//長時間結果無効
	printf("短時間最大 中時間最大 長時間最大 役比最大   長時間最小\n");
	printf("%10.5f %10.5f %10.5f %10.5f %10.5f\n", ShortBest, MidBest, LongBest, YakuhiBest, LongWorst);
	printf("短時間不適 中時間不適 長時間不適 役比不適     総合不適\n");
	printf("%10d %10d %10d %10d %10d\n", ShortOver, MidOver, LongOver, YakuhiOver, TotalOver);
	printf("勝ち台数 %d 負け台数 %d\n", iWin, iLose);
	printf("\n");
	for(iHitCd = 0; iHitCd < HitCd_Size; iHitCd++) {
		printf("%d%10d\n", iHitCd, aTousenKaisuu[iHitCd]);	//各条件装置の当選回数
	}
	printf("AT最大セット数 %d\n", iATSetMax);
	printf("AT平均セット数 %f\n", (double)iATSetSum / (double)iATHitCnt);
	printf("AT初当り当選率 %f\n", (double)iATKanGameSuuSum / (double)iATHitCnt);
	fclose(fp);
}
//------------------------------------------------------------------------------
int main(int argc, char* argv[]) {
	int iRank = 5, nYuugiKaisuu = 17500, nSikouDaisuu = 10000, iSikenSyurui = 1;
	StpTst();	//停止テスト
	if(argc >= (1+1)) { iRank        = atoi(argv[1]); if((unsigned)iRank        >     5) { iRank        =     5; } }	//設定値
	if(argc >= (1+2)) { nYuugiKaisuu = atoi(argv[2]); if((unsigned)nYuugiKaisuu > 17500) { nYuugiKaisuu = 17500; } }	//遊技回数
	if(argc >= (1+3)) { nSikouDaisuu = atoi(argv[3]); if((unsigned)nSikouDaisuu > 10000) { nSikouDaisuu = 10000; } }	//試行台数
	if(argc >= (1+4)) { iSikenSyurui = atoi(argv[4]); if((unsigned)iSikenSyurui >     1) { iSikenSyurui =     1; } }	//試験種類
	SimTst(iRank, nYuugiKaisuu, nSikouDaisuu, iSikenSyurui);	//シミュレーションテスト
	return 0;
}
