ミニパットやってみた

submission
movie: nicovideo | youtube

4-2はHIO無理でした\(^o^)/

エンコードについて

今回はL-SMASHでmuxしましたが、FPSを手で指定する必要があったり、ストリーミング向けの場合 --optimize-pd を付けた方がいいという話があったり少々ややこしいです(参考: L-SMASHの簡易(?)FAQ)。MP4Boxで問題ないならその方がいいかも?

今回は --optimize-pd を付け忘れてますが、とりあえずニコニコで普通に再生する分には問題なさそうです(ニコニコの場合サーバ側で何らかの処理をしてくれる、らしい)。ただしZenzaWatchだと正しく再生されないようです。

FC『内藤九段将棋秘伝』の思考ログをとってみた


この局面のCOM玉の詰み判定がおかしい件について調べ中です(再現用ムービー棋譜を置いておきます)。

まだ思考ルーチンの評価ロジックまでは完全にはわかってませんが、コード自体は大体読めたのでLuaスクリプトでこの局面の思考ログをとってみました。

ログによると最善手は以下の順に更新されているようです:

  • 91歩打
  • 71桂打
  • 52金
  • 66桂打
  • 98歩打
  • 48歩打

一度は詰みを逃れる52金を採用したものの、後から66桂打などで上書きされてしまい、最善手を指した局面でも王手を逃れていないため詰みと判定されてしまっているようです。評価ロジックがまだ理解できてないので原因は調査中ですが、大駒が当たりになっていたりして大きな駒損がありうる局面になるとこの現象が発生するようになるのかなと推測しています。どうもこのゲームは駒の価値を点数化する際に玉がそれほど特別扱いされてない感じなので…。

FC『内藤九段将棋秘伝』解析中

思考ルーチンを少しずつ読んでます。以下の要素はだいたい読めた感じです:

  • 局面の特徴量計算
  • 候補手生成(1手読み)
  • PLAYER玉詰み判定

後は評価部だけと思われますが、結構いろいろな要素を評価してるのでもう少しかかりそうです。

以前COM玉の詰み判定がおかしいという記事を書きましたが、なんとなく原因がわかったかもしれません。このゲームはCOM玉に関しては専用の詰み判定ルーチンが存在せず、全候補手を試した上でどうしても玉が取られるなら詰みと判定するようになっているようですが、王手対応に関して全ての手を網羅できていないように思われます。

ルート局面で王手をかけられている場合、なるべく安い駒で合駒するという処理が入っているようですが、指し手データが駒を打つ手とそうでない手どちらも表現できる構造になっているため、駒を打たない手が既に(その時点での)最善手として選ばれていると合駒する手が全部捨てられてしまい、その他の候補手も一部捨てられてしまうものと思われます(まだ全部読んでないので間違ってるかもしれませんが)。

追記: 安い駒で合駒する処理は持駒を打つ手の場合のみ実行されるようなので、上の記述は勘違いだったみたいです。ただ王手対応が完璧かというとやはり怪しい感じはします。

FC『スターソルジャー』のちょっと気になるコード

以前アップされた8面までのスコアアタックTASを引き継ごうかと思って色々調べ中です。今のところコードを読んでるだけですが、気になった点について少しメモ。

CHRバンク切り替え

; マッパー3 CHRバンク切り替え
9F88 : BD 44 D0		lda	$D044,x
9F8B : 9D 44 D0		sta	$D044,x

バンク切り替えを行うだけならレジスタに即値を書き込めばいいはずなのに何故こんな冗長なコードなのかと疑問に思いましたが、ちゃんと理由があるようです。NesDevWikiによるとマッパー3にはbus conflictがあり、レジスタに値を書き込む際はROMの同一アドレスと同じ値を書き込まないと挙動がおかしくなることがあるので上記のようなコードになっていると思われます。

衝突判定

;;; 弾とオブジェクトの衝突判定(弾hitbox:(6,6), オブジェクトhitbox:(12,12))
; Read
;   $00	U8	弾座標x
;   $01	U8	弾座標y
;   $02	U8	オブジェクト座標x
;   $03	U8	オブジェクト座標y
; Write
;   C	bit	0:hit, 1:not-hit
CollideBulletObj:
; # x/yいずれについても、減算結果が -12 以上 6 未満の範囲で C == 0 となる
; A = $02 - $00 + 12
; C = A >= 18
; if(C) return
; A = $03 - $01 + 12
; C = A >= 18
B050 : A5 02		lda	$02
B052 : 38		sec
B053 : E5 00		sbc	$00
B055 : 18		clc
B056 : 69 0C		adc	#$0C
B058 : C9 12		cmp	#$12
B05A : B0 0A		bcs	$B066
B05C : A5 03		lda	$03
B05E : 38		sec
B05F : E5 01		sbc	$01
B061 : 18		clc
B062 : 69 0C		adc	#$0C
B064 : C9 12		cmp	#$12
B066 : 60		rts

かなりシンプルなコードで、一見しただけでは何故これでうまくいくのかわからなかったので少しコメントしてみます。
簡単のためx方向についてのみ考えます(y方向も全く同じ考え方)。まず以下のように変数を設定します:

  • x1: 弾座標(左端)
  • w1: 弾の当たり判定幅
  • x2: オブジェクト座標
  • w2: オブジェクトの当たり判定幅

すると、この衝突判定は2区間 (x1,x1+w1), (x2,x2+w2) が重なっているかどうかの判定に帰着します。この2区間が重ならない条件は

x2 >= x1+w1 or x1 >= x2+w2 # 境界条件はとりあえず適当

なので、2区間が重なる条件はその否定

x2 < x1+w1 and x1 < x2+w2

となり、変形すると

-w2 < x2-x1 < w1

となります。ここで w1=6, w2=12 とすれば、これはまさに上記のコードのコメントに記した条件になっています。実際は半開区間での判定となるため、左から当たったときと右から当たったときの境界条件が異なるという些細な問題はありますが、それにしてもうまいコードだなぁと思いました。なお、オブジェクト同士の衝突判定($B067)もhitboxが異なるだけで同様のコードになっています。

以上を踏まえて当たり判定表示スクリプトを書いてみました。こんな感じ:

ミニパットのTASが来てる

http://tasvideos.org/5083S.html

これ1-5と1-9でHIOが取れなくて投げたんですよね…。やっぱりこのムービーでもできてないようです。
1-5は頑張ればギリギリ近くまでは行けるんですが無理でした。1-9は以前手でプレイしたとき壁と遮断機の間に打ち込むことで壁抜けができた記憶がありますが、ムービーとして再現はできてません。仮にできたとしてもHIOになるかどうかは微妙ですが。

確か当時はLuaでの総当たりまではやらなかった(部分的に絞った探索のみ行った)ので、総当たりすればHIOパターンが見つかるかもしれませんね。1-9のように時間が絡む面は相当時間がかかりそうですが…。

TRADITIONALコースしかやってないみたいなので、できれば全コースやってほしいですね(丸投げ)。

FC 平成天才バカボン 4面ボス解析

$0396 現在の数字(0-origin)
$039C 正解数

24回正解でクリアとなります。数字床は速度 0.938 以下でないと反応しないようです。

$A8A2 が数字($0396)決定処理です。前回と同じになった場合、+1して8で割った余りとなります。

乱数調整は床を踏むフレームをずらすだけです。