/*
 *	clipvsl.c
 *
 *	ビデオスロットゲーム用サブルーチン集
 *
 *	CLiP - Common Library for P/ECE
 *	Copyright (C) 2001-2017 Naoyuki Sawa
 *
 *	* Thu Feb 11 21:46:05 JST 2016 Naoyuki Sawa
 *	- 1st リリース。
 *	* Fri Jun 03 21:47:06 JST 2016 Naoyuki Sawa
 *	- シンボルタイプの定数を定義しました。
 *	  これまではシンボルタイプを直値(-1,0,1)で指定していましたが、今後はシンボル(VslTyp_*)で指定して下さい。
 *	* Tue Jun 07 22:13:11 JST 2016 Naoyuki Sawa
 *	- 通常ラインタイプの、配当額取得関数(旧:fnGetPay)を、ライン配当額取得関数(新:fnLinPay)と、スキャッター配当額取得関数(新:fnScaPay)に分けました。
 *	  243ウェイ・ルート払い戻しタイプの、配当額取得関数(旧:fnGetPay)を、ウェイ配当額取得(新:fnWayPay)と、スキャッター配当額取得関数(新:fnScaPay)に分けました。
 *	  上記のように変更した理由は、揃ったライン(又はウェイ)によって、配当額が変わるケースに対応するためです。
 *	  揃ったライン(又はウェイ)によって配当額が変わるルールの場合は、引数iLin(又はiRow[])を参照して、揃ったラインに応じた配当額を返して下さい。
 *	  揃ったライン(又はウェイ)によって配当額が変わらないルールの場合は、引数iLin(又はiRow[])を無視して下さい。
 *	* Thu Jul 07 21:12:07 JST 2016 Naoyuki Sawa
 *	- 3行以外の行数に対応しました。
 *	  これまでは、5リール3行固定でしたが、今後は、5リール1行～5リール(VslRow_Max)行まで対応可能になりました。
 *	  行数は、ST_Vsl5nl_GetWin_Inf構造体,又は,ST_Vsl243_GetWin_InfのnRowフィールドで指定して下さい。
 *	- 今回の変更により、'243ウェイ・ルート払い戻しタイプ'は厳密には243ウェイではなく、(nRow^5)ウェイとなります。
 *	  しかし便宜上、243ウェイという名前の方が判り易いので、関数名は変えない事にしました。
 *	- 変更後の検証がまだ不十分です。(特にVsl243_GetWin())
 *	  今後、実際に使いながら、検証する予定です。
 *	* Wed Jul 20 21:23:00 JST 2016 Naoyuki Sawa
 *	- シンボルタイプ(列挙値)を廃止し、シンボル属性(フラグ)に変更しました。
 *	  アプリケーション定義の、シンボルタイプ取得関数(*fnGetTyp)()を、シンボル属性取得関数(*fnGetAtt)()に変更しました。
 *	  この変更によって、通常シンボル,ワイルドシンボル,スキャッターシンボルに加えて、スキャッターワイルドシンボルも表現出来るようになりました。
 *	* Sun Aug 07 21:13:31 JST 2016 Naoyuki Sawa
 *	- VslRel_GetSensorCrossingCount_Linear(),VslRel_GetSensorCrossingCount_Circular()を追加しました。
 *	  直線上,又は,円周上の移動において、特定の位置を跨いだ回数を求める、汎用的な処理ですが、
 *	  今回は、リールアニメーション処理で使用するために作成したので、当モジュールに含める事にしました。
 *	  他の用途にも、使用出来ると思います。
 *	* Mon Aug 29 21:46:36 JST 2016 Naoyuki Sawa
 *	- VslRel_GetSensorExceedingCount_Linear()を追加しました。
 *	* Thu Feb 23 21:53:55 JST 2017 Naoyuki Sawa
 *	- 「dVslDefC.exe対応ユーティリティ」を追加しました。
 *	* Fri Feb 24 21:21:52 JST 2017 Naoyuki Sawa
 *	- dVslDefC.exeが出力する列挙定義スクリプトの、シンボルの列挙定義名を"Symbol_*"→"VslSym_*","GameMode_*"→"VslGmd_*"に変更した事に伴い、「dVslDefC.exe対応ユーティリティ」の関数の仮引数名も変更しました。
 *	  関数の仮引数名の修正だけなので、プログラムの動作には変更有りません。
 *	  今回の変更は些細な変更なので、変更前のコードは残していません。
 *	* Thu Mar 16 22:31:07 JST 2017 Naoyuki Sawa
 *	- dVslDefC.exeがライン定義も出力するように変更した事に伴い、「dVslDefC.exe対応ユーティリティ」もやや大幅な変更を行いました。
 *	  具体的には、以下の通りです。
 *	- レジストリ構造が変わった事に伴い、既存の関数の内部処理を変更しました。
 *	  これまでは、ゲームモードのレジストリキーの直下に、リールストリップとペイテーブルのBLOBが有り、bit15が0(=リールストリップ)か1(=ペイテーブル)かによって、両者を区別していました。
 *	  □変更前
 *	  │VslDef─┬─0        リール0のリールストリップのBLOB
 *	  │        ├─1        リール1のリールストリップのBLOB
 *	  │        ├─2        リール2のリールストリップのBLOB
 *	  │        ├─1|0x8000 シンボル1のペイテーブルのBLOB
 *	  │        ├─2|0x8000 シンボル1のペイテーブルのBLOB
 *	  │        └─3|0x8000 シンボル1のペイテーブルのBLOB
 *	  今回、dVslDefC.exeがライン定義を出力するために、ゲームモードのレジストリキーの直下にライン定義も置いてbit14等で区別する方法も可能ではあったのですが、それでは判り辛いし今後の拡張が行い辛いのでその方法は取らない事にしました。
 *	  素直に、ゲームモードのレジストリキーの直下は、リールストリップのキーと、ペイテーブルのキーと、ライン定義のキーを設けて、それぞれのキーの中にそれぞれのデータを入れるように変更しました。
 *	  □変更後
 *	  │VslDef─┬─1─┬─0 リール0のリールストリップのBLOB
 *	  │        │ 	   ├─1 リール1のリールストリップのBLOB
 *	  │        │     └─2 リール2のリールストリップのBLOB
 *	  │        ├─2─┬─0 ライン0のライン定義のBLOB
 *	  │        │ 	   ├─1 ライン1のライン定義のBLOB
 *	  │        │     └─2 ライン2のライン定義のBLOB
 *	  │        └─3─┬─1 シンボル1のペイテーブルのBLOB
 *	  │           	   ├─2 シンボル2のペイテーブルのBLOB
 *	  │               └─3 シンボル3のペイテーブルのBLOB
 *	  尚、ゲームモードのレジストリキーの直下のキー値を「1=リールストリップ,2=ライン定義,3=ペイテーブル」の順番にした理由は、一般的なアプリケーションの処理の順序に一致させた方が直観的に判り易いと思っただけで、特に意味は有りません。
 *	  0ベースでなく1ベースとした理由も、特に意味は有りません。
 *	- 「dVslDefC.exe対応ユーティリティ」の、既存の関数のやや大幅な変更を行ったので、変更前のコードはコメントアウトして残していません。
 *	  変更前のコードを参照する必要が有る場合は、前回のアーカイブを参照して下さい。
 *	  既存の関数の内部処理は変更しましたが、アプリケーションインターフェイスは変更していないので、アプリケーション側での変更は不要です。
 *	- また、今回、ライン定義を追加した事に伴い、新たにVslDef_GetLinNum()関数とVslDef_GetLinRow()関数を追加しました。
 *	  VslDef_GetLinNum()関数の使い方は、自明だと思います。
 *	  VslDef_GetLinRow()関数の使い方は、iReel引数について注意点が有るので補足します。
 *	  一般的には、VslDef_GetLinRow()関数のiReel引数に渡せる範囲は、0～VslDef_GetRstNum()-1 の範囲です。
 *	  しかし、一つのゲームモードの中で(BET数等によって)リールストリップが変化するようなゲーム仕様の場合は、(例えば)5リールでも、リールストリップのデータは6本以上定義しておいて、アプリケーション側で選択して使用する場合が有り得ます。
 *	  その場合、VslDef_GetRstNum()は6以上の値を返すが、VslDef_GetLinRow()関数のiReel引数に渡せる範囲は6-1未満でなくてはならない(一般的には0～4)というケースも生じ得ます。
 *	  実際のリールの本数はアプリケーションしか知り得ないので、VslDef_GetLinRow()関数のiReel引数には適切な範囲の値を指定して下さい。
 *	  もし、ライン定義で定義されたリール数よりも大きな値をVslDef_GetLinRow()関数のiReel引数に指定すると、VslDef_GetLinRow()関数の中でエラー停止します。
 *	* Fri Mar 17 23:53:28 JST 2017 Naoyuki Sawa
 *	- VslDef_GetRstSym_w()を追加しました。
 *	  既存のVslDef_GetRstSym()との違いは、引数iPosの値を自動的に 0～VslDef_GetRstLen()-1 の範囲に折り返す事です。(関数名の'_w'はWraparoundの'w'です。)
 *	  既存のVslDef_GetRstSym()とVslDef_GetRstLen()を使えば、アプリケーション側でも実現出来る処理ではあるのですが、アプリケーション側でこの処理を行う頻度が特に高いので、アプリケーション側の実装の手間を省くために、当モジュール側で共通処理として用意する事にしました。
 *	* Wed Apr 12 22:29:29 JST 2017 Naoyuki Sawa
 *	- VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
 */
