次のページ 前のページ 目次へ

4. Add in 四川省の説明

今回は、Add inソフトの四川省を moreソフトに移植する・・・ということで、 まずは元となる 四川省 V1.3 の構造について説明します (SHISEN13.SRC を参照しながらご覧ください)。 サイズを小さくする為に 1文字変数を多用したり、 数値を書く部分で &13 のように16進数表記 (Add in BASIC では、& をつけた数値は 16進数とみなされる)を使うなど、 姑息な手段を用いてますので非常に汚いソースですが、その点はご了承ください。

4.1 ゲームの概略フロー

四川省は画面一杯に横18,縦8個の計144個の牌が並んでおり、 同じ牌同士をルールに従って選んで取り除いていくものです。 従って、通常はペンタッチされるまでじっと待っており、 タッチされて初めてどの牌が選択されたのか、 この牌の組み合わせは取れるか等の判定処理が行われます。

このペンタッチ判定と牌の取り除き処理は1つの大きなループになっており、 ゲームを終了するか牌を全て取り除くまでは 下図のようにずっとメインループの中を周り続けています。 実際にはもう少々複雑な構成にはなっていますが、 この手のゲームであれば大体こんな感じです (何となくイベントドリブンに向いているというのがわかりますね)。
		【概略フロー】

		各種初期化処理 (20 〜 210)
			|
	+-------------->+ (メインループ: 310 〜 600)
	|		|
	|	ペンタッチされるまで待つ
	|		|
	|	1つ目の牌なら選択
	|		|
	|	2つめの牌なら取れるか確認
	|		|
	|	取れるなら牌を取り除く
	|		|
	|	全ての牌を取り除いたか?
	|		|
	+---------------+
			|
		ゲームクリア表示
			|
		ハイスコア登録
			|
		本ゲームの終了

4.2 使用変数一覧

【定数扱いの変数】
P$(&23)		:	牌の上半分のデータ
Q$(&23)		:	牌の下半分のデータ
VM(&9)		:	垂直ライン処理で使用するマスク値
VS(&9)		:	垂直ライン処理で使用する開始位置の値
VR(&9)		:	垂直ライン処理で使用する終了位置の値
HM(&13,&1)	:	水平ライン処理で使用するマスク値
HS(&13,&1)	:	水平ライン処理で使用する開始位置の値
HR(&13,&1)	:	水平ライン処理で使用する終了位置の値
P		:	1 を入れとく変数
N		:	-1 を入れとく変数
O		:	0 を入れとく変数
J$="順位  名前      記録    記録日時"
K$="                                    "
F$="SX:SHISEN13.BA"

【可変ワーク変数】
LX(&3)		:	確認ラインのx座標
LY(&3)		:	確認ラインのy座標
K(&4)		:	検索した時に、見つけた数を入れる配列
X(&3)		:	検索した時に、見つけた座標を入れるための配列
Y(&3)		:	検索した時に、見つけた座標を入れるための配列
M$(&1,&3)	:	メニュー表示文字列を格納する配列。
LC=&0		:	確認ラインの線の数を返す変数
SX,EX,SY,EY	:	上下左右にどこまでいけるかを入れる変数
H0,H1,V0	:	bit処理による牌の有無チェック補助用作業変数
UB,UT		:	牌がとれるかのチェックで使用する変数
XW,YW		:	牌がとれるかのチェックで使用する作業変数
FA		:	FT,FB,FL,FRの4つをまとめたチェック用フラグ
FT,FB,FL,FR	:	上下左右にチェックする必要があるかを示すフラグ
OK=&0		:	サーチが正常にできたかを返すフラグ
SE=&0		:	ファイルのエラーを示すフラグ
OE=&0		:	ファイルのオープンエラーを示すフラグ
A$,B$		:	キー入力用の作業変数
KF		:	機能キーフラグ
I,J,K,L		:	あちこちで使われる作業変数
XX		:	X座標に関して計算する為のワーク
YY		:	Y座標に関して計算する為のワーク
WX,WY		:	メッセージ表示の時の座標指定です。他にも使うけど。
D		:	コの字型で取るときの距離(1,2,3,...)
LLIN		:	ヘルプで用いるライン数
LP		:	ヘルプで用いるループカウンタ

