より強いロボットにしてみよう


勝負に勝つためには

ここまで

といったことを解説してきました。 後はこれらを活用して、様々な地図に対応し、 早く目的地にたどり着く強いロボットを作るだけです。

このコンテストは、いかに強いアルゴリズムを考え、 それを具現化するコードが書けたかを競うものなので、 これ以上はあまり解説するのは野暮でしょう。 止めておきます。 とはいえ、まったくのノーヒントだといったいどこから着手すればいいのか分からないかもしれません。 そこでここでは幾つか、こういう戦略を取ると強くなるだろうねというアイデアを書いてみます。

二手先を読む

コード 13.1 (表現が違うだけで 12.1, 12.4, 12.5, 12.6, 11.1, 9.6 と同じアルゴリズム) において、もう一度 a25x70_level07.txt を動かし、下の状態から数ステップの動きを観察してみましょう。

まずここやここ。前の前 (gSurTiles[6]) が障害物だと分かっているのに NaviCmd(1,0) で前進して 真正面 (gSurTiles[0]) に障害物を構えてます。

 

その後、右旋回するが分かり切っているので NaviCmd(1,1) にすれば、 それぞれ 1 ステップ節約できます。 さらにここ。

左前方 (gSurTiles[17]) が開けているので、次のステップで左旋回するのが分かっているのに愚直に前進しています。

こちらは NaviCmd(1,2) にすればここでも 1 ステップ節約できます。

このようにロボットは 2 マス先 (gSurTiles[6〜17]) が読み取れるので、 二手先を読んで行動するようにすれば、より速い、強いロボットになります。

目標位置を推定する

NaviCmd(1,0) で前進したところ、先ほどまで前方にあった目標が後方になったとしましょう。 ゴールは真横にあるはずです。 コード 13.1 では右斜め前に目標があるかも見ているので、 下の図の青いパネルのどこかに目標があるはずです。 右か左かは分かりません。

ところがコード 13.1 では次のような軌跡を描きます (目標が右にあった場合)。 90°横にあると分かっているのに 60°しか曲がらなかったので遠回りすることになりました。

横にあると分かった時点で NaviCmd(1,1), NaviCmd(1,2) を交互に行うモードに以降するとロボットはもっと速く目標にたどり着くはずです。

なんらかの理由で旋回したとしましょう。 その時今まで前にあった目標が後ろに動いたのなら、目的地は下図の青いエリアに限定されます。

大体の方向が分かることで、以降旋回する必要が出てきた時にどっち方向の旋回 が有利に働くか考えることができるでしょう。

マッピングする

どっち方向の旋回が有利かを考えるためには、今どっち方向に向いているかを知る必要があります。 と言ってもロボットには東西南北といった絶対的な方角を知る術は無いので、 あくまで初期姿勢に対しての相対的な方角しかわかりません。 しかしそれで十分です。

具体的な相対的な方角は初期値を 0 とした変数に対し、 右旋回すれば+1、左旋回すれば−1 といった処理をすれば得られます。 同様に、どの方向にどれだけ進んだかを蓄積すると、今スタート位置からどれだけ動いているかが分かるでしょう。 地点 A では目的地がこの方向にあると分かった、地点 B ではこの方向にあると分かった、という情報が得られたら、三角測量の原理で目的地の位置がピンポイントで分かります。 最短距離でそこを目指すという作戦もあるでしょう。

またロボットは 18 近傍がどうなっているのかを知ることができます。 巨大な配列を作り 「障害物が無い所」「障害物がある所」「自分のスタート地点」 「未知の所」といった情報を更新すると 独自の地図を作ることができます。

これにより障害物を効率よく避けたり、速く帰ってくることができるでしょう。

相手を錯乱する

対戦相手の中には自分の足跡を辿って帰る戦略を取るロボットがあるかもしれません。 足跡は、後から通った情報で上書きされます。 さらに対戦相手の足跡は「通った」という情報だけで、何ターン目に通ったかはわかりません。 すなわち相手の足跡を見つけたら、積極的にその上を通る、さらに幾つもの枝路を作るようにすると、相手は足跡を辿って帰る戦略が使えなくなるかもしれません。

対戦相手の足跡は何ターン目に通ったかという情報は得られません。 そのため相手の足跡を見つけてもどちらから、どちらの方向に去っていったのかわかりません。 しかし二択ですから、その他の情報から高い確率で類推されるかもしれません。 しかも自分は自分のスタート位置から出発しています。 すなわち自分の足跡を辿られると最短距離で自分のスタート位置を見つけらてしまうかもしれません。

これはスタートした直後、あちこちに意味の無い分岐をすることで相手を陥れることができるかもしれません。 ただし運や相手の賢さにも関係することなので、必ずしも上手くいくとは限りません。

加速命令 Boost() を使う

通常ロボットは 1 ターン毎に 1 回 Loop() 関数が呼ばれます。 そのため互いのロボットは交互に Loop() 関数が呼ばれ、 1 マス移動します。 しかし加速命令 boost() を使うと 1 ターンで 2 回 Loop() が呼ばれるようになります。 すなわち 1 ターンで 2 マス移動できるのです。

もちろん Boost() は無尽蔵に使えません。 1 試合で使える回数は 10 回までと制限があります。 その 10 回を何時使うかというのも勝敗のカギです。 最初に全部使ってロケットスタートしてもいいでしょう。 しかし温存しておいて、ここぞという時に使う手もあります。 相手が 5 マス以内に通ったパネルは通れないというルールがあります。 相手を捕捉したら、Boost() を使って先回りして進行を邪魔するという戦略もあります。 上手く作ると相手にとってイヤらしいロボットを作ることができるでしょう。


[戻る]