#include "clip.h"
/****************************************************************************
 *	共通処理
 ****************************************************************************/
//入賞判定の共通処理を行う。
static int VslCmn_GetWin(int TBL_Sta[5/*iRel*/][VslRow_Max/*iRow*/],
    int nRow,
    int (*fnScaPay)(int iSym, int nOak, void* arg),
    int (*fnGetAtt)(int iSym, void* arg),
    int (*fnGetSta)(int iRel, int iRow, void* arg),
    void (*fnScaWin)(int iSym, int nOak, int nPay, void* arg),
    void* arg) {
	int nPaySum = 0;						//スキャッターシンボルの賞金総額。
	int TBL_Sca[(5*VslRow_Max)/*nSca*/][2/*[0]=iSym,[1]=nOak*/];	//スキャッターシンボルの出現数。スキャッターワイルドシンボルは含めない。	理論上最大で(5*VslRow_Max)種類のスキャッターシンボルが同時に出現しても対応可能である。(まず有り得ないが)
	int nSca = 0;							//スキャッターシンボルの種類数。スキャッターワイルドシンボルは含めない。
	int nScwCnt =  0;						//スキャッターワイルドシンボル出現数。複数種類のスキャッターワイルドシンボルが出現した場合は合算する。
	int iScwSym = -1;						//スキャッターワイルドシンボルの種類。(nScwCnt>=1)の場合のみ有効。複数種類のスキャッターワイルドシンボルが出現した場合はどれを格納するかは不定です。	スキャッターワイルドシンボルだけが出現した場合は、どのスキャッターワイルドシンボルで払い出しても同じ配当となるようにペイテーブルを設計せよ。	←←←←要注意!!
	if((nRow < 1) || (nRow > VslRow_Max)) { DIE(); }
	//--- 停止形を取得する ---
	{
		int iRel;
		for(iRel = 0; iRel < 5; iRel++) {
			int iRow;
			for(iRow = 0; iRow < nRow; iRow++) {
				int iSym = (*fnGetSta)(iRel, iRow, arg);	//シンボルを取得する。
				int iAtt = (*fnGetAtt)(iSym, arg);		//シンボル属性を取得する。
				TBL_Sta[iRel][iRow] = iSym;			//停止形を格納する。
			    //{{停止形を取得しながら、スキャッターウィンの処理も行う。
				//このシンボルがスキャッター属性を持つシンボルならば…
				if(iAtt & VslAtt_Scatter) {
					//このシンボルがワイルド属性を持つシンボルならば…
					if(iAtt & VslAtt_Wild) {
						//スキャッターワイルドシンボル出現数を増やす。
						nScwCnt++;
						//スキャッターワイルドシンボルの種類を格納する。
						iScwSym = iSym;	//既に格納されていた場合も上書きする。(必須ではない。既に格納されている方を優先しても構わない。)
					//このシンボルがワイルド属性を持たないシンボルならば…
					} else {
						//この種類のスキャッターシンボルが既に出現しているか?
						int iSca;
						for(iSca = 0; iSca < nSca; iSca++) {
							if(TBL_Sca[iSca][0/*iSym*/] == iSym) { break; }
						}
						//この種類のスキャッターシンボルが初出ならば、種類を登録する。
						if(iSca == nSca) {
							if(++nSca > ARRAY_SIZE(TBL_Sca)) { DIE(); }	//当関数のバグ
							TBL_Sca[iSca][0/*iSym*/] = iSym;
							TBL_Sca[iSca][1/*nOak*/] = 0;	//すぐこの下で1になる。
						}
						//この種類のスキャッターシンボルの出現数を増やす。
						TBL_Sca[iSca][1/*nOak*/]++;
					}
				}
			    //}}停止形を取得しながら、スキャッターウィンの処理も行う。
			}
		}
	}
	//--- スキャッターウィン ---
	{
		//ワイルド属性を持たないスキャッターシンボルが一種類以上出現していたら、スキャッターワイルドシンボルはそれに含めて通知する。
		//スキャッターワイルドシンボル単体での通知は行わない。
		if(nSca) {
			int iSca;
			for(iSca = 0; iSca < nSca; iSca++) {
				int iSym = TBL_Sca[iSca][0/*iSym*/];
				int nOak = TBL_Sca[iSca][1/*nOak*/] + nScwCnt/*0以上*/;
				int nPay = (*fnScaPay)(iSym, nOak, arg);
				(*fnScaWin)(iSym, nOak, nPay, arg);	//スキャッターウィン通知
				nPaySum += nPay;	//スキャッターシンボルの賞金総額を加算する。
			}
		//ワイルド属性を持たないスキャッターシンボルが一種類も出現していなければ、スキャッターワイルドシンボル単体で通知する。
		//スキャッターワイルドシンボルが二種類以上出現していた場合は、任意の一種類のスキャッターワイルドシンボルに合算して通知する。
		} else if(nScwCnt) {
			int nPay = (*fnScaPay)(iScwSym, nScwCnt, arg);
			(*fnScaWin)(iScwSym, nScwCnt, nPay, arg);	//スキャッターウィン通知
			nPaySum += nPay;		//スキャッターシンボルの賞金総額を加算する。
		}
	}
	return nPaySum;	//スキャッターシンボルの賞金総額を返す。
}
/****************************************************************************
 *	通常ラインタイプ
 ****************************************************************************/
