MINE SWEEPER FX
2009年3月4日
動作環境
FX-890PとZ-1GRで動作確認しました。Z-1でも動きます。(推測)
入力方法
まず、マシン語エリアを&H1AB6以上確保します。
CLEAR 1024,6838,10240
次に、プログラムリストをRUNして下さい。プログラム本体は、2000Hから2B52Hまでの2899バイトです。
実行は
DEFSEG=0
CALL&H2000
です。アドレスに注意してください。このプログラムはリロケータブルではありませんので、必ず指定されたアドレスに読み込んでください。
遊びかた
プログラムを走らせると、タイトルが表示され、レベルの選択画面になります。[EASY][NORMAL][HARD]の順に難しくなります。ここで、[CUSTOM]を選ぶと、縦横のマスの大きさと爆弾数が変更できます。X方向は6から20まで、Y方向は6から49まで、爆弾は、(Y-1)*X-1個まで設定できますが、半分以上爆弾になると、かなり難しくなります。
タイトルと[CUSTOM]では、テンキーでカーソル移動、数字を増やしたり減らしたりするのは[4][6]キー、[RET]で決定です。
ゲーム画面では、カーソルは反転しているものでテンキーで移動します。爆弾を掘るとき(WIN版の左クリックに相当)は[S]、フラグを立てる(右クリックに相当)ときは[A]、周りのマスを一度に開く(同時クリックに相当)のは、掘ったマスの上で[S]です。
ルールは説明するまでもないとおもいますが、念のため説明します。あるマスに書かれている数字は、そのマスの周りにある爆弾の数を示しています。その数を手掛かりにして、すべての爆弾の上にフラグを立てるのが目的です。
クリア条件は「爆弾のないマスを全て掘る」ことです。まわりに爆弾のないマスを掘ったときには、自動的にその周りのマスを掘り進んでくれます。クリアした、又はゲームオーバーになったときは、[RET]でもう一度同じ広さのマスでゲーム、[CLS]を押すとタイトルに戻ります。
一度このゲームにはまってしまうと徹夜が待っています。「あなたの健康のために、遊びすぎに注意しましょう」
プログラムについて
ポケコンの狭い画面を克服するためにいろいろ工夫をしています。
BIOSを使って画面表示をすると4行しか表示できませんが、LCDCを直接操作して、6行表示にしています。それでもまだ狭いので、スクロールしてたくさん表示できるようにしています。スクロールしても、見えないところもきちんと処理していますので大丈夫です。
でも、あまり情報量を必要としない右側は4行表示にすることにより、画面の見づらさはそんなに無いと思います。
Q&A
お待ちかねのQ&Aのコーナーです。今日は「マインスイーパーで空白のマスを掘ったときに自動的に周りのマスを掘り進むアルゴリズムはどうなっているのですか」と言うものです。
このプログラムで採用したルーチンは次のとおりです。
まず、プレーヤーが掘ったマスを自分のマスと呼びます。あるマスに接している8個のマスは周りのマスと呼びます。自分のマスに接している爆弾の数が0個の時、自分のマスの座標を基準にして、上、右上、右、右下、下、左下、左、左上の順に、周りのマスに接している爆弾の数を調べます。もし、周りのマスに接している爆弾の数が0個ならば、基準のマスをそのマスにして、再帰的に、接している爆弾の数が0個のマスを探します。このとき、基準のマスは順番に記録しておきます。もちろん、高速化のため、一度周りの爆弾の数を探したマスは2度目以降は飛ばします。もし、爆弾の数が0個でなければ、そのマスを掘ってしまいますが、基準のマスは変えません。
これを続けていくと、周りのマスは全て処理してしまった、という状態にぶつかります。このようなときは、記録しておいた基準のマスを呼び出して(つまり1歩手前に戻る)、さらに周りのマスを調べていくわけです。このようにして、自分のマスに処理が戻ってきたら、自動的にマスを展開したことになるわけです。
このアルゴの難点は、メモリを大量に消費することです。実質やってることは再帰呼び出しですから。でも最近のポケコンはメモリをいっぱい載っけているので大丈夫でしょう、多分。
具体例
例えば、爆弾が次のように埋まっているとします。
□□□□□□□□
□■□□□□□□
□□□□□□■□
□■□□□□□□
□□□□□■□□
□は空のマス、■は爆弾の埋まっているマスです。周りの数字を記入すると次のようになります。
111□□□□□
1■1□□111
222□□1■1
1■1□1221
111□1■1□
今、×印のマスを掘ったとしましょう。。
□□□□□□□□
□■□□□□□□
□□□□×□■□
□■□□□□□□
□□□□□■□□
結果として、次のように展開できれば成功です。
□□1×××××
□■1××111
□□2××1■□
□■1×12□□
□□1×1■□□
まず、掘ったマスの周りにある爆弾の数が0でなければ、ここで終わりです。その時は自動展開しなくていいんですからね。ここでは、0なので次に進みます。
まず、自分のマスの座標を記録します。(終了判定用)
次にその上のマスの周りにある爆弾の数を調べます。また0なので、元の座標と、調べていた方向を記録し、掘って、そのマスにカーソルを移動させます。
カーソル「X=4、Y=1、上」
□□□□□□□□ (1)X=4、Y=2、?
□■□□×□□□ (2)X=4、Y=2、上
□□□□×□■□
□■□□□□□□
□□□□□■□□
さらに上のマスの周りの爆弾数が0なので、掘って、上に移動します。もちろん座標は記憶します。
カーソル「X=4、Y=0、上」
□□□□×□□□ (1)X=4、Y=2、?
□■□□×□□□ (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□
□□□□□■□□
さて、今度は、上には行けません。上にマスが存在しないときは、時計周り、つまり上、右上、右、右下、下、左下、左、左上の順に移動できるかどうか調べていきます。今回は、右に行けますね。自分の座標と移動方向を記録して、掘って、カーソルを移動します。
カーソル「X=5、Y=0、上」
□□□□××□□ (1)X=4、Y=2、?
□■□□×□□□ (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、右
□□□□□■□□
あと2回右に行きます。
カーソル「X=7、Y=0、上」
□□□□×××× (1)X=4、Y=2、? (6)X=6、Y=0、右
□■□□×□□□ (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、右
□□□□□■□□ (5)X=5、Y=0、右
次は、時計周りに見ていくと、下にはマスがありますね。でも0ではありません。このようなときは、下のマスを掘るだけ掘って、カーソルはそのままにしておきます。座標移動しないので、座標の記録はしません。
カーソル「X=7、Y=0、下」
□□□□×××× (1)X=4、Y=2、? (6)X=6、Y=0、右
□■□□×□□1 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、右
□□□□□■□□ (5)X=5、Y=0、右
同様に、左下も掘ります。
カーソル「X=7、Y=0、左下」
□□□□×××× (1)X=4、Y=2、? (6)X=6、Y=0、右
□■□□×□11 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、右
□□□□□■□□ (5)X=5、Y=0、右
今カーソルのあるマスの左のマスのように、一度処理したマスは、2回目以降は処理しません。これは、別のワークエリアに処理したかどうかのフラグを立ててやればいいのです。
さて、左上のマスは存在しないことですし、行くところがなくなってしまいました。どうしましょう。この時のために座標を記録しておいたのです。行き詰まってしまったら一歩手前に戻ればいいのです。よって、(6)のデータを読みだします。よって、カーソルを「X=6、Y=0、右」とします。時計周りに見ていくと左下が掘れますね。
カーソル「X=6、Y=0、左下」
□□□□×××× (1)X=4、Y=2、?
□■□□×111 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、右
□□□□□■□□ (5)X=5、Y=0、右
また、行き詰まったので戻っていきます。2回戻ります。
カーソル「X=4、Y=0、右」
□□□□×××× (1)X=4、Y=2、?
□■□□×111 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□
□□□□□■□□
時計周りに見ると、左下に移動できます。そのマスの周りの爆弾の数は0なので掘ります。
カーソル「X=3、Y=1、上」
□□□□×××× (1)X=4、Y=2、?
□■□××111 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、左下
□□□□□■□□
お解りいただけたでしょうか。以下、説明を簡略化して続けていきます。上に行きます。
カーソル「X=3、Y=0、上」
□□□××××× (1)X=4、Y=2、?
□■□××111 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、左下
□□□□□■□□ (5)X=3、Y=1、上
左下を開きます。
カーソル「X=3、Y=0、左下」
□□□××××× (1)X=4、Y=2、?
□■1××111 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、左下
□□□□□■□□ (5)X=3、Y=1、上
左も開きます。
カーソル「X=3、Y=0、左」
□□1××××× (1)X=4、Y=2、?
□■1××111 (2)X=4、Y=2、上
□□□□×□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、左下
□□□□□■□□ (5)X=3、Y=1、上
(5)を呼び出します。その状態から下に行きます。
カーソル「X=3、Y=2、上」
□□1××××× (1)X=4、Y=2、?
□■1××111 (2)X=4、Y=2、上
□□□××□■□ (3)X=4、Y=1、上
□■□□□□□□ (4)X=4、Y=0、左下
□□□□□■□□ (5)X=3、Y=1、下
右下を開きますよ。
カーソル「X=3、Y=2、右下」
□□1××××× (1)X=4、Y=2、?
□■1××111 (2)X=4、Y=2、上
□□□××□■□ (3)X=4、Y=1、上
□■□□1□□□ (4)X=4、Y=0、左下
□□□□□■□□ (5)X=3、Y=1、下
下に移動です。
カーソル「X=3、Y=3、上」
□□1××××× (1)X=4、Y=2、? (6)X=3、Y=2、下
□■1××111 (2)X=4、Y=2、上
□□□××□■□ (3)X=4、Y=1、上
□■□×1□□□ (4)X=4、Y=0、左下
□□□□□■□□ (5)X=3、Y=1、下
右下を開き、下に移動です。
カーソル「X=3、Y=4、上」
□□1××××× (1)X=4、Y=2、? (6)X=3、Y=2、下
□■1××111 (2)X=4、Y=2、上 (7)X=3、Y=3、下
□□□××□■□ (3)X=4、Y=1、上
□■□×1□□□ (4)X=4、Y=0、左下
□□□×1■□□ (5)X=3、Y=1、下
左と左上を開きます。
カーソル「X=3、Y=4、左上」
□□1××××× (1)X=4、Y=2、? (6)X=3、Y=2、下
□■1××111 (2)X=4、Y=2、上 (7)X=3、Y=3、下
□□□××□■□ (3)X=4、Y=1、上
□■1×1□□□ (4)X=4、Y=0、左下
□□1×1■□□ (5)X=3、Y=1、下
(7)を呼び出します。左上を掘ります。
カーソル「X=3、Y=3、左上」
□□1××××× (1)X=4、Y=2、? (6)X=3、Y=2、下
□■1××111 (2)X=4、Y=2、上
□□2××□■□ (3)X=4、Y=1、上
□■1×1□□□ (4)X=4、Y=0、左下
□□1×1■□□ (5)X=3、Y=1、下
(6)、(5)、(4)、(3)の順に呼び出します。これらは、周りを調べても、移動するところも掘るところもありません。
カーソル「X=4、Y=1、上」
□□1××××× (1)X=4、Y=2、?
□■1××111 (2)X=4、Y=2、上
□□2××□■□
□■1×1□□□
□□1×1■□□
右下を開いて、(2)を呼び出します。
カーソル「X=4、Y=2、上」
□□1××××× (1)X=4、Y=2、?
□■1××111
□□2××1■□
□■1×1□□□
□□1×1■□□
右下を開いて、(1)を呼び出します。
カーソル「X=4、Y=2、?」
□□1×××××
□■1××111
□□2××1■□
□■1×12□□
□□1×1■□□
ここで、呼び出した座標と元の座標が一致した(つまり、最終的に行き先がなくなった)ので、終わりです。このアルゴリズムだと、どのつながっているマスでも、必ず8方向を調べますので、掘り残すようなことはありません。
実際のプログラムでは、このアルゴリズムを少し応用して自動展開をさせています。この程度のルーチンだとマスの数が多いと処理に時間が掛かりますが、プログラマの腕次第でどうにでもなります。ポケコンのマシン語プログラムだって、数十マスくらいなら一瞬で終わります。ただ、BASICでは無理でしょう。
唯一の欠点は、メモリを大量に消費することです。私の組んだルーチンでは1マスにつき4バイト必要とします(本当は3バイトと1ビット)。
MS-DOSで組めば、仮に80*25=2000マスのマインスイーパーでも2000*4=8000、約8KBです。プログラム本体サイズを足しても使用するメモリはたかが知れています。
プログラムリスト
100 DEFSEG=0:CLS:CLEAR:L=1000:FOR I=&H2000 TO &H2B52 STEP 8
110 READ A$:C=0:LOCATE 0,0:PRINT "LINE:";STR$(L)
120 FOR J=0 TO 7
130 P$=MID$(A$,J*2+1,2):IF P$="##" THEN 150
140 P=VAL("&H"+P$):POKE I+J,P:C=C+P*(J+1)
150 NEXT:READ A$:IF VAL("&H"+A$)-(C AND 255) THEN PRINT "ERROR IN ";L:END
160 L=L+10:NEXT
170 PRINT "COMPLETED END!":END
1000 DATA FC33C08ED88EC0E8,E6
1010 DATA F007B43ACD41BEB2,4B
1020 DATA 3A893C8CC0894402,12
1030 DATA C606A33A14C606A4,F5
1040 DATA 3A0CC706A53A2800,6C
1050 DATA B80105BFE829E8CD,03
1060 DATA 06E8F308B90040E8,6C
1070 DATA CC08E2FBE8BB07B8,49
1080 DATA 0008BFCD29E8B606,E8
1090 DATA B80205BFFF29E8AD,78
1100 DATA 06B8030EBF152AE8,56
1110 DATA A406B8020DB23EE8,3F
1120 DATA 3D06E8C208E89E08,33
1130 DATA 50B88000BB0002E8,35
1140 DATA E7065875358BD8E8,42
1150 DATA ED06D0EE7302B40D,C0
1160 DATA D0EE7302B413D0EE,23
1170 DATA 7302B002D0EE7302,68
1180 DATA B0033BC374CF508B,19
1190 DATA C3B220E8010658B2,48
1200 DATA 3EE8FB05E88008E9,1B
1210 DATA BBFFB9030080FC13,6C
1220 DATA 740380E9013C0374,C0
1230 DATA 0380E90280F90374,D1
1240 DATA 12BE472BC0E10203,3B
1250 DATA F1BFA33AB104F3A4,92
1260 DATA E93001B88000BB00,C9
1270 DATA 02E87D0675F5E819,88
1280 DATA 07C606E2270FB800,52
1290 DATA 0ABF222AE80F06B8,62
1300 DATA 0106BF2E2AE80606,9E
1310 DATA B80206BF432AE8FD,55
1320 DATA 05B80306BF582AE8,C7
1330 DATA F405B80105B23EE8,61
1340 DATA 8D05E8120850B880,A7
1350 DATA 00BB0002E83A0658,4C
1360 DATA 7403E9DE008BD8E8,17
1370 DATA 3D06D0EE73303C03,8C
1380 DATA 74203C02740E803E,78
1390 DATA A33A067421FE0EA3,0C
1400 DATA 3AE91A00803EA43A,9A
1410 DATA 067413FE0EA43AE9,1B
1420 DATA 0C00813EA53A0100,23
1430 DATA 7404FF0EA53AD0EE,66
1440 DATA 733A3C0374203C02,5F
1450 DATA 740E803EA33A1474,BF
1460 DATA 2BFE06A33AE92400,59
1470 DATA 803EA43A31741DFE,38
1480 DATA 06A43AE91600508A,8E
1490 DATA 06A43AFEC8F626A3,C2
1500 DATA 3A3B06A53A587404,D4
1510 DATA FF06A53AD0EE7306,DB
1520 DATA 3C017402FEC8D0EE,68
1530 DATA 73063C037402FEC0,81
1540 DATA 3BC3740E508BC3B2,0C
1550 DATA 20E8E30458B23EE8,7F
1560 DATA DD04508A06A43AFE,79
1570 DATA C8F626A33A3B06A5,88
1580 DATA 3A77048906A53A32,7A
1590 DATA EDB801168A0EA33A,03
1600 DATA E88104B802168A0E,9A
1610 DATA A43AE87704B80316,D5
1620 DATA 8B0EA53AE86D0458,70
1630 DATA E82C07B92003E2FE,09
1640 DATA E912FFE8F40533C0,F1
1650 DATA 8806A73A8806A83A,A5
1660 DATA 8806A93A8806AB3A,C0
1670 DATA C606AC3A018806AD,85
1680 DATA 3AC606E22703BF53,06
1690 DATA 2BB080B9D403F3AA,1A
1700 DATA 8B0EA53A8A06A33A,99
1710 DATA F626A43A2BC18906,62
1720 DATA B03A890EAE3AE8EB,69
1730 DATA 04E2FBB80111BFCD,A5
1740 DATA 29E8AA04B80212BF,21
1750 DATA DD29E8A104E8C706,90
1760 DATA 8A16A93AB500E8A1,82
1770 DATA 058A26A73A8A06A8,EF
1780 DATA 3A0206A93AE83606,30
1790 DATA 8A15B5018A06A83A,15
1800 DATA E8AC05E8E104D0EE,8C
1810 DATA 730B803EA73A0074,40
1820 DATA 04FE0EA73AD0EE73,E2
1830 DATA 108A1EA33AFECB3A,7D
1840 DATA 1EA73A7404FE06A7,54
1850 DATA 3AD0EE7319803EA8,DF
1860 DATA 3A00750E803EA93A,34
1870 DATA 00740BFE0EA93AE9,1B
1880 DATA 0400FE0EA83AD0EE,FA
1890 DATA 731F803EA83A0575,98
1900 DATA 148A3EA43A80EF06,4D
1910 DATA 3A3EA93A740BFE06,41
1920 DATA A93AE90400FE06A8,46
1930 DATA 3AD0EE7207E91D01,D8
1940 DATA 90E9C7018A26A73A,B2
1950 DATA 8A06A83A0206A93A,13
1960 DATA E8AB05F605807503,89
1970 DATA E95001E8A0058A15,D8
1980 DATA F6C2607403E9D8FF,CF
1990 DATA F6C2807503E9D0FF,FB
2000 DATA 80E201881580FA01,AE
2010 DATA 7503E9BD00FF0EB0,06
2020 DATA 3A5057BF272FB9D4,67
2030 DATA 0332C0F3AA5F58C6,97
2040 DATA 06AC3A00B601E882,08
2050 DATA 05B500508A26A73A,A6
2060 DATA 8A06A83AD0E2E8D6,DA
2070 DATA 0458881580FA0074,9C
2080 DATA 03E9830081EF532B,1A
2090 DATA 81C7272FC60501BE,33
2100 DATA FB32B107E89A03B1,4F
2110 DATA 00BF372B5132EDD0,8B
2120 DATA E103F95950022578,95
2130 DATA 4D3A26A33A744702,9A
2140 DATA 450178423A06A43A,49
2150 DATA 743CE81105F60560,E8
2160 DATA 7534F60580742F8B,AC
2170 DATA DF81EB532B81C327,58
2180 DATA 2F803F007520C607,97
2190 DATA 01B601E80D05D0E2,2F
2200 DATA 8815FF0EB03A80FA,03
2210 DATA 00750B8BD858E840,D7
2220 DATA 038BC3E9A1FF58FE,7D
2230 DATA C180F908759BE840,0F
2240 DATA 0381FEFB3275F0E9,7B
2250 DATA 06FF803EAC3A0174,DB
2260 DATA 08C606AD3A01E9F7,99
2270 DATA FEC606AC3A00C605,00
2280 DATA 8057E82F035E3BFE,72
2290 DATA 74F4E9E7FED0EE72,9B
2300 DATA 03E9A7008A26A73A,C1
2310 DATA 8A06A83A0206A93A,13
2320 DATA E88B048A15F6C2E0,AD
2330 DATA 7503E98E008ADA80,A0
2340 DATA E30180E2E0D0E273,F3
2350 DATA 06B220FF0EAE3AF6,66
2360 DATA C2807404FF06AE3A,DF
2370 DATA 0AD38A06A83A8815,6A
2380 DATA B500E8DA03E96300,0F
2390 DATA E960008A26A73A8A,5F
2400 DATA 06A83A0206A93AE8,F6
2410 DATA 4404F605E075E98A,0F
2420 DATA 15D0EA8ACAB620E8,F1
2430 DATA 51043ACA75DAB100,6B
2440 DATA 50BF372B5132EDD0,DB
2450 DATA E103F95902257820,66
2460 DATA 3A26A33A741A0245,6D
2470 DATA 0178153A06A43A74,44
2480 DATA 0FC606F022C351E8,20
2490 DATA 61FE59C606F02290,AC
2500 DATA 58FEC180F90875C8,17
2510 DATA E99DFFB8021C8B0E,EF
2520 DATA AE3AB22081F90080,13
2530 DATA 7204F7D9B22DE8CE,13
2540 DATA 01FEC4E88E01E84E,7D
2550 DATA 04803EAD3A00750E,37
2560 DATA 813EB03A00007503,40
2570 DATA E99700E972FDBF53,B4
2580 DATA 2B8A06A33AF626A4,ED
2590 DATA 3A8BC88A15F6C220,4B
2600 DATA 740AF6C2017511B2,3C
2610 DATA 1AE90C00F6C22075,F2
2620 DATA 07F6C2017402B201,73
2630 DATA 881547E2DEB704B5,73
2640 DATA FF8A16A93AE8E202,C9
2650 DATA E8FC03F6D5FECF75,2F
2660 DATA F0BEE92ABF9B06BD,3E
2670 DATA FB32B306B909008A,B3
2680 DATA 053E8846008A0488,C9
2690 DATA 05474645E2F183C7,56
2700 DATA 17FECB75E7E8CF03,FC
2710 DATA B00433C9E2FEFEC8,05
2720 DATA 75F8BEFB32BF9B06,6C
2730 DATA B306B909008A0488,A6
2740 DATA 054746E2F883C717,00
2750 DATA FECB75EEE8A803E9,80
2760 DATA 7E00BF532B8A06A3,5C
2770 DATA 3AF626A43A8BC88A,54
2780 DATA 15F6C280740880E2,4B
2790 DATA 7F80CA20881547E2,84
2800 DATA EE8A16A93AB500E8,88
2810 DATA 6002B8021D33C9E8,16
2820 DATA B200BEB32ABF9B06,71
2830 DATA BDFB32B306B90900,C8
2840 DATA 8A053E8846008A04,B2
2850 DATA 8805474645E2F183,D3
2860 DATA C717FECB75E7E84E,96
2870 DATA 03B00433C9E2FEFE,56
2880 DATA C875F8BEFB32BF9B,B6
2890 DATA 06B306B909008A04,75
2900 DATA 88054746E2F883C7,86
2910 DATA 17FECB75EEE82703,87
2920 DATA 8A16A93AE80302E8,81
2930 DATA 1D03C606E227C88A,A9
2940 DATA 16A93AE85101C0EE,01
2950 DATA 03730780FA007402,1C
2960 DATA FECAD0EE730D8A3E,FD
2970 DATA A43A80EF063AFA74,44
2980 DATA 02FEC23A16A93A74,C6
2990 DATA 0C8816A93AB500E8,A2
3000 DATA C801E8E202B88000,E4
3010 DATA BB0002E80B01750E,41
3020 DATA B80004BB1000E800,58
3030 DATA 017506E9B1FFE9A2,7F
3040 DATA FBE9D8F96081F900,EE
3050 DATA 807202F7D9BB6400,A1
3060 DATA E81B00E82900FEC4,9D
3070 DATA BB0A00E81000E81E,07
3080 DATA 00FEC4BB0100E805,B9
3090 DATA 00E8130061C332D2,6E
3100 DATA 2BCB7205FEC2E9F7,C4
3110 DATA FF03CB80C230C360,A5
3120 DATA 068BD8D0E7C0E402,33
3130 DATA 02E7B008E800038A,ED
3140 DATA C8BE30068AC432E4,B4
3150 DATA C1E00503F032FFC1,79
3160 DATA E30303F380EA20BB,72
3170 DATA B23A8B3F8B47028E,A2
3180 DATA C032F6C1E20303FA,6B
3190 DATA B408268A35C0E602,41
3200 DATA 4732D2BB00FCD3EB,12
3210 DATA D3EAF7D3203C205C,A0
3220 DATA 20083408542046FE,2A
3230 DATA CC75DF0761C3608A,D6
3240 DATA 154780FA007408E8,3B
3250 DATA 95FFFEC4E9F0FF61,CB
3260 DATA C3538ADCC0E3030A,EE
3270 DATA D98AF8891C46465B,EB
3280 DATA C3534E4E8B1C8ACB,08
3290 DATA 80E1078AE3C0EC03,FA
3300 DATA 8AC75BC3E8CF0180,9E
3310 DATA E21F3A16A33A73F4,76
3320 DATA 8AE2E8C1013A16A4,25
3330 DATA 3A73F78AC2E85E01,01
3340 DATA 803D8075DFC60581,78
3350 DATA C352BA0002EF5058,29
3360 DATA B202ED23C35AC350,C9
3370 DATA 53B801008BD8E8E8,25
3380 DATA FF7404B47FCD4132,63
3390 DATA F6BF1F2BB90200D0,A6
3400 DATA E68B058B5D0283C7,E1
3410 DATA 04E8CDFF740380CE,7D
3420 DATA 01E2ECB104D0E68B,E3
3430 DATA 058B5D0283C704E8,CF
3440 DATA B7FF740880FE0075,4D
3450 DATA 0380CE01E2E78A06,3B
3460 DATA AA3AA870740A8836,BE
3470 DATA AA3A80E60FE93700,78
3480 DATA 240F742F84F07407,F2
3490 DATA FE06AB3AE90800C6,E0
3500 DATA 06AB3A00E91C0080,3F
3510 DATA 3EAB3A007415803E,74
3520 DATA AB3A03730A8836AA,20
3530 DATA 3A80E630E90800FE,59
3540 DATA 0EAB3A8836AA3A5B,AA
3550 DATA 58C333C08EC0BF30,76
3560 DATA 06B90004F3AAE81E,8B
3570 DATA 01C333C002C2E89D,F6
3580 DATA 0032C933C0B4008A,D3
3590 DATA 1547E81200FEC43A,C3
3600 DATA 26A33A75F2FEC0FE,CC
3610 DATA C180F90675E7C360,CC
3620 DATA 8BD8C0E40202E7B0,F2
3630 DATA 08E873018AC8BE30,49
3640 DATA 068AC432E4C1E005,70
3650 DATA 03F032FF03F3C1E3,95
3660 DATA 0203F346F6C2E074,13
3670 DATA 10C0EA0580FA0475,82
3680 DATA 02FECA80C208E90C,15
3690 DATA 00F6C2017505D0EA,9D
3700 DATA E90200B20C8AF2C0,CB
3710 DATA E20202D6BF6D2A32,43
3720 DATA F603FAB4058A3580,82
3730 DATA FD007405F6D680E6,EF
3740 DATA F84732D2BB00F8D3,6B
3750 DATA EBD3EAF7D3203C20,AE
3760 DATA 5C20083408542046,B4
3770 DATA FECC75D961C35053,98
3780 DATA 8A1EA33A32FFBF53,5C
3790 DATA 2B2C01720503FBE9,9E
3800 DATA F7FFFEC086C403F8,FA
3810 DATA 5B58C35751B1008A,BB
3820 DATA D150BF372B5132ED,0D
3830 DATA D0E103F959022578,0B
3840 DATA 1A3A26A33A741402,02
3850 DATA 4501780F3A06A43A,7D
3860 DATA 7409E8B9FF843574,48
3870 DATA 02FEC258FEC180F9,68
3880 DATA 0875CE595FC35053,F5
3890 DATA 51B9DB128AFD8AD9,CA
3900 DATA D1E303CB8AD102D5,1A
3910 DATA 8AEA83C138890E0A,EB
3920 DATA 298AD5595B58C306,7C
3930 DATA 60BE3006B800A08E,EC
3940 DATA C033FFB023AAB035,06
3950 DATA AAB021AAB004AAB0,C3
3960 DATA 22AAB000AAB020AA,28
3970 DATA B92000ACC0E804AA,45
3980 DATA 47E2F8B20547B021,56
3990 DATA AA8AC2AAB022AAB0,0E
4000 DATA 00AAB020AAB92000,6C
4010 DATA 8A64E0ACC1E804AA,43
4020 DATA 47E2F5FEC280FA11,0A
4030 DATA 75DB81EE2000B204,04
4040 DATA 47B021AA8AC2AAB0,16
4050 DATA 22AAB020AAB020AA,A8
4060 DATA B920008A64E0ACC1,11
4070 DATA E804AA47E2F5FEC2,34
4080 DATA 80FA1175DB47B023,54
4090 DATA AAB075AA6107C353,0D
4100 DATA 5133DB8ADCB90800,4A
4110 DATA D1E38AE72AE07204,21
4120 DATA FEC38AFCE2F28AE3,06
4130 DATA 8AC7595BC34D494E,9B
4140 DATA 4520535745455045,29
4150 DATA 5220465800424F4D,E1
4160 DATA 42204C4546543A00,66
4170 DATA 3139393720284329,D7
4180 DATA 204142435020736F,61
4190 DATA 667477617265004C,2F
4200 DATA 4556454C20202020,30
4210 DATA 4541535920204E4F,1E
4220 DATA 524D414C00484152,E6
4230 DATA 442020435553544F,4F
4240 DATA 4D00435553544F4D,92
4250 DATA 204D4F4445004649,42
4260 DATA 454C442058205349,2E
4270 DATA 5A452020205B2020,66
4280 DATA 205D004649454C44,31
4290 DATA 20592053495A4520,EA
4300 DATA 20205B2020205D00,DC
4310 DATA 4E554D424552204F,84
4320 DATA 4620424F4D42205B,4D
4330 DATA 2020205D00000020,34
4340 DATA 0000206020207070,D0
4350 DATA 1070407070107010,90
4360 DATA 7050507010107040,80
4370 DATA 7010707040705070,30
4380 DATA 7050101010705070,20
4390 DATA 5070F8A8F8A8F870,C8
4400 DATA 88300020F8888888,68
4410 DATA F81060F0F0608850,20
4420 DATA 205088FF80878887,EE
4430 DATA 808F80FFFF00A222,93
4440 DATA 22A21C00FFFF0071,37
4450 DATA 8A828A7100FFFF00,E3
4460 DATA CF280F28CF00FFFF,E8
4470 DATA 009E209C02BC00FF,76
4480 DATA FF0179817109F101,7A
4490 DATA FFFF808784878484,13
4500 DATA 80FFFF00C40A911F,7A
4510 DATA 1100FFFF00742424,DE
4520 DATA 247700FFFF002222,07
4530 DATA 22229C00FFFF00F3,C7
4540 DATA 8AF3928B00FFFF01,4D
4550 DATA E101E101E101FF02,FE
4560 DATA 0010000400080000,60
4570 DATA 0140000001100000,E6
4580 DATA 0240008000200000,42
4590 DATA FF01FF0100010100,0F
4600 DATA 01FF01FF00FFFF14,91
4610 DATA 061400140C280014,4A
4620 DATA 146400##########,DC
ソースリスト
;******************************************************************************
; MINE SWEEPER FX
;
; 1997 (C)Copyright ABCP software
;******************************************************************************
ORG 2000H
;**************************************
;初期設定
;**************************************
CLD
XOR AX,AX
MOV DS,AX
MOV ES,AX
CALL CLS
MOV AH,3AH ;ROMフォントアドレスを求める(BIOS)
INT 41H
DB 0BEH
DW OFFSET FONT ;MOV SI,OFFSET FONT
MOV [SI],DI
MOV AX,ES
DB 089H,044H,002H ;MOV [SI+2],AX
MOV BYTE PTR X_SIZE,20
MOV BYTE PTR Y_SIZE,12
MOV WORD PTR NUM_MINE,40
;**************************************
;タイトル表示
;**************************************
MOV AX,0501H
DB 0BFH
DW OFFSET CPYRIGHT ;MOV DI,OFFSET CPYRIGHT
CALL ROMMOJI
CALL VRAM2LCD ;これを呼ばないと画面に表示されない
MOV CX,4000H
CPY_L:
CALL RND
LOOP CPY_L
TITLE:
CALL CLS
MOV AX,0800H
DB 0BFH
DW OFFSET M_DATA1 ;MOV DI,OFFSET M_DATA1
CALL ROMMOJI
MOV AX,0502H
DB 0BFH
DW OFFSET LEVEL ;MOV DI,OFFSET LEVEL
CALL ROMMOJI
MOV AX,0E03H
DB 0BFH
DW OFFSET LEVEL2 ;MOV DI,OFFSET LEVEL2
CALL ROMMOJI
MOV AX,0D02H
MOV DL,62 ;カーソル表示
CALL ONEMOJI
CALL VRAM2LCD
MENU_STR:
CALL RND
PUSH AX
MOV AX,0080H
MOV BX,0200H
CALL KEY ;リターンキーチェック
POP AX
JNZ MENU_END
MOV BX,AX
CALL KEY_KEY
SHR DH,1 ;4
JNC MENU_1
MOV AH,13
MENU_1:
SHR DH,1 ;6
JNC MENU_2
MOV AH,19
MENU_2:
SHR DH,1 ;8
JNC MENU_3
MOV AL,2
MENU_3:
SHR DH,1 ;2
JNC MENU_4
MOV AL,3
MENU_4:
CMP AX,BX
JE MENU_STR ;カーソルの点滅防止
PUSH AX
MOV AX,BX
MOV DL,32
CALL ONEMOJI
POP AX
MOV DL,62
CALL ONEMOJI
CALL VRAM2LCD
JMP MENU_STR
MENU_END:
MOV CX,3
CMP AH,19
JE MENU_A
SUB CL,1
MENU_A:
CMP AL,3
JE MENU_B
SUB CL,2
MENU_B:
CMP CL,3
JE MENU_CUS
DB 0BEH
DW OFFSET LV_DATA ;MOV SI,OFFSET LV_DATA
DB 0C0H,0E1H,2 ;SAL CL,2
ADD SI,CX
DB 0BFH
DW OFFSET X_SIZE ;MOV DI,OFFSET X_SIZE
MOV CL,4
REP MOVSB
JMP INIT
;**************************************
;カスタムモード
;**************************************
MENU_CUS:
MOV AX,0080H
MOV BX,0200H
CALL KEY ;RETを放すまで待つ
JNZ MENU_CUS
CALL CLS
MOV BYTE PTR K_R,15 ;キーリピートまでの待ち時間
MOV AX,0A00H
DB 0BFH
DW OFFSET CUSTOM ;MOV DI,OFFSET CUSTOM
CALL ROMMOJI
MOV AX,0601H
DB 0BFH
DW OFFSET FIELDX ;MOV DI,OFFSET FIELDX
CALL ROMMOJI
MOV AX,0602H
DB 0BFH
DW OFFSET FIELDY ;MOV DI,OFFSET FIELDY
CALL ROMMOJI
MOV AX,0603H
DB 0BFH
DW OFFSET FIELDB ;MOV DI,OFFSET FIELDB
CALL ROMMOJI
MOV AX,0501H
MOV DL,62
CALL ONEMOJI ;カーソル表示
CALL VRAM2LCD
CUSTOM_L:
PUSH AX
MOV AX,0080H
MOV BX,0200H
CALL KEY ;リターンキーチェック
POP AX
JZ CUS_C
JMP INIT
CUS_C:
MOV BX,AX
CALL KEY_KEY
SHR DH,1 ;2
JNC CUSTOM_1
CMP AL,3
JZ CUSTOM_C
CMP AL,2
JZ CUSTOM_B
;CUSTOM_A:
CMP BYTE PTR X_SIZE,6 ;Xサイズの最低値
JZ CUSTOM_1
DEC BYTE PTR X_SIZE
JMP CUSTOM_1
CUSTOM_B:
CMP BYTE PTR Y_SIZE,6 ;Yサイズの最低値
JZ CUSTOM_1
DEC BYTE PTR Y_SIZE
JMP CUSTOM_1
CUSTOM_C:
CMP WORD PTR NUM_MINE,1 ;爆弾数の最低値
JZ CUSTOM_1
DEC WORD PTR NUM_MINE
CUSTOM_1:
SHR DH,1 ;4
JNC CUSTOM_2
CMP AL,3
JZ CUSTOM_F
CMP AL,2
JZ CUSTOM_E
;CUSTOM_D:
CMP BYTE PTR X_SIZE,20 ;Xサイズの最大値
JZ CUSTOM_2
INC BYTE PTR X_SIZE
JMP CUSTOM_2
CUSTOM_E:
CMP BYTE PTR Y_SIZE,49 ;Yサイズの最大値
JZ CUSTOM_2
INC BYTE PTR Y_SIZE
JMP CUSTOM_2
CUSTOM_F:
PUSH AX
MOV AL,Y_SIZE
DEC AL
MUL BYTE PTR X_SIZE ;AX=爆弾の最大値
CMP AX,NUM_MINE
POP AX
JZ CUSTOM_2
INC WORD PTR NUM_MINE
CUSTOM_2:
SHR DH,1 ;8
JNC CUSTOM_3
CMP AL,1
JZ CUSTOM_3
DEC AL
CUSTOM_3:
SHR DH,1 ;2
JNC CUSTOM_4
CMP AL,3
JZ CUSTOM_4
INC AL
CUSTOM_4:
CMP AX,BX
JZ CUSTOM_5 ;カーソルの点滅防止
PUSH AX
MOV AX,BX
MOV DL,32
CALL ONEMOJI
POP AX
MOV DL,62
CALL ONEMOJI
CUSTOM_5:
PUSH AX
MOV AL,Y_SIZE
DEC AL
MUL BYTE PTR X_SIZE
CMP AX,NUM_MINE
JA CUSTOM_6
MOV NUM_MINE,AX
CUSTOM_6:
XOR CH,CH
MOV AX,1601H
MOV CL,X_SIZE
CALL NUMBER
MOV AX,1602H
MOV CL,Y_SIZE
CALL NUMBER
MOV AX,1603H
MOV CX,NUM_MINE
CALL NUMBER
POP AX
CALL VRAM2LCD
MOV CX,800
CUS_WAIT:
LOOP CUS_WAIT
JMP CUSTOM_L
;**************************************
;ワークエリア初期化
;**************************************
INIT:
CALL CLS
XOR AX,AX
MOV NOW_X,AL
MOV NOW_Y,AL
MOV Y_SCROLL,AL
MOV K_REPEAT,AL
MOV BYTE PTR FIRST,1
MOV BOMB,AL
MOV BYTE PTR K_R,3
DB 0BFH
DW OFFSET BRAM ;MOV DI,OFFSET BRAM
MOV AL,080H
MOV CX,980
REP STOSB
PUT_MINE: ;爆弾を置く
MOV CX,NUM_MINE
MOV AL,X_SIZE
MUL BYTE PTR Y_SIZE ;AX=マスの数
SUB AX,CX
MOV MASULEFT,AX
MOV BOMBLEFT,CX
PUT_L:
CALL P_M
LOOP PUT_L
MOV AX,1101H
DB 0BFH
DW OFFSET M_DATA1 ;MOV DI,OFFSET M_DATA1
CALL ROMMOJI
MOV AX,1202H
DB 0BFH
DW OFFSET M_DATA2 ;MOV DI,OFFSET M_DATA2
CALL ROMMOJI
CALL VRAM2LCD
;**************************************
;メイン
;**************************************
MAIN:
MOV DL,Y_SCROLL
MOV CH,0
CALL PRNTMINE ;マス目表示
MOV AH,NOW_X
MOV AL,NOW_Y
ADD AL,Y_SCROLL
CALL XY
MOV DL,[DI]
MOV CH,1
MOV AL,NOW_Y
CALL WRITECHR ;カーソル表示
KEY_READ:
CALL KEY_KEY
KEY_2:
SHR DH,1 ;4
JNC KEY_3
CMP BYTE PTR NOW_X,0
JE KEY_3
DEC BYTE PTR NOW_X
KEY_3:
SHR DH,1 ;6
JNC KEY_4
MOV BL,X_SIZE
DEC BL
CMP BL,NOW_X
JE KEY_4
INC BYTE PTR NOW_X
KEY_4:
SHR DH,1 ;2
JNC KEY_5
CMP BYTE PTR NOW_Y,0
JNZ CUR_UP
CMP BYTE PTR Y_SCROLL,0
JZ KEY_5
DEC BYTE PTR Y_SCROLL ;スクロール
JMP KEY_5
CUR_UP:
DEC BYTE PTR NOW_Y
KEY_5:
SHR DH,1
JNC KEY_6
CMP BYTE PTR NOW_Y,5
JNZ CUR_DW
MOV BH,Y_SIZE
SUB BH,6
CMP BH,Y_SCROLL
JE KEY_6
INC BYTE PTR Y_SCROLL ;スクロール
JMP KEY_6
CUR_DW:
INC BYTE PTR NOW_Y
KEY_6:
SHR DH,1 ;S
JC KEY_S
JMP KEY_7
;**************************************
;マスの自動展開
;**************************************
KEY_ENDS:
NOP
JMP KEY_END
KEY_S:
MOV AH,NOW_X
MOV AL,NOW_Y
ADD AL,Y_SCROLL
CALL XY
TEST BYTE PTR [DI],080H ;そのマスが空の時は同時クリック処理
JNZ KEY_S_ER
JMP KEY_Z
KEY_S_ER:
CALL XY
MOV DL,[DI]
TEST DL,060H ;フラグがなかったら掘る
JZ KEY_S_S
JMP KEY_ENDS
KEY_S_S:
TEST DL,80H ;掘ってなかったら掘る
JNZ KEY_S_S2
JMP KEY_ENDS
KEY_S_S2:
AND DL,01H
MOV [DI],DL ;掘った
CMP DL,01H
JNZ NF_BOMB
JMP F_BOMB ;爆弾を掘ってしまったら;F_BOMB
NF_BOMB:
DEC WORD PTR MASULEFT ;掘られていないマスの数を計算
PUSH AX
PUSH DI
DB 0BFH
DW OFFSET BRAMBRAM ;MOV DI,OFFSET BRAMBRAM
MOV CX,980
XOR AL,AL
REP STOSB ;通り道チェック領域初期化
POP DI
POP AX
MOV BYTE PTR FIRST,0 ;いきなり爆弾防止はもう必要ない
MOV DH,1 ;自分のマスの周りの爆弾探し
CALL AROUND_B
MOV CH,0
PUSH AX
MOV AH,NOW_X
MOV AL,NOW_Y
SAL DL,1
CALL WRITECHR ;自分のマスの情報を表示
POP AX
MOV [DI],DL
CMP DL,0
JE NEAR
JMP NOT_NEAR ;自分のマスが空でなかったら処理しない
NEAR:
SUB DI,OFFSET BRAM
ADD DI,OFFSET BRAMBRAM
MOV BYTE PTR [DI],1
DB 0BEH
DW OFFSET PLACE ;MOV SI,OFFSET PLACE
MOV CL,7
SEARCH_B:
CALL MY_PUSH ;マスの情報を記録
SEARCH:
MOV CL,0
SEARCH_1:
DB 0BFH
DW OFFSET VECTOR ;MOV DI,OFFSET VECTOR
PUSH CX ;次のマスの情報を読む
XOR CH,CH
SAL CL,1
ADD DI,CX ;上から時計周りに調べる
POP CX
PUSH AX ;そのマスが存在するか
ADD AH,[DI]
JS SEARCH_E ;座標がマイナスならばマスは存在しない
CMP AH,X_SIZE ;座標が飛び出していたらマスは存在しない
JE SEARCH_E
DB 02H,45H,01H ;ADD AL,[DI+1]
JS SEARCH_E
CMP AL,Y_SIZE
JE SEARCH_E
CALL XY
TEST BYTE PTR [DI],060H ;そのマスにフラグがあったら処理しない
JNZ SEARCH_E
TEST BYTE PTR [DI],080H ;そのマスが開いていたら処理しない
JZ SEARCH_E
MOV BX,DI
SUB BX,OFFSET BRAM ;通り道は処理しない
ADD BX,OFFSET BRAMBRAM
CMP BYTE PTR [BX],0
JNZ SEARCH_E
MOV BYTE PTR [BX],1
MOV DH,1
CALL AROUND_B ;周りの爆弾の数を求める
SAL DL,1
MOV [DI],DL ;周りの爆弾数記録
DEC WORD PTR MASULEFT
CMP DL,0
JNZ SEARCH_E
MOV BX,AX
POP AX
CALL MY_PUSH ;座標を記録して
MOV AX,BX
JMP SEARCH ;更に掘る
SEARCH_E:
POP AX
SEARCH_N:
INC CL ;次はどの方向を調べるか
CMP CL,8
JNE SEARCH_1
CALL MY_POP ;手前の座標を呼び出す
CMP SI,OFFSET PLACE
JNE SEARCH_N
NOT_NEAR:
JMP KEY_ENDS
;**************************************
;爆弾を掘ってしまった!
;**************************************
F_BOMB:
CMP BYTE PTR FIRST,1
JE NOT_BOMB ;いきなり爆弾の時はなかったことにする
MOV BYTE PTR BOMB,1
JMP KEY_ENDS
NOT_BOMB:
MOV BYTE PTR FIRST,0
NOTBOMB1:
MOV BYTE PTR [DI],080H ;爆弾をなかったことにする
PUSH DI
CALL P_M
POP SI
CMP DI,SI ;同じ場所を選んでしまったらもう一度
JE NOTBOMB1
JMP KEY_S
KEY_7:
SHR DH,1 ;A
JC KEY_A
JMP KEY_END
;**************************************
;フラグ立て
;**************************************
KEY_A:
MOV AH,NOW_X
MOV AL,NOW_Y
ADD AL,Y_SCROLL
CALL XY
MOV DL,[DI]
TEST DL,0E0H ;掘ってあるマスは処理しない
JNZ KEY_A_2
JMP KEY_END
KEY_A_2:
MOV BL,DL ;爆弾フラグを保存
AND BL,01H
AND DL,0E0H
SAL DL,1
JNC N_O_F
MOV DL,020H
DEC WORD PTR BOMBLEFT ;残り爆弾数の調整
N_O_F:
TEST DL,080H
JZ N_O_F2
INC WORD PTR BOMBLEFT ;残り爆弾数の調整
N_O_F2:
OR DL,BL ;爆弾フラグの復帰
MOV AL,NOW_Y
MOV [DI],DL
MOV CH,0
CALL WRITECHR
JMP KEY_END
;**************************************
;同時クリック処理
;**************************************
KEY_ENDZ:
JMP KEY_END
KEY_Z:
MOV AH,NOW_X
MOV AL,NOW_Y
ADD AL,Y_SCROLL
CALL XY
TEST BYTE PTR [DI],0E0H ;マスが開いているときだけ処理
JNZ KEY_ENDZ
MOV DL,[DI]
SHR DL,1 ;DL=そのマスの周りの爆弾数
MOV CL,DL
MOV DH,020H ;周りの旗の数を調べる
CALL AROUND_B
CMP CL,DL ;周りの旗の数と周りの爆弾数が一致したら
JNE KEY_ENDZ ;周り8マスを掘る
MOV CL,0
KEY_Z_L:
PUSH AX
DB 0BFH
DW OFFSET VECTOR ;MOV DI,OFFSET VECTOR
PUSH CX
XOR CH,CH
SAL CL,1
ADD DI,CX
POP CX
ADD AH,[DI] ;掘るマスが存在するかどうか
JS KEY_Z_E
CMP AH,X_SIZE
JE KEY_Z_E
DB 02H,45H,01H ;ADD AL,[DI+1]
JS KEY_Z_E
CMP AL,Y_SIZE
JE KEY_Z_E
MOV BYTE PTR KEY_ENDS,0C3H ;RET
PUSH CX
CALL KEY_S_ER ;サブルーチンとして呼び出す
POP CX
MOV BYTE PTR KEY_ENDS,090H ;NOP
KEY_Z_E:
POP AX
INC CL
CMP CL,8
JNE KEY_Z_L
JMP KEY_ENDZ
;**************************************
;ゲームオーバー判定
;**************************************
KEY_END:
MOV AX,1C02H
MOV CX,BOMBLEFT ;残り爆弾数表示
MOV DL,32
CMP CX,08000H
JC NOT_PLUS
NEG CX
MOV DL,45
NOT_PLUS:
CALL ONEMOJI ;符号表示(SPCか-)
INC AH
CALL NUMBER
CALL VRAM2LCD
CMP BYTE PTR BOMB,0 ;ゲームオーバーフラグが立っていたらゲームオーバー
JNE OVER
CMP WORD PTR MASULEFT,0 ;すべてのマスを掘ってしまったらクリア
JNZ TO_MAIN
JMP CLEAR
TO_MAIN:
JMP MAIN
;**************************************
;ゲームオーバー
;**************************************
OVER:
DB 0BFH
DW OFFSET BRAM ;MOV DI,OFFSET BRAM
MOV AL,X_SIZE
MUL BYTE PTR Y_SIZE
MOV CX,AX
OVER_1:
MOV DL,[DI]
TEST DL,020H ;旗があって
JZ OVER_3
TEST DL,01H ;爆弾なしのときは
JNZ OVER_4
MOV DL,26 ;×を表示
JMP OVER_4
OVER_3:
TEST DL,20H ;旗がなくて
JNZ OVER_4
TEST DL,01H ;爆弾があるときは
JZ OVER_4
MOV DL,1 ;爆弾の表示
OVER_4:
MOV [DI],DL
INC DI
LOOP OVER_1
MOV BH,4
MOV CH,0FFH ;反転表示
OVER_5:
MOV DL,Y_SCROLL
CALL PRNTMINE
CALL VRAM2LCD
NOT CH ;反転と通常の切り替え
DEC BH
JNZ OVER_5
DB 0BEH
DW OFFSET G_OVER ;MOV SI,OFFSET G_OVER
MOV DI,69BH
DB 0BDH
DW OFFSET PLACE ;MOV BP,OFFSET PLACE
MOV BL,6
OVER_6:
MOV CX,9
OVER_7:
MOV AL,[DI]
MOV DS:[BP],AL ;VRAM待避
MOV AL,[SI]
MOV [DI],AL ;FAILURE表示
INC DI
INC SI
INC BP
LOOP OVER_7
DB 083H,0C7H,23 ;ADD DI,23
DEC BL
JNZ OVER_6
CALL VRAM2LCD
MOV AL,4
OVER_8:
XOR CX,CX
OVER_9:
LOOP OVER_9
DEC AL
JNZ OVER_8
DB 0BEH
DW OFFSET PLACE ;MOV SI,OFFSET PLACE
MOV DI,69BH
MOV BL,6
OVER_10:
MOV CX,9
OVER_11:
MOV AL,[SI]
MOV [DI],AL ;元の画面表示
INC DI
INC SI
LOOP OVER_11
DB 083H,0C7H,23 ;ADD DI,23
DEC BL
JNZ OVER_10
CALL VRAM2LCD
JMP END_
;**************************************
;ゲームクリア
;**************************************
CLEAR:
DB 0BFH
DW OFFSET BRAM ;MOV DI,OFFSET BRAM
MOV AL,X_SIZE
MUL BYTE PTR Y_SIZE
MOV CX,AX
CLEAR_1:
MOV DL,[DI]
TEST DL,080H ;開いていないマスは
JZ CLEAR_2
AND DL,07FH ;開いて
OR DL,020H ;フラグを立てる
MOV [DI],DL
CLEAR_2:
INC DI
LOOP CLEAR_1
MOV DL,Y_SCROLL
MOV CH,0
CALL PRNTMINE
MOV AX,1D02H
XOR CX,CX
CALL NUMBER
DB 0BEH
DW OFFSET G_CLEAR ;MOV SI,OFFSET G_CLEAR
MOV DI,69BH
DB 0BDH
DW OFFSET PLACE ;MOV BP,OFFSET PLACE
MOV BL,6
CLEAR_3:
MOV CX,9
CLEAR_4:
MOV AL,[DI]
MOV DS:[BP],AL ;VRAM待避
MOV AL,[SI]
MOV [DI],AL ;SUCCESS表示
INC DI
INC SI
INC BP
LOOP CLEAR_4
DB 083H,0C7H,23 ;ADD DI,23
DEC BL
JNZ CLEAR_3
CALL VRAM2LCD
MOV AL,4
CLEAR_5:
XOR CX,CX
CLEAR_6:
LOOP CLEAR_6
DEC AL
JNZ CLEAR_5
DB 0BEH
DW OFFSET PLACE ;MOV SI,OFFSET PLACE
MOV DI,69BH
MOV BL,6
CLEAR_7:
MOV CX,9
CLEAR_8:
MOV AL,[SI]
MOV [DI],AL ;元の画面を表示
INC DI
INC SI
LOOP CLEAR_8
DB 083H,0C7H,23 ;ADD DI,23
DEC BL
JNZ CLEAR_7
CALL VRAM2LCD
;**************************************
;ゲームエンド&リトライ
;**************************************
END_:
MOV DL,Y_SCROLL
CALL PRNTMINE
CALL VRAM2LCD
MOV BYTE PTR K_R,200
END_END:
MOV DL,Y_SCROLL
CALL KEY_KEY
DB 0C0H,0EEH,3 ;SHR DH,3 / 2
JNC N_UP_B
CMP DL,0
JZ N_UP_B
DEC DL
N_UP_B:
SHR DH,1 ;8
JNC N_DW_B
MOV BH,Y_SIZE
SUB BH,6
CMP BH,DL
JE N_DW_B
INC DL
N_DW_B:
CMP DL,Y_SCROLL
JE N_PRINT
MOV Y_SCROLL,DL
MOV CH,0
CALL PRNTMINE ;スクロールして表示
CALL VRAM2LCD
N_PRINT:
MOV AX,0080H ;[RET]
MOV BX,0200H
CALL KEY
JNZ N_PRINT2
MOV AX,0400H ;[CLS]
MOV BX,0010H
CALL KEY
JNZ N_PRINT3
JMP END_END
N_PRINT2:
JMP INIT
N_PRINT3:
JMP TITLE
;**************************************
;サブルーチンの大群
;**************************************
NUMBER: ;数字の表示
PUSHA
CMP CX,08000H
JC NUMBER1
NEG CX
NUMBER1:
MOV BX,100
CALL WARI16
CALL ONEMOJI
INC AH
MOV BX,10
CALL WARI16
CALL ONEMOJI
INC AH
MOV BX,1
CALL WARI16
CALL ONEMOJI
POPA
RET
WARI16: ;数字表示用割り算
XOR DL,DL
WARI16C:
SUB CX,BX
JC WARI16E
INC DL
JMP WARI16C
WARI16E:
ADD CX,BX
ADD DL,48
RET
ONEMOJI: ;ROM文字の1文字表示
PUSHA
PUSH ES
MOV BX,AX
SAL BH,1
DB 0C0H,0E4H,2 ;SAL AH,2
ADD AH,BH ;6倍
MOV AL,8
CALL WARI
MOV CL,AL
MOV SI,0630H
MOV AL,AH
XOR AH,AH
DB 0C1H,0E0H,5 ;SAL AX,5
ADD SI,AX
XOR BH,BH
DB 0C1H,0E3H,3 ;SAL BX,3
ADD SI,BX
SUB DL,32
DB 0BBH
DW OFFSET FONT ;MOV BX,OFFSET FONT
MOV DI,[BX]
DB 08BH,047H,2 ;MOV AX,[BX+2]
MOV ES,AX
XOR DH,DH
DB 0C1H,0E2H,3 ;SAL DX,3
ADD DI,DX
MOV AH,8
OM_L:
MOV DH,ES:[DI]
DB 0C0H,0E6H,2 ;SAL DH,2
INC DI
XOR DL,DL
MOV BX,0FC00H
SHR BX,CL
SHR DX,CL
NOT BX
AND [SI],BH
DB 020H,05CH,020H ;AND [SI+20H],BL
OR [SI],DH
DB 008H,054H,020H ;OR [SI+20H],DL
INC SI
DEC AH
JNZ OM_L
POP ES
POPA
RET
ROMMOJI: ;ROM文字の表示
PUSHA
ROMMOJIL:
MOV DL,[DI]
INC DI
CMP DL,0
JZ ROMMOJIE
CALL ONEMOJI
INC AH
JMP ROMMOJIL
ROMMOJIE:
POPA
RET
MY_PUSH: ;座標の記憶
PUSH BX
MOV BL,AH
DB 0C0H,0E3H,3 ;SAL BL,3
OR BL,CL
MOV BH,AL
MOV [SI],BX
INC SI
INC SI
POP BX
RET
MY_POP: ;座標の呼び出し
PUSH BX
DEC SI
DEC SI
MOV BX,[SI]
MOV CL,BL
AND CL,07H
MOV AH,BL
DB 0C0H,0ECH,3 ;SHR AH,3
MOV AL,BH
POP BX
RET
P_M: ;マスに爆弾を置く
CALL RND
AND DL,1FH
CMP DL,X_SIZE
JNC P_M
MOV AH,DL
P_M_L2:
CALL RND
CMP DL,Y_SIZE
JNC P_M_L2
MOV AL,DL
CALL XY
CMP BYTE PTR [DI],080H
JNZ P_M
MOV BYTE PTR [DI],081H
RET
KEY: ;キー入力
PUSH DX
MOV DX,200H
OUT DX,AX
PUSH AX
POP AX
MOV DL,2
IN AX,DX
AND AX,BX
POP DX
RET
KEY_KEY: ;リピート付きキー入力
PUSH AX
PUSH BX
MOV AX,1
MOV BX,AX
CALL KEY
JZ KEY_K
MOV AH,7FH ;電源を切る
INT 41H
KEY_K:
XOR DH,DH
DB 0BFH
DW OFFSET K_DAT ;MOV DI,OFFSET K_DAT
MOV CX,2
KEY_KL:
SAL DH,1
MOV AX,[DI]
DB 08BH,05DH,002H ;MOV BX,[DI+2]
DB 083H,0C7H,004H ;ADD DI,4
CALL KEY
JZ KEY_K1 ;そのキーが押されていないとき
OR DH,1
KEY_K1:
LOOP KEY_KL
MOV CL,4
KEY_KL2:
SAL DH,1
MOV AX,[DI]
DB 08BH,05DH,002H ;MOV BX,[DI+2]
DB 083H,0C7H,004H ;ADD DI,4
CALL KEY
JZ KEY_K2 ;そのキーが押されていないとき
CMP DH,0
JNZ KEY_K2 ;他のキーが押されているとき
OR DH,1
KEY_K2:
LOOP KEY_KL2
MOV AL,LASTKEY
TEST AL,070H ;前回A,S,Zを押してなかったら
JZ REPEAT_1
MOV LASTKEY,DH
AND DH,0FH ;A,S,Zのリピート禁止
JMP REPEAT_F
REPEAT_1:
AND AL,0FH ;前回テンキーを押していなかったら
JZ REPEAT_3
TEST DH,AL ;前回と同じキーを押していなかったら
JZ REPEAT_R
INC BYTE PTR K_REPEAT
JMP REPEAT_2
REPEAT_R:
MOV BYTE PTR K_REPEAT,0
JMP REPEAT_3
REPEAT_2:
CMP BYTE PTR K_REPEAT,0 ;最初は反応
JE REPEAT_3
DB 080H,03EH
DW OFFSET K_REPEAT
K_R:
DB 3 ;CMP BYTE PTR K_REPEAT,x
JNC REPEAT_4
MOV LASTKEY,DH
AND DH,30H
JMP REPEAT_F
REPEAT_4:
DEC BYTE PTR K_REPEAT
REPEAT_3:
MOV LASTKEY,DH
REPEAT_F:
POP BX
POP AX
RET
CLS: ;CLS
XOR AX,AX
MOV ES,AX
MOV DI,630H
MOV CX,1024
REP STOSB
CALL VRAM2LCD
RET
PRNTMINE: ;全てのマスの表示
XOR AX,AX
ADD AL,DL
CALL XY
XOR CL,CL
XOR AX,AX
PRNTMN_1:
MOV AH,0
PRNTMN_2:
MOV DL,[DI]
INC DI
CALL WRITECHR
INC AH
CMP AH,X_SIZE
JNE PRNTMN_2
INC AL
INC CL
CMP CL,6
JNE PRNTMN_1
RET
WRITECHR: ;5*5キャラの表示
PUSHA
MOV BX,AX
DB 0C0H,0E4H,2 ;SAL AH,2
ADD AH,BH ;5倍
MOV AL,8
CALL WARI
MOV CL,AL
MOV SI,0630H
MOV AL,AH
XOR AH,AH
DB 0C1H,0E0H,5 ;SAL AX,5
ADD SI,AX
XOR BH,BH
ADD SI,BX
DB 0C1H,0E3H,2 ;SAL BX,2
ADD SI,BX
INC SI
TEST DL,0E0H
JZ MASK_2
DB 0C0H,0EAH,5 ;SHR DL,5
CMP DL,4
JNE MASK_1
DEC DL
MASK_1:
ADD DL,8 ;マスクする
JMP MASK_3
MASK_2:
TEST DL,1
JNZ MASK_4
SHR DL,1
JMP MASK_3
MASK_4:
MOV DL,12
MASK_3:
MOV DH,DL
DB 0C0H,0E2H,2 ;SAL DL,2
ADD DL,DH ;5倍
DB 0BFH
DW OFFSET CHR5 ;MOV DI,OFFSET CHR5
XOR DH,DH
ADD DI,DX
MOV AH,5
W_C_L:
MOV DH,[DI]
CMP CH,0
JZ W_C_LL
NOT DH
AND DH,0F8H
W_C_LL:
INC DI
XOR DL,DL
MOV BX,0F800H
SHR BX,CL
SHR DX,CL
NOT BX
AND [SI],BH
DB 020H,05CH,020H ;AND [SI+20H],BL
OR [SI],DH
DB 008H,054H,020H ;OR [SI+20H],DL
INC SI
DEC AH
JNZ W_C_L
POPA
RET
XY: ;仮想配列変数
PUSH AX
PUSH BX
MOV BL,X_SIZE
XOR BH,BH
DB 0BFH
DW OFFSET BRAM ;MOV DI,OFFSET BRAM
XY_2:
SUB AL,1
JC XY_3
ADD DI,BX
JMP XY_2
XY_3:
INC AL
XCHG AL,AH
ADD DI,AX
POP BX
POP AX
RET
AROUND_B: ;周りの爆弾か旗の数を求める
PUSH DI
PUSH CX
MOV CL,0
MOV DL,CL
AROUND_L:
PUSH AX
DB 0BFH
DW OFFSET VECTOR ;MOV DI,OFFSET VECTOR
PUSH CX
XOR CH,CH
SAL CL,1
ADD DI,CX
POP CX
ADD AH,[DI]
JS AROUND_E
CMP AH,X_SIZE
JE AROUND_E
DB 02H,45H,01H ;ADD AL,[DI+1]
JS AROUND_E
CMP AL,Y_SIZE
JE AROUND_E
CALL XY
TEST BYTE PTR [DI],DH
JZ AROUND_E
INC DL
AROUND_E:
POP AX
INC CL
CMP CL,8
JNE AROUND_L
POP CX
POP DI
RET
RND: ;乱数を発生する
PUSH AX
PUSH BX
PUSH CX
DB 0B9H ;CX=?
RNDDT:
DW 12DBH
MOV BH,CH
MOV BL,CL
SAL BX,1
ADD CX,BX
MOV DL,CL
ADD DL,CH
MOV CH,DL
DB 083H,0C1H,038H ;ADD CX,0038H
MOV RNDDT,CX
MOV DL,CH
POP CX
POP BX
POP AX
RET
VRAM2LCD: ;VRAMをLCDに表示
PUSH ES
PUSHA
MOV SI,630H
MOV AX,0A000H
MOV ES,AX
XOR DI,DI
MOV AL,23H
STOSB
MOV AL,35H
STOSB
MOV AL,21H
STOSB
MOV AL,4
STOSB
MOV AL,22H
STOSB
MOV AL,0
STOSB
MOV AL,20H
STOSB
MOV CX,32
V2L_0:
LODSB
DB 0C0H,0E8H,004H ;SHR AL,4
STOSB
INC DI
LOOP V2L_0
MOV DL,5
V2L_1:
INC DI
MOV AL,21H
STOSB
MOV AL,DL
STOSB
MOV AL,22H
STOSB
MOV AL,0
STOSB
MOV AL,20H
STOSB
MOV CX,32
V2L_2:
DB 08AH,064H,0E0H ;MOV AH,[SI-20H]
LODSB
DB 0C1H,0E8H,004H ;SHR AX,4
STOSB
INC DI
LOOP V2L_2
INC DL
CMP DL,17
JNZ V2L_1
SUB SI,32
MOV DL,4
V2L_3:
INC DI
MOV AL,21H
STOSB
MOV AL,DL
STOSB
MOV AL,22H
STOSB
MOV AL,32
STOSB
MOV AL,20H
STOSB
MOV CX,32
V2L_4:
DB 08AH,064H,0E0H ;MOV AH,[SI-20H]
LODSB
DB 0C1H,0E8H,004H ;SHR AX,4
STOSB
INC DI
LOOP V2L_4
INC DL
CMP DL,17
JNZ V2L_3
INC DI
MOV AL,23H
STOSB
MOV AL,75H
STOSB
POPA
POP ES
RET
WARI: ;AH/AL=AH...AL
PUSH BX
PUSH CX
XOR BX,BX
MOV BL,AH
MOV CX,8
WARI_L:
SAL BX,1
MOV AH,BH
SUB AH,AL
JC WARI_S
INC BL
MOV BH,AH
WARI_S:
LOOP WARI_L
MOV AH,BL
MOV AL,BH
POP CX
POP BX
RET
;**************************************
;データ
;**************************************
M_DATA1:
DB 'MINE '
DB 'SWEEPER FX'
DB 0
M_DATA2:
DB 'BOMB LEFT:'
DB 0
CPYRIGHT:
DB '1997 (C) ABC'
DB 'P software'
DB 0
LEVEL:
DB 'LEVEL '
DB 'EASY NORMAL'
DB 0
LEVEL2:
DB 'HARD CUSTOM'
DB 0
CUSTOM:
DB 'CUSTOM MODE'
DB 0
FIELDX:
DB 'FIELD X SIZE'
DB ' [ ]'
DB 0
FIELDY:
DB 'FIELD Y SIZE'
DB ' [ ]'
DB 0
FIELDB:
DB 'NUMBER OF BO'
DB 'MB [ ]'
DB 0
CHR5:
DB 000H,000H,020H,000H,000H ;0
DB 020H,060H,020H,020H,070H ;1
DB 070H,010H,070H,040H,070H ;2
DB 070H,010H,070H,010H,070H ;3
DB 050H,050H,070H,010H,010H ;4
DB 070H,040H,070H,010H,070H ;5
DB 070H,040H,070H,050H,070H ;6
DB 070H,050H,010H,010H,010H ;7
DB 070H,050H,070H,050H,070H ;8
DB 0F8H,0A8H,0F8H,0A8H,0F8H ;旗
DB 070H,088H,030H,000H,020H ;?
DB 0F8H,088H,088H,088H,0F8H ;空いてないマス
DB 010H,060H,0F0H,0F0H,060H ;爆弾
DB 088H,050H,020H,050H,088H ;×
G_CLEAR:
DB 0FFH,080H,087H,088H,087H,080H,08FH,080H,0FFH
DB 0FFH,000H,0A2H,022H,022H,0A2H,01CH,000H,0FFH
DB 0FFH,000H,071H,08AH,082H,08AH,071H,000H,0FFH
DB 0FFH,000H,0CFH,028H,00FH,028H,0CFH,000H,0FFH
DB 0FFH,000H,09EH,020H,09CH,002H,0BCH,000H,0FFH
DB 0FFH,001H,079H,081H,071H,009H,0F1H,001H,0FFH
G_OVER:
DB 0FFH,080H,087H,084H,087H,084H,084H,080H,0FFH
DB 0FFH,000H,0C4H,00AH,091H,01FH,011H,000H,0FFH
DB 0FFH,000H,074H,024H,024H,024H,077H,000H,0FFH
DB 0FFH,000H,022H,022H,022H,022H,09CH,000H,0FFH
DB 0FFH,000H,0F3H,08AH,0F3H,092H,08BH,000H,0FFH
DB 0FFH,001H,0E1H,001H,0E1H,001H,0E1H,001H,0FFH
K_DAT:
DW 0002H,0010H
DW 0004H,0008H
DW 0100H,0040H
DW 0100H,0010H
DW 0200H,0040H
DW 0080H,0020H
VECTOR:
DB 0,255,1,255,1,0,1,1
DB 0,1,255,1,255,0,255,255
LV_DATA:
DB 20,6
DW 20
DB 20,12
DW 40
DB 20,20
DW 100
;**************************************
;ワークエリア
;**************************************
BRAM DB 980 DUP(?) ;マスの状態
BRAMBRAM DB 980 DUP(?) ;そのマスを処理したか
PLACE DW 980 DUP(?) ;自動展開用ワーク
X_SIZE DB 0 ;X方向のマス数
Y_SIZE DB 0 ;Y方向のマス数
NUM_MINE DW 0 ;爆弾数
NOW_X DB 0 ;カーソルのある場所
NOW_Y DB 0 ;カーソルのある場所
Y_SCROLL DB 0 ;スクロールして何行目か
LASTKEY DB 0 ;前回押されたキー
K_REPEAT DB 0 ;キーリピート時間調整用
FIRST DB 0 ;1発目に爆弾を防ぐ
BOMB DB 0 ;爆発フラグ
BOMBLEFT DW 0 ;残りの爆弾
MASULEFT DW 0 ;掘られていないマスの数
FONT DW 0,0 ;ROMフォントアドレス
























コメント
コメント(0件)
コメントする
トラックバック
トラックバック(0件)
トラックバック先