diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2b40c64 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.gradle +.idea/* +libs/robocode.jar +build/ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..9eb504c --- /dev/null +++ b/build.gradle @@ -0,0 +1,84 @@ +import java.util.stream.Collectors + +plugins { + id 'java' +} + +group 'roborunner' +version '2.0-SNAPSHOT' + +sourceCompatibility = 1.8 + +repositories { + mavenCentral() +} + +dependencies { + implementation files('libs/robocode.jar') + implementation group: 'com.google.guava', name: 'guava', version: '30.0-jre' +} + +sourceSets { + main { + java { + srcDir 'src' + } + } +} + +def distDir = "$buildDir/dist" + +task cleanDist(type: Delete) { + delete += "$distDir" +} + +task copyDependencies(dependsOn: cleanDist, type: Copy) { + from(configurations.runtimeClasspath) { + include 'guava*' + } + into "$distDir/lib" +} + +task runnerJar(type: Jar, dependsOn: [compileJava]) { + from(compileJava.outputs) + + archiveName jar.archiveName +} + +task copyLibs(dependsOn: [runnerJar, copyDependencies], type: Copy) { + from(runnerJar.outputs) + into "$distDir/lib" +} + +task generateScripts(dependsOn: [copyLibs]) { + String genOutputDir = file("$buildDir/generated-scripts") + + File outputFile = file("$genOutputDir/rr.sh") + outputs.file(outputFile) + + doLast { + def libs = copyLibs.outputs.getFiles().singleFile + def path = fileTree(dir: libs).files.stream().map({ x -> 'lib' + x.toString().substring(libs.toString().length()) }).collect(Collectors.joining(File.pathSeparator)) + + def robocodeJar = ['robocodes','r1','libs','robocode.jar'].join(File.separator) + + outputFile.text = "#!/bin/sh\n" + + "java -cp '${path}${File.pathSeparator}${robocodeJar}' robowiki.runner.RoboRunner \$*" + } +} + +task makeDist(dependsOn: copyLibs, type: Copy, group: 'deploy') { + from('scripts') { + include '*.sh' + fileMode = 0755 + } + from('scripts') { + exclude '*.sh' + } + from(generateScripts.getOutputs()) { + fileMode = 0755 + } + into "$distDir" +} + +classes.dependsOn(makeDist) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..aa991fc --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/scripts/sample_1v1.rrc b/scripts/competitions/sample_1v1.rrc similarity index 100% rename from scripts/sample_1v1.rrc rename to scripts/competitions/sample_1v1.rrc diff --git a/scripts/sample_melee.rrc b/scripts/competitions/sample_melee.rrc similarity index 100% rename from scripts/sample_melee.rrc rename to scripts/competitions/sample_melee.rrc diff --git a/scripts/sample_teams.rrc b/scripts/competitions/sample_teams.rrc similarity index 100% rename from scripts/sample_teams.rrc rename to scripts/competitions/sample_teams.rrc diff --git a/scripts/rmall.sh b/scripts/rmall.sh index 34ab746..06a280a 100755 --- a/scripts/rmall.sh +++ b/scripts/rmall.sh @@ -1,7 +1,9 @@ +#!/usr/bin/env bash echo "Clearing Robocode JARs, robot caches and databases... " cd robocodes rm -rf r*/robots/.data rm r*/robots/robot.database -rm r*/robots/*.jar +#rm r*/robots/*.jar +find r*/robots -name '*.jar' -delete echo " Done!" diff --git a/scripts/rmdata.sh b/scripts/rmdata.sh index 0ac7a3a..2b8845d 100755 --- a/scripts/rmdata.sh +++ b/scripts/rmdata.sh @@ -1,2 +1,3 @@ +#!/usr/bin/env bash rm -rf robocodes/r*/robots/.data diff --git a/scripts/rr.sh b/scripts/rr.sh deleted file mode 100755 index 35d0e79..0000000 --- a/scripts/rr.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/sh -java -cp lib/roborunner-1.2.3.jar:lib/guava-12.0.1.jar:robocodes/r1/libs/robocode.jar robowiki.runner.RoboRunner $* diff --git a/scripts/setup.sh b/scripts/setup.sh index 7341af5..403ed32 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -47,7 +47,6 @@ else echo " Done!" fi echo "robocodePaths=$paths" > roborunner.properties - echo "jvmArgs=-Xmx512M" >> roborunner.properties + echo "jvmArgs=-Xmx1024M -Dapple.awt.UIElement\=true -Djava.security.manager=allow -XX:+IgnoreUnrecognizedVMOptions --add-opens\=java.base/sun.net.www.protocol.jar\=ALL-UNNAMED --add-opens\=java.base/java.lang.reflect\=ALL-UNNAMED --add-opens\=java.desktop/javax.swing.text\=ALL-UNNAMED --add-opens\=java.desktop/sun.awt\=ALL-UNNAMED --add-opens\=java.desktop/java.awt\=ALL-UNNAMED --add-opens\=java.base/java.lang\=ALL-UNNAMED --add-opens\=java.desktop/sun.java2d.opengl\=ALL-UNNAMED" >> roborunner.properties echo "botsDirs=./bots" >> roborunner.properties fi - diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..5cb4655 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'roborunner' diff --git a/src/robowiki/runner/BattleRunner.java b/src/robowiki/runner/BattleRunner.java index 9f2e5b4..257de8f 100644 --- a/src/robowiki/runner/BattleRunner.java +++ b/src/robowiki/runner/BattleRunner.java @@ -63,7 +63,10 @@ private void initEngine(String enginePath, String jvmArgs) { String processOutput; do { processOutput = reader.readLine(); - } while (!processOutput.equals(BattleProcess.READY_SIGNAL)); + } while (processOutput != null && !processOutput.equals(BattleProcess.READY_SIGNAL)); + if (processOutput == null) { + throw new IOException("processOutput == null"); + } System.out.println("done!"); _processQueue.add(battleProcess); } catch (IOException e) { diff --git a/src/robowiki/runner/RoboRunner.java b/src/robowiki/runner/RoboRunner.java index 497038d..f13c70d 100644 --- a/src/robowiki/runner/RoboRunner.java +++ b/src/robowiki/runner/RoboRunner.java @@ -379,6 +379,11 @@ private List getBattleList(ScoreLog scoreLog, for (BotList botList : challenge.allReferenceBots) { List battleBots = Lists.newArrayList(challenger); List botNames = botList.getBotNames(); + + if (botNames.contains(challenger)) { + continue; + } + if (!skip(skipMap, scoreLog.getSortedBotList(botNames))) { battleBots.addAll(botNames); battleList.add(new BotList(battleBots)); @@ -424,7 +429,9 @@ private ScoreError getScoreError(ScoreLog scoreLog, List scores = Lists.newArrayList(); for (BattleScore battleScore : battleScores) { RobotScore totalScore = battleScore.getRelativeTotalScore(challenger); - scores.add(scoringStyle.getScore(totalScore)); + if (totalScore != null) { + scores.add(scoringStyle.getScore(totalScore)); + } } return new ScoreError(scores, scoreLog.getAverageBattleScore(botList).getElapsedTime()); @@ -619,9 +626,14 @@ private ScoreSummary getScoreSummary(ScoreLog scoreLog, RobotScore totalRobotScore = scoreLog .getAverageBattleScore(botListString) .getRelativeTotalScore(scoreLog.challenger); - sumScores += scoringStyle.getScore(totalRobotScore); - scoredBotLists++; - numBattles += totalRobotScore.numBattles; + double score = scoringStyle.getScore(totalRobotScore); + if (!Double.isNaN(score)) { + sumScores += score; + scoredBotLists++; + numBattles += totalRobotScore.numBattles; + } else { + System.err.println("NaN: " + scoreLog.challenger + " " + botListString); + } } } return new ScoreSummary(sumScores, numBattles, scoredBotLists); @@ -650,11 +662,12 @@ private void printAllScores(ScoreLog scoreLog, ChallengeConfig challenge, .getAverageBattleScore(botListString) .getRelativeTotalScore(scoreLog.challenger); ScoreError scoreError = errorMap.get(botListString); + double score = challenge.scoringStyle.getScore(totalRobotScore); System.out.println(" " + botListString + ": " - + round(challenge.scoringStyle.getScore(totalRobotScore), 2) - + (scoreError.numBattles > 1 - ? " +- " + round(1.96 * scoreError.getStandardError(), 2) : "") - + " (" + scoreError.numBattles + " battles)"); + + (Double.isNaN(score) ? Double.NaN : round(score, 2)) + + (scoreError.numBattles > 1 + ? " +- " + round(1.96 * scoreError.getStandardError(), 2) : "") + + " (" + scoreError.numBattles + " battles)"); } } } @@ -739,10 +752,12 @@ public void processResults( errorMap.put(botList, getScoreError(scoreLog, scoringStyle, challenger, botList)); - printBattleScore(challenger, botList, lastScore, avgScore, - scoringStyle, elapsedTime, errorMap); - if (robotScores.size() > 2) { - printMeleeScores(lastScore, avgScore, challenger, scoringStyle); + if (lastScore != null) { + printBattleScore(challenger, botList, lastScore, avgScore, + scoringStyle, elapsedTime, errorMap); + if (robotScores.size() > 2 && avgScore != null) { + printMeleeScores(lastScore, avgScore, challenger, scoringStyle); + } } printOverallScores( scoreLog, errorMap, challenger, challenge, printWikiFormat, false); @@ -841,7 +856,7 @@ public ScoreSummary( } public double getTotalScore() { - return round(sumScores / scoredBotLists, 2); + return Double.isNaN(sumScores) ? Double.NaN : round(sumScores / scoredBotLists, 2); } } } diff --git a/src/robowiki/runner/RobotScore.java b/src/robowiki/runner/RobotScore.java index 748381d..9539396 100644 --- a/src/robowiki/runner/RobotScore.java +++ b/src/robowiki/runner/RobotScore.java @@ -95,7 +95,7 @@ public RobotScore getScoreRelativeTo( /** * Calculates this score relative to the given enemy scores. * - * @param enemyScore score data for the other robots in the battle + * @param enemyScores score data for the other robots in the battle * @param numRounds number of rounds in the battle * @return the {@code RobotScore} relative to the given enemy robot scores */ @@ -110,14 +110,38 @@ public RobotScore getScoreRelativeTo( numBattles); } + RobotScore getAverageScoreRelativeTo1(List enemyScores) { + return new RobotScore(botName, + getAverageScore(NORMAL_SCORER, enemyScores), + survivalRounds, + survivalScore, + bulletDamage, + energyConserved, + numBattles); + } + + RobotScore getAverageScoreRelativeTo2(List enemyScores, int numRounds) { + return new RobotScore(botName, + score, + getAverageScore(SURVIVAL_FIRSTS_SCORER, enemyScores), + getAverageScore(SURVIVAL_SCORER, enemyScores), + bulletDamage / numRounds, + getAverageEnergyConserved(enemyScores, numRounds), + numBattles); + } + private double getAverageScore( Function scorer, Collection enemyScores) { double totalScore = 0; double challengerScore = scorer.apply(this); int numScores = 0; for (RobotScore robotScore : enemyScores) { - totalScore += 100 * (challengerScore - / (challengerScore + scorer.apply(robotScore))); + double sum = challengerScore + scorer.apply(robotScore); + if (sum == 0.) { + totalScore += 50; + } else { + totalScore += 100 * (challengerScore / sum); + } numScores++; } return totalScore / numScores; diff --git a/src/robowiki/runner/ScoreLog.java b/src/robowiki/runner/ScoreLog.java index e06391c..e5194ce 100644 --- a/src/robowiki/runner/ScoreLog.java +++ b/src/robowiki/runner/ScoreLog.java @@ -138,6 +138,8 @@ public BattleScore getAverageBattleScore(String botList) { boolean initializeTotalScores = true; for (BattleScore battleScore : battleScores) { for (RobotScore robotScore : battleScore.getRobotScores()) { + robotScore = battleScore.getAverageRelativeTotalScore(robotScore.botName); + if (initializeTotalScores) { totalScores.put(robotScore.botName, robotScore); } else { @@ -152,8 +154,8 @@ public BattleScore getAverageBattleScore(String botList) { totalRounds += battleScore.getNumRounds(); totalTime += battleScore.getElapsedTime(); } - return new BattleScore(totalScores.values(), - totalRounds / battleScores.size(), totalTime / battleScores.size()); + return new AverageBattleScore(totalScores.values(), + totalRounds / battleScores.size(), totalTime / battleScores.size()); } public int getBattleCount(List allReferenceBots) { @@ -191,18 +193,24 @@ public static ScoreLog loadScoreLog(String inputFilePath) XMLEvent event = eventReader.nextEvent(); if (event.isStartElement()) { String localPart = event.asStartElement().getName().getLocalPart(); - if (localPart.equals(SCORES)) { - scoreLog = new ScoreLog(getAttribute(event, CHALLENGER)); - } else if (localPart.equals(BATTLE)) { - robotScores = Lists.newArrayList(); - } else if (localPart.equals(ROBOT_SCORE)) { - robotScores.add(readRobotScore(eventReader)); - } else if (localPart.equals(NUM_ROUNDS)) { - event = eventReader.nextEvent(); - numRounds = Integer.parseInt(event.asCharacters().getData()); - } else if (localPart.equals(TIME)) { - event = eventReader.nextEvent(); - time = Long.parseLong(event.asCharacters().getData()); + switch (localPart) { + case SCORES: + scoreLog = new ScoreLog(getAttribute(event, CHALLENGER)); + break; + case BOT_LIST: + break; + case BATTLE: + robotScores = Lists.newArrayList(); + break; + case ROBOT_SCORE: + robotScores.add(readRobotScore(eventReader)); + break; + case NUM_ROUNDS: + numRounds = Integer.parseInt(eventReader.getElementText()); + break; + case TIME: + time = Long.parseLong(eventReader.getElementText()); + break; } } else if (event.isEndElement()) { String localPart = event.asEndElement().getName().getLocalPart(); @@ -242,17 +250,22 @@ private static RobotScore readRobotScore(XMLEventReader eventReader) } else { if (event.isStartElement()) { String localPart = event.asStartElement().getName().getLocalPart(); - event = eventReader.nextEvent(); - if (localPart.equals(NAME)) { - name = event.asCharacters().getData(); - } else if (localPart.equals(SCORE)) { - score = Double.parseDouble(event.asCharacters().getData()); - } else if (localPart.equals(SURVIVAL_ROUNDS)) { - rounds = Double.parseDouble(event.asCharacters().getData()); - } else if (localPart.equals(SURVIVAL_SCORE)) { - survival = Double.parseDouble(event.asCharacters().getData()); - } else if (localPart.equals(DAMAGE)) { - damage = Double.parseDouble(event.asCharacters().getData()); + switch (localPart) { + case NAME: + name = eventReader.getElementText(); + break; + case SCORE: + score = Double.parseDouble(eventReader.getElementText()); + break; + case SURVIVAL_ROUNDS: + rounds = Double.parseDouble(eventReader.getElementText()); + break; + case SURVIVAL_SCORE: + survival = Double.parseDouble(eventReader.getElementText()); + break; + case DAMAGE: + damage = Double.parseDouble(eventReader.getElementText()); + break; } } } @@ -391,9 +404,9 @@ private void writeValue(XMLEventWriter eventWriter, String name, String value, * @author Voidious */ public static class BattleScore { - private final List _robotScores; - private final int _numRounds; - private final long _elapsedTime; + final List _robotScores; + final int _numRounds; + final long _elapsedTime; public BattleScore( Collection scores, int numRounds, long nanoTime) { @@ -425,9 +438,39 @@ public RobotScore getRobotScore(String botName) { public RobotScore getRelativeTotalScore(String botName) { RobotScore referenceScore = getRobotScore(botName); - List enemyScores = Lists.newArrayList(_robotScores); - enemyScores.remove(referenceScore); - return referenceScore.getScoreRelativeTo(enemyScores, _numRounds); + if (referenceScore != null) { + List enemyScores = Lists.newArrayList(_robotScores); + enemyScores.remove(referenceScore); + return referenceScore.getScoreRelativeTo(enemyScores, _numRounds); + } + return null; + } + + RobotScore getAverageRelativeTotalScore(String botName) { + RobotScore referenceScore = getRobotScore(botName); + if (referenceScore != null) { + List enemyScores = Lists.newArrayList(_robotScores); + enemyScores.remove(referenceScore); + return referenceScore.getAverageScoreRelativeTo1(enemyScores); + } + return null; + } + } + + public static final class AverageBattleScore extends BattleScore { + public AverageBattleScore(Collection scores, int numRounds, long nanoTime) { + super(scores, numRounds, nanoTime); + } + + @Override + public RobotScore getRelativeTotalScore(String botName) { + RobotScore referenceScore = getRobotScore(botName); + if (referenceScore != null) { + List enemyScores = Lists.newArrayList(_robotScores); + enemyScores.remove(referenceScore); + return referenceScore.getAverageScoreRelativeTo2(enemyScores, _numRounds); + } + return null; } } }