//通常ラインタイプの、入賞判定処理を行う。
//制約:1つのゲームモードの中でワイルドシンボルは1種類以下である事を前提とする。		⇒{{2016/07/20コメント追記:リールストリップとペイテーブルが注意深く設計されていれば、ワイルドシンボルが2種類以上でも対応可能である。ただしワイルドシンボルが2種類以上有る場合の問題点として、例えば{Wa,Wa,Wa,Wb,Pa}の並びを「Waの純粋3oak又はPaの複合5oak」と見なすか「W*の純粋4oak又はPaの複合5oak」と見なすかが曖昧である。現在は前者の判定としている。現在のアリゴリズムでは後者の判定を行う事は不可能であり、もし後者の判定とする場合はアルゴリズムの変更が必要となる。}}
int Vsl5nl_GetWin(const ST_Vsl5nl_GetWin_Inf* pInf, void* arg) {
	int nPaySum;					//賞金総額
	int TBL_Sta[5/*iRel*/][VslRow_Max/*iRow*/];	//停止形
	//--- 共通処理 ---
	{
		nPaySum = VslCmn_GetWin(TBL_Sta,
			pInf->nRow,
			pInf->fnScaPay,
			pInf->fnGetAtt,
			pInf->fnGetSta,
			pInf->fnScaWin,
			arg);
	}
	//--- ラインウィン ---
	{
		int iLin, iRel, iRow, iSym[5], iAtt;
		int iPurSym, nPurOak, nPurPay;	//純粋コンビネーションの、シンボル,出現数,賞金額
		int iCpxSym, nCpxOak, nCpxPay;	//複合コンビネーションの、シンボル,出現数,賞金額
		for(iLin = 0; iLin < pInf->nLin; iLin++) {
			//このライン上のシンボルを取得する。
			for(iRel = 0; iRel < 5; iRel++) {
				iRow = (*pInf->fnGetRow)(iLin, iRel, arg);
				if((unsigned)iRow >= (unsigned)pInf->nRow) { DIE(); }
				iSym[iRel] = TBL_Sta[iRel][iRow];
			}
			//第1リールに、ワイルド属性を持たないスキャッターシンボルが有れば、純粋コンビネーションも複合コンビネーションも成立しない。
			if((*pInf->fnGetAtt)(iSym[0], arg) == VslAtt_Scatter) { continue; }	//次のラインの処理へ
			//純粋コンビネーションの、シンボル,及び,出現数(1～5),及び,賞金額を求める。
			// - '純粋コンビネーション'とは、自分で勝手につけた呼び方です。
			//   'スキャッターシンボル以外の特定のシンボル'が、第1リールから連続して並んでいる事を指します。
			iPurSym = iSym[0];
			for(nPurOak = 1; nPurOak < 5; nPurOak++) {
				iAtt = (*pInf->fnGetAtt)(iSym[nPurOak], arg);	//このシンボルの属性を取得する。
				if(iAtt == VslAtt_Scatter) { break; }		//このシンボルが、ワイルド属性を持たないスキャッターシンボルならば、ここまで。
				if(iSym[nPurOak] != iPurSym) { break; }		//異なるシンボルが出現したら、ここまで。
			}
			nPurPay = (*pInf->fnLinPay)(iPurSym, nPurOak, iLin, arg);
			//複合コンビネーションの、シンボル,及び,出現数(1～5),及び,賞金額を求める。
			// - '複合コンビネーション'とは、自分で勝手につけた呼び方です。
			//   'スキャッターシンボル以外の特定のシンボル'が、0個以上のワイルドシンボルを含んで、第1リールから連続して並んでいる事を指します。
			//   'スキャッターシンボル以外の特定のシンボル'自体が、ワイルドシンボルである事も有り得ます。
			iCpxSym = iSym[0];
			for(nCpxOak = 1; nCpxOak < 5; nCpxOak++) {
				iAtt = (*pInf->fnGetAtt)(iSym[nCpxOak], arg);	//このシンボルの属性を取得する。
				if(iAtt == VslAtt_Scatter) { break; }		//このシンボルが、ワイルド属性を持たないスキャッターシンボルならば、ここまで。
				if(iSym[nCpxOak] != iCpxSym) {			//異なるシンボルが出現したら…
					if(!(iAtt & VslAtt_Wild)) {		//このシンボルがワイルド属性を持っていなければ…
						if(!((*pInf->fnGetAtt)(iCpxSym, arg) & VslAtt_Wild)) { break; }	//ワイルド属性を持っていない初出のシンボルでなければ、ここまで。
						iCpxSym = iSym[nCpxOak];	//ワイルド属性を持っていない初出のシンボルを格納する。
					}
				}
			}
			nCpxPay = (*pInf->fnLinPay)(iCpxSym, nCpxOak, iLin, arg);
			//純粋コンビネーションの賞金額の方が大きければ…
			if(nPurPay > nCpxPay) {
				//純粋コンビネーションを通知する。
				(*pInf->fnLinWin)(iPurSym, nPurOak, iLin, nPurPay, arg);	//ラインウィン通知
				nPaySum += nPurPay;	//賞金総額を加算する。
			//複合コンビネーションの賞金額の方が大きい,又は,同じならば、
			} else {
				//複合コンビネーションを通知する。
				// - 複合コンビネーションの方が、出現数が大きい値になっているはずである。
				//   賞金額が同じ場合、出現数が大きい方で入賞を表示する方が、遊技者に不信感を与えないだろうと思い、こうする事にした。
				(*pInf->fnLinWin)(iCpxSym, nCpxOak, iLin, nCpxPay, arg);	//ラインウィン通知
				nPaySum += nCpxPay;	//賞金総額を加算する。
			}
		}
	}
	return nPaySum;	//賞金総額を返す。
}
/****************************************************************************
 *	243ウェイ・ルート払い戻しタイプ
 ****************************************************************************/
