大変謎の多いコンテストでありました。
概要
AIBot は、HackerRankというサイト内で 4/5(日)13:00~4/6(月)1:00 の12時間の間開催されていたAIコンテストです。
7時間のコンテストの企画しといてあれだけど、短い…!
課題のゲーム
"Maze Escape" というゲームで、ルール自体は極めて簡単でした。
2人のプレイヤーが迷路上にランダムに配置され、交互に1マスずつ移動して先に出口に辿り着いた方の勝ち。
ただし、プレイヤーの視界は自身の周囲8マスに限られます(自分のいるマスを入れると9マス)。
また、プレイ中は互いに相手の姿・居場所を確認することができません。
本質的には1人プレイな気がしなくもない。
この単純なゲームを厄介にさせた要因の1つが「プレイヤーの向き」という要素。
プレイヤーは初期配置時に上下左右のいずれかの向きにランダムに設定されます。
各プレイヤーは自分がどの向きを向いているのか認識できません。
そして、毎ターン自分の周囲9マスの情報が入力されるのですが、この情報はプレイヤーの向きに対応した順で与えられます。
上図のように、プレイヤーの向きが上向きになるよう周囲の情報が入力されます。
各ターン、プレイヤーは上下左右に1マス移動しますが、この移動後プレイヤーは移動した方向に向き直り、次のターンの入力はこの向きに準拠します。
ゲームの本質は迷路の探索の仕方だと思いますし、コンテストの時間も短かったので、こんなあまり意味のない処理に時間をかけさせられたくなかった。
To make this game more interesting とのことですが…。
AIの仕様
驚くべきことに、このコンテストではターン毎にプログラムが呼び出され、AIは1ターン分の入出力を行った後処理を終了します。
この仕様により次のような問題が起こります。
- AI内でこれまでのターンの情報を保持できない。
- (C,C++において) time()をシードとして初期化した乱数が、乱数として機能しない。
1.については、ファイル入出力を用いてうまいことやってくれとのこと。面倒。
2.の問題は、AIプログラムが割と高速に呼び出されることにより起こります。
現在時刻を返す time(NULL) の返り値が毎回同じ値となってしまい、乱数のシードとして用いると毎ターン同じ乱数を引くことになるんですね。
これも、ファイル入出力で解決できそうです。でも面倒。
また、このコンテストでは(開催期間が12時間しかないにもかかわらず)2時間に1回しか提出できないという条件がありました。
そのため僕はバグに対してシビアになっており、不慣れなファイル入出力を使う勇気が湧かず、そのターンの入力にのみ依存して行動を決定することに。
乱数については行動を出力する前に0.9秒程ディレイをかけることで無理やり解決しました。
作ったAI
壁が見つかるまで直進し、見つかった後は左手を壁に沿わせ移動するというシンプルな作戦をベースにしました。
ただ、このままでは孤立した壁にぶつかったときその周りを回り続けてしまうので、左折する際は1/3の確率で直進、無理なら右折するように。
結果と闇
コンテスト終了から1日半が経過しましたが、一向に結果が出る気配がない…。
そもそもこのコンテスト、参加者が11人しかいませんでした。
しかもこの題材も2013年に同サイト内で既に公開されていたものの流用っていう。謎が深い。
こっちの方はいつでも提出できる形で、370人程提出済みのようです。
試しにこちらに提出してみたところ、55勝44敗5分の110位でした。
しかし、この対戦のログ見てみても、テストケースのマップ(上図のやつ)1つのみで対戦が行われているようにしか見えないな、と思ってたら、
(この問題のDiscussionsにて)
問題作成者「新しいマップを追加できます。」
参加者「追加 "できる" ?」
どうやらお察しの通りだったようで。多分初期配置も固定です。
現状では、テストケースのマップ・初期配置に特化したAIが高得点を叩き出せるみたいですね。何なんだ一体…。