敵キャラクタについて(3):敵キャラクタ毎の処理 その1(サート)
今回からは、敵キャラクタ毎の処理について調査してみたいと思います。
最初に調査する敵キャラクタは・・・やっぱりアイツしかいませんね!


敵キャラクタ『サート』について
サートは、ゲーム開始時、画面の左右どちらかの上方から出現する敵キャラクタです。
サートには他の敵キャラとは異なる大きな特徴があります。それは、ある条件の下でサートを破壊すると、1UPキャラクタの『ランダー』に変化するという点です。

しかし、サートがランダーに変化する条件については、ZANAC発売後20年あまりが経った現在でも、よく判っていませんでした。
(新しいウィンドウで「ZANAC サート ランダー」をgoogle検索)

これまでに判明しているランダー出現条件は、『ゲーム開始直後、通常弾を一発も撃たずにサートを特殊兵器で攻撃する。』というものです。
しかし、ゲーム中でも、サートを破壊するとまれにランダーが出現することもあります。

ランダー出現条件は完全にランダムなのか?それとも何らかの条件、法則に基づいているのか?
それはサートの処理を解析することで判明すると思われます。


サートの処理のアドレスを調べる
前回のレポートでは、各敵キャラ毎の処理のアドレステーブルは070B9Hにあり、敵キャラクタ毎の処理が開始される際、

 070B7H+(敵ワーク先頭の内容を2倍した値&0FFH)・・・(*)

で分岐が行われることを紹介しました。
前回は緑色の敵(ワーク先頭が02CH/0ACHの敵キャラクタ)の処理ルーチンについて少し触れましたが、今回はサートの処理について調査を行ってみたいと思います。

まずは「敵キャラクタのワークエリアを見る」で紹介した手法で、サートの敵キャラクタ種別コードを調べます。
改造ZANACでゲームを開始し、サートが出現した瞬間にゲームを止め(F6キー)、敵キャラクタワークの内容を確認します。

画面上の敵キャラクタがサートのみ表示されている状態では、2つの敵ワークが利用されているはずです。それぞれの1バイト目に注目しましょう。
このうち、"27"のほうは無視しておくと、残る片方は"BD"となっており、これがサートの敵種別コードとなります。

種別コード0BDHの敵キャラクタの処理アドレスは、(*)式より、

 070B7H+( (0BDH×2)&0FFH )=07131H

に格納されていることとなります。
ZANACのROMアドレスの07131Hからの2バイトには"02 83"が格納されています。
すなわち、ROMアドレス08302Hからがサートの処理ということになります。


サートの処理(初期化)
08302H近辺のZANACのソースを解析してゆきます。

まず、ルーチン先頭では、「敵種別コードの最上位ビットが0かどうか」で分岐が行われています。
これは前回紹介した通り、種別コードの最上位ビットは、その敵キャラに合わせて初期化を行ったか?(=1)、もしくは行っていないか?(=0)を示しているためです。

まずは、初期化を行っていない際に実行されるコードを解析してみます(08308H〜)。
サート初期化ルーチンでは、大雑把に分けて以下のような処理が行われています。

  1. サート出現時のX座標の決定。
    自機のX座標を元に、「自機が画面の左寄りに居たら右に出現、画面の右寄りに居たら左に出現」という計算を行っています。
    なお、キャラクタの座標は、Y座標が(ワーク先頭+1)、X座標が(ワーク先頭+2)に格納されています。

  2. 種別コード"27"のワークの初期化??
    敵ワークの空きを検索し、空いているワークを種別"27"で初期化しているようです。ただし、このルーチンはまだ完全には解析できていません。

    余談ですが、敵種別"27"は、幅が16ドットの敵キャラクタと組になって使用されるのではなく、スプライト2枚重ねで表示される敵キャラクタと組になって使用されるのかもしれません。
    これを判断するには、スプライト表示部分まで解析を進める必要がありそうです。今回はそこまで進みません。

  3. (0E149H)および(ワーク先頭+29)の設定。
    RAMアドレス0E149Hの値を1増加させ、07HとANDを取った後、(ワーク先頭+29)にその値をコピーしています。

    07HとANDを取ることから、この値は00H〜07Hの8通りとなります。 後ほど説明しますが、サート破壊時の特殊兵器出現と関わっているようです。

  4. (ワーク先頭+4)の設定。
    iiiで使用した値を元に、08EAFHからのテーブルから値を計算し、格納しています((08EAFH + iiiの値)で表現されるROMアドレスの値)。
    ただし、計算後の値が081Hのときのみ、08FHに補正されます。

  5. (ワーク先頭+30)の設定。
    定数020Hが代入されています。これも後述しますが、停止時間のカウンタに使われるようです。

  6. その他のワークの設定。
    (ワーク先頭+9)=02H, (ワーク先頭+12)=01H, (ワーク先頭+3)=0F8Hと、それぞれ定数を格納しています。
    これらの値が何に使われているかは、今のところ不明です(当たり判定の大きさやXY方向の速度か?)。

    また、初期化完了後、ワーク先頭の値の最上位ビットを1にします。


