Making「ストレトリ」(その1)

Home PC-6001mkII Program etc

 このページでは、手詰まり実装までの過程を書いています。

Making「ストレトリ」 Top


2006/09/26:やりたいこと
 基本ルールは、HSP版と同じにする。

 HSPで出来てP6で出来ない事(マウス操作や回転カーソル等)はすっぱり諦めて、逆にHSPのショートプログラムで出来なかった事を中心に機能を追加していきたい。どこまでできるかはやはり不明だが、以下を目標に作成する。
  1. 面サイズの拡張
    面のバリエーションを考えると、出来れば8x8サイズにしたい所。
  2. 面数の増加
    10〜16面くらいを目標にする。
  3. 音を入れる
    むしろ、入れて当然かも?
  4. 面データの読込み
    8x8で64バイトなら、なんとか INPUT#でも実現できそうだが...。
  5. コンストラクション
    プログラムサイズさえ許せば比較的簡単に出来るかも?

2006/09/26:心配事
 パズルの移植にあたって、心配事が一つある。手詰まり判定だ。
 逆に言うとここさえクリアできればあとは何とかなる気がする。

 手詰まり判定で気になる部分は、やはり処理速度だ。

 ちなみに、HSP版で手詰まり判定を行う際に行っている判定処理では、
1行分のデータに対し6マス判定が1通り,5マス判定が2通り,4マス判定が3通り,3マス判定が4通りの計10通りで、これが6行6列分あるので、10x(6+6)=120通りとなる。

 これが、8x8マスになると、当然判定パターン数は増える。どれ位かというと、
(1+2+3+4+5+6)x(8+8)=336通り。単純に6x6マスの約3倍の時間が掛かる事になる。
とはいえ、手詰まり処理に1秒以上もかける事は避けたい。さて、上手くいくものか...。

2006/10/01:メモリマップ
 まだ判定ルーチンは試行錯誤中のため、今回はマシン語やデータを格納する場所「メモリマップ」を設定する過程を紹介する。

 私の場合、以下の項目でメモリ領域を区別する。
  1. プログラム領域
  2. グラフィックデータ領域
  3. 表示画面と一手戻し用データ
  4. その他ワーク領域
 これらの項目毎に必要な量を割り出し、P6のメモリマップに合うように領域を配置していく。

プログラム領域
 プログラム領域はどれだけ膨らむかが想像付きにくいが、これまでの作成プログラムでは最長でも約600バイト(少ない?)という事もあって、余裕をもって1,024バイトを割り当てる。

グラフィックデータ領域
 グラフィックでは、最低限「0」〜「9」および空白が必要となる。いつも通りセミグラフィックの6x6ドットで表現すると1キャラクタあたり6バイト(9色フルに使う場合は12バイトだが)で合わせて66バイト。

 実際の画面表示をイメージすると、さらに色のバリエーションが必要だが、データ量を抑えるために表示色はプログラム中で処理してデータの使いまわしを行う事にする。
これと似た事は「マーキー」でも行っているのでなんとかなるだろう。

表示画面と一手戻し用データ
 今回は画面の大きさが8x8だから、64バイト...ではない。画面の端となる「壁データ」が別途必要となる。 これが無いと、判定時に右端と次の行の左端が繋がったり画面を飛び出してしまう場合がある。
ここは、HSP版に習って以下のように壁データも含めたデータ配置にする。
壁8バイト 
画面データ(8x8)
8


壁8バイト
 という訳で、一画面分のデータは89バイトだ。
 あとは一手戻し機能を使用するときに面データを丸ごと保存する領域が必要となる。8x8の画面で、1回の操作で最低3つ減るので、64÷3の小数点以下切り捨てで21画面分必要となる。という事は...
89+21×89=1,958 バイト必要となる。

その他ワーク領域
 今回で言うと、手詰まり判定等で使用するが、それ以外でもマシン語プログラム上で一時的なデータ格納が必要となったときに使う。まあ、100バイトもあれば十分だろう。


 以上の情報を元に、256バイト区切りでメモリアドレスを割り当てる。
項目アドレス(16進表記)
プログラムE800H - EBFFH
表示画面と一手戻し用データEC00H - F3FFH
判定処理用領域F400H - F4FFH
その他ワーク領域F500H - F5FFH

 まあこんな所だろう。BASICプログラムの領域が足りなくなれば、また調整しよう。

2006/10/14:開発環境の変更
 4ヶ月ほど前から、マシン語の作成にWindows用のZ80アセンブラを使用していたのだが、どうも画面表示が多いのと、必要以上に仮想メモリを消費する(なぜか350MB以上取る。ディスクの空き容量は1GBないのに...)のが不満で、思いきって開発環境を切り換える。

 極力シンプルに扱い易くしたかったので、秀丸エディタ+DOS版ZASM の構成に変更した。
アセンブルの操作は、Bernieさんのサイトの情報を元にバッチファイルを作成し、さらに拡張子「.ASM」の右クリックメニューでアセンブルのバッチファイルを実行するように登録した。

 とりあえずこの環境でやってみようと思う。

2006/10/15:まずは表示
 開発環境が整ってやる気が出たところで、まずは表示処理のマシン語を作成する。途中まで比較して特に問題がなさそうだったので、一気に実行...すると、

 ここで、前回に決めたメモリマップを元にしようと思ったら、なんか色々足りない...。という事で、少しメモリマップを変更する。
