2022-09-23に行われた天下一 Game Battle Contest 2022に参加し9位入賞しました。途中サーバー側が不安定になりコンテスト時間が延長されるトラブルがありましたが、ドキュメントやビジュアライザなど丁寧に用意されており非常に楽しいコンテストでした。
コンテストについて
KLab社が毎年開催しているゲームAIのコンテストです。短時間かつ複数人の他の参加者と対戦するのが特徴的です。 今年はプログラムを起動して対戦に参加する部分を提供するRunnerプログラムが提供されていたり、6面体上の移動が実装されたサンプルプログラムやイケイケなビジュアライザが提供されていたりとかなり親切なコンテストでした。
参加しながら考えていたこと
題材となるゲームは6面体上で6人対戦のスプラトゥーン風のゲームで、直近何ゲームかの順位点の合計で順位がつくものです。
6面体上での移動とか短時間で実装したくないぞ!という気持ちになりましたが、提供されているサンプルコードをみると移動どころか、APIと通信をして現状の盤面を構築するStateクラスや、上下左右に移動してみて最も結果が良くなりそうな選択肢からランダム移動する部分まで実装されているではありませんか。 小手先の実装をガチャガチャやっていきたい気持ちが強かったためPythonのサンプルコードをベースに実装していくことにしました。
素敵なチュートリアルが提供されており、WSL2でLinux版の起動に成功、かなり早いタイミングで本番環境に参加することができました。
塗り状態が2種類ある
サンプルコードでは評価関数が「最も多くのマスを自身のエージェントで塗れる移動方向のリストからランダムで方向を決める」となっていますが、このゲームの塗り状態には「完全」と「半壊」の2種類の状態があり、どちらも1マスとして数えられますが、他のプレイヤーに取られるまでの必要塗り回数が異なります。まずはこれを評価関数に追加しましょう。辞書順の評価関数のほうが扱いやすいと感じるので (colored, perfect_coloerd)
が最大になるような移動方向を保持するようにしました。
自陣中心でゆらゆらしないでほしい
移動方向をrandomで決めると自陣中心をふらふらする事象が発生していたので、 next_d = random.choice(best_d)
ではなく next_d = best_d[0]
と変更します。
できれば敵陣を荒らしたい
ここまでの変更ではアグレッシブに敵陣を塗り替えようとしないため、評価関数に敵のマス数を加えました。評価関数は (colored[ME], perfect_coloerd[ME], -sum(colored[ME+1:]), -sum(perfect_coloerd[ME+1:]))
になります。ここで ME=0
, 配列の後ろには全敵プレイヤーの値が入っています。
なかなかいい感じの動きをするようになりました。
天啓:重要なのはマス数を稼ぐことではなく、順位を上げることではないか?
ゲーム内での順位を上げると順位表での順位を上げるための順位点がもらえるので、ゲーム内での順位を最重要指標として組み込みましょう。また、1位の場合は2位を、それ以外のi位の場合はi-1位を攻撃すると順位を上げやすそうです。
※それ以外のケースで1位を妨害したほうがいいんじゃないかと思って -max(colored[ME+1:])
も追加してしまったのですが、これはなくても良かったのではないかと思っています。できれば私以外全員で1位を攻撃していただき、全ての試合で私は着実に2位を取れると順位表的には嬉しそうです。
if my_rank == 0: result = (-my_rank, colored[ME], perfect_coloerd[ME], -ranks[my_rank+1][0], -max(colored[ME+1:]), -sum(colored[ME+1:]), -sum(perfect_coloerd[ME+1:])) else: result = (-my_rank, colored[ME], perfect_coloerd[ME], -ranks[my_rank-1][0], -max(colored[ME+1:]), -sum(colored[ME+1:]), -sum(perfect_coloerd[ME+1:]))
ぐんと強くなりました。
微修正:他のプレイヤーと同じ場所を反復横跳びしないでほしい
ビジュアライザを眺めていると、他のプレイヤーと重なったときにUDUDUDUDと特定の2マスを行ったり来たりしてしまう事象が観察できました。これをしている間に自陣が食い荒らされていくのはもったいないのでXYXYXのパターンを踏みそうになったら4方向からランダム選出することにしました。
結果
一瞬総合1位だった瞬間もあったのですが……
ひどい負けのケースもあり
youtu.be
惜しくも決勝戦進出を逃し9位入賞となりました。