/*	
 *	clipslot.h
 *
 *	スロットゲーム用サブルーチン集
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2016 Naoyuki Sawa
 *
 *	* Sun Jun 02 15:09:44 JST 2013 Naoyuki Sawa
 *	- 1stリリース。
 *	* Sun Aug 18 17:39:58 JST 2013 Naoyuki Sawa
 *	- 役比管理を追加しました。
 *	* Sat Mar 29 15:51:51 JST 2014 Naoyuki Sawa
 *	- テンパイ判定を追加しました。
 *	* Tue Apr 01 00:42:49 JST 2014 Naoyuki Sawa
 *	- 入賞判定を追加しました。
 *	- リール配列を追加しました。
 *	* Tue Apr 08 00:24:56 JST 2014 Naoyuki Sawa
 *	- ラインを追加しました。
 *	- 押順を追加しました。
 *	* Sat May 03 23:21:41 JST 2014 Naoyuki Sawa
 *	- 停止制御を追加しました。
 *	* Mon May 05 15:01:01 JST 2014 Naoyuki Sawa
 *	- 停止制御データビルダを追加しました。
 *	  PC上でツールを作成する時に使用します。P/ECE上では使用しません。
 *	* Mon May 12 12:39:59 JST 2014 Naoyuki Sawa
 *	- スペックデータ作成・出力を追加しました。
 *	  PC上でスペックデータを作成する時に使用します。P/ECE上では使用しません。
 *	* Sat May 31 13:04:14 JST 2014 Naoyuki Sawa
 *	- Slot_PrintStpCtl()が、ST_Slot_StpCtl構造体も出力するように変更しました。
 *	  これまでは、Slot_PrintStpCtl()は個々のテーブルを出力して、アプリケーション側でST_Slot_StpCtl構造体を定義していました。
 *	  今後は、Slot_PrintStpCtl()がST_Slot_StpCtl構造体にまとめて出力するので、アプリケーション側で定義する必要はありません。
 *	* Wed Jun 18 20:20:39 JST 2014 Naoyuki Sawa
 *	- Slot_GetLineRow(),Slot_CheckTenpai(),Slot_CheckPrize()を、5ライン用⇒7ライン用に拡張しました。
 *	  機種によって不要なラインは、アプリケーション側でマスクして使用してください。
 *	* Tue Jun 24 21:30:13 JST 2014 Naoyuki Sawa
 *	- Slot_MakeSpec()をclipsl5n.h,clipsl5n.cへ分離しました。
 *	  当モジュール(clipslot.h,clipslot.c)には、ライン数やタイプにかかわらず共通のサブルーチンのみを残しました。
 *	* Tue Dec 16 21:51:08 JST 2014 Naoyuki Sawa
 *	- 順序番号付き8byte形式コマンドを追加しました。
 *	* Wed Dec 17 21:50:28 JST 2014 Naoyuki Sawa
 *	- シンボル'SlotPos_Max'で、リール駒数を設定できるようにしました。
 *	  設定可能範囲は、「SlotPos_Max=20」(リール駒数=21駒),又は,「SlotPos_Max=19」(リール駒数=20駒)です。
 *	  上記の範囲外は、引込駒数も変える必要が有るので、設定不可です。(引込駒数は4駒決め打ちでハードコーディングしているため。)
 *	- シンボル'SlotPos_Max'を変更した場合は、当モジュールのリビルドが必要です。
 *	  当モジュールをリビルドせずに、アプリケーション側の設定のみで変更することはできません。
 *	- 「SlotPos_Max=19」時の動作は未確認です。(これまでは「SlotPos_Max=20」決め打ちで作成してきたため。)				←┬2014/12/17時点での※TODOです。
 *	  引き続き「SlotPos_Max=19」時の動作確認と、必要に応じて処理の修正を行う必要が有ります。					←┘終了したらこの二行を削除せよ。
 *	* Wed Nov 18 21:37:53 JST 2015 Naoyuki Sawa
 *	- 'extern "C" {'～'}'で囲みました。.cppを含むWin32プロジェクトからもインクルード出来るようにするためです。
 *	* Sun Jul 24 21:18:15 JST 2016 Naoyuki Sawa
 *	- Slot_BuildStpCtl()にて、TinyLZ_compress()の結果が256以上になった時に、正しくはエラー停止すべき所、そのまま(unsigned char)配列に格納してしまい、間違ったデータが生成されていたバグを修正しました。
 *	  修正方法としては、格納する前に(n<256)を検査しても良かったのですが、もし今後(unsigned char)配列を(unsigned short)配列に変更する場合に備えて、格納後に元の値と同じかを比較して検査する事にしました。
 *	* Thu Sep 29 21:37:05 JST 2016 Naoyuki Sawa
 *	- Hewでは停止制御を含めないようにしました。
 */
#ifndef __CLIP_SLOT_H__
#define __CLIP_SLOT_H__

