第26回コンピュータフェスティバル競技部門に参加しました

宇部高専で開催された第26回コンピュータフェスティバルの競技部門に参加し,なんと優勝を勝ち取ることができたので,嬉しさが残ってるうちに記事をしたためておこうと思います.

参加記事は誰かが部のブログに書いてくれると思うので,主に技術的なことを残しておきます.

基本的な気持ち

最良優先探索(priority_queue を使った探索)で5ターン分先読みし,各状態について評価し,もっとも評価値の高かったものを採用するようにしました.

探索結果は保持せず,ターンが進むごとに一から探索しています.

評価関数

以下の5つを評価用のメトリクスとして採用しました.

  1. タイル点による利得
  2. 自チームで領域を形成することによる利得
  3. 相手チームの領域を破壊することによる利得
  4. 自チーム両エージェント間の距離
  5. 移動先での自由度

1. 2. 3. は特に説明しなくても大丈夫だと思います.付け加えるとすれば,領域点よりタイル点の方に多少加重しました.これは理論的な根拠があるわけではなく,テストプレイを積み重ねての実感に依拠しています.領域点を重視すると,いきおい「大風呂敷」を広げがちになり,安定した得点を得られなくなります.

4. についてですが,エージェントがくっついてもいいことはない(とりうる行動が制限される,相手が遠くで策動しているのを防げない,などの弱点ばかりが目立つ)ため導入しました.5. は,自チームのタイルがあらかた置いてあったり,隅っこだったりするところにあまり行かないようにするため設定しました.
これらのメトリクスは,マップのタイル得点の状況に依存しない数値なので,重みを固定した場合,全体として高得点なマップにおいては 1. 2. 3. との不均等が生じてしまいます.そこで,マップのタイル得点の平均値を計算し,それに応じて 4. 5. の重みを動かすようにしました.

また,体感として,タイルによって得点の上下が激しいマップほど領域点が大事になる気がしたので,タイル得点の標準偏差を求め,それがしきい値を超えた場合に 1. の重みを増やすようにしています.

対戦前の時点で,ぼくとソルバで対戦した場合は9割方ソルバが勝つ,くらいの強さまで持っていけていたはず……です.

対戦の結果

1戦目が一番大変でした.与えられたマップが線対称性を前提しておらず,読み込みの時点でエージェント座標をバグらせてしまいました.また,この混乱により,最初の2ターンはロスしました.最終ターンでなんとか逆転して僅差の勝利です.

以降は,上記の不具合も修正し,ソルバも順調に動いたので,基本的にうまく戦えたと思います.たまに,人間からすれば不合理に思える手(-99点のタイルを占領しにいく,序盤10ターンの間ひたすら前進するなど)もありましたが,ソルバを信頼するように努めていました(こう書くと美しいですが,実際には人力モードへの切り替えを導入していなかっただけです).また,コリジョンが連発することもあり,特に決勝では10ターンくらい睨み合っていましたが,この辺も柔軟に対応できるようシステムを作っていなかったので,我を通しつづけた感じです.

所感

この辺の考察を昨年9月の段階でやっておきたかったですね.

基本的なアルゴリズム自体はプロコン本選のものと一緒なんですが,当時は実装力が弱かった(今が強いというわけでもありませんが)ので,かなりひどいコードでした.冬休みの期間にその方面のコードを読み込み,いい感じのプラクティスを吸収できたのが活きてきたんだと思います.