コドゲのシミュレーターを手元で走らせる方法 2023

本記事は、中身をある程度理解した上でSpring Challenge 2023のシミュレーターをローカルで走らせようというものになっています。賢く手軽に走らせたいという方はボンドさんの記事などを参考にした方がいいかもしれないです。


本記事では、初めにビジュアライザ上で自分のボットを走らせた後に、ビジュアライザを起動せずに連続で試合を回せるようにしていきます。

コードを手元に落とす

各コンペのルール中に張られているGitHubへのリンクからコードを落としてくる。必要なコードはこれだけ。

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 starttscwatchモードで起動し待機状態に入るので、適宜自分で終了する必要がある。

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.pngsrc/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を起動すると安全。