【ゲーム中使用変数】
C(&8F)		:	144枚のカードを並べかえる為の配列。(現在の並びを保持)
G(&9,&13)	:	画面のどこに何の牌があるかを保持。
VW(&13)		:	垂直ラインに関する牌の有無を保持する変数
HW(&9,&1)	:	水平ラインに関する牌の有無を保持する変数
SF(&23)		:	検索処理で、既になくなった牌種別かを示す変数
MF=&0		:	確認ラインのON/OFFフラグ(0で現在ONである)
BF=&0		:	現在表示されているボタンを示すフラグ変数
BC		:	この変数にボタンの表示状態を設定して、*BCHGを呼び出す。
S$,E$		:	クリア時間の表示及びゲーム開始時刻の保持
SCH=&0		:	次回サーチする時の開始牌
MD=&0		:	サーチモードの後か否かを示すフラグ(0なら通常)
Z=&90		:	残り牌数(これが0になるとゲームが終わる)
P1=-1		:	1つめの選択してる牌のコードを格納する。
HF=&0		:	ハイスコア記録可能か否かを示す。0なら記録可能。
SV1,SV2,SV3,SV4	:	矩形を指定するための作業変数
X,Y		:	1つめの牌の座標を保持する変数
V,W		:	2つめの牌の座標を保持する変数
T1,U1		:	1つめの牌の座標を保持する変数
T2,U2		:	2つめの牌の座標を保持する変数
S1X,S1Y,S2X,S2Y	:	サーチした時の2つの牌の座標を保持する変数
S		:	開始時刻に使ったり、その他いろいろ。
E		:	終了時刻に使ったり、その他いろいろ。
R		:	経過秒数(繰越し時間格納用変数)
D$		:	クリアした時or最後に時刻を見た時の日付
MES$		:	MKDIAGルーチンで表示するメッセージ受け渡し変数

【その他の変数】
A		:	ハイスコアの検索時に使う作業変数
N$		:	ハイスコア記録者の名前を入れる文字列
TL,TI,TJ	:	サーチする時の作業変数
M		:	実際に見つかった数を調べる為の変数

4.3 サブルーチン一覧

 790 *TCH		ペンタッチ割り込み処理
 810 *ERR		エラー処理
 850 *ERR2		エラー処理2
 870 *CFGW		確認ラインOn/Offフラグの状態を保存
 890 *FINIT		ハイスコアファイルの初期化
1000 *PINIT		牌画像データの読み込み処理
1070 *GINIT		ゲーム画面の初期化
1110 *CINIT		ゲーム用牌の配列を初期化
1160 *SHUFFLE		牌を並び替える(シャッフル)処理
1210 *ALLDRAW		ゲーム画面の描画(全ての牌)
1310 *CGSET		シャッフルした牌を画面用配列へ複写
1410 *HINIT		接続ライン検知作業用ワークの初期化
1500 *MSGSHOW		『並べ替え中』ダイアログの表示
1510 *MSGSHOW2		『検索中』ダイアログの表示
1520 *MSGHIDE2		上記ダイアログの消去
1540 *MINIT		メニューの初期化
1580 *MCHG		確認ラインOn/Offの切替
1640 *MENUOFF		メニューを禁止する
1690 *MENUON		メニューを許可する
1740 *TC1		1つめの牌の選択と反転処理
1800 *TC2		2つめの牌の選択と反転・判定処理
1860 *TC3		確認ライン描画		
1970 *T3		牌を取り除く処理
2120 *HANTENX		(X,Y)の牌を反転する処理
2130 *HANTEN2		(V,W)の牌を反転する処理
2150 *GCLR		『ゲームクリア』のダイアログ表示
2240 *HSS		ハイスコア登録処理
2390 *SEARCH		取れる牌の組み合わせを検索し表示する処理
2790 *HANTEI		(X,Y),(V,W)で指定した牌同士が取れるか判定
3480 *HELP		オンラインヘルプの表示
3670 *SVSCR		(SV1,SV2)-(SV3,SV4)の画面を待避
3710 *LDSCR		(SV1,SV2)-(SV3,SV4)の画面を復帰
3750 *MKDIAG		ダイアログ(Type1)を表示
3820 *MKDIAG2		ダイアログ(Type2)を表示
3880 *BCHG		BC,BFフラグに従い、画面上部のボタンのOn/Off変更
3970 *HSD		ハイスコアリストを画面に表示
4130 *NMINPUT		ハイスコア者の名前を入力する処理
4310 *TEISHI		一時停止の処理(30分でパワーオフ処理含む)
4540 *TSTART		タイマーカウントを新規に開始
4550 *TCONT		タイマーカウント継続
4570 *TSTOP		タイマーカウント一時停止

