コドゲのシミュレーターを手元で走らせる方法 2023
本記事は、中身をある程度理解した上でSpring Challenge 2023のシミュレーターをローカルで走らせようというものになっています。賢く手軽に走らせたいという方はボンドさんの記事などを参考にした方がいいかもしれないです。
本記事では、初めにビジュアライザ上で自分のボットを走らせた後に、ビジュアライザを起動せずに連続で試合を回せるようにしていきます。
http://localhost:8888/
に何かを表示させる
ビジュアライザを完璧に走らせるには複数のステップを踏む必要がある。まずはバグった状態のローカルサーバーを建て、そこから目で確認できる形でバグを1つずつ直していく。
ローカルサーバーを建てるエントリポイントがsrc/test/java/Spring2023Main.java
にある。src/test
の下にあるファイルはコンパイル後のjarに含まれないので、以下のコマンドでsrc/main
に移動する。
mv src/test/java/Spring2023Main.java src/main/java/
以下のコマンドでコンパイル。
mvn assembly:assembly -DdescriptorId=jar-with-dependencies
target/spring-2023-ants-1.0-SNAPSHOT-jar-with-dependencies.jar
が生成される。以下のコマンドでローカルサーバー起動。
java -cp target/spring-2023-ants-1.0-SNAPSHOT-jar-with-dependencies.jar Spring2023Main
http://localhost:8888/にアクセスできるようになっている。
壊れているので紺色のページが表示される。
TypeScriptでJavaScriptを生成する
先程の紺色のページのエラーメッセージを見てみるとViewModule.js
をロードできなかったと書いてある。CodinGameは最近TypeScriptを使うようになったらしくTypeScriptからJavaScriptを生成する必要があるらしい。しかし、ド素人なのでよくわかってはいない。
${root}/typescript
というディレクトリがあるがこれは関係がない。実際には${root}/src/main/resources/view/ts
内のファイルをトランスパイルする必要があり、以下のコマンドでどうにかなる。最後のyarn start
はtscをwatchモードで起動し待機状態に入るので、適宜自分で終了する必要がある。
cd src/main/resources/view/ yarn install yarn start
これでsrc/main/resources/view/graphcis
内にJavaScriptが生成された。余談だが、npm ci; npm run start
を走らせろというコメントをよく見るが、CodinGameの社内レポジトリを参照しようとするらしく動かない。yarn install; yarn start
だと動く。理由は不明。
何はともあれJavaScriptが生成されたので再びローカルサーバーを建ててみる。
mvn clean assembly:assembly -DdescriptorId=jar-with-dependencies java -cp target/spring-2023-ants-1.0-SNAPSHOT-jar-with-dependencies.jar Spring2023Main
http://localhost:8888/にアクセスすると多少直ったページが表示される。
画像を正しい場所に置く
先程のページのエラーメッセージを見てみると/assets/assets/spritesheet.pngにアクセスできないと言っている。ただ、/assets/spritesheet.pngにはアクセスできる。つまり何故かURL内でassets
がダブる仕様になっている。このspritesheet.png
はsrc/main/resources/view/assets
ディレクトリから来ており、そのディレクトリ内の全てのファイルに同様の仕様が適用される。なのでassets
内のファイルだけをassets/assets
に移動するようにMavenにお願いする。
assembly.xml
をルートディレクトリ下に作成し、以下の内容をコピペする。
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd"> <id>jar-with-dependencies</id> <formats> <format>jar</format> </formats> <includeBaseDirectory>false</includeBaseDirectory> <dependencySets> <dependencySet> <outputDirectory>/</outputDirectory> <useProjectArtifact>true</useProjectArtifact> <unpack>true</unpack> <scope>runtime</scope> </dependencySet> </dependencySets> <fileSets> <fileSet> <directory>${project.basedir}/src/main/resources/view/assets</directory> <useDefaultExcludes>true</useDefaultExcludes> <outputDirectory>/view/assets/assets</outputDirectory> </fileSet> <fileSet> <directory>${project.basedir}/src/main/resources/view</directory> <useDefaultExcludes>true</useDefaultExcludes> <outputDirectory>/</outputDirectory> <excludes> <exclude>view/assets/**</exclude> </excludes> </fileSet> </fileSets> </assembly>
assembly.xml
を指定してMavenでコンパイルする。
mvn clean assembly:assembly -Ddescriptor=assembly.xml
以下のコマンドでローカルサーバー起動。
java -cp target/spring-2023-ants-1.0-SNAPSHOT-jar-with-dependencies.jar Spring2023Main
http://localhost:8888/にアクセス。これで問題なく動くはず。ゲーム画面が動いていない用に見えるが、これはデフォルトのボットが何もしないため。ビジュアライザのセットアップはおしまい。
自分のボットを戦わせる
初めに移動したローカルサーバーを起動するためのMainクラスsrc/main/java/Spring2023Main.java
の中でgameRunner.addAgent
が呼ばれているが、この引数としてボットの実行コマンドが渡されている。なので、そこを自分のボットを起動するコマンドに書き換えればいい。
- gameRunner.addAgent("python3 config/Boss.py", "TestBoss_1"); - gameRunner.addAgent("python3 config/Boss.py", "TestBoss_2"); + gameRunner.addAgent("/home/nanaeda/main"); + gameRunner.addAgent("/home/nanaeda/main");
Spring Challenge 2023はリーグによって入力形式が変わるため、src/main/java/Spring2023Main.java
内のgameRunner.setLeagueLevel
の引数を適切な値に変更しないと入力を受け取る所で止まったりする。どのリーグレベルの数値がWoodやGoldに対応するかはよくわからないので、コード中でリーグレベルの値が使用されている所を確認するとよい。
- gameRunner.setLeagueLevel(3); + gameRunner.setLeagueLevel(4);
src/main/java/com/codingame/game/Referee.java
内でのリーグレベルの使用方法を確認した結果、レベル4以上から入力にスコアが追加されるらしい。
int leagueLevel = gameManager.getLeagueLevel(); if (leagueLevel == 1) { Config.FORCE_SINGLE_HILL = true; Config.ENABLE_EGGS = false; Config.LOSING_ANTS_CANT_CARRY = false; Config.MAP_RING_COUNT_MAX = 4; } else if (leagueLevel == 2) { Config.FORCE_SINGLE_HILL = true; Config.LOSING_ANTS_CANT_CARRY = false; Config.MAP_RING_COUNT_MAX = 5; } // level 3 = interactions, big map, multiple hills if (leagueLevel >= 4) { Config.SCORES_IN_IO = true; }
いつも通りコンパイルしてサーバーを起動する。
mvn clean assembly:assembly -Ddescriptor=assembly.xml java -cp target/spring-2023-ants-1.0-SNAPSHOT-jar-with-dependencies.jar Spring2023Main
http://localhost:8888/にアクセスすると動いているはず。
連続で試合を回す
今まではMainクラス内でMultiplayerGameRunner::start
を呼び、ビジュアライザを起動していた。これをMultiplayerGameRunner::simulate
に変更するとビジュアライザを起動せずに対戦だけを行うことができる。例えば、以下のようなコード変更をsrc/test/java/Spring2023Main.java
に行うことができる。
import com.codingame.gameengine.runner.MultiplayerGameRunner; +import com.codingame.gameengine.runner.simulate.GameResult; import com.google.common.io.Files;
gameRunner.setLeagueLevel(4); - gameRunner.start(); + final GameResult result = gameRunner.simulate(); + System.out.println("Player0 score=" + result.scores.get(0)); + System.out.println("Player1 score=" + result.scores.get(1)); }
コンパイルと起動方法は前回と同じ。
mvn assembly:assembly -Ddescriptor=assembly.xml java -cp target/spring-2023-ants-1.0-SNAPSHOT-jar-with-dependencies.jar Spring2023Main
アウトプット例は以下の通り。
Player0 score=66 Player1 score=80
これで対戦だけを回すことができるのだが、CodinGameのコードはJava起動時に初期化されたグローバル変数をそのまま使っている可能性が高い。つまり、forループで対戦を回すとバグるかもしれない。なので対戦毎にJavaを起動すると安全。