//243ウェイ・ルート払い戻しタイプの、入賞判定処理を行う。
//制約:ワイルドシンボルの並びには配当額が設定されていない事を前提とする。
int Vsl243_GetWin(const ST_Vsl243_GetWin_Inf* pInf, void* arg) {
	int nPaySum;					//賞金総額
	int TBL_Sta[5/*iRel*/][VslRow_Max/*iRow*/];	//停止形
	//--- 共通処理 ---
	{
		nPaySum = VslCmn_GetWin(TBL_Sta,
			pInf->nRow,
			pInf->fnScaPay,
			pInf->fnGetAtt,
			pInf->fnGetSta,
			pInf->fnScaWin,
			arg);
	}
	//--- ウェイウィン ---
	{
		int bWay[5], iRow[5], iSym[5], iAtt, nPay;
		bWay[0] = 0;	//1リールウェイ入賞フラグ
		for(iRow[0] = 0; iRow[0] < pInf->nRow; iRow[0]++) {
			iSym[0] = TBL_Sta[0][iRow[0]];			//このリールのシンボルを取得する。
			iAtt = (*pInf->fnGetAtt)(iSym[0], arg);		//このリールのシンボルの属性を取得する。
			if(iAtt == VslAtt_Scatter) { continue; }	//このシンボルが、ワイルド属性を持たないスキャッターシンボルならば、ここまで。
			if(iAtt & VslAtt_Wild) { iSym[0] = -1; }	//このシンボルがワイルド属性を持っていたら、ワイルドシンボルを示す値として(-1)を格納しておく。
			{
				bWay[1] = 0;	//2リールウェイ入賞フラグ
				for(iRow[1] = 0; iRow[1] < pInf->nRow; iRow[1]++) {
					iSym[1] = TBL_Sta[1][iRow[1]];			//このリールのシンボルを取得する。
					iAtt = (*pInf->fnGetAtt)(iSym[1], arg);		//このリールのシンボルの属性を取得する。
					if(iAtt == VslAtt_Scatter) { continue; }	//このシンボルが、ワイルド属性を持たないスキャッターシンボルならば、ここまで。
					if(iAtt & VslAtt_Wild) { iSym[1] = -1; }	//このシンボルがワイルド属性を持っていたら、ワイルドシンボルを示す値として(-1)を格納しておく。
					if(iSym[0] != iSym[1]) {			//前のリールのシンボルと、このリールのシンボルが違ったら…
						if(iSym[0] != -1) {			//前のリールのシンボルが、ワイルドシンボルでなければ…
							if(iSym[1] != -1) {		//このリールのシンボルがワイルドシンボルでなければ…
								continue;		//このリールのこのウェイから派生する入賞判定を行わない。
							} else {			//このリールのシンボルがワイルドシンボルならば…
								iSym[1] = iSym[0];	//このリールのシンボルを、前のリールのシンボルに合わせる。
							}
						}
					}
					{
						bWay[2] = 0;	//3リールウェイ入賞フラグ
						for(iRow[2] = 0; iRow[2] < pInf->nRow; iRow[2]++) {
							iSym[2] = TBL_Sta[2][iRow[2]];			//このリールのシンボルを取得する。
							iAtt = (*pInf->fnGetAtt)(iSym[2], arg);		//このリールのシンボルの属性を取得する。
							if(iAtt == VslAtt_Scatter) { continue; }	//このシンボルが、ワイルド属性を持たないスキャッターシンボルならば、ここまで。
							if(iAtt & VslAtt_Wild) { iSym[2] = -1; }	//このシンボルがワイルド属性を持っていたら、ワイルドシンボルを示す値として(-1)を格納しておく。
							if(iSym[1] != iSym[2]) {			//前のリールのシンボルと、このリールのシンボルが違ったら…
								if(iSym[1] != -1) {			//前のリールのシンボルが、ワイルドシンボルでなければ…
									if(iSym[2] != -1) {		//このリールのシンボルがワイルドシンボルでなければ…
										continue;		//このリールのこのウェイから派生する入賞判定を行わない。
									} else {			//このリールのシンボルがワイルドシンボルならば…
										iSym[2] = iSym[1];	//このリールのシンボルを、前のリールのシンボルに合わせる。
									}
								}
							}
							{
								bWay[3] = 0;	//4リールウェイ入賞フラグ
								for(iRow[3] = 0; iRow[3] < pInf->nRow; iRow[3]++) {
									iSym[3] = TBL_Sta[3][iRow[3]];			//このリールのシンボルを取得する。
									iAtt = (*pInf->fnGetAtt)(iSym[3], arg);		//このリールのシンボルの属性を取得する。
									if(iAtt == VslAtt_Scatter) { continue; }	//このシンボルが、ワイルド属性を持たないスキャッターシンボルならば、ここまで。
									if(iAtt & VslAtt_Wild) { iSym[3] = -1; }	//このシンボルがワイルド属性を持っていたら、ワイルドシンボルを示す値として(-1)を格納しておく。
									if(iSym[2] != iSym[3]) {			//前のリールのシンボルと、このリールのシンボルが違ったら…
										if(iSym[2] != -1) {			//前のリールのシンボルが、ワイルドシンボルでなければ…
											if(iSym[3] != -1) {		//このリールのシンボルがワイルドシンボルでなければ…
												continue;		//このリールのこのウェイから派生する入賞判定を行わない。
											} else {			//このリールのシンボルがワイルドシンボルならば…
												iSym[3] = iSym[2];	//このリールのシンボルを、前のリールのシンボルに合わせる。
											}
										}
									}
									{
										bWay[4] = 0;	//5リールウェイ入賞フラグ
										for(iRow[4] = 0; iRow[4] < pInf->nRow; iRow[4]++) {
											iSym[4] = TBL_Sta[4][iRow[4]];			//このリールのシンボルを取得する。
											iAtt = (*pInf->fnGetAtt)(iSym[4], arg);		//このリールのシンボルの属性を取得する。
											if(iAtt == VslAtt_Scatter) { continue; }	//このシンボルが、ワイルド属性を持たないスキャッターシンボルならば、ここまで。
											if(iAtt & VslAtt_Wild) { iSym[4] = -1; }	//このシンボルがワイルド属性を持っていたら、ワイルドシンボルを示す値として(-1)を格納しておく。
											if(iSym[3] != iSym[4]) {			//前のリールのシンボルと、このリールのシンボルが違ったら…
												if(iSym[3] != -1) {			//前のリールのシンボルが、ワイルドシンボルでなければ…
													if(iSym[4] != -1) {		//このリールのシンボルがワイルドシンボルでなければ…
														continue;		//このリールのこのウェイから派生する入賞判定を行わない。
													} else {			//このリールのシンボルがワイルドシンボルならば…
														iSym[4] = iSym[3];	//このリールのシンボルを、前のリールのシンボルに合わせる。
													}
												}
											}
											//5リールウェイ入賞判定
											if(iSym[4] != -1) {	//このリールまでに一つでもワイルドシンボル以外が有れば…	「243ウェイ・ルート払い戻しタイプ」においては、ワイルドシンボルだけの並びに対して配当を設定しない。後述のコメントを参照せよ。
												nPay = (*pInf->fnWayPay)(iSym[4], 5/*nOak*/, iRow, arg);
												(*pInf->fnWayWin)(iSym[4], 5/*nOak*/, iRow, nPay, arg);	//ウェイウィン通知
												nPaySum += nPay;	//賞金総額を加算する。
												bWay[4] = 1;	//5リールウェイ入賞有り
											}
										}
										if(bWay[4]) {	//5リールウェイ入賞有りならば、この4リールウェイ以下の入賞判定を行わない。
											bWay[3] = 1;	//4リールウェイ入賞有りと見なす
										} else {
											//4リールウェイ入賞判定
											if(iSym[3] != -1) {	//このリールまでに一つでもワイルドシンボル以外が有れば…	「243ウェイ・ルート払い戻しタイプ」においては、ワイルドシンボルだけの並びに対して配当を設定しない。後述のコメントを参照せよ。
												nPay = (*pInf->fnWayPay)(iSym[3], 4/*nOak*/, iRow, arg);
												(*pInf->fnWayWin)(iSym[3], 4/*nOak*/, iRow, nPay, arg);	//ウェイウィン通知
												nPaySum += nPay;	//賞金総額を加算する。
												bWay[3] = 1;	//4リールウェイ入賞有り
											}
										}
									}
								}
								if(bWay[3]) {	//4リールウェイ入賞有りならば、この3リールウェイ以下の入賞判定を行わない。
									bWay[2] = 1;	//3リールウェイ入賞有りと見なす
								} else {
									//3リールウェイ入賞判定
									if(iSym[2] != -1) {	//このリールまでに一つでもワイルドシンボル以外が有れば…	「243ウェイ・ルート払い戻しタイプ」においては、ワイルドシンボルだけの並びに対して配当を設定しない。後述のコメントを参照せよ。
										nPay = (*pInf->fnWayPay)(iSym[2], 3/*nOak*/, iRow, arg);
										(*pInf->fnWayWin)(iSym[2], 3/*nOak*/, iRow, nPay, arg);	//ウェイウィン通知
										nPaySum += nPay;	//賞金総額を加算する。
										bWay[2] = 1;	//3リールウェイ入賞有り
									}
								}
							}
						}
						if(bWay[2]) {	//3リールウェイ入賞有りならば、この2リールウェイ以下の入賞判定を行わない。
							bWay[1] = 1;	//2リールウェイ入賞有りと見なす
						} else {
							//2リールウェイ入賞判定
							if(iSym[1] != -1) {	//このリールまでに一つでもワイルドシンボル以外が有れば…	「243ウェイ・ルート払い戻しタイプ」においては、ワイルドシンボルだけの並びに対して配当を設定しない。後述のコメントを参照せよ。
								nPay = (*pInf->fnWayPay)(iSym[1], 2/*nOak*/, iRow, arg);
								(*pInf->fnWayWin)(iSym[1], 2/*nOak*/, iRow, nPay, arg);	//ウェイウィン通知
								nPaySum += nPay;	//賞金総額を加算する。
								bWay[1] = 1;	//2リールウェイ入賞有り
							}
						}
					}
				}
				if(bWay[1]) {	//2リールウェイ入賞有りならば、この1リールウェイ以下の入賞判定を行わない。
					bWay[0] = 1;	//1リールウェイ入賞有りと見なす
				} else {
					//1リールウェイ入賞判定
					if(iSym[0] != -1) {	//このリールまでに一つでもワイルドシンボル以外が有れば…	「243ウェイ・ルート払い戻しタイプ」においては、ワイルドシンボルだけの並びに対して配当を設定しない。後述のコメントを参照せよ。
						nPay = (*pInf->fnWayPay)(iSym[0], 1/*nOak*/, iRow, arg);
						(*pInf->fnWayWin)(iSym[0], 1/*nOak*/, iRow, nPay, arg);	//ウェイウィン通知
						nPaySum += nPay;	//賞金総額を加算する。
						bWay[0] = 1;	//1リールウェイ入賞有り
					}
				}
			}
		}
	}
	return nPaySum;	//賞金総額を返す。
}
//■「243ウェイ・ルート払い戻しタイプ」においては、ワイルドシンボルだけの並びに対して配当を設定しない。
//│そうしないと、以下の例のような問題が生じるからです。
//□問題が生じる例
//│仮にワイルドシンボルだけの並びに対して配当を設定したと仮定して、下表のようなペイテーブルを設定したとする。
//│  PayTable
//│    Sym 4oak 5oak
//│    Wd    10   15
//│    Pa     1    5
//│    Pb     2   20
//│遊技中に、下図のような停止形が出現したとする。
//│  1st 2nd 3rd 4th 5th
//│   -   -   -   -  Pa 
//│  Wd  Wd  Wd  Wd   - 
//│   -   -   -   -  Pb 
//│この時、賞金額が決定出来ない問題が生じる。具体的には、以下の通りです。
//│  ①仮に「Wd Wd Wd Wd Pa」と「Wd Wd Wd Wd Pb」に対して払い出しを行った場合、
//│    「Wd Wd Wd Wd」よりも「Wd Wd Wd Wd Wa」の方が安いのに、「Wd Wd Wd Wd」を捨てて「Wd Wd Wd Wd Wa」を取って良いのか？という問題が生じる。
//│  ②仮に「Wd Wd Wd Wd」と「Wd Wd Wd Wd Pb」に対して払い出しを行った場合、
//│    「Wd Wd Wd Wd」は「Wd Wd Wd Wd Pb」に含まれるのに、両方に払い出して良いのか？という問題が生じる。
//│①②どちらの方法を取っても、243ウェイ機の原則である、「ウェイ毎に最大の賞金の組み合わせだけに対して支払われる」というルールに反してしまう。
//□解決方法
//│既存のオンラインビデオスロットでは、ワイルドシンボルだけの並びに対して配当を設定しない事で、上記の問題を回避している。
//│また、1stリールにワイルドシンボルを配置しない事で、ワイルドシンボルだけの並びに対して配当を設定しない事を自然に見せている機種も多いようだ。
/****************************************************************************
 *	リールアニメーション処理の補助関数
 ****************************************************************************/