まだ敵キャラクタ表示の部分まで解析が進んでいないため、推測混じりの部分もありますが、キャラクタ表示に必要な各種の情報が、ここで設定されています。

ただし、まだランダー発生の手がかりは無いようです。


サートの処理(初期化済み、平常時の処理)
続いて、サートが初期化された状態で実行されるルーチンを見てみます(0834AH〜)。
なお、このルーチンは初期化ルーチンの直後にあります。先ほどの初期化ルーチンを実行後も、自動的に実行されます。

ルーチン先頭では、まず「現在のサートのY座標が060Hであるか否か?」で分岐が発生しています。

Y座標が060Hである場合、(ワーク先頭+30)を1減らし、減らした後の値が0になっているかどうかで再度分岐しています。
これは、サートの出現後の動作である、「画面上方から降りてきて、しばらく留まった後、また上に戻ってゆく」という動作のうち、 一時停止を担っている処理のようです。
(ワーク先頭+30)はサート初期化時に、020Hが代入されています。そのため、このルーチンは1フレームごとに呼び出されるとすると、020H=32フレームの間、 サートは一時停止していることとなります。

また、サートの状態により、(ワーク先頭+9)および(ワーク先頭+12)も書き換えられています。

 サート出現時(=初期化時): (ワーク先頭+9)=02H, (ワーク先頭+12)=01H

 サート一時停止時: (ワーク先頭+9)=そのまま, (ワーク先頭+12)=00H

 サート上昇時: (ワーク先頭+9)=0FCH(=-4), (ワーク先頭+12)=01H

これらのことから、(ワーク先頭+9)はY方向の移動量を、(ワーク先頭+12)は「そのキャラクタで座標移動が起こっているか?」を示している、と考えられないでしょうか。


ルーチンではその後、いくつかのサブルーチンを呼び出しています。
これらのサブルーチンも、実はまだ完全に解析はしていません。しかし、恐らく、

・このキャラクタの座標移動
・このキャラクタ VS 自機や自弾との当たり判定

を行っているものと思います。


さて、これらのサブルーチンから戻ってきた後、サートのルーチンでは、
『自分の敵種別を調べ、032Hでなければサートのルーチンを終了し、戻る』という処理が行われていました。

そもそもこのルーチンは敵種別が0BDHのキャラクタ用のルーチンだったはずで、これまで解析した初期化/初期化済みルーチンの中でも、 敵種別が変わる処理は行われていませんでした。

実は敵種別を変えるルーチンは、先ほど出てきた「自機や自弾との当たり判定」のルーチンで行われているようです。
当たり判定ルーチンでは、この敵キャラクタが破壊された場合、敵種別を032Hに変化させています。

敵種別032Hとはどんな敵なのか・・・改造ZANACで遊んだ方は判ると思いますが、敵爆発のアニメーションがまさに032Hなのです。
つまり、『自分の敵種別を調べ、032Hだったときの処理』は、サート破壊時の処理ということになります。

やっとランダーの手がかりが掴めそうです。


サートの破壊時の処理と、ランダー出現条件
サートが破壊された際、まずは「ALC値の最上位2ケタから1を引く」というサブルーチンをコールしています。
ランダー出現とはあまり関係無いですが、これはゲーム全体の難易度を下げる効果があります。

サブルーチンから戻ってきた後、いよいよサート出現判定が行われています。
「RAMアドレス0E140Hの内容を03FHとANDした値」と、「RAMアドレス0E103Hの内容を03FHとANDした値」とが等しいかどうか比較を行い、分岐しています。

それぞれのアドレスには何が格納されているかを調べたところ、RAMアドレス0E140Hの内容は「ゲームスタート後、自機通常弾を発射した数」、0E103Hの内容は「SCORE値 百,十の位(BCD表記)」となっていました。
また、それぞれの値を&03FHしていますが、これは「64で割った余りの数」と読みかえられます。

