CodinGame のコンテストでは終盤になるとサブミットしたボットがすべての対戦を終了するのに数時間かかることも珍しくないので、ローカル環境で開発 & 検証を出来ることが重要になっています。
Spring Challenge 2023 では cg-brutaltester を利用してローカル対戦を行っていたのですが
psyleague も同じことが出来るみたいなので試してみました。
対戦環境の構築
ローカルの対戦環境については Jiro さんのブログを参考にしました。
以降は docker 上での環境が整った状態で話をします。
psyleague のインストール
README に従って pip コマンドで psyleague をインストールします。
pip install psyleague --upgrade
対戦スクリプトの作成
Create a script that given two bots, simulates the game and prints out 4 integers on a single line: "P1_rank P2_rank P1_error P2_error". The first two are ranks of the bots, i.e. if first player wins print "0 1", if the second player wins print "1 0", in case of a draw print "0 0". The last two signify that bot crashed during the game: 0 = no error, 1 = error.
ボットの名前を 2つ受け取って対戦を行いその結果を返すスクリプトを用意します。 ファイル名は play_game.py
にしておきます。
import sys import subprocess args = sys.argv bot1 = args[1] bot2 = args[2] result = subprocess.run(f'java -jar spring-2023-ants-1.0-SNAPSHOT.jar -p1 {bot1} -p2 {bot2}', shell=True, capture_output=True) output = result.stdout.split() score1 = int(output[0]) score2 = int(output[1]) rank1 = 0 if score1 > score2 else 1 rank2 = 0 if score1 < score2 else 1 error1 = 0 if score1 != -1 else 1 error2 = 0 if score2 != -1 else 1 print(f'{rank1} {rank2} {error1} {error2}')
今回のコンテストだとスコアが高ければ勝利、また -1
だとエラー扱いなのでこんな感じになりました。(このあたりはコンテストごとに変わるはずです)
設定ファイルの作成
以下のコマンドで設定ファイルを作成します。
psyleague config
デフォルトだとこんな感じのファイルが生成されるはずです
version = "0.2.0" # [MATCHMAKING] n_workers = 1 mm_min_matches = 200 mm_min_matches_preference = 0.75 mm_coeff = 2.5 # [SHOW] # ? at the end means that the column is optional and it's only showed when it contains different values date_format = "%Y/%m/%d %H:%M:%S" #more about the format: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes leaderboard = "POS,NAME,SCORE,GAMES,MU,SIGMA,ACTIVE?,ERRORS?,DATE,DESCRIPTION?" # [RANKING MODEL] model = "trueskill" draw_prob = 0.0001 tau = 0.00025 # [COMMANDS] dir_bots = "bots" cmd_bot_setup = "g++ -std=c++17 %SRC%.cpp -o %DIR%/%NAME%.exe && cp %SRC%.cpp %DIR%/%NAME%.cpp" cmd_play_game = "python play_game.py %DIR%/%P1%.exe %DIR%/%P2%.exe" # [FILES] file_log = "psyleague.log" file_msg = "psyleague.msg" file_db = "psyleague.db" file_games = "psyleague.games"
これを自分の環境に合わせて修正します。今回は n_workers
と cmd_bot_setup
と cmd_play_game
の 3つを修正しました。
version = "0.2.0" # [MATCHMAKING] -n_workers = 1 +n_workers = 4 mm_min_matches = 200 mm_min_matches_preference = 0.75 mm_coeff = 2.5 @@ -18,12 +18,11 @@ tau = 0.00025 # [COMMANDS] dir_bots = "bots" -cmd_bot_setup = "g++ -std=c++17 %SRC%.cpp -o %DIR%/%NAME%.exe && cp %SRC%.cpp %DIR%/%NAME%.cpp" -cmd_play_game = "python play_game.py %DIR%/%P1%.exe %DIR%/%P2%.exe" +cmd_bot_setup = "docker exec local_battle g++ -std=c++17 %SRC% -o %DIR%/%NAME% && cp %SRC% %DIR%/%NAME%.cpp" +cmd_play_game = "docker exec local_battle python3 play_game.py %DIR%/%P1% %DIR%/%P2%"
n_workers
は同時に実行するプロセスの数を決定します。速くたくさん試合したいので 4 にしました。強いマシンを持ってる人ならもっと増やしてもいいかも。
cmd_bot_setup
にはボットをビルドするときのコマンドを設定します。
cmd_play_game
にはボットを対戦させるときのコマンドを設定します。
対戦サーバーの起動
以下のコマンドでサーバーを起動します。
psyleague run
何も無い状態だとこんな感じの表示になります。
Starting Psyleague server, press Ctrl+C to kill it Active Bots: 0 Games since launch: 0 Games in the last 60s: 0
ボットの追加
bot add
コマンドでボットを追加します。
$ psyleague bot add cur_bot -s my_bot.cpp Running Setup: docker exec local_battle g++ -std=c++17 my_bot.cpp -o bots/cur_bot && cp my_bot.cpp bots/cur_bot.cpp
コマンドが成功すると dir_bots
で指定したディレクトリ以下にボットの実行ファイルとソースコードが追加されます。
$ tree bots bots ├── cur_bot └── cur_bot.cpp
またサーバー側のボットの数も増えます。
Starting Psyleague server, press Ctrl+C to kill it ADD_BOT : cur_bot : n/a Active Bots: 1 Games since launch: 0 Games in the last 60s: 0
1体だとまだ動作しないのでもう一体追加を行います。
$ psyleague bot add silver_bot -s silver_bot.cpp Running Setup: docker exec local_battle g++ -std=c++17 silver_bot.cpp -o bots/silver_bot && cp silver_bot.cpp bots/silver_bot.cpp
$ tree bots bots ├── cur_bot ├── cur_bot.cpp ├── silver_bot └── silver_bot.cpp
2体目が追加されるとすぐに対戦が開始されます。
Starting Psyleague server, press Ctrl+C to kill it ADD_BOT : cur_bot : n/a ADD_BOT : silver_bot : n/a Active Bots: 2 Games since launch: 83 Games in the last 60s: 28
対戦結果の確認
psyleague show
で対戦の結果を確認することが出来ます。
$ psyleague show Pos Name Score Games Mu Sigma Errors Created --- ---------- ------ ----- ------ ----- ------ ------------------- 1 cur_bot 23.815 111 26.143 0.776 6 2023/06/07 00:03:55 2 silver_bot 21.528 111 23.857 0.776 4 2023/06/07 00:09:25
対戦回数については何も指定しない場合 sys.maxsize
回行われるので (64ビット環境だと 9223372036854775807) 適当なところで止めてあげると良いです。
games_total = args.games or sys.maxsize
止めるのが面倒な場合は --games
オプションで試合する回数の上限を設定してあげると良いでしょう。
$ psyleague run --games 100 Starting Psyleague server, press Ctrl+C to kill it Active Bots: 2 Games since launch: 2 / 100 Games in the last 60s: 2
まとめ
今回は psyleague の Quick Setup Guide を試してみました。ローカルで実際の CodinGame のようなランキングシステムを構築出来るのは良いと思いましたし、過去の bot とまとめて対戦出来るのは便利でした。次回がいつになるかわかりませんが、その際には psyleague を使ってみようかなと思います。他にも便利な機能があるみたいなので興味がある人は是非試してみてください。