//直線上の移動において、センサを跨いだ回数を求める。
//[in]
//		oldpos		移動前の位置
//		vec		移動距離					(vec＞0.0)ならば正方向の移動、(vec＜0.0)ならば逆方向の移動、(vec＝0.0)ならば移動無し
//		snspos		センサの位置
//		pnewpos		移動後の位置を格納する変数へのポインタ		NULLを指定すると、移動後の位置を格納しません。
//[out]
//		戻り値		正方向にセンサを跨いだ回数(1),又は,逆方向にセンサを跨いだ回数(-1),又は,センサを跨いでいない(0)を返す。
//[note]
//		- 正方向の移動の場合、移動前の位置がセンサの位置未満で、移動後の位置がセンサの位置以上ならば、センサを跨いだと見なす。
//		  逆方向の移動の場合、移動前の位置がセンサの位置以上で、移動後の位置がセンサの位置未満ならば、センサを跨いだと見なす。
//		- リールアニメーション処理では、多分、VslRel_GetSensorCrossingCount_Circular()しか使わないと思います。
//		  VslRel_GetSensorCrossingCount_Linear()は、一応、用意しておいただけで、多分、使う事は無いと思います。
int VslRel_GetSensorCrossingCount_Linear(double oldpos, double vec, double snspos, double* pnewpos/*NULL可*/) {
	int count = 0;	//この変数に、正方向にセンサを跨いだ回数(1),又は,逆方向にセンサを跨いだ回数(-1),又は,センサを跨いでいない(0)を格納する。
	//移動後の位置を求める。
	const double newpos = oldpos + vec;
	//移動方向が正方向ならば…
	if(vec > 0.0) {
		//移動前の位置がセンサの位置未満で、移動後の位置がセンサの位置以上ならば、正方向にセンサを跨いだと見なして1加算する。
		if((oldpos < snspos) && (newpos >= snspos)) { count++; }
	//移動方向が逆方向ならば…
	} else if(vec < 0.0) {
		//移動前の位置がセンサの位置以上で、移動後の位置がセンサの位置未満ならば、逆方向にセンサを跨いだと見なして1減算する。
		if((oldpos >= snspos) && (newpos < snspos)) { count--; }
	//移動方向が無ければ…
	} else {
		/** no job **/
	}
	//移動後の位置を格納する変数のポインタが指定されていたら、移動後の位置を格納する。
	if(pnewpos) { *pnewpos = newpos; }
	//正方向にセンサを跨いだ回数(1),又は,逆方向にセンサを跨いだ回数(-1),又は,センサを跨いでいない(0)を返す。
	return count;
}
/*--------------------------------------------------------------------------*/
//円周上の移動において、センサを跨いだ回数を求める。
//[in]
//		oldpos		移動前の位置					[lbound,ubound)の範囲外を指定しても構いません。当関数が自動的に補正します。			リールアニメーション処理においては、現在のリール位置を指定する事になるだろう。
//		vec		移動距離					(vec＞0.0)ならば正方向の移動、(vec＜0.0)ならば逆方向の移動、(vec＝0.0)ならば移動無し		リールアニメーション処理においては、回転速度を指定する事になるだろう。
//		snspos		センサの位置					[lbound,ubound)の範囲外を指定しても構いません。当関数が自動的に補正します。			リールアニメーション処理においては、停止アニメーション状態(バウンド状態など)へ移行するリール位置を指定する事になるだろう。
//		lbound		下界						┬位置の値を[lbound,ubound)の範囲に補正します。							リールアニメーション処理においては、0.0を指定する事になるだろう。
//		ubound		上界						┘												リールアニメーション処理においては、リールストリップ長を指定する事になるだろう。
//		pnewpos		移動後の位置を格納する変数へのポインタ		NULLを指定すると、移動後の位置を格納しません。							呼び出し側で移動後の位置を別途計算しても構わないが、演算誤差でセンサを跨いだ位置と移動後の位置が矛盾する事を避けるために、当関数が返した移動後の位置を使用する方が望ましい。
//[out]
//		戻り値		正方向にセンサを跨いだ回数(N),又は,逆方向にセンサを跨いだ回数(-N),又は,センサを跨いでいない(0)を返す。						リールアニメーション処理においては、0か0以外かしか見なくて良いだろう。一回の移動で一周分以上回るような速度は設定しないし、万一有ったとしても最初のトリガ以外は無視するから。
//[note]
//		- 正方向の移動の場合、移動前の位置がセンサの位置未満で、移動後の位置がセンサの位置以上ならば、センサを跨いだと見なす。
//		  逆方向の移動の場合、移動前の位置がセンサの位置以上で、移動後の位置がセンサの位置未満ならば、センサを跨いだと見なす。
int VslRel_GetSensorCrossingCount_Circular(double oldpos, double vec, double snspos, double lbound, double ubound, double* pnewpos/*NULL可*/) {
	int count = 0;	//この変数に、正方向にセンサを跨いだ回数(N),又は,逆方向にセンサを跨いだ回数(-N),又は,センサを跨いでいない(0)を格納する。
	//領域の幅を求める。
	const double width = ubound - lbound;
	if(width <= 0.0) { DIE(); }	//(lbound≧ubound)が指定された。呼び出し側のバグです。
	//移動前の位置を、[lbound,ubound)の範囲に補正する。
	oldpos -= lbound;
	oldpos = fmod(oldpos, width);
	if(oldpos < 0.0) { oldpos += width; }
	oldpos += lbound;
	//センサの位置を、[lbound,ubound)の範囲に補正する。
	snspos -= lbound;
	snspos = fmod(snspos, width);
	if(snspos < 0.0) { snspos += width; }
	snspos += lbound;
	{
		//初回のために、移動前の位置を、仮想的な前回の移動後の位置とする。
		double newpos = oldpos;
		//移動方向が正方向ならば…
		if(vec > 0.0) {
			do {
				//前回の移動後の位置を、今回の移動前の位置とする。
				oldpos = newpos;
				//移動後の位置を求める。
				newpos = oldpos + vec;	//(newpos≧ubound)になっても構わない。
				//移動前の位置がセンサの位置未満で、移動後の位置がセンサの位置以上ならば、正方向にセンサを跨いだと見なして1加算する。
				if((oldpos < snspos) && (newpos >= snspos)) { count++; }
				//移動後の位置が上界を超過した分を、次回の移動距離とする。
				vec = newpos - ubound;	//(vec＜0.0)になっても構わない。								//┐
				//移動後の位置が上界以上ならば…											//│
				if(vec >= 0.0) {	//「if(newpos>=ubound){～」で判定しても同じです。	①←┐					//├この処理順序を逆にしないように注意!!
					//移動後の位置を、下界に折り返す。					//　│					//│
					newpos = lbound;							//　│					//┘
					//移動後の位置がセンサの位置以上(イコール判定でも構わない)ならば、正方向にセンサを跨いだと見なして1加算する。	//┬(snspos==lbound)が指定された場合のための判定処理です。
					if(newpos >= snspos) { count++; }	//(newpos==snspos)で判定しても構わない。				//┘(newpos==snspos)でなく(newpos>=snspos)で判定した理由は、上の処理と見た目を合わせるためだけで、実際にはどちらでも構いません。
				}										//　│
			} while(vec > 0.0);	//次回の移動距離が残っている間、繰り返す。			②←┴①は≧,②は＞である事に注意しろ。
		//移動方向が逆方向ならば…
		} else if(vec < 0.0) {
			do {
				//前回の移動後の位置を、今回の移動前の位置とする。
				oldpos = newpos;
				//移動後の位置を求める。
				newpos = oldpos + vec;	//(newpos＜lbound)になっても構わない。
				//移動前の位置がセンサの位置以上で、移動後の位置がセンサの位置未満ならば、逆方向にセンサを跨いだと見なして1減算する。	//┬(snspos==lbound)が指定された場合もここで判定出来ます。
				if((oldpos >= snspos) && (newpos < snspos)) { count--; }								//┘移動方向が正方向の場合の処理と違って、移動後の位置を折り返す処理の中で、センサを跨いだかどうかの判定を行う必要は有りません。
				//移動後の位置が下界を下回った分を、次回の移動距離とする。
				vec = newpos - lbound;	//(vec＞0.0)になっても構わない。								//┐
				//移動後の位置が下界未満ならば…											//│
				if(vec < 0.0) {		//「if(newpos<lbound){～」で判定しても同じです。						//├この処理順序を逆にしないように注意!!
					//移動後の位置を、上界に折り返す。										//│
					newpos = ubound;	//一時的に[lbound,ubound)の範囲外となりますが、必ず次回のループが有るので大丈夫です。	//┘
				}
			} while(vec < 0.0);	//次回の移動距離が残っている間、繰り返す。
		}
		//移動後の位置を格納する変数のポインタが指定されていたら、移動後の位置を格納する。
		if(pnewpos) { *pnewpos = newpos; }
	}
	//正方向にセンサを跨いだ回数(N),又は,逆方向にセンサを跨いだ回数(-N),又は,センサを跨いでいない(0)を返す。
	return count;
}
/*--------------------------------------------------------------------------*/
//□テストスイート
#if 0
void TestSuite() {
	int count;
	double oldpos, vec, snspos, newpos, lbound, ubound;
	//=== VslRel_GetSensorCrossingCount_Linear ===
	//--- Test1.1 ---
	puts("Test1.1");
	//			0.0		1.0
	//			▽				センサ
	//			★──────→☆		移動前→移動後
	oldpos = 0.0, vec = 1.0, snspos = 0.0;
	count = VslRel_GetSensorCrossingCount_Linear(oldpos, vec, snspos, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, newpos);	//count =  0, oldpos =  0.0, vec =  1.0, snspos =  0.0, newpos =  1.0
	//			0.0		1.0
	//			▽				センサ
	//			☆←──────★		移動前→移動後
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Linear(oldpos, vec, snspos, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, newpos);	//count =  0, oldpos =  0.0, vec =  1.0, snspos =  0.0, newpos =  1.0
	//--- Test1.2 ---
	puts("Test1.2");
	//		-0.5	0.0	0.5
	//			▽					センサ
	//		★──────→☆			移動前→移動後
	oldpos = -0.5, vec = 1.0, snspos = 0.0;
	count = VslRel_GetSensorCrossingCount_Linear(oldpos, vec, snspos, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, newpos);	//count =  1, oldpos = -0.5, vec =  1.0, snspos =  0.0, newpos =  0.5
	//		-0.5	0.0	0.5
	//			▽					センサ
	//		☆←──────★			移動前→移動後
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Linear(oldpos, vec, snspos, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, newpos);	//count = -1, oldpos =  0.5, vec = -1.0, snspos =  0.0, newpos = -0.5
	//--- Test1.3 ---
	puts("Test1.3");
	//	-1.0		0.0
	//			▽					センサ
	//	★──────→☆				移動前→移動後
	oldpos = -1.0, vec = 1.0, snspos = 0.0;
	count = VslRel_GetSensorCrossingCount_Linear(oldpos, vec, snspos, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, newpos);	//count =  1, oldpos = -1.0, vec =  1.0, snspos =  0.0, newpos =  0.0
	//	-1.0		0.0
	//			▽					センサ
	//	☆←──────★				移動前→移動後
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Linear(oldpos, vec, snspos, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, newpos);	//count = -1, oldpos =  0.0, vec = -1.0, snspos =  0.0, newpos = -1.0
	//=== VslRel_GetSensorCrossingCount_Circular ===
	//--- Test2.1 ---
	puts("Test2.1");
	//		-0.5	0.0		1.0	1.5
	//		●				〇	下界～上界
	//			▽				センサ
	//			★──────→☆		移動前→移動後
	oldpos = 0.0, vec = 1.0, snspos = 0.0, lbound = -0.5, ubound = 1.5;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count =  0, oldpos =  0.0, vec =  1.0, snspos =  0.0, lbound = -0.5, ubound =  1.5, newpos =  1.0
	//		-0.5	0.0		1.0	1.5
	//		●				〇	下界～上界
	//			▽				センサ
	//			☆←──────★		移動前→移動後
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count =  0, oldpos =  1.0, vec = -1.0, snspos =  0.0, lbound = -0.5, ubound =  1.5, newpos =  0.0
	//--- Test2.2 ---
	puts("Test2.2");
	//			0.0		1.0
	//			●		〇		下界～上界
	//			▽				センサ
	//			★──────→		移動前→移動後
	//			☆
	oldpos = 0.0, vec = 1.0, snspos = 0.0, lbound = 0.0, ubound = 1.0;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count =  1, oldpos =  0.0, vec =  1.0, snspos =  0.0, lbound =  0.0, ubound =  1.0, newpos =  0.0
	//			0.0		1.0
	//			●		〇		下界～上界
	//			▽				センサ
	//			★				移動前→移動後
	//			☆←──────
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count = -1, oldpos =  0.0, vec = -1.0, snspos =  0.0, lbound =  0.0, ubound =  1.0, newpos =  0.0
	//--- Test2.3 ---
	puts("Test2.3");
	//			0.0	0.5	1.0
	//			●		〇		下界～上界
	//				▽			センサ
	//			★──────→		移動前→移動後
	//			☆
	oldpos = 0.0, vec = 1.0, snspos = 0.5, lbound = 0.0, ubound = 1.0;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count =  1, oldpos =  0.0, vec =  1.0, snspos =  0.5, lbound =  0.0, ubound =  1.0, newpos =  0.0
	//			0.0	0.5	1.0
	//			●		〇		下界～上界
	//				▽			センサ
	//			★				移動前→移動後
	//			☆←──────
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count = -1, oldpos =  0.0, vec = -1.0, snspos =  0.5, lbound =  0.0, ubound =  1.0, newpos =  0.0
	//--- Test2.4 ---
	puts("Test2.4");
	//			0.0	0.5	1.0
	//			●		〇		下界～上界
	//				▽			センサ
	//			★──────→		移動前→移動後
	//			　──────→
	//			　──────→
	//			☆
	oldpos = 0.0, vec = 3.0, snspos = 0.5, lbound = 0.0, ubound = 1.0;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count =  3, oldpos =  0.0, vec =  3.0, snspos =  0.5, lbound =  0.0, ubound =  1.0, newpos =  0.0
	//			0.0	0.5	1.0
	//			●		〇		下界～上界
	//				▽			センサ
	//			★				移動前→移動後
	//			　←──────
	//			　←──────
	//			☆←──────
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count = -3, oldpos =  0.0, vec = -3.0, snspos =  0.5, lbound =  0.0, ubound =  1.0, newpos =  0.0
	//--- Test2.5 ---
	puts("Test2.5");
	//			0.0	0.5	1.0
	//			●		〇		下界～上界
	//				▽			センサ
	//			★──────→		移動前→移動後
	//			　──────→
	//			　─────→☆
	oldpos = 0.0, vec = 2.9, snspos = 0.5, lbound = 0.0, ubound = 1.0;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count =  3, oldpos =  0.0, vec =  2.9, snspos =  0.5, lbound =  0.0, ubound =  1.0, newpos =  0.9
	//			0.0	0.5	1.0
	//			●		〇		下界～上界
	//				▽			センサ
	//			　←─────★		移動前→移動後
	//			　←──────
	//			☆←──────
	oldpos = newpos, vec = -vec;
	count = VslRel_GetSensorCrossingCount_Circular(oldpos, vec, snspos, lbound, ubound, &newpos);
	printf("count = % d, oldpos = % .1f, vec = % .1f, snspos = % .1f, lbound = % .1f, ubound = % .1f, newpos = % .1f\n", count, oldpos, vec, snspos, lbound, ubound, newpos);	//count = -3, oldpos =  0.9, vec = -2.9, snspos =  0.5, lbound =  0.0, ubound =  1.0, newpos =  0.0
}
#endif
/*--------------------------------------------------------------------------*/
//□使用例
#if 0
//※TODO:
#endif
/*--------------------------------------------------------------------------*/
//直線上の移動において、センサを超えた回数を求める。
//[in]
//		oldpos		移動前の位置
//		vec		移動距離					(vec＞0.0)ならば正方向の移動、(vec＜0.0)ならば逆方向の移動、(vec＝0.0)ならば移動無し
//		snspos		センサの位置
//		pnewpos		移動後の位置を格納する変数へのポインタ		NULLを指定すると、移動後の位置を格納しません。
//[out]
//		戻り値		正方向にセンサを超えた回数(1),又は,逆方向にセンサを超えた回数(-1),又は,センサを超えていない(0)を返す。
//[note]
//		- 正方向の移動の場合、移動前の位置に関係無く、移動後の位置がセンサの位置以上ならば、センサを超えたと見なす。
//		  逆方向の移動の場合、移動前の位置に関係無く、移動後の位置がセンサの位置未満ならば、センサを超えたと見なす。
//		- 実際の用途としては、位置の判定ではなく、速度の判定を行うために、当関数を追加しました。
//		  <使用例>
//		  │void BoundStart() {
//		  │        double dSpeed       =  1.0;	//初速度
//		  │  const double dAccel       = -0.3;	//加減速度
//		  │  const double dTargetSpeed = -1.0;	//目標速度
//		  │  for(;;) {
//		  │    schedule();
//		  │    //現在速度に加減速度(+ならば正方向加速,-ならば逆方向加速)を加算して、現在速度が目標速度に達したら…
//		  │    if(VslRel_GetSensorExceedingCount_Linear(dSpeed, dAccel, dTargetSpeed, &dSpeed)) {
//		  │      //現在速度を、目標速度に切り詰める。
//		  │      dSpeed = dTargetSpeed;
//		  │      //目標速度に到達した時の処理を行う。
//		  │      printf("目標速度に到達しました。\n"); //実際には、状態遷移等の処理を行う。
//		  │    }
//		  │  }
//		  │}
int VslRel_GetSensorExceedingCount_Linear(double oldpos, double vec, double snspos, double* pnewpos/*NULL可*/) {
	int count = 0;	//この変数に、正方向にセンサを超えた回数(1),又は,逆方向にセンサを超えた回数(-1),又は,センサを超えていない(0)を格納する。
	//移動後の位置を求める。
	const double newpos = oldpos + vec;
	//移動方向が正方向ならば…
	if(vec > 0.0) {
		//移動前の位置に関係無く、移動後の位置がセンサの位置以上ならば、正方向にセンサを超えたと見なして1加算する。
		if(newpos >= snspos) { count++; }
	//移動方向が逆方向ならば…
	} else if(vec < 0.0) {
		//移動前の位置に関係無く、移動後の位置がセンサの位置未満ならば、逆方向にセンサを超えたと見なして1減算する。
		if(newpos <  snspos) { count--; }
	//移動方向が無ければ…
	} else {
		/** no job **/
	}
	//移動後の位置を格納する変数のポインタが指定されていたら、移動後の位置を格納する。
	if(pnewpos) { *pnewpos = newpos; }
	//正方向にセンサを超えた回数(1),又は,逆方向にセンサを超えた回数(-1),又は,センサを超えていない(0)を返す。
	return count;
}
/****************************************************************************
 *	dVslDefC.exe対応ユーティリティ
 ****************************************************************************/