これらの2つの値が等しいときには、敵キャラクタ種別を03EH、つまりランダーに変化させる処理が書かれています。
ついにランダーの出現条件が判明しました。


 【MSX版ZANACにおける、ランダーの出現条件】

 サートを破壊した際、

  「ゲームスタート後から通常弾を発射した数」 = 「SCORE値の百,十の位」

 のとき、ランダーが出現する。
 ただし、それぞれの値が64以上だった場合、64で割った余りについて判定する。


ランダー出現についての通説である『ゲーム開始直後、通常弾を一発も撃たずにサートを特殊兵器で攻撃する。』は、

 通常弾を発射した数・・・ゲーム開始時に0クリアされ、その後一発も撃っていなければ、0
 SCORE値・・・ゲーム開始直後、他の敵を破壊しなければ0

なので、この条件を満たしています。

なお、残念ながらこの条件を満たせない場合、サートが特殊兵器アイテムになるかどうかの判定が行われています。

RAMアドレス0E148Hの値が5以上のとき、サートは特殊兵器アイテムに変化します。
0E148Hの値は、自機がパワーチップ(アイテムBOXを破壊するとたまに出てくる、通常弾をパワーアップするアイテム)を取得した数が格納されていました。
つまり、「パワーチップ保有数が5以上のとき、サートは特殊兵器アイテムに変化する」ということになります。

この条件を満たした場合、敵種別コードを053H(全特殊兵器アイテムで共通)に変えるとともに、(ワーク先頭+28)に(ワーク先頭+29)の値をコピーしています。
おそらく、特殊兵器アイテムの初期化ルーチンでは、(ワーク先頭+28)を元に、「自分が何番の特殊兵器アイテムか?」の処理が行われているのでしょう。


ランダーを出しまくれ!(無理)
20年来の謎も解けたことですし、これで「割り箸も割り放題、ランダーも出し放題」ということですね!
・・・ところが、そう簡単にはいきません。

ゲームの冒頭以外、この条件を狙ってランダーを倒すのは相当難しいです。
どのくらい難しいかを体験してもらえるように、またZANAC用パッチを用意しました。

  zanac-disp_0E140_0E103.exe (zanac-disp_0E140_0E103.lzh : ファイルサイズ 11,066バイト)

LZH形式で圧縮された、Windowsの実行ファイルです。プログラムはWdiffで作成しました。
展開後、生成されたzanac-disp_0E140_0E103.exeをzanac.romと同一のフォルダに移動し、実行してください。

ゲームを開始すると、画面右上に2行の数字が表示されますが、

 一行目の先頭1バイト・・・ゲームスタート後から通常弾を発射した数(RAMアドレス0E140H)
 二行目の先頭1バイト・・・SCORE値の百,十の位(RAMアドレス0E103H)

を示しています。つまり、これら2行の先頭が一致した時、サートを破壊すれば良いことになります。


この状態で、特に意識せずにゲームを遊んでみると、ランダー出現条件を満たす機会はかなり少ないことが判ります。ゲームをクリアするまでに1回ないし2回ある、といったところでしょう。 条件を狙ってサートを破壊するのも結構難しいです。
これは、ZANACの敵キャラクタを倒した際に得られる点が数十点〜数百点の間にあるため、SCORE値が頻繁に変わるためです。

ちなみに、ファミコン版のZANACについては、MSX版よりややランダーの出現機会が多いようです。
ここで、MSX版ZANACの解析を始める前、ある方に聞いた「ファミコン版ZANACのランダー出現条件」を紹介しますと、


 【ファミコン版ZANACにおける、ランダーの出現条件(暫定版)】

 サートを破壊した際、

  「ゲームスタート後から通常弾を発射した数」 = 「SCORE値の千の位」

 のとき、ランダーが出現する。
 ※ただし、これ以外にも条件があるかもしれない。ひょっとしたら「SCORE値の万,千の位」かも??


ファミコン版のほうが、ややランダーの条件を狙うのが易しくなっています。
お子様向けのファミコン版ということで配慮があったのか、それとも先に製作されたMSX版の条件が厳しすぎた反省からでしょうか・・・

いずれにせよ、より良いゲームバランスを目指していた、当時の製作者の心意気をうかがい知ることができたような気がします。




上図はAU版のZANAC。ケータイでZANACが遊べるなんて超I・KE・TE・RU〜!(恥)
通常弾と特殊兵器を同時撃ちにせざるを得ないので、ランダー出現条件は全く異なるようです。さっぱりわからん!


サートだけで1回分のネタができました!
やっぱりZANACってすごいゲームだなあ。
(2005/09/28)


ZANAC解析のトップへ戻る

トップへ戻る