4.4 プログラムの流れ

初期化処理20 〜 210
新規ゲーム220 〜 230
やり直し240 〜 300
メインループ310 〜 600
ゲームクリア620 〜 750
終了処理770
エラー処理810 〜 850

まずは、牌データなど定数として使う変数などの初期化処理を行います。 ハイスコアファイルの初期化(*FINIT)、牌画像データの読み込み(*PINIT)、 接続ライン検知作業用ワークの初期化(*HINIT)、 メニュー項目の初期化(*MINIT)、 初期ゲーム画面の初期化(*GINIT)、 牌のシャッフル準備(*CINIT)を行い、 乱数系列の初期化なども済ませます。

画面上のボタン表示用にICONファイルを開き、 並び替え中メッセージを表示し牌をシャッフル(*SHUFFLE)、 シャッフル後の牌を画面用の配列変数にコピー(*CGSET)、 牌を画面に全て描画(*ALLDRAW)した後、 タイマーカウントを開始(*TSTART)して、メインループに突入します。

メインループ中では、キー入力、ペンタッチ、 またはメニュー操作が行われるまで待ち、 それに応じた処理を繰り返し実行し続けます(310〜600)。 ボタン/メニュー処理として、オンラインヘルプ表示(*HELP)、 ゲームやり直し(*RENEW2)、一時停止(*TEISHI)、 ハイスコア表示(*HSD)、確認ラインOn/Off切替などがあり、 最後に実際に画面上の牌を選んで取り除いていくゲーム本来の処理があります。

牌選択の処理はまず、 500〜510行でペンタッチされた座標から、牌の座標(配列添字値)に変換します。 まだ牌が1つも選択されてない(変数 P1 の値が -1)ならば、 *TC1 で画面用配列 G() を調べて選択と反転処理を行います (G(Y*20+X)の値が -1 なら、そこには牌が存在しない)。 既に牌が選択されている場合は同じ種類の牌かをチェック(*TC2)、 次に *HANTEI を呼び出して、取る事ができるかどうかの判定を行います。 取れるのであれば、そのまま *TC3 で確認ラインの描画を行い、 続く *T3 で今回の2つの牌を消去し各情報ワークを更新します。 なお、この時反転処理に *HANTENX, *HANTEN2 が呼び出され画面に効果がつきます。

後は、牌が無くなるか終了ボタンが押されるまで上記を繰り返すのみです。

牌が全て取り除かれたら *NOPAI に抜けてきますので、 ここで時間計測を終了(*TSTOP)、 ゲームにかかった時間を文字列として S$ に作成した後 ゲームクリアのメッセージを表示します(*GCLR)。 ゲーム中に検索機能を使わなかった場合には、 ハイスコア登録(*HSS)を行い、最後にハイスコア一覧を表示(*HSD)して 入力待ちに戻ります。

4.5 画面描画

Add in 四川省では、 画面の描画といっても牌の描画程度で、他は大した物でもありません。 背景の描画や、選択した牌の反転処理の為に CALL@40 や CALL@41 を使って 矩形の塗りつぶし等を行っている程度です。 ボタンの方は、ICON命令を使って描画と押下処理を行ってもらっていますが、 状態によって一部のボタンを非アクティブにしているくらいで、 それ以上の事はやっていません。

【牌の描画】

GPRINT文を使うと、縦8dot、横任意dotの図形を描くことができますので、 これを使って、縦16dot、横12dotの牌を描画しています。 牌画像データ自体は SHISEN13.BA0 に入ってますので、 初期化処理の *PINIT で P$(35), Q$(35)に読み込んでおき、 GPRINT文を縦に2回使って1つの牌を描画しています。 moreソフトで組むとしたら、生の画像データとして持っておくか、 アイコンと同じように扱うかが考えられます。

【牌の選択状況の表示】

これは CALL@41 を使って、牌の画像を白黒反転させる事で表現しました。 XOR 演算で行いますので、もう1度実行すれば元に戻るというものです。 moreソフトにする場合でも同じ手法が使えなくはありませんが、 カラー画像ではあまり良い結果が得られない為、別な方法を選ぶ必要があります。

【背景の描画】

CALL@40, CALL@41 で矩形領域を塗りつぶしているだけです。 moreソフトでは別な関数を呼ぶ事になるでしょうが、大体同様でしょう。


次のページ 前のページ 目次へ