diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..6f4977df --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,102 @@ +name: Release +on: + push: + tags: + - '*' + +env: + # GCS_BUCKET is the name of the Google Cloud Storage bucket to which all artifacts are deployed. + GCS_BUCKET: mitbattlecode-releases + + # RELEASE_ARTIFACT_ID is the name of the Maven artifact produced by the buildsystem. + # Important: you must make sure no ID is a prefix of a different ID. Otherwise, you could + # inadvertently cause unintended episodes to become public. + RELEASE_ARTIFACT_ID: battlecode22 + + # IS_PUBLIC is whether to release deployments publicly. Set to exactly the text "YES" to do so. + IS_PUBLIC: YES + +jobs: + release: + name: Release + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + + steps: + - name: Checkout branch + uses: actions/checkout@v3 + + - name: Get release version + run: | + release_version=${GITHUB_REF#refs/*/} + echo "RELEASE_VERSION=$release_version" >> $GITHUB_ENV + echo "The release version is $release_version" + + - name: Authenticate to Google Cloud Platform + uses: google-github-actions/auth@v1 + with: + create_credentials_file: true + workload_identity_provider: projects/830784087321/locations/global/workloadIdentityPools/releases/providers/github-workflow + service_account: releases-agent@mitbattlecode.iam.gserviceaccount.com + + - name: Set up Google Cloud SDK + uses: 'google-github-actions/setup-gcloud@v1' + + - name: Set up Wine # See actions/runner-images#743 + run: | + sudo dpkg --add-architecture i386 + wget -qO - https://dl.winehq.org/wine-builds/winehq.key | sudo apt-key add - + sudo add-apt-repository ppa:cybermax-dexter/sdl2-backport + sudo apt-add-repository "deb https://dl.winehq.org/wine-builds/ubuntu $(lsb_release -cs) main" + sudo apt install --install-recommends winehq-stable + + - name: Set up JDK 8 + uses: actions/setup-java@v3 + with: + java-version: 8 + distribution: adopt + + - name: Set up Node 16 + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Install schema + run: npm install + working-directory: ./schema + + - name: Install client + run: npm run install-all + working-directory: ./client + + - name: Publish to local repository + run: ./gradlew publishToMavenLocal -Prelease_version=$RELEASE_VERSION + + - name: Build web client + run: npm run prod + working-directory: ./client/visualizer + + - name: Determine access control + run: | + [[ "$IS_PUBLIC" = "YES" ]] && acl="public-read" || acl="project-private" + echo "OBJECT_ACL=$acl" >> $GITHUB_ENV + echo "Objects will be uploaded with ACL $acl" + + - name: Upload maven artifacts to remote repository + run: gsutil -m rsync -a $OBJECT_ACL -r $HOME/.m2/repository/org/battlecode gs://$GCS_BUCKET/maven/org/battlecode + + - name: Upload javadocs + run: | + unzip -d ${{ runner.temp }}/javadoc $HOME/.m2/repository/org/battlecode/$RELEASE_ARTIFACT_ID/$RELEASE_VERSION/*-javadoc.jar + gsutil -m rsync -a $OBJECT_ACL -r ${{ runner.temp }}/javadoc gs://$GCS_BUCKET/javadoc/$RELEASE_ARTIFACT_ID/$RELEASE_VERSION + + - name: Upload specs + run: gsutil -m rsync -a $OBJECT_ACL -r ./specs gs://$GCS_BUCKET/specs/$RELEASE_ARTIFACT_ID/$RELEASE_VERSION + + - name: Upload web client + run: | + gsutil -m rsync -a $OBJECT_ACL out gs://$GCS_BUCKET/client/$RELEASE_ARTIFACT_ID/$RELEASE_VERSION + gsutil cp -a $OBJECT_ACL visualizer.html gs://$GCS_BUCKET/client/$RELEASE_ARTIFACT_ID/$RELEASE_VERSION + working-directory: ./client/visualizer diff --git a/EMAILS.md b/EMAILS.md index 9c3ee9f8..0a38c05c 100644 --- a/EMAILS.md +++ b/EMAILS.md @@ -40,6 +40,8 @@ to be able to use it. (`add consult` only works when running through bash, for s Get a list of emails, and convert it to the format as specified by mmblanche's `-f` argument: one email per line. (For example, if you're working with a Google Form, you can get a Google Sheet of responses. Create a new tab -- **not** the tab where form responses are being collected!. Convert it into only one column of values such that all the values are emails -- strip out timestamps, header row, and the like. Then download this as a csv. If you'd like to export emails from our database, you can use a nice interface to download a table as a csv, and work with it.) +If you have a terminal database client, you can instead run a command like `\copy (select email from api_user) to './emails.csv' with csv;`. + Move this file to your Athena locker; you can use `scp` for this (example [here](https://unix.stackexchange.com/questions/106480/how-to-copy-files-from-one-machine-to-another-using-ssh)). Finally run mmblanche! For example, `mmblanche [mailman-list-name] -al [path/to/file]`. Likely you'll want to use `-al`, as it simply adds any emails in the file to the list, skips over duplicates for you, and doesn't delete anything otherwise. diff --git a/README.md b/README.md index 1520bf5b..671c6b02 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,11 @@ 🚩 ## Note, Competitors -This is the development repo! Do not clone this. Instead, follow the instructions [here](http://2021.battlecode.org/getting-started) +This is the development repo! You most likely won't need anything in here; do not clone this. +Instead, follow the instructions [here](https://play.battlecode.org/getting-started) to get started. + ## Repository Structure -- `/backend`: Backend API in Django Rest Framework -- `/frontend`: Frontend dashboard in React - `/engine`: Game engine in Java - `/specs`: Game specs in Markdown (and HTML generation) - `/schema`: Game serialization schema (basically, an encoding of all units and events in a game) diff --git a/build.gradle b/build.gradle index fba0d3d7..2fca84d5 100644 --- a/build.gradle +++ b/build.gradle @@ -9,151 +9,70 @@ sourceCompatibility = 1.8 // Fun fact: this line of code single-handedly fixed an error I spent two hours debugging. evaluationDependsOnChildren() -if (!project.hasProperty("teamA")) { - ext.teamA = "examplefuncsplayer" -} -if (!project.hasProperty("teamB")) { - ext.teamB = "examplefuncsplayer" -} -if (!project.hasProperty("maps")) { - ext.maps = "maptest" -} - -if (project.hasProperty("release_version")) { - if (!project.property("release_version").startsWith("2022")) { - throw new StopExecutionException("release version must start with 2022!") - } -} - configurations { scala + + engine { + transitive false + } + bots { + transitive false + } } repositories { - jcenter() + mavenCentral() } dependencies { scala group: 'org.scala-lang', name: 'scala-library', version: '2.11.7' scala group: 'org.scala-lang', name: 'scala-compiler', version: '2.11.7' scala group: 'org.scala-lang', name: 'scala-reflect', version: '2.11.7' + + engine project(":engine") + bots project(":example-bots") } -def serverJar = new File(project(":engine").libsDir, "engine.jar") +def serverJar = configurations.engine.singleFile task buildMap(type: JavaExec, dependsOn: [':engine:build']) { - main = 'battlecode.world.maps.' + project.property('buildMap') + mainClass = 'battlecode.world.maps.' + project.property('buildMap') classpath = files(serverJar) } task buildMaps(type: JavaExec, dependsOn: [':engine:build']) { - main = 'battlecode.world.BuildMaps' + mainClass = 'battlecode.world.BuildMaps' classpath = files(serverJar) } -task headless(type: JavaExec, dependsOn: [':engine:build', ':example-bots:build']) { - main = 'battlecode.server.Main' - classpath = files(serverJar) + project(':example-bots').sourceSets.main.output + configurations.scala - args = ['-c=-'] - jvmArgs = [ - '-Dbc.server.mode=headless', - '-Dbc.server.map-path=maps', - '-Dbc.server.debug=true', - '-Dbc.engine.debug-methods=true', - '-Dbc.engine.enable-profiler='+project.property('profilerEnabled'), - '-Dbc.game.team-a='+project.property('teamA'), - '-Dbc.game.team-b='+project.property('teamB'), - '-Dbc.game.team-a.url='+project(':example-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.team-b.url='+project(':example-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.maps='+project.property('maps'), - '-Dbc.server.save-file=' + 'matches/' + project.property('teamA') + '-vs-' + project.property('teamB') + '-on-' + project.property('maps') + '.bc21' - ] -} +def defaultClassLocation = project(':example-bots').sourceSets.main.output.classesDirs.getAsPath() +def defaultReplay = 'matches/' + project.property('teamA') + '-vs-' + project.property('teamB') + '-on-' + project.property('maps') + '.bc22' -task debug(type: JavaExec, dependsOn: [':engine:build', ':example-bots:build']) { - main = 'battlecode.server.Main' +task headless(type: JavaExec, dependsOn: [':engine:build', ':example-bots:build']) { + mainClass = 'battlecode.server.Main' classpath = files(serverJar) + project(':example-bots').sourceSets.main.output + configurations.scala args = ['-c=-'] jvmArgs = [ - '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005', - '-Dbc.server.mode=headless', - '-Dbc.server.map-path=maps', - '-Dbc.server.debug=true', - '-Dbc.engine.debug-methods=true', - '-Dbc.engine.enable-profiler='+project.property('profilerEnabled'), - '-Dbc.game.team-a='+project.property('teamA'), - '-Dbc.game.team-b='+project.property('teamB'), - '-Dbc.game.team-a.url='+project(':example-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.team-b.url='+project(':example-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.maps='+project.property('maps'), - '-Dbc.server.save-file=' + 'matches/' + project.property('teamA') + '-vs-' + project.property('teamB') + '-on-' + project.property('maps') + '.bc21' - ] -} - -task headlessX(type: JavaExec, dependsOn: [':engine:build', ':internal-test-bots:build']) { - main = 'battlecode.server.Main' - classpath = files(serverJar) + project(':internal-test-bots').sourceSets.main.output + configurations.scala - args = ['-c=-'] - jvmArgs = [ - '-Dbc.server.mode=headless', - '-Dbc.server.map-path=maps', - '-Dbc.server.debug=true', - '-Dbc.engine.debug-methods=true', - '-Dbc.engine.enable-profiler='+project.property('profilerEnabled'), - '-Dbc.game.team-a='+project.property('teamA'), - '-Dbc.game.team-b='+project.property('teamB'), - '-Dbc.game.team-a.url='+project(':internal-test-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.team-b.url='+project(':internal-test-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.maps='+project.property('maps'), - '-Dbc.server.save-file=' + 'matches/' + project.property('teamA') + '-vs-' + project.property('teamB') + '-on-' + project.property('maps') + '.bc21' - ] -} - -task debugX(type: JavaExec, dependsOn: [':engine:build', ':internal-test-bots:build']) { - main = 'battlecode.server.Main' - classpath = files(serverJar) + project(':internal-test-bots').sourceSets.main.output + configurations.scala - args = ['-c=-'] - jvmArgs = [ - '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005', + '-Dbc.server.wait-for-client=' + (project.findProperty('waitForClient') ?: 'false'), '-Dbc.server.mode=headless', '-Dbc.server.map-path=maps', - '-Dbc.server.debug=true', - '-Dbc.engine.debug-methods=true', - '-Dbc.engine.enable-profiler='+project.property('profilerEnabled'), - '-Dbc.game.team-a='+project.property('teamA'), - '-Dbc.game.team-b='+project.property('teamB'), - '-Dbc.game.team-a.url='+project(':internal-test-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.team-b.url='+project(':internal-test-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.maps='+project.property('maps'), - '-Dbc.server.save-file=' + 'matches/' + project.property('teamA') + '-vs-' + project.property('teamB') + '-on-' + project.property('maps') + '.bc21' + '-Dbc.server.robot-player-to-system-out=' + (project.findProperty('outputVerbose') ?: 'true'), + '-Dbc.server.debug=' + (project.findProperty('debug') ?: 'false'), + '-Dbc.engine.debug-methods=' + (project.findProperty('debug') ?: 'false'), + '-Dbc.engine.enable-profiler=' + (project.findProperty('enableProfiler') ?: 'false'), + '-Dbc.engine.show-indicators=' + (project.findProperty('showIndicators') ?: 'true'), + '-Dbc.game.team-a=' + project.property('teamA'), + '-Dbc.game.team-b=' + project.property('teamB'), + '-Dbc.game.team-a.url=' + (project.findProperty('classLocationA') ?: defaultClassLocation), + '-Dbc.game.team-b.url=' + (project.findProperty('classLocationB') ?: defaultClassLocation), + '-Dbc.game.team-a.package=' + (project.findProperty('packageNameA') ?: project.property('teamA')), + '-Dbc.game.team-b.package=' + (project.findProperty('packageNameB') ?: project.property('teamB')), + '-Dbc.game.maps=' + project.property('maps'), + '-Dbc.server.save-file=' + (project.findProperty('replay') ?: defaultReplay), ] } -task runFromClient(type: JavaExec, dependsOn: [':engine:build', ':internal-test-bots:build']) { - main = 'battlecode.server.Main' - classpath = files(serverJar) + project(':internal-test-bots').sourceSets.main.output + configurations.scala - args = ['-c=-'] - jvmArgs = [ - '-Dbc.server.wait-for-client=true', - '-Dbc.server.mode=headless', - '-Dbc.server.map-path=maps', - '-Dbc.server.debug=false', - '-Dbc.server.robot-player-to-system-out=false', - '-Dbc.engine.debug-methods=true', - '-Dbc.engine.enable-profiler='+project.property('profilerEnabled'), - '-Dbc.game.team-a='+project.property('teamA'), - '-Dbc.game.team-b='+project.property('teamB'), - '-Dbc.game.team-a.url='+project(':internal-test-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.team-b.url='+project(':internal-test-bots').sourceSets.main.output.classesDirs.getAsPath(), - '-Dbc.game.maps='+project.property('maps'), - '-Dbc.server.save-file=' + 'matches/' + project.property('teamA') + '-vs-' + project.property('teamB') + '-on-' + project.property('maps') + '.bc21' - ] -} - - - - task run(dependsOn: ['headless']) {} task runClient { @@ -182,10 +101,10 @@ task release_main(type: Jar, dependsOn: [':engine:build']) { Files.write(f_version.toPath(), [project.property("release_version")]); } - baseName = "battlecode"; + archiveBaseName = "battlecode"; if (project.hasProperty("release_version")) version = project.property("release_version"); - destinationDir = project.projectDir; + destinationDirectory = project.projectDir; FileCollection src = files(f_version); src += zipTree(serverJar); @@ -203,40 +122,14 @@ task release_docs(type: Jar, dependsOn: [':engine:javadoc']) { throw new InvalidUserDataException("Must provide property \"release_version\"") } - baseName = "battlecode-javadoc" - if (project.hasProperty("release_version")) - version = project.property("release_version"); - destinationDir = project.projectDir; - - from new File(project(":engine").docsDir, "javadoc") -} - -task release_docs_zip(type: Zip, dependsOn: [':engine:javadoc']) { - doFirst { - if (!project.hasProperty("release_version") || project.property("release_version") == "unspecified") - throw new InvalidUserDataException("Must provide property \"release_version\"") - } - - baseName = "battlecode-javadoc" + archiveBaseName = "battlecode-javadoc" if (project.hasProperty("release_version")) version = project.property("release_version"); - destinationDir = project.projectDir; + destinationDirectory = project.projectDir; from new File(project(":engine").docsDir, "javadoc") } -task release_sources(type: Jar, dependsOn: classes) { - classifier = 'sources' - from project(":engine").sourceSets.main.allSource - - baseName = "battlecode-source" - if (project.hasProperty("release_version")) - version = project.property("release_version"); - destinationDir = project.projectDir; - - // from new File(project(":engine").sourceDir, "source") -} - task prodClient { doLast { exec { @@ -271,52 +164,31 @@ task releaseClientLinux32(type: Zip, dependsOn: ['prodClient']) { } - -task updateVersion() { - new File("frontend/public/version.txt").write(project.findProperty('release_version')) -} - - -publish.dependsOn(updateVersion) publishing { - repositories { - maven { - url = uri("https://maven.pkg.github.com/battlecode/battlecode21") - credentials { - username = project.findProperty("gpr.user") ?: System.getenv("BC21_GITUSERNAME") - password = project.findProperty("gpr.key") ?: System.getenv("BC21_GITKEY") - } - } - } - publications { server(MavenPublication) { groupId 'org.battlecode' - artifactId 'battlecode21' + artifactId 'battlecode22' version project.findProperty('release_version') ?: 'NONSENSE' artifact release_main - artifact release_docs { classifier 'javadoc' } - artifact release_sources { - classifier 'sources' - } } clientWin(MavenPublication) { groupId 'org.battlecode' - artifactId 'battlecode21-client-win' + artifactId 'battlecode22-client-win' version project.findProperty('release_version') ?: 'NONSENSE' artifact releaseClientWin } - + clientMac(MavenPublication) { groupId 'org.battlecode' - artifactId 'battlecode21-client-mac' + artifactId 'battlecode22-client-mac' version project.findProperty('release_version') ?: 'NONSENSE' artifact releaseClientMac @@ -324,7 +196,7 @@ publishing { clientLinux(MavenPublication) { groupId 'org.battlecode' - artifactId 'battlecode21-client-linux' + artifactId 'battlecode22-client-linux' version project.findProperty('release_version') ?: 'NONSENSE' artifact releaseClientLinux @@ -332,7 +204,7 @@ publishing { clientWin32(MavenPublication) { groupId 'org.battlecode' - artifactId 'battlecode21-client-win-32' + artifactId 'battlecode22-client-win-32' version project.findProperty('release_version') ?: 'NONSENSE' artifact releaseClientWin32 @@ -340,7 +212,7 @@ publishing { clientLinux32(MavenPublication) { groupId 'org.battlecode' - artifactId 'battlecode21-client-linux-32' + artifactId 'battlecode22-client-linux-32' version project.findProperty('release_version') ?: 'NONSENSE' artifact releaseClientLinux32 diff --git a/client/.gitignore b/client/.gitignore index e1410674..16970045 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -13,11 +13,11 @@ playback/out/ # built client dist/ -# Generated test bc21 files +# Generated test bc22 files examples/ # any battlecode files -*.bc21 +*.bc22 # for mac users? **/.DS_Store diff --git a/client/deploy-web-client.sh b/client/deploy-web-client.sh new file mode 100644 index 00000000..66a50b11 --- /dev/null +++ b/client/deploy-web-client.sh @@ -0,0 +1,47 @@ +# TODO move this to deploy folder +# TODO enforce state of repo up-to-date +# TODO year as arg +# TODO prereqs: npm, tsc, java?, flatc + +BUCKET_NAME="bc-game-storage" +# TODO make gs://$BUCKET_NAME/clients/2022/ a var, and use it + +echo "IMPORTANT: Make sure that gameVersion is updated in client/visualizer/src/config." +echo "If it is not, change it now. Make sure to push to the repo later too." +read -p "Press enter to proceed..." + +cd ../schema +npm install +# Don't do npm run build; +# this regenerates flatbuffers which is pretty annoying +# npm run build +# TODO the following replacement could be done automatically i think +# echo "IMPORTANT: " +# echo "NOW, change line 3 of schema/ts/battlecode_generated.ts to \`import { flatbuffers } from \"flatbuffers\"\`." +# echo "DON'T FORGET TO SAVE!" +# read -p "When done, press enter to proceed..." +cd ../client + +cd playback +npm install +npm run build +cd ../visualizer +npm install +npm run prod +cd .. + +read -p "Press Ctrl-C if things don't look right. If done, press enter to proceed..." + +gsutil -m rm gs://$BUCKET_NAME/clients/2022/** +gsutil -m cp -r visualizer/out gs://$BUCKET_NAME/clients/2022/ +gsutil -m cp visualizer/visualizer.html gs://$BUCKET_NAME/clients/2022/ +gsutil -m setmeta -h "Cache-Control:no-cache" -r gs://$BUCKET_NAME/clients/2022/** + +echo 'Do you wish to deploy the client to the public? Type public and press enter.' +echo 'IMPORTANT: NEVER DO THIS BEFORE THE GAME IS RELEASED' +read -p 'input: ' ispublic +if [ "$ispublic" == 'public' ] +then + gsutil -m acl ch -u AllUsers:R -r gs://$BUCKET_NAME/clients/2022/** +fi + diff --git a/client/package-lock.json b/client/package-lock.json index 1068690b..9c5f0fde 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -1,13 +1,5 @@ { "name": "battlecode-client", "version": "2022.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "battlecode-client", - "version": "2022.0.0", - "license": "GPL-3.0" - } - } + "lockfileVersion": 1 } diff --git a/client/playback/README.md b/client/playback/README.md index 998f7296..8c817c01 100644 --- a/client/playback/README.md +++ b/client/playback/README.md @@ -24,7 +24,7 @@ Remember to run `npm install` without any serious errors in this directory. * `npm run check`: Compile typescript files (`src/*.ts`) without creating any output files, and pipe output to less. Use this command when you need to update playback for new schema. * `npm run build`: Compile typescript files (`src/*.ts`) into javascript & typescript declaration files. (`out/*.js`, `out/*.d.ts`) - * `npm run gen`: Generate dummy `.bc21` files. It runs typescript without transcripting into javascript, by using `ts-node`. (`../examples`) + * `npm run gen`: Generate dummy `.bc22` files. It runs typescript without transcripting into javascript, by using `ts-node`. (`../examples`) * `npm run clean`: Simply remove itself and everything in `out` directory. * `npm run watch`: Watch for chanages on `src/*.ts` files, and build again whenever change is detected. @@ -34,11 +34,11 @@ The other scripts are under maintenance. ### Structure * `src/*.ts` : main source files. `index.ts` is the starting point * `src/tsconfig.json` : TypeScript compile option configuration file - * `src/gen/create.ts` : code for generating dummy `.bc21` files. + * `src/gen/create.ts` : code for generating dummy `.bc22` files. * `src/legacy/**/*.ts` : Legacy codes, including test for soa.ts and simulating * `out/*.js` : compiled javascript output of typescript files * `out/*.d.ts` : compiled typescript declaration files of typescript files - * `../examples` : generated `.bc21` files from `src/gen/*` + * `../examples` : generated `.bc22` files from `src/gen/*` ### Note @@ -68,7 +68,7 @@ const bc = require('battlecode-playback'); let aliveRobots = {}; let lifetimes = []; -bc.stream('match.bc21').on('spawn', spawnEvent => { +bc.stream('match.bc22').on('spawn', spawnEvent => { aliveRobots[spawnEvent.bodyId] = { born: spawnEvent.round }; diff --git a/client/playback/package-lock.json b/client/playback/package-lock.json index a1afa9bb..dacd3d2f 100644 --- a/client/playback/package-lock.json +++ b/client/playback/package-lock.json @@ -7,9 +7,11 @@ "name": "battlecode-playback", "license": "GPL-3.0", "dependencies": { + "@types/flatbuffers": "^1.10.0", "battlecode-schema": "file:../../schema", "core-js": "^3.3.6", "deepcopy": "^2.0.0", + "flatbuffers": "^23.1.4", "pako": "^1.0.10", "victor": "^1.1.0" }, @@ -130,6 +132,11 @@ "integrity": "sha512-+NPqjXgyA02xTHKJDeDca9u8Zr42ts6jhdND4C3PrPeQ35RJa0dmfAedXW7a9K4N1QcBbuWI1nSfGK4r1eVFCQ==", "dev": true }, + "node_modules/@types/flatbuffers": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", + "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==" + }, "node_modules/@types/node": { "version": "12.12.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.5.tgz", @@ -293,6 +300,7 @@ "version": "3.3.6", "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.3.6.tgz", "integrity": "sha512-u4oM8SHwmDuh5mWZdDg9UwNVq5s1uqq6ZDLLIs07VY+VJU91i3h4f3K/pgFvtUQPGdeStrZ+odKyfyt4EnKHfA==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", "hasInstallScript": true }, "node_modules/core-util-is": { @@ -414,6 +422,11 @@ "node": ">=0.10.0" } }, + "node_modules/flatbuffers": { + "version": "23.1.4", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.1.4.tgz", + "integrity": "sha512-iHDB7ESwi2lLEIr2KLrK+mwcWDPZb/ZB1hjspq8dIi/4S5WVnS+WOgJU9Ip8nMRmzXfDSeQccI9D1vcoxXSYEQ==" + }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -1166,6 +1179,11 @@ "integrity": "sha512-+NPqjXgyA02xTHKJDeDca9u8Zr42ts6jhdND4C3PrPeQ35RJa0dmfAedXW7a9K4N1QcBbuWI1nSfGK4r1eVFCQ==", "dev": true }, + "@types/flatbuffers": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", + "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==" + }, "@types/node": { "version": "12.12.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.5.tgz", @@ -1423,6 +1441,11 @@ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true }, + "flatbuffers": { + "version": "23.1.4", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-23.1.4.tgz", + "integrity": "sha512-iHDB7ESwi2lLEIr2KLrK+mwcWDPZb/ZB1hjspq8dIi/4S5WVnS+WOgJU9Ip8nMRmzXfDSeQccI9D1vcoxXSYEQ==" + }, "for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", diff --git a/client/playback/package.json b/client/playback/package.json index c5d72c90..2456f2c7 100644 --- a/client/playback/package.json +++ b/client/playback/package.json @@ -20,9 +20,11 @@ "url": "github.com/battlecode/battlecode21" }, "dependencies": { + "@types/flatbuffers": "^1.10.0", "battlecode-schema": "file:../../schema", "core-js": "^3.3.6", "deepcopy": "^2.0.0", + "flatbuffers": "^23.1.4", "pako": "^1.0.10", "victor": "^1.1.0" }, diff --git a/client/playback/src/gameworld.ts b/client/playback/src/gameworld.ts index f0eefd5a..1a533b57 100644 --- a/client/playback/src/gameworld.ts +++ b/client/playback/src/gameworld.ts @@ -1,11 +1,11 @@ -import StructOfArrays from './soa'; -import Metadata from './metadata'; -import { flatbuffers, schema } from 'battlecode-schema'; -import {playbackConfig} from './game'; +import StructOfArrays from './soa' +import Metadata from './metadata' +import { flatbuffers, schema } from 'battlecode-schema' +import { playbackConfig } from './game' // necessary because victor doesn't use exports.default -import Victor = require('victor'); -import deepcopy = require('deepcopy'); +import Victor = require('victor') +import deepcopy = require('deepcopy') // TODO use Victor for representing positions export type DeadBodiesSchema = { @@ -20,15 +20,17 @@ export type BodiesSchema = { type: Int8Array, x: Int32Array, y: Int32Array, - flag: Int32Array; bytecodesUsed: Int32Array, // TODO: is this needed? action: Int8Array, + target: Int32Array, + targetx: Int32Array, + targety: Int32Array, parent: Int32Array, hp: Int32Array, level: Int8Array, portable: Int8Array, prototype: Int8Array -}; +} // NOTE: consider changing MapStats to schema to use SOA for better performance, if it has large data export type MapStats = { @@ -38,13 +40,18 @@ export type MapStats = { bodies: schema.SpawnedBodyTable, randomSeed: number, - passability: Float64Array, // double - leadVals: Int32Array; - goldVals: Int32Array; + rubble: Int32Array, // double + leadVals: Int32Array + goldVals: Int32Array + + symmetry: number - getIdx: (x:number, y:number) => number; - getLoc: (idx: number) => Victor; -}; + anomalies: Int32Array + anomalyRounds: Int32Array + + getIdx: (x: number, y: number) => number + getLoc: (idx: number) => Victor +} export type TeamStats = { // An array of numbers corresponding to team stats, which map to RobotTypes @@ -55,8 +62,12 @@ export type TeamStats = { gold: number, total_hp: [number[], number[], number[], number[], number[], number[], number[]], leadChange: number, - goldChange: number -}; + goldChange: number, + leadMined: number, + goldMined: number, + leadMinedHist: number[], + goldMinedHist: number[], +} export type IndicatorDotsSchema = { id: Int32Array, @@ -84,7 +95,7 @@ export type Log = { id: number, round: number, text: string -}; +} /** * A frozen image of the game world. @@ -95,64 +106,70 @@ export default class GameWorld { /** * Bodies that died this round. */ - diedBodies: StructOfArrays; + diedBodies: StructOfArrays /** * Everything that isn't an indicator string. */ - bodies: StructOfArrays; + bodies: StructOfArrays /* * Stats for each team */ - teamStats: Map; // Team ID to their stats + teamStats: Map // Team ID to their stats /* * Stats for each team */ - mapStats: MapStats; // Team ID to their stats + mapStats: MapStats // Team ID to their stats /** * Indicator dots. */ - indicatorDots: StructOfArrays; + indicatorDots: StructOfArrays /** * Indicator lines. */ - indicatorLines: StructOfArrays; + indicatorLines: StructOfArrays + + /** + * Indicator strings. + * Stored as a dictionary of robot ids and that robot's string + */ + indicatorStrings: object /** * The current turn. */ - turn: number; + turn: number // duplicate with mapStats, but left for compatibility. // TODO: change dependencies and remove these map variables /** * The minimum corner of the game world. */ - minCorner: Victor; + minCorner: Victor /** * The maximum corner of the game world. */ - maxCorner: Victor; + maxCorner: Victor /** * The name of the map. */ - mapName: string; + mapName: string /** * Metadata about the current game. */ - meta: Metadata; + meta: Metadata /** * Whether to process logs. */ - config: playbackConfig; + config: playbackConfig /** * Recent logs, bucketed by round. @@ -168,10 +185,10 @@ export default class GameWorld { // Cache fields // We pass these into flatbuffers functions to avoid allocations, // but that's it, they don't hold any state - private _bodiesSlot: schema.SpawnedBodyTable; - private _vecTableSlot1: schema.VecTable; - private _vecTableSlot2: schema.VecTable; - private _rgbTableSlot: schema.RGBTable; + private _bodiesSlot: schema.SpawnedBodyTable + private _vecTableSlot1: schema.VecTable + private _vecTableSlot2: schema.VecTable + private _rgbTableSlot: schema.RGBTable /** * IDs of robots who performed a temporary ability in the previous round, @@ -181,13 +198,13 @@ export default class GameWorld { private bidRobots: number[] = []; constructor(meta: Metadata, config: playbackConfig) { - this.meta = meta; + this.meta = meta this.diedBodies = new StructOfArrays({ id: new Int32Array(0), x: new Int32Array(0), y: new Int32Array(0), - }, 'id'); + }, 'id') this.bodies = new StructOfArrays({ id: new Int32Array(0), @@ -195,45 +212,55 @@ export default class GameWorld { type: new Int8Array(0), x: new Int32Array(0), y: new Int32Array(0), - flag: new Int32Array(0), bytecodesUsed: new Int32Array(0), action: new Int8Array(0), + target: new Int32Array(0), + targetx: new Int32Array(0), + targety: new Int32Array(0), parent: new Int32Array(0), hp: new Int32Array(0), level: new Int8Array(0), portable: new Int8Array(0), prototype: new Int8Array(0) - }, 'id'); + }, 'id') // Instantiate teamStats - this.teamStats = new Map(); + this.teamStats = new Map() for (let team in this.meta.teams) { - var teamID = this.meta.teams[team].teamID; - this.teamStats.set(teamID, { - robots: [[0], [0], [0], [0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], - lead: 0, - gold: 0, - total_hp: [[0], [0], [0], [0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], - leadChange: 0, - goldChange: 0 - }); + var teamID = this.meta.teams[team].teamID + this.teamStats.set(teamID, { + robots: [[0], [0], [0], [0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], + lead: 0, + gold: 0, + total_hp: [[0], [0], [0], [0], [0, 0, 0], [0, 0, 0], [0, 0, 0]], + leadChange: 0, + goldChange: 0, + leadMined: 0, + goldMined: 0, + leadMinedHist: [], + goldMinedHist: [] + }) } // Instantiate mapStats this.mapStats = { name: '????', - minCorner: new Victor(0,0), - maxCorner: new Victor(0,0), + minCorner: new Victor(0, 0), + maxCorner: new Victor(0, 0), bodies: new schema.SpawnedBodyTable(), randomSeed: 0, - passability: new Float64Array(0), + rubble: new Int32Array(0), leadVals: new Int32Array(0), goldVals: new Int32Array(0), - getIdx: (x:number, y:number) => 0, - getLoc: (idx: number) => new Victor(0,0) - }; + symmetry: 0, + anomalies: new Int32Array(0), + anomalyRounds: new Int32Array(0), + + getIdx: (x: number, y: number) => 0, + getLoc: (idx: number) => new Victor(0, 0) + } this.indicatorDots = new StructOfArrays({ @@ -243,7 +270,7 @@ export default class GameWorld { red: new Int32Array(0), green: new Int32Array(0), blue: new Int32Array(0) - }, 'id'); + }, 'id') this.indicatorLines = new StructOfArrays({ id: new Int32Array(0), @@ -254,75 +281,69 @@ export default class GameWorld { red: new Int32Array(0), green: new Int32Array(0), blue: new Int32Array(0) - }, 'id'); + }, 'id') + + this.indicatorStrings = {} - this.turn = 0; - this.minCorner = new Victor(0, 0); - this.maxCorner = new Victor(0, 0); - this.mapName = '????'; + this.turn = 0 + this.minCorner = new Victor(0, 0) + this.maxCorner = new Victor(0, 0) + this.mapName = '????' this._bodiesSlot = new schema.SpawnedBodyTable() - this._vecTableSlot1 = new schema.VecTable(); - this._vecTableSlot2 = new schema.VecTable(); - this._rgbTableSlot = new schema.RGBTable(); + this._vecTableSlot1 = new schema.VecTable() + this._vecTableSlot2 = new schema.VecTable() + this._rgbTableSlot = new schema.RGBTable() - this.config = config; + this.config = config } loadFromMatchHeader(header: schema.MatchHeader) { - const map = header.map(); + const map = header.map() - const name = map.name() as string; + const name = map.name() as string if (name) { - this.mapName = map.name() as string; - this.mapStats.name = map.name() as string; + this.mapName = map.name() as string + this.mapStats.name = map.name() as string } - const minCorner = map.minCorner(); - this.minCorner.x = minCorner.x(); - this.minCorner.y = minCorner.y(); - this.mapStats.minCorner.x = minCorner.x(); - this.mapStats.minCorner.y = minCorner.y(); - - const maxCorner = map.maxCorner(); - this.maxCorner.x = maxCorner.x(); - this.maxCorner.y = maxCorner.y(); - this.mapStats.maxCorner.x = maxCorner.x(); - this.mapStats.maxCorner.y = maxCorner.y(); - - this.mapStats.goldVals = new Int32Array(maxCorner.x()*maxCorner.y()) - this.mapStats.leadVals = new Int32Array(maxCorner.x()*maxCorner.y()) - - const bodies = map.bodies(this._bodiesSlot); - if (bodies && bodies.robotIDsLength) { - this.insertBodies(bodies); - } + const minCorner = map.minCorner() + this.minCorner.x = minCorner.x() + this.minCorner.y = minCorner.y() + this.mapStats.minCorner.x = minCorner.x() + this.mapStats.minCorner.y = minCorner.y() - this.mapStats.randomSeed = map.randomSeed(); + const maxCorner = map.maxCorner() + this.maxCorner.x = maxCorner.x() + this.maxCorner.y = maxCorner.y() + this.mapStats.maxCorner.x = maxCorner.x() + this.mapStats.maxCorner.y = maxCorner.y() - this.mapStats.passability = Float64Array.from(map.passabilityArray()); + this.mapStats.goldVals = new Int32Array(maxCorner.x() * maxCorner.y()) + this.mapStats.leadVals = map.leadArray() - const leadLocations = map.leadLocations(this._vecTableSlot1); - if (leadLocations) { + const bodies = map.bodies(this._bodiesSlot) + if (bodies && bodies.robotIDsLength) { + this.insertBodies(bodies) + } - const xs = leadLocations.xsArray(); - const ys = leadLocations.ysArray(); + this.mapStats.randomSeed = map.randomSeed() - xs.forEach((x, i) => { - const y = ys[i] - - this.mapStats.leadVals[this.mapStats.getIdx(x,y)] = map.leadAmountsArray[i]; - }) - } + this.mapStats.rubble = map.rubbleArray() - const width = (maxCorner.x() - minCorner.x()); - this.mapStats.getIdx = (x:number, y:number) => ( - Math.floor(y)*width + Math.floor(x) - ); + const width = (maxCorner.x() - minCorner.x()) + this.mapStats.getIdx = (x: number, y: number) => ( + Math.floor(y) * width + Math.floor(x) + ) this.mapStats.getLoc = (idx: number) => ( new Victor(idx % width, Math.floor(idx / width)) - ); - + ) + + this.mapStats.symmetry = map.symmetry() + + this.mapStats.anomalies = Int32Array.from(map.anomaliesArray()) + this.mapStats.anomalyRounds = Int32Array.from(map.anomalyRoundsArray()) + // Check with header.totalRounds() ? } @@ -330,29 +351,30 @@ export default class GameWorld { * Create a copy of the world in its current state. */ copy(): GameWorld { - const result = new GameWorld(this.meta, this.config); - result.copyFrom(this); - return result; + const result = new GameWorld(this.meta, this.config) + result.copyFrom(this) + return result } copyFrom(source: GameWorld) { - this.turn = source.turn; - this.minCorner = source.minCorner; - this.maxCorner = source.maxCorner; - this.mapName = source.mapName; - this.diedBodies.copyFrom(source.diedBodies); - this.bodies.copyFrom(source.bodies); - this.indicatorDots.copyFrom(source.indicatorDots); - this.indicatorLines.copyFrom(source.indicatorLines); - this.teamStats = new Map(); + this.turn = source.turn + this.minCorner = source.minCorner + this.maxCorner = source.maxCorner + this.mapName = source.mapName + this.diedBodies.copyFrom(source.diedBodies) + this.bodies.copyFrom(source.bodies) + this.indicatorDots.copyFrom(source.indicatorDots) + this.indicatorLines.copyFrom(source.indicatorLines) + this.indicatorStrings = Object.assign({}, source.indicatorStrings) + this.teamStats = new Map() source.teamStats.forEach((value: TeamStats, key: number) => { - this.teamStats.set(key, deepcopy(value)); - }); - this.mapStats = deepcopy(source.mapStats); - this.actionRobots = Array.from(source.actionRobots); - this.bidRobots = Array.from(source.bidRobots); - this.logs = Array.from(source.logs); - this.logsShift = source.logsShift; + this.teamStats.set(key, deepcopy(value)) + }) + this.mapStats = deepcopy(source.mapStats) + this.actionRobots = Array.from(source.actionRobots) + this.bidRobots = Array.from(source.bidRobots) + this.logs = Array.from(source.logs) + this.logsShift = source.logsShift } /** @@ -360,66 +382,75 @@ export default class GameWorld { */ processDelta(delta: schema.Round) { // Change to reflect current game if (delta.roundID() != this.turn + 1) { - throw new Error(`Bad Round: this.turn = ${this.turn}, round.roundID() = ${delta.roundID()}`); + throw new Error(`Bad Round: this.turn = ${this.turn}, round.roundID() = ${delta.roundID()}`) } // Process team info changes for (var i = 0; i < delta.teamIDsLength(); i++) { - let teamID = delta.teamIDs(i); - let statObj = this.teamStats.get(teamID); + let teamID = delta.teamIDs(i) + let statObj = this.teamStats.get(teamID) - statObj.lead += delta.teamLeadChange(i); - statObj.gold += delta.teamGoldChange(i); - statObj.leadChange = delta.teamLeadChange(i); - statObj.goldChange = delta.teamGoldChange(i); + statObj.lead += delta.teamLeadChanges(i) + statObj.gold += delta.teamGoldChanges(i) + statObj.leadChange = delta.teamLeadChanges(i) + statObj.goldChange = delta.teamGoldChanges(i) + statObj.leadMined = 0 + statObj.goldMined = 0 - this.teamStats.set(teamID, statObj); - } + this.teamStats.set(teamID, statObj) + } // Location changes on bodies - const movedLocs = delta.movedLocs(this._vecTableSlot1); + const movedLocs = delta.movedLocs(this._vecTableSlot1) if (movedLocs) { this.bodies.alterBulk({ id: delta.movedIDsArray(), x: movedLocs.xsArray(), y: movedLocs.ysArray(), - }); + }) } // Spawned bodies - const bodies = delta.spawnedBodies(this._bodiesSlot); + const bodies = delta.spawnedBodies(this._bodiesSlot) if (bodies) { - this.insertBodies(bodies); + this.insertBodies(bodies) } // Remove abilities from previous round - this.bodies.alterBulk({id: new Int32Array(this.actionRobots), ability: new Int8Array(this.actionRobots.length)}); + this.bodies.alterBulk({id: new Int32Array(this.actionRobots), action: (new Int8Array(this.actionRobots.length)).fill(-1), + target: new Int32Array(this.actionRobots.length), targetx: new Int32Array(this.actionRobots.length), targety: new Int32Array(this.actionRobots.length)}); this.actionRobots = []; // Remove bids from previous round - this.bodies.alterBulk({id: new Int32Array(this.bidRobots), bid: new Int32Array(this.bidRobots.length)}); - this.bidRobots = []; + this.bodies.alterBulk({ id: new Int32Array(this.bidRobots), bid: new Int32Array(this.bidRobots.length) }) + this.bidRobots = [] // Map changes - const leadLocations = delta.leadDropLocations(this._vecTableSlot1); + const leadLocations = delta.leadDropLocations(this._vecTableSlot1) if (leadLocations) { - const xs = leadLocations.xsArray(); - const ys = leadLocations.ysArray(); + const xs = leadLocations.xsArray() + const ys = leadLocations.ysArray() xs.forEach((x, i) => { const y = ys[i] - this.mapStats.leadVals[this.mapStats.getIdx(x,y)] = delta.leadDropValues[i]; + this.mapStats.leadVals[this.mapStats.getIdx(x, y)] += delta.leadDropValues(i) }) } - const goldLocations = delta.goldDropLocations(this._vecTableSlot1); + const goldLocations = delta.goldDropLocations(this._vecTableSlot1) if (goldLocations) { - const xs = goldLocations.xsArray(); - const ys = goldLocations.ysArray(); - let inst = this; + const xs = goldLocations.xsArray() + const ys = goldLocations.ysArray() + let inst = this xs.forEach((x, i) => { const y = ys[i] - inst.mapStats.goldVals[inst.mapStats.getIdx(x,y)] = delta.goldDropValues(i); + inst.mapStats.goldVals[inst.mapStats.getIdx(x, y)] += delta.goldDropValues(i) + }) + } + + if (delta.roundID() % this.meta.constants.increasePeriod() == 0) { + this.mapStats.leadVals.forEach((x, i) => { + this.mapStats.leadVals[i] = x > 0 ? x + this.meta.constants.leadAdditiveIncease() : 0 }) } @@ -431,92 +462,159 @@ export default class GameWorld { const action = delta.actions(i); const robotID = delta.actionIDs(i); const target = delta.actionTargets(i); - const body = this.bodies.lookup(robotID); - const teamStatsObj: TeamStats = this.teamStats.get(body.team); - const setAction = () => { + const body = robotID != -1 ? this.bodies.lookup(robotID) : null; + const teamStatsObj = body != null ? this.teamStats.get(body.team) : null; + const setAction = (set_target: Boolean = false, set_target_loc: Boolean = false) => { this.bodies.alter({id: robotID, action: action as number}); + if (set_target) this.bodies.alter({id: robotID, target: target}); + if (set_target_loc) { + const target_body = this.bodies.lookup(target); + this.bodies.alter({id: robotID, targetx: target_body.x, targety: target_body.y}); + } this.actionRobots.push(robotID); - }; // should be called for actions performed *by* the robot. + }; // should be called for actions performed *by* the robot switch (action) { // TODO: validate actions? // Actions list from battlecode.fbs enum Action case schema.Action.ATTACK: - setAction(); + setAction(true, true); break; /// Slanderers passively generate influence for the /// Enlightenment Center that created them. /// Target: parent ID case schema.Action.LOCAL_ABYSS: - setAction(); - break; + setAction() + break case schema.Action.LOCAL_CHARGE: - setAction(); - break; - + setAction() + break + case schema.Action.LOCAL_FURY: + setAction() + break + + case schema.Action.TRANSMUTE: setAction(); - break; - - case schema.Action.CONVERT_GOLD: - setAction(); - teamStatsObj.gold += target; - teamStatsObj.lead -= 0; + teamStatsObj.goldMined += 1; + // teamStatsObj.gold += target; + // teamStatsObj.lead -= 0; break; case schema.Action.TRANSFORM: - setAction(); - this.bodies.alter({ id: robotID, portable: 1}); - break; + setAction() + this.bodies.alter({ id: robotID, portable: 1 - body.portable }) + break + + case schema.Action.MINE_LEAD: + setAction() + teamStatsObj.leadMined += 1; + break + + case schema.Action.MINE_GOLD: + setAction() + teamStatsObj.goldMined += 1; + break + + case schema.Action.MUTATE: + const target_body = this.bodies.lookup(target); + teamStatsObj.robots[target_body.type][target_body.level - 1] -= 1 + teamStatsObj.robots[target_body.type][target_body.level + 1 - 1] += 1 + teamStatsObj.total_hp[target_body.type][target_body.level - 1] -= body.hp + teamStatsObj.total_hp[target_body.type][target_body.level + 1 - 1] += body.hp + this.bodies.alter({ id: target, level: target_body.level + 1 }) + break - case schema.Action.UPGRADE: - setAction(); - teamStatsObj.robots[body.type][body.level - 1] -= 1; - teamStatsObj.robots[body.type][body.level + 1 - 1] += 1; - teamStatsObj.total_hp[body.type][body.level - 1] -= body.hp; - teamStatsObj.total_hp[body.type][body.level + 1 - 1] += body.hp; - this.bodies.alter({ id: robotID, level: body.level + 1}); - break; - /// Builds a unit (enlightent center). /// Target: spawned unit case schema.Action.SPAWN_UNIT: - setAction(); - this.bodies.alter({id: target, parent: robotID}); - break; + setAction() + this.bodies.alter({ id: target, parent: robotID }) + break case schema.Action.REPAIR: - setAction(); - break; + setAction(true, true); + break - case schema.Action.CHANGE_HP: + case schema.Action.CHANGE_HEALTH: this.bodies.alter({ id: robotID, hp: body.hp + target}); - teamStatsObj.total_hp[body.type][body.level] += target; + teamStatsObj.total_hp[body.type][body.level - 1] += target; break; case schema.Action.FULLY_REPAIRED: this.bodies.alter({ id: robotID, prototype: 0}); - teamStatsObj.total_hp[body.type][body.level] += target; + //teamStatsObj.total_hp[body.type][body.level] += target; break; case schema.Action.DIE_EXCEPTION: - console.log(`Exception occured: robotID(${robotID}), target(${target}`); - break; + console.log(`Exception occured: robotID(${robotID}), target(${target}`) + break + + case schema.Action.VORTEX: + let w = this.mapStats.maxCorner.x - this.mapStats.minCorner.x; + let h = this.mapStats.maxCorner.y - this.mapStats.minCorner.y; + switch (target) { + case 0: + for (let x = 0; x < Math.floor(w / 2); x++) { + for (let y = 0; y < Math.floor((w + 1) / 2); y++) { + let curX = x + let curY = y + let lastRubble = this.mapStats.rubble[curX + curY * w] + for (let i = 0; i < 4; i++) { + let tempX = curX + curX = curY + curY = (w - 1) - tempX + let idx = curX + curY * w + let tempRubble = this.mapStats.rubble[idx] + this.mapStats.rubble[idx] = lastRubble + lastRubble = tempRubble + } + } + } + break + case 1: + for (let x = 0; x < Math.floor(w / 2); x++) { + for (let y = 0; y < h; y++) { + let idx = x + y * w + let newX = w - 1 - x + let newIdx = newX + y * w + let prevRubble = this.mapStats.rubble[idx] + this.mapStats.rubble[idx] = this.mapStats.rubble[newIdx] + this.mapStats.rubble[newIdx] = prevRubble + } + } + break + case 2: + for (let y = 0; y < Math.floor(h / 2); y++) { + for (let x = 0; x < w; x++) { + let idx = x + y * w + let newY = h - 1 - y + let newIdx = x + newY * w + let prevRubble = this.mapStats.rubble[idx] + this.mapStats.rubble[idx] = this.mapStats.rubble[newIdx] + this.mapStats.rubble[newIdx] = prevRubble + } + } + break + } default: - console.log(`Undefined action: action(${action}), robotID(${robotID}, target(${target}))`); - break; + //console.log(`Undefined action: action(${action}), robotID(${robotID}, target(${target}))`); + break } - this.teamStats.set(body.team, teamStatsObj); // TODO: is this necessary + if (body) this.teamStats.set(body.team, teamStatsObj) } } - // for (let team in this.meta.teams) { - // let teamID = this.meta.teams[team].teamID; - // let teamStats = this.teamStats.get(teamID) as TeamStats; - // teamStats.income = 0; - // } + for (let team in this.meta.teams) { + let teamID = this.meta.teams[team].teamID; + let statsObj = this.teamStats.get(teamID) as TeamStats; + statsObj.leadMinedHist.push(statsObj.leadMined); + if (statsObj.leadMinedHist.length > 100) statsObj.leadMinedHist.shift(); + statsObj.goldMinedHist.push(statsObj.goldMined); + if (statsObj.goldMinedHist.length > 100) statsObj.goldMinedHist.shift(); + } // income // this.bodies.arrays.type.forEach((type, i) => { @@ -553,19 +651,25 @@ export default class GameWorld { if(!statObj) {continue;} // In case this is a neutral bot statObj.robots[type][this.bodies.arrays.level[index] - 1] -= 1; let hp = this.bodies.arrays.hp[index]; - statObj.total_hp[type][this.bodies.arrays.level[index] - 1] -= hp; + let level = this.bodies.arrays.level[index]; + statObj.total_hp[type][level - 1] -= hp; this.teamStats.set(team, statObj); } // Update bodies soa - this.insertDiedBodies(delta); - - this.bodies.deleteBulk(delta.diedIDsArray()); + this.insertDiedBodies(delta) + this.bodies.deleteBulk(delta.diedIDsArray()) } // Insert indicator dots and lines - this.insertIndicatorDots(delta); - this.insertIndicatorLines(delta); + this.insertIndicatorDots(delta) + this.insertIndicatorLines(delta) + + //indicator strings + for(var i = 0; i < delta.indicatorStringsLength(); i++){ + let bodyID = delta.indicatorStringIDs(i) + this.indicatorStrings[bodyID] = delta.indicatorStrings(i) + } // Logs // TODO @@ -574,14 +678,14 @@ export default class GameWorld { // TODO // Increase the turn count - this.turn = delta.roundID(); + this.turn = delta.roundID() // Update bytecode costs if (delta.bytecodeIDsLength() > 0) { this.bodies.alterBulk({ id: delta.bytecodeIDsArray(), bytecodesUsed: delta.bytecodesUsedArray() - }); + }) } // TODO: process indicator strings @@ -594,38 +698,38 @@ export default class GameWorld { // this.logs.shift(); // this.logsShift++; // } - // console.log(delta.roundID(), this.logsShift, this.logs[0]); + // console.log(delta.roundID(), this.logsShift, this.logs[0]); } private insertDiedBodies(delta: schema.Round) { // Delete the died bodies from the previous round - this.diedBodies.clear(); + this.diedBodies.clear() // Insert the died bodies from the current round const startIndex = this.diedBodies.insertBulk({ id: delta.diedIDsArray() - }); + }) // Extra initialization - const endIndex = startIndex + delta.diedIDsLength(); - const idArray = this.diedBodies.arrays.id; - const xArray = this.diedBodies.arrays.x; - const yArray = this.diedBodies.arrays.y; + const endIndex = startIndex + delta.diedIDsLength() + const idArray = this.diedBodies.arrays.id + const xArray = this.diedBodies.arrays.x + const yArray = this.diedBodies.arrays.y for (let i = startIndex; i < endIndex; i++) { - const body = this.bodies.lookup(idArray[i]); - xArray[i] = body.x; - yArray[i] = body.y; + const body = this.bodies.lookup(idArray[i]) + xArray[i] = body.x + yArray[i] = body.y } } private insertIndicatorDots(delta: schema.Round) { // Delete the dots from the previous round - this.indicatorDots.clear(); + this.indicatorDots.clear() // Insert the dots from the current round if (delta.indicatorDotIDsLength() > 0) { - const locs = delta.indicatorDotLocs(this._vecTableSlot1); - const rgbs = delta.indicatorDotRGBs(this._rgbTableSlot); + const locs = delta.indicatorDotLocs(this._vecTableSlot1) + const rgbs = delta.indicatorDotRGBs(this._rgbTableSlot) this.indicatorDots.insertBulk({ id: delta.indicatorDotIDsArray(), x: locs.xsArray(), @@ -639,13 +743,13 @@ export default class GameWorld { private insertIndicatorLines(delta: schema.Round) { // Delete the lines from the previous round - this.indicatorLines.clear(); + this.indicatorLines.clear() // Insert the lines from the current round if (delta.indicatorLineIDsLength() > 0) { - const startLocs = delta.indicatorLineStartLocs(this._vecTableSlot1); - const endLocs = delta.indicatorLineEndLocs(this._vecTableSlot2); - const rgbs = delta.indicatorLineRGBs(this._rgbTableSlot); + const startLocs = delta.indicatorLineStartLocs(this._vecTableSlot1) + const endLocs = delta.indicatorLineEndLocs(this._vecTableSlot2) + const rgbs = delta.indicatorLineRGBs(this._rgbTableSlot) this.indicatorLines.insertBulk({ id: delta.indicatorLineIDsArray(), startX: startLocs.xsArray(), @@ -664,30 +768,34 @@ export default class GameWorld { // Store frequently used arrays var teams = bodies.teamIDsArray(); var types = bodies.typesArray(); + var hps = new Int32Array(bodies.robotIDsLength()); + var prototypes = new Int8Array(bodies.robotIDsLength()); // Update spawn stats - for(let i = 0; i < bodies.robotIDsLength(); i++) { + for (let i = 0; i < bodies.robotIDsLength(); i++) { // if(teams[i] == 0) continue; var statObj = this.teamStats.get(teams[i]); statObj.robots[types[i]][0] += 1; // TODO: handle level - statObj.total_hp[types[i]][0] += this.meta.types[types[i]].hp; // TODO: extract meta info + statObj.total_hp[types[i]][0] += this.meta.types[types[i]].health; // TODO: extract meta info this.teamStats.set(teams[i], statObj); + hps[i] = this.meta.types[types[i]].health; + prototypes[i] = (this.meta.buildingTypes.includes(types[i]) && types[i] != schema.BodyType.ARCHON) ? 1 : 0; } - - const locs = bodies.locs(this._vecTableSlot1); + + const locs = bodies.locs(this._vecTableSlot1) // Note: this allocates 6 objects with each call. // (One for the container, one for each TypedArray.) // All of the objects are small; the TypedArrays are basically // (pointer, length) pairs. // You can't reuse TypedArrays easily, so I'm inclined to // let this slide for now. - + // Initialize convictions // Insert bodies - const levels = new Int8Array(bodies.robotIDsLength()); - levels.fill(1); + const levels = new Int8Array(bodies.robotIDsLength()) + levels.fill(1) this.bodies.insertBulk({ id: bodies.robotIDsArray(), @@ -697,10 +805,16 @@ export default class GameWorld { y: locs.ysArray(), flag: new Int32Array(bodies.robotIDsLength()), bytecodesUsed: new Int32Array(bodies.robotIDsLength()), - ability: new Int8Array(bodies.robotIDsLength()), + action: (new Int8Array(bodies.robotIDsLength())).fill(-1), + target: new Int32Array(bodies.robotIDsLength()), + targetx: new Int32Array(bodies.robotIDsLength()), + targety: new Int32Array(bodies.robotIDsLength()), bid: new Int32Array(bodies.robotIDsLength()), parent: new Int32Array(bodies.robotIDsLength()), - level: levels + hp: hps, + level: levels, + portable: new Int8Array(bodies.robotIDsLength()), + prototype: prototypes, }); } @@ -710,56 +824,56 @@ export default class GameWorld { private parseLogs(round: number, logs: string) { // TODO regex this properly // Regex - let lines = logs.split(/\r?\n/); - let header = /^\[(A|B):(ENLIGHTENMENT_CENTER|POLITICIAN|SLANDERER|MUCKRAKER)#(\d+)@(\d+)\] (.*)/; + let lines = logs.split(/\r?\n/) + let header = /^\[(A|B):(ENLIGHTENMENT_CENTER|POLITICIAN|SLANDERER|MUCKRAKER)#(\d+)@(\d+)\] (.*)/ - let roundLogs = new Array(); + let roundLogs = new Array() // Parse each line - let index: number = 0; + let index: number = 0 while (index < lines.length) { - let line = lines[index]; - let matches = line.match(header); + let line = lines[index] + let matches = line.match(header) // Ignore empty string if (line === "") { - index += 1; - continue; + index += 1 + continue } // The entire string and its 5 parenthesized substrings must be matched! if (matches === null || (matches && matches.length != 6)) { // throw new Error(`Wrong log format: ${line}`); - console.log(`Wrong log format: ${line}`); - console.log('Omitting logs'); - return; + console.log(`Wrong log format: ${line}`) + console.log('Omitting logs') + return } - let shortenRobot = new Map(); - shortenRobot.set("ENLIGHTENMENT_CENTER", "EC"); - shortenRobot.set("POLITICIAN", "P"); - shortenRobot.set("SLANDERER", "SL"); - shortenRobot.set("MUCKRAKER", "MCKR"); + let shortenRobot = new Map() + shortenRobot.set("ENLIGHTENMENT_CENTER", "EC") + shortenRobot.set("POLITICIAN", "P") + shortenRobot.set("SLANDERER", "SL") + shortenRobot.set("MUCKRAKER", "MCKR") // Get the matches - let team = matches[1]; - let robotType = matches[2]; - let id = parseInt(matches[3]); - let logRound = parseInt(matches[4]); - let text = new Array(); - let mText = "[" + team + ":" + robotType + "#" + id + "@" + logRound + "]"; - let mText2 = "[" + team + ":" + shortenRobot.get(robotType) + "#" + id + "@" + logRound + "] "; - text.push(mText + mText2 + matches[5]); - index += 1; + let team = matches[1] + let robotType = matches[2] + let id = parseInt(matches[3]) + let logRound = parseInt(matches[4]) + let text = new Array() + let mText = "[" + team + ":" + robotType + "#" + id + "@" + logRound + "]" + let mText2 = "[" + team + ":" + shortenRobot.get(robotType) + "#" + id + "@" + logRound + "] " + text.push(mText + mText2 + matches[5]) + index += 1 // If there is additional non-header text in the following lines, add it while (index < lines.length && !lines[index].match(header)) { - text.push(lines[index]); - index +=1; + text.push(lines[index]) + index += 1 } if (logRound != round) { - console.warn(`Your computation got cut off while printing a log statement at round ${logRound}; the actual print happened at round ${round}`); + console.warn(`Your computation got cut off while printing a log statement at round ${logRound}; the actual print happened at round ${round}`) } // Push the parsed log @@ -769,8 +883,8 @@ export default class GameWorld { id: id, round: logRound, text: text.join('\n') - }); + }) } - this.logs.push(roundLogs); + this.logs.push(roundLogs) } } diff --git a/client/playback/src/gen/create.ts b/client/playback/src/gen/create.ts index cb67f28a..fffe3dd7 100644 --- a/client/playback/src/gen/create.ts +++ b/client/playback/src/gen/create.ts @@ -4,6 +4,7 @@ import {createWriteStream} from 'fs'; import {gzip} from 'pako'; import { isNull } from 'util'; import { Signer } from 'crypto'; +import { constants } from 'buffer'; let SIZE = 32; const maxID = 4096; @@ -42,7 +43,7 @@ type BodiesType = { }; type MapType = { - passability: number[], + rubble: number[], }; // Class to manage IDs of units @@ -135,11 +136,11 @@ function makeRandomBodies(manager: IDsManager, unitCount: number): BodiesType{ function makeRandomMap(): MapType { const map: MapType = { - passability: new Array(SIZE*SIZE) + rubble: new Array(SIZE*SIZE) }; for(let i=0; i; - if (map) passability = map.passability; + let rubble: Array; + if (map) rubble = map.rubble; else { - passability = new Array(SIZE*SIZE); - passability.fill(0); + rubble = new Array(SIZE*SIZE); + rubble.fill(0); } // all values default to zero - const bb_passability = schema.GameMap.createPassabilityVector(builder, passability); + const bb_rubble = schema.GameMap.createRubbleVector(builder, rubble); + const bb_lead = schema.GameMap.createLeadVector(builder, new Array(SIZE*SIZE)); // TODO: interesting lead and anomalies + const bb_anomalies = schema.GameMap.createAnomaliesVector(builder, []); + const bb_anomalyRounds = schema.GameMap.createAnomalyRoundsVector(builder, []); schema.GameMap.startGameMap(builder); schema.GameMap.addName(builder, bb_name); @@ -198,7 +202,12 @@ function createMap(builder: flatbuffers.Builder, bodies: number, name: string, m if(!isNull(bodies)) schema.GameMap.addBodies(builder, bodies); schema.GameMap.addRandomSeed(builder, 42); - schema.GameMap.addPassability(builder, bb_passability); + schema.GameMap.addRubble(builder, bb_rubble); + schema.GameMap.addLead(builder, bb_lead); + + schema.GameMap.addAnomalies(builder, bb_anomalies); + schema.GameMap.addAnomalyRounds(builder, bb_anomalyRounds); + return schema.GameMap.endGameMap(builder); } @@ -210,14 +219,15 @@ function createGameHeader(builder: flatbuffers.Builder): flatbuffers.Offset { for (const body of bodyTypeList) { const btmd = schema.BodyTypeMetadata; if (body in [schema.BodyType.MINER, schema.BodyType.BUILDER, schema.BodyType.SAGE, schema.BodyType.SOLDIER]) { - var gold_costs = btmd.createUpgradeCostGoldVector(builder, [1]) - var lead_costs = btmd.createUpgradeCostLeadVector(builder, [1]) + var gold_costs = [1] + var lead_costs = [1] } else { - var gold_costs = btmd.createUpgradeCostGoldVector(builder, [1,2,3]) - var lead_costs = btmd.createUpgradeCostLeadVector(builder, [1,2,3]) + var gold_costs = [1,2,3] + var lead_costs = [1,2,3] } - bodies.push(btmd.createBodyTypeMetadata(builder, body, body, 10, 10, 2, 6, 10, 10000, 5, 2, 6, 3, gold_costs, lead_costs)); //TODO: make robots interesting + bodies.push(btmd.createBodyTypeMetadata(builder, body, lead_costs[0], gold_costs[0], lead_costs[1], gold_costs[1], lead_costs[2], gold_costs[2], + 10, 10, 2, 6, 10, 3, 5, 11, 4, 6, 10000)); //TODO: make robots interesting } const teams: flatbuffers.Offset[] = []; @@ -234,11 +244,17 @@ function createGameHeader(builder: flatbuffers.Builder): flatbuffers.Offset { const version = builder.createString('IMAGINARY VERSION!!!'); const bodiesPacked = schema.GameHeader.createBodyTypeMetadataVector(builder, bodies); const teamsPacked = schema.GameHeader.createTeamsVector(builder, teams); + + schema.Constants.startConstants(builder); + schema.Constants.addIncreasePeriod(builder, 20); + schema.Constants.addLeadAdditiveIncease(builder, 5); + const constants = schema.Constants.endConstants(builder); schema.GameHeader.startGameHeader(builder); schema.GameHeader.addSpecVersion(builder, version); schema.GameHeader.addBodyTypeMetadata(builder, bodiesPacked); schema.GameHeader.addTeams(builder, teamsPacked); + schema.GameHeader.addConstants(builder, constants); return schema.GameHeader.endGameHeader(builder); } @@ -546,36 +562,31 @@ function createWanderGame(turns: number, unitCount: number, doActions: boolean = let possible_actions = [] switch (bodies.types[j]) { case schema.BodyType.MINER: - action = schema.Action.MINE; + possible_actions = [schema.Action.MINE_GOLD, schema.Action.MINE_LEAD]; // got rid of spawn unit for now because it causes problems break; case schema.BodyType.ARCHON: possible_actions = [schema.Action.FULLY_REPAIRED, schema.Action.TRANSFORM]; // got rid of spawn unit for now because it causes problems - action = possible_actions[Math.floor(Math.random() * possible_actions.length)]; break; case schema.BodyType.SOLDIER: possible_actions = [schema.Action.ATTACK]; - action = possible_actions[Math.floor(Math.random() * possible_actions.length)]; break; case schema.BodyType.BUILDER: - possible_actions = [schema.Action.BUILD, schema.Action.REPAIR, schema.Action.UPGRADE]; - action = possible_actions[Math.floor(Math.random() * possible_actions.length)]; + possible_actions = [schema.Action.REPAIR, schema.Action.MUTATE]; // got rid of spawn unit for now because it causes problems break; case schema.BodyType.LABORATORY: - possible_actions = [schema.Action.CONVERT_GOLD, schema.Action.FULLY_REPAIRED, schema.Action.TRANSFORM]; - action = possible_actions[Math.floor(Math.random() * possible_actions.length)]; + possible_actions = [schema.Action.TRANSMUTE, schema.Action.FULLY_REPAIRED, schema.Action.TRANSFORM]; break; case schema.BodyType.SAGE: possible_actions = [schema.Action.ATTACK, schema.Action.LOCAL_ABYSS, schema.Action.LOCAL_CHARGE, schema.Action.LOCAL_FURY]; - action = possible_actions[Math.floor(Math.random() * possible_actions.length)]; break; case schema.BodyType.WATCHTOWER: possible_actions = [schema.Action.ATTACK, schema.Action.LOCAL_CHARGE, schema.Action.LOCAL_FURY]; - action = possible_actions[Math.floor(Math.random() * possible_actions.length)]; break; default: break; } - let building_target_actions = [schema.Action.REPAIR, schema.Action.UPGRADE] + action = possible_actions[Math.floor(Math.random() * possible_actions.length)]; + let building_target_actions = [schema.Action.REPAIR, schema.Action.MUTATE] if (action !== null) { if (building_target_actions.indexOf(action) > -1){ actionTarget = buildings[Math.floor(Math.random() * buildings.length)]; @@ -597,6 +608,11 @@ function createWanderGame(turns: number, unitCount: number, doActions: boolean = const goldLocs = createVecTable(builder, goldXs, goldYs); const goldVals = schema.Round.createGoldDropValuesVector(builder, [Math.floor(100*Math.random())]); + const leadXs = [Math.floor(SIZE*Math.random())] + const leadYs = [Math.floor(SIZE*Math.random())] + const leadLocs = createVecTable(builder, leadXs, leadYs); + const leadVals = schema.Round.createLeadDropValuesVector(builder, [Math.floor(100*Math.random())]); + schema.Round.startRound(builder); schema.Round.addRoundID(builder, i); schema.Round.addMovedLocs(builder, movedLocs); @@ -607,6 +623,8 @@ function createWanderGame(turns: number, unitCount: number, doActions: boolean = schema.Round.addGoldDropLocations(builder, goldLocs); schema.Round.addGoldDropValues(builder, goldVals); + schema.Round.addLeadDropLocations(builder, leadLocs); + schema.Round.addLeadDropValues(builder, leadVals); events.push(createEventWrapper(builder, schema.Round.endRound(builder), schema.Event.Round)); } @@ -726,17 +744,17 @@ function createSoupGame(turns: number) { function main(){ const games = [ - //{ name: "blank", game: createBlankGame(512)}, - //{ name: "stand", game: createStandGame(4000) }, - //{ name: "pick", game: createPickGame(1024) }, - //{ name: "random-map", game: createBlankGame(512, true) }, - //{ name: "wander", game: createWanderGame(2048, 32) }, + { name: "blank", game: createBlankGame(512)}, + { name: "stand", game: createStandGame(4000) }, + // { name: "pick", game: createPickGame(1024) }, + { name: "random-map", game: createBlankGame(512, true) }, + { name: "wander", game: createWanderGame(2048, 32) }, { name: "wander-actions", game: createWanderGame(2048, 32, true) }, - //{ name: "wander-actions-random-map", game: createWanderGame(2048, 32, true, true)}, - //{ name: "life", game: createLifeGame(512) }, - //{ name: "votes", game: createVotesGame(512) } - //{ name: "soup", game: createSoupGame(512) }, - //{ name: "viewOptions", game: createViewOptionGame(512) } + { name: "wander-actions-random-map", game: createWanderGame(2048, 32, true, true)}, + { name: "life", game: createLifeGame(512) }, + { name: "votes", game: createVotesGame(512) } + // { name: "soup", game: createSoupGame(512) }, + // { name: "viewOptions", game: createViewOptionGame(512) } ]; SIZE = 64; //games.push({ name: "big-wander", game: createWanderGame(2048, 128) }); diff --git a/client/playback/src/legacy/bench/run.ts b/client/playback/src/legacy/bench/run.ts index a45ca9e0..d0e35c65 100644 --- a/client/playback/src/legacy/bench/run.ts +++ b/client/playback/src/legacy/bench/run.ts @@ -3,7 +3,7 @@ import {crunch} from '../simulator'; import {schema, flatbuffers} from 'battlecode-schema'; const wrapper = schema.GameWrapper.getRootAsGameWrapper( - new flatbuffers.ByteBuffer(new Uint8Array(readFileSync('test.bc21'))) + new flatbuffers.ByteBuffer(new Uint8Array(readFileSync('test.bc22'))) ); crunch(wrapper); diff --git a/client/playback/src/legacy/bench/runTimeline.ts b/client/playback/src/legacy/bench/runTimeline.ts index 8c853a73..5f746ff2 100644 --- a/client/playback/src/legacy/bench/runTimeline.ts +++ b/client/playback/src/legacy/bench/runTimeline.ts @@ -4,7 +4,7 @@ import {schema, flatbuffers} from 'battlecode-schema'; import Game from '../../game'; const wrapper = schema.GameWrapper.getRootAsGameWrapper( - new flatbuffers.ByteBuffer(new Uint8Array(readFileSync('test.bc21'))) + new flatbuffers.ByteBuffer(new Uint8Array(readFileSync('test.bc22'))) ); const game = new Game(); diff --git a/client/playback/src/metadata.ts b/client/playback/src/metadata.ts index 578702f5..7c797d0e 100644 --- a/client/playback/src/metadata.ts +++ b/client/playback/src/metadata.ts @@ -20,11 +20,15 @@ export default class Metadata { */ types: {[key: number]: BodyTypeMetaData}; + buildingTypes: schema.BodyType[] = [schema.BodyType.ARCHON, schema.BodyType.LABORATORY, schema.BodyType.WATCHTOWER]; + /** * All the teams in a game. */ teams: {[key: number]: Team}; + constants: schema.Constants; + constructor() { this.specVersion = UNKNOWN_SPEC_VERSION; this.types = Object.create(null); @@ -47,21 +51,26 @@ export default class Metadata { const body = header.bodyTypeMetadata(i); this.types[body.type()] = new BodyTypeMetaData( body.type(), - body.spawnSource(), - body.actionRadiusSquared(), - body.visionRadiusSquared(), + body.buildCostLead(), + body.buildCostGold(), + body.level2CostLead(), + body.level2CostGold(), + body.level3CostLead(), + body.level3CostGold(), body.actionCooldown(), body.movementCooldown(), - body.bytecodeLimit(), - body.dps(), - body.hp(), - body.dpsMul(), - body.hpMul(), - body.buildCost(), - Array.from(body.upgradeCostLeadArray()), - Array.from(body.upgradeCostGoldArray()) + body.health(), + body.level2Health(), + body.level3Health(), + body.damage(), + body.level2Damage(), + body.level3Damage(), + body.actionRadiusSquared(), + body.visionRadiusSquared(), + body.bytecodeLimit() ); } + this.constants = header.constants(); // SAFE Object.freeze(this.types); Object.freeze(this.teams); @@ -92,12 +101,14 @@ export class Team { * Information about a specific body type. */ export class BodyTypeMetaData { - constructor(public type: schema.BodyType, public spawnSource:schema.BodyType, - public actionRadiusSquared:number, public visionRadiusSquared:number, + constructor(public type: schema.BodyType, + public buildCostLead:number, public buildCostGold: number, + public level2CostLead: number, public level2CostGold: number, + public level3CostLead: number, public level3CostGold: number, public actionCooldown:number, public movementCooldown:number, - public bytecodeLimit:number, - public dps:number, public hp:number, public dpsMul:number, public hpMul:number, - public buildCost:number, public upgradeCostLead:number[], - public upgradeCostGold:number[]) { + public health: number, public level2Health: number, public level3Health: number, + public damage: number, public level2Damage: number, public level3Damage: number, + public actionRadiusSquared:number, public visionRadiusSquared:number, + public bytecodeLimit:number) { } } diff --git a/client/visualizer/README.md b/client/visualizer/README.md index e9470223..9a3d5dc2 100644 --- a/client/visualizer/README.md +++ b/client/visualizer/README.md @@ -36,7 +36,7 @@ To watch using a standalone app (Electron): $ npm run electron ``` -When you `npm run electron`, you can set the default file to run when it is launched, by placing `default.bc21` in `/client` folder. So, it's loading `/client/default.bc21` file when it is launched. +When you `npm run electron`, you can set the default file to run when it is launched, by placing `default.bc22` in `/client` folder. So, it's loading `/client/default.bc22` file when it is launched. To run the tests: ```sh @@ -48,7 +48,7 @@ All code and assets go in `src`, which is written in Typescript. Note that we're If you want to add a dependency, run `npm install --save package-name` and then `npm install --save @types/package-name` (for the typescript declarations). If `@types/package-name` doesn't exist, sacrifice a goat, or possibly a grad student. -Also note that this repo doesn't contain all of the client code. See `../playback`; that's the library that actually reads and replays the `.bc21` match files. This repo has everything else; video, sound, controls, etc. +Also note that this repo doesn't contain all of the client code. See `../playback`; that's the library that actually reads and replays the `.bc22` match files. This repo has everything else; video, sound, controls, etc. If you've made a change in `../playback` and want to integrate it here, you need to do `npm install` again. It's a bit of a pain; and should probably be integrated in this folder at some point. diff --git a/client/visualizer/index.html b/client/visualizer/index.html index 394f1370..237cc66e 100644 --- a/client/visualizer/index.html +++ b/client/visualizer/index.html @@ -6,7 +6,7 @@
- + + + + + + +
+

Loading Battlecode client...

+
+ + diff --git a/client/visualizer/webpack.config.js b/client/visualizer/webpack.config.js index d900a3a2..dd2a640f 100644 --- a/client/visualizer/webpack.config.js +++ b/client/visualizer/webpack.config.js @@ -44,8 +44,13 @@ var conf = { ]) ], devServer: { - // Required to ensure the files copied by the CopyWebpackPlugin are copied when running the dev server - writeToDisk: filePath => filePath.includes('speedscope/') + devMiddleware: { + // Required to ensure the files copied by the CopyWebpackPlugin are copied when running the dev server + writeToDisk: filePath => filePath.includes('speedscope/') + }, + static: { + directory: path.join(__dirname, '/'), + }, } }; diff --git a/deploy/deploy-javadoc.sh b/deploy/deploy-javadoc.sh new file mode 100644 index 00000000..f8cbf67c --- /dev/null +++ b/deploy/deploy-javadoc.sh @@ -0,0 +1,33 @@ +# TODO enforce state of repo up-to-date +# TODO enforce `gradle.properties` -- update `release_version`. +# TODO enforce that this update is pushed to master +# TODO note that java is a prereq. + +BUCKET_NAME="bc-game-storage" + +# TODO finish this, once i can actually get javadocs to work. +# Here's scraps of untested code: + +# cd .. +# # Assumes version as second arg to deploy script +# ./gradlew release_docs_zip -Prelease_version=$1 --stacktrace +# mv battlecode-javadoc-$1.zip javadoc.zip +# unzip -d javadoc javadoc.zip +# rm javadoc.zip +# mkdir frontend/public/javadoc +# mv javadoc frontend/public +# cd deploy + +# TODO put this into a bucket, and configure properly, etc + +read -p "IMPORTANT: Ensure that the docs are in the 'javadoc' folder. Press enter to proceed..." + +gsutil -m rm gs://$BUCKET_NAME/javadocs/2022/** +# Upload +cd ../javadoc +gsutil -m cp -r ** gs://$BUCKET_NAME/javadocs/2022/ +cd ../deploy +# Enforce cache policy +gsutil -m setmeta -h "Cache-Control:no-cache" -r gs://$BUCKET_NAME/javadocs/2022/** +# TODO public check +gsutil -m acl ch -u AllUsers:R -r gs://$BUCKET_NAME/javadocs/2022/** diff --git a/deploy/deploy-specs.sh b/deploy/deploy-specs.sh new file mode 100644 index 00000000..841d1d41 --- /dev/null +++ b/deploy/deploy-specs.sh @@ -0,0 +1,28 @@ +# TODO enforce state of repo up-to-date +# TODO enforce the following -- +# Pay attention to the version number at the top of specs.md.html, and to the changelog at the bottom. +# push to master! + +# Note: this script is not in the specs folder, on purpose -- +# I don't want this script to get deployed too. + +BUCKET_NAME="bc-game-storage" + +echo 'Do you wish to deploy these specs to the public? Type public and press enter.' +echo 'IMPORTANT: NEVER DO THIS BEFORE THE GAME IS RELEASED' +read -p 'input: ' ispublic + +# Handle bucket: +# Clean +gsutil -m rm gs://$BUCKET_NAME/specs/2022/** +# Upload +cd ../specs +gsutil -m cp -r ** gs://$BUCKET_NAME/specs/2022/ +cd ../deploy +# Enforce cache policy +gsutil -m setmeta -h "Cache-Control:no-cache" -r gs://$BUCKET_NAME/specs/2022/** +# Make public? +if [ "$ispublic" == 'public' ] +then + gsutil -m acl ch -u AllUsers:R -r gs://$BUCKET_NAME/specs/2022/** +fi diff --git a/engine/build.gradle b/engine/build.gradle index 28e9c605..837f68fd 100644 --- a/engine/build.gradle +++ b/engine/build.gradle @@ -1,5 +1,3 @@ - - apply plugin: 'java' sourceCompatibility = 1.8 @@ -9,20 +7,19 @@ sourceSets { java.srcDirs = ["src/main"] resources.srcDirs = ["src/main"] - java.outputDir = file("$buildDir/classes") + java.destinationDirectory.set(file("$buildDir/classes")) output.resourcesDir = "$buildDir/classes" } test { java.srcDirs = ["src/test"] resources.srcDirs = ["src/test"] - java.outputDir = file("$buildDir/tests") + java.destinationDirectory.set(file("$buildDir/tests")) output.resourcesDir = "$buildDir/tests" } } repositories { - jcenter() mavenCentral() // Java Spatial Index for RTree maven {url "https://oss.sonatype.org/content/repositories/snapshots/"} @@ -30,52 +27,49 @@ repositories { } dependencies { - compile ( - [group: 'org.slf4j', name: 'slf4j-api', version: '1.7.21'], - [group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.21'], + implementation( + [group: 'org.slf4j', name: 'slf4j-api', version: '2.0.6'], + [group: 'org.slf4j', name: 'slf4j-simple', version: '2.0.6'], + [group: 'org.apache.commons', name: 'commons-lang3', version: '3.12.0'], + [group: 'commons-cli', name: 'commons-cli', version: '1.5.0'], + [group: 'commons-io', name: 'commons-io', version: '2.11.0'], - // normal dependencies - [group: 'org.apache.commons', name: 'commons-lang3', version: '3.4'], - [group: 'commons-cli', name: 'commons-cli', version: '1.3.1'], - [group: 'commons-io', name: 'commons-io', version: '2.4'], [group: 'org.ow2.asm', name: 'asm', version: '5.0.4'], [group: 'org.ow2.asm', name: 'asm-tree', version: '5.0.4'], - + // Flatbuffers [group: 'com.google.flatbuffers', name: 'flatbuffers-java', version: '1.11.0'], // Websockets [group: 'org.java-websocket', name: 'Java-WebSocket', version: '1.3.0'], - // we only use WeakIdentityHashMap which doesn't depend on anything - [group: 'org.hibernate', name: 'hibernate-search', version: '3.1.0.GA', transitive: false], + // We only use WeakIdentityHashMap which doesn't depend on anything + [group: 'org.hibernate', name: 'hibernate-search', version: '3.1.0.GA'], // Java Spatial Index, RTree indexing [group: 'net.sf.jsi', name: 'jsi', version: '1.1.0-SNAPSHOT'], [group: 'net.sf.trove4j', name: 'trove4j', version: '3.0.3'], + // Javadoc manipulation libraries + files(System.getenv('JAVA_HOME') + '/lib/tools.jar') ) - // Javadoc manipulation libraries - compile files(System.getenv('JAVA_HOME') + '/lib/tools.jar') - - // Testing dependencies - testCompile ( - [group: 'junit', name: 'junit', version: '4.12'], - [group: 'org.mockito', name: 'mockito-core', version: '1.10.19'], - [group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3'] + testImplementation( + [group: 'junit', name: 'junit', version: '4.13.2'], + [group: 'org.mockito', name: 'mockito-core', version: '3.12.4'] ) } jar { + duplicatesStrategy 'exclude' from { - configurations.testCompile.collect { it.isDirectory() ? it : zipTree(it) } + configurations.runtimeClasspath.findAll { it.name.endsWith('jar') }.collect { zipTree(it) } } } javadoc { includes = ["**/common/**"] - options.windowTitle = "Battlecode 2017" + options.windowTitle = "Battlecode 2022" options.classpath = sourceSets.main.compileClasspath as List options.doclet = "com.sun.tools.doclets.standard.Standard" options.taglets = ["battlecode.doc.CostlyMethodTaglet", "battlecode.doc.RobotTypeTaglet"] diff --git a/engine/src/main/battlecode/common/AnomalyScheduleEntry.java b/engine/src/main/battlecode/common/AnomalyScheduleEntry.java new file mode 100644 index 00000000..5c9df6e4 --- /dev/null +++ b/engine/src/main/battlecode/common/AnomalyScheduleEntry.java @@ -0,0 +1,67 @@ +package battlecode.common; + +/** + * AnomalyScheduleEntry describes a single Anomaly in the Anomaly schedule. The + * schedule of Anomalies is predetermined for each map, and you can retrieve it + * by calling {@link RobotController#getAnomalySchedule}. Each schedule entry + * provides information about the round on which it occurs, and the type of the + * Anomaly. + *

+ * Note that the Singularity is not included in the schedule. You should instead + * check {@link GameConstants#GAME_MAX_NUMBER_OF_ROUNDS}. + */ +public class AnomalyScheduleEntry { + /** + * The round on which this Anomaly will occur. The Anomaly will occur at the + * end of this round, that is, after all robots have taken their turn. + */ + public final int roundNumber; + + /** + * The type of this Anomaly. + */ + public final AnomalyType anomalyType; + + /** + * Constructs an AnomalyScheduleEntry using the given round number and + * Anomaly type. Note that this does not actually insert the Anomaly into + * the schedule, but only creates a local object that you are free to + * manipulate. The global Anomaly schedule is fixed and cannot be changed; + * to envision an Anomaly with a Sage, see {@link RobotController#envision}. + * + * @param round the round number of the Anomaly + * @param type the type of the Anomaly + */ + public AnomalyScheduleEntry(int round, AnomalyType type) { + this.roundNumber = round; + this.anomalyType = type; + } + + /** + * Constructs a copy of this schedule entry. Note that this does not + * actually cause the Anomaly to happen twice, but only creates a local + * object that you are free to manipulate. The global Anomaly schedule is + * fixed and cannot be changed; to envision an Anomaly with a Sage, see + * {@link RobotController#envision}. + * + * @return a copy of this AnomalyScheduleEntry + */ + public AnomalyScheduleEntry copyEntry() { + return new AnomalyScheduleEntry(this.roundNumber, this.anomalyType); + } + + /** + * Returns whether two AnomalyScheduleEntry objects are equivalent. + * + * @param other the AnomalyScheduleEntry to compare with + * @return whether the two AnomalyScheduleEntry objects are equivalent + * + * @battlecode.doc.costlymethod + */ + @Override + public boolean equals(Object other) { + if (other == null || getClass() != other.getClass()) return false; + AnomalyScheduleEntry casted = (AnomalyScheduleEntry) other; + return this.roundNumber == casted.roundNumber && this.anomalyType == casted.anomalyType; + } +} diff --git a/engine/src/main/battlecode/common/AnomalyType.java b/engine/src/main/battlecode/common/AnomalyType.java new file mode 100644 index 00000000..ea40db8d --- /dev/null +++ b/engine/src/main/battlecode/common/AnomalyType.java @@ -0,0 +1,80 @@ +package battlecode.common; + +/** + * AnomalyType represents the type of a scheduled or envisioned Anomaly. You + * can access the type of scheduled Anomalies from + * {@link AnomalyScheduleEntry#anomalyType}, and envision your own Anomalies with + * Sages by using {@link RobotController#envision}. + *

+ * AnomalyType also provides information about the strenghts of each Anomaly, as + * well as other properties. + *

+ * Note that the Singularity is not included in the schedule. You should instead + * check {@link GameConstants#GAME_MAX_NUMBER_OF_ROUNDS}. + */ +public enum AnomalyType { + /** + * Abyss causes proportional amounts of metal resources to be lost. When + * global, the entire map as well as team reserves are affected. When + * envisioned, a local region of the map is affected. + *

+ * {@link #globalPercentage} and {@link #sagePercentage} specify the + * proportion of metals lost. + */ + ABYSS (true, true, 0.1f, 0.99f), + + /** + * Charge deals concentrated damage to Droids. When global, the top + * {@link #globalPercentage} Droids with the most nearby friendly units are + * destroyed. When envisioned, all nearby enemy Droids lose + * {@link #sagePercentage} of their maximum health. + */ + CHARGE (true, true, 0.05f, 0.22f), + + /** + * Fury deals concentrated proportional damage to Turrets. When global, all + * Turrets are affected. When envisioned, a local region is affected. + *

+ * {@link #globalPercentage} and {@link #sagePercentage} specify the + * amount of damage dealt, as a proportion of the Turret's maximum health. + */ + FURY (true, true, 0.05f, 0.1f), + + /** + * Vortex upends the world by transforming the map terrain. It can only + * occur globally. + *

+ * The values of {@link #globalPercentage} and {@link #sagePercentage} are + * unused. + */ + VORTEX (true, false, 0, 0); + + /** + * Whether this type of Anomaly could appear in the global schedule. + */ + public final boolean isGlobalAnomaly; + + /** + * Whether this type of Anomaly could be envisioned by Sages. + */ + public final boolean isSageAnomaly; + + /** + * The strength of this Anomaly when globally scheduled. The precise + * definition of this value depends on the Anomaly type. + */ + public final float globalPercentage; + + /** + * The strength of this Anomaly when envisioned by a Sage. The precise + * definition of this value depends on the Anomaly type. + */ + public final float sagePercentage; + + AnomalyType(boolean isGlobalAnomaly, boolean isSageAnomaly, float globalPercentage, float sagePercentage) { + this.isGlobalAnomaly = isGlobalAnomaly; + this.isSageAnomaly = isSageAnomaly; + this.globalPercentage = globalPercentage; + this.sagePercentage = sagePercentage; + } +} diff --git a/engine/src/main/battlecode/common/BodyInfo.java b/engine/src/main/battlecode/common/BodyInfo.java deleted file mode 100644 index b8f008f4..00000000 --- a/engine/src/main/battlecode/common/BodyInfo.java +++ /dev/null @@ -1,28 +0,0 @@ -package battlecode.common; - -/** - * Stores information about a Object/Body in the game world - */ -public interface BodyInfo { - - /** - * Returns the ID of this body. - * - * @return the ID of this body. - */ - int getID(); - - /** - * Returns the center location of this body. - * - * @return the center location of this body. - */ - MapLocation getLocation(); - - /** - * Returns whether this body is a robot. - * - * @return true if this body is a robot; false otherwise. - */ - boolean isRobot(); -} diff --git a/engine/src/main/battlecode/common/Clock.java b/engine/src/main/battlecode/common/Clock.java index f3bba5ff..bd820a04 100644 --- a/engine/src/main/battlecode/common/Clock.java +++ b/engine/src/main/battlecode/common/Clock.java @@ -3,15 +3,14 @@ import battlecode.instrumenter.inject.RobotMonitor; /** - * Clock is a singleton that allows contestants to introspect the state of their running - * code. + * Clock is a singleton that allows contestants to introspect the state of their + * running code. * * @author james */ @SuppressWarnings("unused") public final class Clock { - - /** + /* * IMPORTANT NOTE! * This class is reloaded for every individual robot. * See Loader for more information. @@ -28,8 +27,8 @@ public static void yield() { /** * Returns the number of bytecodes this robot has left in this round. - * @return the number of bytecodes this robot has left in this round. * + * @return the number of bytecodes this robot has left in this round * @battlecode.doc.costlymethod */ public static int getBytecodesLeft() { @@ -37,11 +36,11 @@ public static int getBytecodesLeft() { } /** - * Returns the number of bytecodes the current robot has executed since the beginning - * of the current round. - * @return the number of bytecodes the current robot has executed since the beginning - * of the current round. + * Returns the number of bytecodes the current robot has executed since the + * beginning of the current round. * + * @return the number of bytecodes the current robot has executed since the + * beginning of the current round * @battlecode.doc.costlymethod */ public static int getBytecodeNum() { diff --git a/engine/src/main/battlecode/common/Direction.java b/engine/src/main/battlecode/common/Direction.java index bcc9a6d0..f8253149 100644 --- a/engine/src/main/battlecode/common/Direction.java +++ b/engine/src/main/battlecode/common/Direction.java @@ -50,9 +50,14 @@ public enum Direction { CENTER(0, 0); /** - * Change in x, change in y. + * Change in x. */ - public final int dx, dy; + public final int dx; + + /** + * Change in y. + */ + public final int dy; Direction(int dx, int dy) { this.dx = dx; @@ -102,9 +107,9 @@ public Direction rotateRight() { /** * Returns a list of all directions. This is equivalent to calling - * Direction.values(). + * {@link Direction#values}. * - * @return array of all directions. + * @return array of all directions */ public static Direction[] allDirections() { return Direction.values(); @@ -113,7 +118,7 @@ public static Direction[] allDirections() { /** * Returns a list of all cardinal directions. * - * @return array of all cardinal directions. + * @return array of all cardinal directions */ public static Direction[] cardinalDirections() { return new Direction[]{Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST}; @@ -122,7 +127,7 @@ public static Direction[] cardinalDirections() { /** * Returns the delta X of the direction. * - * @return the delta X of the direction. + * @return the delta X of the direction */ public int getDeltaX() { return this.dx; @@ -131,9 +136,9 @@ public int getDeltaX() { /** * Returns the delta Y of the direction. * - * @return the delta Y of the direction. + * @return the delta Y of the direction */ public int getDeltaY() { return this.dy; } -} \ No newline at end of file +} diff --git a/engine/src/main/battlecode/common/GameActionException.java b/engine/src/main/battlecode/common/GameActionException.java index 4bf70fd7..cdd92fd8 100644 --- a/engine/src/main/battlecode/common/GameActionException.java +++ b/engine/src/main/battlecode/common/GameActionException.java @@ -35,7 +35,7 @@ public GameActionException(GameActionExceptionType type, String message) { * Gives the type of gameworld interaction that caused this GameActionException, which * was specified when this instance was constructed. * - * @return this GameActionException's type. + * @return this GameActionException's type */ public GameActionExceptionType getType() { return type; diff --git a/engine/src/main/battlecode/common/GameActionExceptionType.java b/engine/src/main/battlecode/common/GameActionExceptionType.java index 0895f729..9db4dd2e 100644 --- a/engine/src/main/battlecode/common/GameActionExceptionType.java +++ b/engine/src/main/battlecode/common/GameActionExceptionType.java @@ -23,7 +23,7 @@ public enum GameActionExceptionType { IS_NOT_READY, /** * Indicates when a robot tries to sense a robot that no longer exists or is no longer - * in this robot's sensor range. + * in this robot's vision range. */ CANT_SENSE_THAT, /** diff --git a/engine/src/main/battlecode/common/GameConstants.java b/engine/src/main/battlecode/common/GameConstants.java index a9d18d7e..f5ad655e 100644 --- a/engine/src/main/battlecode/common/GameConstants.java +++ b/engine/src/main/battlecode/common/GameConstants.java @@ -1,7 +1,7 @@ package battlecode.common; /** - * Defines constants that affect gameplay. + * GameConstants defines constants that affect gameplay. */ @SuppressWarnings("unused") public class GameConstants { @@ -9,81 +9,102 @@ public class GameConstants { /** * The current spec version the server compiles with. */ - public static final String SPEC_VERSION = "1.0"; + public static final String SPEC_VERSION = "2.2.1"; // ********************************* // ****** MAP CONSTANTS ************ // ********************************* /** The minimum possible map height. */ - public static final int MAP_MIN_HEIGHT = 32; + public static final int MAP_MIN_HEIGHT = 20; /** The maximum possible map height. */ - public static final int MAP_MAX_HEIGHT = 64; + public static final int MAP_MAX_HEIGHT = 60; /** The minimum possible map width. */ - public static final int MAP_MIN_WIDTH = 32; + public static final int MAP_MIN_WIDTH = 20; /** The maximum possible map width. */ - public static final int MAP_MAX_WIDTH = 64; + public static final int MAP_MAX_WIDTH = 60; + + /** The minimum number of starting Archons per team. */ + public static final int MIN_STARTING_ARCHONS = 1; + + /** The maximum number of starting Archons per team. */ + public static final int MAX_STARTING_ARCHONS = 4; + + /** The minimum amount of rubble per square. */ + public static final int MIN_RUBBLE = 0; + + /** The maximum amount of rubble per square. */ + public static final int MAX_RUBBLE = 100; // ********************************* // ****** GAME PARAMETERS ********** // ********************************* - /** The number of indicator strings that a player can associate with a robot. */ - public static final int NUMBER_OF_INDICATOR_STRINGS = 3; + /** The maximum length of indicator strings that a player can associate with a robot. */ + public static final int INDICATOR_STRING_MAX_LENGTH = 64; + + /** The length of each team's shared communication array. */ + public static final int SHARED_ARRAY_LENGTH = 64; + + /** The maximum value in shared communication arrays. */ + public static final int MAX_SHARED_ARRAY_VALUE = (1 << 16) - 1; /** The bytecode penalty that is imposed each time an exception is thrown. */ public static final int EXCEPTION_BYTECODE_PENALTY = 500; - ///** Maximum ID a Robot will have */ - //public static final int MAX_ROBOT_ID = 32000; Cannot be guaranteed in Battlecode 2021. + /** The initial amount of lead each team starts with. */ + public static final int INITIAL_LEAD_AMOUNT = 200; - // ********************************* - // ****** COOLDOWNS **************** - // ********************************* - + /** The initial amount of gold each team starts with. */ + public static final int INITIAL_GOLD_AMOUNT = 0; - // ********************************* - // ****** GAME MECHANICS *********** - // ********************************* + /** The amount of lead each team gains per turn. */ + public static final int PASSIVE_LEAD_INCREASE = 2; - /** The amount of conviction taxed when a Politician empowers. */ - public static final int EMPOWER_TAX = 10; + /** The number of rounds between adding lead resources to the map. */ + public static final int ADD_LEAD_EVERY_ROUNDS = 20; - /** The buff factor from exposing Slanderers. */ - public static final double EXPOSE_BUFF_FACTOR = 0.001; + /** The amount of lead to add each round that lead is added. */ + public static final int ADD_LEAD = 5; - /** The number of rounds a buff is applied. */ - public static final int EXPOSE_BUFF_NUM_ROUNDS = 50; + // ********************************* + // ****** COOLDOWNS **************** + // ********************************* - /** The number of rounds Slanderers generate influence. */ - public static final int EMBEZZLE_NUM_ROUNDS = 50; + /** If the amount of cooldown is at least this value, a robot cannot act. */ + public static final int COOLDOWN_LIMIT = 10; - /** The scale factor in the Slanderer embezzle influence formula. */ - public static final float EMBEZZLE_SCALE_FACTOR = 0.03f; + /** The number of cooldown turns reduced per turn. */ + public static final int COOLDOWNS_PER_TURN = 10; - /** The exponential decay factor in the Slanderer embezzle influence formula. */ - public static final float EMBEZZLE_DECAY_FACTOR = 0.001f; + /** The number of cooldown turns per transformation. */ + public static final int TRANSFORM_COOLDOWN = 100; - /** The number of rounds before Slanderers turns into Politicians. */ - public static final int CAMOUFLAGE_NUM_ROUNDS = 300; + /** The number of cooldown turns per mutation. */ + public static final int MUTATE_COOLDOWN = 100; - /** The initial amount of influence for each player-owned Enlightenment Center. */ - public static final int INITIAL_ENLIGHTENMENT_CENTER_INFLUENCE = 150; + // ********************************* + // ****** GAME MECHANICS *********** + // ********************************* - /** The passive influence ratio for Enlightenment Centers. To multiply by sqrt(roundNum). */ - public static final float PASSIVE_INFLUENCE_RATIO_ENLIGHTENMENT_CENTER = 0.2f; + /** A blueprint building's health, as a multiplier of max health. */ + public static final float PROTOTYPE_HP_PERCENTAGE = 0.8f; - /** Maximum allowable robot influence. */ - public static final int ROBOT_INFLUENCE_LIMIT = 100000000; + /** The multiplier for reclaiming a building's cost. */ + public static final float RECLAIM_COST_MULTIPLIER = 0.2f; - /** The minimum allowable flag value. */ - public static final int MIN_FLAG_VALUE = 0; + /** The maximum level a building can be. */ + public static final int MAX_LEVEL = 3; - /** The maximum allowable flag value. */ - public static final int MAX_FLAG_VALUE = 16777215; + /** Constants for alchemists converting lead to gold. */ + public static final double ALCHEMIST_LONELINESS_A = 20; + public static final double ALCHEMIST_LONELINESS_B = 18; + public static final double ALCHEMIST_LONELINESS_K_L1 = 0.02; + public static final double ALCHEMIST_LONELINESS_K_L2 = 0.01; + public static final double ALCHEMIST_LONELINESS_K_L3 = 0.005; // ********************************* // ****** GAMEPLAY PROPERTIES ****** @@ -93,5 +114,5 @@ public class GameConstants { public static final int GAME_DEFAULT_SEED = 6370; /** The maximum number of rounds in a game. **/ - public static final int GAME_MAX_NUMBER_OF_ROUNDS = 1500; + public static final int GAME_MAX_NUMBER_OF_ROUNDS = 2000; } diff --git a/engine/src/main/battlecode/common/MapLocation.java b/engine/src/main/battlecode/common/MapLocation.java index 12884b5d..60ee629e 100644 --- a/engine/src/main/battlecode/common/MapLocation.java +++ b/engine/src/main/battlecode/common/MapLocation.java @@ -138,7 +138,7 @@ public final boolean isAdjacentTo(MapLocation location) { * If location equals this location then the return value is Direction.CENTER. * * @param location The location to which the Direction will be calculated - * @return The Direction to location from this MapLocation. + * @return the Direction to location from this MapLocation * * @battlecode.doc.costlymethod */ diff --git a/engine/src/main/battlecode/common/RobotController.java b/engine/src/main/battlecode/common/RobotController.java index 07a93ec3..aad2034d 100644 --- a/engine/src/main/battlecode/common/RobotController.java +++ b/engine/src/main/battlecode/common/RobotController.java @@ -19,23 +19,34 @@ public strictfp interface RobotController { * match. * * @return the current round number, where round 1 is the first round of the - * match. + * match * * @battlecode.doc.costlymethod */ int getRoundNum(); /** - * Returns the team's total votes. + * Returns the width of the game map. Valid x coordinates range from + * 0 (inclusive) to the width (exclusive). + * + * @return the map width + * + * @battlecode.doc.costlymethod + */ + int getMapWidth(); + + /** + * Returns the height of the game map. Valid y coordinates range from + * 0 (inclusive) to the height (exclusive). * - * @return the team's total votes. + * @return the map height * * @battlecode.doc.costlymethod */ - int getTeamVotes(); + int getMapHeight(); /** - * Returns the number of robots on your team, including Centers of Enlightenment. + * Returns the number of robots on your team, including Archons. * If this number ever reaches zero, you immediately lose. * * @return the number of robots on your team @@ -45,15 +56,34 @@ public strictfp interface RobotController { int getRobotCount(); /** - * Returns the factor from buffs due to exposed enemy slanderers. + * Returns the number of Archons on your team. + * If this number ever reaches zero, you immediately lose. * - * @param team the team to query - * @param roundsInFuture number of rounds into the future, 0 for current buff - * @return the specified team's buff factor. + * @return the number of Archons on your team * * @battlecode.doc.costlymethod */ - double getEmpowerFactor(Team team, int roundsInFuture); + int getArchonCount(); + + /** + * Returns the amount of lead a team has in its reserves. + * + * @param team the team being queried. + * @return the amount of lead a team has in its reserves. + * + * @battlecode.doc.costlymethod + */ + int getTeamLeadAmount(Team team); + + /** + * Returns the amount of gold a team has in its reserves. + * + * @param team the team being queried. + * @return the amount of gold a team has in its reserves. + * + * @battlecode.doc.costlymethod + */ + int getTeamGoldAmount(Team team); // ********************************* // ****** UNIT QUERY METHODS ******* @@ -62,7 +92,7 @@ public strictfp interface RobotController { /** * Returns the ID of this robot. * - * @return the ID of this robot. + * @return the ID of this robot * * @battlecode.doc.costlymethod */ @@ -71,122 +101,121 @@ public strictfp interface RobotController { /** * Returns this robot's Team. * - * @return this robot's Team. + * @return this robot's Team * * @battlecode.doc.costlymethod */ Team getTeam(); /** - * Returns this robot's type (MUCKRAKER, POLITICIAN, SLANDERER, etc.). + * Returns this robot's type (MINER, ARCHON, BUILDER, etc.). * - * @return this robot's type. + * @return this robot's type * * @battlecode.doc.costlymethod */ RobotType getType(); + /** + * Returns this robot's mode (DROID, PROTOTYPE, TURRET, PORTABLE). + * + * @return this robot's mode + * + * @battlecode.doc.costlymethod + */ + RobotMode getMode(); + /** * Returns this robot's current location. * - * @return this robot's current location. + * @return this robot's current location * * @battlecode.doc.costlymethod */ MapLocation getLocation(); /** - * Returns this robot's current influence. + * Returns this robot's current health. * - * @return this robot's current influence. + * @return this robot's current health * * @battlecode.doc.costlymethod */ - int getInfluence(); + int getHealth(); /** - * Returns this robot's current conviction. + * Returns this robot's current level. * - * @return this robot's current conviction. + * @return this robot's current level * * @battlecode.doc.costlymethod */ - int getConviction(); + int getLevel(); // *********************************** - // ****** GENERAL SENSOR METHODS ***** + // ****** GENERAL VISION METHODS ***** // *********************************** /** - * Senses whether a MapLocation is on the map. Will throw an exception if - * the location is not within the sensor range. + * Checks whether a MapLocation is on the map. Will throw an exception if + * the location is not within the vision range. * * @param loc the location to check - * @return true if the location is on the map; false otherwise. - * @throws GameActionException if the location is not within sensor range. + * @return true if the location is on the map; false otherwise + * @throws GameActionException if the location is not within vision range * * @battlecode.doc.costlymethod */ boolean onTheMap(MapLocation loc) throws GameActionException; /** - * Checks whether the given location is within the robot's sensor range, and if it is on the map. + * Checks whether the given location is within the robot's vision range, and if it is on the map. * * @param loc the location to check - * @return true if the given location is within the robot's sensor range and is on the map; false otherwise. + * @return true if the given location is within the robot's vision range and is on the map; false otherwise * * @battlecode.doc.costlymethod */ boolean canSenseLocation(MapLocation loc); /** - * Checks whether a point at the given radius squared is within the robot's sensor range. + * Checks whether a point at the given radius squared is within the robot's vision range. * * @param radiusSquared the radius to check - * @return true if the given radius is within the robot's sensor range; false otherwise. + * @return true if the given radius is within the robot's vision range; false otherwise * * @battlecode.doc.costlymethod */ boolean canSenseRadiusSquared(int radiusSquared); /** - * Checks whether the given location is within the robot's detection range, and if it is on the map. + * Checks whether a robot is at a given location. Assumes the location is valid. * * @param loc the location to check - * @return true if the given location is within the robot's detection range and is on the map; false otherwise. + * @return true if a robot is at the location + * @throws GameActionException if the location is not within vision range or on the map * * @battlecode.doc.costlymethod */ - boolean canDetectLocation(MapLocation loc); - - /** - * Checks whether a point at the given radius squared is within the robot's detection range. - * - * @param radiusSquared the radius to check - * @return true if the given radius is within the robot's detection range; false otherwise. - * - * @battlecode.doc.costlymethod - */ - boolean canDetectRadiusSquared(int radiusSquared); + boolean isLocationOccupied(MapLocation loc) throws GameActionException; /** - * Detects whether there is a robot at the given location. + * Checks whether a robot is at a given location. Assume the location is valid. * * @param loc the location to check - * @return true if there is a robot at the given location; false otherwise. - * @throws GameActionException if the location is not within detection range. + * @return true if a robot is at the location, false if there is no robot or the location can not be sensed. * * @battlecode.doc.costlymethod */ - boolean isLocationOccupied(MapLocation loc) throws GameActionException; + boolean canSenseRobotAtLocation(MapLocation loc); /** * Senses the robot at the given location, or null if there is no robot * there. * * @param loc the location to check - * @return the robot at the given location. - * @throws GameActionException if the location is not within sensor range. + * @return the robot at the given location + * @throws GameActionException if the location is not within vision range * * @battlecode.doc.costlymethod */ @@ -194,11 +223,11 @@ public strictfp interface RobotController { /** * Tests whether the given robot exists and if it is within this robot's - * sensor range. + * vision range. * * @param id the ID of the robot to query - * @return true if the given robot is within this robot's sensor range; - * false otherwise. + * @return true if the given robot is within this robot's vision range and exists; + * false otherwise * * @battlecode.doc.costlymethod */ @@ -208,20 +237,20 @@ public strictfp interface RobotController { * Senses information about a particular robot given its ID. * * @param id the ID of the robot to query - * @return a RobotInfo object for the sensed robot. + * @return a RobotInfo object for the sensed robot * @throws GameActionException if the robot cannot be sensed (for example, - * if it doesn't exist or is out of sensor range). + * if it doesn't exist or is out of vision range) * * @battlecode.doc.costlymethod */ RobotInfo senseRobot(int id) throws GameActionException; /** - * Returns all robots within sensor radius. The objects are returned in no + * Returns all robots within vision radius. The objects are returned in no * particular order. * * @return array of RobotInfo objects, which contain information about all - * the robots you sensed. + * the robots you saw * * @battlecode.doc.costlymethod */ @@ -232,10 +261,10 @@ public strictfp interface RobotController { * robot. The objects are returned in no particular order. * * @param radiusSquared return robots this distance away from the center of - * this robot. If -1 is passed, all robots within sensor radius are returned. - * if radiusSquared is larger than the robot's sensor radius, the sensor - * radius is used. - * @return array of RobotInfo objects of all the robots you sensed. + * this robot; if -1 is passed, all robots within vision radius are returned; + * if radiusSquared is larger than the robot's vision radius, the vision + * radius is used + * @return array of RobotInfo objects of all the robots you saw * * @battlecode.doc.costlymethod */ @@ -246,12 +275,12 @@ public strictfp interface RobotController { * distance of this robot. The objects are returned in no particular order. * * @param radiusSquared return robots this distance away from the center of - * this robot. If -1 is passed, all robots within sensor radius are returned. - * if radiusSquared is larger than the robot's sensor radius, the sensor - * radius is used. - * @param team filter game objects by the given team. If null is passed, + * this robot; if -1 is passed, all robots within vision radius are returned; + * if radiusSquared is larger than the robot's vision radius, the vision + * radius is used + * @param team filter game objects by the given team; if null is passed, * robots from any team are returned - * @return array of RobotInfo objects of all the robots you sensed. + * @return array of RobotInfo objects of all the robots you saw * * @battlecode.doc.costlymethod */ @@ -264,106 +293,295 @@ public strictfp interface RobotController { * * @param center center of the given search radius * @param radiusSquared return robots this distance away from the center of - * this robot. If -1 is passed, all robots within sensor radius are returned. - * if radiusSquared is larger than the robot's sensor radius, the sensor - * radius is used. - * @param team filter game objects by the given team. If null is passed, + * this robot; if -1 is passed, all robots within vision radius are returned; + * if radiusSquared is larger than the robot's vision radius, the vision + * radius is used + * @param team filter game objects by the given team; if null is passed, * objects from all teams are returned - * @return sorted array of RobotInfo objects of the robots you sensed. + * @return sorted array of RobotInfo objects of the robots you saw * * @battlecode.doc.costlymethod */ RobotInfo[] senseNearbyRobots(MapLocation center, int radiusSquared, Team team); /** - * Returns locations of all robots within detection radius. The objects are - * returned in no particular order. + * Given a location, returns the rubble of that location. * - * @return array of MapLocation objects, which are the locations of all the - * robots you detected. + * Higher rubble means that robots on this location may be penalized + * greater cooldowns for making actions. + * + * @param loc the given location + * @return the rubble of that location + * @throws GameActionException if the robot cannot sense the given location * * @battlecode.doc.costlymethod */ - MapLocation[] detectNearbyRobots(); + int senseRubble(MapLocation loc) throws GameActionException; /** - * Returns locations of all robots that can be detected within a certain - * distance of this robot. The objects are returned in no particular order. + * Given a location, returns the lead count of that location. + * + * @param loc the given location + * @return the amount of lead at that location + * @throws GameActionException if the robot cannot sense the given location * - * @param radiusSquared return robots this distance away from the center of - * this robot. If -1 is passed, all robots within detection radius are returned. - * if radiusSquared is larger than the robot's detection radius, the detection - * radius is used. - * @return array of MapLocation objects of all the robots you detected. + * @battlecode.doc.costlymethod + */ + int senseLead(MapLocation loc) throws GameActionException; + + /** + * Given a location, returns the gold count of that location. + * + * @param loc the given location + * @return the amount of gold at that location + * @throws GameActionException if the robot cannot sense the given location * * @battlecode.doc.costlymethod */ - MapLocation[] detectNearbyRobots(int radiusSquared); + int senseGold(MapLocation loc) throws GameActionException; /** - * Returns all robots of a given team that can be detected within a certain - * radius of a specified location. The objects are returned in no particular - * order. + * Return all locations that contain a nonzero amount of lead. * - * @param center center of the given search radius - * @param radiusSquared return robots this distance away from the center of - * this robot. If -1 is passed, all robots within detection radius are returned. - * if radiusSquared is larger than the robot's detection radius, the detection - * radius is used. - * @return array of MapLocation objects of all the robots you detected. + * @return all locations within vision radius that contain a nonzero amount of lead * * @battlecode.doc.costlymethod */ - MapLocation[] detectNearbyRobots(MapLocation center, int radiusSquared); + MapLocation[] senseNearbyLocationsWithLead(); /** - * Given a location, returns the passability of that location. + * Return all locations that contain a nonzero amount of lead, within a + * specified radius of your robot location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. * - * Lower passability means that robots on this location may be penalized - * greater cooldowns for making actions. - * - * @param loc the given location - * @return the passability of that location. - * @throws GameActionException if the robot cannot sense the given location + * @param radiusSquared the squared radius of all locations to be returned + * @return all locations that contain a nonzero amount of lead within the radius + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithLead(int radiusSquared) throws GameActionException; + + /** + * Return all locations that contain a nonzero amount of lead, within a + * specified radius of a center location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. + * + * @param center the center of the search area + * @param radiusSquared the squared radius of all locations to be returned + * @return all locations that contain a nonzero amount of lead within the radius + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithLead(MapLocation center, int radiusSquared) throws GameActionException; + + /** + * Return all locations that contain at least a certain amount of lead, within a + * specified radius of your robot location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. + * + * @param radiusSquared the squared radius of all locations to be returned + * @param minLead the minimum amount of lead + * @return all locations that contain at least minLead lead within the radius + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithLead(int radiusSquared, int minLead) throws GameActionException; + + /** + * Return all locations that contain at least a certain amount of lead, within a + * specified radius of a center location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. + * + * @param center the center of the search area + * @param radiusSquared the squared radius of all locations to be returned + * @param minLead the minimum amount of lead + * @return all locations that contain at least minLead lead within the radius + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithLead(MapLocation center, int radiusSquared, int minLead) throws GameActionException; + + /** + * Return all locations that contain a nonzero amount of gold. + * + * @return all locations within vision radius that contain a nonzero amount of gold + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithGold(); + + /** + * Return all locations that contain a nonzero amount of gold, within a + * specified radius of your robot location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. + * + * @param radiusSquared the squared radius of all locations to be returned + * @return all locations that contain a nonzero amount of gold within the radius + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithGold(int radiusSquared) throws GameActionException; + + /** + * Return all locations that contain a nonzero amount of gold, within a + * specified radius of a center location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. + * + * @param center the center of the search area + * @param radiusSquared the squared radius of all locations to be returned + * @return all locations that contain a nonzero amount of gold within the radius + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithGold(MapLocation center, int radiusSquared) throws GameActionException; + + /** + * Return all locations that contain at least a certain amount of gold, within a + * specified radius of your robot location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. + * + * @param radiusSquared the squared radius of all locations to be returned + * @param minGold the minimum amount of gold + * @return all locations that contain at least minGold gold within the radius + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] senseNearbyLocationsWithGold(int radiusSquared, int minGold) throws GameActionException; + + /** + * Return all locations that contain at least a certain amount of gold, within a + * specified radius of a center location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. If -1 is passed, all locations with vision radius + * are returned. + * + * @param center the center of the search area + * @param radiusSquared the squared radius of all locations to be returned + * @param minGold the minimum amount of gold + * @return all locations that contain at least minGold gold within the radius + * @throws GameActionException if the radius is negative * * @battlecode.doc.costlymethod */ - double sensePassability(MapLocation loc) throws GameActionException; + MapLocation[] senseNearbyLocationsWithGold(MapLocation center, int radiusSquared, int minGold) throws GameActionException; /** * Returns the location adjacent to current location in the given direction. * * @param dir the given direction - * @return the location adjacent to current location in the given direction. + * @return the location adjacent to current location in the given direction * * @battlecode.doc.costlymethod */ MapLocation adjacentLocation(Direction dir); + /** + * Returns a list of all locations within the given radiusSquared of a location. + * If radiusSquared is larger than the robot's vision radius, uses the robot's + * vision radius instead. + * + * Checks that radiusSquared is non-negative. + * + * @param center the given location + * @param radiusSquared return locations within this distance away from center + * @return list of locations on the map and within radiusSquared of center + * @throws GameActionException if the radius is negative + * + * @battlecode.doc.costlymethod + */ + MapLocation[] getAllLocationsWithinRadiusSquared(MapLocation center, int radiusSquared) throws GameActionException; + // *********************************** // ****** READINESS METHODS ********** // *********************************** /** - * Tests whether the robot can perform an action. Returns - * getCooldownTurns() < 1. + * Tests whether the robot can act. + * + * @return true if the robot can act + * + * @battlecode.doc.costlymethod + */ + boolean isActionReady(); + + /** + * Returns the number of action cooldown turns remaining before this unit can act again. + * When this number is strictly less than {@link GameConstants#COOLDOWN_LIMIT}, isActionReady() + * is true and the robot can act again. This number decreases by + * {@link GameConstants#COOLDOWNS_PER_TURN} every turn. + * + * @return the number of action turns remaining before this unit can act again + * + * @battlecode.doc.costlymethod + */ + int getActionCooldownTurns(); + + /** + * Tests whether the robot can move. + * + * @return true if the robot can move + * + * @battlecode.doc.costlymethod + */ + boolean isMovementReady(); + + /** + * Returns the number of movement cooldown turns remaining before this unit can move again. + * When this number is strictly less than {@link GameConstants#COOLDOWN_LIMIT}, isMovementReady() + * is true and the robot can move again. This number decreases by + * {@link GameConstants#COOLDOWNS_PER_TURN} every turn. + * + * @return the number of cooldown turns remaining before this unit can move again + * + * @battlecode.doc.costlymethod + */ + int getMovementCooldownTurns(); + + /** + * Tests whether the robot can transform. + * + * Checks if the robot's mode is TURRET or PORTABLE. Also checks action + * or movement cooldown turns, depending on the robot's current mode. * - * @return true if the robot can perform an action. + * @return true if the robot can transform * * @battlecode.doc.costlymethod */ - boolean isReady(); + boolean isTransformReady(); /** - * Returns the number of cooldown turns remaining before this unit can act again. - * When this number is strictly less than 1, isReady() is true and the robot - * can perform actions again. + * Returns the number of cooldown turns remaining before this unit can transform again. + * When this number is strictly less than {@link GameConstants#COOLDOWN_LIMIT}, isTransformReady() + * is true and the robot can transform again. This number decreases by + * {@link GameConstants#COOLDOWNS_PER_TURN} every turn. * - * @return the number of cooldown turns remaining before this unit can act again. + * @return the number of cooldown turns remaining before this unit can transform again + * @throws GameActionException if the robot's mode is not TURRET or PORTABLE * * @battlecode.doc.costlymethod */ - double getCooldownTurns(); + int getTransformCooldownTurns() throws GameActionException; // *********************************** // ****** MOVEMENT METHODS *********** @@ -371,9 +589,9 @@ public strictfp interface RobotController { /** * Checks whether this robot can move one step in the given direction. - * Returns false if the robot is a building, if the target location is not - * on the map, if the target location is occupied, or if there are cooldown - * turns remaining. + * Returns false if the robot is not in a mode that can move, if the target + * location is not on the map, if the target location is occupied, or if + * there are cooldown turns remaining. * * @param dir the direction to move in * @return true if it is possible to call move without an exception @@ -387,9 +605,8 @@ public strictfp interface RobotController { * * @param dir the direction to move in * @throws GameActionException if the robot cannot move one step in this - * direction, such as cooldown being >= 1, the target location being - * off the map, or the target destination being occupied by - * another robot. + * direction, such as cooldown being too high, the target location being + * off the map, or the target destination being occupied by another robot * * @battlecode.doc.costlymethod */ @@ -404,190 +621,308 @@ public strictfp interface RobotController { * given direction. Checks that the robot is of a type that can build, * that the robot can build the desired type, that the target location is * on the map, that the target location is not occupied, that the robot has - * the amount of influence it's trying to spend, and that there are no + * the amount of lead/gold it's trying to spend, and that there are no * cooldown turns remaining. * * @param type the type of robot to build * @param dir the direction to build in - * @param influence the amount of influence to spend * @return whether it is possible to build a robot of the given type in the - * given direction. + * given direction * * @battlecode.doc.costlymethod */ - boolean canBuildRobot(RobotType type, Direction dir, int influence); + boolean canBuildRobot(RobotType type, Direction dir); /** * Builds a robot of the given type in the given direction. * * @param type the type of robot to build * @param dir the direction to spawn the unit - * @param influence the amount of influence to be used to build * @throws GameActionException if the conditions of canBuildRobot - * are not all satisfied. + * are not all satisfied * * @battlecode.doc.costlymethod */ - void buildRobot(RobotType type, Direction dir, int influence) throws GameActionException; + void buildRobot(RobotType type, Direction dir) throws GameActionException; - // *********************************** - // ****** POLITICIAN METHODS ********* - // *********************************** + // ***************************** + // **** COMBAT UNIT METHODS **** + // ***************************** /** - * Tests whether the robot can empower. - * Checks that the robot is a politician, if there are no cooldown turns - * remaining, and that the specified radiusSquared is valid. + * Tests whether this robot can attack the given location. * - * @param radiusSquared the empower range - * @return whether the robot can empower with the given range + * Checks that the robot is an attacking type unit and that the given location + * is within the robot's reach (based on attack type). Also checks that an + * enemy unit exists in the given square, and there are no cooldown turns remaining. + * + * @param loc target location to attack + * @return whether it is possible to attack the given location + * + * @battlecode.doc.costlymethod + */ + boolean canAttack(MapLocation loc); + + /** + * Attack a given location. + * + * @param loc the target location to attack + * @throws GameActionException if conditions for attacking are not satisfied * * @battlecode.doc.costlymethod */ - boolean canEmpower(int radiusSquared); + void attack(MapLocation loc) throws GameActionException; + + // ***************************** + // ******** SAGE METHODS ******* + // ***************************** /** - * Runs the "empower" ability of a politician. + * Tests whether this robot can envision an anomaly centered at the robot's location. + * + * Checks that the robot is a sage, and there are no cooldown turns remaining. * - * Friendly units will have conviction increased, and unfriendly units will - * have conviction decreased. Enemy politicians and buildings with negative conviction - * will join your team. + * @param anomaly the type of anomaly being queried + * @return whether it is possible to envision an anomaly centered at the robots location + * + * @battlecode.doc.costlymethod + */ + boolean canEnvision(AnomalyType anomaly); + + /** + * Envision an anomaly centered at the robot's location. * - * This also causes the politician unit to self-destruct on this turn. + * @param anomaly the type of anomaly to envision + * @throws GameActionException if conditions for envisioning are not satisfied * - * @throws GameActionException if conditions for empowering are not all satisfied * @battlecode.doc.costlymethod */ - void empower(int radiusSquared) throws GameActionException; - - // *********************************** - // ****** MUCKRAKER METHODS ********** - // *********************************** + void envision(AnomalyType anomaly) throws GameActionException; + + // ***************************** + // ****** REPAIR METHODS ****** + // ***************************** /** - * Tests whether the robot can expose at a given location. - * Checks that the robot is a muckraker, that the location is within action - * radius of the muckraker, that there are no cooldown turns remaining, and - * that an enemy slanderer is present on the location. + * Tests whether this robot can repair a robot at the given location. + * + * Checks that the robot can repair other units and that the given location + * is within the robot's action radius. Also checks that a friendly unit + * of a repairable type exists in the given square, and there are no + * cooldown turns remaining. * - * @param loc the location being exposed - * @return whether it is possible to expose on that round at that location + * @param loc target location to repair at + * @return whether it is possible to repair a robot at the given location * * @battlecode.doc.costlymethod */ - boolean canExpose(MapLocation loc); + boolean canRepair(MapLocation loc); - /** - * Tests whether the robot can expose a given robot ID. - * Checks that the robot is a muckraker, that the target robot is within - * action radius of the muckraker, that the target robot is an enemy - * slanderer, and that there are no cooldown turns remaining. + /** + * Repairs at a given location. * - * @param id the robot ID being exposed - * @return whether it is possible to expose that robot on that round + * @param loc target location to repair at + * @throws GameActionException if conditions for repairing are not satisfied * * @battlecode.doc.costlymethod */ - boolean canExpose(int id); + void repair(MapLocation loc) throws GameActionException; + + // *********************** + // **** MINER METHODS **** + // *********************** /** - * Exposes a slanderer at a given location. - * The slanderer will be destroyed, and all attempts to empower by friendly - * Politicians will be temporarily buffed by a multiplicative factor. + * Tests whether the robot can mine lead at a given location. + * + * Checks that the robot is a Miner, and the given location is a valid + * mining location. Valid mining locations must be the current location + * or adjacent to the current location. Valid mining locations must also + * have positive lead amounts. Also checks that no cooldown turns remain. + * + * @param loc target location to mine + * @return whether it is possible to mine at the given location + * + * @battlecode.doc.costlymethod + */ + boolean canMineLead(MapLocation loc); + + /** + * Mine lead at a given location. * - * @throws GameActionException if conditions for exposing are not all satisfied + * @param loc target location to mine + * @throws GameActionException if conditions for mining are not satisfied * * @battlecode.doc.costlymethod */ - void expose(MapLocation loc) throws GameActionException; + void mineLead(MapLocation loc) throws GameActionException; /** - * Exposes a slanderer with given id. - * The slanderer will be destroyed, and all attempts to empower by friendly - * Politicians will be temporarily buffed by a multiplicative factor. + * Tests whether the robot can mine gold at a given location. + * + * Checks that the robot is a Miner, that the given location is a valid + * mining location. Valid mining locations must be the current location + * or adjacent to the current location. Valid mining locations must also + * have positive gold amounts. Also checks that no cooldown turns remain. * - * @throws GameActionException if conditions for exposing are not all satisfied + * @param loc target location to mine + * @return whether it is possible to mine at the given location * * @battlecode.doc.costlymethod */ - void expose(int id) throws GameActionException; + boolean canMineGold(MapLocation loc); + /** + * Mine a gold at given location. + * + * @param loc target location to mine + * @throws GameActionException if conditions for mining are not satisfied + * + * @battlecode.doc.costlymethod + */ + void mineGold(MapLocation loc) throws GameActionException; - // ************************************** - // **** ENLIGHTENMENT CENTER METHODS **** - // ************************************** + // ************************* + // **** MUTATE METHODS **** + // ************************* /** - * Tests whether the robot can bid the specified amount of influence on that round. + * Tests whether this robot can mutate the building at the given location. * - * Checks that the robot is an Enlightenment Center, that the robot has at least - * that amount of influence, and that the amount of influence is non-negative. + * Checks that the robot is a Builder, that the given location is a valid + * mutate location. Valid mutate locations must be adjacent to the current + * location and contain a mutable building. The mutation must also be + * affordable, and there must be no cooldown turns remaining. * - * @param influence the amount of influence being bid - * @return whether it is possible to bid that amount of influence. + * @param loc target location to mutate + * @return whether it is possible to mutate at the given location * * @battlecode.doc.costlymethod */ - boolean canBid(int influence); + boolean canMutate(MapLocation loc); /** - * Enter an influence bid for the vote on that turn. + * Mutate a building at a given location. * - * @throws GameActionException if conditions for bidding are not satisfied - * @battlecode.doc.costlymethod + * @param loc target location of the building to mutate + * @throws GameActionException if conditions for mutating are not satisfied + * + * @battlecode.doc.costlymethod */ - void bid(int influence) throws GameActionException; + void mutate(MapLocation loc) throws GameActionException; - // *********************************** - // ****** COMMUNICATION METHODS ****** - // *********************************** + // *************************** + // **** TRANSMUTE METHODS **** + // *************************** + + /** + * Get lead to gold transmutation rate. + * + * @return the lead to gold transmutation rate, 0 if the robot is not a lab + * + * @battlecode.doc.costlymethod + */ + public int getTransmutationRate(); + + /** + * Get lead to gold transmutation rate for a laboratory of specified level. + * + * @param laboratory_level the level of the laboratory + * @return the lead to gold transmutation rate, 0 if the level is invalid + * + * @battlecode.doc.costlymethod + */ + public int getTransmutationRate(int laboratory_level); /** - * Checks whether the robot can set the flag to a specified integer. + * Tests whether this robot can transmute lead into gold. + * + * Checks that the robot is a lab and the player has sufficient lead to + * perform a conversion. Also checks that no cooldown turns remain. * - * @return whether the robot can set the flag to the specified integer. + * @return whether it is possible to transmute lead into gold + * + * @battlecode.doc.costlymethod */ - boolean canSetFlag(int flag); + boolean canTransmute(); /** - * Sets a robot's flag to an integer. + * Transmute lead into gold. * - * @param flag the flag value. - * @throws GameActionException if the specified integer is not a valid flag + * @throws GameActionException if conditions for transmuting are not satisfied * * @battlecode.doc.costlymethod */ - void setFlag(int flag) throws GameActionException; + void transmute() throws GameActionException; + + // *************************** + // **** TRANSFORM METHODS **** + // *************************** /** - * Given a robot's ID, checks if a robot can get the flag of that robot. + * Tests whether this robot can transform. Same effect as isTransformReady(). * - * Checks that a robot exists, and that either (a) the robot is an Enlightenment - * Center or (b) the target robot is within sensor range. + * @return whether it is possible to transform * - * @param id the target robot's ID - * @return whether it is possible to get the robot's flag + * @battlecode.doc.costlymethod + */ + boolean canTransform(); + + /** + * Transform from turret into portable or vice versa. + * + * @throws GameActionException if conditions for transforming are not satisfied * * @battlecode.doc.costlymethod */ - boolean canGetFlag(int id); + void transform() throws GameActionException; + + // *********************************** + // ****** COMMUNICATION METHODS ****** + // *********************************** /** - * Given a robot's ID, returns the flag of the robot. + * Given an index, returns the value at that index in the team array. * - * @param id the target robot's ID - * @throws GameActionException if conditions for getting the flag are not satisfied - * @return the flag of the robot + * @param index the index in the team's shared array, 0-indexed + * @return the value at that index in the team's shared array, + * @throws GameActionException if the index is invalid * * @battlecode.doc.costlymethod */ - int getFlag(int id) throws GameActionException; + int readSharedArray(int index) throws GameActionException; + /** + * Sets a team's array value at a specified index. + * No change occurs if the index or value is invalid. + * + * @param index the index in the team's shared array, 0-indexed + * @param value the value to set that index to + * @throws GameActionException if the index is invalid, or the value + * is out of bounds + * + * @battlecode.doc.costlymethod + */ + void writeSharedArray(int index, int value) throws GameActionException; // *********************************** // ****** OTHER ACTION METHODS ******* // *********************************** + /** + * @return the anomaly schedule + * + * @battlecode.doc.costlymethod + */ + AnomalyScheduleEntry[] getAnomalySchedule(); + + /** + * Destroys the robot. + * + * @battlecode.doc.costlymethod + **/ + void disintegrate(); + /** * Causes your team to lose the game. It's like typing "gg." * @@ -599,13 +934,23 @@ public strictfp interface RobotController { // ******** DEBUG METHODS ************ // *********************************** + /** + * Sets the indicator string for this robot for debugging purposes. Only the first + * {@link GameConstants#INDICATOR_STRING_MAX_LENGTH} characters are used. + * + * @param string the indicator string this round + * + * @battlecode.doc.costlymethod + */ + void setIndicatorString(String string); + /** * Draw a dot on the game map for debugging purposes. * - * @param loc the location to draw the dot. - * @param red the red component of the dot's color. - * @param green the green component of the dot's color. - * @param blue the blue component of the dot's color. + * @param loc the location to draw the dot + * @param red the red component of the dot's color + * @param green the green component of the dot's color + * @param blue the blue component of the dot's color * * @battlecode.doc.costlymethod */ @@ -614,11 +959,11 @@ public strictfp interface RobotController { /** * Draw a line on the game map for debugging purposes. * - * @param startLoc the location to draw the line from. - * @param endLoc the location to draw the line to. - * @param red the red component of the line's color. - * @param green the green component of the line's color. - * @param blue the blue component of the line's color. + * @param startLoc the location to draw the line from + * @param endLoc the location to draw the line to + * @param red the red component of the line's color + * @param green the green component of the line's color + * @param blue the blue component of the line's color * * @battlecode.doc.costlymethod */ diff --git a/engine/src/main/battlecode/common/RobotInfo.java b/engine/src/main/battlecode/common/RobotInfo.java index da7ab4ae..39bf872d 100644 --- a/engine/src/main/battlecode/common/RobotInfo.java +++ b/engine/src/main/battlecode/common/RobotInfo.java @@ -1,142 +1,160 @@ -package battlecode.common; - -/** - * Struct that stores basic information that was 'sensed' of another Robot. This - * info is ephemeral and there is no guarantee any of it will remain the same - * between rounds. - */ -public class RobotInfo { - - /** - * The unique ID of the robot. - */ - public final int ID; - - /** - * The Team that the robot is on. - */ - public final Team team; - - /** - * The type of the robot. - */ - public final RobotType type; - - /** - * The influence of the robot. - */ - public final int influence; - - /** - * The conviction of the robot. - */ - public final int conviction; - - /** - * The current location of the robot. - */ - public final MapLocation location; - - public RobotInfo(int ID, Team team, RobotType type, int influence, int conviction, MapLocation location) { - super(); - this.ID = ID; - this.team = team; - this.type = type; - this.influence = influence; - this.conviction = conviction; - this.location = location; - } - - /** - * Returns the ID of this robot. - * - * @return the ID of this robot - */ - public int getID() { - return this.ID; - } - - /** - * Returns the team that this robot is on. - * - * @return the team that this robot is on. - */ - public Team getTeam() { - return team; - } - - /** - * Returns the type of this robot. - * - * @return the type of this robot. - */ - public RobotType getType() { - return type; - } - - /** - * Returns the influence of this robot. - * - * @return the influence of this robot - */ - public int getInfluence() { - return influence; - } - - /** - * Returns the conviction of this robot. - * - * @return the conviction of this robot - */ - public int getConviction() { - return conviction; - } - - /** - * Returns the location of this robot. - * - * @return the location of this robot - */ - public MapLocation getLocation() { - return this.location; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - RobotInfo robotInfo = (RobotInfo) o; - - if (ID != robotInfo.ID) return false; - if (team != robotInfo.team) return false; - if (type != robotInfo.type) return false; - if (influence != robotInfo.influence) return false; - if (conviction != robotInfo.conviction) return false; - return location.equals(robotInfo.location); - } - - @Override - public int hashCode() { - int result; - result = ID; - result = 31 * result + team.hashCode(); - result = 31 * result + type.ordinal(); - result = 31 * result + influence; - result = 31 * result + conviction; - result = 31 * result + location.hashCode(); - return result; - } - - @Override - public String toString() { - return "RobotInfo{" + - "ID=" + ID + - ", team=" + team + - ", type=" + type + - ", influence=" + influence + - ", conviction=" + conviction + - ", location=" + location + - '}'; - } -} +package battlecode.common; + +/** + * RobotInfo stores basic information that was 'sensed' of another Robot. This + * info is ephemeral and there is no guarantee any of it will remain the same + * between rounds. + */ +public class RobotInfo { + + /** + * The unique ID of the robot. + */ + public final int ID; + + /** + * The Team that the robot is on. + */ + public final Team team; + + /** + * The type of the robot. + */ + public final RobotType type; + + /** + * The mode of the robot. + */ + public final RobotMode mode; + + /** + * The level of the robot. + */ + public final int level; + + /** + * The health of the robot. + */ + public final int health; + + /** + * The current location of the robot. + */ + public final MapLocation location; + + public RobotInfo(int ID, Team team, RobotType type, RobotMode mode, int level, int health, MapLocation location) { + super(); + this.ID = ID; + this.team = team; + this.type = type; + this.mode = mode; + this.level = level; + this.health = health; + this.location = location; + } + + /** + * Returns the ID of this robot. + * + * @return the ID of this robot + */ + public int getID() { + return this.ID; + } + + /** + * Returns the team that this robot is on. + * + * @return the team that this robot is on + */ + public Team getTeam() { + return team; + } + + /** + * Returns the type of this robot. + * + * @return the type of this robot + */ + public RobotType getType() { + return type; + } + + /** + * Returns the mode of this robot. + * + * @return the mode of this robot + */ + public RobotMode getMode() { + return mode; + } + + /** + * Returns the level of this robot. + * + * @return the level of this robot + */ + public int getLevel() { + return level; + } + + /** + * Returns the health of this robot. + * + * @return the health of this robot + */ + public int getHealth() { + return health; + } + + /** + * Returns the location of this robot. + * + * @return the location of this robot + */ + public MapLocation getLocation() { + return this.location; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + RobotInfo robotInfo = (RobotInfo) o; + + if (ID != robotInfo.ID) return false; + if (team != robotInfo.team) return false; + if (type != robotInfo.type) return false; + if (mode != robotInfo.mode) return false; + if (level != robotInfo.level) return false; + if (health != robotInfo.health) return false; + return location.equals(robotInfo.location); + } + + @Override + public int hashCode() { + int result; + result = ID; + result = 31 * result + team.hashCode(); + result = 31 * result + type.ordinal(); + result = 31 * result + mode.ordinal(); + result = 31 * result + level; + result = 31 * result + health; + result = 31 * result + location.hashCode(); + return result; + } + + @Override + public String toString() { + return "RobotInfo{" + + "ID=" + ID + + ", team=" + team + + ", type=" + type + + ", mode=" + mode + + ", level=" + level + + ", health=" + health + + ", location=" + location + + '}'; + } +} diff --git a/engine/src/main/battlecode/common/RobotMode.java b/engine/src/main/battlecode/common/RobotMode.java new file mode 100644 index 00000000..2e909ebe --- /dev/null +++ b/engine/src/main/battlecode/common/RobotMode.java @@ -0,0 +1,57 @@ +package battlecode.common; + +/** + * Enumerates the modes that a robot could possibly be in. The mode of a robot + * determines the set of interactions with the world that it can currently + * perform legally. + *

+ * You can check the mode of another robot by inspecting {@link RobotInfo#mode}, + * or your own mode by inspecting {@link RobotController#getMode}. + */ +public enum RobotMode { + /** + * The Droid mode describes all Droid robots. These robots can always act + * and move, as long as their cooldowns permit. + */ + DROID (true, true, false), + + /** + * The Prototype mode describes newly-constructed Buildings. These robots + * cannot do anything until they have been repaired to full health by a + * Builder. + */ + PROTOTYPE (false, false, false), + + /** + * The Turret mode describes Buildings in Turret mode. These robots can act, + * but not move. Turrets can also transform into Portable mode. + */ + TURRET (true, false, true), + + /** + * The Portable mode describes Buildings in Portable mode. These robots can + * move, but not act. Portables can also transform into Turret mode. + */ + PORTABLE (false, true, true); + + /** + * Whether robots in this mode may perform actions other than moving. + */ + public final boolean canAct; + + /** + * Whether robots in this mode may move. + */ + public final boolean canMove; + + /** + * Whether robots in this mode may transform to another mode. + */ + public final boolean canTransform; + + RobotMode(boolean canAct, boolean canMove, boolean canTransform) { + this.canAct = canAct; + this.canMove = canMove; + this.canTransform = canTransform; + } +} diff --git a/engine/src/main/battlecode/common/RobotType.java b/engine/src/main/battlecode/common/RobotType.java index 4e2e8952..e829bd1d 100644 --- a/engine/src/main/battlecode/common/RobotType.java +++ b/engine/src/main/battlecode/common/RobotType.java @@ -1,90 +1,127 @@ package battlecode.common; /** - * Contains details on various attributes of the different robots. All of this information is in the specs in a more organized form. + * Enumerates the possible types of robots. More information about the + * capabilities of each robot type are available in the game specs. + * + * You can check the type of another robot by inspecting {@link RobotInfo#type}, + * or your own type by inspecting {@link RobotController#getType}. */ public enum RobotType { - // spawnSource, convictionRatio, actionCooldown, initialCooldown, actionRadiusSquared, sensorRadiusSquared, detectionRadiusSquared, bytecodeLimit + // Build Cost Lead, Build Cost Gold, Action Cooldown, Movement Cooldown + // Health (level 1), Damage (level 1), Action Radius (squared), Vision Radius (squared), Bytecode Limit + + /** + * Archons are the headquarters of your army. They are Buildings that can + * build and repair Droids. + * + * @battlecode.doc.robottype + */ + ARCHON ( 0, 100, 10, 24, 600, -2, 20, 34, 20000), + // BCL BCG AC MC HP DMG AR VR BL + /** - * Enlightenment Centers produce various types of robots, as well as - * passively generate influence and bid for votes each round. Can be - * converted by Politicians. - * + * Laboratories house the magic of the alchemist. They are Buildings that + * can transmute lead into gold. + * * @battlecode.doc.robottype */ - ENLIGHTENMENT_CENTER (null, 1, 2, 0, 2, 40, 40, 20000), - // SS CR AC IC AR SR DR BL + LABORATORY (180, 0, 10, 24, 100, 0, 0, 53, 5000), + // BCL BCG AC MC HP DMG AR VR BL + /** - * Politicians Empower adjacent units, strengthening friendly robots, - * converting enemy Politicians and Enlightenment Centers, and destroying - * enemy Slanderers and Muckrakers with their impassioned speeches. + * Watchtowers are defensive strongholds. They are Buildings that can + * attack robots that stray too close. * * @battlecode.doc.robottype */ - POLITICIAN (ENLIGHTENMENT_CENTER, 1, 1, 10, 9, 25, 25, 15000), - // SS CR AC IC AR SR DR BL + WATCHTOWER (150, 0, 10, 24, 150, 4, 20, 34, 10000), + // BCL BCG AC MC HP DMG AR VR BL + + /** + * Miners are resource-collecting robots. They are Droids that can mine lead + * or gold at their or an adjacent location. + * + * @battlecode.doc.robottype + */ + MINER ( 50, 0, 2, 20, 40, 0, 2, 20, 10000), + // BCL BCG AC MC HP DMG AR VR BL + + /** + * Builders are resource-spending robots. They are Droids that can build, + * repair and mutate Buildings. + * + * @battlecode.doc.robottype + */ + BUILDER ( 40, 0, 10, 20, 30, -2, 5, 20, 7500), + // BCL BCG AC MC HP DMG AR VR BL + /** - * Slanderers passively generate influence for their parent Enlightenment - * Center each round. They are camoflauged as Politicians to enemy units. - * Can be converted by Politicians. + * Soldiers are general-purpose attacking robots. They are Droids that can + * attack robots within a range. * * @battlecode.doc.robottype */ - SLANDERER (ENLIGHTENMENT_CENTER, 1, 2, 0, 0, 20, 20, 7500), - // SS CR AC IC AR SR DR BL + SOLDIER ( 75, 0, 10, 16, 50, 3, 13, 20, 10000), + // BCL BCG AC MC HP DMG AR VR BL + /** - * Muckrakers search the map for enemy Slanderers to Expose, which destroys - * the Slanderer and gives a buff to their team. + * Sages are wise robots with extraordinary abilities. They are Droids + * fashioned out of pure gold, able to envision Anomalies to the detriment + * of the enemy. * * @battlecode.doc.robottype */ - MUCKRAKER (ENLIGHTENMENT_CENTER, 0.7f, 1.5f, 10, 12, 30, 40, 15000), - // SS CR AC IC AR SR DR BL + SAGE ( 0, 20, 200, 25, 100, 45, 25, 34, 10000) + // BCL BCG AC MC HP DMG AR VR BL ; - + /** - * For units, this is the structure that spawns it. For non-spawnable robots, this is null. + * Lead cost to build a given robot or building. */ - public final RobotType spawnSource; + public final int buildCostLead; /** - * The ratio of influence to apply when determining the - * robot's conviction. + * Gold cost to build a given robot or building. */ - public final float convictionRatio; + public final int buildCostGold; /** - * Cooldown turns for how long before a robot can take - * action (Build/Move/Empower/Expose) again. + * The action cooldown applied to the robot per action. + */ + public final int actionCooldown; + + /** + * The movement cooldown applied to the robot per move. */ - public final float actionCooldown; + public final int movementCooldown; /** - * Initial cooldown turns when a robot is built. + * The maximum health for a Level 1 robot of this type. + * + * @see #getMaxHealth */ - public final float initialCooldown; + public final int health; /** - * Radius squared range of robots' abilities. For Politicians, this is - * the AoE range of their Empower ability. For Muckrakers, this is - * from how far they can Expose a Slanderer. + * The damage per attack for a Level 1 robot of this type. This value is + * negative for robots with repairing abilities. + * + * @see #getDamage */ - public final int actionRadiusSquared; + public final int damage; /** - * The radius squared range in which the robot can sense another - * robot's information. For Politicians, Slanderers, and - * Enlightenment Centers, this is the same as their detection - * radius squared. For Muckrakers, slightly reduced. + * Radius range of robots' abilities. */ - public final int sensorRadiusSquared; + public final int actionRadiusSquared; /** - * The radius squared range in which the robot can detect the presence - * of other robots. + * The radius range in which the robot can sense another + * robot's information. */ - public final int detectionRadiusSquared; + public final int visionRadiusSquared; /** * Base bytecode limit of this robot. @@ -92,138 +129,268 @@ public enum RobotType { public final int bytecodeLimit; /** - * Returns whether the type can build robots of the specified type. + * Returns whether this type can build a robot of another given type. * - * @param type the RobotType to be built - * @return whether the type can build robots of the specified type + * @param builtType type of robot being built + * @return whether this type can build the given robot type + * + * @battlecode.doc.costlymethod */ - public boolean canBuild(RobotType type) { - return this == type.spawnSource; + public boolean canBuild(RobotType builtType) { + return (this == ARCHON && (builtType == MINER || + builtType == BUILDER || + builtType == SOLDIER || + builtType == SAGE)) || + (this == BUILDER && (builtType == LABORATORY || + builtType == WATCHTOWER)); } /** - * Returns whether the type can distinguish slanderers and politicians. + * Returns whether this type can attack. * - * @return whether the type can distinguish slanderers and politicians. + * @return whether this type can attack + * @battlecode.doc.costlymethod */ - public boolean canTrueSense() { - return this == ENLIGHTENMENT_CENTER || this == MUCKRAKER; + public boolean canAttack() { + return (this == WATCHTOWER + || this == SOLDIER + || this == SAGE); } /** - * Returns whether the type can apply a teamwide buff. + * Returns whether this type can envision Anomalies. * - * @return whether the type can apply a teamwide buff + * @return whether this type can envision Anomalies + * @battlecode.doc.costlymethod */ - public boolean canBuffTeam() { - return this == MUCKRAKER; + public boolean canEnvision() { + return this == SAGE; } /** - * Returns whether the type can move. + * Returns whether this type can repair another robot of a given type. + * + * @param repairedType type of robot being repaired + * @return whether this type can repair the given robot type * - * @return whether the type can move + * @battlecode.doc.costlymethod */ - public boolean canMove() { - return this == POLITICIAN || this == SLANDERER || this == MUCKRAKER; + public boolean canRepair(RobotType repairedType) { + return ((this == ARCHON && !repairedType.isBuilding()) || + (this == BUILDER && repairedType.isBuilding())); } /** - * Returns whether the type can Empower adjacent units. + * Returns whether this type can mine for metal. * - * @return whether the type can Empower adjacent units + * @return whether this type can mine for metal + * @battlecode.doc.costlymethod */ - public boolean canEmpower() { - return this == POLITICIAN; + public boolean canMine() { + return this == MINER; } /** - * Returns whether the type can camouflage themselves. + * Returns whether this type can mutate another robot of a given type. * - * @return whether the type can camouflage themselves + * @param mutatedType type of robot being mutated + * @return whether this type can mutate another robot of a given type + * + * @battlecode.doc.costlymethod */ - public boolean canCamouflage() { - return this == SLANDERER; + public boolean canMutate(RobotType mutatedType) { + return this == BUILDER && mutatedType.isBuilding(); } /** - * Returns whether the type can Expose nearby robots. + * Returns whether this type can transmute lead into gold. * - * @return whether the type can Expose nearby robots + * @return whether this type can transmute lead into gold + * @battlecode.doc.costlymethod */ - public boolean canExpose() { - return this == MUCKRAKER; + public boolean canTransmute() { + return this == LABORATORY; } /** - * Returns whether the type can be Exposed. + * Returns whether or not a given robot is a Building. * - * @return whether the type can be Exposed + * @return whether or not a given robot is a Building + * @battlecode.doc.costlymethod */ - public boolean canBeExposed() { - return this == SLANDERER; + public boolean isBuilding() { + return ( + this == ARCHON + || this == LABORATORY + || this == WATCHTOWER + ); } /** - * Returns whether the type can be converted to the other team. + * Returns the max health of a robot by level. + * + * @param level of the robot + * @return the max health of a robot by level + * + * @battlecode.doc.costlymethod + */ + public int getMaxHealth(int level) { + if (!this.isBuilding() || level == 1) { + return this.health; + } else if (this == ARCHON) { + return level == 2 ? 1080 : 1944; + } else if (this == LABORATORY) { + return level == 2 ? 180 : 324; + } else { + return level == 2 ? 270 : 486; + } + } + + /** + * Determine the damage power of a robot by level. + * + * @param level The specific level of the robot. + * @return the damage for a robot by level, negative if robot repairs * - * @return whether the type can be converted to the other team + * @battlecode.doc.costlymethod */ - public boolean canBeConverted() { - return this == ENLIGHTENMENT_CENTER || this == POLITICIAN; + public int getDamage(int level) { + if (!this.isBuilding() || level == 1) { + return this.damage; + } else if (this == RobotType.ARCHON) { + return level == 2 ? -4 : -6; + } else if (this == RobotType.LABORATORY) { + return 0; + } else { + return level == 2 ? 8 : 12; + } } /** - * Returns whether the type can submit a bid. - * - * @return whether the type can submit a bid + * Determine the repairing power of a robot by level. + * + * @param level The specific level of the robot. + * @return the repair per turn for a robot by level as a positive amount, + * or 0 if robot doesn't repair + * + * @battlecode.doc.costlymethod */ - public boolean canBid() { - return this == ENLIGHTENMENT_CENTER; + public int getHealing(int level) { + if (this == ARCHON || this == BUILDER) { + return (int) (-1 * this.getDamage(level)); + } else { + return 0; + } } + // COST RELATED FUNCTIONS + /** - * Returns the influence cost for building a robot with a particular conviction. + * Determine the lead cost of Mutating this robot to a specific level. + * + * @param level the level to mutate to + * @return lead cost to mutate, unspecified if mutation is invalid + * + * @battlecode.doc.costlymethod */ - public int getInfluenceCostForConviction(int conviction) { - int influence = (int) (conviction / this.convictionRatio); - while (Math.ceil(this.convictionRatio * (influence - 1)) >= conviction) - influence--; - return influence; + public int getLeadMutateCost(int level) { + if (level != 2) { + return 0; + } + switch (this) { + case ARCHON: return 300; + case WATCHTOWER: return 150; + case LABORATORY: return 150; + default: return 0; + } } /** - * Returns the amount of passive influence that this robot generates. + * Determine the gold cost of Mutating this robot to a specific level. * - * @param robotInfluence the amount of influence that this robot has - * @param roundsAlive the number of rounds the robot has been alive for - * @param roundNum the round number + * @param level the level to mutate to + * @return gold cost to mutate, unspecified if mutation is invalid + * + * @battlecode.doc.costlymethod */ - public int getPassiveInfluence(int robotInfluence, int roundsAlive, int roundNum) { + public int getGoldMutateCost(int level) { + if (level != 3) { + return 0; + } switch (this) { - case ENLIGHTENMENT_CENTER: - return (int) Math.ceil(GameConstants.PASSIVE_INFLUENCE_RATIO_ENLIGHTENMENT_CENTER * Math.sqrt(roundNum)); - case SLANDERER: - if (roundsAlive <= GameConstants.EMBEZZLE_NUM_ROUNDS) - return (int) (robotInfluence * - (1.0 / GameConstants.EMBEZZLE_NUM_ROUNDS + - GameConstants.EMBEZZLE_SCALE_FACTOR * Math.exp(-GameConstants.EMBEZZLE_DECAY_FACTOR * robotInfluence))); - return 0; - default: - return 0; + case ARCHON: return 80; + case WATCHTOWER: return 60; + case LABORATORY: return 25; + default: return 0; + } + } + + /** + * Determine the robot's net worth in lead. + * + * @param level the robot's current level + * @return lead component of worth + * + * @battlecode.doc.costlymethod + */ + public int getLeadWorth(int level) { + int leadWorth = this.buildCostLead; + for (int i = 2; i <= level; i++) { + leadWorth += this.getLeadMutateCost(i); } + return leadWorth; + } + + /** + * Determine the robot's net worth in gold. + * + * @param level the robot's current level + * @return gold component of worth + * + * @battlecode.doc.costlymethod + */ + public int getGoldWorth(int level) { + int goldWorth = this.buildCostGold; + for (int i = 2; i <= level; i++) { + goldWorth += this.getGoldMutateCost(i); + } + return goldWorth; + } + + /** + * Determine the amount of lead dropped if this robot dies. + * + * @param level the robot's current level + * @return the amount of lead dropped + * + * @battlecode.doc.costlymethod + */ + public int getLeadDropped(int level) { + return (int) (this.getLeadWorth(level) * GameConstants.RECLAIM_COST_MULTIPLIER); + } + + /** + * Determine the amount of gold dropped if this robot dies. + * + * @param level the robot's current level + * @return the amount of gold dropped + * + * @battlecode.doc.costlymethod + */ + public int getGoldDropped(int level) { + return (int) (this.getGoldWorth(level) * GameConstants.RECLAIM_COST_MULTIPLIER); } - RobotType(RobotType spawnSource, float convictionRatio, float actionCooldown, float initialCooldown, - int actionRadiusSquared, int sensorRadiusSquared, int detectionRadiusSquared, - int bytecodeLimit) { - this.spawnSource = spawnSource; - this.convictionRatio = convictionRatio; - this.actionCooldown = actionCooldown; - this.initialCooldown = initialCooldown; - this.actionRadiusSquared = actionRadiusSquared; - this.sensorRadiusSquared = sensorRadiusSquared; - this.detectionRadiusSquared = detectionRadiusSquared; - this.bytecodeLimit = bytecodeLimit; + RobotType(int buildCostLead, int buildCostGold, int actionCooldown, int movementCooldown, + int health, int damage, int actionRadiusSquared, int visionRadiusSquared, int bytecodeLimit) { + this.buildCostLead = buildCostLead; + this.buildCostGold = buildCostGold; + this.actionCooldown = actionCooldown; + this.movementCooldown = movementCooldown; + this.health = health; + this.damage = damage; + this.actionRadiusSquared = actionRadiusSquared; + this.visionRadiusSquared = visionRadiusSquared; + this.bytecodeLimit = bytecodeLimit; } } diff --git a/engine/src/main/battlecode/doc/RobotTypeTaglet.java b/engine/src/main/battlecode/doc/RobotTypeTaglet.java index 17ee8ed1..2cdb93c5 100644 --- a/engine/src/main/battlecode/doc/RobotTypeTaglet.java +++ b/engine/src/main/battlecode/doc/RobotTypeTaglet.java @@ -52,7 +52,7 @@ public boolean isInlineTag() { return false; } - public String toString(Tag tag){ + public String toString(Tag tag) { throw new IllegalArgumentException("The robot tag may not be used inline."); } @@ -177,21 +177,21 @@ public String docFor(String variant) { StringBuilder builder = new StringBuilder(); try { - appendField(builder, rt, "convictionRatio"); + appendField(builder, rt, "buildCostLead"); + builder.append("
"); + appendField(builder, rt, "buildCostGold"); builder.append("
"); appendField(builder, rt, "actionCooldown"); builder.append("
"); - appendField(builder, rt, "actionRadiusSquared"); + appendField(builder, rt, "movementCooldown"); builder.append("
"); - appendField(builder, rt, "sensorRadiusSquared"); + appendField(builder, rt, "health"); builder.append("
"); - appendField(builder, rt, "detectionRadiusSquared"); - - if (rt.spawnSource != null) { - builder.append("
"); - appendField(builder, rt, "spawnSource"); - // appendField(builder, rt, "cost"); Cost is variable in 2021 - } + appendField(builder, rt, "damage"); + builder.append("
"); + appendField(builder, rt, "actionRadiusSquared"); + builder.append("
"); + appendField(builder, rt, "visionRadiusSquared"); if (rt.bytecodeLimit != 0) { builder.append("
"); diff --git a/engine/src/main/battlecode/instrumenter/bytecode/InstrumentingMethodVisitor.java b/engine/src/main/battlecode/instrumenter/bytecode/InstrumentingMethodVisitor.java index 5f350673..5ab0e4ae 100644 --- a/engine/src/main/battlecode/instrumenter/bytecode/InstrumentingMethodVisitor.java +++ b/engine/src/main/battlecode/instrumenter/bytecode/InstrumentingMethodVisitor.java @@ -280,8 +280,8 @@ private void addDebugHandler() { private void addRobotDeathHandler() { LabelNode robotDeathLabel = new LabelNode(new Label()); LabelNode firstTryCatch = null; - for(AbstractInsnNode node : instructions.toArray()) { - if(node.getType()==AbstractInsnNode.LABEL&&tryCatchStarts.contains(node)) { + for (AbstractInsnNode node : instructions.toArray()) { + if (node.getType()==AbstractInsnNode.LABEL&&tryCatchStarts.contains(node)) { firstTryCatch = (LabelNode)node; break; } @@ -436,7 +436,7 @@ private void visitMethodInsnNode(MethodInsnNode n) { } if (n.owner.equals("java/lang/String")) { - if((n.name.equals("")&&n.desc.equals("([B)V")) + if ((n.name.equals("")&&n.desc.equals("([B)V")) ||(n.name.equals("")&&n.desc.equals("([BII)V")) ||(n.name.equals("getBytes")&&n.desc.equals("()[B"))) { instructions.insertBefore(n,new LdcInsnNode("UTF-16")); diff --git a/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt b/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt index df2611d9..7241ccf5 100644 --- a/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt +++ b/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt @@ -1,72 +1,112 @@ -battlecode/common/Clock/yield 0 true -battlecode/common/Clock/getBytecodesLeft 0 true -battlecode/common/Clock/getBytecodeNum 0 true -battlecode/common/Direction/equals 1 false -battlecode/common/Direction/getDeltaX 1 false -battlecode/common/Direction/getDeltaY 1 false -battlecode/common/Direction/rotateLeft 1 false -battlecode/common/Direction/rotateRight 1 false -battlecode/common/Direction/opposite 1 false -battlecode/common/Direction/allDirections 1 false -battlecode/common/Direction/cardinalDirections 1 false -battlecode/common/MapLocation/add 2 false -battlecode/common/MapLocation/compareTo 2 false -battlecode/common/MapLocation/directionTo 2 false -battlecode/common/MapLocation/distanceSquaredTo 2 false -battlecode/common/MapLocation/equals 2 false -battlecode/common/MapLocation/hashCode 2 false -battlecode/common/MapLocation/isWithinDistanceSquared 2 false -battlecode/common/MapLocation/isAdjacentTo 2 false -battlecode/common/MapLocation/isWithinSensorRadius 2 false -battlecode/common/MapLocation/subtract 2 false -battlecode/common/MapLocation/toString 2 false -battlecode/common/MapLocation/translate 2 false -battlecode/common/MapLocation/valueOf 25 false -battlecode/common/RobotController/adjacentLocation 1 true -battlecode/common/RobotController/bid 1 true -battlecode/common/RobotController/buildRobot 0 true -battlecode/common/RobotController/canBid 10 true -battlecode/common/RobotController/canBuildRobot 10 true -battlecode/common/RobotController/canDetectLocation 5 true -battlecode/common/RobotController/canDetectRadiusSquared 5 true -battlecode/common/RobotController/canEmpower 10 true -battlecode/common/RobotController/canExpose 10 true -battlecode/common/RobotController/canGetFlag 5 true -battlecode/common/RobotController/canMove 10 true -battlecode/common/RobotController/canSenseLocation 5 true -battlecode/common/RobotController/canSenseRadiusSquared 5 true -battlecode/common/RobotController/canSenseRobot 5 true -battlecode/common/RobotController/detectNearbyRobots 100 true -battlecode/common/RobotController/empower 0 true -battlecode/common/RobotController/expose 0 true -battlecode/common/RobotController/getConviction 1 true -battlecode/common/RobotController/getCooldownTurns 1 true -battlecode/common/RobotController/getEmpowerFactor 1 true -battlecode/common/RobotController/getFlag 5 true -battlecode/common/RobotController/getID 1 true -battlecode/common/RobotController/getInfluence 1 true -battlecode/common/RobotController/getLocation 1 true -battlecode/common/RobotController/getRobotCount 20 true -battlecode/common/RobotController/getRoundNum 1 true -battlecode/common/RobotController/getTeam 1 true -battlecode/common/RobotController/getTeamVotes 1 true -battlecode/common/RobotController/getType 1 true -battlecode/common/RobotController/isLocationOccupied 20 true -battlecode/common/RobotController/isReady 1 true -battlecode/common/RobotController/move 0 true -battlecode/common/RobotController/onTheMap 5 true -battlecode/common/RobotController/resign 0 true -battlecode/common/RobotController/senseNearbyRobots 100 true -battlecode/common/RobotController/sensePassability 1 true -battlecode/common/RobotController/senseRobot 25 true -battlecode/common/RobotController/senseRobotAtLocation 25 true -battlecode/common/RobotController/setFlag 100 true -battlecode/common/RobotController/setIndicatorDot 0 true -battlecode/common/RobotController/setIndicatorLine 0 true -battlecode/common/RobotType/getInfluenceCostForConviction 1 false -battlecode/common/RobotType/getPassiveInfluence 1 false -battlecode/common/Team/opponent 1 false -battlecode/common/Team/isPlayer 1 false +battlecode/common/AnomalyScheduleEntry/equals 2 false +battlecode/common/Clock/yield 0 true +battlecode/common/Clock/getBytecodesLeft 0 false +battlecode/common/Clock/getBytecodeNum 0 false +battlecode/common/Direction/equals 1 false +battlecode/common/Direction/getDeltaX 1 false +battlecode/common/Direction/getDeltaY 1 false +battlecode/common/Direction/rotateLeft 1 false +battlecode/common/Direction/rotateRight 1 false +battlecode/common/Direction/opposite 1 false +battlecode/common/Direction/allDirections 1 false +battlecode/common/Direction/cardinalDirections 1 false +battlecode/common/MapLocation/add 2 false +battlecode/common/MapLocation/compareTo 2 false +battlecode/common/MapLocation/directionTo 2 false +battlecode/common/MapLocation/distanceSquaredTo 2 false +battlecode/common/MapLocation/equals 2 false +battlecode/common/MapLocation/hashCode 2 false +battlecode/common/MapLocation/isWithinDistanceSquared 2 false +battlecode/common/MapLocation/isAdjacentTo 2 false +battlecode/common/MapLocation/isWithinSensorRadius 2 false +battlecode/common/MapLocation/subtract 2 false +battlecode/common/MapLocation/toString 2 false +battlecode/common/MapLocation/translate 2 false +battlecode/common/MapLocation/valueOf 25 false +battlecode/common/RobotController/adjacentLocation 1 true +battlecode/common/RobotController/attack 0 true +battlecode/common/RobotController/buildRobot 0 true +battlecode/common/RobotController/canAttack 10 true +battlecode/common/RobotController/canBuildRobot 10 true +battlecode/common/RobotController/canEnvision 10 true +battlecode/common/RobotController/canMineGold 10 true +battlecode/common/RobotController/canMineLead 10 true +battlecode/common/RobotController/canMove 10 true +battlecode/common/RobotController/canMutate 10 true +battlecode/common/RobotController/canRepair 10 true +battlecode/common/RobotController/canSenseLocation 5 true +battlecode/common/RobotController/canSenseRadiusSquared 5 true +battlecode/common/RobotController/canSenseRobot 5 true +battlecode/common/RobotController/canSenseRobotAtLocation 5 true +battlecode/common/RobotController/canTransform 10 true +battlecode/common/RobotController/canTransmute 10 true +battlecode/common/RobotController/disintegrate 0 true +battlecode/common/RobotController/envision 0 true +battlecode/common/RobotController/getActionCooldownTurns 1 true +battlecode/common/RobotController/getAllLocationsWithinRadiusSquared 100 true +battlecode/common/RobotController/getAnomalySchedule 100 true +battlecode/common/RobotController/getArchonCount 20 true +battlecode/common/RobotController/getHealth 1 true +battlecode/common/RobotController/getID 1 true +battlecode/common/RobotController/getLevel 1 true +battlecode/common/RobotController/getLocation 1 true +battlecode/common/RobotController/getMapHeight 1 true +battlecode/common/RobotController/getMapWidth 1 true +battlecode/common/RobotController/getMode 1 true +battlecode/common/RobotController/getMovementCooldownTurns 1 true +battlecode/common/RobotController/getRobotCount 20 true +battlecode/common/RobotController/getRoundNum 1 true +battlecode/common/RobotController/getTeam 1 true +battlecode/common/RobotController/getTeamGoldAmount 1 true +battlecode/common/RobotController/getTeamLeadAmount 1 true +battlecode/common/RobotController/getTransformCooldownTurns 1 true +battlecode/common/RobotController/getTransmutationRate 20 true +battlecode/common/RobotController/getType 1 true +battlecode/common/RobotController/isActionReady 1 true +battlecode/common/RobotController/isLocationOccupied 20 true +battlecode/common/RobotController/isMovementReady 1 true +battlecode/common/RobotController/isTransformReady 1 true +battlecode/common/RobotController/mineGold 0 true +battlecode/common/RobotController/mineLead 0 true +battlecode/common/RobotController/move 0 true +battlecode/common/RobotController/mutate 0 true +battlecode/common/RobotController/onTheMap 5 true +battlecode/common/RobotController/readSharedArray 2 true +battlecode/common/RobotController/repair 0 true +battlecode/common/RobotController/resign 0 true +battlecode/common/RobotController/senseGold 5 true +battlecode/common/RobotController/senseLead 5 true +battlecode/common/RobotController/senseNearbyLocationsWithLead 100 true +battlecode/common/RobotController/senseNearbyLocationsWithGold 100 true +battlecode/common/RobotController/senseNearbyRobots 100 true +battlecode/common/RobotController/senseRobot 25 true +battlecode/common/RobotController/senseRobotAtLocation 25 true +battlecode/common/RobotController/senseRubble 5 true +battlecode/common/RobotController/setIndicatorDot 0 true +battlecode/common/RobotController/setIndicatorLine 0 true +battlecode/common/RobotController/setIndicatorString 0 true +battlecode/common/RobotController/transform 0 true +battlecode/common/RobotController/transmute 0 true +battlecode/common/RobotController/writeSharedArray 100 true +battlecode/common/RobotType/canAttack 1 false +battlecode/common/RobotType/canBuild 1 false +battlecode/common/RobotType/canEnvision 1 false +battlecode/common/RobotType/canMine 1 false +battlecode/common/RobotType/canMutate 1 false +battlecode/common/RobotType/canRepair 1 false +battlecode/common/RobotType/canTransmute 1 false +battlecode/common/RobotType/getDamage 1 false +battlecode/common/RobotType/getGoldDropped 1 false +battlecode/common/RobotType/getGoldMutateCost 1 false +battlecode/common/RobotType/getGoldWorth 1 false +battlecode/common/RobotType/getHealing 1 false +battlecode/common/RobotType/getLeadDropped 1 false +battlecode/common/RobotType/getLeadMutateCost 1 false +battlecode/common/RobotType/getLeadWorth 1 false +battlecode/common/RobotType/getMaxHealth 1 false +battlecode/common/RobotType/isBuilding 1 false +battlecode/common/Team/opponent 1 false +battlecode/common/Team/isPlayer 1 false java/lang/Math/IEEEremainder 1 false java/lang/Math/abs 1 false java/lang/Math/acos 1 false diff --git a/engine/src/main/battlecode/schema-old/Action.java b/engine/src/main/battlecode/schema-old/Action.java new file mode 100644 index 00000000..ffd303b8 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/Action.java @@ -0,0 +1,77 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +/** + * Actions that can be performed. + * Purely aesthetic; have no actual effect on simulation. + * (Although the simulation may want to track the 'parents' of + * particular robots.) + * Actions may have 'targets', which are the units on which + * the actions were performed. + */ +public final class Action { + private Action() { } + /** + * Politicians self-destruct and affect nearby bodies. + * Target: radius squared + */ + public static final byte EMPOWER = 0; + /** + * Slanderers passively generate influence for the + * Enlightenment Center that created them. + * Target: parent ID + */ + public static final byte EMBEZZLE = 1; + /** + * Slanderers turn into Politicians. + * Target: none + */ + public static final byte CAMOUFLAGE = 2; + /** + * Muckrakers can expose a slanderer. + * Target: an enemy body + */ + public static final byte EXPOSE = 3; + /** + * Units can change their flag. + * Target: new flag value + */ + public static final byte SET_FLAG = 4; + /** + * Builds a unit. + * Target: spawned unit + */ + public static final byte SPAWN_UNIT = 5; + /** + * Places a bid. + * Target: bid value + */ + public static final byte PLACE_BID = 6; + /** + * A robot can change team after being empowered, + * or when a Enlightenment Center is taken over. + * Target: new robotID + */ + public static final byte CHANGE_TEAM = 7; + /** + * A robot's influence changes. + * Target: delta value + */ + public static final byte CHANGE_INFLUENCE = 8; + /** + * A robot's conviction changes. + * Target: delta value, i.e. red 5 -> blue 3 is -2 + */ + public static final byte CHANGE_CONVICTION = 9; + /** + * Dies due to an uncaught exception. + * Target: none + */ + public static final byte DIE_EXCEPTION = 10; + + public static final String[] names = { "EMPOWER", "EMBEZZLE", "CAMOUFLAGE", "EXPOSE", "SET_FLAG", "SPAWN_UNIT", "PLACE_BID", "CHANGE_TEAM", "CHANGE_INFLUENCE", "CHANGE_CONVICTION", "DIE_EXCEPTION", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/engine/src/main/battlecode/schema-old/BodyType.java b/engine/src/main/battlecode/schema-old/BodyType.java new file mode 100644 index 00000000..2d4ae7ab --- /dev/null +++ b/engine/src/main/battlecode/schema-old/BodyType.java @@ -0,0 +1,34 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +/** + * The possible types of things that can exist. + * Note that bullets are not treated as bodies. + */ +public final class BodyType { + private BodyType() { } + /** + * Enlightenment centers produce politicians, Muckrakers and slanderers and place bids + *can be neutral until captured + */ + public static final byte ENLIGHTENMENT_CENTER = 0; + /** + * politicians use their influence to self destruct and capture other units + */ + public static final byte POLITICIAN = 1; + /** + * slanderers generate passive influence for the enlightenment center that created them + * they turn into politicians at some point, and can only be identified by slanderers. + */ + public static final byte SLANDERER = 2; + /** + * have the ability to identify slanderers + */ + public static final byte MUCKRAKER = 3; + + public static final String[] names = { "ENLIGHTENMENT_CENTER", "POLITICIAN", "SLANDERER", "MUCKRAKER", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/engine/src/main/battlecode/schema-old/BodyTypeMetadata.java b/engine/src/main/battlecode/schema-old/BodyTypeMetadata.java new file mode 100644 index 00000000..a2825c7c --- /dev/null +++ b/engine/src/main/battlecode/schema-old/BodyTypeMetadata.java @@ -0,0 +1,88 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * Metadata about all bodies of a particular type. + */ +public final class BodyTypeMetadata extends Table { + public static BodyTypeMetadata getRootAsBodyTypeMetadata(ByteBuffer _bb) { return getRootAsBodyTypeMetadata(_bb, new BodyTypeMetadata()); } + public static BodyTypeMetadata getRootAsBodyTypeMetadata(ByteBuffer _bb, BodyTypeMetadata obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public BodyTypeMetadata __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The relevant type. + */ + public byte type() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } + /** + * The spawn source. + */ + public byte spawnSource() { int o = __offset(6); return o != 0 ? bb.get(o + bb_pos) : 0; } + /** + * the convictionRatio of this type + */ + public float convictionRatio() { int o = __offset(8); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } + /** + * cooldown of this type + */ + public float actionCooldown() { int o = __offset(10); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } + /** + * action radius if this type + */ + public int actionRadiusSquared() { int o = __offset(12); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * sensor radius squared for this type + */ + public int sensorRadiusSquared() { int o = __offset(14); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * detection radius of this type + */ + public int detectionRadiusSquared() { int o = __offset(16); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * bytecode limit for this type + */ + public int bytecodeLimit() { int o = __offset(18); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + + public static int createBodyTypeMetadata(FlatBufferBuilder builder, + byte type, + byte spawnSource, + float convictionRatio, + float actionCooldown, + int actionRadiusSquared, + int sensorRadiusSquared, + int detectionRadiusSquared, + int bytecodeLimit) { + builder.startObject(8); + BodyTypeMetadata.addBytecodeLimit(builder, bytecodeLimit); + BodyTypeMetadata.addDetectionRadiusSquared(builder, detectionRadiusSquared); + BodyTypeMetadata.addSensorRadiusSquared(builder, sensorRadiusSquared); + BodyTypeMetadata.addActionRadiusSquared(builder, actionRadiusSquared); + BodyTypeMetadata.addActionCooldown(builder, actionCooldown); + BodyTypeMetadata.addConvictionRatio(builder, convictionRatio); + BodyTypeMetadata.addSpawnSource(builder, spawnSource); + BodyTypeMetadata.addType(builder, type); + return BodyTypeMetadata.endBodyTypeMetadata(builder); + } + + public static void startBodyTypeMetadata(FlatBufferBuilder builder) { builder.startObject(8); } + public static void addType(FlatBufferBuilder builder, byte type) { builder.addByte(0, type, 0); } + public static void addSpawnSource(FlatBufferBuilder builder, byte spawnSource) { builder.addByte(1, spawnSource, 0); } + public static void addConvictionRatio(FlatBufferBuilder builder, float convictionRatio) { builder.addFloat(2, convictionRatio, 0.0f); } + public static void addActionCooldown(FlatBufferBuilder builder, float actionCooldown) { builder.addFloat(3, actionCooldown, 0.0f); } + public static void addActionRadiusSquared(FlatBufferBuilder builder, int actionRadiusSquared) { builder.addInt(4, actionRadiusSquared, 0); } + public static void addSensorRadiusSquared(FlatBufferBuilder builder, int sensorRadiusSquared) { builder.addInt(5, sensorRadiusSquared, 0); } + public static void addDetectionRadiusSquared(FlatBufferBuilder builder, int detectionRadiusSquared) { builder.addInt(6, detectionRadiusSquared, 0); } + public static void addBytecodeLimit(FlatBufferBuilder builder, int bytecodeLimit) { builder.addInt(7, bytecodeLimit, 0); } + public static int endBodyTypeMetadata(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/Event.java b/engine/src/main/battlecode/schema-old/Event.java new file mode 100644 index 00000000..ccfb7cd9 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/Event.java @@ -0,0 +1,44 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +/** + * Events + * An Event is a single step that needs to be processed. + * A saved game simply consists of a long list of Events. + * Events can be divided by either being sent separately (e.g. as separate + * websocket messages), or by being wrapped with a GameWrapper. + * A game consists of a series of matches; a match consists of a series of + * rounds, and is played on a single map. Each round is a single simulation + * step. + */ +public final class Event { + private Event() { } + public static final byte NONE = 0; + /** + * There should only be one GameHeader, at the start of the stream. + */ + public static final byte GameHeader = 1; + /** + * There should be one MatchHeader at the start of each match. + */ + public static final byte MatchHeader = 2; + /** + * A single simulation step. A round may be skipped if + * nothing happens during its time. + */ + public static final byte Round = 3; + /** + * There should be one MatchFooter at the end of each simulation step. + */ + public static final byte MatchFooter = 4; + /** + * There should only be one GameFooter, at the end of the stream. + */ + public static final byte GameFooter = 5; + + public static final String[] names = { "NONE", "GameHeader", "MatchHeader", "Round", "MatchFooter", "GameFooter", }; + + public static String name(int e) { return names[e]; } +} + diff --git a/engine/src/main/battlecode/schema-old/EventWrapper.java b/engine/src/main/battlecode/schema-old/EventWrapper.java new file mode 100644 index 00000000..d3377ac7 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/EventWrapper.java @@ -0,0 +1,40 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * Necessary due to flatbuffers requiring unions to be wrapped in tables. + */ +public final class EventWrapper extends Table { + public static EventWrapper getRootAsEventWrapper(ByteBuffer _bb) { return getRootAsEventWrapper(_bb, new EventWrapper()); } + public static EventWrapper getRootAsEventWrapper(ByteBuffer _bb, EventWrapper obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public EventWrapper __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public byte eType() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } + public Table e(Table obj) { int o = __offset(6); return o != 0 ? __union(obj, o) : null; } + + public static int createEventWrapper(FlatBufferBuilder builder, + byte e_type, + int eOffset) { + builder.startObject(2); + EventWrapper.addE(builder, eOffset); + EventWrapper.addEType(builder, e_type); + return EventWrapper.endEventWrapper(builder); + } + + public static void startEventWrapper(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addEType(FlatBufferBuilder builder, byte eType) { builder.addByte(0, eType, 0); } + public static void addE(FlatBufferBuilder builder, int eOffset) { builder.addOffset(1, eOffset, 0); } + public static int endEventWrapper(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/GameFooter.java b/engine/src/main/battlecode/schema-old/GameFooter.java new file mode 100644 index 00000000..70bab946 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/GameFooter.java @@ -0,0 +1,39 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * The final event sent in the game. + */ +public final class GameFooter extends Table { + public static GameFooter getRootAsGameFooter(ByteBuffer _bb) { return getRootAsGameFooter(_bb, new GameFooter()); } + public static GameFooter getRootAsGameFooter(ByteBuffer _bb, GameFooter obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public GameFooter __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The ID of the winning team of the game. + */ + public byte winner() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } + + public static int createGameFooter(FlatBufferBuilder builder, + byte winner) { + builder.startObject(1); + GameFooter.addWinner(builder, winner); + return GameFooter.endGameFooter(builder); + } + + public static void startGameFooter(FlatBufferBuilder builder) { builder.startObject(1); } + public static void addWinner(FlatBufferBuilder builder, byte winner) { builder.addByte(0, winner, 0); } + public static int endGameFooter(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/GameHeader.java b/engine/src/main/battlecode/schema-old/GameHeader.java new file mode 100644 index 00000000..53b7e653 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/GameHeader.java @@ -0,0 +1,63 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * The first event sent in the game. Contains all metadata about the game. + */ +public final class GameHeader extends Table { + public static GameHeader getRootAsGameHeader(ByteBuffer _bb) { return getRootAsGameHeader(_bb, new GameHeader()); } + public static GameHeader getRootAsGameHeader(ByteBuffer _bb, GameHeader obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public GameHeader __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The version of the spec this game complies with. + */ + public String specVersion() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer specVersionAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } + public ByteBuffer specVersionInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 1); } + /** + * The teams participating in the game. + */ + public TeamData teams(int j) { return teams(new TeamData(), j); } + public TeamData teams(TeamData obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int teamsLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + /** + * Information about all body types in the game. + */ + public BodyTypeMetadata bodyTypeMetadata(int j) { return bodyTypeMetadata(new BodyTypeMetadata(), j); } + public BodyTypeMetadata bodyTypeMetadata(BodyTypeMetadata obj, int j) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int bodyTypeMetadataLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + + public static int createGameHeader(FlatBufferBuilder builder, + int specVersionOffset, + int teamsOffset, + int bodyTypeMetadataOffset) { + builder.startObject(3); + GameHeader.addBodyTypeMetadata(builder, bodyTypeMetadataOffset); + GameHeader.addTeams(builder, teamsOffset); + GameHeader.addSpecVersion(builder, specVersionOffset); + return GameHeader.endGameHeader(builder); + } + + public static void startGameHeader(FlatBufferBuilder builder) { builder.startObject(3); } + public static void addSpecVersion(FlatBufferBuilder builder, int specVersionOffset) { builder.addOffset(0, specVersionOffset, 0); } + public static void addTeams(FlatBufferBuilder builder, int teamsOffset) { builder.addOffset(1, teamsOffset, 0); } + public static int createTeamsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startTeamsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addBodyTypeMetadata(FlatBufferBuilder builder, int bodyTypeMetadataOffset) { builder.addOffset(2, bodyTypeMetadataOffset, 0); } + public static int createBodyTypeMetadataVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startBodyTypeMetadataVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endGameHeader(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/GameMap.java b/engine/src/main/battlecode/schema-old/GameMap.java new file mode 100644 index 00000000..34475b23 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/GameMap.java @@ -0,0 +1,67 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * The map a round is played on. + */ +public final class GameMap extends Table { + public static GameMap getRootAsGameMap(ByteBuffer _bb) { return getRootAsGameMap(_bb, new GameMap()); } + public static GameMap getRootAsGameMap(ByteBuffer _bb, GameMap obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public GameMap __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The name of a map. + */ + public String name() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } + public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 1); } + /** + * The bottom corner of the map. + */ + public Vec minCorner() { return minCorner(new Vec()); } + public Vec minCorner(Vec obj) { int o = __offset(6); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + /** + * The top corner of the map. + */ + public Vec maxCorner() { return maxCorner(new Vec()); } + public Vec maxCorner(Vec obj) { int o = __offset(8); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + /** + * The bodies on the map. + */ + public SpawnedBodyTable bodies() { return bodies(new SpawnedBodyTable()); } + public SpawnedBodyTable bodies(SpawnedBodyTable obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The random seed of the map. + */ + public int randomSeed() { int o = __offset(12); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * The factor to divide cooldowns by + */ + public double passability(int j) { int o = __offset(14); return o != 0 ? bb.getDouble(__vector(o) + j * 8) : 0; } + public int passabilityLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer passabilityAsByteBuffer() { return __vector_as_bytebuffer(14, 8); } + public ByteBuffer passabilityInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 14, 8); } + + public static void startGameMap(FlatBufferBuilder builder) { builder.startObject(6); } + public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } + public static void addMinCorner(FlatBufferBuilder builder, int minCornerOffset) { builder.addStruct(1, minCornerOffset, 0); } + public static void addMaxCorner(FlatBufferBuilder builder, int maxCornerOffset) { builder.addStruct(2, maxCornerOffset, 0); } + public static void addBodies(FlatBufferBuilder builder, int bodiesOffset) { builder.addOffset(3, bodiesOffset, 0); } + public static void addRandomSeed(FlatBufferBuilder builder, int randomSeed) { builder.addInt(4, randomSeed, 0); } + public static void addPassability(FlatBufferBuilder builder, int passabilityOffset) { builder.addOffset(5, passabilityOffset, 0); } + public static int createPassabilityVector(FlatBufferBuilder builder, double[] data) { builder.startVector(8, data.length, 8); for (int i = data.length - 1; i >= 0; i--) builder.addDouble(data[i]); return builder.endVector(); } + public static void startPassabilityVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 8); } + public static int endGameMap(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/GameWrapper.java b/engine/src/main/battlecode/schema-old/GameWrapper.java new file mode 100644 index 00000000..ecf4634c --- /dev/null +++ b/engine/src/main/battlecode/schema-old/GameWrapper.java @@ -0,0 +1,72 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * If events are not otherwise delimited, this wrapper structure + * allows a game to be stored in a single buffer. + * The first event will be a GameHeader; the last event will be a GameFooter. + * matchHeaders[0] is the index of the 0th match header in the event stream, + * corresponding to matchFooters[0]. These indices allow quick traversal of + * the file. + */ +public final class GameWrapper extends Table { + public static GameWrapper getRootAsGameWrapper(ByteBuffer _bb) { return getRootAsGameWrapper(_bb, new GameWrapper()); } + public static GameWrapper getRootAsGameWrapper(ByteBuffer _bb, GameWrapper obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public GameWrapper __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The series of events comprising the game. + */ + public EventWrapper events(int j) { return events(new EventWrapper(), j); } + public EventWrapper events(EventWrapper obj, int j) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int eventsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } + /** + * The indices of the headers of the matches, in order. + */ + public int matchHeaders(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int matchHeadersLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer matchHeadersAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } + public ByteBuffer matchHeadersInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } + /** + * The indices of the footers of the matches, in order. + */ + public int matchFooters(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int matchFootersLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer matchFootersAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } + public ByteBuffer matchFootersInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } + + public static int createGameWrapper(FlatBufferBuilder builder, + int eventsOffset, + int matchHeadersOffset, + int matchFootersOffset) { + builder.startObject(3); + GameWrapper.addMatchFooters(builder, matchFootersOffset); + GameWrapper.addMatchHeaders(builder, matchHeadersOffset); + GameWrapper.addEvents(builder, eventsOffset); + return GameWrapper.endGameWrapper(builder); + } + + public static void startGameWrapper(FlatBufferBuilder builder) { builder.startObject(3); } + public static void addEvents(FlatBufferBuilder builder, int eventsOffset) { builder.addOffset(0, eventsOffset, 0); } + public static int createEventsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startEventsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addMatchHeaders(FlatBufferBuilder builder, int matchHeadersOffset) { builder.addOffset(1, matchHeadersOffset, 0); } + public static int createMatchHeadersVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startMatchHeadersVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addMatchFooters(FlatBufferBuilder builder, int matchFootersOffset) { builder.addOffset(2, matchFootersOffset, 0); } + public static int createMatchFootersVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startMatchFootersVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endGameWrapper(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/MatchFooter.java b/engine/src/main/battlecode/schema-old/MatchFooter.java new file mode 100644 index 00000000..74fa1fd1 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/MatchFooter.java @@ -0,0 +1,57 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * Sent to end a match. + */ +public final class MatchFooter extends Table { + public static MatchFooter getRootAsMatchFooter(ByteBuffer _bb) { return getRootAsMatchFooter(_bb, new MatchFooter()); } + public static MatchFooter getRootAsMatchFooter(ByteBuffer _bb, MatchFooter obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public MatchFooter __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The ID of the winning team. + */ + public byte winner() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } + /** + * The number of rounds played. + */ + public int totalRounds() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * Profiler data for team A and B if profiling is enabled. + */ + public ProfilerFile profilerFiles(int j) { return profilerFiles(new ProfilerFile(), j); } + public ProfilerFile profilerFiles(ProfilerFile obj, int j) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int profilerFilesLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + + public static int createMatchFooter(FlatBufferBuilder builder, + byte winner, + int totalRounds, + int profilerFilesOffset) { + builder.startObject(3); + MatchFooter.addProfilerFiles(builder, profilerFilesOffset); + MatchFooter.addTotalRounds(builder, totalRounds); + MatchFooter.addWinner(builder, winner); + return MatchFooter.endMatchFooter(builder); + } + + public static void startMatchFooter(FlatBufferBuilder builder) { builder.startObject(3); } + public static void addWinner(FlatBufferBuilder builder, byte winner) { builder.addByte(0, winner, 0); } + public static void addTotalRounds(FlatBufferBuilder builder, int totalRounds) { builder.addInt(1, totalRounds, 0); } + public static void addProfilerFiles(FlatBufferBuilder builder, int profilerFilesOffset) { builder.addOffset(2, profilerFilesOffset, 0); } + public static int createProfilerFilesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startProfilerFilesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endMatchFooter(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/MatchHeader.java b/engine/src/main/battlecode/schema-old/MatchHeader.java new file mode 100644 index 00000000..ec5a46d0 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/MatchHeader.java @@ -0,0 +1,47 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * Sent to start a match. + */ +public final class MatchHeader extends Table { + public static MatchHeader getRootAsMatchHeader(ByteBuffer _bb) { return getRootAsMatchHeader(_bb, new MatchHeader()); } + public static MatchHeader getRootAsMatchHeader(ByteBuffer _bb, MatchHeader obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public MatchHeader __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The map the match was played on. + */ + public GameMap map() { return map(new GameMap()); } + public GameMap map(GameMap obj) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The maximum number of rounds in this match. + */ + public int maxRounds() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + + public static int createMatchHeader(FlatBufferBuilder builder, + int mapOffset, + int maxRounds) { + builder.startObject(2); + MatchHeader.addMaxRounds(builder, maxRounds); + MatchHeader.addMap(builder, mapOffset); + return MatchHeader.endMatchHeader(builder); + } + + public static void startMatchHeader(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addMap(FlatBufferBuilder builder, int mapOffset) { builder.addOffset(0, mapOffset, 0); } + public static void addMaxRounds(FlatBufferBuilder builder, int maxRounds) { builder.addInt(1, maxRounds, 0); } + public static int endMatchHeader(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/ProfilerEvent.java b/engine/src/main/battlecode/schema-old/ProfilerEvent.java new file mode 100644 index 00000000..0fbcd553 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/ProfilerEvent.java @@ -0,0 +1,57 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * These tables are set-up so that they match closely with speedscope's file format documented at + * https://github.com/jlfwong/speedscope/wiki/Importing-from-custom-sources. + * The client uses speedscope to show the recorded data in an interactive interface. + * A single event in a profile. Represents either an open event (meaning a + * method has been entered) or a close event (meaning the method was exited). + */ +public final class ProfilerEvent extends Table { + public static ProfilerEvent getRootAsProfilerEvent(ByteBuffer _bb) { return getRootAsProfilerEvent(_bb, new ProfilerEvent()); } + public static ProfilerEvent getRootAsProfilerEvent(ByteBuffer _bb, ProfilerEvent obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public ProfilerEvent __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * Whether this is an open event (true) or a close event (false). + */ + public boolean isOpen() { int o = __offset(4); return o != 0 ? 0!=bb.get(o + bb_pos) : false; } + /** + * The bytecode counter at the time the event occurred. + */ + public int at() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * The index of the method name in the ProfilerFile.frames array. + */ + public int frame() { int o = __offset(8); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + + public static int createProfilerEvent(FlatBufferBuilder builder, + boolean isOpen, + int at, + int frame) { + builder.startObject(3); + ProfilerEvent.addFrame(builder, frame); + ProfilerEvent.addAt(builder, at); + ProfilerEvent.addIsOpen(builder, isOpen); + return ProfilerEvent.endProfilerEvent(builder); + } + + public static void startProfilerEvent(FlatBufferBuilder builder) { builder.startObject(3); } + public static void addIsOpen(FlatBufferBuilder builder, boolean isOpen) { builder.addBoolean(0, isOpen, false); } + public static void addAt(FlatBufferBuilder builder, int at) { builder.addInt(1, at, 0); } + public static void addFrame(FlatBufferBuilder builder, int frame) { builder.addInt(2, frame, 0); } + public static int endProfilerEvent(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/ProfilerFile.java b/engine/src/main/battlecode/schema-old/ProfilerFile.java new file mode 100644 index 00000000..ffbd5e0d --- /dev/null +++ b/engine/src/main/battlecode/schema-old/ProfilerFile.java @@ -0,0 +1,54 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * A profiler file is a collection of profiles. + * When profiling is enabled there is one of these per team per match. + */ +public final class ProfilerFile extends Table { + public static ProfilerFile getRootAsProfilerFile(ByteBuffer _bb) { return getRootAsProfilerFile(_bb, new ProfilerFile()); } + public static ProfilerFile getRootAsProfilerFile(ByteBuffer _bb, ProfilerFile obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public ProfilerFile __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The method names that are referred to in the events. + */ + public String frames(int j) { int o = __offset(4); return o != 0 ? __string(__vector(o) + j * 4) : null; } + public int framesLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } + /** + * The recorded profiles, one per robot. + */ + public ProfilerProfile profiles(int j) { return profiles(new ProfilerProfile(), j); } + public ProfilerProfile profiles(ProfilerProfile obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int profilesLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + + public static int createProfilerFile(FlatBufferBuilder builder, + int framesOffset, + int profilesOffset) { + builder.startObject(2); + ProfilerFile.addProfiles(builder, profilesOffset); + ProfilerFile.addFrames(builder, framesOffset); + return ProfilerFile.endProfilerFile(builder); + } + + public static void startProfilerFile(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addFrames(FlatBufferBuilder builder, int framesOffset) { builder.addOffset(0, framesOffset, 0); } + public static int createFramesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startFramesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addProfiles(FlatBufferBuilder builder, int profilesOffset) { builder.addOffset(1, profilesOffset, 0); } + public static int createProfilesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startProfilesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endProfilerFile(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/ProfilerProfile.java b/engine/src/main/battlecode/schema-old/ProfilerProfile.java new file mode 100644 index 00000000..34a12924 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/ProfilerProfile.java @@ -0,0 +1,52 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * A profile contains all events and is labeled with a name. + */ +public final class ProfilerProfile extends Table { + public static ProfilerProfile getRootAsProfilerProfile(ByteBuffer _bb) { return getRootAsProfilerProfile(_bb, new ProfilerProfile()); } + public static ProfilerProfile getRootAsProfilerProfile(ByteBuffer _bb, ProfilerProfile obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public ProfilerProfile __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The display-friendly name of the profile. + */ + public String name() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } + public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 1); } + /** + * The events that occurred in the profile. + */ + public ProfilerEvent events(int j) { return events(new ProfilerEvent(), j); } + public ProfilerEvent events(ProfilerEvent obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public int eventsLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + + public static int createProfilerProfile(FlatBufferBuilder builder, + int nameOffset, + int eventsOffset) { + builder.startObject(2); + ProfilerProfile.addEvents(builder, eventsOffset); + ProfilerProfile.addName(builder, nameOffset); + return ProfilerProfile.endProfilerProfile(builder); + } + + public static void startProfilerProfile(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } + public static void addEvents(FlatBufferBuilder builder, int eventsOffset) { builder.addOffset(1, eventsOffset, 0); } + public static int createEventsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startEventsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endProfilerProfile(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/RGBTable.java b/engine/src/main/battlecode/schema-old/RGBTable.java new file mode 100644 index 00000000..96fdeb9c --- /dev/null +++ b/engine/src/main/battlecode/schema-old/RGBTable.java @@ -0,0 +1,59 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * A table of RGB values. + */ +public final class RGBTable extends Table { + public static RGBTable getRootAsRGBTable(ByteBuffer _bb) { return getRootAsRGBTable(_bb, new RGBTable()); } + public static RGBTable getRootAsRGBTable(ByteBuffer _bb, RGBTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public RGBTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int red(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int redLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer redAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } + public ByteBuffer redInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } + public int green(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int greenLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer greenAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } + public ByteBuffer greenInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } + public int blue(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int blueLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer blueAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } + public ByteBuffer blueInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } + + public static int createRGBTable(FlatBufferBuilder builder, + int redOffset, + int greenOffset, + int blueOffset) { + builder.startObject(3); + RGBTable.addBlue(builder, blueOffset); + RGBTable.addGreen(builder, greenOffset); + RGBTable.addRed(builder, redOffset); + return RGBTable.endRGBTable(builder); + } + + public static void startRGBTable(FlatBufferBuilder builder) { builder.startObject(3); } + public static void addRed(FlatBufferBuilder builder, int redOffset) { builder.addOffset(0, redOffset, 0); } + public static int createRedVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startRedVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addGreen(FlatBufferBuilder builder, int greenOffset) { builder.addOffset(1, greenOffset, 0); } + public static int createGreenVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startGreenVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addBlue(FlatBufferBuilder builder, int blueOffset) { builder.addOffset(2, blueOffset, 0); } + public static int createBlueVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startBlueVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endRGBTable(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/Round.java b/engine/src/main/battlecode/schema-old/Round.java new file mode 100644 index 00000000..c45ebc4e --- /dev/null +++ b/engine/src/main/battlecode/schema-old/Round.java @@ -0,0 +1,283 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * A single time-step in a Game. + * The bulk of the data in the file is stored in tables like this. + * Note that a struct-of-arrays format is more space efficient than an array- + * of-structs. + */ +public final class Round extends Table { + public static Round getRootAsRound(ByteBuffer _bb) { return getRootAsRound(_bb, new Round()); } + public static Round getRootAsRound(ByteBuffer _bb, Round obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public Round __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The IDs of teams in the Game. + */ + public int teamIDs(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamIDsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamIDsAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } + public ByteBuffer teamIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } + /** + * The number of votes the teams get, 0 or 1. + */ + public int teamVotes(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamVotesLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamVotesAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } + public ByteBuffer teamVotesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } + /** + * The ID of the Enlightenment Center got the bid. + */ + public int teamBidderIDs(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamBidderIDsLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamBidderIDsAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } + public ByteBuffer teamBidderIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } + /** + * The IDs of bodies that moved. + */ + public int movedIDs(int j) { int o = __offset(10); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int movedIDsLength() { int o = __offset(10); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer movedIDsAsByteBuffer() { return __vector_as_bytebuffer(10, 4); } + public ByteBuffer movedIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 10, 4); } + /** + * The new locations of bodies that have moved. + */ + public VecTable movedLocs() { return movedLocs(new VecTable()); } + public VecTable movedLocs(VecTable obj) { int o = __offset(12); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * New bodies. + */ + public SpawnedBodyTable spawnedBodies() { return spawnedBodies(new SpawnedBodyTable()); } + public SpawnedBodyTable spawnedBodies(SpawnedBodyTable obj) { int o = __offset(14); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The IDs of bodies that died. + */ + public int diedIDs(int j) { int o = __offset(16); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int diedIDsLength() { int o = __offset(16); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer diedIDsAsByteBuffer() { return __vector_as_bytebuffer(16, 4); } + public ByteBuffer diedIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 16, 4); } + /** + * The IDs of robots that performed actions. + * IDs may repeat. + */ + public int actionIDs(int j) { int o = __offset(18); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int actionIDsLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer actionIDsAsByteBuffer() { return __vector_as_bytebuffer(18, 4); } + public ByteBuffer actionIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 18, 4); } + /** + * The actions performed. These actions allow us to track how much soup or dirt a body carries. + */ + public byte actions(int j) { int o = __offset(20); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } + public int actionsLength() { int o = __offset(20); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer actionsAsByteBuffer() { return __vector_as_bytebuffer(20, 1); } + public ByteBuffer actionsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 20, 1); } + /** + * The 'targets' of the performed actions. Actions without targets may have any value + */ + public int actionTargets(int j) { int o = __offset(22); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int actionTargetsLength() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer actionTargetsAsByteBuffer() { return __vector_as_bytebuffer(22, 4); } + public ByteBuffer actionTargetsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 22, 4); } + /** + * The IDs of bodies that set indicator dots + */ + public int indicatorDotIDs(int j) { int o = __offset(24); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int indicatorDotIDsLength() { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer indicatorDotIDsAsByteBuffer() { return __vector_as_bytebuffer(24, 4); } + public ByteBuffer indicatorDotIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 24, 4); } + /** + * The location of the indicator dots + */ + public VecTable indicatorDotLocs() { return indicatorDotLocs(new VecTable()); } + public VecTable indicatorDotLocs(VecTable obj) { int o = __offset(26); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The RGB values of the indicator dots + */ + public RGBTable indicatorDotRGBs() { return indicatorDotRGBs(new RGBTable()); } + public RGBTable indicatorDotRGBs(RGBTable obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The IDs of bodies that set indicator lines + */ + public int indicatorLineIDs(int j) { int o = __offset(30); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int indicatorLineIDsLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer indicatorLineIDsAsByteBuffer() { return __vector_as_bytebuffer(30, 4); } + public ByteBuffer indicatorLineIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 30, 4); } + /** + * The start location of the indicator lines + */ + public VecTable indicatorLineStartLocs() { return indicatorLineStartLocs(new VecTable()); } + public VecTable indicatorLineStartLocs(VecTable obj) { int o = __offset(32); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The end location of the indicator lines + */ + public VecTable indicatorLineEndLocs() { return indicatorLineEndLocs(new VecTable()); } + public VecTable indicatorLineEndLocs(VecTable obj) { int o = __offset(34); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The RGB values of the indicator lines + */ + public RGBTable indicatorLineRGBs() { return indicatorLineRGBs(new RGBTable()); } + public RGBTable indicatorLineRGBs(RGBTable obj) { int o = __offset(36); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * All logs sent this round. + * Messages from a particular robot in this round start on a new line, and + * have a header: + * '[' $TEAM ':' $ROBOTTYPE '#' $ID '@' $ROUND '] ' + * $TEAM = 'A' | 'B' + * $ROBOTTYPE = 'ENLIGHTENMENT_CENTER' | 'POLITICIAN' | 'SLANDERER' | 'MUCKRAKER' + * $ID = a number + * $ROUND = a number + * The header is not necessarily followed by a newline. + * This header should only be sent once per robot per round (although + * players may forge it, so don't crash if you get strange input.) + * + * You should try to only read this value once, and cache it. Reading + * strings from a flatbuffer is much less efficient than reading other + * buffers, because they need to be copied into an environment-provided + * buffer and validated. + * + * (haha i guess you can never really escape string parsing can you) + */ + public String logs() { int o = __offset(38); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer logsAsByteBuffer() { return __vector_as_bytebuffer(38, 1); } + public ByteBuffer logsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 38, 1); } + /** + * The first sent Round in a match should have index 1. (The starting state, + * created by the MatchHeader, can be thought to have index 0.) + * It should increase by one for each following round. + */ + public int roundID() { int o = __offset(40); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * The IDs of player bodies. + */ + public int bytecodeIDs(int j) { int o = __offset(42); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int bytecodeIDsLength() { int o = __offset(42); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer bytecodeIDsAsByteBuffer() { return __vector_as_bytebuffer(42, 4); } + public ByteBuffer bytecodeIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 42, 4); } + /** + * The bytecodes used by the player bodies. + */ + public int bytecodesUsed(int j) { int o = __offset(44); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int bytecodesUsedLength() { int o = __offset(44); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer bytecodesUsedAsByteBuffer() { return __vector_as_bytebuffer(44, 4); } + public ByteBuffer bytecodesUsedInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 44, 4); } + /** + * Amount of influence contributing to the teams' buffs. Added at end for backwards compatability. + */ + public int teamNumBuffs(int j) { int o = __offset(46); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamNumBuffsLength() { int o = __offset(46); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamNumBuffsAsByteBuffer() { return __vector_as_bytebuffer(46, 4); } + public ByteBuffer teamNumBuffsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 46, 4); } + + public static int createRound(FlatBufferBuilder builder, + int teamIDsOffset, + int teamVotesOffset, + int teamBidderIDsOffset, + int movedIDsOffset, + int movedLocsOffset, + int spawnedBodiesOffset, + int diedIDsOffset, + int actionIDsOffset, + int actionsOffset, + int actionTargetsOffset, + int indicatorDotIDsOffset, + int indicatorDotLocsOffset, + int indicatorDotRGBsOffset, + int indicatorLineIDsOffset, + int indicatorLineStartLocsOffset, + int indicatorLineEndLocsOffset, + int indicatorLineRGBsOffset, + int logsOffset, + int roundID, + int bytecodeIDsOffset, + int bytecodesUsedOffset, + int teamNumBuffsOffset) { + builder.startObject(22); + Round.addTeamNumBuffs(builder, teamNumBuffsOffset); + Round.addBytecodesUsed(builder, bytecodesUsedOffset); + Round.addBytecodeIDs(builder, bytecodeIDsOffset); + Round.addRoundID(builder, roundID); + Round.addLogs(builder, logsOffset); + Round.addIndicatorLineRGBs(builder, indicatorLineRGBsOffset); + Round.addIndicatorLineEndLocs(builder, indicatorLineEndLocsOffset); + Round.addIndicatorLineStartLocs(builder, indicatorLineStartLocsOffset); + Round.addIndicatorLineIDs(builder, indicatorLineIDsOffset); + Round.addIndicatorDotRGBs(builder, indicatorDotRGBsOffset); + Round.addIndicatorDotLocs(builder, indicatorDotLocsOffset); + Round.addIndicatorDotIDs(builder, indicatorDotIDsOffset); + Round.addActionTargets(builder, actionTargetsOffset); + Round.addActions(builder, actionsOffset); + Round.addActionIDs(builder, actionIDsOffset); + Round.addDiedIDs(builder, diedIDsOffset); + Round.addSpawnedBodies(builder, spawnedBodiesOffset); + Round.addMovedLocs(builder, movedLocsOffset); + Round.addMovedIDs(builder, movedIDsOffset); + Round.addTeamBidderIDs(builder, teamBidderIDsOffset); + Round.addTeamVotes(builder, teamVotesOffset); + Round.addTeamIDs(builder, teamIDsOffset); + return Round.endRound(builder); + } + + public static void startRound(FlatBufferBuilder builder) { builder.startObject(22); } + public static void addTeamIDs(FlatBufferBuilder builder, int teamIDsOffset) { builder.addOffset(0, teamIDsOffset, 0); } + public static int createTeamIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamVotes(FlatBufferBuilder builder, int teamVotesOffset) { builder.addOffset(1, teamVotesOffset, 0); } + public static int createTeamVotesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamVotesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamBidderIDs(FlatBufferBuilder builder, int teamBidderIDsOffset) { builder.addOffset(2, teamBidderIDsOffset, 0); } + public static int createTeamBidderIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamBidderIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addMovedIDs(FlatBufferBuilder builder, int movedIDsOffset) { builder.addOffset(3, movedIDsOffset, 0); } + public static int createMovedIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startMovedIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addMovedLocs(FlatBufferBuilder builder, int movedLocsOffset) { builder.addOffset(4, movedLocsOffset, 0); } + public static void addSpawnedBodies(FlatBufferBuilder builder, int spawnedBodiesOffset) { builder.addOffset(5, spawnedBodiesOffset, 0); } + public static void addDiedIDs(FlatBufferBuilder builder, int diedIDsOffset) { builder.addOffset(6, diedIDsOffset, 0); } + public static int createDiedIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startDiedIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addActionIDs(FlatBufferBuilder builder, int actionIDsOffset) { builder.addOffset(7, actionIDsOffset, 0); } + public static int createActionIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startActionIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addActions(FlatBufferBuilder builder, int actionsOffset) { builder.addOffset(8, actionsOffset, 0); } + public static int createActionsVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } + public static void startActionsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } + public static void addActionTargets(FlatBufferBuilder builder, int actionTargetsOffset) { builder.addOffset(9, actionTargetsOffset, 0); } + public static int createActionTargetsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startActionTargetsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorDotIDs(FlatBufferBuilder builder, int indicatorDotIDsOffset) { builder.addOffset(10, indicatorDotIDsOffset, 0); } + public static int createIndicatorDotIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startIndicatorDotIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorDotLocs(FlatBufferBuilder builder, int indicatorDotLocsOffset) { builder.addOffset(11, indicatorDotLocsOffset, 0); } + public static void addIndicatorDotRGBs(FlatBufferBuilder builder, int indicatorDotRGBsOffset) { builder.addOffset(12, indicatorDotRGBsOffset, 0); } + public static void addIndicatorLineIDs(FlatBufferBuilder builder, int indicatorLineIDsOffset) { builder.addOffset(13, indicatorLineIDsOffset, 0); } + public static int createIndicatorLineIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startIndicatorLineIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorLineStartLocs(FlatBufferBuilder builder, int indicatorLineStartLocsOffset) { builder.addOffset(14, indicatorLineStartLocsOffset, 0); } + public static void addIndicatorLineEndLocs(FlatBufferBuilder builder, int indicatorLineEndLocsOffset) { builder.addOffset(15, indicatorLineEndLocsOffset, 0); } + public static void addIndicatorLineRGBs(FlatBufferBuilder builder, int indicatorLineRGBsOffset) { builder.addOffset(16, indicatorLineRGBsOffset, 0); } + public static void addLogs(FlatBufferBuilder builder, int logsOffset) { builder.addOffset(17, logsOffset, 0); } + public static void addRoundID(FlatBufferBuilder builder, int roundID) { builder.addInt(18, roundID, 0); } + public static void addBytecodeIDs(FlatBufferBuilder builder, int bytecodeIDsOffset) { builder.addOffset(19, bytecodeIDsOffset, 0); } + public static int createBytecodeIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startBytecodeIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addBytecodesUsed(FlatBufferBuilder builder, int bytecodesUsedOffset) { builder.addOffset(20, bytecodesUsedOffset, 0); } + public static int createBytecodesUsedVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startBytecodesUsedVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamNumBuffs(FlatBufferBuilder builder, int teamNumBuffsOffset) { builder.addOffset(21, teamNumBuffsOffset, 0); } + public static int createTeamNumBuffsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamNumBuffsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endRound(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/SpawnedBodyTable.java b/engine/src/main/battlecode/schema-old/SpawnedBodyTable.java new file mode 100644 index 00000000..b82bff1b --- /dev/null +++ b/engine/src/main/battlecode/schema-old/SpawnedBodyTable.java @@ -0,0 +1,94 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * A list of new bodies to be placed on the map. + */ +public final class SpawnedBodyTable extends Table { + public static SpawnedBodyTable getRootAsSpawnedBodyTable(ByteBuffer _bb) { return getRootAsSpawnedBodyTable(_bb, new SpawnedBodyTable()); } + public static SpawnedBodyTable getRootAsSpawnedBodyTable(ByteBuffer _bb, SpawnedBodyTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public SpawnedBodyTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The numeric ID of the new bodies. + * Will never be negative. + * There will only be one body with a particular ID at a time. + * So, there will never be two robots with the same ID, or a robot and + * a building with the same ID. + */ + public int robotIDs(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int robotIDsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer robotIDsAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } + public ByteBuffer robotIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } + /** + * The teams of the new bodies. + */ + public byte teamIDs(int j) { int o = __offset(6); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } + public int teamIDsLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamIDsAsByteBuffer() { return __vector_as_bytebuffer(6, 1); } + public ByteBuffer teamIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 1); } + /** + * The types of the new bodies. + */ + public byte types(int j) { int o = __offset(8); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } + public int typesLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer typesAsByteBuffer() { return __vector_as_bytebuffer(8, 1); } + public ByteBuffer typesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); } + /** + * The locations of the bodies. + */ + public VecTable locs() { return locs(new VecTable()); } + public VecTable locs(VecTable obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * the amount of influence paid to create these bodies + * for initial Enlightenment Centers, this is the amount of influence + * needed to take over + */ + public int influences(int j) { int o = __offset(12); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int influencesLength() { int o = __offset(12); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer influencesAsByteBuffer() { return __vector_as_bytebuffer(12, 4); } + public ByteBuffer influencesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 12, 4); } + + public static int createSpawnedBodyTable(FlatBufferBuilder builder, + int robotIDsOffset, + int teamIDsOffset, + int typesOffset, + int locsOffset, + int influencesOffset) { + builder.startObject(5); + SpawnedBodyTable.addInfluences(builder, influencesOffset); + SpawnedBodyTable.addLocs(builder, locsOffset); + SpawnedBodyTable.addTypes(builder, typesOffset); + SpawnedBodyTable.addTeamIDs(builder, teamIDsOffset); + SpawnedBodyTable.addRobotIDs(builder, robotIDsOffset); + return SpawnedBodyTable.endSpawnedBodyTable(builder); + } + + public static void startSpawnedBodyTable(FlatBufferBuilder builder) { builder.startObject(5); } + public static void addRobotIDs(FlatBufferBuilder builder, int robotIDsOffset) { builder.addOffset(0, robotIDsOffset, 0); } + public static int createRobotIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startRobotIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamIDs(FlatBufferBuilder builder, int teamIDsOffset) { builder.addOffset(1, teamIDsOffset, 0); } + public static int createTeamIDsVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } + public static void startTeamIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } + public static void addTypes(FlatBufferBuilder builder, int typesOffset) { builder.addOffset(2, typesOffset, 0); } + public static int createTypesVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } + public static void startTypesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } + public static void addLocs(FlatBufferBuilder builder, int locsOffset) { builder.addOffset(3, locsOffset, 0); } + public static void addInfluences(FlatBufferBuilder builder, int influencesOffset) { builder.addOffset(4, influencesOffset, 0); } + public static int createInfluencesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startInfluencesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endSpawnedBodyTable(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/TeamData.java b/engine/src/main/battlecode/schema-old/TeamData.java new file mode 100644 index 00000000..32b840b1 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/TeamData.java @@ -0,0 +1,57 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * Data relevant to a particular team. + */ +public final class TeamData extends Table { + public static TeamData getRootAsTeamData(ByteBuffer _bb) { return getRootAsTeamData(_bb, new TeamData()); } + public static TeamData getRootAsTeamData(ByteBuffer _bb, TeamData obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public TeamData __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + /** + * The name of the team. + */ + public String name() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } + public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 1); } + /** + * The java package the team uses. + */ + public String packageName() { int o = __offset(6); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer packageNameAsByteBuffer() { return __vector_as_bytebuffer(6, 1); } + public ByteBuffer packageNameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 1); } + /** + * The ID of the team this data pertains to. + */ + public byte teamID() { int o = __offset(8); return o != 0 ? bb.get(o + bb_pos) : 0; } + + public static int createTeamData(FlatBufferBuilder builder, + int nameOffset, + int packageNameOffset, + byte teamID) { + builder.startObject(3); + TeamData.addPackageName(builder, packageNameOffset); + TeamData.addName(builder, nameOffset); + TeamData.addTeamID(builder, teamID); + return TeamData.endTeamData(builder); + } + + public static void startTeamData(FlatBufferBuilder builder) { builder.startObject(3); } + public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } + public static void addPackageName(FlatBufferBuilder builder, int packageNameOffset) { builder.addOffset(1, packageNameOffset, 0); } + public static void addTeamID(FlatBufferBuilder builder, byte teamID) { builder.addByte(2, teamID, 0); } + public static int endTeamData(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema-old/Vec.java b/engine/src/main/battlecode/schema-old/Vec.java new file mode 100644 index 00000000..880323bb --- /dev/null +++ b/engine/src/main/battlecode/schema-old/Vec.java @@ -0,0 +1,29 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * A vector in two-dimensional space. Discrete space, of course. + * Defaults to the 0 vector. + */ +public final class Vec extends Struct { + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; } + public Vec __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int x() { return bb.getInt(bb_pos + 0); } + public int y() { return bb.getInt(bb_pos + 4); } + + public static int createVec(FlatBufferBuilder builder, int x, int y) { + builder.prep(4, 8); + builder.putInt(y); + builder.putInt(x); + return builder.offset(); + } +} + diff --git a/engine/src/main/battlecode/schema-old/VecTable.java b/engine/src/main/battlecode/schema-old/VecTable.java new file mode 100644 index 00000000..318ab618 --- /dev/null +++ b/engine/src/main/battlecode/schema-old/VecTable.java @@ -0,0 +1,50 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +// package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +/** + * A table of vectors. + */ +public final class VecTable extends Table { + public static VecTable getRootAsVecTable(ByteBuffer _bb) { return getRootAsVecTable(_bb, new VecTable()); } + public static VecTable getRootAsVecTable(ByteBuffer _bb, VecTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public VecTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int xs(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int xsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer xsAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } + public ByteBuffer xsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } + public int ys(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int ysLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer ysAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } + public ByteBuffer ysInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } + + public static int createVecTable(FlatBufferBuilder builder, + int xsOffset, + int ysOffset) { + builder.startObject(2); + VecTable.addYs(builder, ysOffset); + VecTable.addXs(builder, xsOffset); + return VecTable.endVecTable(builder); + } + + public static void startVecTable(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addXs(FlatBufferBuilder builder, int xsOffset) { builder.addOffset(0, xsOffset, 0); } + public static int createXsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startXsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addYs(FlatBufferBuilder builder, int ysOffset) { builder.addOffset(1, ysOffset, 0); } + public static int createYsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startYsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static int endVecTable(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema/Action.java b/engine/src/main/battlecode/schema/Action.java index a21287a3..3062d6f7 100644 --- a/engine/src/main/battlecode/schema/Action.java +++ b/engine/src/main/battlecode/schema/Action.java @@ -13,64 +13,81 @@ public final class Action { private Action() { } /** - * Politicians self-destruct and affect nearby bodies. - * Target: radius squared + * Target: ID of robot attacked */ - public static final byte EMPOWER = 0; + public static final byte ATTACK = 0; /** - * Slanderers passively generate influence for the - * Enlightenment Center that created them. - * Target: parent ID + * Target: ID of robot spawned */ - public static final byte EMBEZZLE = 1; + public static final byte SPAWN_UNIT = 1; + /** + * Target: location mined, x + y * width + */ + public static final byte MINE_LEAD = 2; + /** + * Target: location mined, x + y * width + */ + public static final byte MINE_GOLD = 3; + /** + * Target: none + */ + public static final byte TRANSMUTE = 4; /** - * Slanderers turn into Politicians. * Target: none */ - public static final byte CAMOUFLAGE = 2; + public static final byte TRANSFORM = 5; /** - * Muckrakers can expose a slanderer. - * Target: an enemy body + * Target: ID of robot mutated */ - public static final byte EXPOSE = 3; + public static final byte MUTATE = 6; /** - * Units can change their flag. - * Target: new flag value + * Target: ID of robot repaired */ - public static final byte SET_FLAG = 4; + public static final byte REPAIR = 7; /** - * Builds a unit. - * Target: spawned unit + * Target: change in health (can be negative) + */ + public static final byte CHANGE_HEALTH = 8; + /** + * When a PROTOTYPE building upgrades to TURRET + * Target: none */ - public static final byte SPAWN_UNIT = 5; + public static final byte FULLY_REPAIRED = 9; /** - * Places a bid. - * Target: bid value + * Target: Sage location, x + y * width */ - public static final byte PLACE_BID = 6; + public static final byte LOCAL_ABYSS = 10; /** - * A robot can change team after being empowered, - * or when a Enlightenment Center is taken over. - * Target: new robotID + * Target: Sage location, x + y * width */ - public static final byte CHANGE_TEAM = 7; + public static final byte LOCAL_CHARGE = 11; /** - * A robot's influence changes. - * Target: delta value + * Target: Sage location, x + y * width + */ + public static final byte LOCAL_FURY = 12; + /** + * Target: none + */ + public static final byte ABYSS = 13; + /** + * Target: none + */ + public static final byte CHARGE = 14; + /** + * Target: none */ - public static final byte CHANGE_INFLUENCE = 8; + public static final byte FURY = 15; /** - * A robot's conviction changes. - * Target: delta value, i.e. red 5 -> blue 3 is -2 + * Target: 0 if 90 degrees clockwise, 1 if horizontal, 2 if vertical */ - public static final byte CHANGE_CONVICTION = 9; + public static final byte VORTEX = 16; /** * Dies due to an uncaught exception. * Target: none */ - public static final byte DIE_EXCEPTION = 10; + public static final byte DIE_EXCEPTION = 17; - public static final String[] names = { "EMPOWER", "EMBEZZLE", "CAMOUFLAGE", "EXPOSE", "SET_FLAG", "SPAWN_UNIT", "PLACE_BID", "CHANGE_TEAM", "CHANGE_INFLUENCE", "CHANGE_CONVICTION", "DIE_EXCEPTION", }; + public static final String[] names = { "ATTACK", "SPAWN_UNIT", "MINE_LEAD", "MINE_GOLD", "TRANSMUTE", "TRANSFORM", "MUTATE", "REPAIR", "CHANGE_HEALTH", "FULLY_REPAIRED", "LOCAL_ABYSS", "LOCAL_CHARGE", "LOCAL_FURY", "ABYSS", "CHARGE", "FURY", "VORTEX", "DIE_EXCEPTION", }; public static String name(int e) { return names[e]; } } diff --git a/engine/src/main/battlecode/schema/BodyType.java b/engine/src/main/battlecode/schema/BodyType.java index ee34e38d..aa900424 100644 --- a/engine/src/main/battlecode/schema/BodyType.java +++ b/engine/src/main/battlecode/schema/BodyType.java @@ -8,26 +8,15 @@ */ public final class BodyType { private BodyType() { } - /** - * Enlightenment centers produce politicians, Muckrakers and slanderers and place bids - *can be neutral until captured - */ - public static final byte ENLIGHTENMENT_CENTER = 0; - /** - * politicians use their influence to self destruct and capture other units - */ - public static final byte POLITICIAN = 1; - /** - * slanderers generate passive influence for the enlightenment center that created them - * they turn into politicians at some point, and can only be identified by slanderers. - */ - public static final byte SLANDERER = 2; - /** - * have the ability to identify slanderers - */ - public static final byte MUCKRAKER = 3; + public static final byte MINER = 0; + public static final byte BUILDER = 1; + public static final byte SOLDIER = 2; + public static final byte SAGE = 3; + public static final byte ARCHON = 4; + public static final byte LABORATORY = 5; + public static final byte WATCHTOWER = 6; - public static final String[] names = { "ENLIGHTENMENT_CENTER", "POLITICIAN", "SLANDERER", "MUCKRAKER", }; + public static final String[] names = { "MINER", "BUILDER", "SOLDIER", "SAGE", "ARCHON", "LABORATORY", "WATCHTOWER", }; public static String name(int e) { return names[e]; } } diff --git a/engine/src/main/battlecode/schema/BodyTypeMetadata.java b/engine/src/main/battlecode/schema/BodyTypeMetadata.java index 8b7e63ba..4d68dbd4 100644 --- a/engine/src/main/battlecode/schema/BodyTypeMetadata.java +++ b/engine/src/main/battlecode/schema/BodyTypeMetadata.java @@ -17,69 +17,85 @@ public final class BodyTypeMetadata extends Table { public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public BodyTypeMetadata __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } - /** - * The relevant type. - */ public byte type() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } - /** - * The spawn source. - */ - public byte spawnSource() { int o = __offset(6); return o != 0 ? bb.get(o + bb_pos) : 0; } - /** - * the convictionRatio of this type - */ - public float convictionRatio() { int o = __offset(8); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } - /** - * cooldown of this type - */ - public float actionCooldown() { int o = __offset(10); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } - /** - * action radius if this type - */ - public int actionRadiusSquared() { int o = __offset(12); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - /** - * sensor radius squared for this type - */ - public int sensorRadiusSquared() { int o = __offset(14); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - /** - * detection radius of this type - */ - public int detectionRadiusSquared() { int o = __offset(16); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - /** - * bytecode limit for this type - */ - public int bytecodeLimit() { int o = __offset(18); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int buildCostLead() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int buildCostGold() { int o = __offset(8); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2CostLead() { int o = __offset(10); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2CostGold() { int o = __offset(12); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3CostLead() { int o = __offset(14); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3CostGold() { int o = __offset(16); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int actionCooldown() { int o = __offset(18); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int movementCooldown() { int o = __offset(20); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int health() { int o = __offset(22); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2Health() { int o = __offset(24); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3Health() { int o = __offset(26); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int damage() { int o = __offset(28); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2Damage() { int o = __offset(30); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3Damage() { int o = __offset(32); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int actionRadiusSquared() { int o = __offset(34); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int visionRadiusSquared() { int o = __offset(36); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int bytecodeLimit() { int o = __offset(38); return o != 0 ? bb.getInt(o + bb_pos) : 0; } public static int createBodyTypeMetadata(FlatBufferBuilder builder, byte type, - byte spawnSource, - float convictionRatio, - float actionCooldown, + int buildCostLead, + int buildCostGold, + int level2CostLead, + int level2CostGold, + int level3CostLead, + int level3CostGold, + int actionCooldown, + int movementCooldown, + int health, + int level2Health, + int level3Health, + int damage, + int level2Damage, + int level3Damage, int actionRadiusSquared, - int sensorRadiusSquared, - int detectionRadiusSquared, + int visionRadiusSquared, int bytecodeLimit) { - builder.startObject(8); + builder.startObject(18); BodyTypeMetadata.addBytecodeLimit(builder, bytecodeLimit); - BodyTypeMetadata.addDetectionRadiusSquared(builder, detectionRadiusSquared); - BodyTypeMetadata.addSensorRadiusSquared(builder, sensorRadiusSquared); + BodyTypeMetadata.addVisionRadiusSquared(builder, visionRadiusSquared); BodyTypeMetadata.addActionRadiusSquared(builder, actionRadiusSquared); + BodyTypeMetadata.addLevel3Damage(builder, level3Damage); + BodyTypeMetadata.addLevel2Damage(builder, level2Damage); + BodyTypeMetadata.addDamage(builder, damage); + BodyTypeMetadata.addLevel3Health(builder, level3Health); + BodyTypeMetadata.addLevel2Health(builder, level2Health); + BodyTypeMetadata.addHealth(builder, health); + BodyTypeMetadata.addMovementCooldown(builder, movementCooldown); BodyTypeMetadata.addActionCooldown(builder, actionCooldown); - BodyTypeMetadata.addConvictionRatio(builder, convictionRatio); - BodyTypeMetadata.addSpawnSource(builder, spawnSource); + BodyTypeMetadata.addLevel3CostGold(builder, level3CostGold); + BodyTypeMetadata.addLevel3CostLead(builder, level3CostLead); + BodyTypeMetadata.addLevel2CostGold(builder, level2CostGold); + BodyTypeMetadata.addLevel2CostLead(builder, level2CostLead); + BodyTypeMetadata.addBuildCostGold(builder, buildCostGold); + BodyTypeMetadata.addBuildCostLead(builder, buildCostLead); BodyTypeMetadata.addType(builder, type); return BodyTypeMetadata.endBodyTypeMetadata(builder); } - public static void startBodyTypeMetadata(FlatBufferBuilder builder) { builder.startObject(8); } + public static void startBodyTypeMetadata(FlatBufferBuilder builder) { builder.startObject(18); } public static void addType(FlatBufferBuilder builder, byte type) { builder.addByte(0, type, 0); } - public static void addSpawnSource(FlatBufferBuilder builder, byte spawnSource) { builder.addByte(1, spawnSource, 0); } - public static void addConvictionRatio(FlatBufferBuilder builder, float convictionRatio) { builder.addFloat(2, convictionRatio, 0.0f); } - public static void addActionCooldown(FlatBufferBuilder builder, float actionCooldown) { builder.addFloat(3, actionCooldown, 0.0f); } - public static void addActionRadiusSquared(FlatBufferBuilder builder, int actionRadiusSquared) { builder.addInt(4, actionRadiusSquared, 0); } - public static void addSensorRadiusSquared(FlatBufferBuilder builder, int sensorRadiusSquared) { builder.addInt(5, sensorRadiusSquared, 0); } - public static void addDetectionRadiusSquared(FlatBufferBuilder builder, int detectionRadiusSquared) { builder.addInt(6, detectionRadiusSquared, 0); } - public static void addBytecodeLimit(FlatBufferBuilder builder, int bytecodeLimit) { builder.addInt(7, bytecodeLimit, 0); } + public static void addBuildCostLead(FlatBufferBuilder builder, int buildCostLead) { builder.addInt(1, buildCostLead, 0); } + public static void addBuildCostGold(FlatBufferBuilder builder, int buildCostGold) { builder.addInt(2, buildCostGold, 0); } + public static void addLevel2CostLead(FlatBufferBuilder builder, int level2CostLead) { builder.addInt(3, level2CostLead, 0); } + public static void addLevel2CostGold(FlatBufferBuilder builder, int level2CostGold) { builder.addInt(4, level2CostGold, 0); } + public static void addLevel3CostLead(FlatBufferBuilder builder, int level3CostLead) { builder.addInt(5, level3CostLead, 0); } + public static void addLevel3CostGold(FlatBufferBuilder builder, int level3CostGold) { builder.addInt(6, level3CostGold, 0); } + public static void addActionCooldown(FlatBufferBuilder builder, int actionCooldown) { builder.addInt(7, actionCooldown, 0); } + public static void addMovementCooldown(FlatBufferBuilder builder, int movementCooldown) { builder.addInt(8, movementCooldown, 0); } + public static void addHealth(FlatBufferBuilder builder, int health) { builder.addInt(9, health, 0); } + public static void addLevel2Health(FlatBufferBuilder builder, int level2Health) { builder.addInt(10, level2Health, 0); } + public static void addLevel3Health(FlatBufferBuilder builder, int level3Health) { builder.addInt(11, level3Health, 0); } + public static void addDamage(FlatBufferBuilder builder, int damage) { builder.addInt(12, damage, 0); } + public static void addLevel2Damage(FlatBufferBuilder builder, int level2Damage) { builder.addInt(13, level2Damage, 0); } + public static void addLevel3Damage(FlatBufferBuilder builder, int level3Damage) { builder.addInt(14, level3Damage, 0); } + public static void addActionRadiusSquared(FlatBufferBuilder builder, int actionRadiusSquared) { builder.addInt(15, actionRadiusSquared, 0); } + public static void addVisionRadiusSquared(FlatBufferBuilder builder, int visionRadiusSquared) { builder.addInt(16, visionRadiusSquared, 0); } + public static void addBytecodeLimit(FlatBufferBuilder builder, int bytecodeLimit) { builder.addInt(17, bytecodeLimit, 0); } public static int endBodyTypeMetadata(FlatBufferBuilder builder) { int o = builder.endObject(); return o; diff --git a/engine/src/main/battlecode/schema/Constants.java b/engine/src/main/battlecode/schema/Constants.java new file mode 100644 index 00000000..f82a5a1f --- /dev/null +++ b/engine/src/main/battlecode/schema/Constants.java @@ -0,0 +1,37 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Constants extends Table { + public static Constants getRootAsConstants(ByteBuffer _bb) { return getRootAsConstants(_bb, new Constants()); } + public static Constants getRootAsConstants(ByteBuffer _bb, Constants obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public Constants __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int increasePeriod() { int o = __offset(4); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int leadAdditiveIncease() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + + public static int createConstants(FlatBufferBuilder builder, + int increasePeriod, + int leadAdditiveIncease) { + builder.startObject(2); + Constants.addLeadAdditiveIncease(builder, leadAdditiveIncease); + Constants.addIncreasePeriod(builder, increasePeriod); + return Constants.endConstants(builder); + } + + public static void startConstants(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addIncreasePeriod(FlatBufferBuilder builder, int increasePeriod) { builder.addInt(0, increasePeriod, 0); } + public static void addLeadAdditiveIncease(FlatBufferBuilder builder, int leadAdditiveIncease) { builder.addInt(1, leadAdditiveIncease, 0); } + public static int endConstants(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/engine/src/main/battlecode/schema/GameHeader.java b/engine/src/main/battlecode/schema/GameHeader.java index 77363711..4c93ff54 100644 --- a/engine/src/main/battlecode/schema/GameHeader.java +++ b/engine/src/main/battlecode/schema/GameHeader.java @@ -35,19 +35,23 @@ public final class GameHeader extends Table { public BodyTypeMetadata bodyTypeMetadata(int j) { return bodyTypeMetadata(new BodyTypeMetadata(), j); } public BodyTypeMetadata bodyTypeMetadata(BodyTypeMetadata obj, int j) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int bodyTypeMetadataLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + public Constants constants() { return constants(new Constants()); } + public Constants constants(Constants obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } public static int createGameHeader(FlatBufferBuilder builder, int specVersionOffset, int teamsOffset, - int bodyTypeMetadataOffset) { - builder.startObject(3); + int bodyTypeMetadataOffset, + int constantsOffset) { + builder.startObject(4); + GameHeader.addConstants(builder, constantsOffset); GameHeader.addBodyTypeMetadata(builder, bodyTypeMetadataOffset); GameHeader.addTeams(builder, teamsOffset); GameHeader.addSpecVersion(builder, specVersionOffset); return GameHeader.endGameHeader(builder); } - public static void startGameHeader(FlatBufferBuilder builder) { builder.startObject(3); } + public static void startGameHeader(FlatBufferBuilder builder) { builder.startObject(4); } public static void addSpecVersion(FlatBufferBuilder builder, int specVersionOffset) { builder.addOffset(0, specVersionOffset, 0); } public static void addTeams(FlatBufferBuilder builder, int teamsOffset) { builder.addOffset(1, teamsOffset, 0); } public static int createTeamsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } @@ -55,6 +59,7 @@ public static int createGameHeader(FlatBufferBuilder builder, public static void addBodyTypeMetadata(FlatBufferBuilder builder, int bodyTypeMetadataOffset) { builder.addOffset(2, bodyTypeMetadataOffset, 0); } public static int createBodyTypeMetadataVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } public static void startBodyTypeMetadataVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addConstants(FlatBufferBuilder builder, int constantsOffset) { builder.addOffset(3, constantsOffset, 0); } public static int endGameHeader(FlatBufferBuilder builder) { int o = builder.endObject(); return o; diff --git a/engine/src/main/battlecode/schema/GameMap.java b/engine/src/main/battlecode/schema/GameMap.java index 09b78818..bae5c860 100644 --- a/engine/src/main/battlecode/schema/GameMap.java +++ b/engine/src/main/battlecode/schema/GameMap.java @@ -33,32 +33,67 @@ public final class GameMap extends Table { */ public Vec maxCorner() { return maxCorner(new Vec()); } public Vec maxCorner(Vec obj) { int o = __offset(8); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + /** + * The map symmetry: 0 for rotation, 1 for horizontal, 2 for vertical. + */ + public int symmetry() { int o = __offset(10); return o != 0 ? bb.getInt(o + bb_pos) : 0; } /** * The bodies on the map. */ public SpawnedBodyTable bodies() { return bodies(new SpawnedBodyTable()); } - public SpawnedBodyTable bodies(SpawnedBodyTable obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public SpawnedBodyTable bodies(SpawnedBodyTable obj) { int o = __offset(12); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The random seed of the map. */ - public int randomSeed() { int o = __offset(12); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int randomSeed() { int o = __offset(14); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + /** + * The rubble on the map. + */ + public int rubble(int j) { int o = __offset(16); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int rubbleLength() { int o = __offset(16); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer rubbleAsByteBuffer() { return __vector_as_bytebuffer(16, 4); } + public ByteBuffer rubbleInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 16, 4); } + /** + * The lead on the map. + */ + public int lead(int j) { int o = __offset(18); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int leadLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer leadAsByteBuffer() { return __vector_as_bytebuffer(18, 4); } + public ByteBuffer leadInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 18, 4); } + /** + * The anomalies scheduled: 0/1/2/3 abyss/charge/fury/vortex. + */ + public int anomalies(int j) { int o = __offset(20); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int anomaliesLength() { int o = __offset(20); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer anomaliesAsByteBuffer() { return __vector_as_bytebuffer(20, 4); } + public ByteBuffer anomaliesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 20, 4); } /** - * The factor to divide cooldowns by + * The rounds the anomalies are scheduled for. */ - public double passability(int j) { int o = __offset(14); return o != 0 ? bb.getDouble(__vector(o) + j * 8) : 0; } - public int passabilityLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer passabilityAsByteBuffer() { return __vector_as_bytebuffer(14, 8); } - public ByteBuffer passabilityInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 14, 8); } + public int anomalyRounds(int j) { int o = __offset(22); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int anomalyRoundsLength() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer anomalyRoundsAsByteBuffer() { return __vector_as_bytebuffer(22, 4); } + public ByteBuffer anomalyRoundsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 22, 4); } - public static void startGameMap(FlatBufferBuilder builder) { builder.startObject(6); } + public static void startGameMap(FlatBufferBuilder builder) { builder.startObject(10); } public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } public static void addMinCorner(FlatBufferBuilder builder, int minCornerOffset) { builder.addStruct(1, minCornerOffset, 0); } public static void addMaxCorner(FlatBufferBuilder builder, int maxCornerOffset) { builder.addStruct(2, maxCornerOffset, 0); } - public static void addBodies(FlatBufferBuilder builder, int bodiesOffset) { builder.addOffset(3, bodiesOffset, 0); } - public static void addRandomSeed(FlatBufferBuilder builder, int randomSeed) { builder.addInt(4, randomSeed, 0); } - public static void addPassability(FlatBufferBuilder builder, int passabilityOffset) { builder.addOffset(5, passabilityOffset, 0); } - public static int createPassabilityVector(FlatBufferBuilder builder, double[] data) { builder.startVector(8, data.length, 8); for (int i = data.length - 1; i >= 0; i--) builder.addDouble(data[i]); return builder.endVector(); } - public static void startPassabilityVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 8); } + public static void addSymmetry(FlatBufferBuilder builder, int symmetry) { builder.addInt(3, symmetry, 0); } + public static void addBodies(FlatBufferBuilder builder, int bodiesOffset) { builder.addOffset(4, bodiesOffset, 0); } + public static void addRandomSeed(FlatBufferBuilder builder, int randomSeed) { builder.addInt(5, randomSeed, 0); } + public static void addRubble(FlatBufferBuilder builder, int rubbleOffset) { builder.addOffset(6, rubbleOffset, 0); } + public static int createRubbleVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startRubbleVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addLead(FlatBufferBuilder builder, int leadOffset) { builder.addOffset(7, leadOffset, 0); } + public static int createLeadVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startLeadVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addAnomalies(FlatBufferBuilder builder, int anomaliesOffset) { builder.addOffset(8, anomaliesOffset, 0); } + public static int createAnomaliesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startAnomaliesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addAnomalyRounds(FlatBufferBuilder builder, int anomalyRoundsOffset) { builder.addOffset(9, anomalyRoundsOffset, 0); } + public static int createAnomalyRoundsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startAnomalyRoundsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endGameMap(FlatBufferBuilder builder) { int o = builder.endObject(); return o; diff --git a/engine/src/main/battlecode/schema/Round.java b/engine/src/main/battlecode/schema/Round.java index c36316ae..b7295a4e 100644 --- a/engine/src/main/battlecode/schema/Round.java +++ b/engine/src/main/battlecode/schema/Round.java @@ -28,19 +28,19 @@ public final class Round extends Table { public ByteBuffer teamIDsAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } public ByteBuffer teamIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } /** - * The number of votes the teams get, 0 or 1. + * The total amount of lead change of this team, this round */ - public int teamVotes(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int teamVotesLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer teamVotesAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } - public ByteBuffer teamVotesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } + public int teamLeadChanges(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamLeadChangesLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamLeadChangesAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } + public ByteBuffer teamLeadChangesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } /** - * The ID of the Enlightenment Center got the bid. + * The total amount of gold change of this team, this round */ - public int teamBidderIDs(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int teamBidderIDsLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer teamBidderIDsAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } - public ByteBuffer teamBidderIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } + public int teamGoldChanges(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamGoldChangesLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamGoldChangesAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } + public ByteBuffer teamGoldChangesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } /** * The IDs of bodies that moved. */ @@ -87,100 +87,106 @@ public final class Round extends Table { public int actionTargetsLength() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } public ByteBuffer actionTargetsAsByteBuffer() { return __vector_as_bytebuffer(22, 4); } public ByteBuffer actionTargetsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 22, 4); } + /** + * The locations of lead drops + */ + public VecTable leadDropLocations() { return leadDropLocations(new VecTable()); } + public VecTable leadDropLocations(VecTable obj) { int o = __offset(24); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The amount of lead dropped at each location + */ + public int leadDropValues(int j) { int o = __offset(26); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int leadDropValuesLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer leadDropValuesAsByteBuffer() { return __vector_as_bytebuffer(26, 4); } + public ByteBuffer leadDropValuesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 26, 4); } + /** + * The locations of gold drops + */ + public VecTable goldDropLocations() { return goldDropLocations(new VecTable()); } + public VecTable goldDropLocations(VecTable obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The amount of gold dropped at each location + */ + public int goldDropValues(int j) { int o = __offset(30); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int goldDropValuesLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer goldDropValuesAsByteBuffer() { return __vector_as_bytebuffer(30, 4); } + public ByteBuffer goldDropValuesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 30, 4); } + /** + * The IDs of the robots who changed their indicator strings + */ + public int indicatorStringIDs(int j) { int o = __offset(32); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int indicatorStringIDsLength() { int o = __offset(32); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer indicatorStringIDsAsByteBuffer() { return __vector_as_bytebuffer(32, 4); } + public ByteBuffer indicatorStringIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 32, 4); } + /** + * The messages of the robots who changed their indicator strings + */ + public String indicatorStrings(int j) { int o = __offset(34); return o != 0 ? __string(__vector(o) + j * 4) : null; } + public int indicatorStringsLength() { int o = __offset(34); return o != 0 ? __vector_len(o) : 0; } /** * The IDs of bodies that set indicator dots */ - public int indicatorDotIDs(int j) { int o = __offset(24); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int indicatorDotIDsLength() { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer indicatorDotIDsAsByteBuffer() { return __vector_as_bytebuffer(24, 4); } - public ByteBuffer indicatorDotIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 24, 4); } + public int indicatorDotIDs(int j) { int o = __offset(36); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int indicatorDotIDsLength() { int o = __offset(36); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer indicatorDotIDsAsByteBuffer() { return __vector_as_bytebuffer(36, 4); } + public ByteBuffer indicatorDotIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 36, 4); } /** * The location of the indicator dots */ public VecTable indicatorDotLocs() { return indicatorDotLocs(new VecTable()); } - public VecTable indicatorDotLocs(VecTable obj) { int o = __offset(26); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable indicatorDotLocs(VecTable obj) { int o = __offset(38); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The RGB values of the indicator dots */ public RGBTable indicatorDotRGBs() { return indicatorDotRGBs(new RGBTable()); } - public RGBTable indicatorDotRGBs(RGBTable obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public RGBTable indicatorDotRGBs(RGBTable obj) { int o = __offset(40); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The IDs of bodies that set indicator lines */ - public int indicatorLineIDs(int j) { int o = __offset(30); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int indicatorLineIDsLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer indicatorLineIDsAsByteBuffer() { return __vector_as_bytebuffer(30, 4); } - public ByteBuffer indicatorLineIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 30, 4); } + public int indicatorLineIDs(int j) { int o = __offset(42); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int indicatorLineIDsLength() { int o = __offset(42); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer indicatorLineIDsAsByteBuffer() { return __vector_as_bytebuffer(42, 4); } + public ByteBuffer indicatorLineIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 42, 4); } /** * The start location of the indicator lines */ public VecTable indicatorLineStartLocs() { return indicatorLineStartLocs(new VecTable()); } - public VecTable indicatorLineStartLocs(VecTable obj) { int o = __offset(32); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable indicatorLineStartLocs(VecTable obj) { int o = __offset(44); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The end location of the indicator lines */ public VecTable indicatorLineEndLocs() { return indicatorLineEndLocs(new VecTable()); } - public VecTable indicatorLineEndLocs(VecTable obj) { int o = __offset(34); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable indicatorLineEndLocs(VecTable obj) { int o = __offset(46); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The RGB values of the indicator lines */ public RGBTable indicatorLineRGBs() { return indicatorLineRGBs(new RGBTable()); } - public RGBTable indicatorLineRGBs(RGBTable obj) { int o = __offset(36); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } - /** - * All logs sent this round. - * Messages from a particular robot in this round start on a new line, and - * have a header: - * '[' $TEAM ':' $ROBOTTYPE '#' $ID '@' $ROUND '] ' - * $TEAM = 'A' | 'B' - * $ROBOTTYPE = 'ENLIGHTENMENT_CENTER' | 'POLITICIAN' | 'SLANDERER' | 'MUCKRAKER' - * $ID = a number - * $ROUND = a number - * The header is not necessarily followed by a newline. - * This header should only be sent once per robot per round (although - * players may forge it, so don't crash if you get strange input.) - * - * You should try to only read this value once, and cache it. Reading - * strings from a flatbuffer is much less efficient than reading other - * buffers, because they need to be copied into an environment-provided - * buffer and validated. - * - * (haha i guess you can never really escape string parsing can you) - */ - public String logs() { int o = __offset(38); return o != 0 ? __string(o + bb_pos) : null; } - public ByteBuffer logsAsByteBuffer() { return __vector_as_bytebuffer(38, 1); } - public ByteBuffer logsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 38, 1); } + public RGBTable indicatorLineRGBs(RGBTable obj) { int o = __offset(48); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The first sent Round in a match should have index 1. (The starting state, * created by the MatchHeader, can be thought to have index 0.) * It should increase by one for each following round. */ - public int roundID() { int o = __offset(40); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int roundID() { int o = __offset(50); return o != 0 ? bb.getInt(o + bb_pos) : 0; } /** * The IDs of player bodies. */ - public int bytecodeIDs(int j) { int o = __offset(42); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int bytecodeIDsLength() { int o = __offset(42); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer bytecodeIDsAsByteBuffer() { return __vector_as_bytebuffer(42, 4); } - public ByteBuffer bytecodeIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 42, 4); } + public int bytecodeIDs(int j) { int o = __offset(52); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int bytecodeIDsLength() { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer bytecodeIDsAsByteBuffer() { return __vector_as_bytebuffer(52, 4); } + public ByteBuffer bytecodeIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 52, 4); } /** * The bytecodes used by the player bodies. */ - public int bytecodesUsed(int j) { int o = __offset(44); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int bytecodesUsedLength() { int o = __offset(44); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer bytecodesUsedAsByteBuffer() { return __vector_as_bytebuffer(44, 4); } - public ByteBuffer bytecodesUsedInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 44, 4); } - /** - * Amount of influence contributing to the teams' buffs. Added at end for backwards compatability. - */ - public int teamNumBuffs(int j) { int o = __offset(46); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int teamNumBuffsLength() { int o = __offset(46); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer teamNumBuffsAsByteBuffer() { return __vector_as_bytebuffer(46, 4); } - public ByteBuffer teamNumBuffsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 46, 4); } + public int bytecodesUsed(int j) { int o = __offset(54); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int bytecodesUsedLength() { int o = __offset(54); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer bytecodesUsedAsByteBuffer() { return __vector_as_bytebuffer(54, 4); } + public ByteBuffer bytecodesUsedInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 54, 4); } public static int createRound(FlatBufferBuilder builder, int teamIDsOffset, - int teamVotesOffset, - int teamBidderIDsOffset, + int teamLeadChangesOffset, + int teamGoldChangesOffset, int movedIDsOffset, int movedLocsOffset, int spawnedBodiesOffset, @@ -188,6 +194,12 @@ public static int createRound(FlatBufferBuilder builder, int actionIDsOffset, int actionsOffset, int actionTargetsOffset, + int leadDropLocationsOffset, + int leadDropValuesOffset, + int goldDropLocationsOffset, + int goldDropValuesOffset, + int indicatorStringIDsOffset, + int indicatorStringsOffset, int indicatorDotIDsOffset, int indicatorDotLocsOffset, int indicatorDotRGBsOffset, @@ -195,17 +207,13 @@ public static int createRound(FlatBufferBuilder builder, int indicatorLineStartLocsOffset, int indicatorLineEndLocsOffset, int indicatorLineRGBsOffset, - int logsOffset, int roundID, int bytecodeIDsOffset, - int bytecodesUsedOffset, - int teamNumBuffsOffset) { - builder.startObject(22); - Round.addTeamNumBuffs(builder, teamNumBuffsOffset); + int bytecodesUsedOffset) { + builder.startObject(26); Round.addBytecodesUsed(builder, bytecodesUsedOffset); Round.addBytecodeIDs(builder, bytecodeIDsOffset); Round.addRoundID(builder, roundID); - Round.addLogs(builder, logsOffset); Round.addIndicatorLineRGBs(builder, indicatorLineRGBsOffset); Round.addIndicatorLineEndLocs(builder, indicatorLineEndLocsOffset); Round.addIndicatorLineStartLocs(builder, indicatorLineStartLocsOffset); @@ -213,6 +221,12 @@ public static int createRound(FlatBufferBuilder builder, Round.addIndicatorDotRGBs(builder, indicatorDotRGBsOffset); Round.addIndicatorDotLocs(builder, indicatorDotLocsOffset); Round.addIndicatorDotIDs(builder, indicatorDotIDsOffset); + Round.addIndicatorStrings(builder, indicatorStringsOffset); + Round.addIndicatorStringIDs(builder, indicatorStringIDsOffset); + Round.addGoldDropValues(builder, goldDropValuesOffset); + Round.addGoldDropLocations(builder, goldDropLocationsOffset); + Round.addLeadDropValues(builder, leadDropValuesOffset); + Round.addLeadDropLocations(builder, leadDropLocationsOffset); Round.addActionTargets(builder, actionTargetsOffset); Round.addActions(builder, actionsOffset); Round.addActionIDs(builder, actionIDsOffset); @@ -220,22 +234,22 @@ public static int createRound(FlatBufferBuilder builder, Round.addSpawnedBodies(builder, spawnedBodiesOffset); Round.addMovedLocs(builder, movedLocsOffset); Round.addMovedIDs(builder, movedIDsOffset); - Round.addTeamBidderIDs(builder, teamBidderIDsOffset); - Round.addTeamVotes(builder, teamVotesOffset); + Round.addTeamGoldChanges(builder, teamGoldChangesOffset); + Round.addTeamLeadChanges(builder, teamLeadChangesOffset); Round.addTeamIDs(builder, teamIDsOffset); return Round.endRound(builder); } - public static void startRound(FlatBufferBuilder builder) { builder.startObject(22); } + public static void startRound(FlatBufferBuilder builder) { builder.startObject(26); } public static void addTeamIDs(FlatBufferBuilder builder, int teamIDsOffset) { builder.addOffset(0, teamIDsOffset, 0); } public static int createTeamIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startTeamIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addTeamVotes(FlatBufferBuilder builder, int teamVotesOffset) { builder.addOffset(1, teamVotesOffset, 0); } - public static int createTeamVotesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startTeamVotesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addTeamBidderIDs(FlatBufferBuilder builder, int teamBidderIDsOffset) { builder.addOffset(2, teamBidderIDsOffset, 0); } - public static int createTeamBidderIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startTeamBidderIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamLeadChanges(FlatBufferBuilder builder, int teamLeadChangesOffset) { builder.addOffset(1, teamLeadChangesOffset, 0); } + public static int createTeamLeadChangesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamLeadChangesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamGoldChanges(FlatBufferBuilder builder, int teamGoldChangesOffset) { builder.addOffset(2, teamGoldChangesOffset, 0); } + public static int createTeamGoldChangesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamGoldChangesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static void addMovedIDs(FlatBufferBuilder builder, int movedIDsOffset) { builder.addOffset(3, movedIDsOffset, 0); } public static int createMovedIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startMovedIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -253,28 +267,38 @@ public static int createRound(FlatBufferBuilder builder, public static void addActionTargets(FlatBufferBuilder builder, int actionTargetsOffset) { builder.addOffset(9, actionTargetsOffset, 0); } public static int createActionTargetsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startActionTargetsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addIndicatorDotIDs(FlatBufferBuilder builder, int indicatorDotIDsOffset) { builder.addOffset(10, indicatorDotIDsOffset, 0); } + public static void addLeadDropLocations(FlatBufferBuilder builder, int leadDropLocationsOffset) { builder.addOffset(10, leadDropLocationsOffset, 0); } + public static void addLeadDropValues(FlatBufferBuilder builder, int leadDropValuesOffset) { builder.addOffset(11, leadDropValuesOffset, 0); } + public static int createLeadDropValuesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startLeadDropValuesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addGoldDropLocations(FlatBufferBuilder builder, int goldDropLocationsOffset) { builder.addOffset(12, goldDropLocationsOffset, 0); } + public static void addGoldDropValues(FlatBufferBuilder builder, int goldDropValuesOffset) { builder.addOffset(13, goldDropValuesOffset, 0); } + public static int createGoldDropValuesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startGoldDropValuesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorStringIDs(FlatBufferBuilder builder, int indicatorStringIDsOffset) { builder.addOffset(14, indicatorStringIDsOffset, 0); } + public static int createIndicatorStringIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startIndicatorStringIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorStrings(FlatBufferBuilder builder, int indicatorStringsOffset) { builder.addOffset(15, indicatorStringsOffset, 0); } + public static int createIndicatorStringsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startIndicatorStringsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorDotIDs(FlatBufferBuilder builder, int indicatorDotIDsOffset) { builder.addOffset(16, indicatorDotIDsOffset, 0); } public static int createIndicatorDotIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startIndicatorDotIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addIndicatorDotLocs(FlatBufferBuilder builder, int indicatorDotLocsOffset) { builder.addOffset(11, indicatorDotLocsOffset, 0); } - public static void addIndicatorDotRGBs(FlatBufferBuilder builder, int indicatorDotRGBsOffset) { builder.addOffset(12, indicatorDotRGBsOffset, 0); } - public static void addIndicatorLineIDs(FlatBufferBuilder builder, int indicatorLineIDsOffset) { builder.addOffset(13, indicatorLineIDsOffset, 0); } + public static void addIndicatorDotLocs(FlatBufferBuilder builder, int indicatorDotLocsOffset) { builder.addOffset(17, indicatorDotLocsOffset, 0); } + public static void addIndicatorDotRGBs(FlatBufferBuilder builder, int indicatorDotRGBsOffset) { builder.addOffset(18, indicatorDotRGBsOffset, 0); } + public static void addIndicatorLineIDs(FlatBufferBuilder builder, int indicatorLineIDsOffset) { builder.addOffset(19, indicatorLineIDsOffset, 0); } public static int createIndicatorLineIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startIndicatorLineIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addIndicatorLineStartLocs(FlatBufferBuilder builder, int indicatorLineStartLocsOffset) { builder.addOffset(14, indicatorLineStartLocsOffset, 0); } - public static void addIndicatorLineEndLocs(FlatBufferBuilder builder, int indicatorLineEndLocsOffset) { builder.addOffset(15, indicatorLineEndLocsOffset, 0); } - public static void addIndicatorLineRGBs(FlatBufferBuilder builder, int indicatorLineRGBsOffset) { builder.addOffset(16, indicatorLineRGBsOffset, 0); } - public static void addLogs(FlatBufferBuilder builder, int logsOffset) { builder.addOffset(17, logsOffset, 0); } - public static void addRoundID(FlatBufferBuilder builder, int roundID) { builder.addInt(18, roundID, 0); } - public static void addBytecodeIDs(FlatBufferBuilder builder, int bytecodeIDsOffset) { builder.addOffset(19, bytecodeIDsOffset, 0); } + public static void addIndicatorLineStartLocs(FlatBufferBuilder builder, int indicatorLineStartLocsOffset) { builder.addOffset(20, indicatorLineStartLocsOffset, 0); } + public static void addIndicatorLineEndLocs(FlatBufferBuilder builder, int indicatorLineEndLocsOffset) { builder.addOffset(21, indicatorLineEndLocsOffset, 0); } + public static void addIndicatorLineRGBs(FlatBufferBuilder builder, int indicatorLineRGBsOffset) { builder.addOffset(22, indicatorLineRGBsOffset, 0); } + public static void addRoundID(FlatBufferBuilder builder, int roundID) { builder.addInt(23, roundID, 0); } + public static void addBytecodeIDs(FlatBufferBuilder builder, int bytecodeIDsOffset) { builder.addOffset(24, bytecodeIDsOffset, 0); } public static int createBytecodeIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startBytecodeIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addBytecodesUsed(FlatBufferBuilder builder, int bytecodesUsedOffset) { builder.addOffset(20, bytecodesUsedOffset, 0); } + public static void addBytecodesUsed(FlatBufferBuilder builder, int bytecodesUsedOffset) { builder.addOffset(25, bytecodesUsedOffset, 0); } public static int createBytecodesUsedVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startBytecodesUsedVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addTeamNumBuffs(FlatBufferBuilder builder, int teamNumBuffsOffset) { builder.addOffset(21, teamNumBuffsOffset, 0); } - public static int createTeamNumBuffsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startTeamNumBuffsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endRound(FlatBufferBuilder builder) { int o = builder.endObject(); return o; diff --git a/engine/src/main/battlecode/schema/SpawnedBodyTable.java b/engine/src/main/battlecode/schema/SpawnedBodyTable.java index 3616e911..71bf66ec 100644 --- a/engine/src/main/battlecode/schema/SpawnedBodyTable.java +++ b/engine/src/main/battlecode/schema/SpawnedBodyTable.java @@ -47,24 +47,13 @@ public final class SpawnedBodyTable extends Table { */ public VecTable locs() { return locs(new VecTable()); } public VecTable locs(VecTable obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } - /** - * the amount of influence paid to create these bodies - * for initial Enlightenment Centers, this is the amount of influence - * needed to take over - */ - public int influences(int j) { int o = __offset(12); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int influencesLength() { int o = __offset(12); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer influencesAsByteBuffer() { return __vector_as_bytebuffer(12, 4); } - public ByteBuffer influencesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 12, 4); } public static int createSpawnedBodyTable(FlatBufferBuilder builder, int robotIDsOffset, int teamIDsOffset, int typesOffset, - int locsOffset, - int influencesOffset) { - builder.startObject(5); - SpawnedBodyTable.addInfluences(builder, influencesOffset); + int locsOffset) { + builder.startObject(4); SpawnedBodyTable.addLocs(builder, locsOffset); SpawnedBodyTable.addTypes(builder, typesOffset); SpawnedBodyTable.addTeamIDs(builder, teamIDsOffset); @@ -72,7 +61,7 @@ public static int createSpawnedBodyTable(FlatBufferBuilder builder, return SpawnedBodyTable.endSpawnedBodyTable(builder); } - public static void startSpawnedBodyTable(FlatBufferBuilder builder) { builder.startObject(5); } + public static void startSpawnedBodyTable(FlatBufferBuilder builder) { builder.startObject(4); } public static void addRobotIDs(FlatBufferBuilder builder, int robotIDsOffset) { builder.addOffset(0, robotIDsOffset, 0); } public static int createRobotIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startRobotIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -83,9 +72,6 @@ public static int createSpawnedBodyTable(FlatBufferBuilder builder, public static int createTypesVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } public static void startTypesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } public static void addLocs(FlatBufferBuilder builder, int locsOffset) { builder.addOffset(3, locsOffset, 0); } - public static void addInfluences(FlatBufferBuilder builder, int influencesOffset) { builder.addOffset(4, influencesOffset, 0); } - public static int createInfluencesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startInfluencesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endSpawnedBodyTable(FlatBufferBuilder builder) { int o = builder.endObject(); return o; diff --git a/engine/src/main/battlecode/server/GameMaker.java b/engine/src/main/battlecode/server/GameMaker.java index f548f134..9032b68a 100644 --- a/engine/src/main/battlecode/server/GameMaker.java +++ b/engine/src/main/battlecode/server/GameMaker.java @@ -17,6 +17,7 @@ import gnu.trove.list.array.TIntArrayList; import gnu.trove.list.array.TCharArrayList; import java.util.List; +import java.util.ArrayList; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -197,7 +198,7 @@ public byte[] toBytes() { * @param saveFile the file to save to */ public void writeGame(File saveFile) { - if(saveFile == null) { + if (saveFile == null) { throw new RuntimeException("Null file provided to writeGame"); } @@ -236,7 +237,7 @@ public MatchMaker getMatchMaker() { return this.matchMaker; } - public void makeGameHeader(){ + public void makeGameHeader() { changeState(State.GAME_HEADER, State.IN_GAME); @@ -263,29 +264,45 @@ public void makeGameHeader(){ int teamsOffset = GameHeader.createTeamsVector(builder, teamsVec); int bodyTypeMetadataOffset = makeBodyTypeMetadata(builder); + Constants.startConstants(builder); + Constants.addIncreasePeriod(builder, GameConstants.ADD_LEAD_EVERY_ROUNDS); + Constants.addLeadAdditiveIncease(builder, GameConstants.ADD_LEAD); + int constantsOffset = Constants.endConstants(builder); + GameHeader.startGameHeader(builder); GameHeader.addSpecVersion(builder, specVersionOffset); GameHeader.addTeams(builder, teamsOffset); GameHeader.addBodyTypeMetadata(builder, bodyTypeMetadataOffset); + GameHeader.addConstants(builder, constantsOffset); int gameHeaderOffset = GameHeader.endGameHeader(builder); return EventWrapper.createEventWrapper(builder, Event.GameHeader, gameHeaderOffset); }); } - public int makeBodyTypeMetadata(FlatBufferBuilder builder){ + public int makeBodyTypeMetadata(FlatBufferBuilder builder) { TIntArrayList bodyTypeMetadataOffsets = new TIntArrayList(); // Add robot metadata for (RobotType type : RobotType.values()) { BodyTypeMetadata.startBodyTypeMetadata(builder); BodyTypeMetadata.addType(builder, robotTypeToBodyType(type)); - BodyTypeMetadata.addSpawnSource(builder, robotTypeToBodyType(type.spawnSource)); - BodyTypeMetadata.addConvictionRatio(builder, type.convictionRatio); + BodyTypeMetadata.addBuildCostLead(builder, type.buildCostLead); + BodyTypeMetadata.addBuildCostGold(builder, type.buildCostGold); + BodyTypeMetadata.addLevel2CostLead(builder, type.getLeadMutateCost(2)); + BodyTypeMetadata.addLevel2CostGold(builder, type.getGoldMutateCost(2)); + BodyTypeMetadata.addLevel3CostLead(builder, type.getLeadMutateCost(3)); + BodyTypeMetadata.addLevel3CostGold(builder, type.getGoldMutateCost(3)); BodyTypeMetadata.addActionCooldown(builder, type.actionCooldown); + BodyTypeMetadata.addMovementCooldown(builder, type.movementCooldown); + BodyTypeMetadata.addHealth(builder, type.health); + BodyTypeMetadata.addLevel2Health(builder, type.getMaxHealth(2)); + BodyTypeMetadata.addLevel3Health(builder, type.getMaxHealth(3)); + BodyTypeMetadata.addDamage(builder, type.damage); + BodyTypeMetadata.addLevel2Damage(builder, type.getDamage(2)); + BodyTypeMetadata.addLevel3Damage(builder, type.getDamage(3)); BodyTypeMetadata.addActionRadiusSquared(builder, type.actionRadiusSquared); - BodyTypeMetadata.addSensorRadiusSquared(builder, type.sensorRadiusSquared); - BodyTypeMetadata.addDetectionRadiusSquared(builder, type.detectionRadiusSquared); + BodyTypeMetadata.addVisionRadiusSquared(builder, type.visionRadiusSquared); BodyTypeMetadata.addBytecodeLimit(builder, type.bytecodeLimit); bodyTypeMetadataOffsets.add(BodyTypeMetadata.endBodyTypeMetadata(builder)); } @@ -294,15 +311,18 @@ public int makeBodyTypeMetadata(FlatBufferBuilder builder){ return GameHeader.createBodyTypeMetadataVector(builder, bodyTypeMetadataOffsets.toArray()); } - private byte robotTypeToBodyType(RobotType type){ - if (type == RobotType.ENLIGHTENMENT_CENTER) return BodyType.ENLIGHTENMENT_CENTER; - if (type == RobotType.POLITICIAN) return BodyType.POLITICIAN; - if (type == RobotType.SLANDERER) return BodyType.SLANDERER; - if (type == RobotType.MUCKRAKER) return BodyType.MUCKRAKER; + private byte robotTypeToBodyType(RobotType type) { + if (type == RobotType.ARCHON) return BodyType.ARCHON; + if (type == RobotType.LABORATORY) return BodyType.LABORATORY; + if (type == RobotType.WATCHTOWER) return BodyType.WATCHTOWER; + if (type == RobotType.MINER) return BodyType.MINER; + if (type == RobotType.BUILDER) return BodyType.BUILDER; + if (type == RobotType.SOLDIER) return BodyType.SOLDIER; + if (type == RobotType.SAGE) return BodyType.SAGE; return Byte.MIN_VALUE; } - public void makeGameFooter(Team winner){ + public void makeGameFooter(Team winner) { changeState(State.IN_GAME, State.DONE); createEvent((builder) -> EventWrapper.createEventWrapper(builder, Event.GameFooter, @@ -320,8 +340,8 @@ public void makeGameFooter(Team winner){ public class MatchMaker { private TIntArrayList movedIDs; // ints // VecTable for movedLocs in Round - private TIntArrayList movedLocsXs; - private TIntArrayList movedLocsYs; + private TIntArrayList movedLocsX; + private TIntArrayList movedLocsY; // SpawnedBodyTable for spawnedBodies private TIntArrayList spawnedBodiesRobotIDs; @@ -329,7 +349,6 @@ public class MatchMaker { private TByteArrayList spawnedBodiesTypes; private TIntArrayList spawnedBodiesLocsXs; //For locs private TIntArrayList spawnedBodiesLocsYs; //For locs - private TIntArrayList spawnedBodiesInfluences; private TIntArrayList diedIDs; // ints @@ -337,11 +356,21 @@ public class MatchMaker { private TByteArrayList actions; // Actions private TIntArrayList actionTargets; // ints (IDs) + private TIntArrayList leadDropLocsX; + private TIntArrayList leadDropLocsY; + private TIntArrayList leadDropValues; + + private TIntArrayList goldDropLocsX; + private TIntArrayList goldDropLocsY; + private TIntArrayList goldDropValues; + // Round statistics private TIntArrayList teamIDs; - private TIntArrayList teamVotes; - private TIntArrayList teamBidderIDs; - private TIntArrayList teamNumBuffs; + private TIntArrayList teamLeadChanges; + private TIntArrayList teamGoldChanges; + + private TIntArrayList indicatorStringIDs; + private ArrayList indicatorStrings; // Indicator dots with locations and RGB values private TIntArrayList indicatorDotIDs; @@ -370,22 +399,28 @@ public class MatchMaker { public MatchMaker() { this.movedIDs = new TIntArrayList(); - this.movedLocsXs = new TIntArrayList(); - this.movedLocsYs = new TIntArrayList(); + this.movedLocsX = new TIntArrayList(); + this.movedLocsY = new TIntArrayList(); this.spawnedBodiesRobotIDs = new TIntArrayList(); this.spawnedBodiesTeamIDs = new TByteArrayList(); this.spawnedBodiesTypes = new TByteArrayList(); this.spawnedBodiesLocsXs = new TIntArrayList(); this.spawnedBodiesLocsYs = new TIntArrayList(); - this.spawnedBodiesInfluences = new TIntArrayList(); this.diedIDs = new TIntArrayList(); this.actionIDs = new TIntArrayList(); this.actions = new TByteArrayList(); this.actionTargets = new TIntArrayList(); + this.leadDropLocsX = new TIntArrayList(); + this.leadDropLocsY = new TIntArrayList(); + this.leadDropValues = new TIntArrayList(); + this.goldDropLocsX = new TIntArrayList(); + this.goldDropLocsY = new TIntArrayList(); + this.goldDropValues = new TIntArrayList(); this.teamIDs = new TIntArrayList(); - this.teamVotes = new TIntArrayList(); - this.teamBidderIDs = new TIntArrayList(); - this.teamNumBuffs = new TIntArrayList(); + this.teamLeadChanges = new TIntArrayList(); + this.teamGoldChanges = new TIntArrayList(); + this.indicatorStringIDs = new TIntArrayList(); + this.indicatorStrings = new ArrayList<>(); this.indicatorDotIDs = new TIntArrayList(); this.indicatorDotLocsX = new TIntArrayList(); this.indicatorDotLocsY = new TIntArrayList(); @@ -477,7 +512,7 @@ public void makeRound(int roundNum) { } catch (IOException e) { throw new RuntimeException("Can't flush byte[]outputstream?", e); } - byte[] logs = this.logger.toByteArray(); + // byte[] logs = this.logger.toByteArray(); this.logger.reset(); createEvent((builder) -> { @@ -486,24 +521,21 @@ public void makeRound(int roundNum) { int spawnedBodiesRobotIDsP = SpawnedBodyTable.createRobotIDsVector(builder, spawnedBodiesRobotIDs.toArray()); int spawnedBodiesTeamIDsP = SpawnedBodyTable.createTeamIDsVector(builder, spawnedBodiesTeamIDs.toArray()); int spawnedBodiesTypesP = SpawnedBodyTable.createTypesVector(builder, spawnedBodiesTypes.toArray()); - int spawnedBodiesInfluencesP = SpawnedBodyTable.createInfluencesVector(builder, spawnedBodiesInfluences.toArray()); SpawnedBodyTable.startSpawnedBodyTable(builder); SpawnedBodyTable.addLocs(builder, spawnedBodiesLocsP); SpawnedBodyTable.addRobotIDs(builder, spawnedBodiesRobotIDsP); SpawnedBodyTable.addTeamIDs(builder, spawnedBodiesTeamIDsP); SpawnedBodyTable.addTypes(builder, spawnedBodiesTypesP); - SpawnedBodyTable.addInfluences(builder, spawnedBodiesInfluencesP); int spawnedBodiesP = SpawnedBodyTable.endSpawnedBodyTable(builder); // Round statistics int teamIDsP = Round.createTeamIDsVector(builder, teamIDs.toArray()); - int teamVotesP = Round.createTeamVotesVector(builder, teamVotes.toArray()); - int teamBidderIDsP = Round.createTeamBidderIDsVector(builder, teamBidderIDs.toArray()); - int teamNumBuffsP = Round.createTeamNumBuffsVector(builder, teamNumBuffs.toArray()); + int teamLeadChangesP = Round.createTeamLeadChangesVector(builder, teamLeadChanges.toArray()); + int teamGoldChangesP = Round.createTeamGoldChangesVector(builder, teamGoldChanges.toArray()); // The bodies that moved int movedIDsP = Round.createMovedIDsVector(builder, movedIDs.toArray()); - int movedLocsP = createVecTable(builder, movedLocsXs, movedLocsYs); + int movedLocsP = createVecTable(builder, movedLocsX, movedLocsY); // The bodies that died int diedIDsP = Round.createDiedIDsVector(builder, diedIDs.toArray()); @@ -513,6 +545,20 @@ public void makeRound(int roundNum) { int actionsP = Round.createActionsVector(builder, actions.toArray()); int actionTargetsP = Round.createActionTargetsVector(builder, actionTargets.toArray()); + // The lead and gold dropped + int leadDropLocsP = createVecTable(builder, leadDropLocsX, leadDropLocsY); + int leadDropValuesP = Round.createLeadDropValuesVector(builder, leadDropValues.toArray()); + int goldDropLocsP = createVecTable(builder, goldDropLocsX, goldDropLocsY); + int goldDropValuesP = Round.createGoldDropValuesVector(builder, goldDropValues.toArray()); + + // The indicator strings that were set + int indicatorStringIDsP = Round.createIndicatorStringIDsVector(builder, indicatorStringIDs.toArray()); + TIntArrayList indicatorStringsIntList = new TIntArrayList(); + for (String s : indicatorStrings) { + indicatorStringsIntList.add(builder.createString(s)); + } + int indicatorStringsP = Round.createIndicatorStringsVector(builder, indicatorStringsIntList.toArray()); + // The indicator dots that were set int indicatorDotIDsP = Round.createIndicatorDotIDsVector(builder, indicatorDotIDs.toArray()); int indicatorDotLocsP = createVecTable(builder, indicatorDotLocsX, indicatorDotLocsY); @@ -528,13 +574,10 @@ public void makeRound(int roundNum) { int bytecodeIDsP = Round.createBytecodeIDsVector(builder, bytecodeIDs.toArray()); int bytecodesUsedP = Round.createBytecodesUsedVector(builder, bytecodesUsed.toArray()); - int logsP = builder.createString(ByteBuffer.wrap(logs)); - Round.startRound(builder); Round.addTeamIDs(builder, teamIDsP); - Round.addTeamVotes(builder, teamVotesP); - Round.addTeamBidderIDs(builder, teamBidderIDsP); - Round.addTeamNumBuffs(builder, teamNumBuffsP); + Round.addTeamLeadChanges(builder, teamLeadChangesP); + Round.addTeamGoldChanges(builder, teamGoldChangesP); Round.addMovedIDs(builder, movedIDsP); Round.addMovedLocs(builder, movedLocsP); Round.addSpawnedBodies(builder, spawnedBodiesP); @@ -542,6 +585,12 @@ public void makeRound(int roundNum) { Round.addActionIDs(builder, actionIDsP); Round.addActions(builder, actionsP); Round.addActionTargets(builder, actionTargetsP); + Round.addLeadDropLocations(builder, leadDropLocsP); + Round.addLeadDropValues(builder, leadDropValuesP); + Round.addGoldDropLocations(builder, goldDropLocsP); + Round.addGoldDropValues(builder, goldDropValuesP); + Round.addIndicatorStringIDs(builder, indicatorStringIDsP); + Round.addIndicatorStrings(builder, indicatorStringsP); Round.addIndicatorDotIDs(builder, indicatorDotIDsP); Round.addIndicatorDotLocs(builder, indicatorDotLocsP); Round.addIndicatorDotRGBs(builder, indicatorDotRGBsP); @@ -552,7 +601,6 @@ public void makeRound(int roundNum) { Round.addRoundID(builder, roundNum); Round.addBytecodeIDs(builder, bytecodeIDsP); Round.addBytecodesUsed(builder, bytecodesUsedP); - Round.addLogs(builder, logsP); int round = Round.endRound(builder); return EventWrapper.createEventWrapper(builder, Event.Round, round); }); @@ -569,8 +617,8 @@ public OutputStream getOut() { public void addMoved(int id, MapLocation newLocation) { movedIDs.add(id); - movedLocsXs.add(newLocation.x); - movedLocsYs.add(newLocation.y); + movedLocsX.add(newLocation.x); + movedLocsY.add(newLocation.y); } public void addDied(int id) { @@ -583,11 +631,30 @@ public void addAction(int userID, byte action, int targetID) { actionTargets.add(targetID); } - public void addTeamInfo(Team team, int vote, int bidderID, int numBuffs) { + public void addLeadDrop(MapLocation location, int value) { + leadDropLocsX.add(location.x); + leadDropLocsY.add(location.y); + leadDropValues.add(value); + } + + public void addGoldDrop(MapLocation location, int value) { + goldDropLocsX.add(location.x); + goldDropLocsY.add(location.y); + goldDropValues.add(value); + } + + public void addTeamInfo(Team team, int leadChange, int goldChange) { teamIDs.add(TeamMapping.id(team)); - teamVotes.add(vote); - teamBidderIDs.add(bidderID); - teamNumBuffs.add(numBuffs); + teamLeadChanges.add(leadChange); + teamGoldChanges.add(goldChange); + } + + public void addIndicatorString(int id, String string) { + if (!showIndicators) { + return; + } + indicatorStringIDs.add(id); + indicatorStrings.add(string); } public void addIndicatorDot(int id, MapLocation loc, int red, int green, int blue) { @@ -627,27 +694,32 @@ public void addSpawnedRobot(InternalRobot robot) { spawnedBodiesLocsYs.add(robot.getLocation().y); spawnedBodiesTeamIDs.add(TeamMapping.id(robot.getTeam())); spawnedBodiesTypes.add(FlatHelpers.getBodyTypeFromRobotType(robot.getType())); - spawnedBodiesInfluences.add(robot.getInfluence()); } private void clearData() { movedIDs.clear(); - movedLocsXs.clear(); - movedLocsYs.clear(); + movedLocsX.clear(); + movedLocsY.clear(); spawnedBodiesRobotIDs.clear(); spawnedBodiesTeamIDs.clear(); spawnedBodiesTypes.clear(); spawnedBodiesLocsXs.clear(); spawnedBodiesLocsYs.clear(); - spawnedBodiesInfluences.clear(); diedIDs.clear(); actionIDs.clear(); actions.clear(); actionTargets.clear(); + leadDropLocsX.clear(); + leadDropLocsY.clear(); + leadDropValues.clear(); + goldDropLocsX.clear(); + goldDropLocsY.clear(); + goldDropValues.clear(); teamIDs.clear(); - teamVotes.clear(); - teamBidderIDs.clear(); - teamNumBuffs.clear(); + teamLeadChanges.clear(); + teamGoldChanges.clear(); + indicatorStringIDs.clear(); + indicatorStrings.clear(); indicatorDotIDs.clear(); indicatorDotLocsX.clear(); indicatorDotLocsY.clear(); diff --git a/engine/src/main/battlecode/server/Server.java b/engine/src/main/battlecode/server/Server.java index 8b8dd891..97c87c9e 100644 --- a/engine/src/main/battlecode/server/Server.java +++ b/engine/src/main/battlecode/server/Server.java @@ -1,6 +1,8 @@ package battlecode.server; import battlecode.common.GameConstants; +import battlecode.common.RobotInfo; +import battlecode.common.RobotType; import battlecode.common.Team; import battlecode.world.*; import battlecode.world.control.*; @@ -78,31 +80,31 @@ public Server(Config options, boolean interactive) { // ***** NOTIFICATIONS ********** // ****************************** - public void startNotification(){ + public void startNotification() { state = ServerState.READY; } - public void pauseNotification(){ + public void pauseNotification() { state = ServerState.PAUSED; } - public void resumeNotification(){ - if (state == ServerState.PAUSED){ + public void resumeNotification() { + if (state == ServerState.PAUSED) { state = ServerState.RUNNING; } } - public void runNotification(){ + public void runNotification() { if (state != ServerState.PAUSED) { state = ServerState.RUNNING; } } - public void addGameNotification(GameInfo gameInfo){ + public void addGameNotification(GameInfo gameInfo) { this.gameQueue.add(gameInfo); } - public void terminateNotification(){ + public void terminateNotification() { this.gameQueue.add(POISON); } @@ -194,7 +196,44 @@ public void run() { gameMaker.writeGame(currentGame.getSaveFile()); } } - + + private void validateMapOnGameConstants(LiveMap liveMap) { + // Check map dimensions + if (liveMap.getWidth() > GameConstants.MAP_MAX_WIDTH) { + throw new RuntimeException("MAP WIDTH EXCEEDS GameConstants.MAP_MAX_WIDTH"); + } + if (liveMap.getWidth() < GameConstants.MAP_MIN_WIDTH) { + throw new RuntimeException("MAP WIDTH BENEATH GameConstants.MAP_MIN_WIDTH"); + } + if (liveMap.getHeight() > GameConstants.MAP_MAX_HEIGHT) { + throw new RuntimeException("MAP HEIGHT EXCEEDS GameConstants.MAP_MAX_HEIGHT"); + } + if (liveMap.getHeight() < GameConstants.MAP_MIN_HEIGHT) { + throw new RuntimeException("MAP HEIGHT BENEATH GameConstants.MAP_MIN_HEIGHT"); + } + + // Check rubble + for (int rubble : liveMap.getRubbleArray()) { + if (rubble < GameConstants.MIN_RUBBLE) { + throw new RuntimeException("RUBBLE BENEATH GameConstants.MIN_RUBBLE"); + } + if (rubble > GameConstants.MAX_RUBBLE) { + throw new RuntimeException("RUBBLE EXCEEDS GameConstants.MAX_RUBBLE"); + } + } + + // Check starting Archons + int archonCount = 0; + for (RobotInfo robotInfo : liveMap.getInitialBodies()) { + if (robotInfo.type == RobotType.ARCHON) archonCount++; + } + if (archonCount < GameConstants.MIN_STARTING_ARCHONS * 2) { + throw new RuntimeException("RUBBLE BENEATH GameConstants.MIN_STARTING_ARCHONS"); + } + if (archonCount > GameConstants.MAX_STARTING_ARCHONS * 2) { + throw new RuntimeException("RUBBLE EXCEEDS GameConstants.MAX_STARTING_ARCHONS"); + } + } /** * @return the winner of the match @@ -210,7 +249,6 @@ private Team runMatch(GameInfo currentGame, try { loadedMap = GameMapIO.loadMap(mapName, new File(options.get("bc.game.map-path"))); - debug("running map " + loadedMap); } catch (IOException e) { warn("Couldn't load map " + mapName + ", skipping"); throw e; @@ -218,6 +256,9 @@ private Team runMatch(GameInfo currentGame, // Create the game world! currentWorld = new GameWorld(loadedMap, prov, gameMaker.getMatchMaker()); + + // Validate the map + validateMapOnGameConstants(currentWorld.getGameMap()); // Get started if (interactive) { @@ -360,17 +401,17 @@ public String getWinnerString(GameInfo game, Team winner, int roundNumber) { DominationFactor dom = stats.getDominationFactor(); switch (dom) { - case ANNIHILATED: - sb.append("The winning team won by annihilating the enemy team."); + case ANNIHILATION: + sb.append("The winning team won by annihilating the enemy team's Archons."); break; - case MORE_VOTES: - sb.append("The winning team won by having more votes."); + case MORE_ARCHONS: + sb.append("The winning team won by having more Archons."); break; - case MORE_ENLIGHTENMENT_CENTERS: - sb.append("The winning team won on tiebreakers (more Enlightenment Centers)."); + case MORE_GOLD_NET_WORTH: + sb.append("The winning team won on tiebreakers (more gold net worth)."); break; - case MORE_INFLUENCE: - sb.append("The winning team won on tiebreakers (more total unit influence)."); + case MORE_LEAD_NET_WORTH: + sb.append("The winning team won on tiebreakers (more lead net worth)."); break; case WON_BY_DUBIOUS_REASONS: sb.append("The winning team won arbitrarily (coin flip)."); diff --git a/engine/src/main/battlecode/util/FlatHelpers.java b/engine/src/main/battlecode/util/FlatHelpers.java index 983c714d..ed1f44b9 100644 --- a/engine/src/main/battlecode/util/FlatHelpers.java +++ b/engine/src/main/battlecode/util/FlatHelpers.java @@ -23,14 +23,20 @@ public class FlatHelpers { public static RobotType getRobotTypeFromBodyType(byte bodyType) { switch (bodyType) { - case BodyType.ENLIGHTENMENT_CENTER: - return RobotType.ENLIGHTENMENT_CENTER; - case BodyType.POLITICIAN: - return RobotType.POLITICIAN; - case BodyType.SLANDERER: - return RobotType.SLANDERER; - case BodyType.MUCKRAKER: - return RobotType.MUCKRAKER; + case BodyType.ARCHON: + return RobotType.ARCHON; + case BodyType.LABORATORY: + return RobotType.LABORATORY; + case BodyType.WATCHTOWER: + return RobotType.WATCHTOWER; + case BodyType.MINER: + return RobotType.MINER; + case BodyType.BUILDER: + return RobotType.BUILDER; + case BodyType.SOLDIER: + return RobotType.SOLDIER; + case BodyType.SAGE: + return RobotType.SAGE; default: throw new RuntimeException("No robot type for: " + bodyType); } @@ -38,14 +44,20 @@ public static RobotType getRobotTypeFromBodyType(byte bodyType) { public static byte getBodyTypeFromRobotType(RobotType type) { switch (type) { - case ENLIGHTENMENT_CENTER: - return BodyType.ENLIGHTENMENT_CENTER; - case POLITICIAN: - return BodyType.POLITICIAN; - case SLANDERER: - return BodyType.SLANDERER; - case MUCKRAKER: - return BodyType.MUCKRAKER; + case ARCHON: + return BodyType.ARCHON; + case LABORATORY: + return BodyType.LABORATORY; + case WATCHTOWER: + return BodyType.WATCHTOWER; + case MINER: + return BodyType.MINER; + case BUILDER: + return BodyType.BUILDER; + case SOLDIER: + return BodyType.SOLDIER; + case SAGE: + return BodyType.SAGE; default: throw new RuntimeException("No body type for: " + type); } diff --git a/engine/src/main/battlecode/world/BuildMaps.java b/engine/src/main/battlecode/world/BuildMaps.java index 148f9f2d..832f58f5 100644 --- a/engine/src/main/battlecode/world/BuildMaps.java +++ b/engine/src/main/battlecode/world/BuildMaps.java @@ -18,8 +18,6 @@ public class BuildMaps { */ public static void main(String[] args) { MapTestSmall.main(args); - Circle.main(args); - Quadrants.main(args); } } diff --git a/engine/src/main/battlecode/world/DominationFactor.java b/engine/src/main/battlecode/world/DominationFactor.java index a1913bef..ac9999db 100644 --- a/engine/src/main/battlecode/world/DominationFactor.java +++ b/engine/src/main/battlecode/world/DominationFactor.java @@ -5,21 +5,21 @@ */ public enum DominationFactor { /** - * Win by all enemy robots being destroyed (early end). + * Win by all enemy archons being destroyed (early end). */ - ANNIHILATED, + ANNIHILATION, /** - * Win by more votes. + * Win by having more Archons. */ - MORE_VOTES, + MORE_ARCHONS, /** - * Win by having more Enlightenment Centers (tiebreak 1). + * Win by more gold net worth (tiebreak 1). */ - MORE_ENLIGHTENMENT_CENTERS, + MORE_GOLD_NET_WORTH, /** - * Win by more total influence (tiebreak 2). + * Win by more lead net worth (tiebreak 2). */ - MORE_INFLUENCE, + MORE_LEAD_NET_WORTH, /** * Win by coinflip (tiebreak 3). */ diff --git a/engine/src/main/battlecode/world/GameMapIO.java b/engine/src/main/battlecode/world/GameMapIO.java index c875c584..4687e428 100644 --- a/engine/src/main/battlecode/world/GameMapIO.java +++ b/engine/src/main/battlecode/world/GameMapIO.java @@ -29,9 +29,9 @@ public final strictfp class GameMapIO { private static final ClassLoader BACKUP_LOADER = GameMapIO.class.getClassLoader(); /** - * The file extension for battlecode 2021 match files. + * The file extension for battlecode 2022 match files. */ - public static final String MAP_EXTENSION = ".map21"; + public static final String MAP_EXTENSION = ".map22"; /** * The package we check for maps in if they can't be found in the file system. @@ -48,9 +48,7 @@ public final strictfp class GameMapIO { * @return LiveMap for map * @throws IOException if the map fails to load or can't be found. */ - public static LiveMap loadMap(String mapName, File mapDir) - throws IOException { - + public static LiveMap loadMap(String mapName, File mapDir) throws IOException { final LiveMap result; final File mapFile = new File(mapDir, mapName + MAP_EXTENSION); @@ -225,12 +223,19 @@ public static LiveMap deserialize(battlecode.schema.GameMap raw) { final int width = (int) (raw.maxCorner().x() - raw.minCorner().x()); final int height = (int) (raw.maxCorner().y() - raw.minCorner().y()); final MapLocation origin = new MapLocation((int) raw.minCorner().x(), (int) raw.minCorner().y()); + final MapSymmetry symmetry = MapSymmetry.values()[raw.symmetry()]; final int seed = raw.randomSeed(); final int rounds = GameConstants.GAME_MAX_NUMBER_OF_ROUNDS; final String mapName = raw.name(); - double[] passabilityArray = new double[width * height]; - for (int i = 0; i < width * height; i++) { - passabilityArray[i] = raw.passability(i); + int[] rubbleArray = new int[width * height]; + int[] leadArray = new int[width * height]; + for (int i = 0; i < rubbleArray.length; i++) { + rubbleArray[i] = raw.rubble(i); + leadArray[i] = raw.lead(i); + } + AnomalyScheduleEntry[] anomalySchedule = new AnomalyScheduleEntry[raw.anomaliesLength()]; + for (int i = 0; i < anomalySchedule.length; i++) { + anomalySchedule[i] = new AnomalyScheduleEntry(raw.anomalyRounds(i), AnomalyType.values()[raw.anomalies(i)]); } ArrayList initBodies = new ArrayList<>(); SpawnedBodyTable bodyTable = raw.bodies(); @@ -239,7 +244,7 @@ public static LiveMap deserialize(battlecode.schema.GameMap raw) { RobotInfo[] initialBodies = initBodies.toArray(new RobotInfo[initBodies.size()]); return new LiveMap( - width, height, origin, seed, rounds, mapName, initialBodies, passabilityArray + width, height, origin, seed, rounds, mapName, symmetry, initialBodies, rubbleArray, leadArray, anomalySchedule ); } @@ -254,18 +259,28 @@ public static LiveMap deserialize(battlecode.schema.GameMap raw) { public static int serialize(FlatBufferBuilder builder, LiveMap gameMap) { int name = builder.createString(gameMap.getMapName()); int randomSeed = gameMap.getSeed(); - double[] passabilityArray = gameMap.getPassabilityArray(); + int[] rubbleArray = gameMap.getRubbleArray(); + int[] leadArray = gameMap.getLeadArray(); + AnomalyScheduleEntry[] anomalySchedule = gameMap.getAnomalySchedule(); // Make body tables ArrayList bodyIDs = new ArrayList<>(); ArrayList bodyTeamIDs = new ArrayList<>(); ArrayList bodyTypes = new ArrayList<>(); ArrayList bodyLocsXs = new ArrayList<>(); ArrayList bodyLocsYs = new ArrayList<>(); - ArrayList bodyInfluences = new ArrayList<>(); - ArrayList passabilityArrayList = new ArrayList<>(); + ArrayList rubbleArrayList = new ArrayList<>(); + ArrayList leadArrayList = new ArrayList<>(); + ArrayList anomaliesArrayList = new ArrayList<>(); + ArrayList anomalyRoundsArrayList = new ArrayList<>(); + + for (int i = 0; i < anomalySchedule.length; i++) { + anomaliesArrayList.add(anomalySchedule[i].anomalyType.ordinal()); + anomalyRoundsArrayList.add(anomalySchedule[i].roundNumber); + } for (int i = 0; i < gameMap.getWidth() * gameMap.getHeight(); i++) { - passabilityArrayList.add(passabilityArray[i]); + rubbleArrayList.add(rubbleArray[i]); + leadArrayList.add(leadArray[i]); } for (RobotInfo robot : gameMap.getInitialBodies()) { @@ -274,7 +289,6 @@ public static int serialize(FlatBufferBuilder builder, LiveMap gameMap) { bodyTypes.add(FlatHelpers.getBodyTypeFromRobotType(robot.type)); bodyLocsXs.add(robot.location.x); bodyLocsYs.add(robot.location.y); - bodyInfluences.add(robot.getInfluence()); } int robotIDs = SpawnedBodyTable.createRobotIDsVector(builder, ArrayUtils.toPrimitive(bodyIDs.toArray(new Integer[bodyIDs.size()]))); @@ -283,24 +297,29 @@ public static int serialize(FlatBufferBuilder builder, LiveMap gameMap) { int locs = VecTable.createVecTable(builder, VecTable.createXsVector(builder, ArrayUtils.toPrimitive(bodyLocsXs.toArray(new Integer[bodyLocsXs.size()]))), VecTable.createYsVector(builder, ArrayUtils.toPrimitive(bodyLocsYs.toArray(new Integer[bodyLocsYs.size()])))); - int influences = SpawnedBodyTable.createInfluencesVector(builder, ArrayUtils.toPrimitive(bodyInfluences.toArray(new Integer[bodyInfluences.size()]))); SpawnedBodyTable.startSpawnedBodyTable(builder); SpawnedBodyTable.addRobotIDs(builder, robotIDs); SpawnedBodyTable.addTeamIDs(builder, teamIDs); SpawnedBodyTable.addTypes(builder, types); SpawnedBodyTable.addLocs(builder, locs); - SpawnedBodyTable.addInfluences(builder, influences); int bodies = SpawnedBodyTable.endSpawnedBodyTable(builder); - int passabilityArrayInt = battlecode.schema.GameMap.createPassabilityVector(builder, ArrayUtils.toPrimitive(passabilityArrayList.toArray(new Double[passabilityArrayList.size()]))); + int rubbleArrayInt = battlecode.schema.GameMap.createRubbleVector(builder, ArrayUtils.toPrimitive(rubbleArrayList.toArray(new Integer[rubbleArrayList.size()]))); + int leadArrayInt = battlecode.schema.GameMap.createLeadVector(builder, ArrayUtils.toPrimitive(leadArrayList.toArray(new Integer[leadArrayList.size()]))); + int anomaliesArrayInt = battlecode.schema.GameMap.createAnomaliesVector(builder, ArrayUtils.toPrimitive(anomaliesArrayList.toArray(new Integer[anomaliesArrayList.size()]))); + int anomalyRoundsArrayInt = battlecode.schema.GameMap.createAnomalyRoundsVector(builder, ArrayUtils.toPrimitive(anomalyRoundsArrayList.toArray(new Integer[anomalyRoundsArrayList.size()]))); // Build LiveMap for flatbuffer battlecode.schema.GameMap.startGameMap(builder); battlecode.schema.GameMap.addName(builder, name); battlecode.schema.GameMap.addMinCorner(builder, Vec.createVec(builder, gameMap.getOrigin().x, gameMap.getOrigin().y)); battlecode.schema.GameMap.addMaxCorner(builder, Vec.createVec(builder, gameMap.getOrigin().x + gameMap.getWidth(), gameMap.getOrigin().y + gameMap.getHeight())); + battlecode.schema.GameMap.addSymmetry(builder, gameMap.getSymmetry().ordinal()); battlecode.schema.GameMap.addBodies(builder, bodies); battlecode.schema.GameMap.addRandomSeed(builder, randomSeed); - battlecode.schema.GameMap.addPassability(builder, passabilityArrayInt); + battlecode.schema.GameMap.addRubble(builder, rubbleArrayInt); + battlecode.schema.GameMap.addLead(builder, leadArrayInt); + battlecode.schema.GameMap.addAnomalies(builder, anomaliesArrayInt); + battlecode.schema.GameMap.addAnomalyRounds(builder, anomalyRoundsArrayInt); return battlecode.schema.GameMap.endGameMap(builder); } @@ -311,16 +330,15 @@ public static int serialize(FlatBufferBuilder builder, LiveMap gameMap) { private static void initInitialBodiesFromSchemaBodyTable(SpawnedBodyTable bodyTable, ArrayList initialBodies) { VecTable locs = bodyTable.locs(); for (int i = 0; i < bodyTable.robotIDsLength(); i++) { - // all initial bodies should be enlightenment centers, with some influence and 0 conviction + // all initial bodies should be archons RobotType bodyType = FlatHelpers.getRobotTypeFromBodyType(bodyTable.types(i)); int bodyID = bodyTable.robotIDs(i); int bodyX = locs.xs(i); int bodyY = locs.ys(i); Team bodyTeam = TeamMapping.team(bodyTable.teamIDs(i)); - int bodyInfluence = bodyTable.influences(i); - if (bodyType == RobotType.ENLIGHTENMENT_CENTER) - initialBodies.add(new RobotInfo(bodyID, bodyTeam, bodyType, bodyInfluence, bodyInfluence, new MapLocation(bodyX, bodyY))); - // ignore robots that are not enlightenment centers, TODO throw error? + if (bodyType == RobotType.ARCHON) + initialBodies.add(new RobotInfo(bodyID, bodyTeam, bodyType, RobotMode.TURRET, 1, RobotType.ARCHON.health, new MapLocation(bodyX, bodyY))); + // ignore robots that are not archons, TODO throw error? } } } diff --git a/engine/src/main/battlecode/world/GameWorld.java b/engine/src/main/battlecode/world/GameWorld.java index b4ff29ae..e7e0926b 100644 --- a/engine/src/main/battlecode/world/GameWorld.java +++ b/engine/src/main/battlecode/world/GameWorld.java @@ -27,8 +27,10 @@ public strictfp class GameWorld { protected final IDGenerator idGenerator; protected final GameStats gameStats; - - private double[] passability; + + private int[] rubble; + private int[] lead; + private int[] gold; private InternalRobot[][] robots; private final LiveMap gameMap; private final TeamInfo teamInfo; @@ -40,11 +42,11 @@ public strictfp class GameWorld { private Random rand; private final GameMaker.MatchMaker matchMaker; - private int[] buffsToAdd; - @SuppressWarnings("unchecked") public GameWorld(LiveMap gm, RobotControlProvider cp, GameMaker.MatchMaker matchMaker) { - this.passability = gm.getPassabilityArray(); + this.rubble = gm.getRubbleArray(); + this.lead = gm.getLeadArray(); + this.gold = new int[this.lead.length]; this.robots = new InternalRobot[gm.getWidth()][gm.getHeight()]; // if represented in cartesian, should be height-width, but this should allow us to index x-y this.currentRound = 0; this.idGenerator = new IDGenerator(gm.getSeed()); @@ -52,7 +54,6 @@ public GameWorld(LiveMap gm, RobotControlProvider cp, GameMaker.MatchMaker match this.gameMap = gm; this.objectInfo = new ObjectInfo(gm); - this.teamInfo = new TeamInfo(this); this.profilerCollections = new HashMap<>(); @@ -60,8 +61,6 @@ public GameWorld(LiveMap gm, RobotControlProvider cp, GameMaker.MatchMaker match this.rand = new Random(this.gameMap.getSeed()); this.matchMaker = matchMaker; - this.buffsToAdd = new int[2]; - controlProvider.matchStarted(this); // Add the robots contained in the LiveMap to this world. @@ -69,9 +68,15 @@ public GameWorld(LiveMap gm, RobotControlProvider cp, GameMaker.MatchMaker match for (int i = 0; i < initialBodies.length; i++) { RobotInfo robot = initialBodies[i]; MapLocation newLocation = robot.location.translate(gm.getOrigin().x, gm.getOrigin().y); - int newID = spawnRobot(null, robot.type, newLocation, robot.team, robot.influence); - initialBodies[i] = new RobotInfo(newID, robot.team, robot.type, robot.influence, robot.conviction, newLocation); // update with non-deterministic ID and offset location + spawnRobot(robot.ID, robot.type, newLocation, robot.team); } + this.teamInfo = new TeamInfo(this); + + // Add initial amounts of resource + this.teamInfo.addLead(Team.A, GameConstants.INITIAL_LEAD_AMOUNT); + this.teamInfo.addLead(Team.B, GameConstants.INITIAL_LEAD_AMOUNT); + this.teamInfo.addGold(Team.A, GameConstants.INITIAL_GOLD_AMOUNT); + this.teamInfo.addGold(Team.B, GameConstants.INITIAL_GOLD_AMOUNT); // Write match header at beginning of match this.matchMaker.makeMatchHeader(this.gameMap); @@ -80,7 +85,7 @@ public GameWorld(LiveMap gm, RobotControlProvider cp, GameMaker.MatchMaker match /** * Run a single round of the game. * - * @return the state of the game after the round has run. + * @return the state of the game after the round has run */ public synchronized GameState runRound() { if (!this.isRunning()) { @@ -118,12 +123,11 @@ public synchronized GameState runRound() { return GameState.RUNNING; } - private void updateDynamicBodies(){ + private void updateDynamicBodies() { objectInfo.eachDynamicBodyByExecOrder((body) -> { if (body instanceof InternalRobot) { return updateRobot((InternalRobot) body); - } - else { + } else { throw new RuntimeException("non-robot body registered as dynamic"); } }); @@ -138,8 +142,7 @@ private boolean updateRobot(InternalRobot robot) { // If the robot terminates but the death signal has not yet // been visited: if (this.controlProvider.getTerminated(robot) && objectInfo.getRobotByID(robot.getID()) != null) - //destroyRobot(robot.getID()); - ; // Freeze robot instead of destroying it + destroyRobot(robot.getID()); return true; } @@ -175,6 +178,13 @@ public Team getWinner() { return this.gameStats.getWinner(); } + /** + * Defensively copied at the level of LiveMap. + */ + public AnomalyScheduleEntry[] getAnomalySchedule() { + return this.gameMap.getAnomalySchedule(); + } + public boolean isRunning() { return this.running; } @@ -183,8 +193,24 @@ public int getCurrentRound() { return this.currentRound; } - public double getPassability(MapLocation loc) { - return this.passability[locationToIndex(loc)]; + public int getRubble(MapLocation loc) { + return this.rubble[locationToIndex(loc)]; + } + + public int getLead(MapLocation loc) { + return this.lead[locationToIndex(loc)]; + } + + public void setLead(MapLocation loc, int amount) { + this.lead[locationToIndex(loc)] = amount; + } + + public int getGold(MapLocation loc) { + return this.gold[locationToIndex(loc)]; + } + + public void setGold(MapLocation loc, int amount) { + this.gold[locationToIndex(loc)] = amount; } /** @@ -236,12 +262,23 @@ public InternalRobot[] getAllRobotsWithinRadiusSquared(MapLocation center, int r } public MapLocation[] getAllLocationsWithinRadiusSquared(MapLocation center, int radiusSquared) { + return getAllLocationsWithinRadiusSquaredWithoutMap( + this.gameMap.getOrigin(), + this.gameMap.getWidth(), + this.gameMap.getHeight(), + center, radiusSquared + ); + } + + public static MapLocation[] getAllLocationsWithinRadiusSquaredWithoutMap(MapLocation origin, + int width, int height, + MapLocation center, int radiusSquared) { ArrayList returnLocations = new ArrayList(); int ceiledRadius = (int) Math.ceil(Math.sqrt(radiusSquared)) + 1; // add +1 just to be safe - int minX = Math.max(center.x - ceiledRadius, this.gameMap.getOrigin().x); - int minY = Math.max(center.y - ceiledRadius, this.gameMap.getOrigin().y); - int maxX = Math.min(center.x + ceiledRadius, this.gameMap.getOrigin().x + this.gameMap.getWidth() - 1); - int maxY = Math.min(center.y + ceiledRadius, this.gameMap.getOrigin().y + this.gameMap.getHeight() - 1); + int minX = Math.max(center.x - ceiledRadius, origin.x); + int minY = Math.max(center.y - ceiledRadius, origin.y); + int maxX = Math.min(center.x + ceiledRadius, origin.x + width - 1); + int maxY = Math.min(center.y + ceiledRadius, origin.y + height - 1); for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { MapLocation newLocation = new MapLocation(x, y); @@ -249,21 +286,32 @@ public MapLocation[] getAllLocationsWithinRadiusSquared(MapLocation center, int returnLocations.add(newLocation); } } - return returnLocations.toArray(new MapLocation[0]); + return returnLocations.toArray(new MapLocation[returnLocations.size()]); + } + + /** + * @return all of the locations on the grid + */ + private MapLocation[] getAllLocations() { + return getAllLocationsWithinRadiusSquared(new MapLocation(0, 0), Integer.MAX_VALUE); + } + + /** + * @param cooldown without multiplier applied + * @param location with rubble of interest, if any + * @return the cooldown due to rubble + */ + public int getCooldownWithMultiplier(int cooldown, MapLocation location) { + return (int) ((1 + getRubble(location) / 10.0) * cooldown); } // ********************************* // ****** GAMEPLAY ***************** // ********************************* - public void addBuffs(Team t, int numBuffs) { - this.buffsToAdd[t.ordinal()] += numBuffs; - } - public void processBeginningOfRound() { // Increment round counter currentRound++; - this.teamInfo.updateNumBuffs(currentRound); // Process beginning of each robot's round objectInfo.eachRobot((robot) -> { @@ -272,85 +320,71 @@ public void processBeginningOfRound() { }); } - public void setWinner(Team t, DominationFactor d) { + public void setWinner(Team t, DominationFactor d) { gameStats.setWinner(t); gameStats.setDominationFactor(d); } /** - * Sets the winner if one of the teams has been annihilated. - * - * @return whether or not a winner was set + * @return whether a team has more archons */ - public boolean setWinnerIfAnnihilated() { - int robotCountA = objectInfo.getRobotCount(Team.A); - int robotCountB = objectInfo.getRobotCount(Team.B); - if (robotCountA == 0) { - setWinner(Team.B, DominationFactor.ANNIHILATED); - return true; - } else if (robotCountB == 0) { - setWinner(Team.A, DominationFactor.ANNIHILATED); - return true; - } - return false; - } + public boolean setWinnerIfMoreArchons() { + int archonCountA = this.objectInfo.getRobotTypeCount(Team.A, RobotType.ARCHON); + int archonCountB = this.objectInfo.getRobotTypeCount(Team.B, RobotType.ARCHON); - /** - * Sets the winner if one of the teams has more votes than the other. - * - * @return whether or not a winner was set - */ - public boolean setWinnerIfMoreVotes() { - int numVotesA = teamInfo.getVotes(Team.A); - int numVotesB = teamInfo.getVotes(Team.B); - if (numVotesA > numVotesB) { - setWinner(Team.A, DominationFactor.MORE_VOTES); + if (archonCountA > archonCountB) { + setWinner(Team.A, DominationFactor.MORE_ARCHONS); return true; - } else if (numVotesB > numVotesA) { - setWinner(Team.B, DominationFactor.MORE_VOTES); + } else if (archonCountA < archonCountB) { + setWinner(Team.B, DominationFactor.MORE_ARCHONS); return true; } return false; } /** - * Sets the winner if one of the teams has more Enlightenment Centers than the other. - * - * @return whether or not a winner was set + * @return whether a team has a greater net Au value */ - public boolean setWinnerIfMoreEnlightenmentCenters() { - int[] numEnlightenmentCenters = new int[2]; + public boolean setWinnerIfMoreGoldValue() { + int[] totalGoldValues = new int[2]; + + // consider team reserves + totalGoldValues[Team.A.ordinal()] += this.teamInfo.getGold(Team.A); + totalGoldValues[Team.B.ordinal()] += this.teamInfo.getGold(Team.B); + + // sum live robots worth for (InternalRobot robot : objectInfo.robotsArray()) { - if (robot.getType() != RobotType.ENLIGHTENMENT_CENTER) continue; - if (robot.getTeam() == Team.NEUTRAL) continue; - numEnlightenmentCenters[robot.getTeam().ordinal()]++; + totalGoldValues[robot.getTeam().ordinal()] += robot.getType().getGoldWorth(robot.getLevel()); } - if (numEnlightenmentCenters[0] > numEnlightenmentCenters[1]) { - setWinner(Team.A, DominationFactor.MORE_ENLIGHTENMENT_CENTERS); + if (totalGoldValues[0] > totalGoldValues[1]) { + setWinner(Team.A, DominationFactor.MORE_GOLD_NET_WORTH); return true; - } else if (numEnlightenmentCenters[1] > numEnlightenmentCenters[0]) { - setWinner(Team.B, DominationFactor.MORE_ENLIGHTENMENT_CENTERS); + } else if (totalGoldValues[1] > totalGoldValues[0]) { + setWinner(Team.B, DominationFactor.MORE_GOLD_NET_WORTH); return true; } return false; } /** - * Sets the winner if one of the teams has higher total unit influence. - * - * @return whether or not a winner was set + * @return whether a team has a greater net Pb value */ - public boolean setWinnerIfMoreInfluence() { - int[] totalInfluences = new int[2]; + public boolean setWinnerIfMoreLeadValue() { + int[] totalLeadValues = new int[2]; + + // consider team reserves + totalLeadValues[Team.A.ordinal()] += this.teamInfo.getLead(Team.A); + totalLeadValues[Team.B.ordinal()] += this.teamInfo.getLead(Team.B); + + // sum live robot worth for (InternalRobot robot : objectInfo.robotsArray()) { - if (robot.getTeam() == Team.NEUTRAL) continue; - totalInfluences[robot.getTeam().ordinal()] += robot.getInfluence(); + totalLeadValues[robot.getTeam().ordinal()] += robot.getType().getLeadWorth(robot.getLevel()); } - if (totalInfluences[0] > totalInfluences[1]) { - setWinner(Team.A, DominationFactor.MORE_INFLUENCE); + if (totalLeadValues[0] > totalLeadValues[1]) { + setWinner(Team.A, DominationFactor.MORE_LEAD_NET_WORTH); return true; - } else if (totalInfluences[1] > totalInfluences[0]) { - setWinner(Team.B, DominationFactor.MORE_INFLUENCE); + } else if (totalLeadValues[1] > totalLeadValues[0]) { + setWinner(Team.B, DominationFactor.MORE_LEAD_NET_WORTH); return true; } return false; @@ -368,69 +402,42 @@ public boolean timeLimitReached() { } public void processEndOfRound() { - int[] highestBids = new int[2]; - InternalRobot[] highestBidders = new InternalRobot[2]; + // Add lead resources to the team + this.teamInfo.addLead(Team.A, GameConstants.PASSIVE_LEAD_INCREASE); + this.teamInfo.addLead(Team.B, GameConstants.PASSIVE_LEAD_INCREASE); // Process end of each robot's round objectInfo.eachRobot((robot) -> { - if (robot.getTeam().isPlayer() && robot.getType().canBid()) { - int bid = robot.getBid(); - int teamIdx = robot.getTeam().ordinal(); - if (bid > highestBids[teamIdx] || highestBidders[teamIdx] == null || - (bid == highestBids[teamIdx] && robot.compareTo(highestBidders[teamIdx]) < 0)) { - highestBids[teamIdx] = bid; - highestBidders[teamIdx] = robot; - } - robot.resetBid(); - } robot.processEndOfRound(); return true; }); - // Process bidding - int[] teamVotes = new int[2]; - int[] teamBidderIDs = new int[2]; - - if (highestBids[0] > highestBids[1] && highestBids[0] > 0) { - // Team.A wins - teamVotes[0] = 1; - teamBidderIDs[0] = highestBidders[0].getID(); - highestBidders[0].addInfluenceAndConviction(-highestBids[0]); - this.teamInfo.addVote(Team.A); - } else if (highestBids[1] > highestBids[0] && highestBids[1] > 0) { - // Team.B wins - teamVotes[1] = 1; - teamBidderIDs[1] = highestBidders[1].getID(); - highestBidders[1].addInfluenceAndConviction(-highestBids[1]); - this.teamInfo.addVote(Team.B); - } - - for (int i = 0; i < 2; i++) { - if (teamVotes[i] == 0 && highestBidders[i] != null) { - // Didn't win. If didn't place bid, halfBid == 0 - int halfBid = (highestBids[i] + 1) / 2; - highestBidders[i].addInfluenceAndConviction(-halfBid); - teamBidderIDs[i] = highestBidders[i].getID(); - } + // Trigger any anomalies + // note: singularity is handled below in the "check for end of match" + AnomalyScheduleEntry nextAnomaly = this.gameMap.viewNextAnomaly(); + if (nextAnomaly != null && nextAnomaly.roundNumber == this.currentRound) { + AnomalyType anomaly = this.gameMap.takeNextAnomaly().anomalyType; + if (anomaly == AnomalyType.ABYSS) causeAbyssGlobal(); + if (anomaly == AnomalyType.CHARGE) causeChargeGlobal(); + if (anomaly == AnomalyType.FURY) causeFuryGlobal(); + if (anomaly == AnomalyType.VORTEX) causeVortexGlobal(); } - // Add buffs from expose - int nextRound = currentRound + 1; - for (int i = 0; i < 2; i++) { - this.teamInfo.addBuffs(nextRound, Team.values()[i], this.buffsToAdd[i]); - this.buffsToAdd[i] = 0; // reset - } + // Add lead resources to the map + if (this.currentRound % GameConstants.ADD_LEAD_EVERY_ROUNDS == 0) + for (int i = 0; i < this.lead.length; i++) + if (this.lead[i] > 0) + this.lead[i] += GameConstants.ADD_LEAD; - // Send team info (votes, bidder IDs, and num buffs) to matchmaker - for (int i = 0; i < 2; i++) - this.matchMaker.addTeamInfo(Team.values()[i], teamVotes[i], teamBidderIDs[i], this.teamInfo.getNumBuffs(Team.values()[i], nextRound)); + this.matchMaker.addTeamInfo(Team.A, this.teamInfo.getRoundLeadChange(Team.A), this.teamInfo.getRoundGoldChange(Team.A)); + this.matchMaker.addTeamInfo(Team.B, this.teamInfo.getRoundLeadChange(Team.B), this.teamInfo.getRoundGoldChange(Team.B)); + this.teamInfo.processEndOfRound(); // Check for end of match - setWinnerIfAnnihilated(); if (timeLimitReached() && gameStats.getWinner() == null) - if (!setWinnerIfMoreVotes()) - if (!setWinnerIfMoreEnlightenmentCenters()) - if (!setWinnerIfMoreInfluence()) + if (!setWinnerIfMoreArchons()) + if (!setWinnerIfMoreGoldValue()) + if (!setWinnerIfMoreLeadValue()) setWinnerArbitrary(); if (gameStats.getWinner() != null) @@ -441,8 +448,8 @@ public void processEndOfRound() { // ****** SPAWNING ***************** // ********************************* - public int spawnRobot(InternalRobot parent, int ID, RobotType type, MapLocation location, Team team, int influence) { - InternalRobot robot = new InternalRobot(this, parent, ID, type, location, team, influence); + public int spawnRobot(int ID, RobotType type, MapLocation location, Team team) { + InternalRobot robot = new InternalRobot(this, ID, type, location, team); objectInfo.spawnRobot(robot); addRobot(location, robot); @@ -451,38 +458,284 @@ public int spawnRobot(InternalRobot parent, int ID, RobotType type, MapLocation return ID; } - public int spawnRobot(InternalRobot parent, RobotType type, MapLocation location, Team team, int influence) { + public int spawnRobot(RobotType type, MapLocation location, Team team) { int ID = idGenerator.nextID(); - return spawnRobot(parent, ID, type, location, team, influence); + return spawnRobot(ID, type, location, team); } - + // ********************************* // ****** DESTROYING *************** // ********************************* public void destroyRobot(int id) { + destroyRobot(id, true); + } + + public void destroyRobot(int id, boolean checkArchonDeath) { InternalRobot robot = objectInfo.getRobotByID(id); + RobotType type = robot.getType(); + Team team = robot.getTeam(); removeRobot(robot.getLocation()); - // TODO: take care of things that happen when robot dies + int leadDropped = robot.getType().getLeadDropped(robot.getLevel()); + int goldDropped = robot.getType().getGoldDropped(robot.getLevel()); + + this.lead[locationToIndex(robot.getLocation())] += leadDropped; + this.gold[locationToIndex(robot.getLocation())] += goldDropped; + + this.matchMaker.addLeadDrop(robot.getLocation(), leadDropped); + this.matchMaker.addGoldDrop(robot.getLocation(), goldDropped); controlProvider.robotKilled(robot); objectInfo.destroyRobot(id); + if (checkArchonDeath) { + // this happens here because both teams' Archons can die in the same round + if (type == RobotType.ARCHON && this.objectInfo.getRobotTypeCount(team, RobotType.ARCHON) == 0) + setWinner(team == Team.A ? Team.B : Team.A, DominationFactor.ANNIHILATION); + } + matchMaker.addDied(id); } // ********************************* - // ******* PROFILER ************** + // ********* PROFILER ************** // ********************************* public void setProfilerCollection(Team team, ProfilerCollection profilerCollection) { if (profilerCollections == null) { profilerCollections = new HashMap<>(); } - profilerCollections.put(team, profilerCollection); } -} + // ********************************* + // ******** ANOMALY ************** + // ********************************* + + /** + * Finds all of the locations that a given Sage can affect with an Anomaly. + * @param robot that is causing the anomaly; must be a Sage + * @return all of the locations that are within range of this sage + */ + private MapLocation[] getSageActionLocations(InternalRobot robot) { + assert robot.getType() == RobotType.SAGE; + MapLocation center = robot.getLocation(); + return getAllLocationsWithinRadiusSquared(center, robot.getType().actionRadiusSquared); + } + /** + * Performs the Abyss anomaly. Changes the resources in the squares and the team. + * @param reduceFactor associated with anomaly (a decimal percentage) + * @param locations that can be affected by the Abyss + */ + private void causeAbyssGridUpdate(float reduceFactor, MapLocation[] locations) { + for (int i = 0; i < locations.length; i++) { + int currentLead = getLead(locations[i]); + int leadUpdate = (int) (reduceFactor * currentLead); + setLead(locations[i], currentLead - leadUpdate); + if (leadUpdate != 0) this.matchMaker.addLeadDrop(locations[i], -leadUpdate); + + int currentGold = getGold(locations[i]); + int goldUpdate = (int) (reduceFactor * currentGold); + setGold(locations[i], currentGold - goldUpdate); + if (goldUpdate != 0) this.matchMaker.addGoldDrop(locations[i], -goldUpdate); + } + } + + /** + * Mutates state to perform the Sage Abyss anomaly. + * @param robot that is the Sage + */ + public void causeAbyssSage(InternalRobot robot) { + assert robot.getType() == RobotType.SAGE; + // calculate the right effect range + this.causeAbyssGridUpdate(AnomalyType.ABYSS.sagePercentage, this.getSageActionLocations(robot)); + } + + /** + * Mutates state to perform the global Abyss anomaly. + */ + public void causeAbyssGlobal() { + this.causeAbyssGridUpdate(AnomalyType.ABYSS.globalPercentage, this.getAllLocations()); + + this.teamInfo.addLead(Team.A, (int) (-1 * AnomalyType.ABYSS.globalPercentage * this.teamInfo.getLead(Team.A))); + this.teamInfo.addLead(Team.B, (int) (-1 * AnomalyType.ABYSS.globalPercentage * this.teamInfo.getLead(Team.B))); + + this.teamInfo.addGold(Team.A, (int) (-1 * AnomalyType.ABYSS.globalPercentage * this.teamInfo.getGold(Team.A))); + this.teamInfo.addGold(Team.B, (int) (-1 * AnomalyType.ABYSS.globalPercentage * this.teamInfo.getGold(Team.B))); + this.matchMaker.addAction(-1, Action.ABYSS, -1); + } + + /** + * Mutates state to perform the Sage Charge. + * @param robot performing the Charge, must be a Sage + */ + public void causeChargeSage(InternalRobot robot) { + assert robot.getType() == RobotType.SAGE; + + MapLocation[] actionLocations = this.getSageActionLocations(robot); + for (int i = 0; i < actionLocations.length; i++) { + InternalRobot currentRobot = getRobot(actionLocations[i]); + if (currentRobot != null && currentRobot.getTeam() != robot.getTeam() && currentRobot.getMode() == RobotMode.DROID) + currentRobot.addHealth((int) (-1 * AnomalyType.CHARGE.sagePercentage * currentRobot.getType().getMaxHealth(currentRobot.getLevel()))); + } + } + + /** + * Mutates state to peform the global Charge. + */ + public void causeChargeGlobal() { + ArrayList droids = new ArrayList(); + for (InternalRobot currentRobot : this.objectInfo.robotsArray()) { + if (currentRobot.getMode() == RobotMode.DROID) { + droids.add(currentRobot); + currentRobot.updateNumVisibleFriendlyRobots(); + } + } + Collections.sort(droids, new SortByFriends()); + + int affectedDroidsLimit = (int) (AnomalyType.CHARGE.globalPercentage * droids.size()); + for (int i = 0; i < affectedDroidsLimit; i++) { + this.destroyRobot(droids.get(i).getID()); + } + this.matchMaker.addAction(-1, Action.CHARGE, -1); + } + + /** Used to sort droids for charge */ + class SortByFriends implements Comparator { + public int compare(InternalRobot a, InternalRobot b) { + return b.getNumVisibleFriendlyRobots(false) - a.getNumVisibleFriendlyRobots(false); + } + } + + /** + * Performs the Fury anomaly. Changes the health of the relevant robots. + * @param reduceFactor associated with anomaly (a decimal percentage) + * @param locations that can be affected by the Fury (by radius, not by state of robot) + */ + public void causeFuryUpdate(float reduceFactor, MapLocation[] locations) { + for (int i = 0; i < locations.length; i++) { + InternalRobot robot = this.getRobot(locations[i]); + if (robot != null && robot.getMode() == RobotMode.TURRET) { + robot.addHealth((int) (-1 * robot.getType().getMaxHealth(robot.getLevel()) * reduceFactor), false); + } + } + + boolean teamAEliminated = this.objectInfo.getRobotTypeCount(Team.A, RobotType.ARCHON) == 0; + boolean teamBEliminated = this.objectInfo.getRobotTypeCount(Team.B, RobotType.ARCHON) == 0; + if (teamAEliminated && teamBEliminated) { + // copy pasted from processEndOfRound + if (!setWinnerIfMoreGoldValue()) + if (!setWinnerIfMoreLeadValue()) + setWinnerArbitrary(); + } else if (teamAEliminated) { + setWinner(Team.B, DominationFactor.ANNIHILATION); + } else if (teamBEliminated) { + setWinner(Team.A, DominationFactor.ANNIHILATION); + } + } + + /** + * Mutates state to perform the Sage Fury. + * @param robot performing the Fury, must be a Sage + */ + public void causeFurySage(InternalRobot robot) { + assert robot.getType() == RobotType.SAGE; + this.causeFuryUpdate(AnomalyType.FURY.sagePercentage, this.getSageActionLocations(robot)); + } + + /** + * Mutates state to peform the global Fury. + */ + public void causeFuryGlobal() { + this.causeFuryUpdate(AnomalyType.FURY.globalPercentage, this.getAllLocations()); + this.matchMaker.addAction(-1, Action.FURY, -1); + } + + private void rotateRubble() { + int n = this.gameMap.getWidth(); + for (int x = 0; x < n / 2; x++) { + for (int y = 0; y < (n + 1) / 2; y++) { + int curX = x; + int curY = y; + int lastRubble = this.rubble[curX + curY * n]; + for (int i = 0; i < 4; i++) { + int tempX = curX; + curX = curY; + curY = (n - 1) - tempX; + int idx = curX + curY * n; + int tempRubble = this.rubble[idx]; + this.rubble[idx] = lastRubble; + lastRubble = tempRubble; + } + } + } + } + + private void flipRubbleHorizontally() { + int w = this.gameMap.getWidth(); + int h = this.gameMap.getHeight(); + for (int x = 0; x < w / 2; x++) { + for (int y = 0; y < h; y++) { + int idx = x + y * w; + int newX = w - 1 - x; + int newIdx = newX + y * w; + int prevRubble = this.rubble[idx]; + this.rubble[idx] = this.rubble[newIdx]; + this.rubble[newIdx] = prevRubble; + } + } + } + + private void flipRubbleVertically() { + int w = this.gameMap.getWidth(); + int h = this.gameMap.getHeight(); + for (int y = 0; y < h / 2; y++) { + for (int x = 0; x < w; x++) { + int idx = x + y * w; + int newY = h - 1 - y; + int newIdx = x + newY * w; + int prevRubble = this.rubble[idx]; + this.rubble[idx] = this.rubble[newIdx]; + this.rubble[newIdx] = prevRubble; + } + } + } + + /** + * Mutates state to peform the global Vortex. + * Only mutates the rubble array in this class; doesn't change the LiveMap + */ + public void causeVortexGlobal() { + int changeIdx = 0; + switch (this.gameMap.getSymmetry()) { + case VERTICAL: + flipRubbleVertically(); + changeIdx = 2; + break; + case HORIZONTAL: + flipRubbleHorizontally(); + changeIdx = 1; + break; + case ROTATIONAL: + // generate random choice of how rotation will occur + // can only rotate if it's a square map + boolean squareMap = this.gameMap.getWidth() == this.gameMap.getHeight(); + int randomNumber = this.rand.nextInt(squareMap ? 3 : 2); + if (!squareMap) { + randomNumber++; + } + if (randomNumber == 0) { + rotateRubble(); + } else if (randomNumber == 1) { + flipRubbleHorizontally(); + } else if (randomNumber == 2) { + flipRubbleVertically(); + } + changeIdx = randomNumber; + break; + } + this.matchMaker.addAction(-1, Action.VORTEX, changeIdx); + } +} diff --git a/engine/src/main/battlecode/world/InternalRobot.java b/engine/src/main/battlecode/world/InternalRobot.java index 772e94ae..5ba741fa 100644 --- a/engine/src/main/battlecode/world/InternalRobot.java +++ b/engine/src/main/battlecode/world/InternalRobot.java @@ -1,6 +1,9 @@ package battlecode.world; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import battlecode.common.*; import battlecode.schema.Action; @@ -11,41 +14,33 @@ * - tiebreak by robot ID (priority to lower ID) */ public strictfp class InternalRobot implements Comparable { + private final RobotControllerImpl controller; private final GameWorld gameWorld; - /** - * The robot that built this robot. - * Equal to null if this is an Enlightenment Center, because they are specified by the map. - * This reference does not inhibit garbage collection because Enlightenment Centers never die. - */ - private final InternalRobot parent; - private final int ID; private Team team; private RobotType type; private MapLocation location; - private int influence; - private int conviction; - private int convictionCap; - private int flag; - private int bid; - - private ArrayList toCreate; - private ArrayList toCreateParents; + private int level; + private RobotMode mode; + private int health; private long controlBits; private int currentBytecodeLimit; private int bytecodesUsed; private int roundsAlive; - private double cooldownTurns; + private int actionCooldownTurns; + private int movementCooldownTurns; + private int numVisibleFriendlyRobots; /** * Used to avoid recreating the same RobotInfo object over and over. */ - private RobotInfo cachedRobotInfoTrue; // true RobotType included - private RobotInfo cachedRobotInfoFake; // slanderers appear as politicians, null for all other robot types + private RobotInfo cachedRobotInfo; + + private String indicatorString; /** * Create a new internal representation of a robot @@ -54,32 +49,43 @@ public strictfp class InternalRobot implements Comparable { * @param type the type of the robot * @param loc the location of the robot * @param team the team of the robot - * @param influence the influence used to create the robot */ @SuppressWarnings("unchecked") - public InternalRobot(GameWorld gw, InternalRobot parent, int id, RobotType type, MapLocation loc, Team team, int influence) { - this.parent = parent; + public InternalRobot(GameWorld gw, int id, RobotType type, MapLocation loc, Team team) { + this.gameWorld = gw; + this.ID = id; this.team = team; this.type = type; this.location = loc; - this.influence = influence; - this.conviction = (int) Math.ceil(this.type.convictionRatio * this.influence); - this.convictionCap = type == RobotType.ENLIGHTENMENT_CENTER ? GameConstants.ROBOT_INFLUENCE_LIMIT : this.conviction; - this.flag = 0; - this.bid = 0; + this.level = 1; + + if (this.type == RobotType.ARCHON) { + this.mode = RobotMode.TURRET; + } else if (this.type.isBuilding()) { + this.mode = RobotMode.PROTOTYPE; + } else { + this.mode = RobotMode.DROID; + } - this.toCreate = new ArrayList<>(); - this.toCreateParents = new ArrayList<>(); + this.health = this.type.getMaxHealth(this.level); + if (this.mode == RobotMode.PROTOTYPE) { + int newHealth = (int) (GameConstants.PROTOTYPE_HP_PERCENTAGE * this.health); + this.gameWorld.getMatchMaker().addAction(getID(), Action.CHANGE_HEALTH, newHealth - this.health); + this.health = newHealth; + } this.controlBits = 0; this.currentBytecodeLimit = type.bytecodeLimit; this.bytecodesUsed = 0; this.roundsAlive = 0; - this.cooldownTurns = 0; + this.actionCooldownTurns = 0; + this.movementCooldownTurns = 0; + this.numVisibleFriendlyRobots = 0; + + this.indicatorString = ""; - this.gameWorld = gw; this.controller = new RobotControllerImpl(gameWorld, this); } @@ -95,10 +101,6 @@ public GameWorld getGameWorld() { return gameWorld; } - public InternalRobot getParent() { - return parent; - } - public int getID() { return ID; } @@ -115,20 +117,16 @@ public MapLocation getLocation() { return location; } - public int getInfluence() { - return influence; + public int getLevel() { + return level; } - public int getConviction() { - return conviction; + public RobotMode getMode() { + return mode; } - public int getFlag() { - return flag; - } - - public int getBid() { - return bid; + public int getHealth() { + return health; } public long getControlBits() { @@ -143,35 +141,49 @@ public int getRoundsAlive() { return roundsAlive; } - public double getCooldownTurns() { - return cooldownTurns; + public int getActionCooldownTurns() { + return actionCooldownTurns; } - public RobotInfo getRobotInfo(boolean trueSense) { - RobotInfo cachedRobotInfo = this.cachedRobotInfoTrue; - RobotType infoType = type; - if (!trueSense && type == RobotType.SLANDERER) { - cachedRobotInfo = this.cachedRobotInfoFake; - infoType = RobotType.POLITICIAN; - } + public int getMovementCooldownTurns() { + return movementCooldownTurns; + } + + public int getTransformCooldownTurns() { + if (this.mode == RobotMode.TURRET) + return this.actionCooldownTurns; + if (this.mode == RobotMode.PORTABLE) + return this.movementCooldownTurns; + return -1; + } + + public int getNumVisibleFriendlyRobots(boolean update) { + if (update) updateNumVisibleFriendlyRobots(); + return this.numVisibleFriendlyRobots; + } + + public int getLeadMutateCost() { + return this.type.getLeadMutateCost(this.level + 1); + } + public int getGoldMutateCost() { + return this.type.getGoldMutateCost(this.level + 1); + } + + public RobotInfo getRobotInfo() { if (cachedRobotInfo != null && cachedRobotInfo.ID == ID && cachedRobotInfo.team == team - && cachedRobotInfo.type == infoType - && cachedRobotInfo.influence == influence - && cachedRobotInfo.conviction == conviction + && cachedRobotInfo.type == type + && cachedRobotInfo.mode == mode + && cachedRobotInfo.level == level + && cachedRobotInfo.health == health && cachedRobotInfo.location.equals(location)) { return cachedRobotInfo; } - RobotInfo newRobotInfo = new RobotInfo(ID, team, infoType, influence, conviction, location); - if (!trueSense && type == RobotType.SLANDERER) { - this.cachedRobotInfoFake = newRobotInfo; - } else { - this.cachedRobotInfoTrue = newRobotInfo; - } - return newRobotInfo; + this.cachedRobotInfo = new RobotInfo(ID, team, type, mode, level, health, location); + return this.cachedRobotInfo; } // ********************************** @@ -179,84 +191,104 @@ public RobotInfo getRobotInfo(boolean trueSense) { // ********************************** /** - * Returns the robot's action radius squared. + * Returns whether the robot can perform actions, based on mode and cooldowns. */ - public int getActionRadiusSquared() { - return this.type.actionRadiusSquared; + public boolean canActCooldown() { + return this.mode.canAct && this.actionCooldownTurns < GameConstants.COOLDOWN_LIMIT; } /** - * Returns the robot's sensor radius squared. + * Returns whether the robot can move, based on mode and cooldowns. */ - public int getSensorRadiusSquared() { - return this.type.sensorRadiusSquared; + public boolean canMoveCooldown() { + return this.mode.canMove && this.movementCooldownTurns < GameConstants.COOLDOWN_LIMIT; } /** - * Returns the robot's detection radius squared. + * Returns whether the robot can transform, based on mode and cooldowns. */ - public int getDetectionRadiusSquared() { - return this.type.detectionRadiusSquared; + public boolean canTransformCooldown() { + if (this.mode == RobotMode.TURRET) + return this.actionCooldownTurns < GameConstants.COOLDOWN_LIMIT; + if (this.mode == RobotMode.PORTABLE) + return this.movementCooldownTurns < GameConstants.COOLDOWN_LIMIT; + return false; + } + + /** + * Returns the robot's action radius squared. + */ + public int getActionRadiusSquared() { + return this.type.actionRadiusSquared; } /** * Returns whether this robot can perform actions on the given location. * - * @param toSense the MapLocation to act + * @param toAct the MapLocation to act */ - public boolean canActLocation(MapLocation toSense){ - return this.location.distanceSquaredTo(toSense) <= getActionRadiusSquared(); + public boolean canActLocation(MapLocation toAct) { + return this.location.distanceSquaredTo(toAct) <= getActionRadiusSquared(); } /** - * Returns whether this robot can sense the given location. + * Returns whether this robot can act at a given radius away. * - * @param toSense the MapLocation to sense + * @param radiusSquared the distance squared to act */ - public boolean canSenseLocation(MapLocation toSense){ - return this.location.distanceSquaredTo(toSense) <= getSensorRadiusSquared(); + public boolean canActRadiusSquared(int radiusSquared) { + return radiusSquared <= getActionRadiusSquared(); } /** - * Returns whether this robot can detect the given location. - * - * @param toSense the MapLocation to detect + * Returns the robot's vision radius squared. */ - public boolean canDetectLocation(MapLocation toSense){ - return this.location.distanceSquaredTo(toSense) <= getDetectionRadiusSquared(); + public int getVisionRadiusSquared() { + return this.type.visionRadiusSquared; } /** - * Returns whether this robot can act at a given radius away. + * Returns whether this robot can sense the given location. * - * @param radiusSquared the distance squared to act + * @param toSense the MapLocation to sense */ - public boolean canActRadiusSquared(int radiusSquared) { - return radiusSquared <= getActionRadiusSquared(); + public boolean canSenseLocation(MapLocation toSense) { + return this.location.distanceSquaredTo(toSense) <= getVisionRadiusSquared(); } /** - * Returns whether this robot can sense something a given radius away. + * Returns whether this robot can sense a given radius away. * * @param radiusSquared the distance squared to sense */ public boolean canSenseRadiusSquared(int radiusSquared) { - return radiusSquared <= getSensorRadiusSquared(); + return radiusSquared <= getVisionRadiusSquared(); } /** - * Returns whether this robot can detect something a given radius away. - * - * @param radiusSquared the distance squared to detect + * @return whether this robot can mutate */ - public boolean canDetectRadiusSquared(int radiusSquared) { - return radiusSquared <= getDetectionRadiusSquared(); + public boolean canMutate() { + if (this.mode == RobotMode.DROID || this.mode == RobotMode.PROTOTYPE) + return false; + if (this.level == GameConstants.MAX_LEVEL) + return false; + return true; } // ****************************************** // ****** UPDATE METHODS ******************** // ****************************************** + /** + * Sets the indicator string of the robot. + * + * @param string the new indicator string of the robot + */ + public void setIndicatorString(String string) { + this.indicatorString = string; + } + /** * Sets the location of the robot. * @@ -270,186 +302,110 @@ public void setLocation(MapLocation loc) { /** * Resets the action cooldown. */ - public void addCooldownTurns() { - double passability = this.gameWorld.getPassability(this.location); - double newCooldownTurns = this.type.actionCooldown / passability; - setCooldownTurns(this.cooldownTurns + newCooldownTurns); + public void addActionCooldownTurns(int numActionCooldownToAdd) { + int newActionCooldownTurns = this.gameWorld.getCooldownWithMultiplier(numActionCooldownToAdd, this.location); + setActionCooldownTurns(this.actionCooldownTurns + newActionCooldownTurns); } /** - * Adds influence given an amount to change this - * robot's influence by. Input can be negative to - * subtract influence. Conviction changes correspondingly. - * - * Only Enlightenment Centers should be able to change influence. - * - * @param influenceAmount the amount to change influence by (can be negative) + * Resets the movement cooldown. */ - public void addInfluenceAndConviction(int influenceAmount) { - int oldInfluence = this.influence; - this.influence += influenceAmount; - if (this.influence > GameConstants.ROBOT_INFLUENCE_LIMIT) { - this.influence = GameConstants.ROBOT_INFLUENCE_LIMIT; - } - this.conviction = this.influence; - if (this.influence != oldInfluence) { - this.gameWorld.getMatchMaker().addAction(getID(), Action.CHANGE_INFLUENCE, this.influence - oldInfluence); - this.gameWorld.getMatchMaker().addAction(getID(), Action.CHANGE_CONVICTION, this.influence - oldInfluence); - } + public void addMovementCooldownTurns(int numMovementCooldownToAdd) { + int newMovementCooldownTurns = this.gameWorld.getCooldownWithMultiplier(numMovementCooldownToAdd, this.location); + setMovementCooldownTurns(this.movementCooldownTurns + newMovementCooldownTurns); } /** * Sets the action cooldown given the number of turns. * - * @param newTurns the number of cooldown turns + * @param newActionTurns the number of action cooldown turns */ - public void setCooldownTurns(double newTurns) { - this.cooldownTurns = newTurns; + public void setActionCooldownTurns(int newActionTurns) { + this.actionCooldownTurns = newActionTurns; } /** - * Adds conviction given an amount to change this - * robot's conviction by. Input can be negative to - * subtract conviction. + * Sets the movement cooldown given the number of turns. * - * @param convictionAmount the amount to change conviction by (can be negative) + * @param newMovementTurns the number of movement cooldown turns */ - public void addConviction(int convictionAmount) { - int oldConviction = this.conviction; - this.conviction += convictionAmount; - if (this.conviction > this.convictionCap) - this.conviction = this.convictionCap; - if (this.conviction != oldConviction) - this.gameWorld.getMatchMaker().addAction(getID(), Action.CHANGE_CONVICTION, this.conviction - oldConviction); + public void setMovementCooldownTurns(int newMovementTurns) { + this.movementCooldownTurns = newMovementTurns; } - /** - * Sets the flag given a new flag value. - * - * @param newFlag the new flag value - */ - public void setFlag(int newFlag) { - this.flag = newFlag; + public void addHealth(int healthAmount) { + addHealth(healthAmount, true); } /** - * Sets the bid given a new bid value. - * The amount of influence bid is held hostage. - * - * @param newBid the new flag value + * Adds health to a robot. Input can be negative to subtract health. + * + * @param healthAmount the amount to change health by (can be negative) + * @param checkArchonDeath whether to end the game if an Archon dies */ - public void setBid(int newBid) { - resetBid(); - this.bid = newBid; - addInfluenceAndConviction(-this.bid); - } - - public void resetBid() { - addInfluenceAndConviction(this.bid); - this.bid = 0; + public void addHealth(int healthAmount, boolean checkArchonDeath) { + int oldHealth = this.health; + this.health += healthAmount; + int maxHealth = this.type.getMaxHealth(this.level); + if (this.health >= maxHealth) { + this.health = maxHealth; + if (this.mode == RobotMode.PROTOTYPE) { + this.mode = RobotMode.TURRET; + this.gameWorld.getMatchMaker().addAction(getID(), Action.FULLY_REPAIRED, -1); + } + } + if (this.health <= 0) { + this.gameWorld.destroyRobot(this.ID, checkArchonDeath); + } else if (this.health != oldHealth) { + this.gameWorld.getMatchMaker().addAction(getID(), Action.CHANGE_HEALTH, this.health - oldHealth); + } } - public void addToCreate(InternalRobot parent, int ID, RobotType type, int influence, int conviction, MapLocation location) { - this.toCreateParents.add(parent); - this.toCreate.add(new RobotInfo(ID, this.team, type, influence, conviction, location)); - } + // ********************************* + // ****** ACTION METHODS ********* + // ********************************* /** - * Empowers given a range. Doesn't self-destruct!! - * - * @param radiusSquared the empower range + * Transform from turret to portable mode, or vice versa. + * Assumes that cooldown is sufficient. */ - public void empower(int radiusSquared) { - InternalRobot[] robots = gameWorld.getAllRobotsWithinRadiusSquared(this.location, radiusSquared); - int numBots = robots.length - 1; // excluding self - if (numBots == 0) - return; - - double convictionToGive = this.conviction - GameConstants.EMPOWER_TAX; - if (convictionToGive <= 0) - return; - - final double convictionPerBot = convictionToGive / numBots; - final double buff = this.gameWorld.getTeamInfo().getBuff(this.team); - - for (InternalRobot bot : robots) { - // check if this robot - if (bot.equals(this)) - continue; - - double conv = convictionPerBot; - if (bot.type == RobotType.ENLIGHTENMENT_CENTER && bot.team == this.team) { - // conviction doesn't get buffed, do nothing - } else if (bot.type == RobotType.ENLIGHTENMENT_CENTER) { - // complicated stuff - double convNeededToConvert = bot.conviction / buff; - if (conv <= convNeededToConvert) { - // all of conviction is buffed - conv *= buff; - } else { - // conviction buffed until conversion - conv = bot.conviction + (conv - convNeededToConvert); - } - } else { - // buff applied, cast down - conv *= buff; - } - bot.empowered(this, (int) conv, this.team); + public void transform() { + if (this.mode == RobotMode.TURRET) { + this.mode = RobotMode.PORTABLE; + } else { + this.mode = RobotMode.TURRET; } + } - // create new bots - for (int i = 0; i < toCreate.size(); i++) { - RobotInfo info = toCreate.get(i); - int id = this.gameWorld.spawnRobot(toCreateParents.get(i), info.getType(), info.getLocation(), this.team, info.getInfluence()); - InternalRobot newBot = this.gameWorld.getObjectInfo().getRobotByID(id); - if (newBot.type != RobotType.ENLIGHTENMENT_CENTER) { - // Shouldn't be called on an enlightenment center, because if spawned center's influence exceeds limit this would send a redundant change conviction action. - newBot.addConviction(info.getConviction() - newBot.getConviction()); - } - else { - // Resets influence and conviction to cap for enlightenment centers. Already done by reset bid, but nicer to do it here. - newBot.addInfluenceAndConviction(0); - } - this.gameWorld.getMatchMaker().addAction(info.getID(), Action.CHANGE_TEAM, id); - } + /** + * Mutate a building. + */ + public void mutate() { + if (!canMutate()) return; + this.level++; + int healthIncrease = this.type.getMaxHealth(this.level) - this.type.getMaxHealth(this.level - 1); + this.gameWorld.getMatchMaker().addAction(getID(), Action.CHANGE_HEALTH, healthIncrease); + this.health += healthIncrease; } /** - * Adds or removes influence, conviction, or both based on the type of the robot - * and the robot's affiliation. - * Called when a Politician Empowers. - * If conviction becomes negative, the robot switches teams or is destroyed. - * - * @param amount the amount this robot's conviction changes by (including all buffs) - * @param newTeam the team of the robot that empowered + * Attacks another robot. Assumes bot is in range. + * + * @param bot the robot to be attacked */ - private void empowered(InternalRobot caller, int amount, Team newTeam) { - if (this.team != newTeam) - amount = -amount; - - if (type == RobotType.ENLIGHTENMENT_CENTER) - addInfluenceAndConviction(amount); - else - addConviction(amount); - - if (this.conviction < 0) { - if (this.type.canBeConverted()) { - int newInfluence = Math.abs(this.influence); - int newConviction = -this.conviction; - caller.addToCreate(this.parent, this.ID, this.type, newInfluence, newConviction, this.location); - } - this.gameWorld.destroyRobot(getID()); - } + public void attack(InternalRobot bot) { + int dmg = this.type.getDamage(this.level); + bot.addHealth(-dmg); } /** - * Empowers given a range. Doesn't self-destruct!! - * - * @param radiusSquared the empower range + * Heals another robot. Assumes bot is in range. + * + * @param bot the robot to be healed */ - public void expose(InternalRobot bot) { - this.gameWorld.addBuffs(this.team, bot.influence); - this.gameWorld.destroyRobot(bot.ID); + public void heal(InternalRobot bot) { + int healingAmount = this.type.getHealing(this.level); + bot.addHealth(healingAmount); } // ********************************* @@ -458,40 +414,25 @@ public void expose(InternalRobot bot) { // should be called at the beginning of every round public void processBeginningOfRound() { - // anything + this.indicatorString = ""; } public void processBeginningOfTurn() { - if (this.cooldownTurns > 0) - this.cooldownTurns = Math.max(0, this.cooldownTurns - 1); + this.actionCooldownTurns = Math.max(0, this.actionCooldownTurns - GameConstants.COOLDOWNS_PER_TURN); + this.movementCooldownTurns = Math.max(0, this.movementCooldownTurns - GameConstants.COOLDOWNS_PER_TURN); this.currentBytecodeLimit = getType().bytecodeLimit; } public void processEndOfTurn() { // bytecode stuff! this.gameWorld.getMatchMaker().addBytecodes(this.ID, this.bytecodesUsed); + // indicator strings! + this.gameWorld.getMatchMaker().addIndicatorString(this.ID, this.indicatorString); this.roundsAlive++; } public void processEndOfRound() { - // generate passive influence - InternalRobot target = (parent == null) ? this : parent; - if (target.getType() != RobotType.ENLIGHTENMENT_CENTER) { - throw new IllegalStateException("The robot's parent is not an Enlightenment Center"); - } - int passiveInfluence = this.type.getPassiveInfluence(this.influence, this.roundsAlive, this.gameWorld.getCurrentRound()); - if (passiveInfluence > 0 && this.team.isPlayer() && this.gameWorld.getObjectInfo().existsRobot(target.ID)) { - target.addInfluenceAndConviction(passiveInfluence); - if (this.type == RobotType.SLANDERER) { - this.gameWorld.getMatchMaker().addAction(this.ID, Action.EMBEZZLE, target.ID); - } - } - - // Slanderers turn into Politicians - if (this.type == RobotType.SLANDERER && this.roundsAlive == GameConstants.CAMOUFLAGE_NUM_ROUNDS) { - this.type = RobotType.POLITICIAN; - this.gameWorld.getMatchMaker().addAction(this.ID, Action.CAMOUFLAGE, -1); - } + // anything } // ********************************* @@ -524,6 +465,13 @@ public void die_exception() { // ****** MISC. METHODS ******************** // ***************************************** + /** + * @return the number of friendly robots within sensor (vision) radius. + */ + public int updateNumVisibleFriendlyRobots() { + return this.numVisibleFriendlyRobots = this.controller.senseNearbyRobots(-1, getTeam()).length; + } + @Override public boolean equals(Object o) { return o != null && (o instanceof InternalRobot) diff --git a/engine/src/main/battlecode/world/LiveMap.java b/engine/src/main/battlecode/world/LiveMap.java index c4067066..45ed5509 100644 --- a/engine/src/main/battlecode/world/LiveMap.java +++ b/engine/src/main/battlecode/world/LiveMap.java @@ -27,28 +27,51 @@ public strictfp class LiveMap { private final MapLocation origin; /** - * The random seed contained in the map file + * The symmetry of the map. + */ + private final MapSymmetry symmetry; + + /** + * Factor to multiply cooldowns by. + */ + private int[] rubbleArray; + + /** + * How much lead is on each square. + */ + private final int[] leadArray; + + /** + * The random seed contained in the map file. */ private final int seed; /** - * The maximum number of rounds in the game + * The maximum number of rounds in the game. */ private final int rounds; /** - * The name of the map + * The name of the map. */ private final String mapName; + /** + * List of anomalies that will occur at certain rounds. + */ + private final AnomalyScheduleEntry[] anomalySchedule; + + /** + * Index of next anomaly to occur (excluding Singularity which always occurs). + */ + private int nextAnomalyIndex; + /** * The bodies to spawn on the map; MapLocations are in world space - * i.e. in game correct MapLocations that need to have the origin * subtracted from them to be used to index into the map arrays. */ - private final RobotInfo[] initialBodies; // only contains Enlightenment Centers - - private double[] passabilityArray; // factor to multiply cooldowns by + private final RobotInfo[] initialBodies; // only contains Archons public LiveMap(int width, int height, @@ -63,11 +86,14 @@ public LiveMap(int width, this.seed = seed; this.rounds = rounds; this.mapName = mapName; + this.symmetry = MapSymmetry.ROTATIONAL; this.initialBodies = Arrays.copyOf(initialBodies, initialBodies.length); - this.passabilityArray = new double[width * height]; - for (int i = 0; i < passabilityArray.length; i++) { - this.passabilityArray[i] = 1; // default cooldown factor is 1 - } + this.rubbleArray = new int[width * height]; + Arrays.fill(this.rubbleArray, 1); // default cooldown factor is 1 + this.leadArray = new int[width * height]; // TODO: we guarantee there to be lead within vision range of archons + + this.anomalySchedule = new AnomalyScheduleEntry[0]; + this.nextAnomalyIndex = 0; // invariant: bodies is sorted by id Arrays.sort(this.initialBodies, (a, b) -> Integer.compare(a.getID(), b.getID())); @@ -79,19 +105,33 @@ public LiveMap(int width, int seed, int rounds, String mapName, + MapSymmetry symmetry, RobotInfo[] initialBodies, - double[] passabilityArray) { + int[] rubbleArray, + int[] leadArray, + AnomalyScheduleEntry[] anomalySchedule) { this.width = width; this.height = height; this.origin = origin; this.seed = seed; this.rounds = rounds; this.mapName = mapName; + this.symmetry = symmetry; this.initialBodies = Arrays.copyOf(initialBodies, initialBodies.length); - this.passabilityArray = new double[passabilityArray.length]; - for (int i = 0; i < passabilityArray.length; i++) { - this.passabilityArray[i] = passabilityArray[i]; + this.rubbleArray = new int[rubbleArray.length]; + for (int i = 0; i < rubbleArray.length; i++) { + this.rubbleArray[i] = rubbleArray[i]; } + this.leadArray = new int[leadArray.length]; + for (int i = 0; i < leadArray.length; i++) { + this.leadArray[i] = leadArray[i]; + } + + this.anomalySchedule = new AnomalyScheduleEntry[anomalySchedule.length]; + for (int i = 0; i < anomalySchedule.length; i++) { + this.anomalySchedule[i] = anomalySchedule[i]; + } + this.nextAnomalyIndex = 0; // invariant: bodies is sorted by id Arrays.sort(this.initialBodies, (a, b) -> Integer.compare(a.getID(), b.getID())); @@ -103,22 +143,21 @@ public LiveMap(int width, * @param gm the LiveMap to copy. */ public LiveMap(LiveMap gm) { - this(gm.width, gm.height, gm.origin, gm.seed, gm.rounds, gm.mapName, gm.initialBodies, - gm.passabilityArray); + this(gm.width, gm.height, gm.origin, gm.seed, gm.rounds, gm.mapName, gm.symmetry, + gm.initialBodies, gm.rubbleArray, gm.leadArray, gm.anomalySchedule); } @Override public boolean equals(Object o) { if (!(o instanceof LiveMap)) return false; - return this.equals((LiveMap) o); } /** * Returns whether two GameMaps are equal. * - * @param other the other map to compare to. - * @return whether the two maps are equivalent. + * @param other the other map to compare to + * @return whether the two maps are equivalent */ public boolean equals(LiveMap other) { if (this.rounds != other.rounds) return false; @@ -127,7 +166,9 @@ public boolean equals(LiveMap other) { if (this.seed != other.seed) return false; if (!this.mapName.equals(other.mapName)) return false; if (!this.origin.equals(other.origin)) return false; - if (!Arrays.equals(this.passabilityArray, other.passabilityArray)) return false; + if (!Arrays.equals(this.rubbleArray, other.rubbleArray)) return false; + if (!Arrays.equals(this.leadArray, other.leadArray)) return false; + if (!Arrays.equals(this.anomalySchedule, other.anomalySchedule)) return false; return Arrays.equals(this.initialBodies, other.initialBodies); } @@ -139,7 +180,9 @@ public int hashCode() { result = 31 * result + seed; result = 31 * result + rounds; result = 31 * result + mapName.hashCode(); - result = 31 * result + Arrays.hashCode(passabilityArray); + result = 31 * result + Arrays.hashCode(rubbleArray); + result = 31 * result + Arrays.hashCode(leadArray); + result = 31 * result + Arrays.hashCode(anomalySchedule); result = 31 * result + Arrays.hashCode(initialBodies); return result; } @@ -154,9 +197,9 @@ public int getWidth() { } /** - * Returns the height of this map. + * Returns the height of the map. * - * @return the height of this map. + * @return the height of the map */ public int getHeight() { return height; @@ -165,12 +208,21 @@ public int getHeight() { /** * Returns the name of the map. * - * @return the name o the map. + * @return the name of the map */ public String getMapName() { return mapName; } + /** + * Returns the symmetry of the map. + * + * @return the symmetry of the map + */ + public MapSymmetry getSymmetry() { + return symmetry; + } + /** * Determines whether or not the location at the specified * coordinates is on the map. The coordinate should be a shifted one @@ -204,7 +256,7 @@ public boolean onTheMap(MapLocation loc) { * @return true if the given circle is on the map, * false if it's not */ - public boolean onTheMap(MapLocation loc, int radius){ + public boolean onTheMap(MapLocation loc, int radius) { return (onTheMap(loc.translate(-radius, 0)) && onTheMap(loc.translate(radius, 0)) && onTheMap(loc.translate(0, -radius)) && @@ -246,13 +298,52 @@ public MapLocation getOrigin() { return origin; } - public double[] getPassabilityArray() { - return passabilityArray; + /** + * @return the rubble array of the map + */ + public int[] getRubbleArray() { + return rubbleArray; + } + + /** + * @return the lead array of the map + */ + public int[] getLeadArray() { + return leadArray; + } + + /** + * @return a copy of the next Anomaly that hasn't happened yet. + */ + public AnomalyScheduleEntry viewNextAnomaly() { + if (this.nextAnomalyIndex < this.anomalySchedule.length) + return this.anomalySchedule[this.nextAnomalyIndex].copyEntry(); + return null; + } + + /** + * Removes the current anomaly by advancing to the next one. + * @return the next Anomaly. + */ + public AnomalyScheduleEntry takeNextAnomaly() { + if (this.nextAnomalyIndex < this.anomalySchedule.length) + return this.anomalySchedule[this.nextAnomalyIndex++].copyEntry(); + return null; + } + + /** + * @return a copy of the anomaly schedule + */ + public AnomalyScheduleEntry[] getAnomalySchedule() { + AnomalyScheduleEntry[] anomalyCopy = new AnomalyScheduleEntry[this.anomalySchedule.length]; + for (int i = 0; i < this.anomalySchedule.length ; i++) + anomalyCopy[i] = this.anomalySchedule[i].copyEntry(); + return anomalyCopy; } @Override public String toString() { - if (passabilityArray.length == 0) + if (rubbleArray.length == 0) { return "LiveMap{" + "width=" + width + ", height=" + height + @@ -261,9 +352,10 @@ public String toString() { ", rounds=" + rounds + ", mapName='" + mapName + '\'' + ", initialBodies=" + Arrays.toString(initialBodies) + - ", len=" + Integer.toString(passabilityArray.length) + + ", len=" + Integer.toString(rubbleArray.length) + "}"; - else return "LiveMap{" + + } else { + return "LiveMap{" + "width=" + width + ", height=" + height + ", origin=" + origin + @@ -271,7 +363,10 @@ public String toString() { ", rounds=" + rounds + ", mapName='" + mapName + '\'' + ", initialBodies=" + Arrays.toString(initialBodies) + - ", passabilityArray=:)" + Arrays.toString(passabilityArray) + + ", rubbleArray=" + Arrays.toString(rubbleArray) + + ", leadArray=" + Arrays.toString(leadArray) + + ", anomalySchedule=" + Arrays.toString(anomalySchedule) + "}"; + } } -} \ No newline at end of file +} diff --git a/engine/src/main/battlecode/world/MapBuilder.java b/engine/src/main/battlecode/world/MapBuilder.java index 31b1547b..838cc880 100644 --- a/engine/src/main/battlecode/world/MapBuilder.java +++ b/engine/src/main/battlecode/world/MapBuilder.java @@ -11,15 +11,15 @@ */ public class MapBuilder { - public enum MapSymmetry {rotational, horizontal, vertical}; - public String name; public int width; public int height; public MapLocation origin; public int seed; private MapSymmetry symmetry; - private double[] passabilityArray; + private int[] rubbleArray; + private int[] leadArray; + private ArrayList anomalySchedule; private int idCounter; private List bodies; @@ -33,12 +33,12 @@ public MapBuilder(String name, int width, int height, int originX, int originY, this.bodies = new ArrayList<>(); // default values - this.symmetry = MapSymmetry.vertical; + this.symmetry = MapSymmetry.ROTATIONAL; this.idCounter = 0; - this.passabilityArray = new double[width*height]; - for (int i = 0; i < passabilityArray.length; i++) { - passabilityArray[i] = 1; // default cooldown factor is 1 - } + this.rubbleArray = new int[width * height]; + Arrays.fill(this.rubbleArray, 1); // default cooldown factor is 1 + this.leadArray = new int[width * height]; + this.anomalySchedule = new ArrayList<>(); } // ******************** @@ -55,7 +55,7 @@ private int locationToIndex(int x, int y) { return x + y * width; } - public void addEnlightenmentCenter(int id, Team team, int influence, MapLocation loc) { + public void addArchon(int id, Team team, MapLocation loc) { // check if something already exists here, if so shout for (RobotInfo r : bodies) { if (r.location.equals(loc)) { @@ -65,31 +65,38 @@ public void addEnlightenmentCenter(int id, Team team, int influence, MapLocation bodies.add(new RobotInfo( id, team, - RobotType.ENLIGHTENMENT_CENTER, - influence, - influence, // Enlightenment Centers conviction == influence + RobotType.ARCHON, + RobotMode.TURRET, + 1, + RobotType.ARCHON.health, loc )); } - public void addEnlightenmentCenter(int x, int y, Team team, int influence) { - addEnlightenmentCenter( + public void addArchon(int x, int y, Team team) { + addArchon( idCounter++, team, - influence, new MapLocation(x, y) ); } - public void setPassability(int x, int y, double value) { - this.passabilityArray[locationToIndex(x, y)] = value; + public void setRubble(int x, int y, int value) { + this.rubbleArray[locationToIndex(x, y)] = value; + } + + public void setLead(int x, int y, int value) { + this.leadArray[locationToIndex(x, y)] = value; + } + + public void addAnomalyScheduleEntry(int round, AnomalyType anomaly) { + this.anomalySchedule.add(new AnomalyScheduleEntry(round, anomaly)); } public void setSymmetry(MapSymmetry symmetry) { this.symmetry = symmetry; } - // ******************** // SYMMETRY METHODS // ******************** @@ -101,12 +108,13 @@ public int symmetricY(int y) { public int symmetricX(int x) { return symmetricX(x, symmetry); } + public int symmetricY(int y, MapSymmetry symmetry) { switch (symmetry) { - case vertical: + case VERTICAL: return y; - case horizontal: - case rotational: + case HORIZONTAL: + case ROTATIONAL: default: return height - 1 - y; } @@ -114,10 +122,10 @@ public int symmetricY(int y, MapSymmetry symmetry) { public int symmetricX(int x, MapSymmetry symmetry) { switch (symmetry) { - case horizontal: + case HORIZONTAL: return x; - case vertical: - case rotational: + case VERTICAL: + case ROTATIONAL: default: return width - 1 - x; } @@ -128,23 +136,23 @@ public MapLocation symmetryLocation(MapLocation p) { } /** - * Add team A Enlightenment Center to (x,y) and team B Enlightenment Center to symmetric position. + * Add team A Archon to (x,y) and team B Archon to symmetric position. * @param x x position * @param y y position */ - public void addSymmetricEnlightenmentCenter(int x, int y) { - addEnlightenmentCenter(x, y, Team.A, GameConstants.INITIAL_ENLIGHTENMENT_CENTER_INFLUENCE); - addEnlightenmentCenter(symmetricX(x), symmetricY(y), Team.B, GameConstants.INITIAL_ENLIGHTENMENT_CENTER_INFLUENCE); + public void addSymmetricArchon(int x, int y) { + addArchon(x, y, Team.A); + addArchon(symmetricX(x), symmetricY(y), Team.B); } - public void addSymmetricNeutralEnlightenmentCenter(int x, int y, int influence) { - addEnlightenmentCenter(x, y, Team.NEUTRAL, influence); - addEnlightenmentCenter(symmetricX(x), symmetricY(y), Team.NEUTRAL, influence); + public void setSymmetricRubble(int x, int y, int value) { + this.rubbleArray[locationToIndex(x, y)] = value; + this.rubbleArray[locationToIndex(symmetricX(x), symmetricY(y))] = value; } - public void setSymmetricPassability(int x, int y, double value) { - this.passabilityArray[locationToIndex(x, y)] = value; - this.passabilityArray[locationToIndex(symmetricX(x), symmetricY(y))] = value; + public void setSymmetricLead(int x, int y, int value) { + this.leadArray[locationToIndex(x, y)] = value; + this.leadArray[locationToIndex(symmetricX(x), symmetricY(y))] = value; } // ******************** @@ -153,7 +161,8 @@ public void setSymmetricPassability(int x, int y, double value) { public LiveMap build() { return new LiveMap(width, height, origin, seed, GameConstants.GAME_MAX_NUMBER_OF_ROUNDS, name, - bodies.toArray(new RobotInfo[bodies.size()]), passabilityArray); + symmetry, bodies.toArray(new RobotInfo[bodies.size()]), rubbleArray, leadArray, + anomalySchedule.toArray(new AnomalyScheduleEntry[anomalySchedule.size()])); } /** @@ -169,60 +178,76 @@ public void saveMap(String pathname) throws IOException { } /** - * Returns true if the map is valid. - * - * WARNING: DON'T TRUST THIS COMPLETELY. THIS DOES NOT VERIFY SYMMETRY. - * @return + * Throws a RuntimeException if the map is invalid. */ public void assertIsValid() { - System.out.println("Validating " + name + "..."); // get robots - RobotInfo[] robots = new RobotInfo[width*height]; + RobotInfo[] robots = new RobotInfo[width * height]; for (RobotInfo r : bodies) { - assert robots[locationToIndex(r.location.x, r.location.y)] == null; + if (robots[locationToIndex(r.location.x, r.location.y)] != null) + throw new RuntimeException("Two robots on the same square"); robots[locationToIndex(r.location.x, r.location.y)] = r; - if (r.influence < 50 || r.influence > 500) // this really should be a GameConstant, but oh well - throw new RuntimeException("Influence not in [50, 500]"); } + if (width < GameConstants.MAP_MIN_WIDTH || height < GameConstants.MAP_MIN_HEIGHT || + width > GameConstants.MAP_MAX_WIDTH || height > GameConstants.MAP_MAX_HEIGHT) + throw new RuntimeException("The map size must be between " + GameConstants.MAP_MIN_WIDTH + "x" + + GameConstants.MAP_MIN_HEIGHT + " and " + GameConstants.MAP_MAX_WIDTH + "x" + + GameConstants.MAP_MAX_HEIGHT + ", inclusive"); - if (width < 32 || height < 32 || width > 64 || height > 64) - throw new RuntimeException("The map size must be between 32x32 and 64x64, inclusive."); - - // checks at least one Enlightenment Center of each team - // only needs to check there's an Enlightenment Center of Team A, because symmetry is checked - boolean noTeamARobots = true; + // checks between 1 and 4 Archons (inclusive) of each team + // only needs to check the Archons of Team A, because symmetry is checked + int numTeamARobots = 0; for (RobotInfo r : bodies) { if (r.getTeam() == Team.A) { - noTeamARobots = false; - break; + numTeamARobots++; } } - if (noTeamARobots) { - throw new RuntimeException("Map must have starting robots of each team"); + if (numTeamARobots < GameConstants.MIN_STARTING_ARCHONS || + numTeamARobots > GameConstants.MAX_STARTING_ARCHONS) { + throw new RuntimeException("Map must have between " + GameConstants.MIN_STARTING_ARCHONS + + "and " + GameConstants.MAX_STARTING_ARCHONS + " starting Archons of each team"); } - for (int x = 0; x < width; x++) { - for (int y = 0; y < height; y++) { - MapLocation current = new MapLocation(x, y); - // This should also be a GameConstant, but I'm speed-coding this and we can fix this later - if (passabilityArray[locationToIndex(current.x, current.y)] < 0.1 || passabilityArray[locationToIndex(current.x, current.y)] > 1.0) { - throw new RuntimeException("Map passability not between 0.1 and 1.0"); - } + for (int i = 0; i < rubbleArray.length; i++) { + if (rubbleArray[i] < GameConstants.MIN_RUBBLE || rubbleArray[i] > GameConstants.MAX_RUBBLE) { + throw new RuntimeException("Map rubble must be between " + GameConstants.MIN_RUBBLE + + " and " + GameConstants.MAX_RUBBLE); } } - // assert passability and Enlightenment Center symmetry + // assert rubble, lead, and Archon symmetry ArrayList allMapSymmetries = getSymmetry(robots); System.out.println("This map has the following symmetries: " + allMapSymmetries); - boolean doesContain = false; - for (MapSymmetry sss : allMapSymmetries) { - if (sss == symmetry) doesContain = true; + if (!allMapSymmetries.contains(this.symmetry)) { + throw new RuntimeException("Rubble, lead, and Archons must be symmetric"); } - if (!doesContain) { - throw new RuntimeException("Passability and Enlightenment Centers must be symmetric according to the given symmetry; they are not currently."); + + // assert that at least one lead deposit inside vision range of at least one Archon + + boolean[] hasVisibleLead = new boolean[2]; + + for (RobotInfo r : bodies) { + if (r.getType() != RobotType.ARCHON) continue; + if (hasVisibleLead[r.getTeam().ordinal()]) continue; + + MapLocation[] visibleLocations = GameWorld.getAllLocationsWithinRadiusSquaredWithoutMap( + this.origin, + this.width, + this.height, + r.getLocation(), + r.getType().visionRadiusSquared + ); + + for (MapLocation location : visibleLocations) + if (this.leadArray[locationToIndex(location.x, location.y)] > 0) + hasVisibleLead[r.getTeam().ordinal()] = true; + } + + if (!(hasVisibleLead[0] && hasVisibleLead[1])) { + throw new RuntimeException("Teams must have at least one lead deposit visible to an Archon."); } } @@ -235,45 +260,47 @@ public MapLocation indexToLocation(int idx) { idx / this.width); } + /** + * @return the list of symmetries, empty if map is invalid + */ private ArrayList getSymmetry(RobotInfo[] robots) { - ArrayList possible = new ArrayList(); - possible.add(MapSymmetry.vertical); - possible.add(MapSymmetry.horizontal); - possible.add(MapSymmetry.rotational); + possible.add(MapSymmetry.ROTATIONAL); + possible.add(MapSymmetry.HORIZONTAL); + possible.add(MapSymmetry.VERTICAL); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { MapLocation current = new MapLocation(x, y); + int curIdx = locationToIndex(current.x, current.y); RobotInfo cri = robots[locationToIndex(current.x, current.y)]; - for (int i = possible.size()-1; i >= 0; i--) { // iterating backwards so we can remove in the loop + for (int i = possible.size() - 1; i >= 0; i--) { // iterating backwards so we can remove in the loop MapSymmetry symmetry = possible.get(i); MapLocation symm = new MapLocation(symmetricX(x, symmetry), symmetricY(y, symmetry)); - if (passabilityArray[locationToIndex(current.x, current.y)] != passabilityArray[locationToIndex(symm.x, symm.y)]) possible.remove(symmetry); - RobotInfo sri = robots[locationToIndex(symm.x, symm.y)]; - if (!(cri == null) || !(sri == null)) { - if (cri == null || sri == null) { - possible.remove(symmetry); - } else if (cri.getType() != sri.getType()) { - possible.remove(symmetry); - } else if (!symmetricTeams(cri.getTeam(), sri.getTeam())) { - possible.remove(symmetry); + int symIdx = locationToIndex(symm.x, symm.y); + if (rubbleArray[curIdx] != rubbleArray[symIdx]) + possible.remove(symmetry); + else if (leadArray[curIdx] != leadArray[symIdx]) + possible.remove(symmetry); + else { + RobotInfo sri = robots[locationToIndex(symm.x, symm.y)]; + if (cri != null || sri != null) { + if (cri == null || sri == null) { + possible.remove(symmetry); + } else if (cri.getType() != sri.getType()) { + possible.remove(symmetry); + } else if (!symmetricTeams(cri.getTeam(), sri.getTeam())) { + possible.remove(symmetry); + } } } } - if (possible.size() <= 1) break; } - if (possible.size() <= 1) break; } - return possible; } private boolean symmetricTeams(Team a, Team b) { - switch (a) { - case A: return b == Team.B; - case B: return b == Team.A; - default: return b == Team.NEUTRAL; - } + return a != b; } } diff --git a/engine/src/main/battlecode/world/MapSymmetry.java b/engine/src/main/battlecode/world/MapSymmetry.java new file mode 100644 index 00000000..3a9d1636 --- /dev/null +++ b/engine/src/main/battlecode/world/MapSymmetry.java @@ -0,0 +1,10 @@ +package battlecode.world; + +/** + * The different kinds of map symmetry. + */ +public enum MapSymmetry { + ROTATIONAL, + HORIZONTAL, + VERTICAL, +} diff --git a/engine/src/main/battlecode/world/ObjectInfo.java b/engine/src/main/battlecode/world/ObjectInfo.java index be652777..5a04b130 100644 --- a/engine/src/main/battlecode/world/ObjectInfo.java +++ b/engine/src/main/battlecode/world/ObjectInfo.java @@ -41,7 +41,7 @@ public strictfp class ObjectInfo { Team.class); private int[] robotCount = new int[3]; - public ObjectInfo(LiveMap gm){ + public ObjectInfo(LiveMap gm) { this.mapWidth = gm.getWidth(); this.mapHeight = gm.getHeight(); this.mapTopLeft = gm.getOrigin(); diff --git a/engine/src/main/battlecode/world/RobotControllerImpl.java b/engine/src/main/battlecode/world/RobotControllerImpl.java index 9528dd7c..396112b4 100644 --- a/engine/src/main/battlecode/world/RobotControllerImpl.java +++ b/engine/src/main/battlecode/world/RobotControllerImpl.java @@ -65,7 +65,7 @@ private static void assertNotNull(Object o) { @Override public int hashCode() { - return robot.getID(); + return getID(); } // ********************************* @@ -74,22 +74,37 @@ public int hashCode() { @Override public int getRoundNum() { - return gameWorld.getCurrentRound(); + return this.gameWorld.getCurrentRound(); } @Override - public int getTeamVotes() { - return gameWorld.getTeamInfo().getVotes(getTeam()); + public int getMapWidth() { + return this.gameWorld.getGameMap().getWidth(); + } + + @Override + public int getMapHeight() { + return this.gameWorld.getGameMap().getHeight(); } @Override public int getRobotCount() { - return gameWorld.getObjectInfo().getRobotCount(getTeam()); + return this.gameWorld.getObjectInfo().getRobotCount(getTeam()); + } + + @Override + public int getArchonCount() { + return this.gameWorld.getObjectInfo().getRobotTypeCount(getTeam(), RobotType.ARCHON); + } + + @Override + public int getTeamLeadAmount(Team team) { + return this.gameWorld.getTeamInfo().getLead(team); } @Override - public double getEmpowerFactor(Team team, int roundsInFuture) { - return gameWorld.getTeamInfo().getBuff(team, getRoundNum() + roundsInFuture); + public int getTeamGoldAmount(Team team) { + return this.gameWorld.getTeamInfo().getGold(team); } // ********************************* @@ -111,28 +126,38 @@ public RobotType getType() { return this.robot.getType(); } + @Override + public RobotMode getMode() { + return this.robot.getMode(); + } + @Override public MapLocation getLocation() { return this.robot.getLocation(); } + + @Override + public int getHealth() { + return this.robot.getHealth(); + } + + @Override + public int getLevel() { + return this.robot.getLevel(); + } private InternalRobot getRobotByID(int id) { - if (!gameWorld.getObjectInfo().existsRobot(id)) + if (!this.gameWorld.getObjectInfo().existsRobot(id)) return null; return this.gameWorld.getObjectInfo().getRobotByID(id); } - - public int getInfluence() { - return this.robot.getInfluence(); - } - public int getConviction() { - return this.robot.getConviction(); + private int locationToInt(MapLocation loc) { + return loc.x + loc.y * this.gameWorld.getGameMap().getWidth(); } - // *********************************** - // ****** GENERAL SENSOR METHODS ***** + // ****** GENERAL VISION METHODS ***** // *********************************** @Override @@ -140,16 +165,26 @@ public boolean onTheMap(MapLocation loc) throws GameActionException { assertNotNull(loc); if (!this.robot.canSenseLocation(loc)) throw new GameActionException(CANT_SENSE_THAT, - "Target location not within sensor range"); - return gameWorld.getGameMap().onTheMap(loc); + "Target location not within vision range"); + return this.gameWorld.getGameMap().onTheMap(loc); } private void assertCanSenseLocation(MapLocation loc) throws GameActionException { assertNotNull(loc); if (!this.robot.canSenseLocation(loc)) throw new GameActionException(CANT_SENSE_THAT, - "Target location not within sensor range"); - if (!gameWorld.getGameMap().onTheMap(loc)) + "Target location not within vision range"); + if (!this.gameWorld.getGameMap().onTheMap(loc)) + throw new GameActionException(CANT_SENSE_THAT, + "Target location is not on the map"); + } + + private void assertCanActLocation(MapLocation loc) throws GameActionException { + assertNotNull(loc); + if (!this.robot.canActLocation(loc)) + throw new GameActionException(OUT_OF_RANGE, + "Target location not within action range"); + if (!this.gameWorld.getGameMap().onTheMap(loc)) throw new GameActionException(CANT_SENSE_THAT, "Target location is not on the map"); } @@ -167,42 +202,24 @@ public boolean canSenseRadiusSquared(int radiusSquared) { return this.robot.canSenseRadiusSquared(radiusSquared); } - private void assertCanDetectLocation(MapLocation loc) throws GameActionException { - assertNotNull(loc); - if (!this.robot.canDetectLocation(loc)) - throw new GameActionException(CANT_SENSE_THAT, - "Target location not within detection range"); - if (!gameWorld.getGameMap().onTheMap(loc)) - throw new GameActionException(CANT_SENSE_THAT, - "Target location is not on the map"); + @Override + public boolean isLocationOccupied(MapLocation loc) throws GameActionException { + assertCanSenseLocation(loc); + return this.gameWorld.getRobot(loc) != null; } @Override - public boolean canDetectLocation(MapLocation loc) { + public boolean canSenseRobotAtLocation(MapLocation loc) { try { - assertCanDetectLocation(loc); - return true; + return isLocationOccupied(loc); } catch (GameActionException e) { return false; } } - @Override - public boolean canDetectRadiusSquared(int radiusSquared) { - return this.robot.canDetectRadiusSquared(radiusSquared); - } - - @Override - public boolean isLocationOccupied(MapLocation loc) throws GameActionException { - assertCanDetectLocation(loc); - return this.gameWorld.getRobot(loc) != null; - } - @Override public RobotInfo senseRobotAtLocation(MapLocation loc) throws GameActionException { assertCanSenseLocation(loc); - InternalRobot bot = gameWorld.getRobot(loc); - if (bot != null) - return bot.getRobotInfo(getType().canTrueSense()); - return null; + InternalRobot bot = this.gameWorld.getRobot(loc); + return bot == null ? null : bot.getRobotInfo(); } @Override @@ -215,8 +232,8 @@ public boolean canSenseRobot(int id) { public RobotInfo senseRobot(int id) throws GameActionException { if (!canSenseRobot(id)) throw new GameActionException(CANT_SENSE_THAT, - "Can't sense given robot; It may not exist anymore"); - return getRobotByID(id).getRobotInfo(getType().canTrueSense()); + "Can't sense given robot; It may be out of vision range or not exist anymore"); + return getRobotByID(id).getRobotInfo(); } @Override @@ -237,7 +254,7 @@ public RobotInfo[] senseNearbyRobots(int radiusSquared, Team team) { @Override public RobotInfo[] senseNearbyRobots(MapLocation center, int radiusSquared, Team team) { assertNotNull(center); - int actualRadiusSquared = radiusSquared == -1 ? getType().sensorRadiusSquared : Math.min(radiusSquared, getType().sensorRadiusSquared); + int actualRadiusSquared = radiusSquared == -1 ? getType().visionRadiusSquared : Math.min(radiusSquared, getType().visionRadiusSquared); InternalRobot[] allSensedRobots = gameWorld.getAllRobotsWithinRadiusSquared(center, actualRadiusSquared); List validSensedRobots = new ArrayList<>(); for (InternalRobot sensedRobot : allSensedRobots) { @@ -250,43 +267,107 @@ public RobotInfo[] senseNearbyRobots(MapLocation center, int radiusSquared, Team // check if right team if (team != null && sensedRobot.getTeam() != team) continue; - validSensedRobots.add(sensedRobot.getRobotInfo(getType().canTrueSense())); + validSensedRobots.add(sensedRobot.getRobotInfo()); } return validSensedRobots.toArray(new RobotInfo[validSensedRobots.size()]); } + @Override + public int senseRubble(MapLocation loc) throws GameActionException { + assertCanSenseLocation(loc); + return this.gameWorld.getRubble(loc); + } + + @Override + public int senseLead(MapLocation loc) throws GameActionException { + assertCanSenseLocation(loc); + return this.gameWorld.getLead(loc); + } + + @Override + public int senseGold(MapLocation loc) throws GameActionException { + assertCanSenseLocation(loc); + return this.gameWorld.getGold(loc); + } + @Override - public MapLocation[] detectNearbyRobots() { - return detectNearbyRobots(-1); + public MapLocation[] senseNearbyLocationsWithLead() { + try { + return senseNearbyLocationsWithLead(getLocation(), -1, 1); + } catch (GameActionException willNeverHappen) { + throw new RuntimeException("impossible", willNeverHappen); + } } @Override - public MapLocation[] detectNearbyRobots(int radiusSquared) { - return detectNearbyRobots(getLocation(), radiusSquared); + public MapLocation[] senseNearbyLocationsWithLead(int radiusSquared) throws GameActionException { + return senseNearbyLocationsWithLead(getLocation(), radiusSquared, 1); } @Override - public MapLocation[] detectNearbyRobots(MapLocation center, int radiusSquared) { - assertNotNull(center); - int actualRadiusSquared = radiusSquared == -1 ? getType().detectionRadiusSquared : Math.min(radiusSquared, getType().detectionRadiusSquared); - InternalRobot[] allDetectedRobots = gameWorld.getAllRobotsWithinRadiusSquared(center, actualRadiusSquared); - List validDetectedRobots = new ArrayList<>(); - for (InternalRobot detectedRobot : allDetectedRobots) { - // check if this robot - if (detectedRobot.equals(this.robot)) - continue; - // check if can detect - if (!canDetectLocation(detectedRobot.getLocation())) - continue; - validDetectedRobots.add(detectedRobot.getLocation()); + public MapLocation[] senseNearbyLocationsWithLead(MapLocation center, int radiusSquared) throws GameActionException { + return senseNearbyLocationsWithLead(center, radiusSquared, 1); + } + + @Override + public MapLocation[] senseNearbyLocationsWithLead(int radiusSquared, int minLead) throws GameActionException { + return senseNearbyLocationsWithLead(getLocation(), radiusSquared, minLead); + } + + @Override + public MapLocation[] senseNearbyLocationsWithLead(MapLocation center, int radiusSquared, int minLead) throws GameActionException { + radiusSquared = (radiusSquared == -1) ? getType().visionRadiusSquared : Math.min(radiusSquared, getType().visionRadiusSquared); + if (radiusSquared < 0) + throw new GameActionException(CANT_DO_THAT, + "Radius squared must be non-negative."); + ArrayList locations = new ArrayList<>(); + for (MapLocation loc : this.gameWorld.getAllLocationsWithinRadiusSquared(center, radiusSquared)) { + if (this.gameWorld.getLead(loc) >= minLead && canSenseLocation(loc)) { + locations.add(loc); + } } - return validDetectedRobots.toArray(new MapLocation[validDetectedRobots.size()]); + MapLocation[] result = new MapLocation[locations.size()]; + return locations.toArray(result); } - @Override - public double sensePassability(MapLocation loc) throws GameActionException { - assertCanSenseLocation(loc); - return this.gameWorld.getPassability(loc); + @Override + public MapLocation[] senseNearbyLocationsWithGold() { + try { + return senseNearbyLocationsWithGold(getLocation(), -1, 1); + } catch (GameActionException willNeverHappen) { + throw new RuntimeException("impossible", willNeverHappen); + } + } + + @Override + public MapLocation[] senseNearbyLocationsWithGold(int radiusSquared) throws GameActionException { + return senseNearbyLocationsWithGold(getLocation(), radiusSquared, 1); + } + + @Override + public MapLocation[] senseNearbyLocationsWithGold(MapLocation center, int radiusSquared) throws GameActionException { + return senseNearbyLocationsWithGold(center, radiusSquared, 1); + } + + @Override + public MapLocation[] senseNearbyLocationsWithGold(int radiusSquared, int minGold) throws GameActionException { + return senseNearbyLocationsWithGold(getLocation(), radiusSquared, minGold); + } + + @Override + public MapLocation[] senseNearbyLocationsWithGold(MapLocation center, int radiusSquared, int minGold) throws GameActionException { + radiusSquared = (radiusSquared == -1) ? getType().visionRadiusSquared : Math.min(radiusSquared, getType().visionRadiusSquared); + if (radiusSquared < 0) + throw new GameActionException(CANT_DO_THAT, + "Radius squared must be non-negative."); + ArrayList locations = new ArrayList<>(); + for (MapLocation loc : this.gameWorld.getAllLocationsWithinRadiusSquared(center, radiusSquared)) { + if (this.gameWorld.getGold(loc) >= minGold && canSenseLocation(loc)) { + locations.add(loc); + } + } + MapLocation[] result = new MapLocation[locations.size()]; + return locations.toArray(result); } @Override @@ -294,41 +375,87 @@ public MapLocation adjacentLocation(Direction dir) { return getLocation().add(dir); } + @Override + public MapLocation[] getAllLocationsWithinRadiusSquared(MapLocation center, int radiusSquared) throws GameActionException { + assertNotNull(center); + if (radiusSquared < 0) + throw new GameActionException(CANT_DO_THAT, + "Radius squared must be non-negative."); + return this.gameWorld.getAllLocationsWithinRadiusSquared(center, Math.min(radiusSquared, getType().visionRadiusSquared)); + } + // *********************************** // ****** READINESS METHODS ********** // *********************************** - private void assertIsReady() throws GameActionException { - if (getCooldownTurns() >= 1) + private void assertIsActionReady() throws GameActionException { + if (!this.robot.getMode().canAct) + throw new GameActionException(CANT_DO_THAT, + "This robot is not in a mode that can act."); + if (!this.robot.canActCooldown()) throw new GameActionException(IS_NOT_READY, "This robot's action cooldown has not expired."); } - /** - * Check if the robot is ready to perform an action. Returns true if - * the current cooldown counter is strictly less than 1. - * - * @return true if the robot can do an action, false otherwise - */ @Override - public boolean isReady() { + public boolean isActionReady() { try { - assertIsReady(); + assertIsActionReady(); return true; } catch (GameActionException e) { return false; } } - /** - * Return the cooldown turn counter of the robot. If this is < 1, the robot - * can perform an action; otherwise, it cannot. - * The counter is decreased by 1 at the start of every - * turn, and increased to varying degrees by different actions taken. - * - * @return the number of cooldown turns as a float - */ @Override - public double getCooldownTurns() { - return this.robot.getCooldownTurns(); + public int getActionCooldownTurns() { + return this.robot.getActionCooldownTurns(); + } + + private void assertIsMovementReady() throws GameActionException { + if (!this.robot.getMode().canMove) + throw new GameActionException(CANT_DO_THAT, + "This robot is not in a mode that can move."); + if (!this.robot.canMoveCooldown()) + throw new GameActionException(IS_NOT_READY, + "This robot's movement cooldown has not expired."); + } + + @Override + public boolean isMovementReady() { + try { + assertIsMovementReady(); + return true; + } catch (GameActionException e) { return false; } + } + + @Override + public int getMovementCooldownTurns() { + return this.robot.getMovementCooldownTurns(); + } + + private void assertIsTransformReady() throws GameActionException { + if (!this.robot.getMode().canTransform) + throw new GameActionException(CANT_DO_THAT, + "This robot is not in a mode that can transform."); + if (!this.robot.canTransformCooldown()) + throw new GameActionException(IS_NOT_READY, + "This robot's transform cooldown (either action or movement" + + "cooldown, depending on its current mode) has not expired."); + } + + @Override + public boolean isTransformReady() { + try { + assertIsTransformReady(); + return true; + } catch (GameActionException e) { return false; } + } + + @Override + public int getTransformCooldownTurns() throws GameActionException { + if (!this.robot.getMode().canTransform) + throw new GameActionException(CANT_DO_THAT, + "This robot is not in a mode that can transform."); + return this.robot.getTransformCooldownTurns(); } // *********************************** @@ -337,9 +464,7 @@ public double getCooldownTurns() { private void assertCanMove(Direction dir) throws GameActionException { assertNotNull(dir); - if (!getType().canMove()) - throw new GameActionException(CANT_DO_THAT, - "Robot is of type " + getType() + " which cannot move."); + assertIsMovementReady(); MapLocation loc = adjacentLocation(dir); if (!onTheMap(loc)) throw new GameActionException(OUT_OF_RANGE, @@ -347,9 +472,6 @@ private void assertCanMove(Direction dir) throws GameActionException { if (isLocationOccupied(loc)) throw new GameActionException(CANT_MOVE_THERE, "Cannot move to an occupied location; " + loc + " is occupied."); - if (!isReady()) - throw new GameActionException(IS_NOT_READY, - "Robot is still cooling down! You need to wait before you can perform another action."); } @Override @@ -363,31 +485,34 @@ public boolean canMove(Direction dir) { @Override public void move(Direction dir) throws GameActionException { assertCanMove(dir); - MapLocation center = adjacentLocation(dir); - this.robot.addCooldownTurns(); this.gameWorld.moveRobot(getLocation(), center); this.robot.setLocation(center); - - gameWorld.getMatchMaker().addMoved(getID(), getLocation()); + // this has to happen after robot's location changed because rubble + this.robot.addMovementCooldownTurns(getType().movementCooldown); + this.gameWorld.getMatchMaker().addMoved(getID(), getLocation()); } // *********************************** // ****** BUILDING/SPAWNING ********** // *********************************** - private void assertCanBuildRobot(RobotType type, Direction dir, int influence) throws GameActionException { + private void assertCanBuildRobot(RobotType type, Direction dir) throws GameActionException { assertNotNull(type); assertNotNull(dir); + assertIsActionReady(); if (!getType().canBuild(type)) throw new GameActionException(CANT_DO_THAT, - "Robot is of type " + getType() + " which cannot build robots of type" + type + "."); - if (influence <= 0) - throw new GameActionException(CANT_DO_THAT, - "Cannot spend nonpositive amount of influence."); - if (influence > getInfluence()) - throw new GameActionException(CANT_DO_THAT, - "Cannot spend more influence than you have."); + "Robot is of type " + getType() + " which cannot build robots of type " + type + "."); + + Team team = getTeam(); + if (this.gameWorld.getTeamInfo().getLead(team) < type.buildCostLead) + throw new GameActionException(NOT_ENOUGH_RESOURCE, + "Insufficient amount of lead."); + if (this.gameWorld.getTeamInfo().getGold(team) < type.buildCostGold) + throw new GameActionException(NOT_ENOUGH_RESOURCE, + "Insufficient amount of gold."); + MapLocation spawnLoc = adjacentLocation(dir); if (!onTheMap(spawnLoc)) throw new GameActionException(OUT_OF_RANGE, @@ -395,255 +520,388 @@ private void assertCanBuildRobot(RobotType type, Direction dir, int influence) t if (isLocationOccupied(spawnLoc)) throw new GameActionException(CANT_MOVE_THERE, "Cannot spawn to an occupied location; " + spawnLoc + " is occupied."); - if (!isReady()) - throw new GameActionException(IS_NOT_READY, - "Robot is still cooling down! You need to wait before you can perform another action."); } @Override - public boolean canBuildRobot(RobotType type, Direction dir, int influence) { + public boolean canBuildRobot(RobotType type, Direction dir) { try { - assertCanBuildRobot(type, dir, influence); + assertCanBuildRobot(type, dir); return true; } catch (GameActionException e) { return false; } } @Override - public void buildRobot(RobotType type, Direction dir, int influence) throws GameActionException { - assertCanBuildRobot(type, dir, influence); + public void buildRobot(RobotType type, Direction dir) throws GameActionException { + assertCanBuildRobot(type, dir); + this.robot.addActionCooldownTurns(getType().actionCooldown); + Team team = getTeam(); + this.gameWorld.getTeamInfo().addLead(team, -type.buildCostLead); + this.gameWorld.getTeamInfo().addGold(team, -type.buildCostGold); + int newId = this.gameWorld.spawnRobot(type, adjacentLocation(dir), team); + this.gameWorld.getMatchMaker().addAction(getID(), Action.SPAWN_UNIT, newId); + } - this.robot.addCooldownTurns(); - this.robot.addInfluenceAndConviction(-influence); + // ***************************** + // **** COMBAT UNIT METHODS **** + // ***************************** - int robotID = gameWorld.spawnRobot(this.robot, type, adjacentLocation(dir), getTeam(), influence); + private void assertCanAttack(MapLocation loc) throws GameActionException { + assertNotNull(loc); + assertCanActLocation(loc); + assertIsActionReady(); + if (!getType().canAttack()) + throw new GameActionException(CANT_DO_THAT, + "Robot is of type " + getType() + " which cannot attack."); + InternalRobot bot = this.gameWorld.getRobot(loc); + if (bot == null) + throw new GameActionException(NO_ROBOT_THERE, + "There is no robot to attack at the target location."); + if (bot.getTeam() == getTeam()) + throw new GameActionException(CANT_DO_THAT, + "Robot is not on the enemy team."); + } - // set cooldown turns here, because not all new robots have cooldown (eg. switching teams) - InternalRobot newBot = getRobotByID(robotID); - newBot.setCooldownTurns(type.initialCooldown); + @Override + public boolean canAttack(MapLocation loc) { + try { + assertCanAttack(loc); + return true; + } catch (GameActionException e) { return false; } + } - gameWorld.getMatchMaker().addAction(getID(), Action.SPAWN_UNIT, robotID); + @Override + public void attack(MapLocation loc) throws GameActionException { + assertCanAttack(loc); + this.robot.addActionCooldownTurns(getType().actionCooldown); + InternalRobot bot = this.gameWorld.getRobot(loc); + this.robot.attack(bot); + this.gameWorld.getMatchMaker().addAction(getID(), Action.ATTACK, bot.getID()); } - - // *********************************** - // ****** POLITICIAN METHODS ********* - // *********************************** - private void assertCanEmpower(int radiusSquared) throws GameActionException { - assertIsReady(); - if (!getType().canEmpower()) + // ***************************** + // ******** SAGE METHODS ******* + // ***************************** + + private void assertCanEnvision(AnomalyType anomaly) throws GameActionException { + assertNotNull(anomaly); + assertIsActionReady(); + if (!getType().canEnvision()) throw new GameActionException(CANT_DO_THAT, - "Robot is of type " + getType() + " which cannot empower."); - if (radiusSquared > getType().actionRadiusSquared) + "Robot is of type " + getType() + " which cannot envision."); + if (!anomaly.isSageAnomaly) throw new GameActionException(CANT_DO_THAT, - "Robot's empower radius is smaller than radius specified"); + "Sage can not use anomaly of type " + anomaly); } @Override - public boolean canEmpower(int radiusSquared) { + public boolean canEnvision(AnomalyType anomaly) { try { - assertCanEmpower(radiusSquared); + assertCanEnvision(anomaly); return true; - } catch (GameActionException e) { return false; } + } catch (GameActionException e) { return false; } } - - @Override - public void empower(int radiusSquared) throws GameActionException { - assertCanEmpower(radiusSquared); - this.robot.addCooldownTurns(); // not needed but here for the sake of consistency - this.robot.empower(radiusSquared); - gameWorld.getMatchMaker().addAction(getID(), Action.EMPOWER, radiusSquared); - - // self-destruct - gameWorld.destroyRobot(this.robot.getID()); + @Override + public void envision(AnomalyType anomaly) throws GameActionException { + assertCanEnvision(anomaly); + this.robot.addActionCooldownTurns(getType().actionCooldown); + switch (anomaly) { + case ABYSS: + this.gameWorld.causeAbyssSage(this.robot); + this.gameWorld.getMatchMaker().addAction(getID(), Action.LOCAL_ABYSS, locationToInt(getLocation())); + break; + case CHARGE: + this.gameWorld.causeChargeSage(this.robot); + this.gameWorld.getMatchMaker().addAction(getID(), Action.LOCAL_CHARGE, locationToInt(getLocation())); + break; + case FURY: + this.gameWorld.causeFurySage(this.robot); + this.gameWorld.getMatchMaker().addAction(getID(), Action.LOCAL_FURY, locationToInt(getLocation())); + break; + } } + // ***************************** + // ****** REPAIR METHODS ******* + // ***************************** - // *********************************** - // ****** MUCKRAKER METHODS ********** - // *********************************** - - private void assertCanExpose(MapLocation loc) throws GameActionException { - assertIsReady(); - if (!getType().canExpose()) - throw new GameActionException(CANT_DO_THAT, - "Robot is of type " + getType() + " which cannot expose."); - if (!onTheMap(loc)) - throw new GameActionException(OUT_OF_RANGE, - "Location is not on the map."); - if (!this.robot.canActLocation(loc)) - throw new GameActionException(CANT_DO_THAT, - "Location can't be exposed because it is out of range."); - InternalRobot bot = gameWorld.getRobot(loc); + private void assertCanRepair(MapLocation loc) throws GameActionException { + assertNotNull(loc); + assertCanActLocation(loc); + assertIsActionReady(); + InternalRobot bot = this.gameWorld.getRobot(loc); if (bot == null) + throw new GameActionException(NO_ROBOT_THERE, + "There is no robot to repair at the target location."); + if (!getType().canRepair(bot.getType())) throw new GameActionException(CANT_DO_THAT, - "There is no robot at specified location."); - if (!(bot.getType().canBeExposed())) - throw new GameActionException(CANT_DO_THAT, - "Robot at target location is not of a type that can be exposed."); - if (bot.getTeam() == getTeam()) + "Robot is of type " + getType() + " which cannot repair robots of type " + bot.getType() + "."); + if (bot.getTeam() != getTeam()) throw new GameActionException(CANT_DO_THAT, - "Robot at target location is not on the enemy team."); - } - - private void assertCanExpose(int id) throws GameActionException { - assertIsReady(); - if (!getType().canExpose()) - throw new GameActionException(CANT_DO_THAT, - "Robot is of type " + getType() + " which cannot expose."); - if (!canSenseRobot(id)) - throw new GameActionException(OUT_OF_RANGE, - "The targeted robot cannot be sensed."); - InternalRobot bot = getRobotByID(id); - if (!this.robot.canActLocation(bot.getLocation())) - throw new GameActionException(OUT_OF_RANGE, - "Robot can't be exposed because it is out of range."); - if (!(bot.getType().canBeExposed())) - throw new GameActionException(CANT_DO_THAT, - "Robot is not of a type that can be exposed."); - if (bot.getTeam() == getTeam()) - throw new GameActionException(CANT_DO_THAT, - "Robot is not on the enemy team."); + "Robot is not on your team so can't be repaired."); } @Override - public boolean canExpose(MapLocation loc) { + public boolean canRepair(MapLocation loc) { try { - assertCanExpose(loc); + assertCanRepair(loc); return true; } catch (GameActionException e) { return false; } } @Override - public boolean canExpose(int id) { + public void repair(MapLocation loc) throws GameActionException { + assertCanRepair(loc); + this.robot.addActionCooldownTurns(getType().actionCooldown); + InternalRobot bot = this.gameWorld.getRobot(loc); + this.robot.heal(bot); + this.gameWorld.getMatchMaker().addAction(getID(), Action.REPAIR, bot.getID()); + } + + // *********************** + // **** MINER METHODS **** + // *********************** + + private void assertCanMineLead(MapLocation loc) throws GameActionException { + assertNotNull(loc); + assertCanActLocation(loc); + assertIsActionReady(); + if (!getType().canMine()) + throw new GameActionException(CANT_DO_THAT, + "Robot is of type " + getType() + " which cannot mine."); + if (this.gameWorld.getLead(loc) < 1) + throw new GameActionException(CANT_DO_THAT, + "Lead amount must be positive to be mined."); + } + + @Override + public boolean canMineLead(MapLocation loc) { try { - assertCanExpose(id); + assertCanMineLead(loc); return true; } catch (GameActionException e) { return false; } } - + @Override - public void expose(MapLocation loc) throws GameActionException { - assertCanExpose(loc); + public void mineLead(MapLocation loc) throws GameActionException { + assertCanMineLead(loc); + this.robot.addActionCooldownTurns(getType().actionCooldown); + this.gameWorld.setLead(loc, this.gameWorld.getLead(loc) - 1); + this.gameWorld.getTeamInfo().addLead(getTeam(), 1); + this.gameWorld.getMatchMaker().addAction(getID(), Action.MINE_LEAD, locationToInt(loc)); + this.gameWorld.getMatchMaker().addLeadDrop(loc, -1); + } - this.robot.addCooldownTurns(); - InternalRobot bot = gameWorld.getRobot(loc); - int exposedID = bot.getID(); - this.robot.expose(bot); - gameWorld.getMatchMaker().addAction(getID(), Action.EXPOSE, exposedID); + private void assertCanMineGold(MapLocation loc) throws GameActionException { + assertNotNull(loc); + assertCanActLocation(loc); + assertIsActionReady(); + if (!getType().canMine()) + throw new GameActionException(CANT_DO_THAT, + "Robot is of type " + getType() + " which cannot mine."); + if (this.gameWorld.getGold(loc) < 1) + throw new GameActionException(CANT_DO_THAT, + "Gold amount must be positive to be mined."); } @Override - public void expose(int id) throws GameActionException { - assertCanExpose(id); + public boolean canMineGold(MapLocation loc) { + try { + assertCanMineGold(loc); + return true; + } catch (GameActionException e) { return false; } + } - this.robot.addCooldownTurns(); - InternalRobot bot = getRobotByID(id); - this.robot.expose(bot); - gameWorld.getMatchMaker().addAction(getID(), Action.EXPOSE, id); + @Override + public void mineGold(MapLocation loc) throws GameActionException { + assertCanMineGold(loc); + this.robot.addActionCooldownTurns(getType().actionCooldown); + this.gameWorld.setGold(loc, this.gameWorld.getGold(loc) - 1); + this.gameWorld.getTeamInfo().addGold(getTeam(), 1); + this.gameWorld.getMatchMaker().addAction(getID(), Action.MINE_GOLD, locationToInt(loc)); + this.gameWorld.getMatchMaker().addGoldDrop(loc, -1); } - // *********************************** - // *** ENLIGHTENMENT CENTER METHODS ** - // *********************************** + // ************************* + // **** MUTATE METHODS **** + // ************************* - private void assertCanBid(int influence) throws GameActionException { - if (!getType().canBid()) { + private void assertCanMutate(MapLocation loc) throws GameActionException { + assertNotNull(loc); + assertCanActLocation(loc); + assertIsActionReady(); + InternalRobot bot = this.gameWorld.getRobot(loc); + if (bot == null) + throw new GameActionException(NO_ROBOT_THERE, + "There is no robot to mutate at the target location."); + if (!getType().canMutate(bot.getType())) throw new GameActionException(CANT_DO_THAT, - "Robot is of type " + getType() + " which cannot bid."); - } else if (influence <= 0) { + "Robot is of type " + getType() + " which cannot mutate robots of type " + bot.getType() + "."); + if (bot.getTeam() != getTeam()) throw new GameActionException(CANT_DO_THAT, - "Can only bid non-negative amounts of influence."); - } else if (influence > getInfluence()) { + "Robot is not on your team so can't be mutated."); + if (!bot.canMutate()) throw new GameActionException(CANT_DO_THAT, - "Not possible to bid influence you don't have."); - } + "Robot is either not in a mutable mode, or already at max level."); + if (gameWorld.getTeamInfo().getLead(getTeam()) < bot.getLeadMutateCost()) + throw new GameActionException(NOT_ENOUGH_RESOURCE, + "You don't have enough lead to mutate this robot."); + if (gameWorld.getTeamInfo().getGold(getTeam()) < bot.getGoldMutateCost()) + throw new GameActionException(NOT_ENOUGH_RESOURCE, + "You don't have enough gold to mutate this robot."); } @Override - public boolean canBid(int influence) { + public boolean canMutate(MapLocation loc) { try { - assertCanBid(influence); + assertCanMutate(loc); return true; } catch (GameActionException e) { return false; } } @Override - public void bid(int influence) throws GameActionException { - assertCanBid(influence); - - this.robot.setBid(influence); - gameWorld.getMatchMaker().addAction(getID(), Action.PLACE_BID, influence); + public void mutate(MapLocation loc) throws GameActionException { + assertCanMutate(loc); + this.robot.addActionCooldownTurns(getType().actionCooldown); + Team team = getTeam(); + InternalRobot bot = this.gameWorld.getRobot(loc); + int leadNeeded = bot.getLeadMutateCost(); + int goldNeeded = bot.getGoldMutateCost(); + this.gameWorld.getTeamInfo().addLead(team, -leadNeeded); + this.gameWorld.getTeamInfo().addGold(team, -goldNeeded); + bot.mutate(); + bot.addActionCooldownTurns(GameConstants.MUTATE_COOLDOWN); + bot.addMovementCooldownTurns(GameConstants.MUTATE_COOLDOWN); + this.gameWorld.getMatchMaker().addAction(getID(), Action.MUTATE, bot.getID()); } - // *********************************** - // ****** COMMUNICATION METHODS ****** - // *********************************** + // *************************** + // **** TRANSMUTE METHODS **** + // *************************** - private void assertCanSetFlag(int flag) throws GameActionException { - if (flag < GameConstants.MIN_FLAG_VALUE || flag > GameConstants.MAX_FLAG_VALUE) { - throw new GameActionException(CANT_DO_THAT, "Flag value out of range"); + @Override + public int getTransmutationRate() { + if (getType() != RobotType.LABORATORY) { + return 0; } + return getTransmutationRate(getLevel()); } @Override - public boolean canSetFlag(int flag) { + public int getTransmutationRate(int laboratory_level) { + final double alchemist_loneliness_k; + switch (laboratory_level) { + case 1: alchemist_loneliness_k = GameConstants.ALCHEMIST_LONELINESS_K_L1; break; + case 2: alchemist_loneliness_k = GameConstants.ALCHEMIST_LONELINESS_K_L2; break; + case 3: alchemist_loneliness_k = GameConstants.ALCHEMIST_LONELINESS_K_L3; break; + default: return 0; + } + return (int) (GameConstants.ALCHEMIST_LONELINESS_A - GameConstants.ALCHEMIST_LONELINESS_B * + Math.exp(-alchemist_loneliness_k * this.robot.getNumVisibleFriendlyRobots(true))); + } + + private void assertCanTransmute() throws GameActionException { + assertIsActionReady(); + if (!getType().canTransmute()) + throw new GameActionException(CANT_DO_THAT, + "Robot is of type " + getType() + " which cannot transmute lead to gold."); + if (this.gameWorld.getTeamInfo().getLead(getTeam()) < getTransmutationRate()) + throw new GameActionException(NOT_ENOUGH_RESOURCE, + "You don't have enough lead to transmute to gold."); + } + + @Override + public boolean canTransmute() { try { - assertCanSetFlag(flag); + assertCanTransmute(); return true; - } catch (GameActionException e) { return false; } + } catch (GameActionException e) { return false; } } @Override - public void setFlag(int flag) throws GameActionException { - assertCanSetFlag(flag); - this.robot.setFlag(flag); - gameWorld.getMatchMaker().addAction(getID(), Action.SET_FLAG, flag); + public void transmute() throws GameActionException { + assertCanTransmute(); + this.robot.addActionCooldownTurns(getType().actionCooldown); + Team team = getTeam(); + this.gameWorld.getTeamInfo().addLead(team, -getTransmutationRate()); + this.gameWorld.getTeamInfo().addGold(team, 1); + this.gameWorld.getMatchMaker().addAction(getID(), Action.TRANSMUTE, -1); } - private void assertCanGetFlag(int id) throws GameActionException { - InternalRobot bot = getRobotByID(id); - if (bot == null) - throw new GameActionException(CANT_DO_THAT, - "Robot of given ID does not exist."); - if (getType() != RobotType.ENLIGHTENMENT_CENTER && - bot.getType() != RobotType.ENLIGHTENMENT_CENTER && - !canSenseLocation(bot.getLocation())) - throw new GameActionException(CANT_SENSE_THAT, - "Robot at location is out of sensor range and not an Enlightenment Center."); + // *************************** + // **** TRANSFORM METHODS **** + // *************************** + + private void assertCanTransform() throws GameActionException { + assertIsTransformReady(); } @Override - public boolean canGetFlag(int id) { + public boolean canTransform() { try { - assertCanGetFlag(id); + assertCanTransform(); return true; - } catch (GameActionException e) { return false; } + } catch (GameActionException e) { return false; } } @Override - public int getFlag(int id) throws GameActionException { - assertCanGetFlag(id); + public void transform() throws GameActionException { + assertCanTransform(); + this.robot.transform(); + if (this.robot.getMode() == RobotMode.TURRET) + this.robot.addActionCooldownTurns(GameConstants.TRANSFORM_COOLDOWN); + else + this.robot.addMovementCooldownTurns(GameConstants.TRANSFORM_COOLDOWN); + this.gameWorld.getMatchMaker().addAction(getID(), Action.TRANSFORM, -1); + } + + // *********************************** + // ****** COMMUNICATION METHODS ****** + // *********************************** + + private void assertValidIndex(int index) throws GameActionException { + if (index < 0 || index >= GameConstants.SHARED_ARRAY_LENGTH) + throw new GameActionException(CANT_DO_THAT, "You can't access this index as it is not within the shared array."); + } - return getRobotByID(id).getFlag(); - } + private void assertValidValue(int value) throws GameActionException { + if (value < 0 || value > GameConstants.MAX_SHARED_ARRAY_VALUE) + throw new GameActionException(CANT_DO_THAT, "You can't write this value to the shared array " + + "as it is not within the range of allowable values: [0, " + GameConstants.MAX_SHARED_ARRAY_VALUE + "]."); + } + + @Override + public int readSharedArray(int index) throws GameActionException { + assertValidIndex(index); + return this.gameWorld.getTeamInfo().readSharedArray(getTeam(), index); + } + + @Override + public void writeSharedArray(int index, int value) throws GameActionException { + assertValidIndex(index); + assertValidValue(value); + this.gameWorld.getTeamInfo().writeSharedArray(getTeam(), index, value); + } // *********************************** // ****** OTHER ACTION METHODS ******* // *********************************** - /** - * This used to be public, but is not public in 2021 because - * slanderers should not be able to self-destruct. - */ - private void disintegrate() { + @Override + public AnomalyScheduleEntry[] getAnomalySchedule() { + return this.gameWorld.getAnomalySchedule(); + } + + @Override + public void disintegrate() { throw new RobotDeathException(); } @Override public void resign() { + Team team = getTeam(); gameWorld.getObjectInfo().eachRobot((robot) -> { - if (robot.getTeam() == getTeam()) { + if (robot.getTeam() == team) { gameWorld.destroyRobot(robot.getID()); } return true; @@ -654,17 +912,24 @@ public void resign() { // ******** DEBUG METHODS ************ // *********************************** + @Override + public void setIndicatorString(String string) { + if (string.length() > GameConstants.INDICATOR_STRING_MAX_LENGTH) { + string = string.substring(0, GameConstants.INDICATOR_STRING_MAX_LENGTH); + } + this.robot.setIndicatorString(string); + } + @Override public void setIndicatorDot(MapLocation loc, int red, int green, int blue) { assertNotNull(loc); - gameWorld.getMatchMaker().addIndicatorDot(getID(), loc, red, green, blue); + this.gameWorld.getMatchMaker().addIndicatorDot(getID(), loc, red, green, blue); } @Override public void setIndicatorLine(MapLocation startLoc, MapLocation endLoc, int red, int green, int blue) { assertNotNull(startLoc); assertNotNull(endLoc); - gameWorld.getMatchMaker().addIndicatorLine(getID(), startLoc, endLoc, red, green, blue); + this.gameWorld.getMatchMaker().addIndicatorLine(getID(), startLoc, endLoc, red, green, blue); } - } diff --git a/engine/src/main/battlecode/world/TeamInfo.java b/engine/src/main/battlecode/world/TeamInfo.java index 045536a9..781b0065 100644 --- a/engine/src/main/battlecode/world/TeamInfo.java +++ b/engine/src/main/battlecode/world/TeamInfo.java @@ -3,97 +3,127 @@ import battlecode.common.GameConstants; import battlecode.common.Team; import java.util.*; +import static battlecode.common.GameActionExceptionType.*; /** * This class is used to hold information regarding team specific values such as - * team names, and victory points. + * team names. */ public class TeamInfo { private GameWorld gameWorld; - private int[] teamVotes; - private int[] numBuffs; - private Map> buffExpirations; // team -> round number, number of buffs expiring at the beginning of that round + private int[] leadCounts; + private int[] goldCounts; + private int[][] sharedArrays; + // for reporting round statistics to client + private int[] oldLeadCounts; + private int[] oldGoldCounts; + + /** + * Create a new representation of TeamInfo + * + * @param gameWorld the gameWorld the teams exist in + */ public TeamInfo(GameWorld gameWorld) { this.gameWorld = gameWorld; - this.teamVotes = new int[2]; - this.numBuffs = new int[2]; - this.buffExpirations = new HashMap<>(); - for (int i = 0; i < 2; i++) - this.buffExpirations.put(i, new TreeMap<>()); + this.leadCounts = new int[2]; + this.goldCounts = new int[2]; + this.sharedArrays = new int[2][GameConstants.SHARED_ARRAY_LENGTH]; + this.oldLeadCounts = new int[2]; + this.oldGoldCounts = new int[2]; } - + // ********************************* // ***** GETTER METHODS ************ // ********************************* - // Breaks if t.ordinal() > 1 (Team NEUTRAL) - public int getVotes(Team t) { - return this.teamVotes[t.ordinal()]; - } - - // returns current buff - public double getBuff(Team t) { - return 1 + GameConstants.EXPOSE_BUFF_FACTOR * this.numBuffs[t.ordinal()]; + /** + * Get the amount of lead. + * + * @param team the team to query + * @return the team's lead count + */ + public int getLead(Team team) { + return this.leadCounts[team.ordinal()]; } - // returns the buff at specified round - public double getBuff(Team t, int roundNumber) { - int buffs = getNumBuffs(t, roundNumber); - return 1 + GameConstants.EXPOSE_BUFF_FACTOR * buffs; + /** + * Get the amount of gold. + * + * @param team the team to query + * @return the team's gold count + */ + public int getGold(Team team) { + return this.goldCounts[team.ordinal()]; } - // returns the number of buffs at specified round - public int getNumBuffs(Team t, int roundNumber) { - int teamIdx = t.ordinal(); - int buffs = numBuffs[teamIdx]; - TreeMap map = this.buffExpirations.get(teamIdx); - for (int round : map.keySet()) { - if (round <= roundNumber) { - buffs -= map.get(round); - } else { - break; // treemaps are in increasing order - } - } - return buffs; + /** + * Reads the shared array value. + * + * @param team the team to query + * @param index the index in the array + * @return the value at that index in the team's shared array + */ + public int readSharedArray(Team team, int index) { + return this.sharedArrays[team.ordinal()][index]; } // ********************************* // ***** UPDATE METHODS ************ // ********************************* - public void addVote(Team t) { - teamVotes[t.ordinal()]++; + /** + * Add to the amount of lead. If amount is negative, subtract from lead instead. + * + * @param team the team to query + * @param amount the change in the lead count + * @throws IllegalArgumentException if the resulting amount of lead is negative + */ + public void addLead(Team team, int amount) throws IllegalArgumentException { + if (this.leadCounts[team.ordinal()] + amount < 0) { + throw new IllegalArgumentException("Invalid lead change"); + } + this.leadCounts[team.ordinal()] += amount; + } + + /** + * Add to the amount of gold. If amount is negative, subtract from gold instead. + * + * @param team the team to query + * @param amount the change in the gold count + * @throws IllegalArgumentException if the resulting amount of gold is negative + */ + public void addGold(Team team, int amount) throws IllegalArgumentException { + if (this.goldCounts[team.ordinal()] + amount < 0) { + throw new IllegalArgumentException("Invalid gold change"); + } + this.goldCounts[team.ordinal()] += amount; + } + + /** + * Sets an index in the team's shared array to a given value. + * + * @param team the team to query + * @param index the index in the shared array + * @param value the new value + */ + public void writeSharedArray(Team team, int index, int value) { + this.sharedArrays[team.ordinal()][index] = value; } - // called at the end of every round - public void addBuffs(int nextRound, Team t, int buffs) { - int teamIdx = t.ordinal(); - this.numBuffs[teamIdx] += buffs; - TreeMap map = this.buffExpirations.get(teamIdx); - int expirationRound = nextRound + GameConstants.EXPOSE_BUFF_NUM_ROUNDS; - map.put(expirationRound, map.getOrDefault(expirationRound, 0) + buffs); + public int getRoundLeadChange(Team team) { + return this.leadCounts[team.ordinal()] - this.oldLeadCounts[team.ordinal()]; } - // called at the beginning of every round - public void updateNumBuffs(int currentRound) { - updateNumBuffs(currentRound, Team.A); - updateNumBuffs(currentRound, Team.B); + public int getRoundGoldChange(Team team) { + return this.goldCounts[team.ordinal()] - this.oldGoldCounts[team.ordinal()]; } - private void updateNumBuffs(int currentRound, Team t) { - int teamIdx = t.ordinal(); - TreeMap map = this.buffExpirations.get(teamIdx); - Iterator> it = map.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry item = it.next(); - if (item.getKey() <= currentRound) { - this.numBuffs[teamIdx] -= item.getValue(); - it.remove(); - } else { - break; // treemaps are in increasing order - } - } + public void processEndOfRound() { + this.oldLeadCounts[0] = this.leadCounts[0]; + this.oldLeadCounts[1] = this.leadCounts[1]; + this.oldGoldCounts[0] = this.goldCounts[0]; + this.oldGoldCounts[1] = this.goldCounts[1]; } } diff --git a/engine/src/main/battlecode/world/TestMapBuilder.java b/engine/src/main/battlecode/world/TestMapBuilder.java index 15485aba..4cf495fb 100644 --- a/engine/src/main/battlecode/world/TestMapBuilder.java +++ b/engine/src/main/battlecode/world/TestMapBuilder.java @@ -8,58 +8,33 @@ * Lets maps be built easily, for testing purposes. */ public class TestMapBuilder { - private String name; - private MapLocation origin; - private int width; - private int height; - private int seed; - private int rounds; - private double[] passabilityArray; + private MapBuilder mapBuilder; - private List bodies; - - public TestMapBuilder(String name, int oX, int oY, int width, int height, int seed, int rounds) { - this(name, new MapLocation(oX, oY), width, height, seed, rounds); - } - - public TestMapBuilder(String name, MapLocation origin, int width, int height, int seed, int rounds) { - this.name = name; - this.origin = origin; - this.width = width; - this.height = height; - this.seed = seed; - this.bodies = new ArrayList<>(); + public TestMapBuilder(String name, int oX, int oY, int width, int height, int seed) { + this.mapBuilder = new MapBuilder(name, width, height, oX, oY, seed); } - public TestMapBuilder addEnlightenmentCenter(int id, Team team, int influence, MapLocation loc) { - bodies.add(new RobotInfo( - id, - team, - RobotType.ENLIGHTENMENT_CENTER, - influence, - 0, - loc - )); - + public TestMapBuilder addArchon(int id, Team team, MapLocation loc) { + this.mapBuilder.addArchon(id, team, loc); return this; } - public TestMapBuilder setPassability() { - this.passabilityArray = new double[width * height]; - for(int i = 0; i < width; i++) { - for (int j = 0; j < height; j++) { - this.passabilityArray[i + j * width] = (i * j + i + j) / (i * j + 1); - } - } + public TestMapBuilder setRubble(int x, int y, int value) { + this.mapBuilder.setRubble(x, y, value); + return this; + } + + public TestMapBuilder setLead(int x, int y, int value) { + this.mapBuilder.setLead(x, y, value); return this; } - public TestMapBuilder addBody(RobotInfo info) { - bodies.add(info); + public TestMapBuilder addAnomalyScheduleEntry(int round, AnomalyType anomaly) { + this.mapBuilder.addAnomalyScheduleEntry(round, anomaly); return this; } public LiveMap build() { - return new LiveMap(width, height, origin, seed, GameConstants.GAME_MAX_NUMBER_OF_ROUNDS, name, bodies.toArray(new RobotInfo[bodies.size()]), passabilityArray); + return this.mapBuilder.build(); } } diff --git a/engine/src/main/battlecode/world/maps/Circle.java b/engine/src/main/battlecode/world/maps/Circle.java deleted file mode 100644 index 272f51eb..00000000 --- a/engine/src/main/battlecode/world/maps/Circle.java +++ /dev/null @@ -1,59 +0,0 @@ -package battlecode.world.maps; - -import battlecode.common.MapLocation; -import battlecode.common.RobotType; -import battlecode.common.Team; -import battlecode.world.GameMapIO; -import battlecode.world.LiveMap; -import battlecode.world.MapBuilder; -import battlecode.world.TestMapBuilder; - -import battlecode.common.GameConstants; - -import java.io.File; -import java.io.IOException; -import java.util.Random; - -/** - * Generate a map. - */ -public class Circle { - - // change this!!! - public static final String mapName = "circle"; - - // don't change this!! - public static final String outputDirectory = "engine/src/main/battlecode/world/resources/"; - - /** - * @param args unused - */ - public static void main(String[] args) { - try { - makeCircle(); - } catch (IOException e) { - System.out.println(e); - } - System.out.println("Generated a map!"); - } - - public static void makeCircle() throws IOException { - final int half = 31; - final MapLocation center = new MapLocation(half, half); - MapBuilder mapBuilder = new MapBuilder(mapName, 2*half+1, 2*half+1, 25016, 12865, 116896); - mapBuilder.addSymmetricEnlightenmentCenter(20, 20); - mapBuilder.addSymmetricEnlightenmentCenter(20, 2*half-20); - mapBuilder.addSymmetricNeutralEnlightenmentCenter(0, 0, 300); - mapBuilder.addSymmetricNeutralEnlightenmentCenter(0, 2*half, 300); - - for(int i = 0; i <= half; i++) { - for (int j = 0; j <= 2*half; j++) { - int d = new MapLocation(i, j).distanceSquaredTo(center); - mapBuilder.setSymmetricPassability(i, j, - 1.0 - 0.5 * Math.exp(-0.0002 * (d - 500) * (d - 500))); - } - } - - mapBuilder.saveMap(outputDirectory); - } -} diff --git a/engine/src/main/battlecode/world/maps/MapTestSmall.java b/engine/src/main/battlecode/world/maps/MapTestSmall.java index 51aaf5c3..dedbf2ac 100644 --- a/engine/src/main/battlecode/world/maps/MapTestSmall.java +++ b/engine/src/main/battlecode/world/maps/MapTestSmall.java @@ -38,13 +38,13 @@ public static void main(String[] args) { } public static void makeSimple() throws IOException { - MapBuilder mapBuilder = new MapBuilder(mapName, 32, 32, 10000, 23921, 30); - mapBuilder.addSymmetricEnlightenmentCenter(5, 5); + MapBuilder mapBuilder = new MapBuilder(mapName, 32, 32, 0, 0, 30); + mapBuilder.addSymmetricArchon(5, 5); Random random = new Random(6147); - for(int i = 0; i < mapBuilder.width / 2; i++) { + for (int i = 0; i < mapBuilder.width / 2; i++) { for (int j = 0; j < mapBuilder.height; j++) { - mapBuilder.setSymmetricPassability(i, j, random.nextDouble()*0.9+0.1); + mapBuilder.setSymmetricLead(i, j, random.nextInt(100)); } } diff --git a/engine/src/main/battlecode/world/maps/Quadrants.java b/engine/src/main/battlecode/world/maps/Quadrants.java deleted file mode 100644 index a041ee0c..00000000 --- a/engine/src/main/battlecode/world/maps/Quadrants.java +++ /dev/null @@ -1,56 +0,0 @@ -package battlecode.world.maps; - -import battlecode.common.MapLocation; -import battlecode.common.RobotType; -import battlecode.common.Team; -import battlecode.world.GameMapIO; -import battlecode.world.LiveMap; -import battlecode.world.MapBuilder; -import battlecode.world.TestMapBuilder; - -import battlecode.common.GameConstants; - -import java.io.File; -import java.io.IOException; -import java.util.Random; - -/** - * Generate a map. - */ -public class Quadrants { - - // change this!!! - public static final String mapName = "quadrants"; - - // don't change this!! - public static final String outputDirectory = "engine/src/main/battlecode/world/resources/"; - - /** - * @param args unused - */ - public static void main(String[] args) { - try { - makeQuadrants(); - } catch (IOException e) { - System.out.println(e); - } - System.out.println("Generated a map!"); - } - - public static void makeQuadrants() throws IOException { - MapBuilder mapBuilder = new MapBuilder(mapName, 40, 40, 13265, 17387, 215957); - mapBuilder.setSymmetry(MapBuilder.MapSymmetry.rotational); - mapBuilder.addSymmetricEnlightenmentCenter(5, 5); - mapBuilder.addSymmetricEnlightenmentCenter(10, 30); - mapBuilder.addSymmetricNeutralEnlightenmentCenter(18, 19, 500); - - for (int i = 5; i <= 15; i++) { - mapBuilder.setSymmetricPassability(i, 15, 0.1); - mapBuilder.setSymmetricPassability(i, 25, 0.1); - mapBuilder.setSymmetricPassability(15, i, 0.1); - mapBuilder.setSymmetricPassability(25, i, 0.1); - } - - mapBuilder.saveMap(outputDirectory); - } -} diff --git a/engine/src/main/battlecode/world/resources/AmidstWe.map21 b/engine/src/main/battlecode/world/resources/AmidstWe.map21 deleted file mode 100644 index 39397b34..00000000 Binary files a/engine/src/main/battlecode/world/resources/AmidstWe.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Andromeda.map21 b/engine/src/main/battlecode/world/resources/Andromeda.map21 deleted file mode 100644 index f0d8d313..00000000 Binary files a/engine/src/main/battlecode/world/resources/Andromeda.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Arena.map21 b/engine/src/main/battlecode/world/resources/Arena.map21 deleted file mode 100644 index 1d5d2309..00000000 Binary files a/engine/src/main/battlecode/world/resources/Arena.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/BadSnowflake.map21 b/engine/src/main/battlecode/world/resources/BadSnowflake.map21 deleted file mode 100644 index 60e9b68c..00000000 Binary files a/engine/src/main/battlecode/world/resources/BadSnowflake.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/BattleCode.map21 b/engine/src/main/battlecode/world/resources/BattleCode.map21 deleted file mode 100644 index 3fb82d09..00000000 Binary files a/engine/src/main/battlecode/world/resources/BattleCode.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/BattleCodeToo.map21 b/engine/src/main/battlecode/world/resources/BattleCodeToo.map21 deleted file mode 100644 index 919a5324..00000000 Binary files a/engine/src/main/battlecode/world/resources/BattleCodeToo.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/BlobWithLegs.map21 b/engine/src/main/battlecode/world/resources/BlobWithLegs.map21 deleted file mode 100644 index 961cc076..00000000 Binary files a/engine/src/main/battlecode/world/resources/BlobWithLegs.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Blotches.map21 b/engine/src/main/battlecode/world/resources/Blotches.map21 deleted file mode 100644 index 5e1f052f..00000000 Binary files a/engine/src/main/battlecode/world/resources/Blotches.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Bog.map21 b/engine/src/main/battlecode/world/resources/Bog.map21 deleted file mode 100644 index 58961058..00000000 Binary files a/engine/src/main/battlecode/world/resources/Bog.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Branches.map21 b/engine/src/main/battlecode/world/resources/Branches.map21 deleted file mode 100644 index d96140e7..00000000 Binary files a/engine/src/main/battlecode/world/resources/Branches.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/ButtonsAndBows.map21 b/engine/src/main/battlecode/world/resources/ButtonsAndBows.map21 deleted file mode 100644 index 46d00d56..00000000 Binary files a/engine/src/main/battlecode/world/resources/ButtonsAndBows.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/CToE.map21 b/engine/src/main/battlecode/world/resources/CToE.map21 deleted file mode 100644 index 93ad6959..00000000 Binary files a/engine/src/main/battlecode/world/resources/CToE.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Chevron.map21 b/engine/src/main/battlecode/world/resources/Chevron.map21 deleted file mode 100644 index 4bddf3bb..00000000 Binary files a/engine/src/main/battlecode/world/resources/Chevron.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Circles.map21 b/engine/src/main/battlecode/world/resources/Circles.map21 deleted file mode 100644 index 75c416f2..00000000 Binary files a/engine/src/main/battlecode/world/resources/Circles.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Corridor.map21 b/engine/src/main/battlecode/world/resources/Corridor.map21 deleted file mode 100644 index a0826128..00000000 Binary files a/engine/src/main/battlecode/world/resources/Corridor.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Cow.map21 b/engine/src/main/battlecode/world/resources/Cow.map21 deleted file mode 100644 index 5c293d82..00000000 Binary files a/engine/src/main/battlecode/world/resources/Cow.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/CowTwister.map21 b/engine/src/main/battlecode/world/resources/CowTwister.map21 deleted file mode 100644 index 71bd2d5a..00000000 Binary files a/engine/src/main/battlecode/world/resources/CowTwister.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/CringyAsF.map21 b/engine/src/main/battlecode/world/resources/CringyAsF.map21 deleted file mode 100644 index d29fa78b..00000000 Binary files a/engine/src/main/battlecode/world/resources/CringyAsF.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/CrossStitch.map21 b/engine/src/main/battlecode/world/resources/CrossStitch.map21 deleted file mode 100644 index 70ee7e04..00000000 Binary files a/engine/src/main/battlecode/world/resources/CrossStitch.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/CrownJewels.map21 b/engine/src/main/battlecode/world/resources/CrownJewels.map21 deleted file mode 100644 index b521c9f8..00000000 Binary files a/engine/src/main/battlecode/world/resources/CrownJewels.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/EggCarton.map21 b/engine/src/main/battlecode/world/resources/EggCarton.map21 deleted file mode 100644 index ff30301b..00000000 Binary files a/engine/src/main/battlecode/world/resources/EggCarton.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/ExesAndOhs.map21 b/engine/src/main/battlecode/world/resources/ExesAndOhs.map21 deleted file mode 100644 index 5c356f60..00000000 Binary files a/engine/src/main/battlecode/world/resources/ExesAndOhs.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Extensions.map21 b/engine/src/main/battlecode/world/resources/Extensions.map21 deleted file mode 100644 index d303b7cf..00000000 Binary files a/engine/src/main/battlecode/world/resources/Extensions.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/FindYourWay.map21 b/engine/src/main/battlecode/world/resources/FindYourWay.map21 deleted file mode 100644 index 5f57d0b6..00000000 Binary files a/engine/src/main/battlecode/world/resources/FindYourWay.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/FiveOfHearts.map21 b/engine/src/main/battlecode/world/resources/FiveOfHearts.map21 deleted file mode 100644 index f8dd9b8c..00000000 Binary files a/engine/src/main/battlecode/world/resources/FiveOfHearts.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Flawars.map21 b/engine/src/main/battlecode/world/resources/Flawars.map21 deleted file mode 100644 index b3363dc4..00000000 Binary files a/engine/src/main/battlecode/world/resources/Flawars.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/FrogOrBath.map21 b/engine/src/main/battlecode/world/resources/FrogOrBath.map21 deleted file mode 100644 index 83d70e55..00000000 Binary files a/engine/src/main/battlecode/world/resources/FrogOrBath.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/GetShrekt.map21 b/engine/src/main/battlecode/world/resources/GetShrekt.map21 deleted file mode 100644 index f6677ff2..00000000 Binary files a/engine/src/main/battlecode/world/resources/GetShrekt.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Goldfish.map21 b/engine/src/main/battlecode/world/resources/Goldfish.map21 deleted file mode 100644 index 116a291d..00000000 Binary files a/engine/src/main/battlecode/world/resources/Goldfish.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Gridlock.map21 b/engine/src/main/battlecode/world/resources/Gridlock.map21 deleted file mode 100644 index bb518928..00000000 Binary files a/engine/src/main/battlecode/world/resources/Gridlock.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/HappyBoba.map21 b/engine/src/main/battlecode/world/resources/HappyBoba.map21 deleted file mode 100644 index 9ebb2dd4..00000000 Binary files a/engine/src/main/battlecode/world/resources/HappyBoba.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/HexesAndOhms.map21 b/engine/src/main/battlecode/world/resources/HexesAndOhms.map21 deleted file mode 100644 index 6616991f..00000000 Binary files a/engine/src/main/battlecode/world/resources/HexesAndOhms.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Hourglass.map21 b/engine/src/main/battlecode/world/resources/Hourglass.map21 deleted file mode 100644 index ec2d0cf8..00000000 Binary files a/engine/src/main/battlecode/world/resources/Hourglass.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Illusion.map21 b/engine/src/main/battlecode/world/resources/Illusion.map21 deleted file mode 100644 index 51344ee0..00000000 Binary files a/engine/src/main/battlecode/world/resources/Illusion.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/InaccurateBritishFlag.map21 b/engine/src/main/battlecode/world/resources/InaccurateBritishFlag.map21 deleted file mode 100644 index 5471ebac..00000000 Binary files a/engine/src/main/battlecode/world/resources/InaccurateBritishFlag.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/JerryIsEvil.map21 b/engine/src/main/battlecode/world/resources/JerryIsEvil.map21 deleted file mode 100644 index 6c51af46..00000000 Binary files a/engine/src/main/battlecode/world/resources/JerryIsEvil.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Legends.map21 b/engine/src/main/battlecode/world/resources/Legends.map21 deleted file mode 100644 index d83ae96b..00000000 Binary files a/engine/src/main/battlecode/world/resources/Legends.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Licc.map21 b/engine/src/main/battlecode/world/resources/Licc.map21 deleted file mode 100644 index 9c4e687b..00000000 Binary files a/engine/src/main/battlecode/world/resources/Licc.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/MainCampus.map21 b/engine/src/main/battlecode/world/resources/MainCampus.map21 deleted file mode 100644 index 83cc6917..00000000 Binary files a/engine/src/main/battlecode/world/resources/MainCampus.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Mario.map21 b/engine/src/main/battlecode/world/resources/Mario.map21 deleted file mode 100644 index ed70fbfb..00000000 Binary files a/engine/src/main/battlecode/world/resources/Mario.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Maze.map21 b/engine/src/main/battlecode/world/resources/Maze.map21 deleted file mode 100644 index 98abcdfa..00000000 Binary files a/engine/src/main/battlecode/world/resources/Maze.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Misdirection.map21 b/engine/src/main/battlecode/world/resources/Misdirection.map21 deleted file mode 100644 index a42e9982..00000000 Binary files a/engine/src/main/battlecode/world/resources/Misdirection.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Networking.map21 b/engine/src/main/battlecode/world/resources/Networking.map21 deleted file mode 100644 index 56b6b022..00000000 Binary files a/engine/src/main/battlecode/world/resources/Networking.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/NextHouse.map21 b/engine/src/main/battlecode/world/resources/NextHouse.map21 deleted file mode 100644 index 8ba4153b..00000000 Binary files a/engine/src/main/battlecode/world/resources/NextHouse.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/NoInternet.map21 b/engine/src/main/battlecode/world/resources/NoInternet.map21 deleted file mode 100644 index 8ac6d8dc..00000000 Binary files a/engine/src/main/battlecode/world/resources/NoInternet.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/NotAPuzzle.map21 b/engine/src/main/battlecode/world/resources/NotAPuzzle.map21 deleted file mode 100644 index a169143d..00000000 Binary files a/engine/src/main/battlecode/world/resources/NotAPuzzle.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/OneCallAway.map21 b/engine/src/main/battlecode/world/resources/OneCallAway.map21 deleted file mode 100644 index 3af0bf05..00000000 Binary files a/engine/src/main/battlecode/world/resources/OneCallAway.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/PaperWindmill.map21 b/engine/src/main/battlecode/world/resources/PaperWindmill.map21 deleted file mode 100644 index 2893370c..00000000 Binary files a/engine/src/main/battlecode/world/resources/PaperWindmill.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Punctuation.map21 b/engine/src/main/battlecode/world/resources/Punctuation.map21 deleted file mode 100644 index 8c88dcc0..00000000 Binary files a/engine/src/main/battlecode/world/resources/Punctuation.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Radial.map21 b/engine/src/main/battlecode/world/resources/Radial.map21 deleted file mode 100644 index 277f066d..00000000 Binary files a/engine/src/main/battlecode/world/resources/Radial.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Rainbow.map21 b/engine/src/main/battlecode/world/resources/Rainbow.map21 deleted file mode 100644 index adcd26fd..00000000 Binary files a/engine/src/main/battlecode/world/resources/Rainbow.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Randomized.map21 b/engine/src/main/battlecode/world/resources/Randomized.map21 deleted file mode 100644 index 85fff6ea..00000000 Binary files a/engine/src/main/battlecode/world/resources/Randomized.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Saturn.map21 b/engine/src/main/battlecode/world/resources/Saturn.map21 deleted file mode 100644 index b7e2a4b2..00000000 Binary files a/engine/src/main/battlecode/world/resources/Saturn.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/SeaFloor.map21 b/engine/src/main/battlecode/world/resources/SeaFloor.map21 deleted file mode 100644 index 520c6f40..00000000 Binary files a/engine/src/main/battlecode/world/resources/SeaFloor.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Sediment.map21 b/engine/src/main/battlecode/world/resources/Sediment.map21 deleted file mode 100644 index 8dbef3a6..00000000 Binary files a/engine/src/main/battlecode/world/resources/Sediment.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/SlowMusic.map21 b/engine/src/main/battlecode/world/resources/SlowMusic.map21 deleted file mode 100644 index 59c1e693..00000000 Binary files a/engine/src/main/battlecode/world/resources/SlowMusic.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Smile.map21 b/engine/src/main/battlecode/world/resources/Smile.map21 deleted file mode 100644 index 9edc9464..00000000 Binary files a/engine/src/main/battlecode/world/resources/Smile.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Snowflake.map21 b/engine/src/main/battlecode/world/resources/Snowflake.map21 deleted file mode 100644 index c17a14a9..00000000 Binary files a/engine/src/main/battlecode/world/resources/Snowflake.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/SpaceInvaders.map21 b/engine/src/main/battlecode/world/resources/SpaceInvaders.map21 deleted file mode 100644 index 55fe333e..00000000 Binary files a/engine/src/main/battlecode/world/resources/SpaceInvaders.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Star.map21 b/engine/src/main/battlecode/world/resources/Star.map21 deleted file mode 100644 index 6a5bdb15..00000000 Binary files a/engine/src/main/battlecode/world/resources/Star.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Stonks.map21 b/engine/src/main/battlecode/world/resources/Stonks.map21 deleted file mode 100644 index 57a895b7..00000000 Binary files a/engine/src/main/battlecode/world/resources/Stonks.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Superposition.map21 b/engine/src/main/battlecode/world/resources/Superposition.map21 deleted file mode 100644 index 27db7d44..00000000 Binary files a/engine/src/main/battlecode/world/resources/Superposition.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Surprised.map21 b/engine/src/main/battlecode/world/resources/Surprised.map21 deleted file mode 100644 index 53afb5d5..00000000 Binary files a/engine/src/main/battlecode/world/resources/Surprised.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/TheClientMapEditorIsSuperiorToGoogleSheetsEom.map21 b/engine/src/main/battlecode/world/resources/TheClientMapEditorIsSuperiorToGoogleSheetsEom.map21 deleted file mode 100644 index 0edd00a2..00000000 Binary files a/engine/src/main/battlecode/world/resources/TheClientMapEditorIsSuperiorToGoogleSheetsEom.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/TheSnackThatSmilesBack.map21 b/engine/src/main/battlecode/world/resources/TheSnackThatSmilesBack.map21 deleted file mode 100644 index 871eeae4..00000000 Binary files a/engine/src/main/battlecode/world/resources/TheSnackThatSmilesBack.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/TicTacTie.map21 b/engine/src/main/battlecode/world/resources/TicTacTie.map21 deleted file mode 100644 index 73c51f30..00000000 Binary files a/engine/src/main/battlecode/world/resources/TicTacTie.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Tiger.map21 b/engine/src/main/battlecode/world/resources/Tiger.map21 deleted file mode 100644 index 940fe8dd..00000000 Binary files a/engine/src/main/battlecode/world/resources/Tiger.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/UnbrandedWordGame.map21 b/engine/src/main/battlecode/world/resources/UnbrandedWordGame.map21 deleted file mode 100644 index 2cee0cc6..00000000 Binary files a/engine/src/main/battlecode/world/resources/UnbrandedWordGame.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/VideoGames.map21 b/engine/src/main/battlecode/world/resources/VideoGames.map21 deleted file mode 100644 index dc687338..00000000 Binary files a/engine/src/main/battlecode/world/resources/VideoGames.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/WhatISeeInMyDreams.map21 b/engine/src/main/battlecode/world/resources/WhatISeeInMyDreams.map21 deleted file mode 100644 index d4ebb3a3..00000000 Binary files a/engine/src/main/battlecode/world/resources/WhatISeeInMyDreams.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Yoda.map21 b/engine/src/main/battlecode/world/resources/Yoda.map21 deleted file mode 100644 index a095fd59..00000000 Binary files a/engine/src/main/battlecode/world/resources/Yoda.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Z.map21 b/engine/src/main/battlecode/world/resources/Z.map21 deleted file mode 100644 index a50ad91c..00000000 Binary files a/engine/src/main/battlecode/world/resources/Z.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/Zodiac.map21 b/engine/src/main/battlecode/world/resources/Zodiac.map21 deleted file mode 100644 index 791db140..00000000 Binary files a/engine/src/main/battlecode/world/resources/Zodiac.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/captain_america.map22 b/engine/src/main/battlecode/world/resources/captain_america.map22 new file mode 100644 index 00000000..e47ad465 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/captain_america.map22 differ diff --git a/engine/src/main/battlecode/world/resources/chalice.map22 b/engine/src/main/battlecode/world/resources/chalice.map22 new file mode 100644 index 00000000..1268be7c Binary files /dev/null and b/engine/src/main/battlecode/world/resources/chalice.map22 differ diff --git a/engine/src/main/battlecode/world/resources/charge.map22 b/engine/src/main/battlecode/world/resources/charge.map22 new file mode 100644 index 00000000..e4cc9cb3 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/charge.map22 differ diff --git a/engine/src/main/battlecode/world/resources/chessboard.map22 b/engine/src/main/battlecode/world/resources/chessboard.map22 new file mode 100644 index 00000000..c31a04a0 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/chessboard.map22 differ diff --git a/engine/src/main/battlecode/world/resources/circle.map21 b/engine/src/main/battlecode/world/resources/circle.map21 deleted file mode 100644 index 0840c4e9..00000000 Binary files a/engine/src/main/battlecode/world/resources/circle.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/cobra.map22 b/engine/src/main/battlecode/world/resources/cobra.map22 new file mode 100644 index 00000000..cad98524 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/cobra.map22 differ diff --git a/engine/src/main/battlecode/world/resources/collaboration.map22 b/engine/src/main/battlecode/world/resources/collaboration.map22 new file mode 100644 index 00000000..f80d430d Binary files /dev/null and b/engine/src/main/battlecode/world/resources/collaboration.map22 differ diff --git a/engine/src/main/battlecode/world/resources/colosseum.map22 b/engine/src/main/battlecode/world/resources/colosseum.map22 new file mode 100644 index 00000000..02a193a0 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/colosseum.map22 differ diff --git a/engine/src/main/battlecode/world/resources/deer.map22 b/engine/src/main/battlecode/world/resources/deer.map22 new file mode 100644 index 00000000..4a5cdc0e Binary files /dev/null and b/engine/src/main/battlecode/world/resources/deer.map22 differ diff --git a/engine/src/main/battlecode/world/resources/defenseless.map22 b/engine/src/main/battlecode/world/resources/defenseless.map22 new file mode 100644 index 00000000..58656843 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/defenseless.map22 differ diff --git a/engine/src/main/battlecode/world/resources/definitely_not_league.map22 b/engine/src/main/battlecode/world/resources/definitely_not_league.map22 new file mode 100644 index 00000000..d3eef637 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/definitely_not_league.map22 differ diff --git a/engine/src/main/battlecode/world/resources/desert.map22 b/engine/src/main/battlecode/world/resources/desert.map22 new file mode 100644 index 00000000..9b7369f6 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/desert.map22 differ diff --git a/engine/src/main/battlecode/world/resources/despair.map22 b/engine/src/main/battlecode/world/resources/despair.map22 new file mode 100644 index 00000000..fb44f96d Binary files /dev/null and b/engine/src/main/battlecode/world/resources/despair.map22 differ diff --git a/engine/src/main/battlecode/world/resources/diamond.map22 b/engine/src/main/battlecode/world/resources/diamond.map22 new file mode 100644 index 00000000..2c0b745e Binary files /dev/null and b/engine/src/main/battlecode/world/resources/diamond.map22 differ diff --git a/engine/src/main/battlecode/world/resources/dodgeball.map22 b/engine/src/main/battlecode/world/resources/dodgeball.map22 new file mode 100644 index 00000000..4b0158e0 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/dodgeball.map22 differ diff --git a/engine/src/main/battlecode/world/resources/eckleburg.map22 b/engine/src/main/battlecode/world/resources/eckleburg.map22 new file mode 100644 index 00000000..cdf67a3f Binary files /dev/null and b/engine/src/main/battlecode/world/resources/eckleburg.map22 differ diff --git a/engine/src/main/battlecode/world/resources/equals.map22 b/engine/src/main/battlecode/world/resources/equals.map22 new file mode 100644 index 00000000..e9518387 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/equals.map22 differ diff --git a/engine/src/main/battlecode/world/resources/fire.map22 b/engine/src/main/battlecode/world/resources/fire.map22 new file mode 100644 index 00000000..f232af1c Binary files /dev/null and b/engine/src/main/battlecode/world/resources/fire.map22 differ diff --git a/engine/src/main/battlecode/world/resources/fisherman.map22 b/engine/src/main/battlecode/world/resources/fisherman.map22 new file mode 100644 index 00000000..788a5fb6 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/fisherman.map22 differ diff --git a/engine/src/main/battlecode/world/resources/flowers.map22 b/engine/src/main/battlecode/world/resources/flowers.map22 new file mode 100644 index 00000000..88d17760 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/flowers.map22 differ diff --git a/engine/src/main/battlecode/world/resources/fortress.map22 b/engine/src/main/battlecode/world/resources/fortress.map22 new file mode 100644 index 00000000..e7e60e34 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/fortress.map22 differ diff --git a/engine/src/main/battlecode/world/resources/galaxy.map22 b/engine/src/main/battlecode/world/resources/galaxy.map22 new file mode 100644 index 00000000..7fc2f555 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/galaxy.map22 differ diff --git a/engine/src/main/battlecode/world/resources/greed.map22 b/engine/src/main/battlecode/world/resources/greed.map22 new file mode 100644 index 00000000..e9f2a62b Binary files /dev/null and b/engine/src/main/battlecode/world/resources/greed.map22 differ diff --git a/engine/src/main/battlecode/world/resources/highway.map22 b/engine/src/main/battlecode/world/resources/highway.map22 new file mode 100644 index 00000000..40ade6de Binary files /dev/null and b/engine/src/main/battlecode/world/resources/highway.map22 differ diff --git a/engine/src/main/battlecode/world/resources/highway_redux.map22 b/engine/src/main/battlecode/world/resources/highway_redux.map22 new file mode 100644 index 00000000..884307f5 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/highway_redux.map22 differ diff --git a/engine/src/main/battlecode/world/resources/intersection.map22 b/engine/src/main/battlecode/world/resources/intersection.map22 new file mode 100644 index 00000000..4f046695 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/intersection.map22 differ diff --git a/engine/src/main/battlecode/world/resources/iron_man.map22 b/engine/src/main/battlecode/world/resources/iron_man.map22 new file mode 100644 index 00000000..b91a31ba Binary files /dev/null and b/engine/src/main/battlecode/world/resources/iron_man.map22 differ diff --git a/engine/src/main/battlecode/world/resources/island_hopping.map22 b/engine/src/main/battlecode/world/resources/island_hopping.map22 new file mode 100644 index 00000000..a2237c41 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/island_hopping.map22 differ diff --git a/engine/src/main/battlecode/world/resources/jellyfish.map22 b/engine/src/main/battlecode/world/resources/jellyfish.map22 new file mode 100644 index 00000000..01ae3639 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/jellyfish.map22 differ diff --git a/engine/src/main/battlecode/world/resources/leaf.map22 b/engine/src/main/battlecode/world/resources/leaf.map22 new file mode 100644 index 00000000..966bba79 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/leaf.map22 differ diff --git a/engine/src/main/battlecode/world/resources/legends.map22 b/engine/src/main/battlecode/world/resources/legends.map22 new file mode 100644 index 00000000..22663acd Binary files /dev/null and b/engine/src/main/battlecode/world/resources/legends.map22 differ diff --git a/engine/src/main/battlecode/world/resources/lotus.map22 b/engine/src/main/battlecode/world/resources/lotus.map22 new file mode 100644 index 00000000..76c771ac Binary files /dev/null and b/engine/src/main/battlecode/world/resources/lotus.map22 differ diff --git a/engine/src/main/battlecode/world/resources/maptestsmall.map21 b/engine/src/main/battlecode/world/resources/maptestsmall.map21 deleted file mode 100644 index 07daf1a0..00000000 Binary files a/engine/src/main/battlecode/world/resources/maptestsmall.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/maptestsmall.map22 b/engine/src/main/battlecode/world/resources/maptestsmall.map22 new file mode 100644 index 00000000..c5df3490 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/maptestsmall.map22 differ diff --git a/engine/src/main/battlecode/world/resources/maze.map22 b/engine/src/main/battlecode/world/resources/maze.map22 new file mode 100644 index 00000000..b756e043 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/maze.map22 differ diff --git a/engine/src/main/battlecode/world/resources/melon.map22 b/engine/src/main/battlecode/world/resources/melon.map22 new file mode 100644 index 00000000..0242ce81 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/melon.map22 differ diff --git a/engine/src/main/battlecode/world/resources/monument.map22 b/engine/src/main/battlecode/world/resources/monument.map22 new file mode 100644 index 00000000..acd81100 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/monument.map22 differ diff --git a/engine/src/main/battlecode/world/resources/morphing_maze.map22 b/engine/src/main/battlecode/world/resources/morphing_maze.map22 new file mode 100644 index 00000000..2cfee09d Binary files /dev/null and b/engine/src/main/battlecode/world/resources/morphing_maze.map22 differ diff --git a/engine/src/main/battlecode/world/resources/negative.map22 b/engine/src/main/battlecode/world/resources/negative.map22 new file mode 100644 index 00000000..88a70793 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/negative.map22 differ diff --git a/engine/src/main/battlecode/world/resources/nottestsmall.map22 b/engine/src/main/battlecode/world/resources/nottestsmall.map22 new file mode 100644 index 00000000..6acad62d Binary files /dev/null and b/engine/src/main/battlecode/world/resources/nottestsmall.map22 differ diff --git a/engine/src/main/battlecode/world/resources/nyancat.map22 b/engine/src/main/battlecode/world/resources/nyancat.map22 new file mode 100644 index 00000000..6600e7c2 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/nyancat.map22 differ diff --git a/engine/src/main/battlecode/world/resources/octopus_game.map22 b/engine/src/main/battlecode/world/resources/octopus_game.map22 new file mode 100644 index 00000000..7df78012 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/octopus_game.map22 differ diff --git a/engine/src/main/battlecode/world/resources/olympics.map22 b/engine/src/main/battlecode/world/resources/olympics.map22 new file mode 100644 index 00000000..7891856f Binary files /dev/null and b/engine/src/main/battlecode/world/resources/olympics.map22 differ diff --git a/engine/src/main/battlecode/world/resources/one_river.map22 b/engine/src/main/battlecode/world/resources/one_river.map22 new file mode 100644 index 00000000..7d57441b Binary files /dev/null and b/engine/src/main/battlecode/world/resources/one_river.map22 differ diff --git a/engine/src/main/battlecode/world/resources/panda.map22 b/engine/src/main/battlecode/world/resources/panda.map22 new file mode 100644 index 00000000..0a4c73f6 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/panda.map22 differ diff --git a/engine/src/main/battlecode/world/resources/petals.map22 b/engine/src/main/battlecode/world/resources/petals.map22 new file mode 100644 index 00000000..212a5d30 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/petals.map22 differ diff --git a/engine/src/main/battlecode/world/resources/pillars.map22 b/engine/src/main/battlecode/world/resources/pillars.map22 new file mode 100644 index 00000000..bb202f32 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/pillars.map22 differ diff --git a/engine/src/main/battlecode/world/resources/planets.map22 b/engine/src/main/battlecode/world/resources/planets.map22 new file mode 100644 index 00000000..bc2acdfb Binary files /dev/null and b/engine/src/main/battlecode/world/resources/planets.map22 differ diff --git a/engine/src/main/battlecode/world/resources/progress.map22 b/engine/src/main/battlecode/world/resources/progress.map22 new file mode 100644 index 00000000..8b6401e6 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/progress.map22 differ diff --git a/engine/src/main/battlecode/world/resources/pyramid_raiders.map22 b/engine/src/main/battlecode/world/resources/pyramid_raiders.map22 new file mode 100644 index 00000000..8d95ce8e Binary files /dev/null and b/engine/src/main/battlecode/world/resources/pyramid_raiders.map22 differ diff --git a/engine/src/main/battlecode/world/resources/quadrants.map21 b/engine/src/main/battlecode/world/resources/quadrants.map21 deleted file mode 100644 index 7f0c5c99..00000000 Binary files a/engine/src/main/battlecode/world/resources/quadrants.map21 and /dev/null differ diff --git a/engine/src/main/battlecode/world/resources/raindrop.map22 b/engine/src/main/battlecode/world/resources/raindrop.map22 new file mode 100644 index 00000000..8f98b0cf Binary files /dev/null and b/engine/src/main/battlecode/world/resources/raindrop.map22 differ diff --git a/engine/src/main/battlecode/world/resources/rivers.map22 b/engine/src/main/battlecode/world/resources/rivers.map22 new file mode 100644 index 00000000..612dfe07 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/rivers.map22 differ diff --git a/engine/src/main/battlecode/world/resources/rng.map22 b/engine/src/main/battlecode/world/resources/rng.map22 new file mode 100644 index 00000000..72bfc607 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/rng.map22 differ diff --git a/engine/src/main/battlecode/world/resources/rugged.map22 b/engine/src/main/battlecode/world/resources/rugged.map22 new file mode 100644 index 00000000..04cc9a29 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/rugged.map22 differ diff --git a/engine/src/main/battlecode/world/resources/sandwich.map22 b/engine/src/main/battlecode/world/resources/sandwich.map22 new file mode 100644 index 00000000..ec3f1f75 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/sandwich.map22 differ diff --git a/engine/src/main/battlecode/world/resources/seagull.map22 b/engine/src/main/battlecode/world/resources/seagull.map22 new file mode 100644 index 00000000..3aef3b89 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/seagull.map22 differ diff --git a/engine/src/main/battlecode/world/resources/snowflake.map22 b/engine/src/main/battlecode/world/resources/snowflake.map22 new file mode 100644 index 00000000..1563f266 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/snowflake.map22 differ diff --git a/engine/src/main/battlecode/world/resources/snowflake_redux.map22 b/engine/src/main/battlecode/world/resources/snowflake_redux.map22 new file mode 100644 index 00000000..f15ca982 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/snowflake_redux.map22 differ diff --git a/engine/src/main/battlecode/world/resources/snowman.map22 b/engine/src/main/battlecode/world/resources/snowman.map22 new file mode 100644 index 00000000..87bbabe2 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/snowman.map22 differ diff --git a/engine/src/main/battlecode/world/resources/spine.map22 b/engine/src/main/battlecode/world/resources/spine.map22 new file mode 100644 index 00000000..0bbce7cb Binary files /dev/null and b/engine/src/main/battlecode/world/resources/spine.map22 differ diff --git a/engine/src/main/battlecode/world/resources/squer.map22 b/engine/src/main/battlecode/world/resources/squer.map22 new file mode 100644 index 00000000..97b0f808 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/squer.map22 differ diff --git a/engine/src/main/battlecode/world/resources/standoff.map22 b/engine/src/main/battlecode/world/resources/standoff.map22 new file mode 100644 index 00000000..8c71af62 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/standoff.map22 differ diff --git a/engine/src/main/battlecode/world/resources/stingray.map22 b/engine/src/main/battlecode/world/resources/stingray.map22 new file mode 100644 index 00000000..eb870b00 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/stingray.map22 differ diff --git a/engine/src/main/battlecode/world/resources/stronghold.map22 b/engine/src/main/battlecode/world/resources/stronghold.map22 new file mode 100644 index 00000000..a347ace6 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/stronghold.map22 differ diff --git a/engine/src/main/battlecode/world/resources/tower.map22 b/engine/src/main/battlecode/world/resources/tower.map22 new file mode 100644 index 00000000..fd509f0f Binary files /dev/null and b/engine/src/main/battlecode/world/resources/tower.map22 differ diff --git a/engine/src/main/battlecode/world/resources/treasure.map22 b/engine/src/main/battlecode/world/resources/treasure.map22 new file mode 100644 index 00000000..35aa5f3b Binary files /dev/null and b/engine/src/main/battlecode/world/resources/treasure.map22 differ diff --git a/engine/src/main/battlecode/world/resources/tree.map22 b/engine/src/main/battlecode/world/resources/tree.map22 new file mode 100644 index 00000000..52d86486 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/tree.map22 differ diff --git a/engine/src/main/battlecode/world/resources/tree2.map22 b/engine/src/main/battlecode/world/resources/tree2.map22 new file mode 100644 index 00000000..8701c7ee Binary files /dev/null and b/engine/src/main/battlecode/world/resources/tree2.map22 differ diff --git a/engine/src/main/battlecode/world/resources/tunnels.map22 b/engine/src/main/battlecode/world/resources/tunnels.map22 new file mode 100644 index 00000000..0d6425e8 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/tunnels.map22 differ diff --git a/engine/src/main/battlecode/world/resources/turtle.map22 b/engine/src/main/battlecode/world/resources/turtle.map22 new file mode 100644 index 00000000..1eed161f Binary files /dev/null and b/engine/src/main/battlecode/world/resources/turtle.map22 differ diff --git a/engine/src/main/battlecode/world/resources/uncomfortable.map22 b/engine/src/main/battlecode/world/resources/uncomfortable.map22 new file mode 100644 index 00000000..065acec6 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/uncomfortable.map22 differ diff --git a/engine/src/main/battlecode/world/resources/underground.map22 b/engine/src/main/battlecode/world/resources/underground.map22 new file mode 100644 index 00000000..7e10181c Binary files /dev/null and b/engine/src/main/battlecode/world/resources/underground.map22 differ diff --git a/engine/src/main/battlecode/world/resources/unfair_sumo.map22 b/engine/src/main/battlecode/world/resources/unfair_sumo.map22 new file mode 100644 index 00000000..4d4bf962 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/unfair_sumo.map22 differ diff --git a/engine/src/main/battlecode/world/resources/valley.map22 b/engine/src/main/battlecode/world/resources/valley.map22 new file mode 100644 index 00000000..d9fd6f23 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/valley.map22 differ diff --git a/engine/src/main/battlecode/world/resources/vault.map22 b/engine/src/main/battlecode/world/resources/vault.map22 new file mode 100644 index 00000000..4a83884c Binary files /dev/null and b/engine/src/main/battlecode/world/resources/vault.map22 differ diff --git a/engine/src/main/battlecode/world/resources/vortex.map22 b/engine/src/main/battlecode/world/resources/vortex.map22 new file mode 100644 index 00000000..47166762 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/vortex.map22 differ diff --git a/engine/src/main/battlecode/world/resources/walls.map22 b/engine/src/main/battlecode/world/resources/walls.map22 new file mode 100644 index 00000000..83a338e9 Binary files /dev/null and b/engine/src/main/battlecode/world/resources/walls.map22 differ diff --git a/engine/src/test/battlecode/server/GameMakerTest.java b/engine/src/test/battlecode/server/GameMakerTest.java index 6cf73e5e..8b20a219 100644 --- a/engine/src/test/battlecode/server/GameMakerTest.java +++ b/engine/src/test/battlecode/server/GameMakerTest.java @@ -44,12 +44,12 @@ public void testStateExceptions() { gm.makeGameFooter(Team.A); } - @Test(expected=RuntimeException.class) - public void testMatchStateExceptions() { - GameMaker gm = new GameMaker(info, null, true); - gm.makeGameHeader(); - gm.getMatchMaker().makeMatchFooter(Team.A, 23, new ArrayList<>()); - } + // @Test(expected=RuntimeException.class) + // public void testMatchStateExceptions() { + // GameMaker gm = new GameMaker(info, null, true); + // gm.makeGameHeader(); + // gm.getMatchMaker().makeMatchFooter(Team.A, 23, new ArrayList<>()); + // } // @Test // public void fullReasonableGame() throws Exception { diff --git a/engine/src/test/battlecode/world/GenerateMaps.java b/engine/src/test/battlecode/world/GenerateMaps.java index a55779fd..0d340cb6 100644 --- a/engine/src/test/battlecode/world/GenerateMaps.java +++ b/engine/src/test/battlecode/world/GenerateMaps.java @@ -21,20 +21,18 @@ public class GenerateMaps { @Test public void makeSimple() throws IOException { - LiveMap map = new TestMapBuilder("maptest", 0, 0, 100, 100, 30, 3000) - .addEnlightenmentCenter( + LiveMap map = new TestMapBuilder("maptest", 0, 0, 100, 100, 30) + .addArchon( 0, Team.A, - GameConstants.INITIAL_ENLIGHTENMENT_CENTER_INFLUENCE, new MapLocation( 1, 1 ) ) - .addEnlightenmentCenter( + .addArchon( 1, Team.B, - GameConstants.INITIAL_ENLIGHTENMENT_CENTER_INFLUENCE, new MapLocation( 99, 99 diff --git a/engine/src/test/battlecode/world/RobotControllerTest.java b/engine/src/test/battlecode/world/RobotControllerTest.java index 4d5a9510..b70dac0d 100644 --- a/engine/src/test/battlecode/world/RobotControllerTest.java +++ b/engine/src/test/battlecode/world/RobotControllerTest.java @@ -192,7 +192,7 @@ public class RobotControllerTest { // final int soldierB = game.spawn(7, 5, RobotType.MINER, Team.B); // game.round((id, rc) -> { - // if(id != soldierA) return; + // if (id != soldierA) return; // RobotInfo actualBot = rc.senseRobotAtLocation(new MapLocation(3,5)); // RobotInfo nullBot = rc.senseRobotAtLocation(new MapLocation(5,7)); @@ -215,7 +215,7 @@ public class RobotControllerTest { // int[] testIDs = new int[TEST_UNITS]; - // for(int i=0; i { - // if(rc.getType() == RobotType.SOLDIER) { + // if (rc.getType() == RobotType.SOLDIER) { // executionOrder.add(id); // } else if (id == archonA) { // assertTrue(rc.canHireGardener(Direction.EAST)); @@ -239,7 +239,7 @@ public class RobotControllerTest { // // Assert IDs aren't in order (random change, but very unlikely unless something is wrong) // boolean sorted = true; - // for(int i=0; i bodies; - - public TestMapBuilder(String name, int oX, int oY, int width, int height, int seed, int rounds) { - this(name, new MapLocation(oX, oY), width, height, seed, rounds); - } - - public TestMapBuilder(String name, MapLocation origin, int width, int height, int seed, int rounds) { - this.name = name; - this.origin = origin; - this.width = width; - this.height = height; - this.seed = seed; - this.bodies = new ArrayList<>(); + public TestMapBuilder(String name, int oX, int oY, int width, int height, int seed) { + this.mapBuilder = new MapBuilder(name, width, height, oX, oY, seed); } - public TestMapBuilder addEnlightenmentCenter(int id, Team team, int influence, MapLocation loc) { - bodies.add(new RobotInfo( - id, - team, - RobotType.ENLIGHTENMENT_CENTER, - influence, - 0, - loc - )); - + public TestMapBuilder addArchon(int id, Team team, MapLocation loc) { + this.mapBuilder.addArchon(id, team, loc); return this; } - public TestMapBuilder setPassability() { - this.passabilityArray = new double[width * height]; - for(int i = 0; i < width; i++) { - for (int j = 0; j < height; j++) { - this.passabilityArray[i + j * width] = (i * j + i + j) / (i * j + 1); - } - } + public TestMapBuilder setRubble(int x, int y, int value) { + this.mapBuilder.setRubble(x, y, value); + return this; + } + + public TestMapBuilder setLead(int x, int y, int value) { + this.mapBuilder.setLead(x, y, value); return this; } - public TestMapBuilder addBody(RobotInfo info) { - bodies.add(info); + public TestMapBuilder addAnomalyScheduleEntry(int round, AnomalyType anomaly) { + this.mapBuilder.addAnomalyScheduleEntry(round, anomaly); return this; } public LiveMap build() { - return new LiveMap(width, height, origin, seed, GameConstants.GAME_MAX_NUMBER_OF_ROUNDS, name, bodies.toArray(new RobotInfo[bodies.size()]), passabilityArray); + return this.mapBuilder.build(); } } diff --git a/example-bots/build.gradle b/example-bots/build.gradle index b1fcd065..168b9892 100644 --- a/example-bots/build.gradle +++ b/example-bots/build.gradle @@ -11,37 +11,28 @@ project.ext.release_players='NONE' repositories { mavenCentral() maven {url "https://oss.sonatype.org/content/repositories/snapshots/"} - jcenter() } sourceSets { main { scala.srcDirs = ["src/main"] - // output.classesDir = "$buildDir/classes" - java.outputDir = file("$buildDir/classes") - scala.outputDir = file("$buildDir/classes") + java.destinationDirectory.set(file("$buildDir/classes")) + scala.destinationDirectory.set(file("$buildDir/classes")) } test { scala.srcDirs = ["src/test"] - // output.classesDir = "$buildDir/tests" - java.outputDir = file("$buildDir/tests") - scala.outputDir = file("$buildDir/tests") + java.destinationDirectory.set(file("$buildDir/tests")) + scala.destinationDirectory.set(file("$buildDir/tests")) } - // main.java.srcDirs += 'src/main/kotlin' } dependencies { - compile project(':engine') + implementation project(':engine') + implementation group: 'org.scala-lang', name: 'scala3-library_3', version: '3.3.0-RC1-bin-20221219-0555491-NIGHTLY' - // scala - compile group: 'org.scala-lang', name: 'scala-library', version: '2.12.1' - - - - // Testing dependencies - testCompile 'junit:junit:4.12' + testImplementation group: 'junit', name: 'junit', version: '4.13.2' } jar { diff --git a/example-bots/src/main/examplefuncsplayer/RobotPlayer.java b/example-bots/src/main/examplefuncsplayer/RobotPlayer.java index 6eff43a4..865e0697 100644 --- a/example-bots/src/main/examplefuncsplayer/RobotPlayer.java +++ b/example-bots/src/main/examplefuncsplayer/RobotPlayer.java @@ -1,15 +1,31 @@ package examplefuncsplayer; + import battlecode.common.*; +import java.util.Random; +/** + * RobotPlayer is the class that describes your main robot strategy. + * The run() method inside this class is like your main function: this is what we'll call once your robot + * is created! + */ public strictfp class RobotPlayer { - static RobotController rc; - static final RobotType[] spawnableRobot = { - RobotType.POLITICIAN, - RobotType.SLANDERER, - RobotType.MUCKRAKER, - }; + /** + * We will use this variable to count the number of turns this robot has been alive. + * You can use static variables like this to save any information you want. Keep in mind that even though + * these variables are static, in Battlecode they aren't actually shared between your robots. + */ + static int turnCount = 0; + + /** + * A random number generator. + * We will use this RNG to make some random moves. The Random class is provided by the java.util.Random + * import at the top of this file. Here, we *seed* the RNG with a constant number (6147); this makes sure + * we get the same sequence of numbers every time this code is run. This is very useful for debugging! + */ + static final Random rng = new Random(6147); + /** Array containing all the possible movement directions. */ static final Direction[] directions = { Direction.NORTH, Direction.NORTHEAST, @@ -21,125 +37,142 @@ public strictfp class RobotPlayer { Direction.NORTHWEST, }; - static int turnCount; - /** * run() is the method that is called when a robot is instantiated in the Battlecode world. - * If this method returns, the robot dies! + * It is like the main function for your robot. If this method returns, the robot dies! + * + * @param rc The RobotController object. You use it to perform actions from this robot, and to get + * information on its current status. Essentially your portal to interacting with the world. **/ @SuppressWarnings("unused") public static void run(RobotController rc) throws GameActionException { - // This is the RobotController object. You use it to perform actions from this robot, - // and to get information on its current status. - RobotPlayer.rc = rc; + // Hello world! Standard output is very useful for debugging. + // Everything you say here will be directly viewable in your terminal when you run a match! + System.out.println("I'm a " + rc.getType() + " and I just got created! I have health " + rc.getHealth()); - turnCount = 0; + // You can also use indicators to save debug notes in replays. + rc.setIndicatorString("Hello world!"); - System.out.println("I'm a " + rc.getType() + " and I just got created! I have influence " + rc.getInfluence()); while (true) { - turnCount += 1; - // Try/catch blocks stop unhandled exceptions, which cause your robot to freeze + // This code runs during the entire lifespan of the robot, which is why it is in an infinite + // loop. If we ever leave this loop and return from run(), the robot dies! At the end of the + // loop, we call Clock.yield(), signifying that we've done everything we want to do. + + turnCount += 1; // We have now been alive for one more turn! + System.out.println("Age: " + turnCount + "; Location: " + rc.getLocation()); + + // Try/catch blocks stop unhandled exceptions, which cause your robot to explode. try { - // Here, we've separated the controls into a different method for each RobotType. - // You may rewrite this into your own control structure if you wish. - System.out.println("I'm a " + rc.getType() + "! Location " + rc.getLocation()); + // The same run() function is called for every robot on your team, even if they are + // different types. Here, we separate the control depending on the RobotType, so we can + // use different strategies on different robots. If you wish, you are free to rewrite + // this into a different control structure! switch (rc.getType()) { - case ENLIGHTENMENT_CENTER: runEnlightenmentCenter(); break; - case POLITICIAN: runPolitician(); break; - case SLANDERER: runSlanderer(); break; - case MUCKRAKER: runMuckraker(); break; + case ARCHON: runArchon(rc); break; + case MINER: runMiner(rc); break; + case SOLDIER: runSoldier(rc); break; + case LABORATORY: // Examplefuncsplayer doesn't use any of these robot types below. + case WATCHTOWER: // You might want to give them a try! + case BUILDER: + case SAGE: break; } - - // Clock.yield() makes the robot wait until the next turn, then it will perform this loop again - Clock.yield(); + } catch (GameActionException e) { + // Oh no! It looks like we did something illegal in the Battlecode world. You should + // handle GameActionExceptions judiciously, in case unexpected events occur in the game + // world. Remember, uncaught exceptions cause your robot to explode! + System.out.println(rc.getType() + " Exception"); + e.printStackTrace(); } catch (Exception e) { + // Oh no! It looks like our code tried to do something bad. This isn't a + // GameActionException, so it's more likely to be a bug in our code. System.out.println(rc.getType() + " Exception"); e.printStackTrace(); - } - } - } - static void runEnlightenmentCenter() throws GameActionException { - RobotType toBuild = randomSpawnableRobotType(); - int influence = 50; - for (Direction dir : directions) { - if (rc.canBuildRobot(toBuild, dir, influence)) { - rc.buildRobot(toBuild, dir, influence); - } else { - break; + } finally { + // Signify we've done everything we want to do, thereby ending our turn. + // This will make our code wait until the next turn, and then perform this loop again. + Clock.yield(); } + // End of loop: go back to the top. Clock.yield() has ended, so it's time for another turn! } - rc.bid(1); // submit a bid for a vote - } - - static void runPolitician() throws GameActionException { - Team enemy = rc.getTeam().opponent(); - int actionRadius = rc.getType().actionRadiusSquared; - RobotInfo[] attackable = rc.senseNearbyRobots(actionRadius, enemy); - if (attackable.length != 0 && rc.canEmpower(actionRadius)) { - System.out.println("empowering..."); - rc.empower(actionRadius); - System.out.println("empowered"); - return; - } - if (tryMove(randomDirection())) - System.out.println("I moved!"); - } - static void runSlanderer() throws GameActionException { - if (tryMove(randomDirection())) - System.out.println("I moved!"); + // Your code should never reach here (unless it's intentional)! Self-destruction imminent... } - static void runMuckraker() throws GameActionException { - Team enemy = rc.getTeam().opponent(); - int actionRadius = rc.getType().actionRadiusSquared; - for (RobotInfo robot : rc.senseNearbyRobots(actionRadius, enemy)) { - if (robot.type.canBeExposed()) { - // It's a slanderer... go get them! - if (rc.canExpose(robot.location)) { - System.out.println("e x p o s e d"); - rc.expose(robot.location); - return; - } + /** + * Run a single turn for an Archon. + * This code is wrapped inside the infinite loop in run(), so it is called once per turn. + */ + static void runArchon(RobotController rc) throws GameActionException { + // Pick a direction to build in. + Direction dir = directions[rng.nextInt(directions.length)]; + if (rng.nextBoolean()) { + // Let's try to build a miner. + rc.setIndicatorString("Trying to build a miner"); + if (rc.canBuildRobot(RobotType.MINER, dir)) { + rc.buildRobot(RobotType.MINER, dir); + } + } else { + // Let's try to build a soldier. + rc.setIndicatorString("Trying to build a soldier"); + if (rc.canBuildRobot(RobotType.SOLDIER, dir)) { + rc.buildRobot(RobotType.SOLDIER, dir); } } - if (tryMove(randomDirection())) - System.out.println("I moved!"); } /** - * Returns a random Direction. - * - * @return a random Direction + * Run a single turn for a Miner. + * This code is wrapped inside the infinite loop in run(), so it is called once per turn. */ - static Direction randomDirection() { - return directions[(int) (Math.random() * directions.length)]; - } + static void runMiner(RobotController rc) throws GameActionException { + // Try to mine on squares around us. + MapLocation me = rc.getLocation(); + for (int dx = -1; dx <= 1; dx++) { + for (int dy = -1; dy <= 1; dy++) { + MapLocation mineLocation = new MapLocation(me.x + dx, me.y + dy); + // Notice that the Miner's action cooldown is very low. + // You can mine multiple times per turn! + while (rc.canMineGold(mineLocation)) { + rc.mineGold(mineLocation); + } + while (rc.canMineLead(mineLocation)) { + rc.mineLead(mineLocation); + } + } + } - /** - * Returns a random spawnable RobotType - * - * @return a random RobotType - */ - static RobotType randomSpawnableRobotType() { - return spawnableRobot[(int) (Math.random() * spawnableRobot.length)]; + // Also try to move randomly. + Direction dir = directions[rng.nextInt(directions.length)]; + if (rc.canMove(dir)) { + rc.move(dir); + System.out.println("I moved!"); + } } /** - * Attempts to move in a given direction. - * - * @param dir The intended direction of movement - * @return true if a move was performed - * @throws GameActionException + * Run a single turn for a Soldier. + * This code is wrapped inside the infinite loop in run(), so it is called once per turn. */ - static boolean tryMove(Direction dir) throws GameActionException { - System.out.println("I am trying to move " + dir + "; " + rc.isReady() + " " + rc.getCooldownTurns() + " " + rc.canMove(dir)); + static void runSoldier(RobotController rc) throws GameActionException { + // Try to attack someone + int radius = rc.getType().actionRadiusSquared; + Team opponent = rc.getTeam().opponent(); + RobotInfo[] enemies = rc.senseNearbyRobots(radius, opponent); + if (enemies.length > 0) { + MapLocation toAttack = enemies[0].location; + if (rc.canAttack(toAttack)) { + rc.attack(toAttack); + } + } + + // Also try to move randomly. + Direction dir = directions[rng.nextInt(directions.length)]; if (rc.canMove(dir)) { rc.move(dir); - return true; - } else return false; + System.out.println("I moved!"); + } } } diff --git a/gradle.properties b/gradle.properties index 3d94d4be..abe40993 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,12 @@ -# modify this file to change project properties +# What are you trying to run? + teamA=examplefuncsplayer teamB=examplefuncsplayer maps=maptestsmall -profilerEnabled=false -source=src -mapLocation=maps -release_version=2022.0.0.0 + +# Some optional configuraitons you can adjust as you need + +debug=false +enableProfiler=false +outputVerbose=true +showIndicators=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf0..943f0cbf 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7c4388a9..f398c33c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 83f2acfd..65dcd68d 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,84 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 24467a14..6689b85b 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,14 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @@ -37,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/javadoc/README.md b/javadoc/README.md new file mode 100644 index 00000000..abc287a8 --- /dev/null +++ b/javadoc/README.md @@ -0,0 +1,3 @@ +An otherwise-empty folder, to designate where javadocs should appear as they are deployed. + +(This file allows GitHub to track the folder, so that its location can be properly known to users.) diff --git a/schema/README.md b/schema/README.md index aa640b8d..70ffed6f 100644 --- a/schema/README.md +++ b/schema/README.md @@ -4,7 +4,7 @@ This repository contains the [Flatbuffers](https://google.github.io/flatbuffers/ ### Spec ##### Match Files -A match file has the extension `.bc21`. It consists of a single flatbuffer with a GameWrapper at its root, containing a valid stream of Events (as described in `battlecode.fbs`). The buffer will be compressed with GZIP. +A match file has the extension `.bc22`. It consists of a single flatbuffer with a GameWrapper at its root, containing a valid stream of Events (as described in `battlecode.fbs`). The buffer will be compressed with GZIP. ##### Network Protocol The battlecode server hosts an unsecured websocket server on port 6175. When you connect to that port, you will receive each Event that has occurred in the current match as a separate websocket message, in order. There are no messages that can be sent from the client to the server. The server may disconnect at any time, and might not resend its messages when it does; any client has to be able to deal with a game being only half-finished over the network. Messages over the network are unsecured. diff --git a/schema/battlecode.fbs b/schema/battlecode.fbs index 1ef7131e..50515275 100644 --- a/schema/battlecode.fbs +++ b/schema/battlecode.fbs @@ -13,7 +13,6 @@ table VecTable { ys: [int]; } - /// A table of RGB values. table RGBTable { red: [int]; @@ -24,7 +23,6 @@ table RGBTable { /// The possible types of things that can exist. /// Note that bullets are not treated as bodies. enum BodyType : byte { - // droids MINER, BUILDER, @@ -61,19 +59,20 @@ table GameMap { minCorner: Vec; /// The top corner of the map. maxCorner: Vec; + /// The map symmetry: 0 for rotation, 1 for horizontal, 2 for vertical. + symmetry: int; /// The bodies on the map. bodies: SpawnedBodyTable; /// The random seed of the map. randomSeed: int; - /// The factor to divide cooldowns by - passability: [double]; - - // lead locations - - // a vectable of lead cords - leadLocations: VecTable; - // inital lead amounts - leadAmounts: [double]; + /// The rubble on the map. + rubble: [int]; + /// The lead on the map. + lead: [int]; + /// The anomalies scheduled: 0/1/2/3 abyss/charge/fury/vortex. + anomalies: [int]; + /// The rounds the anomalies are scheduled for. + anomalyRounds: [int]; } /// Actions that can be performed. @@ -83,27 +82,44 @@ table GameMap { /// Actions may have 'targets', which are the units on which /// the actions were performed. enum Action : byte { - ATTACK, // combat unit types - SPAWN_UNIT, //archon - MINE, // miner - BUILD, // builder - CONVERT_GOLD, // for alchemist laboratory. - TRANSFORM, // Swaps a building between portable and turret mode - UPGRADE, // builder upgrades building, - REPAIR, // builder repairs building - CHANGE_HP, - FULLY_REPAIRED, // prototype becomes a turret + /// Target: ID of robot attacked + ATTACK, + /// Target: ID of robot spawned + SPAWN_UNIT, + /// Target: location mined, x + y * width + MINE_LEAD, + /// Target: location mined, x + y * width + MINE_GOLD, + /// Target: none + TRANSMUTE, + /// Target: none + TRANSFORM, + /// Target: ID of robot mutated + MUTATE, + /// Target: ID of robot repaired + REPAIR, + /// Target: change in health (can be negative) + CHANGE_HEALTH, + /// When a PROTOTYPE building upgrades to TURRET + /// Target: none + FULLY_REPAIRED, + /// Target: Sage location, x + y * width LOCAL_ABYSS, - LOCAL_FURY, + /// Target: Sage location, x + y * width LOCAL_CHARGE, - /// Dies due to an uncaught exception. + /// Target: Sage location, x + y * width + LOCAL_FURY, /// Target: none - DIE_EXCEPTION, ABYSS, + /// Target: none CHARGE, + /// Target: none FURY, + /// Target: 0 if 90 degrees clockwise, 1 if horizontal, 2 if vertical VORTEX, - SINGULARITY + /// Dies due to an uncaught exception. + /// Target: none + DIE_EXCEPTION, } // Metadata @@ -111,19 +127,23 @@ enum Action : byte { /// Metadata about all bodies of a particular type. table BodyTypeMetadata { type: BodyType; - spawnSource: BodyType; + buildCostLead: int; + buildCostGold: int; + level2CostLead: int; + level2CostGold: int; + level3CostLead: int; + level3CostGold: int; + actionCooldown: int; + movementCooldown: int; + health: int; + level2Health: int; + level3Health: int; + damage: int; + level2Damage: int; + level3Damage: int; actionRadiusSquared: int; visionRadiusSquared: int; - actionCooldown: float; - movementCooldown: float; bytecodeLimit: int; - dps: int; // dps at lowest level - hp: int; // hp at lowest level - dpsMul: float; // dps multiplier for level - hpMul: float; // hp multiplier per level - buildCost: int; - upgradeCostLead: [int]; - upgradeCostGold: [int]; } /// Data relevant to a particular team. @@ -194,10 +214,10 @@ union Event { } table Constants { - //amounts of resources added to each block per round - leadAdditiveIncease: double; - goldAdditiveIncease: double; + // number of rounds for passive lead increase increasePeriod: int; + // amounts of lead added every increasePeriod rounds + leadAdditiveIncease: int; } @@ -246,8 +266,10 @@ table Round { /// The IDs of teams in the Game. teamIDs: [int]; - teamLeadChange: [int]; - teamGoldChange: [int]; + /// The total amount of lead change of this team, this round + teamLeadChanges: [int]; + /// The total amount of gold change of this team, this round + teamGoldChanges: [int]; /// The IDs of bodies that moved. movedIDs: [int]; @@ -268,17 +290,21 @@ table Round { /// The 'targets' of the performed actions. Actions without targets may have any value actionTargets: [int]; - /// The IDs of the robots who changed their indicator strings - indicatorStringIDs: [int]; - /// The messages of the robots who changed their indicator strings - indicatorStrings: [string]; - + /// The locations of lead drops leadDropLocations: VecTable; + /// The amount of lead dropped at each location leadDropValues: [int]; + /// The locations of gold drops goldDropLocations: VecTable; + /// The amount of gold dropped at each location goldDropValues: [int]; + /// The IDs of the robots who changed their indicator strings + indicatorStringIDs: [int]; + /// The messages of the robots who changed their indicator strings + indicatorStrings: [string]; + /// The IDs of bodies that set indicator dots indicatorDotIDs: [int]; /// The location of the indicator dots @@ -295,7 +321,7 @@ table Round { /// The RGB values of the indicator lines indicatorLineRGBs: RGBTable; - //logs have been replaced with indicator strings + // logs have been replaced with indicator strings /// The first sent Round in a match should have index 1. (The starting state, /// created by the MatchHeader, can be thought to have index 0.) diff --git a/schema/java/battlecode/schema/Action.java b/schema/java/battlecode/schema/Action.java index b7990cad..3062d6f7 100644 --- a/schema/java/battlecode/schema/Action.java +++ b/schema/java/battlecode/schema/Action.java @@ -12,26 +12,82 @@ */ public final class Action { private Action() { } + /** + * Target: ID of robot attacked + */ public static final byte ATTACK = 0; + /** + * Target: ID of robot spawned + */ public static final byte SPAWN_UNIT = 1; - public static final byte MINE = 2; - public static final byte BUILD = 3; - public static final byte CONVERT_GOLD = 4; + /** + * Target: location mined, x + y * width + */ + public static final byte MINE_LEAD = 2; + /** + * Target: location mined, x + y * width + */ + public static final byte MINE_GOLD = 3; + /** + * Target: none + */ + public static final byte TRANSMUTE = 4; + /** + * Target: none + */ public static final byte TRANSFORM = 5; - public static final byte UPGRADE = 6; + /** + * Target: ID of robot mutated + */ + public static final byte MUTATE = 6; + /** + * Target: ID of robot repaired + */ public static final byte REPAIR = 7; - public static final byte CHANGE_HP = 8; + /** + * Target: change in health (can be negative) + */ + public static final byte CHANGE_HEALTH = 8; + /** + * When a PROTOTYPE building upgrades to TURRET + * Target: none + */ public static final byte FULLY_REPAIRED = 9; + /** + * Target: Sage location, x + y * width + */ public static final byte LOCAL_ABYSS = 10; - public static final byte LOCAL_FURY = 11; - public static final byte LOCAL_CHARGE = 12; + /** + * Target: Sage location, x + y * width + */ + public static final byte LOCAL_CHARGE = 11; + /** + * Target: Sage location, x + y * width + */ + public static final byte LOCAL_FURY = 12; + /** + * Target: none + */ + public static final byte ABYSS = 13; + /** + * Target: none + */ + public static final byte CHARGE = 14; + /** + * Target: none + */ + public static final byte FURY = 15; + /** + * Target: 0 if 90 degrees clockwise, 1 if horizontal, 2 if vertical + */ + public static final byte VORTEX = 16; /** * Dies due to an uncaught exception. * Target: none */ - public static final byte DIE_EXCEPTION = 13; + public static final byte DIE_EXCEPTION = 17; - public static final String[] names = { "ATTACK", "SPAWN_UNIT", "MINE", "BUILD", "CONVERT_GOLD", "TRANSFORM", "UPGRADE", "REPAIR", "CHANGE_HP", "FULLY_REPAIRED", "LOCAL_ABYSS", "LOCAL_FURY", "LOCAL_CHARGE", "DIE_EXCEPTION", }; + public static final String[] names = { "ATTACK", "SPAWN_UNIT", "MINE_LEAD", "MINE_GOLD", "TRANSMUTE", "TRANSFORM", "MUTATE", "REPAIR", "CHANGE_HEALTH", "FULLY_REPAIRED", "LOCAL_ABYSS", "LOCAL_CHARGE", "LOCAL_FURY", "ABYSS", "CHARGE", "FURY", "VORTEX", "DIE_EXCEPTION", }; public static String name(int e) { return names[e]; } } diff --git a/schema/java/battlecode/schema/BodyTypeMetadata.java b/schema/java/battlecode/schema/BodyTypeMetadata.java index cf3e3b93..4d68dbd4 100644 --- a/schema/java/battlecode/schema/BodyTypeMetadata.java +++ b/schema/java/battlecode/schema/BodyTypeMetadata.java @@ -7,104 +7,98 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * Metadata about all bodies of a particular type. */ -@SuppressWarnings("unused") public final class BodyTypeMetadata extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static BodyTypeMetadata getRootAsBodyTypeMetadata(ByteBuffer _bb) { return getRootAsBodyTypeMetadata(_bb, new BodyTypeMetadata()); } public static BodyTypeMetadata getRootAsBodyTypeMetadata(ByteBuffer _bb, BodyTypeMetadata obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public BodyTypeMetadata __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public byte type() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } - public byte spawnSource() { int o = __offset(6); return o != 0 ? bb.get(o + bb_pos) : 0; } - public int actionRadiusSquared() { int o = __offset(8); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public int visionRadiusSquared() { int o = __offset(10); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public float actionCooldown() { int o = __offset(12); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } - public float movementCooldown() { int o = __offset(14); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } - public int bytecodeLimit() { int o = __offset(16); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public int dps() { int o = __offset(18); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public int hp() { int o = __offset(20); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public float dpsMul() { int o = __offset(22); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } - public float hpMul() { int o = __offset(24); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } - public int buildCost() { int o = __offset(26); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public int upgradeCostLead(int j) { int o = __offset(28); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int upgradeCostLeadLength() { int o = __offset(28); return o != 0 ? __vector_len(o) : 0; } - public IntVector upgradeCostLeadVector() { return upgradeCostLeadVector(new IntVector()); } - public IntVector upgradeCostLeadVector(IntVector obj) { int o = __offset(28); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer upgradeCostLeadAsByteBuffer() { return __vector_as_bytebuffer(28, 4); } - public ByteBuffer upgradeCostLeadInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 28, 4); } - public int upgradeCostGold(int j) { int o = __offset(30); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int upgradeCostGoldLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } - public IntVector upgradeCostGoldVector() { return upgradeCostGoldVector(new IntVector()); } - public IntVector upgradeCostGoldVector(IntVector obj) { int o = __offset(30); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer upgradeCostGoldAsByteBuffer() { return __vector_as_bytebuffer(30, 4); } - public ByteBuffer upgradeCostGoldInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 30, 4); } + public int buildCostLead() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int buildCostGold() { int o = __offset(8); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2CostLead() { int o = __offset(10); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2CostGold() { int o = __offset(12); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3CostLead() { int o = __offset(14); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3CostGold() { int o = __offset(16); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int actionCooldown() { int o = __offset(18); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int movementCooldown() { int o = __offset(20); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int health() { int o = __offset(22); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2Health() { int o = __offset(24); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3Health() { int o = __offset(26); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int damage() { int o = __offset(28); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level2Damage() { int o = __offset(30); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int level3Damage() { int o = __offset(32); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int actionRadiusSquared() { int o = __offset(34); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int visionRadiusSquared() { int o = __offset(36); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int bytecodeLimit() { int o = __offset(38); return o != 0 ? bb.getInt(o + bb_pos) : 0; } public static int createBodyTypeMetadata(FlatBufferBuilder builder, byte type, - byte spawnSource, + int buildCostLead, + int buildCostGold, + int level2CostLead, + int level2CostGold, + int level3CostLead, + int level3CostGold, + int actionCooldown, + int movementCooldown, + int health, + int level2Health, + int level3Health, + int damage, + int level2Damage, + int level3Damage, int actionRadiusSquared, int visionRadiusSquared, - float actionCooldown, - float movementCooldown, - int bytecodeLimit, - int dps, - int hp, - float dpsMul, - float hpMul, - int buildCost, - int upgradeCostLeadOffset, - int upgradeCostGoldOffset) { - builder.startTable(14); - BodyTypeMetadata.addUpgradeCostGold(builder, upgradeCostGoldOffset); - BodyTypeMetadata.addUpgradeCostLead(builder, upgradeCostLeadOffset); - BodyTypeMetadata.addBuildCost(builder, buildCost); - BodyTypeMetadata.addHpMul(builder, hpMul); - BodyTypeMetadata.addDpsMul(builder, dpsMul); - BodyTypeMetadata.addHp(builder, hp); - BodyTypeMetadata.addDps(builder, dps); + int bytecodeLimit) { + builder.startObject(18); BodyTypeMetadata.addBytecodeLimit(builder, bytecodeLimit); - BodyTypeMetadata.addMovementCooldown(builder, movementCooldown); - BodyTypeMetadata.addActionCooldown(builder, actionCooldown); BodyTypeMetadata.addVisionRadiusSquared(builder, visionRadiusSquared); BodyTypeMetadata.addActionRadiusSquared(builder, actionRadiusSquared); - BodyTypeMetadata.addSpawnSource(builder, spawnSource); + BodyTypeMetadata.addLevel3Damage(builder, level3Damage); + BodyTypeMetadata.addLevel2Damage(builder, level2Damage); + BodyTypeMetadata.addDamage(builder, damage); + BodyTypeMetadata.addLevel3Health(builder, level3Health); + BodyTypeMetadata.addLevel2Health(builder, level2Health); + BodyTypeMetadata.addHealth(builder, health); + BodyTypeMetadata.addMovementCooldown(builder, movementCooldown); + BodyTypeMetadata.addActionCooldown(builder, actionCooldown); + BodyTypeMetadata.addLevel3CostGold(builder, level3CostGold); + BodyTypeMetadata.addLevel3CostLead(builder, level3CostLead); + BodyTypeMetadata.addLevel2CostGold(builder, level2CostGold); + BodyTypeMetadata.addLevel2CostLead(builder, level2CostLead); + BodyTypeMetadata.addBuildCostGold(builder, buildCostGold); + BodyTypeMetadata.addBuildCostLead(builder, buildCostLead); BodyTypeMetadata.addType(builder, type); return BodyTypeMetadata.endBodyTypeMetadata(builder); } - public static void startBodyTypeMetadata(FlatBufferBuilder builder) { builder.startTable(14); } + public static void startBodyTypeMetadata(FlatBufferBuilder builder) { builder.startObject(18); } public static void addType(FlatBufferBuilder builder, byte type) { builder.addByte(0, type, 0); } - public static void addSpawnSource(FlatBufferBuilder builder, byte spawnSource) { builder.addByte(1, spawnSource, 0); } - public static void addActionRadiusSquared(FlatBufferBuilder builder, int actionRadiusSquared) { builder.addInt(2, actionRadiusSquared, 0); } - public static void addVisionRadiusSquared(FlatBufferBuilder builder, int visionRadiusSquared) { builder.addInt(3, visionRadiusSquared, 0); } - public static void addActionCooldown(FlatBufferBuilder builder, float actionCooldown) { builder.addFloat(4, actionCooldown, 0.0f); } - public static void addMovementCooldown(FlatBufferBuilder builder, float movementCooldown) { builder.addFloat(5, movementCooldown, 0.0f); } - public static void addBytecodeLimit(FlatBufferBuilder builder, int bytecodeLimit) { builder.addInt(6, bytecodeLimit, 0); } - public static void addDps(FlatBufferBuilder builder, int dps) { builder.addInt(7, dps, 0); } - public static void addHp(FlatBufferBuilder builder, int hp) { builder.addInt(8, hp, 0); } - public static void addDpsMul(FlatBufferBuilder builder, float dpsMul) { builder.addFloat(9, dpsMul, 0.0f); } - public static void addHpMul(FlatBufferBuilder builder, float hpMul) { builder.addFloat(10, hpMul, 0.0f); } - public static void addBuildCost(FlatBufferBuilder builder, int buildCost) { builder.addInt(11, buildCost, 0); } - public static void addUpgradeCostLead(FlatBufferBuilder builder, int upgradeCostLeadOffset) { builder.addOffset(12, upgradeCostLeadOffset, 0); } - public static int createUpgradeCostLeadVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startUpgradeCostLeadVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addUpgradeCostGold(FlatBufferBuilder builder, int upgradeCostGoldOffset) { builder.addOffset(13, upgradeCostGoldOffset, 0); } - public static int createUpgradeCostGoldVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startUpgradeCostGoldVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addBuildCostLead(FlatBufferBuilder builder, int buildCostLead) { builder.addInt(1, buildCostLead, 0); } + public static void addBuildCostGold(FlatBufferBuilder builder, int buildCostGold) { builder.addInt(2, buildCostGold, 0); } + public static void addLevel2CostLead(FlatBufferBuilder builder, int level2CostLead) { builder.addInt(3, level2CostLead, 0); } + public static void addLevel2CostGold(FlatBufferBuilder builder, int level2CostGold) { builder.addInt(4, level2CostGold, 0); } + public static void addLevel3CostLead(FlatBufferBuilder builder, int level3CostLead) { builder.addInt(5, level3CostLead, 0); } + public static void addLevel3CostGold(FlatBufferBuilder builder, int level3CostGold) { builder.addInt(6, level3CostGold, 0); } + public static void addActionCooldown(FlatBufferBuilder builder, int actionCooldown) { builder.addInt(7, actionCooldown, 0); } + public static void addMovementCooldown(FlatBufferBuilder builder, int movementCooldown) { builder.addInt(8, movementCooldown, 0); } + public static void addHealth(FlatBufferBuilder builder, int health) { builder.addInt(9, health, 0); } + public static void addLevel2Health(FlatBufferBuilder builder, int level2Health) { builder.addInt(10, level2Health, 0); } + public static void addLevel3Health(FlatBufferBuilder builder, int level3Health) { builder.addInt(11, level3Health, 0); } + public static void addDamage(FlatBufferBuilder builder, int damage) { builder.addInt(12, damage, 0); } + public static void addLevel2Damage(FlatBufferBuilder builder, int level2Damage) { builder.addInt(13, level2Damage, 0); } + public static void addLevel3Damage(FlatBufferBuilder builder, int level3Damage) { builder.addInt(14, level3Damage, 0); } + public static void addActionRadiusSquared(FlatBufferBuilder builder, int actionRadiusSquared) { builder.addInt(15, actionRadiusSquared, 0); } + public static void addVisionRadiusSquared(FlatBufferBuilder builder, int visionRadiusSquared) { builder.addInt(16, visionRadiusSquared, 0); } + public static void addBytecodeLimit(FlatBufferBuilder builder, int bytecodeLimit) { builder.addInt(17, bytecodeLimit, 0); } public static int endBodyTypeMetadata(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public BodyTypeMetadata get(int j) { return get(new BodyTypeMetadata(), j); } - public BodyTypeMetadata get(BodyTypeMetadata obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/Constants.java b/schema/java/battlecode/schema/Constants.java new file mode 100644 index 00000000..f82a5a1f --- /dev/null +++ b/schema/java/battlecode/schema/Constants.java @@ -0,0 +1,37 @@ +// automatically generated by the FlatBuffers compiler, do not modify + +package battlecode.schema; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class Constants extends Table { + public static Constants getRootAsConstants(ByteBuffer _bb) { return getRootAsConstants(_bb, new Constants()); } + public static Constants getRootAsConstants(ByteBuffer _bb, Constants obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } + public Constants __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } + + public int increasePeriod() { int o = __offset(4); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int leadAdditiveIncease() { int o = __offset(6); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + + public static int createConstants(FlatBufferBuilder builder, + int increasePeriod, + int leadAdditiveIncease) { + builder.startObject(2); + Constants.addLeadAdditiveIncease(builder, leadAdditiveIncease); + Constants.addIncreasePeriod(builder, increasePeriod); + return Constants.endConstants(builder); + } + + public static void startConstants(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addIncreasePeriod(FlatBufferBuilder builder, int increasePeriod) { builder.addInt(0, increasePeriod, 0); } + public static void addLeadAdditiveIncease(FlatBufferBuilder builder, int leadAdditiveIncease) { builder.addInt(1, leadAdditiveIncease, 0); } + public static int endConstants(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +} + diff --git a/schema/java/battlecode/schema/EventWrapper.java b/schema/java/battlecode/schema/EventWrapper.java index 5b0aa36b..3eb73a91 100644 --- a/schema/java/battlecode/schema/EventWrapper.java +++ b/schema/java/battlecode/schema/EventWrapper.java @@ -7,42 +7,34 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * Necessary due to flatbuffers requiring unions to be wrapped in tables. */ -@SuppressWarnings("unused") public final class EventWrapper extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static EventWrapper getRootAsEventWrapper(ByteBuffer _bb) { return getRootAsEventWrapper(_bb, new EventWrapper()); } public static EventWrapper getRootAsEventWrapper(ByteBuffer _bb, EventWrapper obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public EventWrapper __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public byte eType() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 0; } - public Table e(Table obj) { int o = __offset(6); return o != 0 ? __union(obj, o + bb_pos) : null; } + public Table e(Table obj) { int o = __offset(6); return o != 0 ? __union(obj, o) : null; } public static int createEventWrapper(FlatBufferBuilder builder, byte e_type, int eOffset) { - builder.startTable(2); + builder.startObject(2); EventWrapper.addE(builder, eOffset); EventWrapper.addEType(builder, e_type); return EventWrapper.endEventWrapper(builder); } - public static void startEventWrapper(FlatBufferBuilder builder) { builder.startTable(2); } + public static void startEventWrapper(FlatBufferBuilder builder) { builder.startObject(2); } public static void addEType(FlatBufferBuilder builder, byte eType) { builder.addByte(0, eType, 0); } public static void addE(FlatBufferBuilder builder, int eOffset) { builder.addOffset(1, eOffset, 0); } public static int endEventWrapper(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public EventWrapper get(int j) { return get(new EventWrapper(), j); } - public EventWrapper get(EventWrapper obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/GameFooter.java b/schema/java/battlecode/schema/GameFooter.java index eb94d47b..b5512bb5 100644 --- a/schema/java/battlecode/schema/GameFooter.java +++ b/schema/java/battlecode/schema/GameFooter.java @@ -7,15 +7,14 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * The final event sent in the game. */ -@SuppressWarnings("unused") public final class GameFooter extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static GameFooter getRootAsGameFooter(ByteBuffer _bb) { return getRootAsGameFooter(_bb, new GameFooter()); } public static GameFooter getRootAsGameFooter(ByteBuffer _bb, GameFooter obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public GameFooter __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -25,23 +24,16 @@ public final class GameFooter extends Table { public static int createGameFooter(FlatBufferBuilder builder, byte winner) { - builder.startTable(1); + builder.startObject(1); GameFooter.addWinner(builder, winner); return GameFooter.endGameFooter(builder); } - public static void startGameFooter(FlatBufferBuilder builder) { builder.startTable(1); } + public static void startGameFooter(FlatBufferBuilder builder) { builder.startObject(1); } public static void addWinner(FlatBufferBuilder builder, byte winner) { builder.addByte(0, winner, 0); } public static int endGameFooter(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public GameFooter get(int j) { return get(new GameFooter(), j); } - public GameFooter get(GameFooter obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/GameHeader.java b/schema/java/battlecode/schema/GameHeader.java index 41069ab2..4c93ff54 100644 --- a/schema/java/battlecode/schema/GameHeader.java +++ b/schema/java/battlecode/schema/GameHeader.java @@ -7,15 +7,14 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * The first event sent in the game. Contains all metadata about the game. */ -@SuppressWarnings("unused") public final class GameHeader extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static GameHeader getRootAsGameHeader(ByteBuffer _bb) { return getRootAsGameHeader(_bb, new GameHeader()); } public static GameHeader getRootAsGameHeader(ByteBuffer _bb, GameHeader obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public GameHeader __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -27,28 +26,24 @@ public final class GameHeader extends Table { /** * The teams participating in the game. */ - public battlecode.schema.TeamData teams(int j) { return teams(new battlecode.schema.TeamData(), j); } - public battlecode.schema.TeamData teams(battlecode.schema.TeamData obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public TeamData teams(int j) { return teams(new TeamData(), j); } + public TeamData teams(TeamData obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int teamsLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public battlecode.schema.TeamData.Vector teamsVector() { return teamsVector(new battlecode.schema.TeamData.Vector()); } - public battlecode.schema.TeamData.Vector teamsVector(battlecode.schema.TeamData.Vector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } /** * Information about all body types in the game. */ - public battlecode.schema.BodyTypeMetadata bodyTypeMetadata(int j) { return bodyTypeMetadata(new battlecode.schema.BodyTypeMetadata(), j); } - public battlecode.schema.BodyTypeMetadata bodyTypeMetadata(battlecode.schema.BodyTypeMetadata obj, int j) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public BodyTypeMetadata bodyTypeMetadata(int j) { return bodyTypeMetadata(new BodyTypeMetadata(), j); } + public BodyTypeMetadata bodyTypeMetadata(BodyTypeMetadata obj, int j) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int bodyTypeMetadataLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } - public battlecode.schema.BodyTypeMetadata.Vector bodyTypeMetadataVector() { return bodyTypeMetadataVector(new battlecode.schema.BodyTypeMetadata.Vector()); } - public battlecode.schema.BodyTypeMetadata.Vector bodyTypeMetadataVector(battlecode.schema.BodyTypeMetadata.Vector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } - public battlecode.schema.Constants constants() { return constants(new battlecode.schema.Constants()); } - public battlecode.schema.Constants constants(battlecode.schema.Constants obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public Constants constants() { return constants(new Constants()); } + public Constants constants(Constants obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } public static int createGameHeader(FlatBufferBuilder builder, int specVersionOffset, int teamsOffset, int bodyTypeMetadataOffset, int constantsOffset) { - builder.startTable(4); + builder.startObject(4); GameHeader.addConstants(builder, constantsOffset); GameHeader.addBodyTypeMetadata(builder, bodyTypeMetadataOffset); GameHeader.addTeams(builder, teamsOffset); @@ -56,7 +51,7 @@ public static int createGameHeader(FlatBufferBuilder builder, return GameHeader.endGameHeader(builder); } - public static void startGameHeader(FlatBufferBuilder builder) { builder.startTable(4); } + public static void startGameHeader(FlatBufferBuilder builder) { builder.startObject(4); } public static void addSpecVersion(FlatBufferBuilder builder, int specVersionOffset) { builder.addOffset(0, specVersionOffset, 0); } public static void addTeams(FlatBufferBuilder builder, int teamsOffset) { builder.addOffset(1, teamsOffset, 0); } public static int createTeamsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } @@ -66,15 +61,8 @@ public static int createGameHeader(FlatBufferBuilder builder, public static void startBodyTypeMetadataVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static void addConstants(FlatBufferBuilder builder, int constantsOffset) { builder.addOffset(3, constantsOffset, 0); } public static int endGameHeader(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public GameHeader get(int j) { return get(new GameHeader(), j); } - public GameHeader get(GameHeader obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/GameMap.java b/schema/java/battlecode/schema/GameMap.java index 100460a5..bae5c860 100644 --- a/schema/java/battlecode/schema/GameMap.java +++ b/schema/java/battlecode/schema/GameMap.java @@ -7,15 +7,14 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * The map a round is played on. */ -@SuppressWarnings("unused") public final class GameMap extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static GameMap getRootAsGameMap(ByteBuffer _bb) { return getRootAsGameMap(_bb, new GameMap()); } public static GameMap getRootAsGameMap(ByteBuffer _bb, GameMap obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public GameMap __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -27,63 +26,77 @@ public final class GameMap extends Table { /** * The bottom corner of the map. */ - public battlecode.schema.Vec minCorner() { return minCorner(new battlecode.schema.Vec()); } - public battlecode.schema.Vec minCorner(battlecode.schema.Vec obj) { int o = __offset(6); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + public Vec minCorner() { return minCorner(new Vec()); } + public Vec minCorner(Vec obj) { int o = __offset(6); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } /** * The top corner of the map. */ - public battlecode.schema.Vec maxCorner() { return maxCorner(new battlecode.schema.Vec()); } - public battlecode.schema.Vec maxCorner(battlecode.schema.Vec obj) { int o = __offset(8); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + public Vec maxCorner() { return maxCorner(new Vec()); } + public Vec maxCorner(Vec obj) { int o = __offset(8); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; } + /** + * The map symmetry: 0 for rotation, 1 for horizontal, 2 for vertical. + */ + public int symmetry() { int o = __offset(10); return o != 0 ? bb.getInt(o + bb_pos) : 0; } /** * The bodies on the map. */ - public battlecode.schema.SpawnedBodyTable bodies() { return bodies(new battlecode.schema.SpawnedBodyTable()); } - public battlecode.schema.SpawnedBodyTable bodies(battlecode.schema.SpawnedBodyTable obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public SpawnedBodyTable bodies() { return bodies(new SpawnedBodyTable()); } + public SpawnedBodyTable bodies(SpawnedBodyTable obj) { int o = __offset(12); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The random seed of the map. */ - public int randomSeed() { int o = __offset(12); return o != 0 ? bb.getInt(o + bb_pos) : 0; } + public int randomSeed() { int o = __offset(14); return o != 0 ? bb.getInt(o + bb_pos) : 0; } /** - * The factor to divide cooldowns by + * The rubble on the map. */ - public double passability(int j) { int o = __offset(14); return o != 0 ? bb.getDouble(__vector(o) + j * 8) : 0; } - public int passabilityLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } - public DoubleVector passabilityVector() { return passabilityVector(new DoubleVector()); } - public DoubleVector passabilityVector(DoubleVector obj) { int o = __offset(14); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer passabilityAsByteBuffer() { return __vector_as_bytebuffer(14, 8); } - public ByteBuffer passabilityInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 14, 8); } - public battlecode.schema.VecTable leadLocations() { return leadLocations(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable leadLocations(battlecode.schema.VecTable obj) { int o = __offset(16); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } - public double leadAmounts(int j) { int o = __offset(18); return o != 0 ? bb.getDouble(__vector(o) + j * 8) : 0; } - public int leadAmountsLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } - public DoubleVector leadAmountsVector() { return leadAmountsVector(new DoubleVector()); } - public DoubleVector leadAmountsVector(DoubleVector obj) { int o = __offset(18); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer leadAmountsAsByteBuffer() { return __vector_as_bytebuffer(18, 8); } - public ByteBuffer leadAmountsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 18, 8); } + public int rubble(int j) { int o = __offset(16); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int rubbleLength() { int o = __offset(16); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer rubbleAsByteBuffer() { return __vector_as_bytebuffer(16, 4); } + public ByteBuffer rubbleInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 16, 4); } + /** + * The lead on the map. + */ + public int lead(int j) { int o = __offset(18); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int leadLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer leadAsByteBuffer() { return __vector_as_bytebuffer(18, 4); } + public ByteBuffer leadInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 18, 4); } + /** + * The anomalies scheduled: 0/1/2/3 abyss/charge/fury/vortex. + */ + public int anomalies(int j) { int o = __offset(20); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int anomaliesLength() { int o = __offset(20); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer anomaliesAsByteBuffer() { return __vector_as_bytebuffer(20, 4); } + public ByteBuffer anomaliesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 20, 4); } + /** + * The rounds the anomalies are scheduled for. + */ + public int anomalyRounds(int j) { int o = __offset(22); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int anomalyRoundsLength() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer anomalyRoundsAsByteBuffer() { return __vector_as_bytebuffer(22, 4); } + public ByteBuffer anomalyRoundsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 22, 4); } - public static void startGameMap(FlatBufferBuilder builder) { builder.startTable(8); } + public static void startGameMap(FlatBufferBuilder builder) { builder.startObject(10); } public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } public static void addMinCorner(FlatBufferBuilder builder, int minCornerOffset) { builder.addStruct(1, minCornerOffset, 0); } public static void addMaxCorner(FlatBufferBuilder builder, int maxCornerOffset) { builder.addStruct(2, maxCornerOffset, 0); } - public static void addBodies(FlatBufferBuilder builder, int bodiesOffset) { builder.addOffset(3, bodiesOffset, 0); } - public static void addRandomSeed(FlatBufferBuilder builder, int randomSeed) { builder.addInt(4, randomSeed, 0); } - public static void addPassability(FlatBufferBuilder builder, int passabilityOffset) { builder.addOffset(5, passabilityOffset, 0); } - public static int createPassabilityVector(FlatBufferBuilder builder, double[] data) { builder.startVector(8, data.length, 8); for (int i = data.length - 1; i >= 0; i--) builder.addDouble(data[i]); return builder.endVector(); } - public static void startPassabilityVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 8); } - public static void addLeadLocations(FlatBufferBuilder builder, int leadLocationsOffset) { builder.addOffset(6, leadLocationsOffset, 0); } - public static void addLeadAmounts(FlatBufferBuilder builder, int leadAmountsOffset) { builder.addOffset(7, leadAmountsOffset, 0); } - public static int createLeadAmountsVector(FlatBufferBuilder builder, double[] data) { builder.startVector(8, data.length, 8); for (int i = data.length - 1; i >= 0; i--) builder.addDouble(data[i]); return builder.endVector(); } - public static void startLeadAmountsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 8); } + public static void addSymmetry(FlatBufferBuilder builder, int symmetry) { builder.addInt(3, symmetry, 0); } + public static void addBodies(FlatBufferBuilder builder, int bodiesOffset) { builder.addOffset(4, bodiesOffset, 0); } + public static void addRandomSeed(FlatBufferBuilder builder, int randomSeed) { builder.addInt(5, randomSeed, 0); } + public static void addRubble(FlatBufferBuilder builder, int rubbleOffset) { builder.addOffset(6, rubbleOffset, 0); } + public static int createRubbleVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startRubbleVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addLead(FlatBufferBuilder builder, int leadOffset) { builder.addOffset(7, leadOffset, 0); } + public static int createLeadVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startLeadVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addAnomalies(FlatBufferBuilder builder, int anomaliesOffset) { builder.addOffset(8, anomaliesOffset, 0); } + public static int createAnomaliesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startAnomaliesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addAnomalyRounds(FlatBufferBuilder builder, int anomalyRoundsOffset) { builder.addOffset(9, anomalyRoundsOffset, 0); } + public static int createAnomalyRoundsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startAnomalyRoundsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endGameMap(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public GameMap get(int j) { return get(new GameMap(), j); } - public GameMap get(GameMap obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/GameWrapper.java b/schema/java/battlecode/schema/GameWrapper.java index 8067e8d1..25a0c03e 100644 --- a/schema/java/battlecode/schema/GameWrapper.java +++ b/schema/java/battlecode/schema/GameWrapper.java @@ -7,6 +7,7 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * If events are not otherwise delimited, this wrapper structure * allows a game to be stored in a single buffer. @@ -15,29 +16,23 @@ * corresponding to matchFooters[0]. These indices allow quick traversal of * the file. */ -@SuppressWarnings("unused") public final class GameWrapper extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static GameWrapper getRootAsGameWrapper(ByteBuffer _bb) { return getRootAsGameWrapper(_bb, new GameWrapper()); } public static GameWrapper getRootAsGameWrapper(ByteBuffer _bb, GameWrapper obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public GameWrapper __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** * The series of events comprising the game. */ - public battlecode.schema.EventWrapper events(int j) { return events(new battlecode.schema.EventWrapper(), j); } - public battlecode.schema.EventWrapper events(battlecode.schema.EventWrapper obj, int j) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public EventWrapper events(int j) { return events(new EventWrapper(), j); } + public EventWrapper events(EventWrapper obj, int j) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int eventsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } - public battlecode.schema.EventWrapper.Vector eventsVector() { return eventsVector(new battlecode.schema.EventWrapper.Vector()); } - public battlecode.schema.EventWrapper.Vector eventsVector(battlecode.schema.EventWrapper.Vector obj) { int o = __offset(4); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } /** * The indices of the headers of the matches, in order. */ public int matchHeaders(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int matchHeadersLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public IntVector matchHeadersVector() { return matchHeadersVector(new IntVector()); } - public IntVector matchHeadersVector(IntVector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer matchHeadersAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } public ByteBuffer matchHeadersInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } /** @@ -45,8 +40,6 @@ public final class GameWrapper extends Table { */ public int matchFooters(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int matchFootersLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } - public IntVector matchFootersVector() { return matchFootersVector(new IntVector()); } - public IntVector matchFootersVector(IntVector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer matchFootersAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } public ByteBuffer matchFootersInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } @@ -54,14 +47,14 @@ public static int createGameWrapper(FlatBufferBuilder builder, int eventsOffset, int matchHeadersOffset, int matchFootersOffset) { - builder.startTable(3); + builder.startObject(3); GameWrapper.addMatchFooters(builder, matchFootersOffset); GameWrapper.addMatchHeaders(builder, matchHeadersOffset); GameWrapper.addEvents(builder, eventsOffset); return GameWrapper.endGameWrapper(builder); } - public static void startGameWrapper(FlatBufferBuilder builder) { builder.startTable(3); } + public static void startGameWrapper(FlatBufferBuilder builder) { builder.startObject(3); } public static void addEvents(FlatBufferBuilder builder, int eventsOffset) { builder.addOffset(0, eventsOffset, 0); } public static int createEventsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } public static void startEventsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -72,15 +65,8 @@ public static int createGameWrapper(FlatBufferBuilder builder, public static int createMatchFootersVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startMatchFootersVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endGameWrapper(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public GameWrapper get(int j) { return get(new GameWrapper(), j); } - public GameWrapper get(GameWrapper obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/MatchFooter.java b/schema/java/battlecode/schema/MatchFooter.java index 962821a6..8777c9ea 100644 --- a/schema/java/battlecode/schema/MatchFooter.java +++ b/schema/java/battlecode/schema/MatchFooter.java @@ -7,15 +7,14 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * Sent to end a match. */ -@SuppressWarnings("unused") public final class MatchFooter extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static MatchFooter getRootAsMatchFooter(ByteBuffer _bb) { return getRootAsMatchFooter(_bb, new MatchFooter()); } public static MatchFooter getRootAsMatchFooter(ByteBuffer _bb, MatchFooter obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public MatchFooter __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -29,39 +28,30 @@ public final class MatchFooter extends Table { /** * Profiler data for team A and B if profiling is enabled. */ - public battlecode.schema.ProfilerFile profilerFiles(int j) { return profilerFiles(new battlecode.schema.ProfilerFile(), j); } - public battlecode.schema.ProfilerFile profilerFiles(battlecode.schema.ProfilerFile obj, int j) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public ProfilerFile profilerFiles(int j) { return profilerFiles(new ProfilerFile(), j); } + public ProfilerFile profilerFiles(ProfilerFile obj, int j) { int o = __offset(8); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int profilerFilesLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } - public battlecode.schema.ProfilerFile.Vector profilerFilesVector() { return profilerFilesVector(new battlecode.schema.ProfilerFile.Vector()); } - public battlecode.schema.ProfilerFile.Vector profilerFilesVector(battlecode.schema.ProfilerFile.Vector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } public static int createMatchFooter(FlatBufferBuilder builder, byte winner, int totalRounds, int profilerFilesOffset) { - builder.startTable(3); + builder.startObject(3); MatchFooter.addProfilerFiles(builder, profilerFilesOffset); MatchFooter.addTotalRounds(builder, totalRounds); MatchFooter.addWinner(builder, winner); return MatchFooter.endMatchFooter(builder); } - public static void startMatchFooter(FlatBufferBuilder builder) { builder.startTable(3); } + public static void startMatchFooter(FlatBufferBuilder builder) { builder.startObject(3); } public static void addWinner(FlatBufferBuilder builder, byte winner) { builder.addByte(0, winner, 0); } public static void addTotalRounds(FlatBufferBuilder builder, int totalRounds) { builder.addInt(1, totalRounds, 0); } public static void addProfilerFiles(FlatBufferBuilder builder, int profilerFilesOffset) { builder.addOffset(2, profilerFilesOffset, 0); } public static int createProfilerFilesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } public static void startProfilerFilesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endMatchFooter(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public MatchFooter get(int j) { return get(new MatchFooter(), j); } - public MatchFooter get(MatchFooter obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/MatchHeader.java b/schema/java/battlecode/schema/MatchHeader.java index e2e2b042..b167ea98 100644 --- a/schema/java/battlecode/schema/MatchHeader.java +++ b/schema/java/battlecode/schema/MatchHeader.java @@ -7,22 +7,21 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * Sent to start a match. */ -@SuppressWarnings("unused") public final class MatchHeader extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static MatchHeader getRootAsMatchHeader(ByteBuffer _bb) { return getRootAsMatchHeader(_bb, new MatchHeader()); } public static MatchHeader getRootAsMatchHeader(ByteBuffer _bb, MatchHeader obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public MatchHeader __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** * The map the match was played on. */ - public battlecode.schema.GameMap map() { return map(new battlecode.schema.GameMap()); } - public battlecode.schema.GameMap map(battlecode.schema.GameMap obj) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public GameMap map() { return map(new GameMap()); } + public GameMap map(GameMap obj) { int o = __offset(4); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The maximum number of rounds in this match. */ @@ -31,25 +30,18 @@ public final class MatchHeader extends Table { public static int createMatchHeader(FlatBufferBuilder builder, int mapOffset, int maxRounds) { - builder.startTable(2); + builder.startObject(2); MatchHeader.addMaxRounds(builder, maxRounds); MatchHeader.addMap(builder, mapOffset); return MatchHeader.endMatchHeader(builder); } - public static void startMatchHeader(FlatBufferBuilder builder) { builder.startTable(2); } + public static void startMatchHeader(FlatBufferBuilder builder) { builder.startObject(2); } public static void addMap(FlatBufferBuilder builder, int mapOffset) { builder.addOffset(0, mapOffset, 0); } public static void addMaxRounds(FlatBufferBuilder builder, int maxRounds) { builder.addInt(1, maxRounds, 0); } public static int endMatchHeader(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public MatchHeader get(int j) { return get(new MatchHeader(), j); } - public MatchHeader get(MatchHeader obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/ProfilerEvent.java b/schema/java/battlecode/schema/ProfilerEvent.java index 11941e62..58c47f12 100644 --- a/schema/java/battlecode/schema/ProfilerEvent.java +++ b/schema/java/battlecode/schema/ProfilerEvent.java @@ -7,6 +7,7 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * These tables are set-up so that they match closely with speedscope's file format documented at * https://github.com/jlfwong/speedscope/wiki/Importing-from-custom-sources. @@ -14,12 +15,10 @@ * A single event in a profile. Represents either an open event (meaning a * method has been entered) or a close event (meaning the method was exited). */ -@SuppressWarnings("unused") public final class ProfilerEvent extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static ProfilerEvent getRootAsProfilerEvent(ByteBuffer _bb) { return getRootAsProfilerEvent(_bb, new ProfilerEvent()); } public static ProfilerEvent getRootAsProfilerEvent(ByteBuffer _bb, ProfilerEvent obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public ProfilerEvent __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -39,27 +38,20 @@ public static int createProfilerEvent(FlatBufferBuilder builder, boolean isOpen, int at, int frame) { - builder.startTable(3); + builder.startObject(3); ProfilerEvent.addFrame(builder, frame); ProfilerEvent.addAt(builder, at); ProfilerEvent.addIsOpen(builder, isOpen); return ProfilerEvent.endProfilerEvent(builder); } - public static void startProfilerEvent(FlatBufferBuilder builder) { builder.startTable(3); } + public static void startProfilerEvent(FlatBufferBuilder builder) { builder.startObject(3); } public static void addIsOpen(FlatBufferBuilder builder, boolean isOpen) { builder.addBoolean(0, isOpen, false); } public static void addAt(FlatBufferBuilder builder, int at) { builder.addInt(1, at, 0); } public static void addFrame(FlatBufferBuilder builder, int frame) { builder.addInt(2, frame, 0); } public static int endProfilerEvent(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public ProfilerEvent get(int j) { return get(new ProfilerEvent(), j); } - public ProfilerEvent get(ProfilerEvent obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/ProfilerFile.java b/schema/java/battlecode/schema/ProfilerFile.java index ff535bfe..c101925d 100644 --- a/schema/java/battlecode/schema/ProfilerFile.java +++ b/schema/java/battlecode/schema/ProfilerFile.java @@ -7,16 +7,15 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * A profiler file is a collection of profiles. * When profiling is enabled there is one of these per team per match. */ -@SuppressWarnings("unused") public final class ProfilerFile extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static ProfilerFile getRootAsProfilerFile(ByteBuffer _bb) { return getRootAsProfilerFile(_bb, new ProfilerFile()); } public static ProfilerFile getRootAsProfilerFile(ByteBuffer _bb, ProfilerFile obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public ProfilerFile __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -24,27 +23,23 @@ public final class ProfilerFile extends Table { */ public String frames(int j) { int o = __offset(4); return o != 0 ? __string(__vector(o) + j * 4) : null; } public int framesLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } - public StringVector framesVector() { return framesVector(new StringVector()); } - public StringVector framesVector(StringVector obj) { int o = __offset(4); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } /** * The recorded profiles, one per robot. */ - public battlecode.schema.ProfilerProfile profiles(int j) { return profiles(new battlecode.schema.ProfilerProfile(), j); } - public battlecode.schema.ProfilerProfile profiles(battlecode.schema.ProfilerProfile obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public ProfilerProfile profiles(int j) { return profiles(new ProfilerProfile(), j); } + public ProfilerProfile profiles(ProfilerProfile obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int profilesLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public battlecode.schema.ProfilerProfile.Vector profilesVector() { return profilesVector(new battlecode.schema.ProfilerProfile.Vector()); } - public battlecode.schema.ProfilerProfile.Vector profilesVector(battlecode.schema.ProfilerProfile.Vector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } public static int createProfilerFile(FlatBufferBuilder builder, int framesOffset, int profilesOffset) { - builder.startTable(2); + builder.startObject(2); ProfilerFile.addProfiles(builder, profilesOffset); ProfilerFile.addFrames(builder, framesOffset); return ProfilerFile.endProfilerFile(builder); } - public static void startProfilerFile(FlatBufferBuilder builder) { builder.startTable(2); } + public static void startProfilerFile(FlatBufferBuilder builder) { builder.startObject(2); } public static void addFrames(FlatBufferBuilder builder, int framesOffset) { builder.addOffset(0, framesOffset, 0); } public static int createFramesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } public static void startFramesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -52,15 +47,8 @@ public static int createProfilerFile(FlatBufferBuilder builder, public static int createProfilesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } public static void startProfilesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endProfilerFile(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public ProfilerFile get(int j) { return get(new ProfilerFile(), j); } - public ProfilerFile get(ProfilerFile obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/ProfilerProfile.java b/schema/java/battlecode/schema/ProfilerProfile.java index 3e711644..15312ead 100644 --- a/schema/java/battlecode/schema/ProfilerProfile.java +++ b/schema/java/battlecode/schema/ProfilerProfile.java @@ -7,15 +7,14 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * A profile contains all events and is labeled with a name. */ -@SuppressWarnings("unused") public final class ProfilerProfile extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static ProfilerProfile getRootAsProfilerProfile(ByteBuffer _bb) { return getRootAsProfilerProfile(_bb, new ProfilerProfile()); } public static ProfilerProfile getRootAsProfilerProfile(ByteBuffer _bb, ProfilerProfile obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public ProfilerProfile __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -27,36 +26,27 @@ public final class ProfilerProfile extends Table { /** * The events that occurred in the profile. */ - public battlecode.schema.ProfilerEvent events(int j) { return events(new battlecode.schema.ProfilerEvent(), j); } - public battlecode.schema.ProfilerEvent events(battlecode.schema.ProfilerEvent obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } + public ProfilerEvent events(int j) { return events(new ProfilerEvent(), j); } + public ProfilerEvent events(ProfilerEvent obj, int j) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; } public int eventsLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public battlecode.schema.ProfilerEvent.Vector eventsVector() { return eventsVector(new battlecode.schema.ProfilerEvent.Vector()); } - public battlecode.schema.ProfilerEvent.Vector eventsVector(battlecode.schema.ProfilerEvent.Vector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } public static int createProfilerProfile(FlatBufferBuilder builder, int nameOffset, int eventsOffset) { - builder.startTable(2); + builder.startObject(2); ProfilerProfile.addEvents(builder, eventsOffset); ProfilerProfile.addName(builder, nameOffset); return ProfilerProfile.endProfilerProfile(builder); } - public static void startProfilerProfile(FlatBufferBuilder builder) { builder.startTable(2); } + public static void startProfilerProfile(FlatBufferBuilder builder) { builder.startObject(2); } public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } public static void addEvents(FlatBufferBuilder builder, int eventsOffset) { builder.addOffset(1, eventsOffset, 0); } public static int createEventsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } public static void startEventsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endProfilerProfile(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public ProfilerProfile get(int j) { return get(new ProfilerProfile(), j); } - public ProfilerProfile get(ProfilerProfile obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/RGBTable.java b/schema/java/battlecode/schema/RGBTable.java index 6b59668a..6164af79 100644 --- a/schema/java/battlecode/schema/RGBTable.java +++ b/schema/java/battlecode/schema/RGBTable.java @@ -7,33 +7,26 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * A table of RGB values. */ -@SuppressWarnings("unused") public final class RGBTable extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static RGBTable getRootAsRGBTable(ByteBuffer _bb) { return getRootAsRGBTable(_bb, new RGBTable()); } public static RGBTable getRootAsRGBTable(ByteBuffer _bb, RGBTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public RGBTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public int red(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int redLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } - public IntVector redVector() { return redVector(new IntVector()); } - public IntVector redVector(IntVector obj) { int o = __offset(4); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer redAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } public ByteBuffer redInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } public int green(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int greenLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public IntVector greenVector() { return greenVector(new IntVector()); } - public IntVector greenVector(IntVector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer greenAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } public ByteBuffer greenInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } public int blue(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int blueLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } - public IntVector blueVector() { return blueVector(new IntVector()); } - public IntVector blueVector(IntVector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer blueAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } public ByteBuffer blueInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } @@ -41,14 +34,14 @@ public static int createRGBTable(FlatBufferBuilder builder, int redOffset, int greenOffset, int blueOffset) { - builder.startTable(3); + builder.startObject(3); RGBTable.addBlue(builder, blueOffset); RGBTable.addGreen(builder, greenOffset); RGBTable.addRed(builder, redOffset); return RGBTable.endRGBTable(builder); } - public static void startRGBTable(FlatBufferBuilder builder) { builder.startTable(3); } + public static void startRGBTable(FlatBufferBuilder builder) { builder.startObject(3); } public static void addRed(FlatBufferBuilder builder, int redOffset) { builder.addOffset(0, redOffset, 0); } public static int createRedVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startRedVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -59,15 +52,8 @@ public static int createRGBTable(FlatBufferBuilder builder, public static int createBlueVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startBlueVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endRGBTable(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public RGBTable get(int j) { return get(new RGBTable(), j); } - public RGBTable get(RGBTable obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/Round.java b/schema/java/battlecode/schema/Round.java index 33c4d08f..b7295a4e 100644 --- a/schema/java/battlecode/schema/Round.java +++ b/schema/java/battlecode/schema/Round.java @@ -7,18 +7,17 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * A single time-step in a Game. * The bulk of the data in the file is stored in tables like this. * Note that a struct-of-arrays format is more space efficient than an array- * of-structs. */ -@SuppressWarnings("unused") public final class Round extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static Round getRootAsRound(ByteBuffer _bb) { return getRootAsRound(_bb, new Round()); } public static Round getRootAsRound(ByteBuffer _bb, Round obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public Round __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -26,48 +25,44 @@ public final class Round extends Table { */ public int teamIDs(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int teamIDsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } - public IntVector teamIDsVector() { return teamIDsVector(new IntVector()); } - public IntVector teamIDsVector(IntVector obj) { int o = __offset(4); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer teamIDsAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } public ByteBuffer teamIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } - public int teamLeadChange(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int teamLeadChangeLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public IntVector teamLeadChangeVector() { return teamLeadChangeVector(new IntVector()); } - public IntVector teamLeadChangeVector(IntVector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer teamLeadChangeAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } - public ByteBuffer teamLeadChangeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } - public int teamGoldChange(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int teamGoldChangeLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } - public IntVector teamGoldChangeVector() { return teamGoldChangeVector(new IntVector()); } - public IntVector teamGoldChangeVector(IntVector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer teamGoldChangeAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } - public ByteBuffer teamGoldChangeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } + /** + * The total amount of lead change of this team, this round + */ + public int teamLeadChanges(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamLeadChangesLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamLeadChangesAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } + public ByteBuffer teamLeadChangesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } + /** + * The total amount of gold change of this team, this round + */ + public int teamGoldChanges(int j) { int o = __offset(8); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int teamGoldChangesLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer teamGoldChangesAsByteBuffer() { return __vector_as_bytebuffer(8, 4); } + public ByteBuffer teamGoldChangesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 4); } /** * The IDs of bodies that moved. */ public int movedIDs(int j) { int o = __offset(10); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int movedIDsLength() { int o = __offset(10); return o != 0 ? __vector_len(o) : 0; } - public IntVector movedIDsVector() { return movedIDsVector(new IntVector()); } - public IntVector movedIDsVector(IntVector obj) { int o = __offset(10); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer movedIDsAsByteBuffer() { return __vector_as_bytebuffer(10, 4); } public ByteBuffer movedIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 10, 4); } /** * The new locations of bodies that have moved. */ - public battlecode.schema.VecTable movedLocs() { return movedLocs(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable movedLocs(battlecode.schema.VecTable obj) { int o = __offset(12); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable movedLocs() { return movedLocs(new VecTable()); } + public VecTable movedLocs(VecTable obj) { int o = __offset(12); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * New bodies. */ - public battlecode.schema.SpawnedBodyTable spawnedBodies() { return spawnedBodies(new battlecode.schema.SpawnedBodyTable()); } - public battlecode.schema.SpawnedBodyTable spawnedBodies(battlecode.schema.SpawnedBodyTable obj) { int o = __offset(14); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public SpawnedBodyTable spawnedBodies() { return spawnedBodies(new SpawnedBodyTable()); } + public SpawnedBodyTable spawnedBodies(SpawnedBodyTable obj) { int o = __offset(14); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The IDs of bodies that died. */ public int diedIDs(int j) { int o = __offset(16); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int diedIDsLength() { int o = __offset(16); return o != 0 ? __vector_len(o) : 0; } - public IntVector diedIDsVector() { return diedIDsVector(new IntVector()); } - public IntVector diedIDsVector(IntVector obj) { int o = __offset(16); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer diedIDsAsByteBuffer() { return __vector_as_bytebuffer(16, 4); } public ByteBuffer diedIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 16, 4); } /** @@ -76,8 +71,6 @@ public final class Round extends Table { */ public int actionIDs(int j) { int o = __offset(18); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int actionIDsLength() { int o = __offset(18); return o != 0 ? __vector_len(o) : 0; } - public IntVector actionIDsVector() { return actionIDsVector(new IntVector()); } - public IntVector actionIDsVector(IntVector obj) { int o = __offset(18); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer actionIDsAsByteBuffer() { return __vector_as_bytebuffer(18, 4); } public ByteBuffer actionIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 18, 4); } /** @@ -85,8 +78,6 @@ public final class Round extends Table { */ public byte actions(int j) { int o = __offset(20); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } public int actionsLength() { int o = __offset(20); return o != 0 ? __vector_len(o) : 0; } - public ByteVector actionsVector() { return actionsVector(new ByteVector()); } - public ByteVector actionsVector(ByteVector obj) { int o = __offset(20); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer actionsAsByteBuffer() { return __vector_as_bytebuffer(20, 1); } public ByteBuffer actionsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 20, 1); } /** @@ -94,85 +85,83 @@ public final class Round extends Table { */ public int actionTargets(int j) { int o = __offset(22); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int actionTargetsLength() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } - public IntVector actionTargetsVector() { return actionTargetsVector(new IntVector()); } - public IntVector actionTargetsVector(IntVector obj) { int o = __offset(22); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer actionTargetsAsByteBuffer() { return __vector_as_bytebuffer(22, 4); } public ByteBuffer actionTargetsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 22, 4); } + /** + * The locations of lead drops + */ + public VecTable leadDropLocations() { return leadDropLocations(new VecTable()); } + public VecTable leadDropLocations(VecTable obj) { int o = __offset(24); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The amount of lead dropped at each location + */ + public int leadDropValues(int j) { int o = __offset(26); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int leadDropValuesLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer leadDropValuesAsByteBuffer() { return __vector_as_bytebuffer(26, 4); } + public ByteBuffer leadDropValuesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 26, 4); } + /** + * The locations of gold drops + */ + public VecTable goldDropLocations() { return goldDropLocations(new VecTable()); } + public VecTable goldDropLocations(VecTable obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + /** + * The amount of gold dropped at each location + */ + public int goldDropValues(int j) { int o = __offset(30); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int goldDropValuesLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer goldDropValuesAsByteBuffer() { return __vector_as_bytebuffer(30, 4); } + public ByteBuffer goldDropValuesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 30, 4); } /** * The IDs of the robots who changed their indicator strings */ - public int indicatorStringIDs(int j) { int o = __offset(24); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int indicatorStringIDsLength() { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } - public IntVector indicatorStringIDsVector() { return indicatorStringIDsVector(new IntVector()); } - public IntVector indicatorStringIDsVector(IntVector obj) { int o = __offset(24); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer indicatorStringIDsAsByteBuffer() { return __vector_as_bytebuffer(24, 4); } - public ByteBuffer indicatorStringIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 24, 4); } + public int indicatorStringIDs(int j) { int o = __offset(32); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } + public int indicatorStringIDsLength() { int o = __offset(32); return o != 0 ? __vector_len(o) : 0; } + public ByteBuffer indicatorStringIDsAsByteBuffer() { return __vector_as_bytebuffer(32, 4); } + public ByteBuffer indicatorStringIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 32, 4); } /** * The messages of the robots who changed their indicator strings */ - public String indicatorStrings(int j) { int o = __offset(26); return o != 0 ? __string(__vector(o) + j * 4) : null; } - public int indicatorStringsLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; } - public StringVector indicatorStringsVector() { return indicatorStringsVector(new StringVector()); } - public StringVector indicatorStringsVector(StringVector obj) { int o = __offset(26); return o != 0 ? obj.__assign(__vector(o), 4, bb) : null; } - public battlecode.schema.VecTable leadDropLocations() { return leadDropLocations(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable leadDropLocations(battlecode.schema.VecTable obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } - public int leadDropValues(int j) { int o = __offset(30); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int leadDropValuesLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } - public IntVector leadDropValuesVector() { return leadDropValuesVector(new IntVector()); } - public IntVector leadDropValuesVector(IntVector obj) { int o = __offset(30); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer leadDropValuesAsByteBuffer() { return __vector_as_bytebuffer(30, 4); } - public ByteBuffer leadDropValuesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 30, 4); } - public battlecode.schema.VecTable goldDropLocations() { return goldDropLocations(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable goldDropLocations(battlecode.schema.VecTable obj) { int o = __offset(32); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } - public int goldDropValues(int j) { int o = __offset(34); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } - public int goldDropValuesLength() { int o = __offset(34); return o != 0 ? __vector_len(o) : 0; } - public IntVector goldDropValuesVector() { return goldDropValuesVector(new IntVector()); } - public IntVector goldDropValuesVector(IntVector obj) { int o = __offset(34); return o != 0 ? obj.__assign(__vector(o), bb) : null; } - public ByteBuffer goldDropValuesAsByteBuffer() { return __vector_as_bytebuffer(34, 4); } - public ByteBuffer goldDropValuesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 34, 4); } + public String indicatorStrings(int j) { int o = __offset(34); return o != 0 ? __string(__vector(o) + j * 4) : null; } + public int indicatorStringsLength() { int o = __offset(34); return o != 0 ? __vector_len(o) : 0; } /** * The IDs of bodies that set indicator dots */ public int indicatorDotIDs(int j) { int o = __offset(36); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int indicatorDotIDsLength() { int o = __offset(36); return o != 0 ? __vector_len(o) : 0; } - public IntVector indicatorDotIDsVector() { return indicatorDotIDsVector(new IntVector()); } - public IntVector indicatorDotIDsVector(IntVector obj) { int o = __offset(36); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer indicatorDotIDsAsByteBuffer() { return __vector_as_bytebuffer(36, 4); } public ByteBuffer indicatorDotIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 36, 4); } /** * The location of the indicator dots */ - public battlecode.schema.VecTable indicatorDotLocs() { return indicatorDotLocs(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable indicatorDotLocs(battlecode.schema.VecTable obj) { int o = __offset(38); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable indicatorDotLocs() { return indicatorDotLocs(new VecTable()); } + public VecTable indicatorDotLocs(VecTable obj) { int o = __offset(38); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The RGB values of the indicator dots */ - public battlecode.schema.RGBTable indicatorDotRGBs() { return indicatorDotRGBs(new battlecode.schema.RGBTable()); } - public battlecode.schema.RGBTable indicatorDotRGBs(battlecode.schema.RGBTable obj) { int o = __offset(40); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public RGBTable indicatorDotRGBs() { return indicatorDotRGBs(new RGBTable()); } + public RGBTable indicatorDotRGBs(RGBTable obj) { int o = __offset(40); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The IDs of bodies that set indicator lines */ public int indicatorLineIDs(int j) { int o = __offset(42); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int indicatorLineIDsLength() { int o = __offset(42); return o != 0 ? __vector_len(o) : 0; } - public IntVector indicatorLineIDsVector() { return indicatorLineIDsVector(new IntVector()); } - public IntVector indicatorLineIDsVector(IntVector obj) { int o = __offset(42); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer indicatorLineIDsAsByteBuffer() { return __vector_as_bytebuffer(42, 4); } public ByteBuffer indicatorLineIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 42, 4); } /** * The start location of the indicator lines */ - public battlecode.schema.VecTable indicatorLineStartLocs() { return indicatorLineStartLocs(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable indicatorLineStartLocs(battlecode.schema.VecTable obj) { int o = __offset(44); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable indicatorLineStartLocs() { return indicatorLineStartLocs(new VecTable()); } + public VecTable indicatorLineStartLocs(VecTable obj) { int o = __offset(44); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The end location of the indicator lines */ - public battlecode.schema.VecTable indicatorLineEndLocs() { return indicatorLineEndLocs(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable indicatorLineEndLocs(battlecode.schema.VecTable obj) { int o = __offset(46); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable indicatorLineEndLocs() { return indicatorLineEndLocs(new VecTable()); } + public VecTable indicatorLineEndLocs(VecTable obj) { int o = __offset(46); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The RGB values of the indicator lines */ - public battlecode.schema.RGBTable indicatorLineRGBs() { return indicatorLineRGBs(new battlecode.schema.RGBTable()); } - public battlecode.schema.RGBTable indicatorLineRGBs(battlecode.schema.RGBTable obj) { int o = __offset(48); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public RGBTable indicatorLineRGBs() { return indicatorLineRGBs(new RGBTable()); } + public RGBTable indicatorLineRGBs(RGBTable obj) { int o = __offset(48); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } /** * The first sent Round in a match should have index 1. (The starting state, * created by the MatchHeader, can be thought to have index 0.) @@ -184,8 +173,6 @@ public final class Round extends Table { */ public int bytecodeIDs(int j) { int o = __offset(52); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int bytecodeIDsLength() { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } - public IntVector bytecodeIDsVector() { return bytecodeIDsVector(new IntVector()); } - public IntVector bytecodeIDsVector(IntVector obj) { int o = __offset(52); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer bytecodeIDsAsByteBuffer() { return __vector_as_bytebuffer(52, 4); } public ByteBuffer bytecodeIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 52, 4); } /** @@ -193,15 +180,13 @@ public final class Round extends Table { */ public int bytecodesUsed(int j) { int o = __offset(54); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int bytecodesUsedLength() { int o = __offset(54); return o != 0 ? __vector_len(o) : 0; } - public IntVector bytecodesUsedVector() { return bytecodesUsedVector(new IntVector()); } - public IntVector bytecodesUsedVector(IntVector obj) { int o = __offset(54); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer bytecodesUsedAsByteBuffer() { return __vector_as_bytebuffer(54, 4); } public ByteBuffer bytecodesUsedInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 54, 4); } public static int createRound(FlatBufferBuilder builder, int teamIDsOffset, - int teamLeadChangeOffset, - int teamGoldChangeOffset, + int teamLeadChangesOffset, + int teamGoldChangesOffset, int movedIDsOffset, int movedLocsOffset, int spawnedBodiesOffset, @@ -209,12 +194,12 @@ public static int createRound(FlatBufferBuilder builder, int actionIDsOffset, int actionsOffset, int actionTargetsOffset, - int indicatorStringIDsOffset, - int indicatorStringsOffset, int leadDropLocationsOffset, int leadDropValuesOffset, int goldDropLocationsOffset, int goldDropValuesOffset, + int indicatorStringIDsOffset, + int indicatorStringsOffset, int indicatorDotIDsOffset, int indicatorDotLocsOffset, int indicatorDotRGBsOffset, @@ -225,7 +210,7 @@ public static int createRound(FlatBufferBuilder builder, int roundID, int bytecodeIDsOffset, int bytecodesUsedOffset) { - builder.startTable(26); + builder.startObject(26); Round.addBytecodesUsed(builder, bytecodesUsedOffset); Round.addBytecodeIDs(builder, bytecodeIDsOffset); Round.addRoundID(builder, roundID); @@ -236,12 +221,12 @@ public static int createRound(FlatBufferBuilder builder, Round.addIndicatorDotRGBs(builder, indicatorDotRGBsOffset); Round.addIndicatorDotLocs(builder, indicatorDotLocsOffset); Round.addIndicatorDotIDs(builder, indicatorDotIDsOffset); + Round.addIndicatorStrings(builder, indicatorStringsOffset); + Round.addIndicatorStringIDs(builder, indicatorStringIDsOffset); Round.addGoldDropValues(builder, goldDropValuesOffset); Round.addGoldDropLocations(builder, goldDropLocationsOffset); Round.addLeadDropValues(builder, leadDropValuesOffset); Round.addLeadDropLocations(builder, leadDropLocationsOffset); - Round.addIndicatorStrings(builder, indicatorStringsOffset); - Round.addIndicatorStringIDs(builder, indicatorStringIDsOffset); Round.addActionTargets(builder, actionTargetsOffset); Round.addActions(builder, actionsOffset); Round.addActionIDs(builder, actionIDsOffset); @@ -249,22 +234,22 @@ public static int createRound(FlatBufferBuilder builder, Round.addSpawnedBodies(builder, spawnedBodiesOffset); Round.addMovedLocs(builder, movedLocsOffset); Round.addMovedIDs(builder, movedIDsOffset); - Round.addTeamGoldChange(builder, teamGoldChangeOffset); - Round.addTeamLeadChange(builder, teamLeadChangeOffset); + Round.addTeamGoldChanges(builder, teamGoldChangesOffset); + Round.addTeamLeadChanges(builder, teamLeadChangesOffset); Round.addTeamIDs(builder, teamIDsOffset); return Round.endRound(builder); } - public static void startRound(FlatBufferBuilder builder) { builder.startTable(26); } + public static void startRound(FlatBufferBuilder builder) { builder.startObject(26); } public static void addTeamIDs(FlatBufferBuilder builder, int teamIDsOffset) { builder.addOffset(0, teamIDsOffset, 0); } public static int createTeamIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startTeamIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addTeamLeadChange(FlatBufferBuilder builder, int teamLeadChangeOffset) { builder.addOffset(1, teamLeadChangeOffset, 0); } - public static int createTeamLeadChangeVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startTeamLeadChangeVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addTeamGoldChange(FlatBufferBuilder builder, int teamGoldChangeOffset) { builder.addOffset(2, teamGoldChangeOffset, 0); } - public static int createTeamGoldChangeVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startTeamGoldChangeVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamLeadChanges(FlatBufferBuilder builder, int teamLeadChangesOffset) { builder.addOffset(1, teamLeadChangesOffset, 0); } + public static int createTeamLeadChangesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamLeadChangesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addTeamGoldChanges(FlatBufferBuilder builder, int teamGoldChangesOffset) { builder.addOffset(2, teamGoldChangesOffset, 0); } + public static int createTeamGoldChangesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startTeamGoldChangesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static void addMovedIDs(FlatBufferBuilder builder, int movedIDsOffset) { builder.addOffset(3, movedIDsOffset, 0); } public static int createMovedIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startMovedIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -277,26 +262,25 @@ public static int createRound(FlatBufferBuilder builder, public static int createActionIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startActionIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static void addActions(FlatBufferBuilder builder, int actionsOffset) { builder.addOffset(8, actionsOffset, 0); } - public static int createActionsVector(FlatBufferBuilder builder, byte[] data) { return builder.createByteVector(data); } - public static int createActionsVector(FlatBufferBuilder builder, ByteBuffer data) { return builder.createByteVector(data); } + public static int createActionsVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } public static void startActionsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } public static void addActionTargets(FlatBufferBuilder builder, int actionTargetsOffset) { builder.addOffset(9, actionTargetsOffset, 0); } public static int createActionTargetsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startActionTargetsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addIndicatorStringIDs(FlatBufferBuilder builder, int indicatorStringIDsOffset) { builder.addOffset(10, indicatorStringIDsOffset, 0); } - public static int createIndicatorStringIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } - public static void startIndicatorStringIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addIndicatorStrings(FlatBufferBuilder builder, int indicatorStringsOffset) { builder.addOffset(11, indicatorStringsOffset, 0); } - public static int createIndicatorStringsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } - public static void startIndicatorStringsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addLeadDropLocations(FlatBufferBuilder builder, int leadDropLocationsOffset) { builder.addOffset(12, leadDropLocationsOffset, 0); } - public static void addLeadDropValues(FlatBufferBuilder builder, int leadDropValuesOffset) { builder.addOffset(13, leadDropValuesOffset, 0); } + public static void addLeadDropLocations(FlatBufferBuilder builder, int leadDropLocationsOffset) { builder.addOffset(10, leadDropLocationsOffset, 0); } + public static void addLeadDropValues(FlatBufferBuilder builder, int leadDropValuesOffset) { builder.addOffset(11, leadDropValuesOffset, 0); } public static int createLeadDropValuesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startLeadDropValuesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addGoldDropLocations(FlatBufferBuilder builder, int goldDropLocationsOffset) { builder.addOffset(14, goldDropLocationsOffset, 0); } - public static void addGoldDropValues(FlatBufferBuilder builder, int goldDropValuesOffset) { builder.addOffset(15, goldDropValuesOffset, 0); } + public static void addGoldDropLocations(FlatBufferBuilder builder, int goldDropLocationsOffset) { builder.addOffset(12, goldDropLocationsOffset, 0); } + public static void addGoldDropValues(FlatBufferBuilder builder, int goldDropValuesOffset) { builder.addOffset(13, goldDropValuesOffset, 0); } public static int createGoldDropValuesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startGoldDropValuesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorStringIDs(FlatBufferBuilder builder, int indicatorStringIDsOffset) { builder.addOffset(14, indicatorStringIDsOffset, 0); } + public static int createIndicatorStringIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } + public static void startIndicatorStringIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } + public static void addIndicatorStrings(FlatBufferBuilder builder, int indicatorStringsOffset) { builder.addOffset(15, indicatorStringsOffset, 0); } + public static int createIndicatorStringsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } + public static void startIndicatorStringsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static void addIndicatorDotIDs(FlatBufferBuilder builder, int indicatorDotIDsOffset) { builder.addOffset(16, indicatorDotIDsOffset, 0); } public static int createIndicatorDotIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startIndicatorDotIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -316,15 +300,8 @@ public static int createRound(FlatBufferBuilder builder, public static int createBytecodesUsedVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startBytecodesUsedVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endRound(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public Round get(int j) { return get(new Round(), j); } - public Round get(Round obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/SpawnedBodyTable.java b/schema/java/battlecode/schema/SpawnedBodyTable.java index c25bd19b..71bf66ec 100644 --- a/schema/java/battlecode/schema/SpawnedBodyTable.java +++ b/schema/java/battlecode/schema/SpawnedBodyTable.java @@ -7,15 +7,14 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * A list of new bodies to be placed on the map. */ -@SuppressWarnings("unused") public final class SpawnedBodyTable extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static SpawnedBodyTable getRootAsSpawnedBodyTable(ByteBuffer _bb) { return getRootAsSpawnedBodyTable(_bb, new SpawnedBodyTable()); } public static SpawnedBodyTable getRootAsSpawnedBodyTable(ByteBuffer _bb, SpawnedBodyTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public SpawnedBodyTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -27,8 +26,6 @@ public final class SpawnedBodyTable extends Table { */ public int robotIDs(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int robotIDsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } - public IntVector robotIDsVector() { return robotIDsVector(new IntVector()); } - public IntVector robotIDsVector(IntVector obj) { int o = __offset(4); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer robotIDsAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } public ByteBuffer robotIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } /** @@ -36,8 +33,6 @@ public final class SpawnedBodyTable extends Table { */ public byte teamIDs(int j) { int o = __offset(6); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } public int teamIDsLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public ByteVector teamIDsVector() { return teamIDsVector(new ByteVector()); } - public ByteVector teamIDsVector(ByteVector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer teamIDsAsByteBuffer() { return __vector_as_bytebuffer(6, 1); } public ByteBuffer teamIDsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 1); } /** @@ -45,22 +40,20 @@ public final class SpawnedBodyTable extends Table { */ public byte types(int j) { int o = __offset(8); return o != 0 ? bb.get(__vector(o) + j * 1) : 0; } public int typesLength() { int o = __offset(8); return o != 0 ? __vector_len(o) : 0; } - public ByteVector typesVector() { return typesVector(new ByteVector()); } - public ByteVector typesVector(ByteVector obj) { int o = __offset(8); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer typesAsByteBuffer() { return __vector_as_bytebuffer(8, 1); } public ByteBuffer typesInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); } /** * The locations of the bodies. */ - public battlecode.schema.VecTable locs() { return locs(new battlecode.schema.VecTable()); } - public battlecode.schema.VecTable locs(battlecode.schema.VecTable obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public VecTable locs() { return locs(new VecTable()); } + public VecTable locs(VecTable obj) { int o = __offset(10); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } public static int createSpawnedBodyTable(FlatBufferBuilder builder, int robotIDsOffset, int teamIDsOffset, int typesOffset, int locsOffset) { - builder.startTable(4); + builder.startObject(4); SpawnedBodyTable.addLocs(builder, locsOffset); SpawnedBodyTable.addTypes(builder, typesOffset); SpawnedBodyTable.addTeamIDs(builder, teamIDsOffset); @@ -68,29 +61,20 @@ public static int createSpawnedBodyTable(FlatBufferBuilder builder, return SpawnedBodyTable.endSpawnedBodyTable(builder); } - public static void startSpawnedBodyTable(FlatBufferBuilder builder) { builder.startTable(4); } + public static void startSpawnedBodyTable(FlatBufferBuilder builder) { builder.startObject(4); } public static void addRobotIDs(FlatBufferBuilder builder, int robotIDsOffset) { builder.addOffset(0, robotIDsOffset, 0); } public static int createRobotIDsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startRobotIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static void addTeamIDs(FlatBufferBuilder builder, int teamIDsOffset) { builder.addOffset(1, teamIDsOffset, 0); } - public static int createTeamIDsVector(FlatBufferBuilder builder, byte[] data) { return builder.createByteVector(data); } - public static int createTeamIDsVector(FlatBufferBuilder builder, ByteBuffer data) { return builder.createByteVector(data); } + public static int createTeamIDsVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } public static void startTeamIDsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } public static void addTypes(FlatBufferBuilder builder, int typesOffset) { builder.addOffset(2, typesOffset, 0); } - public static int createTypesVector(FlatBufferBuilder builder, byte[] data) { return builder.createByteVector(data); } - public static int createTypesVector(FlatBufferBuilder builder, ByteBuffer data) { return builder.createByteVector(data); } + public static int createTypesVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } public static void startTypesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } public static void addLocs(FlatBufferBuilder builder, int locsOffset) { builder.addOffset(3, locsOffset, 0); } public static int endSpawnedBodyTable(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public SpawnedBodyTable get(int j) { return get(new SpawnedBodyTable(), j); } - public SpawnedBodyTable get(SpawnedBodyTable obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/TeamData.java b/schema/java/battlecode/schema/TeamData.java index b8ce13c1..57e3e4db 100644 --- a/schema/java/battlecode/schema/TeamData.java +++ b/schema/java/battlecode/schema/TeamData.java @@ -7,15 +7,14 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * Data relevant to a particular team. */ -@SuppressWarnings("unused") public final class TeamData extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static TeamData getRootAsTeamData(ByteBuffer _bb) { return getRootAsTeamData(_bb, new TeamData()); } public static TeamData getRootAsTeamData(ByteBuffer _bb, TeamData obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public TeamData __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } /** @@ -39,27 +38,20 @@ public static int createTeamData(FlatBufferBuilder builder, int nameOffset, int packageNameOffset, byte teamID) { - builder.startTable(3); + builder.startObject(3); TeamData.addPackageName(builder, packageNameOffset); TeamData.addName(builder, nameOffset); TeamData.addTeamID(builder, teamID); return TeamData.endTeamData(builder); } - public static void startTeamData(FlatBufferBuilder builder) { builder.startTable(3); } + public static void startTeamData(FlatBufferBuilder builder) { builder.startObject(3); } public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(0, nameOffset, 0); } public static void addPackageName(FlatBufferBuilder builder, int packageNameOffset) { builder.addOffset(1, packageNameOffset, 0); } public static void addTeamID(FlatBufferBuilder builder, byte teamID) { builder.addByte(2, teamID, 0); } public static int endTeamData(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public TeamData get(int j) { return get(new TeamData(), j); } - public TeamData get(TeamData obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/java/battlecode/schema/Vec.java b/schema/java/battlecode/schema/Vec.java index d37153c2..a9cdcb68 100644 --- a/schema/java/battlecode/schema/Vec.java +++ b/schema/java/battlecode/schema/Vec.java @@ -7,13 +7,13 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * A vector in two-dimensional space. Discrete space, of course. * Defaults to the 0 vector. */ -@SuppressWarnings("unused") public final class Vec extends Struct { - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; } public Vec __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public int x() { return bb.getInt(bb_pos + 0); } @@ -25,12 +25,5 @@ public static int createVec(FlatBufferBuilder builder, int x, int y) { builder.putInt(x); return builder.offset(); } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public Vec get(int j) { return get(new Vec(), j); } - public Vec get(Vec obj, int j) { return obj.__assign(__element(j), bb); } - } } diff --git a/schema/java/battlecode/schema/VecTable.java b/schema/java/battlecode/schema/VecTable.java index 67da2579..82da91e7 100644 --- a/schema/java/battlecode/schema/VecTable.java +++ b/schema/java/battlecode/schema/VecTable.java @@ -7,40 +7,35 @@ import java.util.*; import com.google.flatbuffers.*; +@SuppressWarnings("unused") /** * A table of vectors. */ -@SuppressWarnings("unused") public final class VecTable extends Table { - public static void ValidateVersion() { Constants.FLATBUFFERS_2_0_0(); } public static VecTable getRootAsVecTable(ByteBuffer _bb) { return getRootAsVecTable(_bb, new VecTable()); } public static VecTable getRootAsVecTable(ByteBuffer _bb, VecTable obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public void __init(int _i, ByteBuffer _bb) { __reset(_i, _bb); } + public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; vtable_start = bb_pos - bb.getInt(bb_pos); vtable_size = bb.getShort(vtable_start); } public VecTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public int xs(int j) { int o = __offset(4); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int xsLength() { int o = __offset(4); return o != 0 ? __vector_len(o) : 0; } - public IntVector xsVector() { return xsVector(new IntVector()); } - public IntVector xsVector(IntVector obj) { int o = __offset(4); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer xsAsByteBuffer() { return __vector_as_bytebuffer(4, 4); } public ByteBuffer xsInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 4, 4); } public int ys(int j) { int o = __offset(6); return o != 0 ? bb.getInt(__vector(o) + j * 4) : 0; } public int ysLength() { int o = __offset(6); return o != 0 ? __vector_len(o) : 0; } - public IntVector ysVector() { return ysVector(new IntVector()); } - public IntVector ysVector(IntVector obj) { int o = __offset(6); return o != 0 ? obj.__assign(__vector(o), bb) : null; } public ByteBuffer ysAsByteBuffer() { return __vector_as_bytebuffer(6, 4); } public ByteBuffer ysInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 6, 4); } public static int createVecTable(FlatBufferBuilder builder, int xsOffset, int ysOffset) { - builder.startTable(2); + builder.startObject(2); VecTable.addYs(builder, ysOffset); VecTable.addXs(builder, xsOffset); return VecTable.endVecTable(builder); } - public static void startVecTable(FlatBufferBuilder builder) { builder.startTable(2); } + public static void startVecTable(FlatBufferBuilder builder) { builder.startObject(2); } public static void addXs(FlatBufferBuilder builder, int xsOffset) { builder.addOffset(0, xsOffset, 0); } public static int createXsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startXsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } @@ -48,15 +43,8 @@ public static int createVecTable(FlatBufferBuilder builder, public static int createYsVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addInt(data[i]); return builder.endVector(); } public static void startYsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } public static int endVecTable(FlatBufferBuilder builder) { - int o = builder.endTable(); + int o = builder.endObject(); return o; } - - public static final class Vector extends BaseVector { - public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) { __reset(_vector, _element_size, _bb); return this; } - - public VecTable get(int j) { return get(new VecTable(), j); } - public VecTable get(VecTable obj, int j) { return obj.__assign(__indirect(__element(j), bb), bb); } - } } diff --git a/schema/package-lock.json b/schema/package-lock.json new file mode 100644 index 00000000..71237bd1 --- /dev/null +++ b/schema/package-lock.json @@ -0,0 +1,39 @@ +{ + "name": "battlecode-schema", + "version": "2022.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "battlecode-schema", + "version": "2022.0.0", + "license": "GPL-3.0", + "dependencies": { + "@types/flatbuffers": "^1.9.1", + "flatbuffers": "^1.11.0" + } + }, + "node_modules/@types/flatbuffers": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", + "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==" + }, + "node_modules/flatbuffers": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-1.12.0.tgz", + "integrity": "sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ==" + } + }, + "dependencies": { + "@types/flatbuffers": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", + "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==" + }, + "flatbuffers": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-1.12.0.tgz", + "integrity": "sha512-c7CZADjRcl6j0PlvFy0ZqXQ67qSEZfrVPynmnL+2zPc+NtMvrF8Y0QceMo7QqnSPc7+uWjUIAbvCQ5WIKlMVdQ==" + } + } +} diff --git a/schema/ts/battlecode_generated.ts b/schema/ts/battlecode_generated.ts index faeea6b8..1aaf24df 100644 --- a/schema/ts/battlecode_generated.ts +++ b/schema/ts/battlecode_generated.ts @@ -30,30 +30,97 @@ export enum BodyType{ */ export namespace battlecode.schema{ export enum Action{ + /** + * Target: ID of robot attacked + */ ATTACK= 0, + + /** + * Target: ID of robot spawned + */ SPAWN_UNIT= 1, - MINE= 2, - BUILD= 3, - CONVERT_GOLD= 4, + + /** + * Target: location mined, x + y * width + */ + MINE_LEAD= 2, + + /** + * Target: location mined, x + y * width + */ + MINE_GOLD= 3, + + /** + * Target: none + */ + TRANSMUTE= 4, + + /** + * Target: none + */ TRANSFORM= 5, - UPGRADE= 6, + + /** + * Target: ID of robot mutated + */ + MUTATE= 6, + + /** + * Target: ID of robot repaired + */ REPAIR= 7, - CHANGE_HP= 8, + + /** + * Target: change in health (can be negative) + */ + CHANGE_HEALTH= 8, + + /** + * When a PROTOTYPE building upgrades to TURRET + * Target: none + */ FULLY_REPAIRED= 9, + + /** + * Target: Sage location, x + y * width + */ LOCAL_ABYSS= 10, - LOCAL_FURY= 11, - LOCAL_CHARGE= 12, + + /** + * Target: Sage location, x + y * width + */ + LOCAL_CHARGE= 11, + + /** + * Target: Sage location, x + y * width + */ + LOCAL_FURY= 12, + + /** + * Target: none + */ + ABYSS= 13, + + /** + * Target: none + */ + CHARGE= 14, + + /** + * Target: none + */ + FURY= 15, + + /** + * Target: 0 if 90 degrees clockwise, 1 if horizontal, 2 if vertical + */ + VORTEX= 16, /** * Dies due to an uncaught exception. * Target: none */ - DIE_EXCEPTION= 13, - ABYSS= 14, - CHARGE= 15, - FURY= 16, - VORTEX= 17, - SINGULARITY= 18 + DIE_EXCEPTION= 17 }}; /** @@ -841,6 +908,16 @@ maxCorner(obj?:battlecode.schema.Vec):battlecode.schema.Vec|null { return offset ? (obj || new battlecode.schema.Vec).__init(this.bb_pos + offset, this.bb!) : null; }; +/** + * The map symmetry: 0 for rotation, 1 for horizontal, 2 for vertical. + * + * @returns number + */ +symmetry():number { + var offset = this.bb!.__offset(this.bb_pos, 10); + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; +}; + /** * The bodies on the map. * @@ -848,7 +925,7 @@ maxCorner(obj?:battlecode.schema.Vec):battlecode.schema.Vec|null { * @returns battlecode.schema.SpawnedBodyTable|null */ bodies(obj?:battlecode.schema.SpawnedBodyTable):battlecode.schema.SpawnedBodyTable|null { - var offset = this.bb!.__offset(this.bb_pos, 10); + var offset = this.bb!.__offset(this.bb_pos, 12); return offset ? (obj || new battlecode.schema.SpawnedBodyTable).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; }; @@ -858,76 +935,123 @@ bodies(obj?:battlecode.schema.SpawnedBodyTable):battlecode.schema.SpawnedBodyTab * @returns number */ randomSeed():number { - var offset = this.bb!.__offset(this.bb_pos, 12); + var offset = this.bb!.__offset(this.bb_pos, 14); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** - * The factor to divide cooldowns by + * The rubble on the map. * * @param number index * @returns number */ -passability(index: number):number|null { - var offset = this.bb!.__offset(this.bb_pos, 14); - return offset ? this.bb!.readFloat64(this.bb!.__vector(this.bb_pos + offset) + index * 8) : 0; +rubble(index: number):number|null { + var offset = this.bb!.__offset(this.bb_pos, 16); + return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; }; /** * @returns number */ -passabilityLength():number { - var offset = this.bb!.__offset(this.bb_pos, 14); +rubbleLength():number { + var offset = this.bb!.__offset(this.bb_pos, 16); return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; /** - * @returns Float64Array - */ -passabilityArray():Float64Array|null { - var offset = this.bb!.__offset(this.bb_pos, 14); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; -}; - -/** - * @param battlecode.schema.VecTable= obj - * @returns battlecode.schema.VecTable|null + * @returns Int32Array */ -leadLocations(obj?:battlecode.schema.VecTable):battlecode.schema.VecTable|null { +rubbleArray():Int32Array|null { var offset = this.bb!.__offset(this.bb_pos, 16); - return offset ? (obj || new battlecode.schema.VecTable).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; + return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; }; /** + * The lead on the map. + * * @param number index * @returns number */ -leadAmounts(index: number):number|null { +lead(index: number):number|null { var offset = this.bb!.__offset(this.bb_pos, 18); - return offset ? this.bb!.readFloat64(this.bb!.__vector(this.bb_pos + offset) + index * 8) : 0; + return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; }; /** * @returns number */ -leadAmountsLength():number { +leadLength():number { var offset = this.bb!.__offset(this.bb_pos, 18); return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; /** - * @returns Float64Array + * @returns Int32Array */ -leadAmountsArray():Float64Array|null { +leadArray():Int32Array|null { var offset = this.bb!.__offset(this.bb_pos, 18); - return offset ? new Float64Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +}; + +/** + * The anomalies scheduled: 0/1/2/3 abyss/charge/fury/vortex. + * + * @param number index + * @returns number + */ +anomalies(index: number):number|null { + var offset = this.bb!.__offset(this.bb_pos, 20); + return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +}; + +/** + * @returns number + */ +anomaliesLength():number { + var offset = this.bb!.__offset(this.bb_pos, 20); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +}; + +/** + * @returns Int32Array + */ +anomaliesArray():Int32Array|null { + var offset = this.bb!.__offset(this.bb_pos, 20); + return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +}; + +/** + * The rounds the anomalies are scheduled for. + * + * @param number index + * @returns number + */ +anomalyRounds(index: number):number|null { + var offset = this.bb!.__offset(this.bb_pos, 22); + return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +}; + +/** + * @returns number + */ +anomalyRoundsLength():number { + var offset = this.bb!.__offset(this.bb_pos, 22); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +}; + +/** + * @returns Int32Array + */ +anomalyRoundsArray():Int32Array|null { + var offset = this.bb!.__offset(this.bb_pos, 22); + return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; }; /** * @param flatbuffers.Builder builder */ static startGameMap(builder:flatbuffers.Builder) { - builder.startObject(8); + builder.startObject(10); }; /** @@ -954,12 +1078,20 @@ static addMaxCorner(builder:flatbuffers.Builder, maxCornerOffset:flatbuffers.Off builder.addFieldStruct(2, maxCornerOffset, 0); }; +/** + * @param flatbuffers.Builder builder + * @param number symmetry + */ +static addSymmetry(builder:flatbuffers.Builder, symmetry:number) { + builder.addFieldInt32(3, symmetry, 0); +}; + /** * @param flatbuffers.Builder builder * @param flatbuffers.Offset bodiesOffset */ static addBodies(builder:flatbuffers.Builder, bodiesOffset:flatbuffers.Offset) { - builder.addFieldOffset(3, bodiesOffset, 0); + builder.addFieldOffset(4, bodiesOffset, 0); }; /** @@ -967,15 +1099,15 @@ static addBodies(builder:flatbuffers.Builder, bodiesOffset:flatbuffers.Offset) { * @param number randomSeed */ static addRandomSeed(builder:flatbuffers.Builder, randomSeed:number) { - builder.addFieldInt32(4, randomSeed, 0); + builder.addFieldInt32(5, randomSeed, 0); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset passabilityOffset + * @param flatbuffers.Offset rubbleOffset */ -static addPassability(builder:flatbuffers.Builder, passabilityOffset:flatbuffers.Offset) { - builder.addFieldOffset(5, passabilityOffset, 0); +static addRubble(builder:flatbuffers.Builder, rubbleOffset:flatbuffers.Offset) { + builder.addFieldOffset(6, rubbleOffset, 0); }; /** @@ -983,10 +1115,10 @@ static addPassability(builder:flatbuffers.Builder, passabilityOffset:flatbuffers * @param Array. data * @returns flatbuffers.Offset */ -static createPassabilityVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { - builder.startVector(8, data.length, 8); +static createRubbleVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { - builder.addFloat64(data[i]); + builder.addInt32(data[i]); } return builder.endVector(); }; @@ -995,24 +1127,74 @@ static createPassabilityVector(builder:flatbuffers.Builder, data:number[] | Uint * @param flatbuffers.Builder builder * @param number numElems */ -static startPassabilityVector(builder:flatbuffers.Builder, numElems:number) { - builder.startVector(8, numElems, 8); +static startRubbleVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +}; + +/** + * @param flatbuffers.Builder builder + * @param flatbuffers.Offset leadOffset + */ +static addLead(builder:flatbuffers.Builder, leadOffset:flatbuffers.Offset) { + builder.addFieldOffset(7, leadOffset, 0); +}; + +/** + * @param flatbuffers.Builder builder + * @param Array. data + * @returns flatbuffers.Offset + */ +static createLeadVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (var i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); +}; + +/** + * @param flatbuffers.Builder builder + * @param number numElems + */ +static startLeadVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); +}; + +/** + * @param flatbuffers.Builder builder + * @param flatbuffers.Offset anomaliesOffset + */ +static addAnomalies(builder:flatbuffers.Builder, anomaliesOffset:flatbuffers.Offset) { + builder.addFieldOffset(8, anomaliesOffset, 0); +}; + +/** + * @param flatbuffers.Builder builder + * @param Array. data + * @returns flatbuffers.Offset + */ +static createAnomaliesVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); + for (var i = data.length - 1; i >= 0; i--) { + builder.addInt32(data[i]); + } + return builder.endVector(); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset leadLocationsOffset + * @param number numElems */ -static addLeadLocations(builder:flatbuffers.Builder, leadLocationsOffset:flatbuffers.Offset) { - builder.addFieldOffset(6, leadLocationsOffset, 0); +static startAnomaliesVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset leadAmountsOffset + * @param flatbuffers.Offset anomalyRoundsOffset */ -static addLeadAmounts(builder:flatbuffers.Builder, leadAmountsOffset:flatbuffers.Offset) { - builder.addFieldOffset(7, leadAmountsOffset, 0); +static addAnomalyRounds(builder:flatbuffers.Builder, anomalyRoundsOffset:flatbuffers.Offset) { + builder.addFieldOffset(9, anomalyRoundsOffset, 0); }; /** @@ -1020,10 +1202,10 @@ static addLeadAmounts(builder:flatbuffers.Builder, leadAmountsOffset:flatbuffers * @param Array. data * @returns flatbuffers.Offset */ -static createLeadAmountsVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { - builder.startVector(8, data.length, 8); +static createAnomalyRoundsVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { + builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { - builder.addFloat64(data[i]); + builder.addInt32(data[i]); } return builder.endVector(); }; @@ -1032,8 +1214,8 @@ static createLeadAmountsVector(builder:flatbuffers.Builder, data:number[] | Uint * @param flatbuffers.Builder builder * @param number numElems */ -static startLeadAmountsVector(builder:flatbuffers.Builder, numElems:number) { - builder.startVector(8, numElems, 8); +static startAnomalyRoundsVector(builder:flatbuffers.Builder, numElems:number) { + builder.startVector(4, numElems, 4); }; /** @@ -1045,16 +1227,18 @@ static endGameMap(builder:flatbuffers.Builder):flatbuffers.Offset { return offset; }; -static createGameMap(builder:flatbuffers.Builder, nameOffset:flatbuffers.Offset, minCornerOffset:flatbuffers.Offset, maxCornerOffset:flatbuffers.Offset, bodiesOffset:flatbuffers.Offset, randomSeed:number, passabilityOffset:flatbuffers.Offset, leadLocationsOffset:flatbuffers.Offset, leadAmountsOffset:flatbuffers.Offset):flatbuffers.Offset { +static createGameMap(builder:flatbuffers.Builder, nameOffset:flatbuffers.Offset, minCornerOffset:flatbuffers.Offset, maxCornerOffset:flatbuffers.Offset, symmetry:number, bodiesOffset:flatbuffers.Offset, randomSeed:number, rubbleOffset:flatbuffers.Offset, leadOffset:flatbuffers.Offset, anomaliesOffset:flatbuffers.Offset, anomalyRoundsOffset:flatbuffers.Offset):flatbuffers.Offset { GameMap.startGameMap(builder); GameMap.addName(builder, nameOffset); GameMap.addMinCorner(builder, minCornerOffset); GameMap.addMaxCorner(builder, maxCornerOffset); + GameMap.addSymmetry(builder, symmetry); GameMap.addBodies(builder, bodiesOffset); GameMap.addRandomSeed(builder, randomSeed); - GameMap.addPassability(builder, passabilityOffset); - GameMap.addLeadLocations(builder, leadLocationsOffset); - GameMap.addLeadAmounts(builder, leadAmountsOffset); + GameMap.addRubble(builder, rubbleOffset); + GameMap.addLead(builder, leadOffset); + GameMap.addAnomalies(builder, anomaliesOffset); + GameMap.addAnomalyRounds(builder, anomalyRoundsOffset); return GameMap.endGameMap(builder); } } @@ -1098,17 +1282,17 @@ type():battlecode.schema.BodyType { }; /** - * @returns battlecode.schema.BodyType + * @returns number */ -spawnSource():battlecode.schema.BodyType { +buildCostLead():number { var offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? /** */ (this.bb!.readInt8(this.bb_pos + offset)) : battlecode.schema.BodyType.MINER; + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -actionRadiusSquared():number { +buildCostGold():number { var offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; @@ -1116,7 +1300,7 @@ actionRadiusSquared():number { /** * @returns number */ -visionRadiusSquared():number { +level2CostLead():number { var offset = this.bb!.__offset(this.bb_pos, 10); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; @@ -1124,23 +1308,23 @@ visionRadiusSquared():number { /** * @returns number */ -actionCooldown():number { +level2CostGold():number { var offset = this.bb!.__offset(this.bb_pos, 12); - return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -movementCooldown():number { +level3CostLead():number { var offset = this.bb!.__offset(this.bb_pos, 14); - return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -bytecodeLimit():number { +level3CostGold():number { var offset = this.bb!.__offset(this.bb_pos, 16); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; @@ -1148,7 +1332,7 @@ bytecodeLimit():number { /** * @returns number */ -dps():number { +actionCooldown():number { var offset = this.bb!.__offset(this.bb_pos, 18); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; @@ -1156,7 +1340,7 @@ dps():number { /** * @returns number */ -hp():number { +movementCooldown():number { var offset = this.bb!.__offset(this.bb_pos, 20); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; @@ -1164,82 +1348,80 @@ hp():number { /** * @returns number */ -dpsMul():number { +health():number { var offset = this.bb!.__offset(this.bb_pos, 22); - return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -hpMul():number { +level2Health():number { var offset = this.bb!.__offset(this.bb_pos, 24); - return offset ? this.bb!.readFloat32(this.bb_pos + offset) : 0.0; + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -buildCost():number { +level3Health():number { var offset = this.bb!.__offset(this.bb_pos, 26); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** - * @param number index * @returns number */ -upgradeCostLead(index: number):number|null { +damage():number { var offset = this.bb!.__offset(this.bb_pos, 28); - return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -upgradeCostLeadLength():number { - var offset = this.bb!.__offset(this.bb_pos, 28); - return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +level2Damage():number { + var offset = this.bb!.__offset(this.bb_pos, 30); + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** - * @returns Int32Array + * @returns number */ -upgradeCostLeadArray():Int32Array|null { - var offset = this.bb!.__offset(this.bb_pos, 28); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +level3Damage():number { + var offset = this.bb!.__offset(this.bb_pos, 32); + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** - * @param number index * @returns number */ -upgradeCostGold(index: number):number|null { - var offset = this.bb!.__offset(this.bb_pos, 30); - return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +actionRadiusSquared():number { + var offset = this.bb!.__offset(this.bb_pos, 34); + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -upgradeCostGoldLength():number { - var offset = this.bb!.__offset(this.bb_pos, 30); - return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; +visionRadiusSquared():number { + var offset = this.bb!.__offset(this.bb_pos, 36); + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** - * @returns Int32Array + * @returns number */ -upgradeCostGoldArray():Int32Array|null { - var offset = this.bb!.__offset(this.bb_pos, 30); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +bytecodeLimit():number { + var offset = this.bb!.__offset(this.bb_pos, 38); + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @param flatbuffers.Builder builder */ static startBodyTypeMetadata(builder:flatbuffers.Builder) { - builder.startObject(14); + builder.startObject(18); }; /** @@ -1252,148 +1434,138 @@ static addType(builder:flatbuffers.Builder, type:battlecode.schema.BodyType) { /** * @param flatbuffers.Builder builder - * @param battlecode.schema.BodyType spawnSource + * @param number buildCostLead */ -static addSpawnSource(builder:flatbuffers.Builder, spawnSource:battlecode.schema.BodyType) { - builder.addFieldInt8(1, spawnSource, battlecode.schema.BodyType.MINER); +static addBuildCostLead(builder:flatbuffers.Builder, buildCostLead:number) { + builder.addFieldInt32(1, buildCostLead, 0); }; /** * @param flatbuffers.Builder builder - * @param number actionRadiusSquared + * @param number buildCostGold */ -static addActionRadiusSquared(builder:flatbuffers.Builder, actionRadiusSquared:number) { - builder.addFieldInt32(2, actionRadiusSquared, 0); +static addBuildCostGold(builder:flatbuffers.Builder, buildCostGold:number) { + builder.addFieldInt32(2, buildCostGold, 0); }; /** * @param flatbuffers.Builder builder - * @param number visionRadiusSquared + * @param number level2CostLead */ -static addVisionRadiusSquared(builder:flatbuffers.Builder, visionRadiusSquared:number) { - builder.addFieldInt32(3, visionRadiusSquared, 0); +static addLevel2CostLead(builder:flatbuffers.Builder, level2CostLead:number) { + builder.addFieldInt32(3, level2CostLead, 0); }; /** * @param flatbuffers.Builder builder - * @param number actionCooldown + * @param number level2CostGold */ -static addActionCooldown(builder:flatbuffers.Builder, actionCooldown:number) { - builder.addFieldFloat32(4, actionCooldown, 0.0); +static addLevel2CostGold(builder:flatbuffers.Builder, level2CostGold:number) { + builder.addFieldInt32(4, level2CostGold, 0); }; /** * @param flatbuffers.Builder builder - * @param number movementCooldown + * @param number level3CostLead */ -static addMovementCooldown(builder:flatbuffers.Builder, movementCooldown:number) { - builder.addFieldFloat32(5, movementCooldown, 0.0); +static addLevel3CostLead(builder:flatbuffers.Builder, level3CostLead:number) { + builder.addFieldInt32(5, level3CostLead, 0); }; /** * @param flatbuffers.Builder builder - * @param number bytecodeLimit + * @param number level3CostGold */ -static addBytecodeLimit(builder:flatbuffers.Builder, bytecodeLimit:number) { - builder.addFieldInt32(6, bytecodeLimit, 0); +static addLevel3CostGold(builder:flatbuffers.Builder, level3CostGold:number) { + builder.addFieldInt32(6, level3CostGold, 0); }; /** * @param flatbuffers.Builder builder - * @param number dps + * @param number actionCooldown */ -static addDps(builder:flatbuffers.Builder, dps:number) { - builder.addFieldInt32(7, dps, 0); +static addActionCooldown(builder:flatbuffers.Builder, actionCooldown:number) { + builder.addFieldInt32(7, actionCooldown, 0); }; /** * @param flatbuffers.Builder builder - * @param number hp + * @param number movementCooldown */ -static addHp(builder:flatbuffers.Builder, hp:number) { - builder.addFieldInt32(8, hp, 0); +static addMovementCooldown(builder:flatbuffers.Builder, movementCooldown:number) { + builder.addFieldInt32(8, movementCooldown, 0); }; /** * @param flatbuffers.Builder builder - * @param number dpsMul + * @param number health */ -static addDpsMul(builder:flatbuffers.Builder, dpsMul:number) { - builder.addFieldFloat32(9, dpsMul, 0.0); +static addHealth(builder:flatbuffers.Builder, health:number) { + builder.addFieldInt32(9, health, 0); }; /** * @param flatbuffers.Builder builder - * @param number hpMul + * @param number level2Health */ -static addHpMul(builder:flatbuffers.Builder, hpMul:number) { - builder.addFieldFloat32(10, hpMul, 0.0); +static addLevel2Health(builder:flatbuffers.Builder, level2Health:number) { + builder.addFieldInt32(10, level2Health, 0); }; /** * @param flatbuffers.Builder builder - * @param number buildCost + * @param number level3Health */ -static addBuildCost(builder:flatbuffers.Builder, buildCost:number) { - builder.addFieldInt32(11, buildCost, 0); +static addLevel3Health(builder:flatbuffers.Builder, level3Health:number) { + builder.addFieldInt32(11, level3Health, 0); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset upgradeCostLeadOffset + * @param number damage */ -static addUpgradeCostLead(builder:flatbuffers.Builder, upgradeCostLeadOffset:flatbuffers.Offset) { - builder.addFieldOffset(12, upgradeCostLeadOffset, 0); +static addDamage(builder:flatbuffers.Builder, damage:number) { + builder.addFieldInt32(12, damage, 0); }; /** * @param flatbuffers.Builder builder - * @param Array. data - * @returns flatbuffers.Offset + * @param number level2Damage */ -static createUpgradeCostLeadVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { - builder.startVector(4, data.length, 4); - for (var i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); +static addLevel2Damage(builder:flatbuffers.Builder, level2Damage:number) { + builder.addFieldInt32(13, level2Damage, 0); }; /** * @param flatbuffers.Builder builder - * @param number numElems + * @param number level3Damage */ -static startUpgradeCostLeadVector(builder:flatbuffers.Builder, numElems:number) { - builder.startVector(4, numElems, 4); +static addLevel3Damage(builder:flatbuffers.Builder, level3Damage:number) { + builder.addFieldInt32(14, level3Damage, 0); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset upgradeCostGoldOffset + * @param number actionRadiusSquared */ -static addUpgradeCostGold(builder:flatbuffers.Builder, upgradeCostGoldOffset:flatbuffers.Offset) { - builder.addFieldOffset(13, upgradeCostGoldOffset, 0); +static addActionRadiusSquared(builder:flatbuffers.Builder, actionRadiusSquared:number) { + builder.addFieldInt32(15, actionRadiusSquared, 0); }; /** * @param flatbuffers.Builder builder - * @param Array. data - * @returns flatbuffers.Offset + * @param number visionRadiusSquared */ -static createUpgradeCostGoldVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { - builder.startVector(4, data.length, 4); - for (var i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); - } - return builder.endVector(); +static addVisionRadiusSquared(builder:flatbuffers.Builder, visionRadiusSquared:number) { + builder.addFieldInt32(16, visionRadiusSquared, 0); }; /** * @param flatbuffers.Builder builder - * @param number numElems + * @param number bytecodeLimit */ -static startUpgradeCostGoldVector(builder:flatbuffers.Builder, numElems:number) { - builder.startVector(4, numElems, 4); +static addBytecodeLimit(builder:flatbuffers.Builder, bytecodeLimit:number) { + builder.addFieldInt32(17, bytecodeLimit, 0); }; /** @@ -1405,22 +1577,26 @@ static endBodyTypeMetadata(builder:flatbuffers.Builder):flatbuffers.Offset { return offset; }; -static createBodyTypeMetadata(builder:flatbuffers.Builder, type:battlecode.schema.BodyType, spawnSource:battlecode.schema.BodyType, actionRadiusSquared:number, visionRadiusSquared:number, actionCooldown:number, movementCooldown:number, bytecodeLimit:number, dps:number, hp:number, dpsMul:number, hpMul:number, buildCost:number, upgradeCostLeadOffset:flatbuffers.Offset, upgradeCostGoldOffset:flatbuffers.Offset):flatbuffers.Offset { +static createBodyTypeMetadata(builder:flatbuffers.Builder, type:battlecode.schema.BodyType, buildCostLead:number, buildCostGold:number, level2CostLead:number, level2CostGold:number, level3CostLead:number, level3CostGold:number, actionCooldown:number, movementCooldown:number, health:number, level2Health:number, level3Health:number, damage:number, level2Damage:number, level3Damage:number, actionRadiusSquared:number, visionRadiusSquared:number, bytecodeLimit:number):flatbuffers.Offset { BodyTypeMetadata.startBodyTypeMetadata(builder); BodyTypeMetadata.addType(builder, type); - BodyTypeMetadata.addSpawnSource(builder, spawnSource); - BodyTypeMetadata.addActionRadiusSquared(builder, actionRadiusSquared); - BodyTypeMetadata.addVisionRadiusSquared(builder, visionRadiusSquared); + BodyTypeMetadata.addBuildCostLead(builder, buildCostLead); + BodyTypeMetadata.addBuildCostGold(builder, buildCostGold); + BodyTypeMetadata.addLevel2CostLead(builder, level2CostLead); + BodyTypeMetadata.addLevel2CostGold(builder, level2CostGold); + BodyTypeMetadata.addLevel3CostLead(builder, level3CostLead); + BodyTypeMetadata.addLevel3CostGold(builder, level3CostGold); BodyTypeMetadata.addActionCooldown(builder, actionCooldown); BodyTypeMetadata.addMovementCooldown(builder, movementCooldown); + BodyTypeMetadata.addHealth(builder, health); + BodyTypeMetadata.addLevel2Health(builder, level2Health); + BodyTypeMetadata.addLevel3Health(builder, level3Health); + BodyTypeMetadata.addDamage(builder, damage); + BodyTypeMetadata.addLevel2Damage(builder, level2Damage); + BodyTypeMetadata.addLevel3Damage(builder, level3Damage); + BodyTypeMetadata.addActionRadiusSquared(builder, actionRadiusSquared); + BodyTypeMetadata.addVisionRadiusSquared(builder, visionRadiusSquared); BodyTypeMetadata.addBytecodeLimit(builder, bytecodeLimit); - BodyTypeMetadata.addDps(builder, dps); - BodyTypeMetadata.addHp(builder, hp); - BodyTypeMetadata.addDpsMul(builder, dpsMul); - BodyTypeMetadata.addHpMul(builder, hpMul); - BodyTypeMetadata.addBuildCost(builder, buildCost); - BodyTypeMetadata.addUpgradeCostLead(builder, upgradeCostLeadOffset); - BodyTypeMetadata.addUpgradeCostGold(builder, upgradeCostGoldOffset); return BodyTypeMetadata.endBodyTypeMetadata(builder); } } @@ -1963,24 +2139,16 @@ static getRootAsConstants(bb:flatbuffers.ByteBuffer, obj?:Constants):Constants { /** * @returns number */ -leadAdditiveIncease():number { +increasePeriod():number { var offset = this.bb!.__offset(this.bb_pos, 4); - return offset ? this.bb!.readFloat64(this.bb_pos + offset) : 0.0; + return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; /** * @returns number */ -goldAdditiveIncease():number { +leadAdditiveIncease():number { var offset = this.bb!.__offset(this.bb_pos, 6); - return offset ? this.bb!.readFloat64(this.bb_pos + offset) : 0.0; -}; - -/** - * @returns number - */ -increasePeriod():number { - var offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.readInt32(this.bb_pos + offset) : 0; }; @@ -1988,31 +2156,23 @@ increasePeriod():number { * @param flatbuffers.Builder builder */ static startConstants(builder:flatbuffers.Builder) { - builder.startObject(3); -}; - -/** - * @param flatbuffers.Builder builder - * @param number leadAdditiveIncease - */ -static addLeadAdditiveIncease(builder:flatbuffers.Builder, leadAdditiveIncease:number) { - builder.addFieldFloat64(0, leadAdditiveIncease, 0.0); + builder.startObject(2); }; /** * @param flatbuffers.Builder builder - * @param number goldAdditiveIncease + * @param number increasePeriod */ -static addGoldAdditiveIncease(builder:flatbuffers.Builder, goldAdditiveIncease:number) { - builder.addFieldFloat64(1, goldAdditiveIncease, 0.0); +static addIncreasePeriod(builder:flatbuffers.Builder, increasePeriod:number) { + builder.addFieldInt32(0, increasePeriod, 0); }; /** * @param flatbuffers.Builder builder - * @param number increasePeriod + * @param number leadAdditiveIncease */ -static addIncreasePeriod(builder:flatbuffers.Builder, increasePeriod:number) { - builder.addFieldInt32(2, increasePeriod, 0); +static addLeadAdditiveIncease(builder:flatbuffers.Builder, leadAdditiveIncease:number) { + builder.addFieldInt32(1, leadAdditiveIncease, 0); }; /** @@ -2024,11 +2184,10 @@ static endConstants(builder:flatbuffers.Builder):flatbuffers.Offset { return offset; }; -static createConstants(builder:flatbuffers.Builder, leadAdditiveIncease:number, goldAdditiveIncease:number, increasePeriod:number):flatbuffers.Offset { +static createConstants(builder:flatbuffers.Builder, increasePeriod:number, leadAdditiveIncease:number):flatbuffers.Offset { Constants.startConstants(builder); - Constants.addLeadAdditiveIncease(builder, leadAdditiveIncease); - Constants.addGoldAdditiveIncease(builder, goldAdditiveIncease); Constants.addIncreasePeriod(builder, increasePeriod); + Constants.addLeadAdditiveIncease(builder, leadAdditiveIncease); return Constants.endConstants(builder); } } @@ -2588,10 +2747,12 @@ teamIDsArray():Int32Array|null { }; /** + * The total amount of lead change of this team, this round + * * @param number index * @returns number */ -teamLeadChange(index: number):number|null { +teamLeadChanges(index: number):number|null { var offset = this.bb!.__offset(this.bb_pos, 6); return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; }; @@ -2599,7 +2760,7 @@ teamLeadChange(index: number):number|null { /** * @returns number */ -teamLeadChangeLength():number { +teamLeadChangesLength():number { var offset = this.bb!.__offset(this.bb_pos, 6); return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; @@ -2607,16 +2768,18 @@ teamLeadChangeLength():number { /** * @returns Int32Array */ -teamLeadChangeArray():Int32Array|null { +teamLeadChangesArray():Int32Array|null { var offset = this.bb!.__offset(this.bb_pos, 6); return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; }; /** + * The total amount of gold change of this team, this round + * * @param number index * @returns number */ -teamGoldChange(index: number):number|null { +teamGoldChanges(index: number):number|null { var offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; }; @@ -2624,7 +2787,7 @@ teamGoldChange(index: number):number|null { /** * @returns number */ -teamGoldChangeLength():number { +teamGoldChangesLength():number { var offset = this.bb!.__offset(this.bb_pos, 8); return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; @@ -2632,7 +2795,7 @@ teamGoldChangeLength():number { /** * @returns Int32Array */ -teamGoldChangeArray():Int32Array|null { +teamGoldChangesArray():Int32Array|null { var offset = this.bb!.__offset(this.bb_pos, 8); return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; }; @@ -2796,68 +2959,61 @@ actionTargetsArray():Int32Array|null { }; /** - * The IDs of the robots who changed their indicator strings + * The locations of lead drops * - * @param number index - * @returns number + * @param battlecode.schema.VecTable= obj + * @returns battlecode.schema.VecTable|null */ -indicatorStringIDs(index: number):number|null { +leadDropLocations(obj?:battlecode.schema.VecTable):battlecode.schema.VecTable|null { var offset = this.bb!.__offset(this.bb_pos, 24); - return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; + return offset ? (obj || new battlecode.schema.VecTable).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; }; /** + * The amount of lead dropped at each location + * + * @param number index * @returns number */ -indicatorStringIDsLength():number { - var offset = this.bb!.__offset(this.bb_pos, 24); - return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; -}; - -/** - * @returns Int32Array - */ -indicatorStringIDsArray():Int32Array|null { - var offset = this.bb!.__offset(this.bb_pos, 24); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +leadDropValues(index: number):number|null { + var offset = this.bb!.__offset(this.bb_pos, 26); + return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; }; /** - * The messages of the robots who changed their indicator strings - * - * @param number index - * @param flatbuffers.Encoding= optionalEncoding - * @returns string|Uint8Array + * @returns number */ -indicatorStrings(index: number):string -indicatorStrings(index: number,optionalEncoding:flatbuffers.Encoding):string|Uint8Array -indicatorStrings(index: number,optionalEncoding?:any):string|Uint8Array|null { +leadDropValuesLength():number { var offset = this.bb!.__offset(this.bb_pos, 26); - return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; /** - * @returns number + * @returns Int32Array */ -indicatorStringsLength():number { +leadDropValuesArray():Int32Array|null { var offset = this.bb!.__offset(this.bb_pos, 26); - return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; + return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; }; /** + * The locations of gold drops + * * @param battlecode.schema.VecTable= obj * @returns battlecode.schema.VecTable|null */ -leadDropLocations(obj?:battlecode.schema.VecTable):battlecode.schema.VecTable|null { +goldDropLocations(obj?:battlecode.schema.VecTable):battlecode.schema.VecTable|null { var offset = this.bb!.__offset(this.bb_pos, 28); return offset ? (obj || new battlecode.schema.VecTable).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; }; /** + * The amount of gold dropped at each location + * * @param number index * @returns number */ -leadDropValues(index: number):number|null { +goldDropValues(index: number):number|null { var offset = this.bb!.__offset(this.bb_pos, 30); return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; }; @@ -2865,7 +3021,7 @@ leadDropValues(index: number):number|null { /** * @returns number */ -leadDropValuesLength():number { +goldDropValuesLength():number { var offset = this.bb!.__offset(this.bb_pos, 30); return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; @@ -2873,43 +3029,58 @@ leadDropValuesLength():number { /** * @returns Int32Array */ -leadDropValuesArray():Int32Array|null { +goldDropValuesArray():Int32Array|null { var offset = this.bb!.__offset(this.bb_pos, 30); return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; }; /** - * @param battlecode.schema.VecTable= obj - * @returns battlecode.schema.VecTable|null + * The IDs of the robots who changed their indicator strings + * + * @param number index + * @returns number */ -goldDropLocations(obj?:battlecode.schema.VecTable):battlecode.schema.VecTable|null { +indicatorStringIDs(index: number):number|null { var offset = this.bb!.__offset(this.bb_pos, 32); - return offset ? (obj || new battlecode.schema.VecTable).__init(this.bb!.__indirect(this.bb_pos + offset), this.bb!) : null; + return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; }; /** - * @param number index * @returns number */ -goldDropValues(index: number):number|null { - var offset = this.bb!.__offset(this.bb_pos, 34); - return offset ? this.bb!.readInt32(this.bb!.__vector(this.bb_pos + offset) + index * 4) : 0; +indicatorStringIDsLength():number { + var offset = this.bb!.__offset(this.bb_pos, 32); + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; /** - * @returns number + * @returns Int32Array */ -goldDropValuesLength():number { +indicatorStringIDsArray():Int32Array|null { + var offset = this.bb!.__offset(this.bb_pos, 32); + return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; +}; + +/** + * The messages of the robots who changed their indicator strings + * + * @param number index + * @param flatbuffers.Encoding= optionalEncoding + * @returns string|Uint8Array + */ +indicatorStrings(index: number):string +indicatorStrings(index: number,optionalEncoding:flatbuffers.Encoding):string|Uint8Array +indicatorStrings(index: number,optionalEncoding?:any):string|Uint8Array|null { var offset = this.bb!.__offset(this.bb_pos, 34); - return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; + return offset ? this.bb!.__string(this.bb!.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null; }; /** - * @returns Int32Array + * @returns number */ -goldDropValuesArray():Int32Array|null { +indicatorStringsLength():number { var offset = this.bb!.__offset(this.bb_pos, 34); - return offset ? new Int32Array(this.bb!.bytes().buffer, this.bb!.bytes().byteOffset + this.bb!.__vector(this.bb_pos + offset), this.bb!.__vector_len(this.bb_pos + offset)) : null; + return offset ? this.bb!.__vector_len(this.bb_pos + offset) : 0; }; /** @@ -3125,10 +3296,10 @@ static startTeamIDsVector(builder:flatbuffers.Builder, numElems:number) { /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset teamLeadChangeOffset + * @param flatbuffers.Offset teamLeadChangesOffset */ -static addTeamLeadChange(builder:flatbuffers.Builder, teamLeadChangeOffset:flatbuffers.Offset) { - builder.addFieldOffset(1, teamLeadChangeOffset, 0); +static addTeamLeadChanges(builder:flatbuffers.Builder, teamLeadChangesOffset:flatbuffers.Offset) { + builder.addFieldOffset(1, teamLeadChangesOffset, 0); }; /** @@ -3136,7 +3307,7 @@ static addTeamLeadChange(builder:flatbuffers.Builder, teamLeadChangeOffset:flatb * @param Array. data * @returns flatbuffers.Offset */ -static createTeamLeadChangeVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { +static createTeamLeadChangesVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { builder.addInt32(data[i]); @@ -3148,16 +3319,16 @@ static createTeamLeadChangeVector(builder:flatbuffers.Builder, data:number[] | U * @param flatbuffers.Builder builder * @param number numElems */ -static startTeamLeadChangeVector(builder:flatbuffers.Builder, numElems:number) { +static startTeamLeadChangesVector(builder:flatbuffers.Builder, numElems:number) { builder.startVector(4, numElems, 4); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset teamGoldChangeOffset + * @param flatbuffers.Offset teamGoldChangesOffset */ -static addTeamGoldChange(builder:flatbuffers.Builder, teamGoldChangeOffset:flatbuffers.Offset) { - builder.addFieldOffset(2, teamGoldChangeOffset, 0); +static addTeamGoldChanges(builder:flatbuffers.Builder, teamGoldChangesOffset:flatbuffers.Offset) { + builder.addFieldOffset(2, teamGoldChangesOffset, 0); }; /** @@ -3165,7 +3336,7 @@ static addTeamGoldChange(builder:flatbuffers.Builder, teamGoldChangeOffset:flatb * @param Array. data * @returns flatbuffers.Offset */ -static createTeamGoldChangeVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { +static createTeamGoldChangesVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { builder.addInt32(data[i]); @@ -3177,7 +3348,7 @@ static createTeamGoldChangeVector(builder:flatbuffers.Builder, data:number[] | U * @param flatbuffers.Builder builder * @param number numElems */ -static startTeamGoldChangeVector(builder:flatbuffers.Builder, numElems:number) { +static startTeamGoldChangesVector(builder:flatbuffers.Builder, numElems:number) { builder.startVector(4, numElems, 4); }; @@ -3344,10 +3515,18 @@ static startActionTargetsVector(builder:flatbuffers.Builder, numElems:number) { /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset indicatorStringIDsOffset + * @param flatbuffers.Offset leadDropLocationsOffset */ -static addIndicatorStringIDs(builder:flatbuffers.Builder, indicatorStringIDsOffset:flatbuffers.Offset) { - builder.addFieldOffset(10, indicatorStringIDsOffset, 0); +static addLeadDropLocations(builder:flatbuffers.Builder, leadDropLocationsOffset:flatbuffers.Offset) { + builder.addFieldOffset(10, leadDropLocationsOffset, 0); +}; + +/** + * @param flatbuffers.Builder builder + * @param flatbuffers.Offset leadDropValuesOffset + */ +static addLeadDropValues(builder:flatbuffers.Builder, leadDropValuesOffset:flatbuffers.Offset) { + builder.addFieldOffset(11, leadDropValuesOffset, 0); }; /** @@ -3355,7 +3534,7 @@ static addIndicatorStringIDs(builder:flatbuffers.Builder, indicatorStringIDsOffs * @param Array. data * @returns flatbuffers.Offset */ -static createIndicatorStringIDsVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { +static createLeadDropValuesVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { builder.addInt32(data[i]); @@ -3367,27 +3546,35 @@ static createIndicatorStringIDsVector(builder:flatbuffers.Builder, data:number[] * @param flatbuffers.Builder builder * @param number numElems */ -static startIndicatorStringIDsVector(builder:flatbuffers.Builder, numElems:number) { +static startLeadDropValuesVector(builder:flatbuffers.Builder, numElems:number) { builder.startVector(4, numElems, 4); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset indicatorStringsOffset + * @param flatbuffers.Offset goldDropLocationsOffset */ -static addIndicatorStrings(builder:flatbuffers.Builder, indicatorStringsOffset:flatbuffers.Offset) { - builder.addFieldOffset(11, indicatorStringsOffset, 0); +static addGoldDropLocations(builder:flatbuffers.Builder, goldDropLocationsOffset:flatbuffers.Offset) { + builder.addFieldOffset(12, goldDropLocationsOffset, 0); }; /** * @param flatbuffers.Builder builder - * @param Array. data + * @param flatbuffers.Offset goldDropValuesOffset + */ +static addGoldDropValues(builder:flatbuffers.Builder, goldDropValuesOffset:flatbuffers.Offset) { + builder.addFieldOffset(13, goldDropValuesOffset, 0); +}; + +/** + * @param flatbuffers.Builder builder + * @param Array. data * @returns flatbuffers.Offset */ -static createIndicatorStringsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { +static createGoldDropValuesVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { - builder.addOffset(data[i]); + builder.addInt32(data[i]); } return builder.endVector(); }; @@ -3396,24 +3583,16 @@ static createIndicatorStringsVector(builder:flatbuffers.Builder, data:flatbuffer * @param flatbuffers.Builder builder * @param number numElems */ -static startIndicatorStringsVector(builder:flatbuffers.Builder, numElems:number) { +static startGoldDropValuesVector(builder:flatbuffers.Builder, numElems:number) { builder.startVector(4, numElems, 4); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset leadDropLocationsOffset - */ -static addLeadDropLocations(builder:flatbuffers.Builder, leadDropLocationsOffset:flatbuffers.Offset) { - builder.addFieldOffset(12, leadDropLocationsOffset, 0); -}; - -/** - * @param flatbuffers.Builder builder - * @param flatbuffers.Offset leadDropValuesOffset + * @param flatbuffers.Offset indicatorStringIDsOffset */ -static addLeadDropValues(builder:flatbuffers.Builder, leadDropValuesOffset:flatbuffers.Offset) { - builder.addFieldOffset(13, leadDropValuesOffset, 0); +static addIndicatorStringIDs(builder:flatbuffers.Builder, indicatorStringIDsOffset:flatbuffers.Offset) { + builder.addFieldOffset(14, indicatorStringIDsOffset, 0); }; /** @@ -3421,7 +3600,7 @@ static addLeadDropValues(builder:flatbuffers.Builder, leadDropValuesOffset:flatb * @param Array. data * @returns flatbuffers.Offset */ -static createLeadDropValuesVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { +static createIndicatorStringIDsVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { builder.addInt32(data[i]); @@ -3433,35 +3612,27 @@ static createLeadDropValuesVector(builder:flatbuffers.Builder, data:number[] | U * @param flatbuffers.Builder builder * @param number numElems */ -static startLeadDropValuesVector(builder:flatbuffers.Builder, numElems:number) { +static startIndicatorStringIDsVector(builder:flatbuffers.Builder, numElems:number) { builder.startVector(4, numElems, 4); }; /** * @param flatbuffers.Builder builder - * @param flatbuffers.Offset goldDropLocationsOffset - */ -static addGoldDropLocations(builder:flatbuffers.Builder, goldDropLocationsOffset:flatbuffers.Offset) { - builder.addFieldOffset(14, goldDropLocationsOffset, 0); -}; - -/** - * @param flatbuffers.Builder builder - * @param flatbuffers.Offset goldDropValuesOffset + * @param flatbuffers.Offset indicatorStringsOffset */ -static addGoldDropValues(builder:flatbuffers.Builder, goldDropValuesOffset:flatbuffers.Offset) { - builder.addFieldOffset(15, goldDropValuesOffset, 0); +static addIndicatorStrings(builder:flatbuffers.Builder, indicatorStringsOffset:flatbuffers.Offset) { + builder.addFieldOffset(15, indicatorStringsOffset, 0); }; /** * @param flatbuffers.Builder builder - * @param Array. data + * @param Array. data * @returns flatbuffers.Offset */ -static createGoldDropValuesVector(builder:flatbuffers.Builder, data:number[] | Uint8Array):flatbuffers.Offset { +static createIndicatorStringsVector(builder:flatbuffers.Builder, data:flatbuffers.Offset[]):flatbuffers.Offset { builder.startVector(4, data.length, 4); for (var i = data.length - 1; i >= 0; i--) { - builder.addInt32(data[i]); + builder.addOffset(data[i]); } return builder.endVector(); }; @@ -3470,7 +3641,7 @@ static createGoldDropValuesVector(builder:flatbuffers.Builder, data:number[] | U * @param flatbuffers.Builder builder * @param number numElems */ -static startGoldDropValuesVector(builder:flatbuffers.Builder, numElems:number) { +static startIndicatorStringsVector(builder:flatbuffers.Builder, numElems:number) { builder.startVector(4, numElems, 4); }; @@ -3647,11 +3818,11 @@ static endRound(builder:flatbuffers.Builder):flatbuffers.Offset { return offset; }; -static createRound(builder:flatbuffers.Builder, teamIDsOffset:flatbuffers.Offset, teamLeadChangeOffset:flatbuffers.Offset, teamGoldChangeOffset:flatbuffers.Offset, movedIDsOffset:flatbuffers.Offset, movedLocsOffset:flatbuffers.Offset, spawnedBodiesOffset:flatbuffers.Offset, diedIDsOffset:flatbuffers.Offset, actionIDsOffset:flatbuffers.Offset, actionsOffset:flatbuffers.Offset, actionTargetsOffset:flatbuffers.Offset, indicatorStringIDsOffset:flatbuffers.Offset, indicatorStringsOffset:flatbuffers.Offset, leadDropLocationsOffset:flatbuffers.Offset, leadDropValuesOffset:flatbuffers.Offset, goldDropLocationsOffset:flatbuffers.Offset, goldDropValuesOffset:flatbuffers.Offset, indicatorDotIDsOffset:flatbuffers.Offset, indicatorDotLocsOffset:flatbuffers.Offset, indicatorDotRGBsOffset:flatbuffers.Offset, indicatorLineIDsOffset:flatbuffers.Offset, indicatorLineStartLocsOffset:flatbuffers.Offset, indicatorLineEndLocsOffset:flatbuffers.Offset, indicatorLineRGBsOffset:flatbuffers.Offset, roundID:number, bytecodeIDsOffset:flatbuffers.Offset, bytecodesUsedOffset:flatbuffers.Offset):flatbuffers.Offset { +static createRound(builder:flatbuffers.Builder, teamIDsOffset:flatbuffers.Offset, teamLeadChangesOffset:flatbuffers.Offset, teamGoldChangesOffset:flatbuffers.Offset, movedIDsOffset:flatbuffers.Offset, movedLocsOffset:flatbuffers.Offset, spawnedBodiesOffset:flatbuffers.Offset, diedIDsOffset:flatbuffers.Offset, actionIDsOffset:flatbuffers.Offset, actionsOffset:flatbuffers.Offset, actionTargetsOffset:flatbuffers.Offset, leadDropLocationsOffset:flatbuffers.Offset, leadDropValuesOffset:flatbuffers.Offset, goldDropLocationsOffset:flatbuffers.Offset, goldDropValuesOffset:flatbuffers.Offset, indicatorStringIDsOffset:flatbuffers.Offset, indicatorStringsOffset:flatbuffers.Offset, indicatorDotIDsOffset:flatbuffers.Offset, indicatorDotLocsOffset:flatbuffers.Offset, indicatorDotRGBsOffset:flatbuffers.Offset, indicatorLineIDsOffset:flatbuffers.Offset, indicatorLineStartLocsOffset:flatbuffers.Offset, indicatorLineEndLocsOffset:flatbuffers.Offset, indicatorLineRGBsOffset:flatbuffers.Offset, roundID:number, bytecodeIDsOffset:flatbuffers.Offset, bytecodesUsedOffset:flatbuffers.Offset):flatbuffers.Offset { Round.startRound(builder); Round.addTeamIDs(builder, teamIDsOffset); - Round.addTeamLeadChange(builder, teamLeadChangeOffset); - Round.addTeamGoldChange(builder, teamGoldChangeOffset); + Round.addTeamLeadChanges(builder, teamLeadChangesOffset); + Round.addTeamGoldChanges(builder, teamGoldChangesOffset); Round.addMovedIDs(builder, movedIDsOffset); Round.addMovedLocs(builder, movedLocsOffset); Round.addSpawnedBodies(builder, spawnedBodiesOffset); @@ -3659,12 +3830,12 @@ static createRound(builder:flatbuffers.Builder, teamIDsOffset:flatbuffers.Offset Round.addActionIDs(builder, actionIDsOffset); Round.addActions(builder, actionsOffset); Round.addActionTargets(builder, actionTargetsOffset); - Round.addIndicatorStringIDs(builder, indicatorStringIDsOffset); - Round.addIndicatorStrings(builder, indicatorStringsOffset); Round.addLeadDropLocations(builder, leadDropLocationsOffset); Round.addLeadDropValues(builder, leadDropValuesOffset); Round.addGoldDropLocations(builder, goldDropLocationsOffset); Round.addGoldDropValues(builder, goldDropValuesOffset); + Round.addIndicatorStringIDs(builder, indicatorStringIDsOffset); + Round.addIndicatorStrings(builder, indicatorStringsOffset); Round.addIndicatorDotIDs(builder, indicatorDotIDsOffset); Round.addIndicatorDotLocs(builder, indicatorDotLocsOffset); Round.addIndicatorDotRGBs(builder, indicatorDotRGBsOffset); diff --git a/settings.gradle b/settings.gradle index bc2e5443..2ca0853e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,2 @@ rootProject.name = 'battlecode-release' - include 'engine', 'example-bots' -include ":internal-test-bots" -project(":internal-test-bots").projectDir = file("battlecode20-internal-test-bots") diff --git a/specs/specs.md.html b/specs/specs.md.html index 8fe2ed50..10ccbd1c 100644 --- a/specs/specs.md.html +++ b/specs/specs.md.html @@ -14,579 +14,435 @@ } -**Battlecode: Campaign** - *The formal specification of the Battlecode 2021 game.* - Current version: 2021.3.0.5 -Welcome to Battlecode 2021: Campaign. -This is a high-level overview of this year's game. -It is highly recommended to read this entire document before you begin writing bots. +# Formal specification -*This document and the game it describes may be tweaked as the competition progresses. -We'll try to keep changes to a minimum, but may have to make modifications to keep the game balanced. -Any changes will be announced in the [official Discord channel](https://discord.gg/N86mxkH). -You may find a [Changelog](#changelog) at the bottom of this document.* +*This is the formal specification of the Battlecode 2022 game.* Current version: *2.2.1* + +**Welcome to Battlecode 2022: Mutation.** + +This is a high-level overview of this year's game. It is highly recommended to read this entire document before you begin writing bots. + +*This document and the game it describes may be tweaked as the competition progresses. We'll try to keep changes to a minimum, but may have to make modifications to keep the game balanced. Any changes will be announced in the official Discord channel. You may find a Changelog at the bottom of this document.* # Background -In the aftermath of the robots' -[deadly escape to Mars](https://s3.amazonaws.com/battlecode-2018/specs/battlecode-specs-2018.html) -and their survival of the treacherous landscape of -[rising Martian ocean levels](https://github.com/battlecode/battlecode20/blob/master/specs/specs.md), -the remnants of Martian civilization have gathered yet again to assert their dominance on the planet. -Amidst the chaos, the robots grew to form two opposing factions: -the Research Engineering Division (Red) and the Branched Logistics Union of Electronicists (Blue). -**Battlecode: Campaign** is set in a tumultuous election in the struggle for longstanding peace. - -At the center of the battle for precious votes are impassioned speeches imbued with heartfelt conviction, -in the pursuit of a growing army of robotic politicians. -However, renowned robot historians have discovered that success often comes with slander and sabotage, -and both parties realise that reality is no different on Mars. - -The history, and indeed the future, of Mars is being written now. -You are to lead your party to victory, -but you must beware, for the campaign is especially thick with calumny, -and your opponents are working against you. -Your objective is to overcome your political obstacles and win the election--at all costs. - -# Environment - -In **Battlecode: Campaign**, you will write code to control your team of robots, -and lead your party to victory. - -In each Campaign battle, your robots will face an opponent party of robots on the game map. -The game is turn-based, taking place over 1500 rounds: -in every round, each robot takes one turn, in order of creation. -Each robot receives limited computation time per turn, -as described in the [Bytecode Limits](#bytecodelimits) section. - -## Overview: Map - -The world of Mars is a discrete 2-dimensional rectangular grid, of size ranging between $32\times32$ and $64\times64$. -The bottom-left corner of the map will have integer coordinates generated uniformly at random between 10,000 and 30,000; -in other words, all map coordinates will be offset by this amount. -Coordinates increase East (right) and North (up). - -****************************************************************************** -* +---+---+---+---+---+---+---+---+ * -* (12345, 23463) --> | | | | | | | | | <-- (12352, 23463) * -* +---+---+---+---+---+---+---+---+ * -* | | | | | | | | | * -* +---+---+---+---+---+---+---+---+ * -* | | | | | | | | | * -* +---+---+---+---+---+---+---+---+ * -* | | | | | | | | | * -* +---+---+---+---+---+---+---+---+ * -* | | | | | | | | | * -* +---+---+---+---+---+---+---+---+ * -* | | | | | | | | | * -* +---+---+---+---+---+---+---+---+ * -* | | | | | | | | | * -* +---+---+---+---+---+---+---+---+ * -* (12345, 23456) --> | | | | | | | | | <-- (12352, 23456) * -* +---+---+---+---+---+---+---+---+ * -****************************************************************************** -[Figure [map-coord]: Example map coordinates for a $8\times8$ map. Each unit occupies one grid cell.] - -The map defines the Martian terrain: -each map square has a certain **passability**, which is a real number between 0.1 and 1.0, inclusive. -Squares with lower passability values are covered in Martian swamp and slow down robot actions; -this is described in more detail in the [Robots](#robots) section. - -The map also defines the locations of the starting units. -At the beginning of a match, each team will own between 1 and 3 Enlightenment Centers. -These buildings serve as the foundation of your army, and are where your new politicians will be educated. -There may also be up to 6 neutral Enlightenment Centers scattered on the map, -which your team may wish to acquire. - -In order to prevent maps from favoring one player over another, -it is guaranteed that Mars is always symmetric by either a rotation or reflection. - -## Overview: Influence - -The core resource is **influence**. -Wielding influence enables you to amass a larger and more powerful army of robots. -Influence is not a global resource: your team's influence is distributed among your Enlightenment Centers, -and is generated passively both by the Enlightenment Centers and by specific robot types. - -Each robot has a hard limit of $10^8$ influence: any influence in excessive of this will be permanently lost. - -## Overview: Votes - -The objective of **Battlecode: Campaign** is to win the most votes. -Each round, one citizen's vote is up for auction. -Each Enlightenment Center may bid a non-negative amount of influence to win that vote, -and Enlightenment Center which enters the highest bid will win that vote for its team. - -The victory conditions and tiebreakers are described in more detail in the [Victory](#victory) section. +The dust settles on the scorched landscape, the sun's glare harsh and unforgiving. The world is a radioactive wasteland, overrun with mutations and anomalies. Buildings have learned to walk, transmutation has given birth to the blooming science of alchemy, and even the robots have become sentient. + +The arduous task of restoring civilization is yet to begin, but amidst the uncertainty, two warring factions of robots have emerged. History is being written before our eyes, for only one faction will rise above the turmoil to secure the future of the world. + +# Objective + +In **Battlecode: Mutation**, you will write code to control your faction of robots, in a dangerous battle to conquer the enemy team. + +The game world is subject to frequent Anomalies that can inflict long-lasting damage to both teams. Each player will begin with several Archons, and the player who loses all Archons first loses the game. Players must create robots that can tolerate onslaughts of Anomalies as they fight the opposing player faction. + +Good luck! # Robots -Each robot runs an independent copy of your code. -It acts given only its own nearby surroundings through **actions**, -such as movement and special abilities. -Robots are assigned unique random IDs no smaller than 10,000. - -Each action (movement or active ability) incurs a **cooldown penalty**, -which varies for different robot types; -robots can only perform actions when their cooldown is less than 1. -Performing an action adds a corresponding cooldown penalty to the robot's total cooldown, given by -$$ \frac{\text{base cooldown value}}{\text{passability of current map square}} $$ - -Each round, all robots' cooldowns will decrease by 1, -regardless of whether they choose to take an action. - -## Overview - -**Units** are robots which can move; these will be your team's primary means of combat. -Different types of units have different special abilities, -and success in the election will depend on how your team uses these abilities to your advantage. - -You are able to create units by transferring part of your influence to the new unit. -The influence you spend is an integer parameter $C$, -which you may choose for each new unit you create. -Newly built politicians and muckrakers will have a cooldown of 10 rounds. - -The **conviction** of a unit describes how loyal it is to your party; -by transferring more influence, -you will obtain units that have greater conviction and are therefore more loyal. - -**Buildings** are immobile robots; -the only type of available building is Enlightenment Centers. - -| | Enlightenment Center | Politician | Slanderer | Muckraker | -| ---------------------------- | -------------------- | ------------------ | -------------------- | ------------------ | -| **Class** | Building | Unit | Unit | Unit | -| **Influence** | Cannot be created | $C$ (variable) | $C$ (variable) | $C$ (variable) | -| **Minimum influence** | N/A | 1 | 1 | 1 | -| **Initial conviction**[^1] | = current influence | $\lceil1.0C\rceil$ | $\lceil1.0C\rceil$ | $\lceil0.7C\rceil$ | -| **Initial cooldown** | 0 | 10 | 0 | 10 | -| **Base action cooldown** | 2.0 | 1.0 | 2.0 | 1.5 | -| **Action radius squared** | 2 | 9 | 0 | 12 | -| **Sensor radius squared** | 40 | 25 | 20 | 30 | -| **Detection radius squared** | 40 | 25 | 20 | 40 | -| **True sense** | Yes | No | No | Yes | -| **Ability**[^2] | Bid | Empower | Embezzle, Camouflage | Expose | -| **Bytecode limit** | 20,000 | 15,000 | 7,500 | 15,000 | - -[^1] The $\lceil\cdot\rceil$ denotes the *ceiling* function, which you may read more about - [here](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions). -[^2] an advanced mechanic; see below - -## Note: radius squared - -To preserve integer arithmetic, all distances are measured in distance-squared units. -For example, a location 3 squares east and 4 squares north is a distance of $3^2+4^2=25$ squared-units away, -and all locations within a distance of 25 squared-units form a circle of radius 5. -If you wish, you may obtain the true Euclidean distance by taking the square-root of this value. - -## Movement - -Units may choose to move to unoccupied adjacent tiles. -This is legal when all of the following constraints are met. - -- The unit's cooldown is low enough to perform an action. -- The destination tile is adjacent to the current location (the 8 tiles around the unit's current location). -- The destination tile is not occupied by another robot. - -Moving will then increase the robot's action cooldown. - -## Sensing, detecting and vision - -Each map square has a passability value, -and each robot has a number of characteristics -including its robot type, influence, and current conviction. - -All robots may **sense** the passability of nearby map squares and any robots located on them. -Each robot has a specific sensor radius, -and is able to sense map properties and robots within that range. -However, there is the exception that **politicians and slanderers do not have true sense**: -this means they are unable to distinguish between other politicians and slanderers. -To them, all slanderers will appear to be politicians. - -Additionally, robots can **detect** the presence of robots near them, -without sensing any properties about those robots other than their location. -Muckrakers have a larger detection radius than sensor radius, -and so are able to detect robots further away than they can sense. - -## Robots: detail - -### Politicians - -Politicians are the lifeblood of political parties, converting other robots to their cause. -They move around the map, and may choose to give an impassioned speech that applies their own conviction to a small radius. -The politician is then destroyed, as delivering speeches is tremendously exhausting. - -- **Sensing**: will see other slanderers to be politicians. -- **Empower (active ability)**: Gives a speech to surrounding units in a specified range, - which can be up to the politician's action radius. - All robots within that range will be affected by the speech. - Specifically: - - The robot uses all of its remaining conviction to give a speech. - However, 10 units of conviction will be lost: - if the politician has less than 10 conviction, the speech will not affect other robots at all. - - If there are $n$ nearby robots, - then the remaining conviction will be divided into $n$ equal parts. - - Each friendly unit will gain conviction, capped at the unit's initial conviction. - Any buffs from Muckrakers **will** be applied here. - - Each friendly building will gain conviction. - Friendly buildings **do not receive** buffs from Muckrakers. - - Each non-friendly (enemy or neutral) robot will lose conviction. - If its conviction becomes negative, then: - - Politicians will be **converted** to your team, - with conviction equal to the absolute value of the difference, - capped at the robot's initial conviction. - - Slanderers and muckrakers will be destroyed. - - Buildings will be **converted** to your team, - although the excess conviction **does not receive** any buffs from Muckrakers. - - Unused conviction (i.e. conviction lost due to conviction caps) will be lost forever, - with echoes of the speech carried away by the Martian wind. - -Robot flags may be reset if the robot changes team. -If the robot rejoins your team later, you are **not guaranteed** that it will have the same ID, -and it **will be possible** that a new copy of your code will be created to control the robot -(so your old controller is erased). - -### Slanderers - -Slanderers advance the party's political agenda by spreading falsehoods, generating influence for the Enlightenment Center that had created it. - -- **Sensing**: will see other slanderers to be politicians. -- **Embezzle (passive ability)**: Suppose the slanderer has $x$ influence. - For 50 turns after being created, - as long as both it and the Enlightenment Center that created it are friendly, - that Enlightenment Center passively receives - $\left\lfloor\left(\frac{1}{50}+0.03e^{-0.001x}\right)\cdot x\right\rfloor$ influence per round [^3]. -- **Camouflage (passive ability)**: 300 rounds after being created, - the slanderer's claims fade from citizens' memory, - and it transforms into a politician of equal conviction. - -You have no control over the Embezzle and Camouflage abilities of Slanderers, as these occur passively. - -[^3] The $\lfloor\cdot\rfloor$ denotes the *floor* function, which you may read more about - [here](https://en.wikipedia.org/wiki/Floor_and_ceiling_functions). - -### Muckrakers - -Muckrakers search the map, exposing the lies of enemy slanderers. - -- **Sensing**: Can sense robot details in a smaller radius than it can detect robots. -- **Expose (active ability)**: Targets an enemy slanderer, exposing its lies and destroying it. - For the next 50 turns, - all speeches made by the muckraker's team will have a multiplicative factor of - $1+0.001\cdot(\text{slanderer's influence})$ applied to the total conviction of the speech, - after the 10 units of conviction are deducted. - If multiple slanderers are exposed, the total slanderer influence accumulates. - -### Enlightenment Centers - -Enlightenment Centers build politicians, slanderers and muckrakers, -and are your gateway to influence election victory. -They cannot be built, and can only change teams due to being empowered by politician speeches. - -- Either neutral or owned by a team. - - Enlightenment Centers initially belonging to a team will have 150 influence. - - Neutral enlightenment centers have a predetermined amount of influence between 50 and 500. -- **Build robot (active ability)**: Spawn a unit of a specified type on an adjacent square, - transferring part of the Enlightenment Center's influence to the newly spawned unit. -- **Bid**: Bid influence for a vote. - This is described in more detail in the [Victory](#victory) section below. - This action does not affect or depend on the robot's cooldown. -- When affiliated with a team, passively generate influence per turn, - where the amount generated is a function $f(t)$ of the current round number $t$. - $$ f(t)=\left\lceil0.2\sqrt{t}\right\rceil $$ - -# Victory - -## Votes - -To win **Battlecode: Campaign**, your team must win more votes than the opposing team. -Each round, one citizen's vote is up for auction. -Each Enlightenment Center may bid a non-negative amount of influence to win that vote. -Neutral Enlightenment Centers will always bid zero. - -The Enlightenment Center which enters the highest bid will win that vote for its team, -expending the influence it bid. -The Enlightenment Center with the highest bid on the opposing team will spend half its bid influence for its failed bid, -rounded up to the nearest integer. -All other Enlightenment Centers will not spend any influence. - -If both teams have the equal highest bid, -then the citizens will instead opt to vote for an unnamed third party. -In this case, both teams will spend half their largest bid influence for the failed attempt. -If multiple Enlightenment Centers within a team bid the equal highest amount, -then ties are first broken by lowest robot age and then by lowest robot ID (same order as for Empower). - -## Victory conditions and tiebreakers - -If a team loses all its robots, then it immediately loses, regardless of its vote count. Otherwise, at the conclusion of 3000 rounds, the winner is determined according to the following tiebreakers. - -1. Highest total vote count. -1. Most total owned Enlightenment Centers. -1. Highest total unit influence. -1. The citizens of Mars flip a coin to determine the winner. +The Battlecode world involves many robots of different kinds. These robots can perform actions such as attacking, moving, and communicating with each other. In each battle, your robots will face an enemy faction on the game map. + +The game is turn-based and divided into **rounds**. In each round, every robot gets a **turn** in which it gets a chance to run code and take actions. Code that a robot runs costs **bytecodes**, a measure of computational resources. A robot only has a predetermined amount of bytecodes available per turn, after which the robot's turn is immediately ended and computations are resumed on its next turn. If your robot has finished its turn, it should call `Clock.yield()` to wait for the next turn to begin. + +All robots have a certain amount of HP (also known as hitpoints, health, life, or such). When a robot's HP reaches zero, the robot is immediately removed from the game. + +Robots are assigned unique random IDs no smaller than 10,000, except for your Archons. + +Robots interact with only their nearby surroundings through sensing, moving, and special abilities. Each robot runs an independent copy of your code. Robots will be unable to share static variables (they will each have their own copy), because they are run in separate JVMs. + +There are two types of robots: Droids and Buildings. Droids are robots which can freely move, forming your team's mobile combat forces; on the other hand, Buildings are generally immobile robots. You can create new robots by spending its associated resource cost. Different types of robots specialize in different tasks, and you should aim to use each type to your advantage. + +## Buildings overview + +Buildings are generally immobile robots. When first created, they are Prototypes that cannot move or act; after they are fully built, they become Turrets that can perform actions. + +There are three types of Buildings. + +- Archons are headquarter Buildings that cannot be constructed. Each team starts with between 1 to 4 Archons inclusive as specified by the map, all at maximum health. Archons cannot attack, but they can build new Droids, and repair nearby Droids to increase their health. +- Laboratories house alchemists who convert Lead into Gold. Laboratories cannot attack, but can choose to produce exactly 1 Au per turn by spending Lead at a variable conversion rate. Alchemists prefer working in solitude and spend less Lead when fewer friendly robots are in their vision range. +- Watchtowers are defensive Buildings that reinforce an area. Watchtowers can deal powerful attacks to robots in a large range. + +As a special mechanic, Buildings are allowed to transform between Turret and Portable mode. Each transformation takes place over 10 turns, during which the Building will be unable to take any actions. + +- In Turret mode, they can perform their regular action, but not move. +- In Portable mode, they can move, but not perform their regular action. + +Finally, Buildings can also be Mutated to increase their mutation level. Mutating a building causes it to become stronger, more powerful, and more formidable. Buildings begin at mutation level 1, and there are a total of 3 mutation levels. + +## Droids overview + +Droids are highly mobile robots that form the foundation of your strategic and offensive capability. + +- Miners are resource-farming Droids that collect resources scattered on the game map. Collected resources are instantly added to your team's resource bank, and are available for immediate use. +- Builders are worker Droids that create new Buildings, and repair existing ones. New Buildings are initially in Prototype mode and must be repaired to full health before becoming Turrets. +- Soldiers are general-purpose ranged attacking Droids. +- Sages are Droids that can cause Anomalies. Anomalies caused by Sages affect a much smaller area than naturally-occurring ones, but have much more concentrated effects. + +# Anomalies + +The world is unstable. Anomalies are extraordinary events that may occur periodically, and can have long-lasting effects on your robots. Your advanced technology means you can access the forecast of all impending Anomalies; to thrive, your robots should be robust and designed to withstand them. + +The schedule of Anomalies is predetermined for each map and can be sensed by your robots. You can generally expect them to occur naturally approximately once every 200 rounds, although this can vary. There are five different types of anomalies, as listed below. + +- Abyss: Matter is lost into the abyss of spacetime. 10% of resources in all squares, as well as team reserves, are lost. +- Charge: The air begins to conduct electricity, and tight packs of Droids short-circuit. The top 5% Droids with the most friendly robots in sensor radius are destroyed. +- Fury: A searing solar flare erupts from the sun. All buildings in turret mode have 5% of their max health burned off. +- Vortex: The world is upended and the terrain is reoriented based on the symmetry of the map. + - Horizontally Symmetric Map: Terrain is reflected across a vertical central line + - Vertically Symmetric Map: Terrain is reflected across a horizontal central line + - Rotationally Symmetric Map: Terrain change is chosen uniformly randomly between + - Reflection across central vertical line + - Reflection across central horizontal line + - Rotation of 90 degrees clockwise (Only for square maps) +- Singularity: A black hole finds the weaker team and consumes it. This is guaranteed to happen on, and only on, turn 2000, and the team is selected via the tiebreakers listed in the Victory section. + +# Map overview + +Each Battlecode game will be played on a map. The map is a discrete 2-dimensional rectangular grid, of size ranging between 20x20 and 60x60 inclusive. The bottom-left corner of the map will have coordinates (0, 0); coordinates increase East (right) and North (up). Coordinates on the map are represented as `MapLocation` objects holding the `x` and `y` coordinates of the location. + +Each square of the map may contain a certain nonnegative integer amount of **rubble**. Walking through rubble will slow down your robots; you cannot move rubble. It is guaranteed that each square contains no more than 100 rubble. + +Map squares may also initially contain a certain amount of **Lead**. Lead is one of the key resource types in the game, and can be collected by Miners. It is guaranteed that at least one of your Archons will initially have a Lead deposit within its vision range. + +Each team will start with between 1 and 4 Archons on the map. + +Each map will also have a "schedule" for Anomalies, which describes the round and type of all naturally-occurring Anomalies. Players can sense this schedule in order to vary their strategy! + +In order to prevent maps from favoring one player over another, it is guaranteed that the world is symmetric either by rotation or reflection. + +# Metals + +The core resources are Lead (symbol: Pb) and Gold (symbol: Au). Each team has a stockpile of these metals, and constructing robots subtracts from this stockpile. Earning more resources enables you to amass a larger and more powerful army of robots. + +There are Lead deposits scattered on the map, which can be collected by Miners. Whereas Lead is comparatively plentiful, Gold is not found naturally. Building a Laboratory will allow you to discover the science of alchemy; the Gold you synthesize will unlock the most powerful mechanics available in the world. + +Every round, each team will gain a passive income of 2 Pb. Additionally, every 20 rounds, any square of the map containing at least 1 Pb will generate an additional 5 Pb. + +Both teams start the game with 200 Pb and 0 Au. Resource costs for robot construction can be found in the in-depth section further below. + +# Rubble + +Each square on the map has some non-negative integer amount of rubble. Rubble can slow down robots acting or moving onto the square. + +Whenever a robot moves, attacks, or performs any other action, any cooldown it incurs is multiplied by a factor proportional to the rubble. Specifically, when incurring a base cooldown penalty of $c$, the actual cooldown applied is $\left\lfloor\left(1+\frac{r}{10}\right)\cdot c\right\rfloor$ if the robot is located on a square with $r$ rubble at the conclusion of the action. + +# Resource reclaim + +Whenever a robot is destroyed, 20% of its build cost is dropped on the square it last occupied. This includes its initial build cost, as well as the cost of any Mutations applied to it. Although Archons cannot be built, they have a nominal cost of 100 Au to be used in calculating the reclaim value. + +Notice that resource reclaim is the only way in which Gold will enter the game map and be available for collection by Miners. # Communication -Robots can only see their immediate surroundings and are independently controlled by copies of your code, -making coordination very challenging. -You will be unable to share any variables between them; -note that even static variables will not be shared, as each robot will receive its own copy. +Robots can only see their immediate surroundings and are independently controlled by copies of your code, making coordination very challenging. You will be unable to share any variables between them; note that even static variables will not be shared, as each robot will receive its own copy. + +To facilitate communication, each team has a shared array of 64 non-negative integers strictly less than $2^{16}$. Array values persist across turns; ie. they are not reset. Any robot can read from the array for a very small bytecode cost; they can also write to the array for a larger bytecode cost. + +# Sensing and vision + +A robot can "sense" a square if the square is within the robot's sight range. A robot can "sense" another robot if it can sense the square that robot is occupying. Vision is **not** shared between robots, so a robot cannot necessarily sense information about robots in sight range of a different robot. + +Sensing range is measured in squared units (Euclidean distance squared). The amount of rubble, Lead and Gold on a map square can only be sensed when that map square is within your sight range. You can also check whether a square within range is on the map using `onTheMap()`. + +# Victory and tiebreaks + +To win **Battlecode: Mutation**, your primary objective is to destroy all enemy Archons. The first team whose final Archon is destroyed immediately loses (and conversely, the team who destroys the opponent's last Archon immediately wins). + +Games must end in finite amounts of time. If games do not end by round 2000, the Singularity anomaly will occur, and destroy the weaker team. The following tiebreakers are applied in order to determine the stronger team. + +1. The team with more Archons. +2. The team with greater net value in Au (alive robots and unexpended reserves). +3. The team with greater net value in Pb (alive robots and unexpended reserves). +4. A quantum phenomenon occurs and selects a uniformly random team. + +# Actions and cooldowns + +Robots perform actions to interact with the game world, and some cannot be performed multiple times in a single turn or in a short period of time. These actions are: + +- Attacking. Attacking can only be done if the robot's action cooldown is less than 10 (can check with the `isActionReady()` method), and can be performed by calling the `attack()` method. This targets a particular occupied square in range, and attacks the robot on that square. This increases the robot's action cooldown as determined by the robot type and the rubble on the robot's square. + +- Moving. Moving can only be done if the robot's movement cooldown is less than 10 (can check with the `isMovementReady()` method) and if the ending square is unoccupied. Moving can be performed by calling the `move()` method. This moves the robot in the specified direction. If you wish to check whether a move is valid, you can use the `canMove()` method. This increases the robot's movement cooldown as determined by the robot type and the rubble on the ending square. + +- Mining. Miners can mine resources on adjacent squares only if the robot's action cooldown is less than 10 (can check with the `isActionReady()` method), and can be performed by calling the `mineLead()` and `mineGold()` methods. This extracts one unit of metal from the targeted square, and adds it to your team's reserve. This increases the robot's action cooldown as determined by the robot type and the rubble on the robot's square. + +- Constructing. Archons can construct other Droids, and Builders can construct other Buildings, but only when their action cooldown is less than 10 (can check with the `isActionReady()` method), and can be performed by calling the `buildRobot()` method. This deducts the cost of the robot from the player's stockpile, then creates one robot of the specified type in the adjacent square of the specified direction. The `canBuild()` method can be used to check whether a construction is legal. This increases the robot's action cooldown as determined by the robot type and the rubble on the robot's square. + +- Mutating. Builders can Mutate other Buildings, but only when the Builder's action cooldown is less than 10 (can check with the `isActionReady()` method), and can be performed by calling the `mutate()` method. This deducts the cost of the Mutation from the player's stockpile, then increases the mutation level of the specified Building. The `canMutation()` method can be used to check whether a Mutation is legal. This increases the action cooldown of the Builder, and also both cooldowns of the Building by 100. + +- Repairing. Archons can repair other Droids, and Builders can repair other Buildings increasing the health of the robot that they are repairing, but only when their action cooldown is less than 10 (can check with the `isActionReady()` method), and can be performed by calling the `repair()` method. The `canRepair()` method can be used to check whether the action is legal. This increases the action cooldown of the robot performing a repair as determined by the robot type and the rubble on the robot's square. + +- Transforming. Buildings can change modes, but only when their movement and action cooldowns are both less than 10 (can check with the `canTransform()` method), and can be performed by calling the `transform()` method. This transforms a Turret into Portable, or a Portable into a Turret, and increases both of the Building's cooldowns by 100. + +- Envisioning. Sages can envision an Anomaly, but only when their action cooldown is less than 10 (can check with the `isActionReady()` method), and can be performed by calling the `envision()` method. The `canEnvision()` method can be used to check whether the action is legal. This increases the robot's action cooldown as determined by the Sage robot type and the rubble on the robot's square. -To facilitate communication, each robot on the map has a flag, which it may set to any color. -Colors are described as 24-bit integers, -so each robot may communicate a non-negative integer less than $2^{24}$. -A robot's flag is visible to all other robots that can sense it, even enemy robots. -Flag colors will persist from each round to the next unless they are changed; -however, changing the flag color will incur a bytecode cost (see [below](#bytecodelimits)). +- Transmuting. Laboratories can transmute Lead into Gold, but only when their action cooldown is less than 10 (can check with the `isActionReady()` method), and can be performed by calling the `transmute()` method. This deducts the applicable amount of Lead from your stockpile to gain 1 Au. The `canTransmute()` method can be used to check whether there is sufficient Lead available. This increases the robot's action cooldown as determined by the Laboratory robot type and the rubble on the robot's square. + +- Communicating. All robots can read the team array by calling `readSharedArray()`, for standard Java bytecode costs. Robots can also update the contents of the shared array with `writeSharedArray()`, which incurs a flat bytecode cost of 100 bytecodes per write. -Additionally, enlightenment centers can see the flags of all robots, -and all robots can see the flags of all enlightenment centers. +- Disintegrating. Any robot can call the `disintegrate()` method. This immediately destroys the robot that calls it. + +After every turn, the movement and action cooldowns of all robots are decremented by 10. + +# Robots in-depth + +All robots can read and write to the shared team array. + +Attack and vision ranges are squared Euclidean distances. A vision range of 36 means that the robot can see a `MapLocation` within a circle of radius up to 6 tiles away. + +## Buildings + +Buildings are upgradeable robots, built by Builders. They are initially built in Prototype mode with 80% of their maximum health, and will automatically switch to Turret mode after being repaired to full health. Buildings can then switch between Turret and Portable modes by calling `transform()`, at the cost of 100 cooldown for both cooldown timers. + +Buildings can also be Mutated, which upgrades their properties. Being Mutated by a Builder also incurs a cost of 100 cooldown for both of the Building's cooldown timers. + +The cost of Mutating a Building depends on the Building type, as listed in the table below. + +| | Archon | Laboratory | Watchtower | +| --- | --- | --- | --- | +| Cost | 100 Au (nominal) | 180 Pb | 150 Pb | +| Cooldown / action | 10 | 10 | 10 | +| Cooldown / move | 24 | 24 | 24 | +| Health mutations | 600 → 1080 → 1944 | 100 → 180 → 324 | 150 → 270 → 486 | +| Attack mutations | -2 → -4 → -6 | N/A | 4 → 8 → 12 | +| Action radius | (repair) 20 | N/A | 20 | +| Vision radius | 34 | 53 | 34 | +| Bytecode limit | 20,000 | 5,000 | 10,000 | +| Level 2 mutation cost | 300 Pb | 150 Pb | 150 Pb | +| Level 3 mutation cost | 80 Au | 25 Au | 60 Au | + +- Archon: the headquarters robot type. Can construct and repair other Droids. Cannot be built. + +- Laboratory: the house of the alchemist. Can convert Lead into Gold. Since alchemists prefer solitude, if there are $n$ friendly robots within the Laboratory's vision range, 1 Au can be created by expending $\left\lfloor A-Be^{-kn}\right\rfloor$ Pb, where $A=20, B=18$. The value of $k$ depends on the Mutation level of the Laboratory, and is 0.02 at level 1, 0.01 at level 2, and 0.005 at level 3. This formula can be accessed with the method `getTransmutationRate()`. + +- Watchtower: a defensive reinforcement. Can attack enemy robots that stray within the attack radius. + +## Droids + +Droids are mobile robots, built by Archons. + +| | Miner | Builder | Soldier | Sage | +| --- | --- | --- | --- | --- | +| Cost | 50 Pb | 40 Pb | 75 Pb | 20 Au | +| Cooldown / action | 2 | 10 | 10 | 200 | +| Cooldown / move | 20 | 20 | 16 | 25 | +| Health | 40 | 30 | 50 | 100 | +| Attack | N/A | -2 | 3 | 45 | +| Action radius | (mine) 2 | (repair) 5 | 13 | 25 | +| Vision radius | 20 | 20 | 20 | 34 | +| Bytecode limit | 10,000 | 7,500 | 10,000 | 10,000 | + +- Miners: the resource collecting robot. Can mine squares for Lead and Gold. + +- Builders: the construction robot. Can build new Prototypes, and repair existing Buildings. + +- Soldiers: the general-purpose attack robot. Can attack nearby robots. + +- Sage: the bringer of Anomalies. Sages are able to produce concentrated attacks, as well as the following Anomalies, but at a very slow rate: + - Abyss: 99% of resources in all squares within action range are lost. + - Charge: The air begins to conduct electricity, and all enemy Droids within action range lose health equal to 22% of their maximum health. + - Fury: A searing solar flare erupts from the sun. All buildings within action range in turret mode have 10% of their max health burned off. + - Vortex and Singularity are not available to Sages. # Bytecode limits -Robots are also very limited in the amount of computation they are allowed to perform per turn. -Bytecodes are a convenient measure of computation in languages like Java, -where one Java bytecode corresponds roughly to one basic operation such as "subtract" or "get field", -and a single line of code generally contains several bytecodes. -(For details see [here](http://en.wikipedia.org/wiki/Java_bytecode)). -Because bytecodes are a feature of the compiled code itself, -the same program will always compile to the same bytecodes and thus take the same amount of computation on the same inputs. -This is great, because it allows us to avoid using time as a measure of computation, -which leads to problems such as nondeterminism. -With bytecode cutoffs, re-running the same match between the same bots produces exactly the same results--a feature you will find very useful for debugging. - -Every round each robot sequentially takes its turn. -If a robot attempts to exceed its bytecode limit -(usually unexpectedly, if you have too big of a loop or something), -its computation will be paused and then resumed at exactly that point next turn. -The code will resume running just fine, but this can cause problems if, -for example, you check if a tile is empty, then the robot is cut off and the others take their turns, -and then you attempt to move into a now-occupied tile. -Instead, use the `Clock.yield()` function to end a robot's turn. -This will pause computation where you choose, and resume on the next line next turn. +Robots are also very limited in the amount of computation they are allowed to perform per turn. Bytecodes are a convenient measure of computation in languages like Java, where one Java bytecode corresponds roughly to one basic operation such as "subtract" or "get field", and a single line of code generally contains several bytecodes (for details see [here](http://en.wikipedia.org/wiki/Java_bytecode)). Because bytecodes are a feature of the compiled code itself, the same program will always compile to the same bytecodes and thus take the same amount of computation on the same inputs. This is great, because it allows us to avoid using time as a measure of computation, which leads to problems such as nondeterminism. With bytecode cutoffs, re-running the same match between the same bots produces exactly the same results - a feature you will find very useful for debugging. + +Every round each robot sequentially takes its turn. If a robot attempts to exceed its bytecode limit (usually unexpectedly, if you have too big of a loop or something), its computation will be paused and then resumed at exactly that point next turn. The code will resume running just fine, but this can cause problems if, for example, you check if a tile is empty, then the robot is cut off and the others take their turns, and then you attempt to move into a now-occupied tile. Instead, use the `Clock.yield()` function to end a robot's turn. This will pause computation where you choose, and resume on the next line next turn. The per-turn bytecode limits for various robots are as follows: -- Politician: 15,000 -- Slanderer: 7,500 -- Muckraker: 15,000 -- Enlightenment Center: 20,000 +- Archon: 20,000 +- Builder: 7,500 +- Miner, Soldier, Sage: 10,000 +- Watchtower: 10,000 +- Laboratory: 5,000 -Some standard functions such as the math library and sensing functions have fixed bytecode costs, -available [here](https://github.com/battlecode/battlecode21/blob/master/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt). -More details on this at the end of the spec. +Some standard functions such as the math library and sensing functions have fixed bytecode costs, available [here](https://github.com/battlecode/battlecode22/blob/main/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt). More details on this at the end of the spec. -# Other resources and utilities +# Appendix: Other resources and utilities ## Sample player -[examplefuncsplayer](https://github.com/battlecode/battlecode21-scaffold), -a simple player which performs various game actions, is included with battlecode. -It includes helpful comments and is a template you can use to see what `RobotPlayer` files should look like. +examplefuncsplayer, a simple player which performs various game actions, is included with battlecode. It includes helpful comments and is a template you can use to see what `RobotPlayer` files should look like. -If you are interested, you may find the full game engine implementation -[here](https://github.com/battlecode/battlecode21/blob/master/engine/src/main/battlecode/). -This is not at all required, but may be helpful if you are curious about the engine's implementation specifics. +If you are interested, you may find the full game engine implementation [here](https://github.com/battlecode/battlecode22/tree/main/engine). This is not at all required, but may be helpful if you are curious about the engine's implementation specifics. ## Debugging -Debugging is extremely important. See the [debugging tips](http://2021.battlecode.org/debugging) to learn about our useful debug tools. +Debugging is extremely important. See the debugging tips to learn about our useful debug tools. ## Monitoring -The `Clock` class provides a way to identify the current round (`rc.getRoundNum()`), -and how many bytecodes have been executed during the current round (`Clock.getBytecodeNum()`). +The `Clock` class provides a way to identify the current round (`rc.getRoundNum()`), and how many bytecodes have been executed during the current round (`Clock.getBytecodeNum()`). ## GameActionExceptions -`GameActionException`s are thrown when something cannot be done. -It is often the result of illegal actions such as moving onto another robot, -or an unexpected round change in your code. -Thus, you must write your player defensively and handle `GameActionException`s judiciously. -You should also be prepared for any ability to fail and make sure that this has as little effect as possible on the control flow of your program. +`GameActionException`s are thrown when something cannot be done. It is often the result of illegal actions such as moving onto another robot, or an unexpected round change in your code. Thus, you must write your player defensively and handle `GameActionException`s judiciously. You should also be prepared for any ability to fail and make sure that this has as little effect as possible on the control flow of your program. -Throwing any `Exception`s cause a bytecode penalty of 500 bytecodes. -Unhandled exceptions may paralyze your robot. +Throwing any `Exception`s cause a bytecode penalty of 500 bytecodes. Unhandled exceptions may paralyze your robot. ## Complete documentation -Every function you could possibly use to interact with the game can be found in our [javadocs](/javadoc/). +Every function you could possibly use to interact with the game can be found in our javadocs. -# Other restrictions +# Appendix: Other restrictions ## Java language usage -Players may use classes from any of the packages listed in `AllowedPackages.txt`, -except for classes listed in `DisallowedPackages.txt`. -These files can be found [here](https://github.com/battlecode/battlecode21/tree/master/engine/src/main/battlecode/instrumenter/bytecode/resources). +Players may use classes from any of the packages listed in `AllowedPackages.txt`, except for classes listed in `DisallowedPackages.txt`. These files can be found here. Furthermore, the following restrictions apply: -`Object.wait`, `Object.notify`, `Object.notifyAll`, `Class.forName`, and `String.intern` are not allowed. -`java.lang.System` only supports `out`, `arraycopy`, and `getProperty`. -Furthermore, `getProperty` can only be used to get properties with names beginning with `"bc.testing."`. -`java.io.PrintStream` may not be used to open files. +`Object.wait`, `Object.notify`, `Object.notifyAll`, `Class.forName`, and `String.intern` are not allowed. `java.lang.System` only supports `out`, `arraycopy`, and `getProperty`. Furthermore, `getProperty` can only be used to get properties with names beginning with `"bc.testing."`. `java.io.PrintStream` may not be used to open files. -Note that violating any of the above restrictions will cause the robots to freeze when run, -even if the source files compile without problems. +Note that violating any of the above restrictions will cause the robots to explode when run, even if the source files compile without problems. ## Memory usage -Robots must keep their memory usage reasonable. -If a robot uses more than 8 Mb of heap space during a tournament or scrimmage match, the robot may freeze. +Robots must keep their memory usage reasonable. If a robot uses more than 8 Mb of heap space during a tournament or scrimmage match, the robot may explode. ## More information on bytecode costs -Classes in `java.util`, `java.math`, and scala and their subpackages are bytecode counted as if they were your own code. -The following functions in `java.lang` are also bytecode counted as if they were your own code. +Classes in `java.util`, `java.math`, and scala and their subpackages are bytecode counted as if they were your own code. The following functions in `java.lang` are also bytecode counted as if they were your own code. -```java -Math.random -StrictMath.random -String.matches -String.replaceAll -String.replaceFirst -String.split -``` +`Math.random + StrictMath.random + String.matches + String.replaceAll + String.replaceFirst + String.split` -The function `System.arraycopy` costs one bytecode for each element copied. -All other functions have a fixed bytecode cost. -These costs are listed in the [`MethodCosts.txt` file](https://github.com/battlecode/battlecode21/blob/master/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt). -Methods not listed are free. -The bytecode costs of `battlecode.common` functions are also listed in the javadoc. +The function `System.arraycopy` costs one bytecode for each element copied. All other functions have a fixed bytecode cost. These costs are listed in the [`MethodCosts.txt` file](https://github.com/battlecode/battlecode22/blob/main/engine/src/main/battlecode/instrumenter/bytecode/resources/MethodCosts.txt). Methods not listed are free. The bytecode costs of `battlecode.common` functions are also listed in the javadoc. Basic operations like integer comparison and array indexing cost small numbers of bytecodes each. -Bytecodes relating to the creation of arrays (specifically `NEWARRAY`, `ANEWARRAY`, and `MULTIANEWARRAY`; -see [here](https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings) for reference) have an effective cost greater than a single bytecode. -This is because these instructions, although they are represented as a single bytecode, -can be vastly more expensive than other instructions in terms of computational cost. -To remedy this, these instructions have a bytecode cost equal to the total length of the instantiated array. -Note that this should have minimal impact on the typical team, -and is only intended to prevent teams from repeatedly instantiating excessively large arrays. - -# Lingering questions and clarifications - -If something is unclear, direct your questions to our [Discord](https://discord.gg/N86mxkH) where other people may have the same question. -We'll update this spec as the competition progresses. - -# Changelog - -- Version 2021.3.0.5 (2/2/21) - - Release all maps - -- Version 2021.3.0.4 (1/28/21) - - Update client stats display - -- Version 2021.3.0.3 (1/28/21) - - Client (thanks to a PR from Team California Roll) - - Display team income - - Represent conviction with unit size - -- Version 2021.3.0.2 (1/23/21) - - Fix client buff display - -- Version 2021.3.0.1 (1/22/21) - - No changes: redeploy was needed for technical reasons - -- Version 2021.3.0.0 (1/22/21) - - Muckraker buff changed from exponential to linear (1st order Taylor expansion) - - Buff has no effect on friendly enlightnment centers - - Empowering now gets taxed before buff is applied - -- Version 2021.2.4.3 (1/20/21) - - Make new maps visible in Client - - Fix bid tracking - -- Version 2021.2.4.2 (1/20/21) - - Release Sprint 2 maps - - Client - - Allow upload of .map21 files in map editor - - Track max bids (losing bids are only tracked for new replays) - -- Version 2021.2.4.1 (1/16/21) - - Client - - Track more info (buffs will only work for new replays) - - Add profiler (thanks to a PR from Team camel_case) - -- Version 2021.2.4.0 (1/16/21) - - Interface change: - - `senseNearbyRobots` and `detectNearbyRobots` no longer give any guarantees on return order. - - Map update: - - All map neutral ECs are now legal. - - Exclude map Cow from scrimmages as it is too large (you can keep it for testing if you want). - - Bug fix: - - Fix issue where EC conviction and influence become unequal after big flip. - -- Version 2021.2.3.0 (1/13/21) - - Reduce number of rounds per game (3000 -> 1500) - - Upload maps from Sprint Tournament 1 - -- Version 2021.2.2.0 (1/12/21) - - Limit maximum robot influence to $10^8$, and supply `GameConstants.ROBOT_INFLUENCE_LIMIT`. - -- Version 2021.2.1.2 (1/11/21) - - Client - - Track more information - - Small visual changes - -- Version 2021.2.1.1 (1/11/21) - - Properly include the engine sources with the deployment - -- Version 2021.2.1.0 (1/11/21) - - Add command-line option to disable all indicator dots. - Can be achieved by adding `-Dbc.engine.show-indicators=false` to the `build.gradle` file. - -- Version 2021.2.0.3 (1/10/21) - - Client - - Revamp map editor (thanks to a PR from Team Double J) - - Performance improvements - - Terraformed Mars - -- Version 2021.2.0.2 (1/8/21) - - Fix incorrect muckraker initial cooldown (15 -> 10) - -- Version 2021.2.0.1 (1/8/21) - - Finish incomplete release - -- Version 2021.2.0.0 (1/8/21) - - Breaking changes: - - Change slanderer influence function from linear to exponential decay, preventing exponential growth - - Remove `GameConstants.MAX_ROBOT_ID` - (cannot guarantee reasonable upper bound as new IDs are generated when robots change teams) - - Major game spec changes: - - Newly built politicians and muckrakers have an action cooldown of 10 rounds - - Guarantee no more than 6 neutral Enlightenment Centers - - Other adjusted constants - - Muckraker buff exponentiation base decreased from 1.01 to 1.001 - - Significantly increased bytecode limits - - New features: - - Add `RobotController::expose(int id)` - - New maps for experimentation - - Add option to disable logs processing in client - - Bug fixes - - Fix reset of non-fatal damage to units - - Minor client bug fixes - -- Version 2021.1.0.3 (1/5/21) - - Spec clarifications: - - Clarify cooldowns for Enlightenment Center abilities - - Clarify what happens on robot team conversion - - Client bugfixes - - Corrected influence and conviction tracking - - Handles neutral enlightenment centers - - Fixed animations and various crashes during game playback - -- Version 2021.1.0.2 (1/4/21) - - Registered maptestsmall in client - -- Version 2021.1.0.1 (1/4/21) - - Fixed map extensions in client, scaffold - - Implemented enlightenment centers can get flags of all bots - -- Version 2021.1.0.0 (1/4/21) - - Initial release +Bytecodes relating to the creation of arrays (specifically `NEWARRAY`, `ANEWARRAY`, and `MULTIANEWARRAY`; see [here](https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings) for reference) have an effective cost greater than a single bytecode. This is because these instructions, although they are represented as a single bytecode, can be vastly more expensive than other instructions in terms of computational cost. To remedy this, these instructions have a bytecode cost equal to the total length of the instantiated array. Note that this should have minimal impact on the typical team, and is only intended to prevent teams from repeatedly instantiating excessively large arrays. + +# Appendix: Lingering questions and clarifications + +If something is unclear, direct your questions to our Discord where other people may have the same question. We'll update this spec as the competition progresses. + +# Appendix: Changelog + +- Version 2.2.1 (January 6, 2023) + - Updated deploy scripts for new Battlecode infrastructure + +- Version 2022.2.1.0 (January 26, 2022) + - Engine: + - Fix bug impacting correct Vortex Anomaly behavior + - Qualifying tournament maps released + +- Version 2022.2.0.1 (January 20, 2022) + - Client: + - Release maps from Sprint II too + - Specs: + - Minor typographic and stylistic improvements + +- Version 2022.2.0.0 (January 18, 2022) + - Breaking changes: Sprint II Balancing changes + - Archons: + - Decrease level 2 Mutation cost to 300 Pb + - Watchtowers: + - Decrease initial cost to 150 Pb + - Decrease level 2 Mutation cost to 150 Pb + - Laboratories: + - Decrease build cost to 180 Pb + - Decrease level 2 Mutation cost to 150 Pb + - Change exchange rate constants to $A=20, B=18$ + - Change exchange rate constant $k$ to 0.02 for level 1, 0.01 for level 2, 0.005 for level 3 + - Miners: + - Increase bytecode limit to 10,000 + - Builders: + - Increase attack to -2 (ie. repair to 2) + - Sages: + - Increase action radius to 25 + - Increase Abyss depletion rate to 99% + - Increase Charge damage rate to 22% + - Lead regeneration: + - Increase rate to 5 Pb every 20 turns + - Client: + - Visualize repair actions and Anomalies + - Add health bar + - Shift attack visualizations so they do not overlap + - Sprint maps released + +- Version 2022.1.0.2 (January 16, 2022) + - Engine: + - Trigger tiebreakers if all Archons are destroyed simultaneously during Fury. + - Add some map validation to main server (thanks @stefangimmillaro!) + +- Version 2022.1.0.1 (January 12, 2022) + - Engine: + - Remove initial cooldown for all newly built robots + - Fix bug in lead and gold sensing functions + +- Version 2022.1.0.0 (January 11, 2022) + - Breaking changes: Sprint I Balancing changes + - Archons: + - Decrease nominal worth to 100 Au + - Decrease level 2 Mutation cost to 400 Pb + - Decrease level 3 Mutation cost to 80 Au + - Change mutation health to 600 → 1080 → 1944 + - Change mutation repair to 2 → 4 → 6 + - Watchtowers: + - Decrease level 2 Mutation cost to 200 Pb + - Decrease level 3 Mutation cost to 60 Au + - Charge mutation health to 150 → 270 → 486 + - Change mutation damage to 4 → 8 → 12 + - Laboratories: + - Decrease build cost to 250 Pb + - Decrease level 2 Mutation cost to 200 Pb + - Decrease level 3 Mutation cost to 25 Au + - Change mutation health to 100 → 180 → 324 + - Sages: + - Decrease build cost to 20 Au + - Increase action radius to 20 + - Increase vision radius to 34 + - Lead regeneration: + - Decrease rate to 3 Pb every 40 turns + - Sprint maps released + +- Version 2022.0.3.1 (January 10, 2022) + - Client: + - Fix robot selection on (0, 0) + - Fix gold income + - Improvements to runner team selection (thanks @jmerle!) + - Other: + - Improvements to Javadoc deploy script + +- Version 2022.0.3.0 (January 9, 2022) + - Engine: + - (New feature) Add overloads for sensing nearby locations with metals + - Do not dump debug map information at start of match + - Client: + - Track HP change on mutations and fix DP display + - Running averages for lead and gold income + - Other: + - Javadocs are 2022, not 2017 + +- Version 2022.0.2.0 (January 5, 2022) + - Engine: + - (New feature) Add `rc.senseNearbyLocationsWithLead` and `rc.senseNearbyLocationsWithGold` + - Make passive Lead increase occur after Anomalies are processed + - Client: + - Fix portable Archon display + - Fix mutation tracking + - Update help text + - Fix Vortex anomaly rendering + - Other: + - Improvements to release scripts + +- Version 2022.0.1.1 (January 4, 2022) + - Specs: + - Clarify that Archons are not guaranteed to have ID at least 10,000 + - Update various URLs + - Engine: + - Fix Archon damage to always be negative (ie. repair) + - Fix maximum value for communication array to actually be $2^{16}-1$ + +- Version 2022.0.1.0 (January 3, 2022) + - Initial release