//シンボルの数を返す。
//[in]
//	pEnmKey			EnmDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_EnmDef)
//	_RegKey_VslSym		RegKey_VslSymの値		RegKey_VslSym
//[out]
//	戻り値			シンボルの数			VslSym_Maxと同じ値になるはずです。
//[note]
//	- シンボルの列挙値は1ベースなので、1～シンボルの数 の範囲の値が、シンボルの列挙値として有効です。
//	- 当関数が返す値は、EnmDef.hに出力されている、VslSym_Maxと同じ値になるはずです。
//	  アプリケーションは、必ずしも、当関数を呼び出す必要は有りません。
int VslDef_GetSymNum(const void* pEnmKey, int _RegKey_VslSym) {
	return EnmDef_GetNum(pEnmKey, _RegKey_VslSym);
}
/*--------------------------------------------------------------------------*/
//{{2017/04/12追加:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
//シンボルの名前を返す。
//[in]
//	pEnmKey			EnmDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_EnmDef)
//	_RegKey_VslSym		RegKey_VslSymの値		RegKey_VslSym
//	iVslSym			シンボル番号			VslSym_*
//[out]
//	戻り値			シンボルの名前
const char* VslDef_GetSymName(const void* pEnmKey, int _RegKey_VslSym, int iVslSym) {
	return EnmDef_GetName(pEnmKey, _RegKey_VslSym, iVslSym);
}
/*--------------------------------------------------------------------------*/
//シンボルの説明を返す。
//[in]
//	pEnmKey			EnmDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_EnmDef)
//	_RegKey_VslSym		RegKey_VslSymの値		RegKey_VslSym
//	iVslSym			シンボル番号			VslSym_*
//[out]
//	戻り値			シンボルの説明
const char* VslDef_GetSymDesc(const void* pEnmKey, int _RegKey_VslSym, int iVslSym) {
	return EnmDef_GetDesc(pEnmKey, _RegKey_VslSym, iVslSym);
}
//}}2017/04/12追加:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
/*--------------------------------------------------------------------------*/
//ゲームモードの数を返す。
//[in]
//	pEnmKey			EnmDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_EnmDef)
//	_RegKey_VslGmd		RegKey_VslGmdの値		RegKey_VslGmd
//[out]
//	戻り値			ゲームモードの数		VslGmd_Maxと同じ値になるはずです。
//[note]
//	- ゲームモードの列挙値は1ベースなので、1～ゲームモードの数 の範囲の値が、ゲームモードの列挙値として有効です。
//	- 当関数が返す値は、EnmDef.hに出力されている、VslGmd_Maxと同じ値になるはずです。
//	  アプリケーションは、必ずしも、当関数を呼び出す必要は有りません。
int VslDef_GetGmdNum(const void* pEnmKey, int _RegKey_VslGmd) {
	return EnmDef_GetNum(pEnmKey, _RegKey_VslGmd);
}
/*--------------------------------------------------------------------------*/
//{{2017/04/12追加:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
//ゲームモードの名前を返す。
//[in]
//	pEnmKey			EnmDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_EnmDef)
//	_RegKey_VslGmd		RegKey_VslGmdの値		RegKey_VslGmd
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//[out]
//	戻り値			ゲームモードの名前
const char* VslDef_GetGmdName(const void* pEnmKey, int _RegKey_VslGmd, int iVslGmd) {
	return EnmDef_GetName(pEnmKey, _RegKey_VslGmd, iVslGmd);
}
//}}2017/04/12追加:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
/*--------------------------------------------------------------------------*/
//このゲームモードの、リールストリップの数を返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//[out]
//	戻り値			リールストリップの数		1～
int VslDef_GetRstNum(const void* pVslKey, int iVslGmd) {
	int nReel = REG_num_blob_l(pVslKey, iVslGmd, VslDef_ReelStrip, -1);
	if(!nReel) { DIE(); }	//リールストリップが一本も無ければエラー停止する。多分呼び出し側のバグです。
	return nReel;
}
/*--------------------------------------------------------------------------*/
//このゲームモードの、このリールストリップの長さを返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//	iReel			リール番号			0～VslDef_GetRstNum(pVslKey,iVslGmd)-1
//[out]
//	戻り値			リールストリップの長さ		1～
int VslDef_GetRstLen(const void* pVslKey, int iVslGmd, int iReel) {
	const unsigned char* pReelStrip = REG_get_blob_l(pVslKey, iVslGmd, VslDef_ReelStrip, iReel, -1);
	if(!pReelStrip) { DIE(); }	//リールストリップのBLOBが取得出来なければエラー停止する。多分呼び出し側のバグです。
	return REG_get_blob_size(pReelStrip);
}
/*--------------------------------------------------------------------------*/
//このゲームモードの、このリールストリップの、指定された位置のシンボルを返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//	iReel			リール番号			0～VslDef_GetRstNum(pVslKey,iVslGmd)-1
//	iPos			シンボル位置			0～VslDef_GetRstLen(pVslKey,iVslGmd,iReel)-1
//[out]
//	戻り値			シンボル番号			VslSym_*
int VslDef_GetRstSym(const void* pVslKey, int iVslGmd, int iReel, int iPos) {
	const unsigned char* pReelStrip = REG_get_blob_l(pVslKey, iVslGmd, VslDef_ReelStrip, iReel, -1);
	if(!pReelStrip) { DIE(); }	//リールストリップのBLOBが取得出来なければエラー停止する。多分呼び出し側のバグです。
	if((unsigned)iPos >= (unsigned)REG_get_blob_size(pReelStrip)) { DIE(); }	//シンボル位置が範囲外ならばエラー停止する。多分呼び出し側のバグです。
	return pReelStrip[iPos];
}
/*--------------------------------------------------------------------------*/
//{{2017/03/17追加:VslDef_GetRstSym_w()を追加しました。
//このゲームモードの、このリールストリップの、指定された位置を自動的に折り返した位置のシンボルを返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//	iReel			リール番号			0～VslDef_GetRstNum(pVslKey,iVslGmd)-1
//	iPos			シンボル位置			INT_MIN～INT_MAX
//[out]
//	戻り値			シンボル番号			VslSym_*
int VslDef_GetRstSym_w(const void* pVslKey, int iVslGmd, int iReel, int iPos) {
	int nLen = VslDef_GetRstLen(pVslKey, iVslGmd, iReel);
	if((iPos %= nLen) < 0) { iPos += nLen; }	//INT_MIN～INT_MAXを、0～VslDef_GetRstNum(pVslKey,iVslGmd)-1の範囲に折り返す。
	return VslDef_GetRstSym(pVslKey, iVslGmd, iReel, iPos);
}
//}}2017/03/17追加:VslDef_GetRstSym_w()を追加しました。
/*--------------------------------------------------------------------------*/
//このゲームモードの、ライン数を返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//[out]
//	戻り値			ライン数			1～
int VslDef_GetLinNum(const void* pVslKey, int iVslGmd) {
	int nLine = REG_num_blob_l(pVslKey, iVslGmd, VslDef_LineDef, -1);
	if(!nLine) { DIE(); }	//ライン定義が一つも無ければエラー停止する。多分呼び出し側のバグです。
	return nLine;
}
/*--------------------------------------------------------------------------*/
//このゲームモードの、このラインの、指定されたリール番号の、行番号を返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//	iLine			ライン番号			0～VslDef_GetLinNum(pVslKey,iVslGmd)-1
//	iReel			リール番号			0～VslDef_GetRstNum(pVslKey,iVslGmd)-1
//[out]
//	戻り値			行番号				0～
int VslDef_GetLinRow(const void* pVslKey, int iVslGmd, int iLine, int iReel) {
	const unsigned char* pLineDef = REG_get_blob_l(pVslKey, iVslGmd, VslDef_LineDef, iLine, -1);
	if(!pLineDef) { DIE(); }	//ライン定義のBLOBが取得出来なければエラー停止する。多分呼び出し側のバグです。
	if((unsigned)iReel >= (unsigned)REG_get_blob_size(pLineDef)) { DIE(); }	//リール番号が範囲外ならばエラー停止する。多分呼び出し側のバグです。
	return pLineDef[iReel];
}
/*--------------------------------------------------------------------------*/
//このゲームモードの、このシンボルに、何個揃いまでの配当額が設定されているかを返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//	iVslSym			シンボル番号			VslSym_*
//[out]
//	戻り値			配当額が設定されている揃い数の最大値	0～
//[note]
//	- このゲームモードのこのシンボルに、配当額が一つも設定されていなければ、0を返します。
//	- 当関数は、設定されている配当額の値について、考慮しません。
//	  たとえば、ある揃い数の配当額として0が設定されていたとしても、その揃い数も含めます。
int VslDef_GetMaxOak(const void* pVslKey, int iVslGmd, int iVslSym) {
	const unsigned short* pPayTable = REG_get_blob_l(pVslKey, iVslGmd, VslDef_PayTable, iVslSym, -1);
	if(!pPayTable) { return 0; }	//このゲームモードのこのシンボルに、配当額が一つも設定されていなければ、0を返します。
	return REG_get_blob_size(pPayTable) / sizeof(unsigned short);
}
/*--------------------------------------------------------------------------*/
//このゲームモードの、このシンボルの、指定されたシンボルと揃った数に対応する、配当額を返す。
//[in]
//	pVslKey			VslDefのレジストリキー		REG_open_key(TBL_RegTbl,RegKey_VslDef)
//	iVslGmd			ゲームモードの列挙値		VslGmd_*
//	iVslSym			シンボル番号			VslSym_*
//	nOfAKind		揃った数			1～VslDef_GetMaxOak(pVslKey,iVslGmd,iVslSym)
//[out]
//	戻り値			配当額				0～
//[note]
//	- 指定された条件の配当額が設定されていなければ、エラー停止します。
//	  指定された条件の配当額が設定されているが、0だった場合は、0を返します。
int VslDef_GetPay(const void* pVslKey, int iVslGmd, int iVslSym, int nOfAKind) {
	const unsigned short* pPayTable = REG_get_blob_l(pVslKey, iVslGmd, VslDef_PayTable, iVslSym, -1);
	if(!pPayTable) { DIE(); }	//ペイテーブルのBLOBが取得出来なければエラー停止する。多分呼び出し側のバグです。
	if((unsigned)(nOfAKind - 1) >= ((unsigned)REG_get_blob_size(pPayTable) / sizeof(unsigned short))) { DIE(); }	//配当額が設定されている揃い数の最大値を超えていたらエラー停止する。多分呼び出し側のバグです。
	return Exp10_Decode(pPayTable[nOfAKind - 1]);	//配当額は、exp10形式で格納されているので、元の値にデコードして返す。
}
/*--------------------------------------------------------------------------*/
//□使用例
#if 0
int app_main(int argc, char* argv[]) {
	const void* pVslKey = REG_open_key(TBL_RegTbl, RegKey_VslDef);
	int nSym, iSym, nGmd, iGmd, nRst, iRst, nLen, iPos, nLin, iLin, iRow, nOak, iOak, nPay;
	//シンボル
	nSym = VslDef_GetSymNum(pEnmKey, RegKey_VslSym);
	printf("(%d == %d) %s\n", nSym, VslSym_Max, (nSym == VslSym_Max) ? "ok" : "ERROR");
	for(iSym = 1; iSym <= nSym; iSym++) {
		printf("%d: %s %s\n",
			iSym,
//{{2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
//			EnmDef_GetName(pEnmKey, RegKey_VslSym, iSym),
//			EnmDef_GetDesc(pEnmKey, RegKey_VslSym, iSym));
//↓2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
			VslDef_GetSymName(pEnmKey, RegKey_VslSym, iSym),
			VslDef_GetSymDesc(pEnmKey, RegKey_VslSym, iSym));
//}}2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
	}
	//ゲームモード
	nGmd = VslDef_GetGmdNum(pEnmKey, RegKey_VslGmd);
	printf("(%d == %d) %s\n", nGmd, VslGmd_Max, (nGmd == VslGmd_Max) ? "ok" : "ERROR");
	for(iGmd = 1; iGmd <= nGmd; iGmd++) {
		printf("%d: %s\n",
			iGmd,
//{{2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
//			EnmDef_GetName(pEnmKey, RegKey_VslGmd, iGmd));
//↓2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
			VslDef_GetGmdName(pEnmKey, RegKey_VslGmd, iGmd));
//}}2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
		//リールストリップ
		nRst = VslDef_GetRstNum(pVslKey, iGmd);
		printf("%d\n", nRst);
		for(iRst = 0; iRst < nRst; iRst++) {
			nLen = VslDef_GetRstLen(pVslKey, iGmd, iRst);
			printf("%d: %2d:", iRst, nLen);
			for(iPos = 0; iPos < nLen; iPos++) {
				iSym = VslDef_GetRstSym(pVslKey, iGmd, iRst, iPos);
//{{2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
//				printf(" %s", EnmDef_GetName(pEnmKey, RegKey_VslSym, iSym));
//↓2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
				printf(" %s", VslDef_GetSymName(pEnmKey, RegKey_VslSym, iSym));
//}}2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
			}
			printf("\n");
		}
		//ライン定義
		nLin = VslDef_GetLinNum(pVslKey, iGmd);
		printf("%d\n", nLin);
		for(iLin = 0; iLin < nLin; iLin++) {
			for(iRst = 0; iRst < nRst; iRst++) {	//当サンプルでは(リール数==リールストリップ数)と仮定した。一般的にはそうだが常にそうだとは限らない。/clip/clipvsl.hの'Thu Mar 16 22:31:07 JST 2017 Naoyuki Sawa'のコメントを参照せよ。
				iRow = VslDef_GetLinRow(pVslKey, iGmd, iLin, iRst);
				printf(" %d", iRow);
			}
			printf("\n");
		}
		//ペイテーブル
		for(iSym = 1; iSym <= nSym; iSym++) {
			nOak = VslDef_GetMaxOak(pVslKey, iGmd, iSym);
			if(nOak) {
//{{2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
//				printf("%s:", EnmDef_GetName(pEnmKey, RegKey_VslSym, iSym));
//↓2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
				printf("%s:", VslDef_GetSymName(pEnmKey, RegKey_VslSym, iSym));
//}}2017/04/12変更:VslDef_GetSymName(),VslDef_GetSymDesc(),VslDef_GetGmdName()を追加しました。
				for(iOak = 1; iOak <= nOak; iOak++) {
					nPay = VslDef_GetPay(pVslKey, iGmd, iSym, iOak);
					printf(" %d", nPay);
				}
				printf("\n");
			}
		}
	}
	return EXIT_SUCCESS;
}
#endif