#ifdef  __cplusplus
extern "C" {
#endif//__cplusplus

//□リール駒数 (以下のどちらか一行のみを選択してください)
	#define SlotPos_Max	20	//リール駒数=21駒
//	#define SlotPos_Max	19	//リール駒数=20駒

/****************************************************************************
 *	出率管理
 ****************************************************************************/

/* 出率管理構造体 */
typedef struct _ST_SlotDeritu {
	double     Deritu[3/*0=短,1=中,2=長*/];	/* 出率[%] */
	unsigned  TotalIn[3/*0=短,1=中,2=長*/];	/* 総投入枚数[枚] (理論上の最大値= 3[枚]×17500[G]= 52500[枚]) */
	unsigned TotalOut[3/*0=短,1=中,2=長*/];	/* 総払出枚数[枚] (理論上の最大値=15[枚]×17500[G]=262500[枚]) */
	unsigned GameCount;			/* 経過ゲーム数[G] */
	unsigned char  InLog[17500/*[G]*/ / 4];	/* 投入枚数ログ[枚] (LSB先行,1レコード=2bit,1バイト=4レコード) */
	unsigned char OutLog[17500/*[G]*/ / 2];	/* 払出枚数ログ[枚] (LSB先行,1レコード=4bit,1バイト=2レコード) */
} ST_SlotDeritu;

#define SlotDeritu_ShortTerm(Me) ((Me)->Deritu[0]) /* 短期出率[%]を取得する */
#define SlotDeritu_MidTerm(Me)   ((Me)->Deritu[1]) /* 中期出率[%]を取得する */
#define SlotDeritu_LongTerm(Me)  ((Me)->Deritu[2]) /* 長期出率[%]を取得する */

/* 出率管理構造体を初期化します。
 * [in]
 *	Me	出率管理構造体
 * [note]
 *	- 本関数の処理は、出率管理構造体の、全フィールドを0クリアするだけです。
 *	  出率管理構造体をBSSに配置し、かつ、使用後に再使用しない条件において、本関数の呼び出しを省略しても構いません。
 */
void SlotDeritu_Init(ST_SlotDeritu* Me);

/* ゲームを進め、出率を更新します。
 * [in]
 *	Me	出率管理構造体
 *	In	今回投入枚数[枚] (0～ 3)
 *	Out	今回払出枚数[枚] (0～15)
 * [out]
 *	無し	更新後の出率を参照するには、以下のマクロを使用してください:
 *		  SlotDeritu_ShortTerm(Me)  短期出率[%]
 *		  SlotDeritu_MidTerm(Me)    中期出率[%]
 *		  SlotDeritu_LongTerm(Me)   長期出率[%]
 * [note]
 *	- 投入(払出)枚数は、RP込み/RP抜き、どちらの解釈で使用することも可能です。
 *	  RP込み/RP抜き両方の出率を管理する場合は、出率管理構造体を二個用意して、それぞれに適切な投入(払出)枚数を指定してください。
 * //{{2013/08/18削除:この応用は間違いでした。役比管理のためには1ゲーム毎に払い出し枚数を二個管理するため、出率管理構造体ではビット数が足りませんでした。役比管理構造体を新たに作成することにしました。
 * //[応用]
 * //	- 本来の意図とは違いますが、役物比率管理に利用することも可能です。その場合、意味を読み替えて、以下のように解釈してください:
 * //	  ・投入枚数　⇒　総払出枚数と見なす
 * //	  ・払出枚数　⇒　役物作動中の払出枚数と見なす。必要に応じ、下記①(BB+RB),及び,②(BB+RB+CB+SB) の出率管理構造体を用意する。
 * //	  ・①の出率管理構造体の中期出率が、①の役物比率に相当する。(6割以内)
 * //	  ・②の出率管理構造体の中期出率が、②の役物比率に相当する。(7割以内)
 * //	  ＜参考資料＞
 * //	  ●役物比率
 * //	  ┃出玉における「役物作動中」の払い出し枚数の比率が、任意の6000Gで以下の2つを越えれば不適合となる。
 * //	  ┃役物作動してない場合の役物連続作動装置中の払い出しは含まれない点に注意。
 * //	  ┃①第1種特別役物(RB中の払い出し枚数、1種BB作動中のJAC中払い出し枚数の合計)が6割以下。
 * //	  ┃②第2種特別役物(CB中の払い出し枚数や、2種BB作動中のCB中払い出し枚数の合計)やSBなどを搭載している場合、
 * //	  ┃　①を満たしつつ、全役物中(RB,CB,SB)のの払い出し枚数の合計が全体の7割以下。
 * //}}2013/08/18削除:この応用は間違いでした。役比管理のためには1ゲーム毎に払い出し枚数を二個管理するため、出率管理構造体ではビット数が足りませんでした。役比管理構造体を新たに作成することにしました。
 */
void SlotDeritu_Update(ST_SlotDeritu* Me, int In, int Out);

/****************************************************************************
 *	役比管理
 ****************************************************************************/

/* 役比管理構造体 */
typedef struct _ST_SlotYakuhi {
	double   Yakuhi;	/* 役比[%] */
	unsigned AllOut;	/*         全払出枚数[枚] (理論上の最大値=15[枚]×6000[G]=90000[枚]) */
	unsigned YakOut;	/* 役物作動中払出枚数[枚] (理論上の最大値=15[枚]×6000[G]=90000[枚]) */
	unsigned GameCount;	/* 経過ゲーム数[G] */
	unsigned char YakLog[6000/*[G]*/ / 8];	/* 役物作動中フラグログ (LSB先行,1レコード=1bit,1バイト=8レコード) */
	unsigned char OutLog[6000/*[G]*/ / 2];	/* 払出枚数ログ[枚]     (LSB先行,1レコード=4bit,1バイト=2レコード) */
} ST_SlotYakuhi;

#define SlotYakuhi_MidTerm(Me) ((Me)->Yakuhi) /* 役比の規定は中時間のみです */

/* 役比管理構造体を初期化します。
 * [in]
 *	Me	役比管理構造体
 * [note]
 *	- 本関数の処理は、役比管理構造体の、全フィールドを0クリアするだけです。
 *	  役比管理構造体をBSSに配置し、かつ、使用後に再使用しない条件において、本関数の呼び出しを省略しても構いません。
 */
void SlotYakuhi_Init(ST_SlotYakuhi* Me);

/* ゲームを進め、役比を更新します。
 * [in]
 *	Me	役比管理構造体
 *	Yak	今回役物作動中フラグ (0=一般遊技中,0以外=役物作動中)	厳密には用途によって解釈を変えます。下記[note]を参照してください。
 *	Out	今回払出枚数[枚] (0～15)
 * [out]
 *	無し	更新後の役比を参照するには、以下のマクロを使用してください:
 *		  SlotYakuhi_MidTerm(Me) 役比[%] 役比の規定は中時間のみです
 * [note]
 *	- 1種BB(6割の規定)と、2種BB,SB(7割の規定)の両方を搭載している場合は、役比管理構造体を2個使用してください。
 *	  ┃①第1種特別役物(RB中の払い出し枚数、1種BB作動中のJAC中払い出し枚数の合計)が6割以下。
 *	  ┃②第2種特別役物(CB中の払い出し枚数や、2種BB作動中のCB中払い出し枚数の合計)やSBなどを搭載している場合、
 *	  ┃　①を満たしつつ、全役物中(RB,CB,SB)のの払い出し枚数の合計が全体の7割以下。
 *	- 1種BB用の役比管理構造体に対して、SlotYakuhi_Update()を呼び出す場合、引数Yakの意味は厳密には"一般遊技中"ではなく、"1種BB非作動中"となります。
 *	  要するに、①の条件である場合に Yak=0以外 を指定し、①の条件外である場合(例えばCT中で厳密に一般遊技中でなくても)は Yak=0 を指定してください。
 */
void SlotYakuhi_Update(ST_SlotYakuhi* Me, int Yak, int Out);

/****************************************************************************
 *	押順
 ****************************************************************************/

#define Slot_Order_LCR 0              /* 左中右 */
#define Slot_Order_CRL 1              /* 中右左 */
#define Slot_Order_RLC 2              /* 右左中 */
#define Slot_Order_LRC 3              /* 左右中 */
#define Slot_Order_CLR 4              /* 中左右 */
#define Slot_Order_RCL 5              /* 右中左 */
#define Slot_Order_123 Slot_Order_LCR /* ①②③ */
#define Slot_Order_312 Slot_Order_CRL /* ③①② */
#define Slot_Order_231 Slot_Order_RLC /* ②③① */
#define Slot_Order_132 Slot_Order_LRC /* ①③② */
#define Slot_Order_213 Slot_Order_CLR /* ②①③ */
#define Slot_Order_321 Slot_Order_RCL /* ③②① */

/* 指定された押順の、指定された停止順の、リールを取得する。
 * [in]
 *	iOrder		押順番号(0～5)
 *	iStop		停止順(0～2)
 * [out]
 *	戻り値		リール番号(0～2)
 */
int Slot_GetOrderReel(int iOrder, int iStop);

/* 指定された第1・第2停止リールに一致する、押順を取得する。
 * [in]
 *	iReel1		第1停止リール番号(0～2)
 *	iReel2		第2停止リール番号(0～2)
 * [out]
 *	戻り値		押順番号(0～5)
 */
int Slot_FindOrder(int iReel1, int iReel2);

/****************************************************************************
 *	ライン
 ****************************************************************************/

#define Slot_Line_T 0 /* 上段ライン (Top row) */
#define Slot_Line_M 1 /* 中段ライン (Middle row) */
#define Slot_Line_B 2 /* 下段ライン (Bottom row) */
#define Slot_Line_F 3 /* 降斜ライン (Falling diagonal) */
#define Slot_Line_Z 4 /* 昇斜ライン (Ris(z)ing diagonal) */	//「Z」の形が昇斜ラインに見える事も掛けています
#define Slot_Line_V 5 /* 小谷ライン (small Valley) */		//「V」の形が小谷ラインに見える事も掛けています
#define Slot_Line_A 6 /* 小山ライン (small mountAin) */		//「A」の形が小山ラインに見える事も掛けています

/* 指定されたラインの、指定されたリールの、段を取得する。
 * [in]
 *	iLine		ライン番号(0～6)
 *	iReel		リール番号(0～2)
 * [out]
 *	戻り値		段番号(0～2)
 */
int Slot_GetLineRow(int iLine, int iReel);

/****************************************************************************
 *	テンパイ判定
 ****************************************************************************/

/* 枠内停止絵柄の中に、指定された絵柄組合せがテンパイしているラインを検索する。
 * [in]
 *	aStopPict[3][3]	枠内停止絵柄
 *			- 配列要素の値(0)は、未停止であることを示す。
 *			  配列要素の値(1以上)は、停止絵柄番号を示す。
 *			- 配列要素と位置の対応は、見た目の位置に一致する:
 *			  ┌───┬───┬───┐
 *			  │[0][0]│[0][1]│[0][2]│
 *			  │[1][0]│[1][1]│[1][2]│
 *			  │[2][0]│[2][1]│[2][2]│
 *			  └───┴───┴───┘
 *	iPictLCR	絵柄組合せ
 *			- ビット 0～ 3 = 左回胴の絵柄番号(1～15),又は,Any(0)
 *			  ビット 4～ 7 = 中回胴の絵柄番号(1～15),又は,Any(0)
 *			  ビット 8～11 = 右回胴の絵柄番号(1～15),又は,Any(0)
 *			  ビット12～31 = 当関数はビット31～12を参照しない。不定値で構わない。
 *			- 規格上の絵柄の種類は10種類以内なので、有効な絵柄番号の範囲は1～10である。
 *			  ただし、当関数の処理上は、絵柄番号の範囲に1～15まで指定可能である。
 * [out]
 *	戻り値		テンパイラインのビットマスク
 *			- ビット0 = 指定された絵柄が上段ラインにテンパイしている場合は1、そうでなければ0
 *			  ビット1 = 指定された絵柄が中段ラインにテンパイしている場合は1、そうでなければ0
 *			  ビット2 = 指定された絵柄が下段ラインにテンパイしている場合は1、そうでなければ0
 *			  ビット3 = 指定された絵柄が降斜ラインにテンパイしている場合は1、そうでなければ0
 *			  ビット4 = 指定された絵柄が昇斜ラインにテンパイしている場合は1、そうでなければ0
 *			  ビット5 = 指定された絵柄が小谷ラインにテンパイしている場合は1、そうでなければ0
 *			  ビット6 = 指定された絵柄が小山ラインにテンパイしている場合は1、そうでなければ0
 * [note]
 *	- 回胴停止数が1,2,3のいずれの状態でも、当関数を呼出すことが出来る。
 *	  - 回胴停止数が1で呼出した場合 (=aStopPict[][]のうち2列が(0)である状態での呼出し)
 *	    指定した絵柄組合せがテンパイする可能性が残っているラインの、ビットマスクを取得する。
 *	  - 回胴停止数が2で呼出した場合 (=aStopPict[][]のうち1列が(0)である状態での呼出し)
 *	    指定した絵柄組合せがテンパイしたラインの、ビットマスクを取得する。
 *	  - 回胴停止数が3で呼出した場合 (=aStopPict[][]の3列全てが(0)でない状態での呼出し)
 *	    指定した絵柄組合せが実際に揃ったラインの、ビットマスクを取得する。
 *	- 尚、回胴停止数が0(即ちaStopPict[][]が全て(0)である状態)で呼出すことも可能ではあるが、意味が無い。
 *	  あらゆる絵柄組合せが全ラインにテンパイする可能性が残っているので、常に全ラインのビットが1となる。
 */
int Slot_CheckTenpai(const unsigned char aStopPict[3/*上中下*/][3/*左中右*/], int iPictLCR);

//■メモ
//引数「枠内停止絵柄」と「絵柄組合せ」の引渡し方が異なる理由は、実際の利用ケースを想定したためです。
//「枠内停止絵柄」は、実行時に回胴停止位置を判断して、RAM上に構築するはずです。
//「絵柄組合せ」は、予め決まっており、ROM上に定義されたテーブルであるはずです。
//また、容量節約のために、「絵柄組合せ」テーブルの上位の空きビットには、払出枚数を格納するでしょう。
//従って、「枠内停止絵柄」はバイト単位の配列、「絵柄組合せ」はビットフィールドが適切と判断しました。
//□使用例
//│enum{Pict_Ay,Pict_Rp,Pict_Be,Pict_Sk,Pict_Ch,Pict_Sv,Pict_Br};//絵柄定義
//│const unsigned short TBL_HitFlg[]={//絵柄組合せ&払出枚数定義ﾃｰﾌﾞﾙ
//│Pict_Ay|Pict_Ay<<4|Pict_Ay<<8| 0<<12, //0 ﾊｽﾞﾚ
//│Pict_Rp|Pict_Rp<<4|Pict_Rp<<8| 0<<12, //1 ﾘﾌﾟﾚｲ
//│Pict_Be|Pict_Be<<4|Pict_Be<<8| 8<<12, //2 ﾍﾞﾙ ( 8枚)
//│Pict_Sk|Pict_Sk<<4|Pict_Sk<<8|10<<12, //3 ｽｲｶ (10枚)
//│Pict_Ch|Pict_Ay<<4|Pict_Ay<<8| 2<<12, //4 ﾁｪﾘｰ( 2枚)
//│Pict_Sv|Pict_Sv<<4|Pict_Sv<<8| 0<<12, //5 BB
//│Pict_Sv|Pict_Sv<<4|Pict_Br<<8| 0<<12};//6 RB
//│void Test(){//ﾃｽﾄ関数
//│  unsigned char aStopPict[3][3];//枠内停止絵柄
//│  //回転開始
//│  memset(aStopPict, 0, sizeof aStopPict);
//│  //第一停止
//│  aStopPict[0][0]=Pict_Sk;
//│  aStopPict[1][0]=Pict_Sv;
//│  aStopPict[2][0]=Pict_Sk;
//│  if(Slot_CheckTenpai(aStopPict,TBL_HitFlg[5/*BB*/])&0x1F/*上中下降昇*/){TRACE("BIG可能性有\n");}
//│  //第二停止
//│  aStopPict[0][1]=Pict_Be;
//│  aStopPict[1][1]=Pict_Sv;
//│  aStopPict[2][1]=Pict_Rp;
//│  if(Slot_CheckTenpai(aStopPict,TBL_HitFlg[5/*BB*/])&0x1F/*上中下降昇*/){TRACE("BIGテンパイ\n");}
//│  //第三停止
//│  aStopPict[0][2]=Pict_Ch;
//│  aStopPict[1][2]=Pict_Sv;
//│  aStopPict[2][2]=Pict_Br;
//│  if(Slot_CheckTenpai(aStopPict,TBL_HitFlg[5/*BB*/])&0x1F/*上中下降昇*/){TRACE("BIGが揃った\n");}
//│}

/****************************************************************************
 *	入賞判定
 ****************************************************************************/

/* 枠内停止絵柄の各ラインに入賞している、絵柄組合せを検索する。
 * [in]
 *	aStopPict[3][3]	枠内停止絵柄
 *			- Slot_CheckTenpai()のaStopPict引数と同じ。
 *			  Slot_CheckTenpai()の説明を参照せよ。
 *	aHitFlg		絵柄組合せテーブル
 *			- 各要素は、Slot_CheckTenpai()のiPictLCR引数と同じ。
 *			  Slot_CheckTenpai()の説明を参照せよ。
 *	nHitFlg		絵柄組合せテーブルの要素数(1～256)
 *	aResult		各ラインに入賞している絵柄組合せ番号を格納する配列。
 * [note]
 *	- 当関数は、絵柄組合せテーブルを、以下のように想定している。
 *	  ・要素[0]が、ハズレを表す(Any・Any・Any)であること。
 *	    当関数は、aResultを明示的にクリアしない。
 *	    指定された絵柄組合せテーブルの、どの要素も入賞していないラインは、aResultの要素が格納されない。
 *	    要素[0]を(Any・Any・Any)とすることで、必ず最初に0が格納され、他の入賞役が無い場合の結果となる。
 *	  ・同一ラインに異なる絵柄組合せが入賞した場合、後者の絵柄組合せ番号で上書きする。
 *	    前述の、最初に0を格納した後、後続の入賞役で上書きすることは、この動作を利用している。
 *	    ただし、最初の0以外の複数の役が、同一ラインに入賞して上書きすることは、適切ではない。
 *	    当関数はエラー検出をしないが、そうならないように絵柄組合せを設計すべきである。
 */
void Slot_CheckPrize(const unsigned char aStopPict[3/*上中下*/][3/*左中右*/], const unsigned short aHitFlg[/*nHitFlg*/], int nHitFlg, unsigned char aResult[7/*上中下降昇谷山*/]);

//□使用例
//│enum{Pict_Ay,Pict_Rp,Pict_Be,Pict_Sk,Pict_Ch,Pict_Sv,Pict_Br};//絵柄定義
//│const unsigned short TBL_HitFlg[]={//絵柄組合せ&払出枚数定義ﾃｰﾌﾞﾙ
//│Pict_Ay|Pict_Ay<<4|Pict_Ay<<8| 0<<12, //0 ﾊｽﾞﾚ
//│Pict_Rp|Pict_Rp<<4|Pict_Rp<<8| 0<<12, //1 ﾘﾌﾟﾚｲ
//│Pict_Be|Pict_Be<<4|Pict_Be<<8| 8<<12, //2 ﾍﾞﾙ ( 8枚)
//│Pict_Sk|Pict_Sk<<4|Pict_Sk<<8|10<<12, //3 ｽｲｶ (10枚)
//│Pict_Ch|Pict_Ay<<4|Pict_Ay<<8| 2<<12, //4 ﾁｪﾘｰ( 2枚)
//│Pict_Sv|Pict_Sv<<4|Pict_Sv<<8| 0<<12, //5 BB
//│Pict_Sv|Pict_Sv<<4|Pict_Br<<8| 0<<12};//6 RB
//│void Test(){//ﾃｽﾄ関数
//│  unsigned char a[7];
//│  //ﾃｽﾄのために､異なる役を同時入賞させている｡実際にはこういう設計は不可｡
//│  //□ﾃｽﾄ1
//│  {unsigned char aStopPict[3][3]={
//│   {Pict_Rp,Pict_Rp,Pict_Rp},
//│   {Pict_Be,Pict_Be,Pict_Be},
//│   {Pict_Sk,Pict_Sk,Pict_Sk}};
//│   Slot_CheckPrize(aStopPict,TBL_HitFlg,ARRAY_SIZE(TBL_HitFlg),a);
//│   TRACE("%d %d %d %d %d\n",a[0],a[1],a[2],a[3],a[4]);}//1 2 3 0 0
//│  //□ﾃｽﾄ2
//│  {unsigned char aStopPict[3][3]={
//│   {Pict_Ch,Pict_Sk,Pict_Sk},
//│   {Pict_Be,Pict_Rp,Pict_Rp},
//│   {Pict_Rp,Pict_Be,Pict_Be}};
//│   Slot_CheckPrize(aStopPict,TBL_HitFlg,ARRAY_SIZE(TBL_HitFlg),a);
//│   TRACE("%d %d %d %d %d\n",a[0],a[1],a[2],a[3],a[4]);}//4 0 0 4 0
//│  //□ﾃｽﾄ3
//│  {unsigned char aStopPict[3][3]={
//│   {Pict_Rp,Pict_Rp,Pict_Sv},
//│   {Pict_Be,Pict_Sv,Pict_Be},
//│   {Pict_Sv,Pict_Sk,Pict_Sk}};
//│   Slot_CheckPrize(aStopPict,TBL_HitFlg,ARRAY_SIZE(TBL_HitFlg),a);
//│   TRACE("%d %d %d %d %d\n",a[0],a[1],a[2],a[3],a[4]);}//0 0 0 0 5
//│}

/****************************************************************************
 *	リール配列
 ****************************************************************************/

/* リール配列の、指定された絵柄位置の、指定された回胴番号の、絵柄を取得する。
 * [in]
 *	aReel[(SlotPos_Max+1)]	リール配列
 *				- 各要素はビットフィールド:
 *				  ビット 0～ 3 = 左回胴の絵柄番号(1～15)
 *				  ビット 4～ 7 = 中回胴の絵柄番号(1～15)
 *				  ビット 8～11 = 右回胴の絵柄番号(1～15)
 *				  ビット12～31 = 当関数はビット31～12を参照しない。不定値で構わない。
 *				- 規格上の絵柄の種類は10種類以内なので、有効な絵柄番号の範囲は1～10である。
 *				  ただし、当関数の処理上は、絵柄番号の範囲に1～15まで指定可能である。
 *	iPos			絵柄位置(0～SlotPos_Max)
 *				- 上(0)⇒下(SlotPos_Max)の順である。雑誌等の絵柄位置の番号表示とは逆なので注意せよ。
 *				- (0～SlotPos_Max)の範囲外の値を指定しても構わない。自動的に(0～SlotPos_Max)の範囲に折り返す。
 *	iReel			回胴番号(0～2)
 * [out]
 *	戻り値			絵柄番号(1～15)
 * [note]
 *	- リール配列の要素に、絵柄番号0が指定されていたら、当関数はエラー停止する。
 *	  当関数の処理上は、絵柄番号0が指定されていても、対応可能ではあったのだが、
 *	  関数群全体で「絵柄番号0=未停止,又は,Any」のルールとするために、エラー停止することにした。
 *	  リール配列の要素に、未停止,又は,Anyが存在するのは、適切でないからである。
 */
int Slot_GetReelPict(const unsigned short aReel[/*(SlotPos_Max+1)*/], int iPos, int iReel);

//□使用例
//│enum{Pict_Ay,Pict_Vi,Pict_Sv,Pict_Br,Pict_Rp,Pict_Be,Pict_Sk,Pict_Ch};
//│const char* const TBL_Pict_Name[]={"Ay","Vi","Sv","Br","Rp","Be","Sk","Ch"};
//│const unsigned short TBL_Reel[(SlotPos_Max+1)]={
//│Pict_Sv|Pict_Sv<<4|Pict_Sv<<8, // 0
//│Pict_Ch|Pict_Rp<<4|Pict_Be<<8, // 1
//│Pict_Br|Pict_Be<<4|Pict_Rp<<8, // 2
//│Pict_Be|Pict_Ch<<4|Pict_Sk<<8, // 3
//│Pict_Rp|Pict_Vi<<4|Pict_Br<<8, // 4
//│Pict_Sk|Pict_Rp<<4|Pict_Be<<8, // 5
//│Pict_Vi|Pict_Be<<4|Pict_Rp<<8, // 6
//│Pict_Vi|Pict_Ch<<4|Pict_Sk<<8, // 7
//│Pict_Vi|Pict_Rp<<4|Pict_Vi<<8, // 8
//│Pict_Be|Pict_Br<<4|Pict_Be<<8, // 9
//│Pict_Rp|Pict_Ch<<4|Pict_Br<<8, //10
//│Pict_Sk|Pict_Be<<4|Pict_Rp<<8, //11
//│Pict_Br|Pict_Sk<<4|Pict_Ch<<8, //12
//│Pict_Ch|Pict_Rp<<4|Pict_Be<<8, //13
//│Pict_Vi|Pict_Sv<<4|Pict_Rp<<8, //14
//│Pict_Be|Pict_Ch<<4|Pict_Sk<<8, //15
//│Pict_Rp|Pict_Be<<4|Pict_Ch<<8, //16
//│Pict_Sk|Pict_Sk<<4|Pict_Be<<8, //17
//│Pict_Be|Pict_Rp<<4|Pict_Rp<<8, //18
//│Pict_Rp|Pict_Be<<4|Pict_Br<<8, //19
//│Pict_Sk|Pict_Ch<<4|Pict_Ch<<8};//20
//│void Test(){//ﾃｽﾄ関数
//│  unsigned char aStopPict[3][3];
//│  int iStopPos[3]={-1,13,20};
//│  int iReel,iRow;
//│  for(iRow=0;iRow<3;iRow++) {
//│    for(iReel=0;iReel<3;iReel++){
//│      aStopPict[iRow][iReel]=Slot_GetReelPict(TBL_Reel,iStopPos[iReel]+iRow,iReel);
//│      TRACE("|%2d %s",iStopPos[iReel]+iRow,TBL_Pict_Name[aStopPict[iRow][iReel]]);
//│    }
//│    TRACE("|\n");
//│  }
//│  if(Slot_CheckTenpai(aStopPict,Pict_Sv|Pict_Sv<<4|Pict_Sv<<8)){TRACE("ｾﾌﾞﾝ揃い\n");}
//│}

#ifndef __RENESAS__	//{{2016/09/29追加:Hewでは停止制御を含めないようにしました。}}
/****************************************************************************
 *	停止制御
 ****************************************************************************/

/* 停止制御データ */
typedef struct _ST_Slot_StpCtl {
	unsigned char  HitCd_Size;
	unsigned char  HkmSet1_CompUnit;
	unsigned char  HkmSet2_CompUnit;
	unsigned char  HkmSet3_CompUnit;
	unsigned short HkmSet1_Size;
	unsigned short HkmSet2_Size;
	unsigned short HkmSet3_Size;
	unsigned short HkmSet1_CompData_Size;
	unsigned short HkmSet2_CompData_Size;
	unsigned short HkmSet3_CompData_Size;
	const unsigned char (*TBL_StpCtl1/*[HitCd_Size]*/)[3]/*[(SlotPos_Max+1)]*/;					//                                                                                          ⇒(TBL_HkmSet1_CompSize,TBL_HkmSet1_CompData)
	const unsigned char (*TBL_StpCtl2/*[HitCd_Size]*/)[6]/*[(SlotPos_Max+1)][(SlotPos_Max+1)]*/;			//                                             ⇒(TBL_HkmSet2_CompSize,TBL_HkmSet2_CompData)⇒(TBL_HkmSet1_CompSize,TBL_HkmSet1_CompData)
	const unsigned char (*TBL_StpCtl3/*[HitCd_Size]*/)[6]/*[(SlotPos_Max+1)][(SlotPos_Max+1)][(SlotPos_Max+1)]*/;	//⇒(TBL_HkmSet3_CompSize,TBL_HkmSet3_CompData)⇒(TBL_HkmSet2_CompSize,TBL_HkmSet2_CompData)⇒(TBL_HkmSet1_CompSize,TBL_HkmSet1_CompData)
	const unsigned char (*TBL_HkmSet1_CompSize/*[(HkmSet1_Size+HkmSet1_CompUnit-1)/HkmSet1_CompUnit]*/);
	const unsigned char (*TBL_HkmSet2_CompSize/*[(HkmSet2_Size+HkmSet2_CompUnit-1)/HkmSet2_CompUnit]*/);
	const unsigned char (*TBL_HkmSet3_CompSize/*[(HkmSet3_Size+HkmSet3_CompUnit-1)/HkmSet3_CompUnit]*/);
	const unsigned char (*TBL_HkmSet1_CompData/*[HkmSet1_CompData_Size]*/);
	const unsigned char (*TBL_HkmSet2_CompData/*[HkmSet2_CompData_Size]*/);
	const unsigned char (*TBL_HkmSet3_CompData/*[HkmSet3_CompData_Size]*/);
} ST_Slot_StpCtl;

/*--------------------------------------------------------------------------*
 *	1リール停止制御
 *--------------------------------------------------------------------------*/

/* 条件装置(iHitCd)が作動時に、第1停止リールが(iReel1)で、
 * 第1停止リールの押下位置が(iPushPos1)の、引込駒数を取得する。
 * [in]
 *	pStpCtl		停止制御データ
 *	iHitCd		条件装置番号		0～(HitCd_Size-1)
 *	iReel1		第1停止リール番号	0～2
 *	iPushPos	第1停止リールの押下位置	0～SlotPos_Max
 * [out]
 *	戻り値		引込駒数		0～4
 */
int Slot_GetStpCtl1(const ST_Slot_StpCtl* pStpCtl, int iHitCd, int iReel1, int iPushPos1);

/*--------------------------------------------------------------------------*
 *	2リール停止制御
 *--------------------------------------------------------------------------*/

/* 条件装置(iHitCd)が作動時に、第1停止リールが(iReel1),第2停止リールが(iReel2)で、
 * 第1停止リールの停止位置が(iStopPos1),第2停止リールの押下位置が(iPushPos2)の、引込駒数を取得する。
 * [in]
 *	pStpCtl		停止制御データ
 *	iHitCd		条件装置番号		0～(HitCd_Size-1)
 *	iReel1		第1停止リール番号	0～2
 *	iReel2		第2停止リール番号	0～2
 *	iStopPos1	第1停止リールの停止位置	0～SlotPos_Max
 *	iPushPos2	第2停止リールの押下位置	0～SlotPos_Max
 * [out]
 *	戻り値		引込駒数		0～4
 */
int Slot_GetStpCtl2(const ST_Slot_StpCtl* pStpCtl, int iHitCd, int iReel1, int iReel2, int iStopPos1, int iPushPos2);

/*--------------------------------------------------------------------------*
 *	3リール停止制御
 *--------------------------------------------------------------------------*/

/* 条件装置(iHitCd)が作動時に、第1停止リールが(iReel1),第2停止リールが(iReel2),第3停止リールが(iReel3)で、
 * 第1停止リールの停止位置が(iStopPos1),第2停止リールの停止位置が(iStopPos2),第3停止リールの押下位置が(iPushPos3)の、引込駒数を取得する。
 * [in]
 *	pStpCtl		停止制御データ
 *	iHitCd		条件装置番号		0～(HitCd_Size-1)
 *	iReel1		第1停止リール番号	0～2
 *	iReel2		第2停止リール番号	0～2
 *	iReel3		第3停止リール番号	0～2
 *	iStopPos1	第1停止リールの停止位置	0～SlotPos_Max
 *	iStopPos2	第2停止リールの停止位置	0～SlotPos_Max
 *	iPushPos3	第3停止リールの押下位置	0～SlotPos_Max
 * [out]
 *	戻り値		引込駒数		0～4
 */
int Slot_GetStpCtl3(const ST_Slot_StpCtl* pStpCtl, int iHitCd, int iReel1, int iReel2, int iReel3, int iStopPos1, int iStopPos2, int iPushPos3);
#endif//__RENESAS__	//{{2016/09/29追加:Hewでは停止制御を含めないようにしました。}}

/****************************************************************************
 *	停止制御データビルダ
 ****************************************************************************/
#ifdef  WIN32	//PC上で停止制御データを作成する時に使用します。P/ECE上では使用しません。
/* 停止制御データビルダ情報 */
typedef struct _ST_Slot_StpCtl_BuilderInfo {
	unsigned char HitCd_Size;		/* 条件装置の数 */
	unsigned char HkmSet1_CompUnit;		/* 引込セット1の圧縮単位。大きい程圧縮率が高くなるが、実行時の展開負荷も高くなる。推奨値=16。0が指定された場合、推奨値を使用する。 */
	unsigned char HkmSet2_CompUnit;		/* 引込セット2の圧縮単位。大きい程圧縮率が高くなるが、実行時の展開負荷も高くなる。推奨値=16。0が指定された場合、推奨値を使用する。 */
	unsigned char HkmSet3_CompUnit;		/* 引込セット3の圧縮単位。大きい程圧縮率が高くなるが、実行時の展開負荷も高くなる。推奨値=16。0が指定された場合、推奨値を使用する。 */
	                    void* pParam;	/* 以下のアプリケーション定義関数の第1引数に渡される、任意の値 */
	int (*fnGetStpCtl1)(void* pParam, int iHitCd, int iReel1, int iPushPos1);							/* アプリケーション定義関数。1リール停止制御の引込駒数を返せ。関数仕様はSlot_GetStpCtl1()と互換である。 */
	int (*fnGetStpCtl2)(void* pParam, int iHitCd, int iReel1, int iReel2, int iStopPos1, int iPushPos2);				/* アプリケーション定義関数。2リール停止制御の引込駒数を返せ。関数仕様はSlot_GetStpCtl2()と互換である。 */
	int (*fnGetStpCtl3)(void* pParam, int iHitCd, int iReel1, int iReel2, int iReel3, int iStopPos1, int iStopPos2, int iPushPos3);	/* アプリケーション定義関数。3リール停止制御の引込駒数を返せ。関数仕様はSlot_GetStpCtl3()と互換である。 */
} ST_Slot_StpCtl_BuilderInfo;
/* 停止制御データを作成する。
 * [in]
 *	pInfo		停止制御データビルダ情報
 * [out]
 *	戻り値		停止制御データのメモリ
 * [note]
 *	- 停止制御データのメモリが不要になったら、呼出側で開放すること。
 *	- 当関数が返す停止制御データのメモリは、1個のメモリブロックとして確保されている。
 *	  解放時も、1個のメモリブロックとして開放せよ:
 *	  <例>
 *	    ST_Slot_StpCtl* pStpCtl = Slot_BuildStpCtl(pInfo);
 *	    n = Slot_GetStpCtl1(pStpCtl,iHitCd,iReel1,iPushPos1);
 *	    n = Slot_GetStpCtl2(pStpCtl,iHitCd,iReel1,iReel2,iStopPos1,iPushPos2);
 *	    n = Slot_GetStpCtl3(pStpCtl,iHitCd,iReel1,iReel2,iReel3,iStopPos1,iStopPos2,iPushPos3);
 *	    free(pStpCtl);//これでpStpCtlの個々のフィールドのメモリもまとめて解放される。
 *	- 主に、Slot_MakeSpec()から使用します。
 *	  アプリケーションプログラムから、直接使用することもできます。
 */
ST_Slot_StpCtl* Slot_BuildStpCtl(const ST_Slot_StpCtl_BuilderInfo* pInfo);
/* 停止制御データを出力する。
 * [in]
 *	pStpCtl		停止制御データ
 *	fpH		ヘッダファイル出力ストリーム
 *	fpC		ソースファイル出力ストリーム
 *	- 主に、Slot_MakeSpec()から使用します。
 *	  アプリケーションプログラムから、直接使用することもできます。
 */
void Slot_PrintStpCtl(const ST_Slot_StpCtl* pStpCtl, FILE* fpH, FILE* fpC);
#endif//WIN32	//PC上で停止制御データを作成する時に使用します。P/ECE上では使用しません。

/****************************************************************************
 *	順序番号付き8byte形式コマンド
 ****************************************************************************/

/* コマンドタイプ(8bit)とコマンドデータ(32bit)の5byteを、順序番号付き8byteに変換します。
 * [in]
 *	Type		コマンドタイプ(8bit)	Type[31:8]は不定値でも構いません。
 *	Data		コマンドデータ(32bit)
 *	pBuf		順序番号付き8byteを格納するバッファのアドレス
 * [out]
 *	pBuf[0]～pBuf[7]に、順序番号付き8byteを格納します。
 */
void SlotCmd58_Encode(/*[in]*/int Type, /*[in]*/int Data, /*[out]*/void* _pBuf/*[8]*/);

/* 順序番号付き8byteを、コマンドタイプ(8bit)とコマンドデータ(32bit)の5byteに復元します。
 * [in]
 *	pType		コマンドタイプ(8bit)を格納する変数のアドレス
 *	pData		コマンドデータ(32bit)を格納する変数のアドレス
 *	_pBuf		順序番号付き8byte
 * [out]
 *	戻り値		正常に復元したら0以外の値を返し、*pTypeと*pDataに値を格納します。
 *			異常を検出したら0を返し、*pTypeと*pDataを変更しません。
 * [note]
 *	- 当関数が0を返した場合、アプリケーションは、順序番号付き8byteの先頭1バイトを捨ててください。
 *	  2バイト目以降の、どこから正常に復帰できるかを、当関数の戻り値から判断することはできません。
 */
int SlotCmd58_Decode(/*[out]*/int* pType, /*[out]*/int* pData, /*[in]*/const void* _pBuf/*[8]*/);

#ifdef  __cplusplus
}//extern "C"
#endif//__cplusplus

#endif/*__CLIP_SLOT_H__*/
