OpenAI GymのPong-ram用資料

OpenAI GymのPong-ram環境用のメモ。

とりあえずメモリアドレスを軽く調べました(趣旨的には解析とか一切なしで解くことが求められているのでしょうけど)。なお、Atari2600は $80-$FF の128 バイトがRAMとなっています(参考: Atari 2600 Specifications)。

address type description
$88 U8 フレームカウンタ
$8D U8 COMスコア
$8E U8 PLAYERスコア
$95 U8 COM座標y
$B1 U8 ボール座標x
$B6 U8 ボール座標y
$B8 S8 ボール速度y?
$BA S8 -1 * ボール速度x
$BC U8 PLAYER座標y

ボールのy方向の動きについては完全には理解していません($B8 に疑問符がついてるのはそのため)。もしかしたらサブピクセルまで計算されていたり、場合により $B8 が2回加えられるかもしれません。ボールの動き計算コード自体は $F554 にあります。

自機の動きには多少の慣性がかかりますが、これをメモリ内容だけで把握する方法はよくわかっていません。多分 $84 を目的座標として前回述べたような処理が行われるのだと思いますが、$84 は1Fおきに全く関係ない値に変わるため、その他のアドレスも参照しないと自機の慣性は正しく把握できないと思います。

とりあえず自機座標とボール座標/速度がわかれば最低限足りるとは思いますが、慣性も考慮しないと得点率が悪くなるかもしれません。手でプレイするとわかりますが適切な角度で打ち返さないとCOMは失点してくれないので、結構繊細な操作が要求されるんですよね…。

ただ、Pong-ram環境では1ステップごとに2-4フレーム進むようなので、そこまで繊細なことを考えても仕方ないのかもしれません。この辺はやってみないとわからない感じですね。

環境に関する情報をまとめておきます:

attribute value
env.action_space Discrete(6)
env.observation_space Box(128,)
env.reward_range (-inf,inf)
env.spec.timestep_limit 10000

actionの意味は以下の通りと思われます(2と4, 3と5の移動量は多分同じだと思いますが確証はありません):

意味
0,1 何もしない
2,4 上へ移動
3,5 下へ移動

observationは128バイトのRAMをそのまま格納した配列です。なお、配列の要素は numpy.uint8 で、Pythonの int と振る舞いが異なるので注意が必要です。

1点取ったとき 1.0, 1点取られたとき -1.0 の報酬が得られるようです。

ターン制限(10000)があるので、単に失点しないだけでなく得点率が求められると思われます。1ステップあたり2-4フレーム進むので、最悪の場合20000フレームで打ち切られます。なお、全く操作せずパーフェクト負けした場合は大体1000ステップ程度かかるようです。

メモリを見つつ1ステップずつ動かせるスクリプトを書いたので一応貼っておきます。