項目アドレス(16進表記)
面データ(64バイトx16面分)E400H - E7FFH
グラフィックデータE800H - E85FH
プログラムE860H - EBFFH
表示画面と一手戻し用データEC00H - F3FFH
判定処理用領域F400H - F4FFH
その他ワーク領域F500H - F5FFH

 BASIC領域がかなり圧迫されてきた部分が気にはなるものの、このまま突き進む事にする。

 表示ルーチンを作る前に決めないとダメな事がある。データフォーマットだ。
  1. 数字(0〜9), 空白,壁のデータ分けが必要
  2. 色データも欲しい
  3. 手詰まりキャラクタか否かの情報も欲しい
  4. 2種類のカーソルの情報も欲しい
 それぞれをデータとして表すと、
  1. 10 + 1 + 1 = 12種類(4ビット)
  2. 8色として、8種類(3ビット)
  3. True/Falseなので2種類(1ビット)
  4. カーソル2種類+カーソルなしで3種類(2ビット)
 ...8ビットに入らない。という事で、カーソルはまた別に表示する事にして、以下のようにビットの役割を割り当てる。
76543210
手詰り
フラグ
色情報(8色) キャラクタ(0〜9, 空白,壁)

 これで、ようやく画面表示を作り始められる。

 表示キャラクタの色は、マシン語上で合成して表示する。4色だと処理が若干楽なのだが、ある目論みもあって8色表示を実装する。

 4色と8色で処理的に何が変わるかというと、4色だとキャラクタ領域のみに描画すればよいものが、8色表示だとキャラクタ領域+色情報の一部(1ビット分)をアトリビュート領域に描画する必要があるので、アトリビュート領域に書きこむ部分の処理がまるまる増える事となる。

 ようやく表示(の一部)が出来あがった。この調子で行くと、今年中でも完成するのか怪しいなぁ。

画面


2006/10/19:手詰まるか?その1
 いきなり本題と関係のない話だが、秀丸の新しいバージョンでは折りたたみ表示が出来るとの事でアップデートしてみた。うん、縦長になりがちなアセンブラソースだと便利かも知れない。

 さて手詰まり判定だが、まだ若干変わるかも知れないが、こんな感じで進めて行く事にする。
まずワークとして、以下の3つの領域を用意する。

(1)1行分のデータ格納領域 (0F400H - 0F408H)
 縦列または横列を大きな単位として処理するため、8マス分のデータを格納する。ここに入れる時点で、データの値を空白:20H, 0〜9:21H〜2AH (分類用領域の下1バイトに対応)に変えておく。

(2)手詰まりフラグ格納用領域 (0F410H - 0F417H)
 1行分のデータに対応したフラグ。1行分のデータ格納時に、「数字のマスに対応した位置」に手詰まり候補として80H(これが、10/15に書いたビットの役割中の手詰まりフラグと対応)を入れる。判定で、取れる組合せになった場合、対応する手詰まりフラグ

(3)分類用領域 (0F420H - 0F42AH(0F42FHまで予約))
 データ(空白, 0〜9)別に分類するための領域。分類された位置には1を入れる。

 1行分判定の大まかな流れとしては、(1)の6番目から3つ分,5番目から3つ分,5番目から4つ分,4番目から3つ分,4番目から4つ分,... ,1番目から7つ分,1番目から8つ分 と順番に行う。

 こういった順番にする事で、3つ分の判定の時点で空白データが入っていたら、4つ分以降でも空白データが入るのは明白なので、この分の判定処理を端折ることができる。

 細かい処理内容は、一旦途中まで書いたけどどうにも分かり辛いので省略する。この1行処理を8行8列で行えば完成という筋道だ。

 さて、これで問題なく動くだろうか?そして肝心の処理速度は許容範囲に入るのか?早く確かめたいけど何となく怖い部分もある。

2006/10/22:手詰まるか?その2
 10/19の処理をもとにマシン語を作成し、問題なく動くかテストを行う。

 まずは、1行分の処理部分のみ実行。1ステップずつ机上シミュレートの結果と比べる...あ、分類用領域のクリアを忘れてた。という事でちょっと修正する。他にも細かいミスがいくつかあったが、一応うまく動くようになったので、今度は8行8列の処理と組合せる。

 すると、止まりはしないものの結果がおかしい。不良部分の範囲を絞るため、横8行分だけ行ってみる...こちらは特に問題がないようだ。多分、縦列の処理ではデータの書きこみ場所が間違っているのだろう。まあ、不安だった1行分判定がうまくいったので、続きはまた後日にしよう。

 ちなみに、一番不安だった処理速度は意外と問題なさげだった。今は処理速度優先でソースコードを多めに書いているのだが、処理が安定したらもう少し短くしようと思う。

画面


2006/10/28:手詰まった(良い意味で)
 10/22の現象の原因がわかった。

 どうやら、横行の判定処理で「取れる」と判断したコマが縦列で取れない時に「手詰まり」に戻っていたのが原因らしい。という訳で、さっくり直す。

 これで上手く動くようになったな...と思い いくつかランダムパターンで様子を見ると、たまに手詰まりでないのに手詰まり表示になる場合があった。

画面

 左上から下方向に向けて「201」と並んでいる部分は取れるはずなのに手詰まり表示になっている。ああ、また1ステップ毎に処理を追わないとダメか。
 注意深く処理を追って行くと、参照のみ行うアドレスに値を書きこんでいた部分があった。この辺りまでわかると、あとは原因を絞り込んで行くだけなので、少し気が楽になる。

 結果は、一部のデータ初期化漏れだった。という訳で、これもさっくり修正。これで、ようやく一番の不安部分が完了した。

画面



Making「ストレトリ」 その2