├── .gitattributes ├── .github └── workflows │ ├── fuzz.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── CITATION.cff ├── LICENSE ├── Makefile ├── README.md ├── build.zig ├── docs ├── CONTRIBUTING.md ├── DESIGN.md ├── NOTES.md ├── PROTOCOL.md ├── RESEARCH.md └── TESTING.md ├── eslint.config.mjs ├── examples ├── c │ ├── Makefile │ └── example.c ├── js │ ├── .parcelrc │ ├── example.ts │ ├── index.html │ ├── package.json │ ├── tsconfig.json │ └── vite.config.mts └── zig │ ├── example.zig │ ├── legacy │ ├── build.zig │ ├── example.zig │ └── lib │ │ └── pkmn │ └── modern │ ├── build.zig │ ├── build.zig.zon │ └── example.zig ├── package.json ├── src ├── bin │ ├── install-pkmn-engine │ └── pkmn-debug ├── data │ ├── data.json │ ├── layout.json │ └── protocol.json ├── include │ └── pkmn.h ├── lib │ ├── bindings │ │ ├── c.zig │ │ ├── node.zig │ │ └── wasm.zig │ ├── c.zig │ ├── common │ │ ├── array.zig │ │ ├── battle.zig │ │ ├── data.zig │ │ ├── data │ │ │ ├── items.zig.tmpl │ │ │ ├── moves.zig.tmpl │ │ │ ├── species.zig.tmpl │ │ │ └── types.zig.tmpl │ │ ├── debug.zig │ │ ├── js.zig │ │ ├── napi.zig │ │ ├── optional.zig │ │ ├── options.zig │ │ ├── protocol.zig │ │ ├── rational.zig │ │ ├── rng.zig │ │ ├── test.zig │ │ └── util.zig │ ├── gen1 │ │ ├── README.md │ │ ├── calc.zig │ │ ├── chance.zig │ │ ├── data.zig │ │ ├── data │ │ │ ├── moves.zig │ │ │ ├── species.zig │ │ │ └── types.zig │ │ ├── helpers.zig │ │ ├── mechanics.zig │ │ └── test.zig │ ├── gen2 │ │ ├── README.md │ │ ├── calc.zig │ │ ├── chance.zig │ │ ├── data.zig │ │ ├── data │ │ │ ├── items.zig │ │ │ ├── moves.zig │ │ │ ├── species.zig │ │ │ └── types.zig │ │ ├── generated.zig │ │ ├── helpers.zig │ │ ├── mechanics.zig │ │ └── test.zig │ ├── node.zig │ ├── pkmn.zig │ ├── test.zig │ └── wasm.zig ├── pkg │ ├── addon.test.ts │ ├── addon.ts │ ├── addon │ │ ├── browser.ts │ │ ├── node.ts │ │ └── wasm.ts │ ├── common.test.ts │ ├── common.ts │ ├── data.test.ts │ ├── data.ts │ ├── data │ │ ├── ids.json │ │ ├── layout.json │ │ ├── mapping.json │ │ └── protocol.json │ ├── fixtures │ │ ├── p1.txt │ │ └── p2.txt │ ├── gen1.test.ts │ ├── gen1.ts │ ├── index.test.ts │ ├── index.ts │ ├── protocol.test.ts │ └── protocol.ts ├── test │ ├── README.md │ ├── benchmark.test.ts │ ├── benchmark.ts │ ├── benchmark.zig │ ├── fixtures │ │ └── gen1 │ │ │ ├── 0x11C7F5D02584A5A4.input.log │ │ │ ├── 0x130C2A0BF1934A4C.showdown.bin │ │ │ ├── 0x138CA5166EFF6A9.input.log │ │ │ ├── 0x166525E4E3DD0132.input.log │ │ │ ├── 0x1A2182BB0BBD9E64.showdown.bin │ │ │ ├── 0x1C6394FF9C3565F4.pkmn.bin │ │ │ ├── 0x1EE16974B4257C8E.input.log │ │ │ ├── 0x208E374CB1E2F97F.input.log │ │ │ ├── 0x20C2659866E5ED21.input.log │ │ │ ├── 0x219E8F9B8DFA3E50.pkmn.bin │ │ │ ├── 0x2E41948934F9D949.input.log │ │ │ ├── 0x2E5A75A49C4B8EA4.input.log │ │ │ ├── 0x306C5E0779663612.input.log │ │ │ ├── 0x30B477546C73D7BC.input.log │ │ │ ├── 0x317C2C25C222F280.input.log │ │ │ ├── 0x39CCE4D290A254CD.input.log │ │ │ ├── 0x3AAFC8792686FE24.input.log │ │ │ ├── 0x43952058CEDD7279.input.log │ │ │ ├── 0x46C1FA4F5C3A1B4B.showdown.bin │ │ │ ├── 0x479DCF7B406B5186.input.log │ │ │ ├── 0x48ADAAC95C9CC04A.input.log │ │ │ ├── 0x490175968B905049.input.log │ │ │ ├── 0x4AE7643BF1626D6C.input.log │ │ │ ├── 0x510BC88B7E670BB9.pkmn.bin │ │ │ ├── 0x53821EB41ED3144A.input.log │ │ │ ├── 0x582807711B0A22D.pkmn.bin │ │ │ ├── 0x5BB7D44744B7DDB5.input.log │ │ │ ├── 0x5C0BFA662F064934.input.log │ │ │ ├── 0x5C0EF6E4C9278E03.input.log │ │ │ ├── 0x5DB1BB2DED9461F2.input.log │ │ │ ├── 0x5F4C27C3C400CCEF.input.log │ │ │ ├── 0x62D8FB8ED11CDD7D.input.log │ │ │ ├── 0x63F75EBC9E2B6DF8.input.log │ │ │ ├── 0x6861A8111EF46045.input.log │ │ │ ├── 0x6C979DFBC6743D5C.input.log │ │ │ ├── 0x6EFF8B7677077FE6.input.log │ │ │ ├── 0x762098D67285A45A.input.log │ │ │ ├── 0x7DE5A2DD96BA07A5.input.log │ │ │ ├── 0x842EFA1D879EC636.showdown.bin │ │ │ ├── 0x87CB47D78C9E83DB.input.log │ │ │ ├── 0x891A4DEC2DA0D04A.input.log │ │ │ ├── 0x895A570B71E79B86.input.log │ │ │ ├── 0x898990C029C4E108.input.log │ │ │ ├── 0x89A935237DDA962E.showdown.bin │ │ │ ├── 0x8C9747603D30586E.input.log │ │ │ ├── 0x924FD037527C65A3.input.log │ │ │ ├── 0x973C10A9C58D94FD.input.log │ │ │ ├── 0x973EF0823E0530B9.input.log │ │ │ ├── 0x9C329D229CD33ED7.input.log │ │ │ ├── 0x9E2B535EAB26BB7E.input.log │ │ │ ├── 0x9FFAFACA6FEECB03.input.log │ │ │ ├── 0xA0406E4B3AA33F5E.input.log │ │ │ ├── 0xA0F50070ADB32DED.input.log │ │ │ ├── 0xA31F27EAF9BF4E3B.input.log │ │ │ ├── 0xA99BCE90DBE18670.pkmn.bin │ │ │ ├── 0xAF52B504F51A337C.pkmn.bin │ │ │ ├── 0xB265471DCC2DDDC8.input.log │ │ │ ├── 0xB5A6F7607C1F2AFD.input.log │ │ │ ├── 0xB679D91D90ED0486.input.log │ │ │ ├── 0xB758AB5F9D7AD36D.input.log │ │ │ ├── 0xB9131B7324E482AD.input.log │ │ │ ├── 0xB9A1A38FCBBF6648.input.log │ │ │ ├── 0xBABA377EE1638987.input.log │ │ │ ├── 0xBB26504CA21FA2C0.input.log │ │ │ ├── 0xBB75F6633DBA4C08.input.log │ │ │ ├── 0xBC0AF7D28AA6F25F.input.log │ │ │ ├── 0xBC867937B5A262F8.input.log │ │ │ ├── 0xBCC4F5F803A4C0C5.input.log │ │ │ ├── 0xC1F3A1A3CBF66E2B.input.log │ │ │ ├── 0xC2A02FC2F3D1EF24.input.log │ │ │ ├── 0xC40D2C12D0F8185D.input.log │ │ │ ├── 0xC468FF6E1CEE314D.pkmn.bin │ │ │ ├── 0xC58F31E184357C16.input.log │ │ │ ├── 0xC8524A847B4AF353.input.log │ │ │ ├── 0xCA20018840CC123.pkmn.bin │ │ │ ├── 0xCB56DFD6457B04BA.input.log │ │ │ ├── 0xCC64741157FC11DB.pkmn.bin │ │ │ ├── 0xCDD8EB1C112F2B02.input.log │ │ │ ├── 0xCDE87ADE2DEA69C.input.log │ │ │ ├── 0xCE3086F839722570.input.log │ │ │ ├── 0xCE87A7774C1AAB24.input.log │ │ │ ├── 0xCF83C12D71CE716D.pkmn.bin │ │ │ ├── 0xD2B1817739AAF4B3.input.log │ │ │ ├── 0xD463BA4C49D333F3.input.log │ │ │ ├── 0xDAF1C0765173FF0F.input.log │ │ │ ├── 0xDAFD0E44A75472CB.input.log │ │ │ ├── 0xDC1E0DB334E0EAF2.input.log │ │ │ ├── 0xDDE61D4454448DA8.input.log │ │ │ ├── 0xE1C1F3089C963B91.input.log │ │ │ ├── 0xE26C9A0D11C52B93.input.log │ │ │ ├── 0xE2D929DD7D14C5F4.showdown.bin │ │ │ ├── 0xE331C7BB28218AD3.input.log │ │ │ ├── 0xE3FE59D3E25042F4.input.log │ │ │ ├── 0xE47319978AD041B1.input.log │ │ │ ├── 0xE6412ECA6071C6D4.pkmn.bin │ │ │ ├── 0xE7E6B0F82286A08B.input.log │ │ │ ├── 0xEBEC48B906A37945.pkmn.bin │ │ │ ├── 0xEC4103CD675CDAA1.input.log │ │ │ ├── 0xEC906D7B433288F0.pkmn.bin │ │ │ ├── 0xED1F32123199F701.input.log │ │ │ ├── 0xED964909377B7E8E.input.log │ │ │ ├── 0xEFAA766A8ED2D5BF.showdown.bin │ │ │ ├── 0xF091D4934DA9A368.input.log │ │ │ ├── 0xF12F2AB7B055F0E7.input.log │ │ │ ├── 0xF2D588816B2E321C.input.log │ │ │ ├── 0xF783B7B8A7EC8BE6.input.log │ │ │ ├── 0xF9035DA297392F5D.input.log │ │ │ └── 0xFFD857F18AB7602.input.log │ ├── fuzz.test.ts │ ├── fuzz.ts │ ├── fuzz.zig │ ├── integration.test.ts │ ├── integration.ts │ ├── regression.test.ts │ ├── showdown.html.tmpl │ ├── showdown.ts │ ├── showdown │ │ ├── gen1.test.ts │ │ └── gen2.test.ts │ └── stats.ts └── tools │ ├── README.md │ ├── analyze.zig │ ├── debug.ts │ ├── demo.ts │ ├── demo.zig │ ├── display │ ├── autocomplete.old.css │ ├── autocomplete.old.ts │ ├── debug.css │ ├── debug.tsx │ ├── demo.tsx │ ├── dom.ts │ ├── index.ts │ ├── select.css │ ├── select.tsx │ ├── ui.css │ ├── ui.tsx │ └── util.ts │ ├── dump.zig │ ├── generate.ts │ ├── release.ts │ ├── serde.ts │ ├── serde.zig │ ├── transitions.zig │ ├── version.zig │ └── vscode │ ├── LICENSE │ ├── README.md │ ├── extension.ts │ └── package.json ├── tsconfig.json ├── vite.config.mts └── zig.patch /.gitattributes: -------------------------------------------------------------------------------- 1 | # Windows 2 | * text=auto 3 | *.zig text=auto eol=lf 4 | *.zon text=auto eol=lf 5 | 6 | # Binary 7 | *.bin binary 8 | 9 | # GitHub 10 | src/data/* linguist-generated=true 11 | src/lib/gen1/data/* linguist-generated=true 12 | src/lib/gen2/data/* linguist-generated=true 13 | src/lib/gen2/generated.zig linguist-generated=true 14 | src/pkg/data/* linguist-generated=true 15 | src/pkg/data/mapping.json linguist-generated=false 16 | -------------------------------------------------------------------------------- /.github/workflows/fuzz.yml: -------------------------------------------------------------------------------- 1 | name: Fuzz 2 | on: 3 | schedule: 4 | - cron: '36 */6 * * *' 5 | push: 6 | branches: [ main ] 7 | pull_request: 8 | branches: [ main ] 9 | workflow_dispatch: 10 | concurrency: 11 | group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} 12 | cancel-in-progress: true 13 | jobs: 14 | fuzz: 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | gen: [1] 19 | options: ['', '-Dshowdown'] 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: scheibo/build-zig@main 24 | with: 25 | patch-file: zig.patch 26 | - run: npm install --ignore-scripts 27 | - run: zig build -Doptimize=ReleaseSafe -Dlog -Dchance -Dcalc ${{matrix.options}} fuzz -- ${{matrix.gen}} 15m | tee seed.txt 28 | shell: bash 29 | - run: | 30 | node src/bin/install-pkmn-engine 31 | npm run --silent fuzz -- ${{matrix.options == '' && 'pkmn' || 'showdown' }} ${{matrix.gen}} 1s $(cat seed.txt) 32 | if: failure() 33 | - run: | 34 | node src/bin/install-pkmn-engine --options="-Dshowdown -Dlog -Dchance -Dcalc" 35 | npm run integration -- --gen=${{matrix.gen}} --duration=15m --maxFailures=5 --debug=false 36 | if: ${{ matrix.options != '' }} 37 | - uses: actions/upload-artifact@v4 38 | if: failure() 39 | with: 40 | name: logs 41 | path: logs 42 | if-no-files-found: error 43 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | schedule: 4 | - cron: '0 2 * * *' 5 | workflow_dispatch: 6 | jobs: 7 | test: 8 | uses: ./.github/workflows/test.yml 9 | release: 10 | needs: test 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v4 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: 20 17 | registry-url: 'https://registry.npmjs.org' 18 | scope: '@pkmn' 19 | - uses: scheibo/build-zig@main 20 | with: 21 | patch-file: zig.patch 22 | - run: npm install --ignore-scripts 23 | - run: npm run release 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | push: 4 | branches: [ main ] 5 | pull_request: 6 | branches: [ main ] 7 | workflow_dispatch: 8 | workflow_call: 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} 11 | cancel-in-progress: true 12 | jobs: 13 | test: 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | os: [ubuntu-latest, macos-latest, windows-latest] 18 | options: ['', '-Dlog -Dchance -Dcalc', '-Dshowdown', '-Dshowdown -Dlog -Dchance -Dcalc'] 19 | zig: [local, 0.14.0, master] # local = 0.11.0 20 | exclude: 21 | - os: windows-latest 22 | zig: local 23 | runs-on: ${{matrix.os}} 24 | steps: 25 | - uses: actions/checkout@v4 26 | - run: git config core.symlinks true 27 | # NOTE: we rely on npm postinstall-ed zig for local zig 28 | - uses: goto-bus-stop/setup-zig@default 29 | if: ${{ matrix.zig != 'local' }} 30 | with: 31 | version: ${{matrix.zig}} 32 | - run: npm install 33 | - run: echo "${GITHUB_WORKSPACE}/build/bin/zig" >> $GITHUB_PATH 34 | if: ${{ matrix.zig == 'local' && matrix.os != 'windows-latest' }} 35 | - run: echo "${env:GITHUB_WORKSPACE}/build/bin/zig" >> $env:GITHUB_PATH 36 | if: ${{ matrix.zig == 'local' && matrix.os == 'windows-latest' }} 37 | - run: zig build test ${{matrix.options}} 38 | - run: zig build test ${{matrix.options}} -Doptimize=ReleaseFast 39 | - run: npm run compile 40 | - run: npm test 41 | - run: node src/bin/install-pkmn-engine --options="${{matrix.options}}" 42 | - run: npm run test:integration 43 | - run: zig build ${{matrix.options}} -p build 44 | - run: make example options="${{matrix.options}}" 45 | - uses: AnnikaCodes/install-ziglint@main 46 | with: 47 | token: ${{ secrets.GITHUB_TOKEN }} 48 | - run: make lint 49 | - run: make clean && node src/bin/install-pkmn-engine --zig 50 | - run: zig build ${{matrix.options}} -p build -Ddynamic 51 | - run: make c-example options="${{matrix.options}}" dynamic=true 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac 2 | .DS_Store 3 | Thumbs.db 4 | .vscode 5 | 6 | # Zig 7 | .zig-cache/ 8 | zig-cache/ 9 | zig-out/ 10 | build/ 11 | /docgen_tmp/ 12 | 13 | # C 14 | *.o 15 | 16 | # JS 17 | coverage/ 18 | node_modules/ 19 | dist/ 20 | *package-lock.json 21 | *npm-debug.log 22 | .eslintcache 23 | .tsbuildinfo 24 | .parcel-cache/ 25 | 26 | # Project 27 | .cache 28 | examples/c/example 29 | examples/zig/zig-cache 30 | logs/ 31 | release/ 32 | !src/test/fixtures/*/*.log 33 | src/tools/vscode/extension.js 34 | *.vsix 35 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | title: libpkmn 3 | type: software 4 | authors: 5 | - given-names: Kirk 6 | family-names: Scheibelhut 7 | email: pre@pkmn.cc 8 | orcid: 'https://orcid.org/0009-0004-7829-4237' 9 | license: MIT 10 | url: 'https://pkmn.cc/engine' 11 | repository-code: 'https://github.com/pkmn/engine' 12 | repository-artifact: 'https://github.com/pkmn/engine/releases/' 13 | abstract: >- 14 | libpkmn is minimal, complete, Pokémon battle simulation engine optimized for 15 | performance and designed for tooling, embedded systems, and artificial 16 | intelligence use cases. This engine aims to be a frame-accurate and 17 | bug-for-bug compatible implementation of both Pokémon battles as defined by 18 | the original game code and the Pokémon Showdown simulator which represents 19 | Pokémon battling as practically interpreted online. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2025 pkmn contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so, 8 | subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 15 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 16 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 17 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 18 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 19 | -------------------------------------------------------------------------------- /docs/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Please read through the [README](../README.md), [docs](../docs), and 4 | [pkmn.cc/@pkmn](https://pkmn.cc/@pkmn/) for general information about the pkmn engine and about 5 | development on `@pkmn` projects respectively. The pkmn engine Zig code loosely adheres to the [style 6 | guidelines outlined by 7 | TigerBeetle](https://github.com/tigerbeetledb/tigerbeetle/blob/main/docs/TIGER_STYLE.md), whereas 8 | the TypeScript code follows the usual [`@pkmn` style](https://pkmn.cc/@pkmn/#style). When opening 9 | issues or pull requests, please use one of the existing templates and fill them out to the best of 10 | your ability. Pull requests are unlikely to be merged without tests, but it's fine to open a pull 11 | request without tests for feedback or to ask for help with testing. :) 12 | 13 | The best way to help contribute to the pkmn engine is actually to contribute to the upstream 14 | projects that the engine depends on - fixing bugs/simplifying 15 | [smogon/pokemon-showdown](https://github.com/smogon/pokemon-showdown) or improving/clarifying the 16 | [pret](https://github.com/pret) decompilations are the highest impact ways to benefit not just the 17 | engine but the larger Pokémon development community. 18 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import pkmn from "@pkmn/eslint-config"; 2 | 3 | export default [...pkmn, { 4 | files: ["src/bin/!(*.*)"], 5 | }, { 6 | ignores: ["dist/", "node_modules/", "examples/zig", "build/", "src/tools/vscode/extension.js"], 7 | }, { 8 | files: ["src/pkg/common.ts", "src/pkg/index.ts", "src/test/integration.ts"], 9 | rules: { 10 | "no-control-regex": "off", 11 | "@typescript-eslint/no-empty-interface": "off", 12 | "@typescript-eslint/no-shadow": "off", 13 | "@typescript-eslint/no-unsafe-declaration-merging": "off" 14 | } 15 | }, { 16 | files: ["src/pkg/addon/node.ts", "src/tools/debug.ts"], 17 | rules: { 18 | "@typescript-eslint/no-var-requires": "off", 19 | "@typescript-eslint/no-require-imports": "off", 20 | } 21 | },{ 22 | files: ["src/test/benchmark*.ts"], 23 | rules: { 24 | "@typescript-eslint/no-unused-vars": "off", 25 | "@typescript-eslint/no-redundant-type-constituents": "off" 26 | } 27 | }, { 28 | files: ["src/pkg/protocol.test.ts"], 29 | rules: {"jest/no-standalone-expect": "off", "jest/no-conditional-expect": "off"} 30 | }, { 31 | files: ["src/test/*.test.ts"], 32 | rules: {"jest/no-standalone-expect": "off"} 33 | }, { 34 | files: ["src/test/showdown/**"], 35 | rules: {"jest/expect-expect": ["warn", {assertFunctionNames: ["expect", "expectLog", "verify"]}]} 36 | }, { 37 | files: ["src/test/fuzz.ts", "src/tools/serde.ts"], 38 | rules: {"@typescript-eslint/prefer-promise-reject-errors": "off"}, 39 | }, { 40 | files: ["src/tools/generate.ts"], 41 | rules: {"@typescript-eslint/restrict-template-expressions": ["error", {"allowBoolean": true}]} 42 | }]; 43 | -------------------------------------------------------------------------------- /examples/js/.parcelrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@parcel/config-default"], 3 | "reporters": ["...", "parcel-reporter-static-files-copy"] 4 | } -------------------------------------------------------------------------------- /examples/js/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @pkmn/engine 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@pkmn/data": "^0.9.31", 4 | "@pkmn/dex": "^0.9.31", 5 | "@pkmn/engine": "file:../..", 6 | "@pkmn/sets": "^5.1.2" 7 | }, 8 | "devDependencies": { 9 | "parcel-reporter-static-files-copy": "^1.5.3", 10 | "parcel": "^2.13.3", 11 | "vite-plugin-commonjs": "^0.10.4", 12 | "vite": "^6.2.0", 13 | "typescript": "^5.8.2" 14 | }, 15 | "scripts": { 16 | "prestart": "tsc -p .", 17 | "start": "node build/example.js", 18 | "start:web": "npm run start:vite", 19 | "start:parcel": "parcel --no-autoinstall index.html", 20 | "start:vite": "vite" 21 | }, 22 | "alias": { 23 | "process": { 24 | "global": "process" 25 | } 26 | }, 27 | "staticFiles": { 28 | "staticPath": "node_modules/@pkmn/engine/build/lib/pkmn-showdown.wasm" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": ["vite.config.mts"], 3 | "compilerOptions": { 4 | "downlevelIteration": true, 5 | "outDir": "build", 6 | "rootDir": ".", 7 | "sourceMap": true, 8 | "strict": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/js/vite.config.mts: -------------------------------------------------------------------------------- 1 | import commonjs from 'vite-plugin-commonjs'; 2 | 3 | export default { 4 | publicDir: 'node_modules/@pkmn/engine/build/lib', 5 | plugins: [commonjs()] 6 | } -------------------------------------------------------------------------------- /examples/zig/legacy/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const pkmn = @import("lib/pkmn/build.zig"); 3 | 4 | pub fn build(b: *std.Build) void { 5 | const target = b.standardTargetOptions(.{}); 6 | const optimize = b.standardOptimizeOption(.{}); 7 | 8 | const showdown = b.option(bool, "showdown", "Enable Pokémon Showdown compatibility mode"); 9 | const log = b.option(bool, "log", "Enable protocol message logging"); 10 | 11 | const exe = b.addExecutable(.{ 12 | .name = "example", 13 | .root_source_file = .{ .path = "example.zig" }, 14 | .optimize = optimize, 15 | .target = target, 16 | }); 17 | const module = pkmn.module(b, .{ .showdown = showdown, .log = log }); 18 | if (@hasField(@TypeOf(exe.*), "root_module")) { 19 | exe.root_module.addImport("pkmn", module); 20 | } else { 21 | exe.addModule("pkmn", module); 22 | } 23 | b.installArtifact(exe); 24 | 25 | const run_cmd = b.addRunArtifact(exe); 26 | run_cmd.step.dependOn(b.getInstallStep()); 27 | if (b.args) |args| run_cmd.addArgs(args); 28 | 29 | const run_step = b.step("run", "Run the app"); 30 | run_step.dependOn(&run_cmd.step); 31 | } 32 | -------------------------------------------------------------------------------- /examples/zig/legacy/example.zig: -------------------------------------------------------------------------------- 1 | ../example.zig -------------------------------------------------------------------------------- /examples/zig/legacy/lib/pkmn: -------------------------------------------------------------------------------- 1 | ../../../.. -------------------------------------------------------------------------------- /examples/zig/modern/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.Build) void { 4 | const target = b.standardTargetOptions(.{}); 5 | const optimize = b.standardOptimizeOption(.{}); 6 | 7 | const showdown = 8 | b.option(bool, "showdown", "Enable Pokémon Showdown compatibility mode") orelse false; 9 | const log = b.option(bool, "log", "Enable protocol message logging") orelse false; 10 | 11 | const exe = b.addExecutable(.{ 12 | .name = "example", 13 | .root_source_file = if (@hasField(std.Build.LazyPath, "path")) 14 | .{ .path = "example.zig" } 15 | else 16 | b.path("example.zig"), 17 | .optimize = optimize, 18 | .target = target, 19 | }); 20 | const pkmn = b.dependency("pkmn", .{ .showdown = showdown, .log = log }); 21 | exe.root_module.addImport("pkmn", pkmn.module("pkmn")); 22 | b.installArtifact(exe); 23 | 24 | const run_cmd = b.addRunArtifact(exe); 25 | run_cmd.step.dependOn(b.getInstallStep()); 26 | if (b.args) |args| run_cmd.addArgs(args); 27 | 28 | const run_step = b.step("run", "Run the app"); 29 | run_step.dependOn(&run_cmd.step); 30 | } 31 | -------------------------------------------------------------------------------- /examples/zig/modern/build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = .example, 3 | .version = "0.0.1", 4 | .fingerprint = 0x6eec9b9ff9b9cee6, 5 | .minimum_zig_version = "0.14.0", 6 | .paths = .{"."}, 7 | .dependencies = .{ 8 | .pkmn = .{ .path = "../../.." }, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /examples/zig/modern/example.zig: -------------------------------------------------------------------------------- 1 | ../example.zig -------------------------------------------------------------------------------- /src/bin/pkmn-debug: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 'use strict'; 3 | 4 | try { 5 | require('source-map-support').install(); 6 | } catch (err) { 7 | if (err.code !== 'MODULE_NOT_FOUND') throw err; 8 | } 9 | 10 | const {execFileSync} = require('child_process'); 11 | const {readFileSync} = require('fs'); 12 | const {join, resolve} = require('path'); 13 | 14 | const ROOT = resolve(__dirname, '..', '..'); 15 | const packageJSON = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8')); 16 | 17 | const missing = []; 18 | for (const dep of ['@pkmn/img', 'html-minifier', 'esbuild']) { 19 | try { 20 | require.resolve(dep); 21 | } catch (e) { 22 | if (e.code !== 'MODULE_NOT_FOUND') throw e; 23 | missing.push(`${dep}@${packageJSON.devDependencies[dep]}`); 24 | } 25 | } 26 | 27 | let Dex = undefined; 28 | try { 29 | Dex = require('@pkmn/sim').Dex; 30 | } catch (err) { 31 | if (err.code !== 'MODULE_NOT_FOUND') throw err; 32 | try { 33 | Dex = require('@pkmn/dex').Dex; 34 | } catch (e) { 35 | if (e.code !== 'MODULE_NOT_FOUND') throw e; 36 | missing.push(`@pkmn/dex@${packageJSON.dependencies['@pkmn/data']}`); 37 | } 38 | } 39 | 40 | if (missing.length) { 41 | if (+/^v(\d+)/.exec(process.version)[1] < 16) { 42 | console.error('pkmn-debug requires Node v16+'); 43 | process.exit(1); 44 | } 45 | 46 | execFileSync('npm', ['install', ...missing, '--global'], {encoding: 'utf8'}); 47 | 48 | const node_modules = execFileSync('npm', ['root', '--global'], {encoding: 'utf8'}).trim(); 49 | if (!process.env.NODE_PATH || !process.env.NODE_PATH.includes(node_modules)) { 50 | console.error(`NODE_PATH must include npm's global node_modules directory: '${node_modules}'`); 51 | process.exit(1); 52 | } 53 | } 54 | 55 | const {Generations} = require('@pkmn/data'); 56 | 57 | const {run} = require('../../build/tools/debug'); 58 | 59 | run(new Generations(Dex)).catch(err => { 60 | console.error(err.message); 61 | process.exit(1); 62 | }); 63 | -------------------------------------------------------------------------------- /src/data/layout.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "sizes": { 4 | "Battle": 384, 5 | "Side": 184, 6 | "Pokemon": 24, 7 | "ActivePokemon": 32, 8 | "Actions": 16, 9 | "Durations": 8, 10 | "Summaries": 12 11 | }, 12 | "offsets": { 13 | "Battle": { 14 | "sides": 0, 15 | "turn": 368, 16 | "last_damage": 370, 17 | "last_moves": 372, 18 | "rng": 374 19 | }, 20 | "Side": { 21 | "pokemon": 0, 22 | "active": 144, 23 | "order": 176, 24 | "last_selected_move": 182, 25 | "last_used_move": 183 26 | }, 27 | "Pokemon": { 28 | "stats": 0, 29 | "moves": 10, 30 | "hp": 18, 31 | "status": 20, 32 | "species": 21, 33 | "types": 22, 34 | "level": 23 35 | }, 36 | "ActivePokemon": { 37 | "stats": 0, 38 | "species": 10, 39 | "types": 11, 40 | "boosts": 12, 41 | "volatiles": 16, 42 | "moves": 24 43 | }, 44 | "Stats": { 45 | "hp": 0, 46 | "atk": 2, 47 | "def": 4, 48 | "spe": 6, 49 | "spc": 8 50 | }, 51 | "Boosts": { 52 | "atk": 0, 53 | "def": 4, 54 | "spe": 8, 55 | "spc": 12, 56 | "accuracy": 16, 57 | "evasion": 20 58 | }, 59 | "Volatiles": { 60 | "Bide": 0, 61 | "Thrashing": 1, 62 | "MultiHit": 2, 63 | "Flinch": 3, 64 | "Charging": 4, 65 | "Binding": 5, 66 | "Invulnerable": 6, 67 | "Confusion": 7, 68 | "Mist": 8, 69 | "FocusEnergy": 9, 70 | "Substitute": 10, 71 | "Recharging": 11, 72 | "Rage": 12, 73 | "LeechSeed": 13, 74 | "Toxic": 14, 75 | "LightScreen": 15, 76 | "Reflect": 16, 77 | "Transform": 17, 78 | "confusion": 18, 79 | "attacks": 21, 80 | "state": 24, 81 | "substitute": 40, 82 | "transform": 48, 83 | "disable_duration": 52, 84 | "disable_move": 56, 85 | "toxic": 59 86 | }, 87 | "Action": { 88 | "damage": 0, 89 | "hit": 8, 90 | "critical_hit": 10, 91 | "secondary_chance": 12, 92 | "speed_tie": 14, 93 | "confused": 16, 94 | "paralyzed": 18, 95 | "duration": 20, 96 | "sleep": 24, 97 | "confusion": 26, 98 | "disable": 29, 99 | "attacking": 31, 100 | "binding": 33, 101 | "move_slot": 36, 102 | "pp": 40, 103 | "multi_hit": 44, 104 | "psywave": 48, 105 | "metronome": 56 106 | }, 107 | "Duration": { 108 | "sleeps": 0, 109 | "confusion": 18, 110 | "disable": 21, 111 | "attacking": 25, 112 | "binding": 28 113 | }, 114 | "Damage": { 115 | "base": 0, 116 | "final": 2, 117 | "capped": 4 118 | } 119 | } 120 | } 121 | ] 122 | -------------------------------------------------------------------------------- /src/lib/bindings/wasm.zig: -------------------------------------------------------------------------------- 1 | const pkmn = @import("../pkmn.zig"); 2 | const std = @import("std"); 3 | 4 | const assert = std.debug.assert; 5 | 6 | const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum; 7 | const Strong = if (@hasField(std.builtin.GlobalLinkage, "strong")) .strong else .Strong; 8 | 9 | pub const options = pkmn.options; 10 | 11 | pub fn gen(comptime num: comptime_int) type { 12 | const g = @field(pkmn, "gen" ++ std.fmt.comptimePrint("{d}", .{num})); 13 | return struct { 14 | pub const CHOICES_SIZE = size(g.CHOICES_SIZE); 15 | pub const LOGS_SIZE = size(g.LOGS_SIZE); 16 | 17 | pub fn update( 18 | battle: *g.Battle(g.PRNG), 19 | c1: pkmn.Choice, 20 | c2: pkmn.Choice, 21 | options_: ?[*]u8, 22 | ) callconv(.C) pkmn.Result { 23 | return (if (options_) |o| result: { 24 | const buf = @as([*]u8, @ptrCast(o))[0..g.LOGS_SIZE]; 25 | var stream: pkmn.protocol.ByteStream = .{ .buffer = buf }; 26 | // TODO: extract out 27 | var opts = pkmn.battle.options( 28 | pkmn.protocol.FixedLog{ .writer = stream.writer() }, 29 | g.chance.NULL, 30 | g.calc.NULL, 31 | ); 32 | break :result battle.update(c1, c2, &opts); 33 | } else battle.update(c1, c2, &g.NULL)) catch unreachable; 34 | } 35 | 36 | pub fn choices( 37 | battle: *g.Battle(g.PRNG), 38 | player: u8, 39 | request: u8, 40 | buf: [*]u8, 41 | ) callconv(.C) u8 { 42 | assert(player <= @field(@typeInfo(pkmn.Player), @tagName(Enum)).fields.len); 43 | assert(request <= @field(@typeInfo(pkmn.Choice.Type), @tagName(Enum)).fields.len); 44 | 45 | const n = CHOICES_SIZE; 46 | return battle.choices(@enumFromInt(player), @enumFromInt(request), @ptrCast(buf[0..n])); 47 | } 48 | }; 49 | } 50 | 51 | pub fn exports() type { 52 | @export(gen(1).update, .{ .name = "GEN1_update", .linkage = Strong }); 53 | @export(gen(1).choices, .{ .name = "GEN1_choices", .linkage = Strong }); 54 | return struct {}; 55 | } 56 | 57 | fn size(n: usize) u32 { 58 | return std.math.ceilPowerOfTwo(u32, @as(u32, @intCast(n))) catch unreachable; 59 | } 60 | -------------------------------------------------------------------------------- /src/lib/c.zig: -------------------------------------------------------------------------------- 1 | const c = @import("bindings/c.zig"); 2 | const std = @import("std"); 3 | 4 | export const PKMN_OPTIONS = c.OPTIONS; 5 | 6 | export const PKMN_MAX_CHOICES = c.MAX_CHOICES; 7 | export const PKMN_CHOICES_SIZE = c.CHOICES_SIZE; 8 | export const PKMN_MAX_LOGS = c.MAX_LOGS; 9 | export const PKMN_LOGS_SIZE = c.LOGS_SIZE; 10 | 11 | export const PKMN_GEN1_MAX_CHOICES = c.gen(1).MAX_CHOICES; 12 | export const PKMN_GEN1_CHOICES_SIZE = c.gen(1).CHOICES_SIZE; 13 | export const PKMN_GEN1_MAX_LOGS = c.gen(1).MAX_LOGS; 14 | export const PKMN_GEN1_LOGS_SIZE = c.gen(1).LOGS_SIZE; 15 | 16 | const exportable = @hasDecl(std.zig, "Zir") and !@hasField(std.zig.Zir.Inst.Tag, "export_value"); 17 | 18 | usingnamespace if (exportable) struct { 19 | export const pkmn_choice_init = c.choice_init; 20 | export const pkmn_choice_type = c.choice_type; 21 | export const pkmn_choice_data = c.choice_data; 22 | 23 | export const pkmn_result_type = c.result_type; 24 | export const pkmn_result_p1 = c.result_p1; 25 | export const pkmn_result_p2 = c.result_p2; 26 | 27 | export const pkmn_error = c.err; 28 | 29 | export const pkmn_psrng_init = c.psrng_init; 30 | export const pkmn_psrng_next = c.psrng_next; 31 | 32 | export const pkmn_rational_init = c.rational_init; 33 | export const pkmn_rational_reduce = c.rational_reduce; 34 | export const pkmn_rational_numerator = c.rational_numerator; 35 | export const pkmn_rational_denominator = c.rational_denominator; 36 | 37 | export const pkmn_gen1_battle_options_set = 38 | c.gen(1).battle_options_set; 39 | export const pkmn_gen1_battle_options_chance_probability = 40 | c.gen(1).battle_options_chance_probability; 41 | export const pkmn_gen1_battle_options_chance_actions = 42 | c.gen(1).battle_options_chance_actions; 43 | export const pkmn_gen1_battle_options_chance_durations = 44 | c.gen(1).battle_options_chance_durations; 45 | export const pkmn_gen1_battle_options_calc_summaries = 46 | c.gen(1).battle_options_calc_summaries; 47 | 48 | export const pkmn_gen1_battle_update = c.gen(1).battle_update; 49 | export const pkmn_gen1_battle_choices = c.gen(1).battle_choices; 50 | } else c.exports(); 51 | -------------------------------------------------------------------------------- /src/lib/common/array.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const expectEqual = std.testing.expectEqual; 4 | const assert = std.debug.assert; 5 | 6 | const Int = if (@hasField(std.builtin.Type, "int")) .int else .Int; 7 | const Enum = if (@hasField(std.builtin.Type, "enum")) .@"enum" else .Enum; 8 | 9 | /// Helpers for working with bit-packed arrays of non-powers-of-2 types. 10 | /// NOTE: ziglang/zig#12547 11 | pub fn Array(comptime n: comptime_int, comptime U: type) type { 12 | return struct { 13 | const size = @bitSizeOf(U); 14 | const options: std.builtin.Type.Int = .{ .signedness = .unsigned, .bits = size * n }; 15 | pub const T = @Type(if (@hasField(std.builtin.Type, "int")) 16 | .{ .int = options } 17 | else 18 | .{ .Int = options }); 19 | 20 | /// Returns the value stored at index `i` in the array `a`. 21 | pub fn get(a: T, i: usize) U { 22 | assert(i < n); 23 | const shift = i * size; 24 | const mask: T = (1 << size) - 1; 25 | const result = (a >> @intCast(shift)) & mask; 26 | return switch (@typeInfo(U)) { 27 | Enum => @enumFromInt(result), 28 | Int => @intCast(result), 29 | else => unreachable, 30 | }; 31 | } 32 | 33 | /// Sets the value at index `i` to `val` in the array `a`. 34 | pub fn set(a: T, i: usize, val: U) T { 35 | assert(i < n); 36 | const v: T = switch (@typeInfo(U)) { 37 | Enum => @intFromEnum(val), 38 | Int => @intCast(val), 39 | else => unreachable, 40 | }; 41 | const shift = i * size; 42 | const mask: T = @as(T, @intCast((1 << size) - 1)) << @intCast(shift); 43 | const result: T = a & ~mask; 44 | return result | (v << @intCast(shift)); 45 | } 46 | }; 47 | } 48 | 49 | test Array { 50 | const A = Array(5, u8); 51 | var a: A.T = 0; 52 | try expectEqual(u40, @TypeOf(a)); 53 | 54 | a = A.set(a, 4, 241); 55 | try expectEqual(@as(u8, 241), A.get(a, 4)); 56 | a = A.set(a, 4, 1); 57 | try expectEqual(@as(u8, 1), A.get(a, 4)); 58 | 59 | for (0..5) |i| a = A.set(a, i, @intCast(i)); 60 | for (0..5) |i| try expectEqual(@as(u8, @intCast(i)), A.get(a, i)); 61 | 62 | const Optional = @import("optional.zig").Optional; 63 | 64 | const B = Array(4, Optional(bool)); 65 | var b: B.T = 0; 66 | try expectEqual(u8, @TypeOf(b)); 67 | 68 | b = B.set(b, 2, .true); 69 | try expectEqual(Optional(bool).None, B.get(b, 1)); 70 | try expectEqual(Optional(bool).true, B.get(b, 2)); 71 | try expectEqual(@as(u8, 0b00100000), b); 72 | b = B.set(b, 2, .None); 73 | b = B.set(b, 0, .false); 74 | try expectEqual(Optional(bool).None, B.get(b, 2)); 75 | try expectEqual(Optional(bool).false, B.get(b, 0)); 76 | try expectEqual(@as(u8, 0b0000001), b); 77 | } 78 | -------------------------------------------------------------------------------- /src/lib/common/battle.zig: -------------------------------------------------------------------------------- 1 | /// Stores state required by optional features to the engine that can be passed to a generation's 2 | /// `Battle.update` function. All generations generically support protocol logging (enabled via 3 | /// `-Dlog`), chance actions and probability tracking (enabled via `-Dchance`), and damage 4 | /// computation and chance overrides (`-Dcalc`), though the concrete types for these features are 5 | /// generation dependent. 6 | pub fn Options(comptime Log: type, comptime Chance: type, comptime Calc: type) type { 7 | return struct { log: Log, chance: Chance, calc: Calc }; 8 | } 9 | 10 | /// Helper to create a battle `Options` object with the provided `log`, `chance`, and `calc`. 11 | pub fn options( 12 | log: anytype, 13 | chance: anytype, 14 | calc: anytype, 15 | ) Options(@TypeOf(log), @TypeOf(chance), @TypeOf(calc)) { 16 | return .{ .log = log, .chance = chance, .calc = calc }; 17 | } 18 | -------------------------------------------------------------------------------- /src/lib/common/data/items.zig.tmpl: -------------------------------------------------------------------------------- 1 | //! Code generated by `tools/generate` - manual edits will be overwritten. 2 | 3 | const data = @import("../../gen{{{ gen }}}/data.zig"); 4 | const std = @import("std"); 5 | 6 | const assert = std.debug.assert; 7 | const Type = data.Type; 8 | 9 | /// Representation of a held item in Generation {{{ roman }}} Pokémon. 10 | pub const Item = enum({{{ Item.type }}}) { 11 | None, 12 | {{{ Item.values }}} 13 | 14 | comptime { 15 | assert(@sizeOf(Item) == {{{ Item.size }}}); 16 | } 17 | 18 | /// The number of held items in this generation. 19 | pub const size = {{{ Item.num }}}; 20 | 21 | /// Returns a `Type` boosted by this item or `null` if the item is not a type-boosting item. 22 | pub fn boost(item: Item) ?Type { 23 | assert(item != .None); 24 | if (item == .PolkadotBow) return .Normal; 25 | return if (@intFromEnum(item) <= {{{ Item.boosts }}}) @enumFromInt(@intFromEnum(item) - 1) else null; 26 | } 27 | 28 | /// Whether or not this item is Mail. 29 | pub fn isMail(item: Item) bool { 30 | assert(item != .None); 31 | return @intFromEnum(item) > {{{ Item.present }}} and @intFromEnum(item) <= {{{ Item.mail }}}; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /src/lib/common/data/moves.zig.tmpl: -------------------------------------------------------------------------------- 1 | //! Code generated by `tools/generate` - manual edits will be overwritten. 2 | 3 | const gen{{{ gen }}} = @import("../../gen{{{ gen }}}/data.zig"); 4 | {{{ import }}} 5 | const std = @import("std"); 6 | 7 | const assert = std.debug.assert;{{{ percent }}} 8 | const Type = gen{{{ gen }}}.Type; 9 | 10 | /// Representation of a Generation {{{ roman }}} Pokémon move. 11 | pub const Move = enum({{{ Move.type }}}) { 12 | None, 13 | {{{ Move.values }}}, 14 | 15 | {{{ Move.Data }}} 16 | 17 | const DATA = [_]Data{ 18 | {{{ Move.data }}}, 19 | }; 20 | {{{ Move.Effect }}} 21 | const Target = enum({{{ Move.targetType }}}) { 22 | // none 23 | All, 24 | AllySide, 25 | Field, 26 | Self, 27 | // resolve 28 | AllOthers, 29 | Depends, 30 | Other, 31 | Any, 32 | Allies, 33 | Ally, 34 | AllyOrSelf, 35 | Foe, 36 | // resolve + run 37 | Foes, 38 | FoeSide, 39 | RandomFoe, 40 | }; 41 | 42 | const PP = [_]u8{ 43 | {{{ Move.ppData }}}, 44 | }; 45 | 46 | comptime { 47 | assert(@sizeOf(Move) == {{{ Move.size }}}); 48 | assert(@sizeOf(@TypeOf(DATA)) == {{{ Move.dataSize }}}); 49 | } 50 | 51 | /// The number of Pokémon moves in this generation. 52 | pub const size = {{{ Move.num }}}; 53 | 54 | /// Pokémon moves that can be called by Metronome in this generation. 55 | pub const METRONOME = {{{ Move.metronome }}} 56 | 57 | /// Returns the `Data` corresponding to the move. 58 | pub fn get(id: Move) Data { 59 | {{{ Move.assert }}} 60 | return DATA[@intFromEnum(id) - 1]; 61 | } 62 | 63 | /// Returns the base PP of the move. 64 | pub fn pp(id: Move) u8 { 65 | assert(id != .None); 66 | return PP[@intFromEnum(id) - 1]; 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /src/lib/common/data/species.zig.tmpl: -------------------------------------------------------------------------------- 1 | //! Code generated by `tools/generate` - manual edits will be overwritten. 2 | 3 | const gen{{{ gen }}} = @import("../../gen{{{ gen }}}/data.zig"); 4 | const std = @import("std"); 5 | 6 | const assert = std.debug.assert; 7 | const Stats = gen{{{ gen }}}.Stats; 8 | const Types = gen{{{ gen }}}.Types; 9 | 10 | /// Representation of a Generation {{{ roman }}} Pokémon species. 11 | pub const Species = enum({{{ Species.type }}}) { 12 | None, 13 | {{{ Species.values }}}, 14 | 15 | {{{ Species.chances }}}{{{ Species.Data }}} 16 | 17 | const DATA = [_]Data{ 18 | {{{ Species.data }}}, 19 | }; 20 | 21 | comptime { 22 | assert(@sizeOf(Species) == {{{ Species.size }}}); 23 | } 24 | 25 | /// The number of Pokémon species in this generation. 26 | pub const size = {{{ Species.num }}};{{{ Species.chanceFn }}} 27 | 28 | /// Returns the `Data` corresponding to the species. 29 | pub fn get(id: Species) Data { 30 | assert(id != .None); 31 | return DATA[@intFromEnum(id) - 1]; 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /src/lib/common/data/types.zig.tmpl: -------------------------------------------------------------------------------- 1 | //! Code generated by `tools/generate` - manual edits will be overwritten. 2 | 3 | const gen1 = @import("../../gen1/data.zig"); 4 | const std = @import("std"); 5 | 6 | const assert = std.debug.assert; 7 | const Effectiveness = gen1.Effectiveness; 8 | 9 | const S = Effectiveness.Super; 10 | const N = Effectiveness.Neutral; 11 | const R = Effectiveness.Resisted; 12 | const I = Effectiveness.Immune; 13 | 14 | /// Representation of a Generation {{{ roman }}} type in Pokémon. 15 | pub const Type = enum({{{ Type.type }}}) { 16 | {{{ Type.values }}}, 17 | 18 | const CHART: [{{{ Type.num }}}][{{{ Type.num }}}]Effectiveness = .{ 19 | {{{ Type.chart }}} 20 | }; 21 | 22 | {{{ Type.precedence }}}{{{ Type.extra }}} 23 | 24 | comptime { 25 | assert(@bitSizeOf(Type) == {{{ Type.bitSize }}}); 26 | assert(@sizeOf(@TypeOf(CHART)) == {{{ Type.chartSize }}}); 27 | assert(@sizeOf(@TypeOf(PRECEDENCE)) == {{{ Type.precedenceSize }}});{{{ Type.extraSizes }}} 28 | } 29 | 30 | /// The number of types in this generation. 31 | pub const size = {{{ Type.num }}}; 32 | 33 | /// Whether or not this type is considered to be special as opposed to physical. 34 | pub fn special(self: Type) bool { 35 | return @intFromEnum(self) >= @intFromEnum(Type.Fire); 36 | } 37 | 38 | /// The `Effectiveness` of type `t2` vs. type `t1`. 39 | pub fn effectiveness(t1: Type, t2: Type) Effectiveness { 40 | return CHART[@intFromEnum(t1)][@intFromEnum(t2)]; 41 | } 42 | 43 | {{{ Type.precedenceFn }}}{{{ Type.extraFns }}} 44 | }; 45 | 46 | /// Representation of a Pokémon's typing. 47 | pub const Types = {{{ Types.qualifier }}} struct { 48 | /// A Pokémon's primary type. 49 | type1: Type = .Normal, 50 | /// A Pokémon's secondary type (may be identical to its primary type). 51 | type2: Type = .Normal, 52 | 53 | comptime { 54 | assert(@sizeOf(Types) == {{{ Types.size }}}); 55 | } 56 | 57 | /// Whether this typing is immune to type `t`. 58 | pub fn immune(self: Types, t: Type) bool { 59 | return t.effectiveness(self.type1) == I or t.effectiveness(self.type2) == I; 60 | } 61 | 62 | /// Whether this typing includes type `t`. 63 | pub fn includes(self: Types, t: Type) bool { 64 | return self.type1 == t or self.type2 == t; 65 | }{{{ Types.extraFns }}} 66 | }; 67 | -------------------------------------------------------------------------------- /src/lib/common/napi.zig: -------------------------------------------------------------------------------- 1 | pub usingnamespace @cImport({ 2 | @cDefine("NAPI_VERSION", "8"); 3 | @cInclude("node_api.h"); 4 | }); 5 | -------------------------------------------------------------------------------- /src/lib/common/optional.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const expect = std.testing.expect; 4 | const assert = std.debug.assert; 5 | 6 | const Bool = if (@hasField(std.builtin.Type, "bool")) .bool else .Bool; 7 | 8 | // TODO: ziglang/zig#104 9 | pub fn Optional(comptime T: type) type { 10 | const fields = std.meta.fields(switch (@typeInfo(T)) { 11 | Bool => enum { false, true }, 12 | else => T, 13 | }); 14 | 15 | var enumFields: [fields.len + 1]std.builtin.Type.EnumField = undefined; 16 | var decls = [_]std.builtin.Type.Declaration{}; 17 | 18 | enumFields[0] = .{ .name = "None", .value = 0 }; 19 | 20 | inline for (fields, 1..) |field, i| { 21 | assert(!std.mem.eql(u8, field.name, "None")); 22 | enumFields[i] = .{ 23 | .name = field.name, 24 | .value = i, 25 | }; 26 | } 27 | 28 | const options: std.builtin.Type.Enum = .{ 29 | .tag_type = std.math.IntFittingRange(0, fields.len), 30 | .fields = &enumFields, 31 | .decls = &decls, 32 | .is_exhaustive = true, 33 | }; 34 | return @Type(if (@hasField(std.builtin.Type, "enum")) 35 | .{ .@"enum" = options } 36 | else 37 | .{ .Enum = options }); 38 | } 39 | 40 | test Optional { 41 | try expect(@bitSizeOf(Optional(bool)) == 2); 42 | 43 | const a: Optional(bool) = .true; 44 | try expect(a != .None); 45 | try expect(a == .true); 46 | try expect(a != .false); 47 | 48 | const b: Optional(bool) = .None; 49 | try expect(b == .None); 50 | try expect(b != .true); 51 | try expect(b != .false); 52 | 53 | const Player = @import("data.zig").Player; 54 | try expect(@bitSizeOf(Optional(Player)) == 2); 55 | 56 | const p: Optional(Player) = .P2; 57 | try expect(p != .None); 58 | try expect(p != .P1); 59 | try expect(p == .P2); 60 | 61 | const q: Optional(Player) = .None; 62 | try expect(q == .None); 63 | try expect(q != .P1); 64 | try expect(q != .P2); 65 | 66 | const Three = enum(u2) { A, B, C }; 67 | try expect(@bitSizeOf(Optional(Three)) == 2); 68 | 69 | const Four = enum(u2) { A, B, C, D }; 70 | try expect(@bitSizeOf(Optional(Four)) == 3); 71 | } 72 | -------------------------------------------------------------------------------- /src/lib/common/options.zig: -------------------------------------------------------------------------------- 1 | const build_options = @import("build_options"); 2 | const root = @import("root"); 3 | 4 | /// Configures the behavior of the pkmn package. 5 | pub const Options = struct { 6 | showdown: ?bool = null, 7 | log: ?bool = null, 8 | chance: ?bool = null, 9 | calc: ?bool = null, 10 | mod: ?bool = null, 11 | advance: ?bool = null, 12 | ebc: ?bool = null, 13 | key: ?bool = null, 14 | miss: ?bool = null, 15 | overwrite: ?bool = null, 16 | internal: ?bool = null, 17 | }; 18 | 19 | /// Whether or not Pokémon Showdown compatibility mode is enabled. 20 | pub const showdown = get("showdown", false); 21 | /// Whether or not protocol message logging is enabled. 22 | pub const log = get("log", false); 23 | /// Whether or not update probability tracking is enabled. 24 | pub const chance = get("chance", false); 25 | /// Whether or not damage calculator support is enabled. 26 | pub const calc = get("calc", false); 27 | 28 | pub const mod = showdown or get("mod", false); 29 | pub const advance = get("advance", true); 30 | pub const ebc = get("ebc", true); 31 | pub const key = get("key", false); 32 | pub const miss = get("miss", true); 33 | pub const overwrite = get("overwrite", true); 34 | pub const internal = get("internal", false); 35 | 36 | fn get(comptime name: []const u8, default: bool) bool { 37 | var build_enable: ?bool = null; 38 | var root_enable: ?bool = null; 39 | 40 | if (@hasDecl(root, "pkmn_options")) { 41 | root_enable = @field(@as(Options, root.pkmn_options), name); 42 | } 43 | if (@hasDecl(build_options, name)) { 44 | build_enable = @as(?bool, @field(build_options, name)); 45 | } 46 | if (build_enable != null and root_enable != null) { 47 | if (build_enable.? != root_enable.?) { 48 | const r = name ++ " (" ++ (if (root_enable.?) "false" else "true") ++ ")"; 49 | const b = name ++ " (" ++ (if (build_enable.?) "false" else "true") ++ ")"; 50 | @compileError("root decl pkmn_options." ++ r ++ " != build option " ++ b ++ "."); 51 | } 52 | } 53 | 54 | return root_enable orelse (build_enable orelse default); 55 | } 56 | -------------------------------------------------------------------------------- /src/lib/common/test.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | _ = @import("array.zig"); 3 | _ = @import("data.zig"); 4 | _ = @import("optional.zig"); 5 | _ = @import("protocol.zig"); 6 | _ = @import("rational.zig"); 7 | _ = @import("rng.zig"); 8 | _ = @import("util.zig"); 9 | } 10 | -------------------------------------------------------------------------------- /src/lib/common/util.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const expect = std.testing.expect; 4 | const expectEqual = std.testing.expectEqual; 5 | 6 | const Pointer = if (@hasField(std.builtin.Type, "pointer")) .pointer else .Pointer; 7 | const One = if (@hasField(std.builtin.Type.Pointer.Size, "one")) .one else .One; 8 | 9 | pub fn PointerType(comptime P: type, comptime C: type) type { 10 | return if (@field(@typeInfo(P), @tagName(Pointer)).is_const) *const C else *C; 11 | } 12 | 13 | test PointerType { 14 | try expectEqual(*bool, PointerType(*u8, bool)); 15 | try expectEqual(*const f64, PointerType(*const i32, f64)); 16 | } 17 | 18 | pub fn isPointerTo(p: anytype, comptime P: type) bool { 19 | const info = @typeInfo(@TypeOf(p)); 20 | return switch (info) { 21 | Pointer => @field(info, @tagName(Pointer)).child == P, 22 | else => false, 23 | }; 24 | } 25 | 26 | test isPointerTo { 27 | const S = struct {}; 28 | const s: S = .{}; 29 | try expect(!isPointerTo(s, S)); 30 | try expect(isPointerTo(&s, S)); 31 | } 32 | 33 | // NOTE: std.mem.bytesAsValue backported from ziglang/zig#18061 34 | pub fn bytesAsValue(comptime T: type, bytes: anytype) BytesAsValueReturnType(T, @TypeOf(bytes)) { 35 | return @as(BytesAsValueReturnType(T, @TypeOf(bytes)), @ptrCast(bytes)); 36 | } 37 | 38 | fn BytesAsValueReturnType(comptime T: type, comptime B: type) type { 39 | return CopyPtrAttrs(B, One, T); 40 | } 41 | 42 | fn CopyPtrAttrs( 43 | comptime source: type, 44 | comptime size: std.builtin.Type.Pointer.Size, 45 | comptime child: type, 46 | ) type { 47 | const info = @field(@typeInfo(source), @tagName(Pointer)); 48 | const args: std.builtin.Type.Pointer = if (@hasField(std.builtin.Type.Pointer, "sentinel")) .{ 49 | .size = size, 50 | .is_const = info.is_const, 51 | .is_volatile = info.is_volatile, 52 | .is_allowzero = info.is_allowzero, 53 | .alignment = info.alignment, 54 | .address_space = info.address_space, 55 | .child = child, 56 | .sentinel = null, 57 | } else .{ 58 | .size = size, 59 | .is_const = info.is_const, 60 | .is_volatile = info.is_volatile, 61 | .is_allowzero = info.is_allowzero, 62 | .alignment = info.alignment, 63 | .address_space = info.address_space, 64 | .child = child, 65 | .sentinel_ptr = null, 66 | }; 67 | return @Type(if (@hasField(std.builtin.Type, "pointer")) 68 | .{ .pointer = args } 69 | else 70 | .{ .Pointer = args }); 71 | } 72 | 73 | // NOTE: std.meta.FieldType replaced by @FieldType in 0.14.0 74 | pub fn FieldType(comptime T: type, comptime field: std.meta.FieldEnum(T)) type { 75 | return std.meta.fieldInfo(T, field).type; 76 | } 77 | -------------------------------------------------------------------------------- /src/lib/node.zig: -------------------------------------------------------------------------------- 1 | const c = @import("common/napi.zig"); 2 | const js = @import("common/js.zig"); 3 | const node = @import("bindings/node.zig"); 4 | const std = @import("std"); 5 | 6 | const assert = std.debug.assert; 7 | 8 | export fn napi_register_module_v1(env: c.napi_env, exports: c.napi_value) c.napi_value { 9 | const properties = [_]c.napi_property_descriptor{ 10 | js.Property.init("engine", .{ .value = node.register(env) }), 11 | }; 12 | assert(c.napi_define_properties(env, exports, properties.len, &properties) == c.napi_ok); 13 | return exports; 14 | } 15 | -------------------------------------------------------------------------------- /src/lib/test.zig: -------------------------------------------------------------------------------- 1 | comptime { 2 | _ = @import("common/test.zig"); 3 | _ = @import("gen1/test.zig"); 4 | _ = @import("gen2/test.zig"); 5 | } 6 | -------------------------------------------------------------------------------- /src/lib/wasm.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const wasm = @import("bindings/wasm.zig"); 3 | 4 | export const SHOWDOWN = wasm.options.showdown; 5 | export const LOG = wasm.options.log; 6 | export const CHANCE = wasm.options.chance; 7 | export const CALC = wasm.options.calc; 8 | 9 | export const GEN1_CHOICES_SIZE = wasm.gen(1).CHOICES_SIZE; 10 | export const GEN1_LOGS_SIZE = wasm.gen(1).LOGS_SIZE; 11 | 12 | const exportable = @hasDecl(std.zig, "Zir") and !@hasField(std.zig.Zir.Inst.Tag, "export_value"); 13 | 14 | usingnamespace if (exportable) struct { 15 | export const GEN1_update = wasm.gen(1).update; 16 | export const GEN1_choices = wasm.gen(1).choices; 17 | } else wasm.exports(); 18 | -------------------------------------------------------------------------------- /src/pkg/addon.test.ts: -------------------------------------------------------------------------------- 1 | import * as addon from './addon'; 2 | 3 | describe('AddOn', () => { 4 | test('check', () => { 5 | expect(() => addon.check(true)).not.toThrow(); 6 | expect(() => addon.check(false)) 7 | .toThrow('@pkmn/engine has only been configured to support Pokémon Showdown'); 8 | }); 9 | 10 | test('supports', () => { 11 | const showdown = true; 12 | const log = true; 13 | 14 | expect(addon.supports(!showdown)).toBe(false); 15 | expect(addon.supports(!showdown, log)).toBe(false); 16 | expect(addon.supports(!showdown, !log)).toBe(false); 17 | 18 | expect(addon.supports(showdown)).toBe(true); 19 | expect(addon.supports(showdown, log)).toBe(false); 20 | expect(addon.supports(showdown, !log)).toBe(true); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/pkg/addon/browser.ts: -------------------------------------------------------------------------------- 1 | 2 | import type {Argument} from '../addon'; 3 | 4 | import {toBindings} from './wasm'; 5 | 6 | export async function load(showdown: boolean, addon?: Argument) { 7 | if (typeof addon === 'string' && addon !== 'wasm') { 8 | throw new Error('Unable to load native addons in the browser!'); 9 | } 10 | 11 | let wasm: WebAssembly.Instance; 12 | if (addon instanceof WebAssembly.Instance) { 13 | wasm = addon; 14 | } else if (addon instanceof WebAssembly.Module) { 15 | try { 16 | wasm = (await WebAssembly.instantiate(addon)); 17 | } catch (err) { 18 | if (!(err instanceof Error)) throw err; 19 | throw new Error(`Could not instantiate WASM module!\n${err.message}`); 20 | } 21 | } else { 22 | const name = `pkmn${showdown ? '-showdown' : ''}.wasm`; 23 | try { 24 | const response = !addon || addon === 'wasm' ? fetch(name) 25 | : (addon as Promise | URL) instanceof URL ? fetch(addon) : addon; 26 | wasm = (await WebAssembly.instantiateStreaming(response)).instance; 27 | } catch (err) { 28 | if (!(err instanceof Error)) throw err; 29 | const message = !addon || addon === 'wasm' 30 | ? `Could not find ${name} - did you run \`npx install-pkmn-engine\`?` 31 | : (addon as Promise | URL) instanceof URL 32 | ? `Could not fetch WASM module from '${(addon as URL).href}'!` 33 | : 'Could not instantiate WASM module!'; 34 | throw new Error(`${message}\n${err.message}`); 35 | } 36 | } 37 | 38 | return toBindings(wasm.exports); 39 | } 40 | 41 | export function loadSync() { 42 | throw new Error('You must `initialize` the WASM addon before using the engine!'); 43 | } 44 | -------------------------------------------------------------------------------- /src/pkg/addon/node.ts: -------------------------------------------------------------------------------- 1 | 2 | import * as fs from 'fs'; 3 | import * as path from 'path'; 4 | 5 | import type {Argument} from '../addon'; 6 | 7 | import {toBindings} from './wasm'; 8 | 9 | const ROOT = path.join(__dirname, '..', '..', '..'); 10 | const LIB = path.join(ROOT, 'build', 'lib'); 11 | 12 | const NODE = [path.join(LIB, 'pkmn.node'), path.join(LIB, 'pkmn-showdown.node')]; 13 | const WASM = [path.join(LIB, 'pkmn.wasm'), path.join(LIB, 'pkmn-showdown.wasm')]; 14 | 15 | export async function load(showdown: boolean, addon?: Argument) { 16 | if (addon === undefined || typeof addon === 'string' && addon !== 'wasm') { 17 | try { 18 | return require(!addon || addon === 'node' ? NODE[+showdown] : addon).engine; 19 | } catch (err) { 20 | if (!(err instanceof Error)) return err; 21 | if (addon && addon !== 'node') { 22 | throw new Error(`Unable to load native addon: '${addon}'\n${err.message}`); 23 | } else { 24 | throw error(NODE[+showdown], err); 25 | } 26 | } 27 | } 28 | 29 | let wasm: WebAssembly.Instance; 30 | if (addon === 'wasm') { 31 | try { 32 | wasm = (await WebAssembly.instantiate(fs.readFileSync(WASM[+showdown]))).instance; 33 | } catch (err) { 34 | throw error(WASM[+showdown], err); 35 | } 36 | } else if (addon instanceof WebAssembly.Instance) { 37 | wasm = addon; 38 | } else if (addon instanceof WebAssembly.Module) { 39 | try { 40 | wasm = (await WebAssembly.instantiate(addon)); 41 | } catch (err) { 42 | if (!(err instanceof Error)) throw err; 43 | throw new Error(`Could not instantiate WASM module!\n${err.message}`); 44 | } 45 | } else { 46 | try { 47 | const response = (addon as Promise | URL) instanceof Promise ? addon : fetch(addon); 48 | wasm = (await WebAssembly.instantiateStreaming(response)).instance; 49 | } catch (err) { 50 | if (!(err instanceof Error)) throw err; 51 | throw new Error(`Could not instantiate WASM module!\n${err.message}`); 52 | } 53 | } 54 | 55 | return toBindings(wasm.exports); 56 | } 57 | 58 | export function loadSync(showdown: boolean) { 59 | try { 60 | return require(NODE[+showdown]).engine; 61 | } catch { 62 | return undefined; 63 | } 64 | } 65 | 66 | function error(file: string, err: unknown) { 67 | if (!(err instanceof Error)) return err; 68 | const message = `Could not find ${path.basename(file)} addon`; 69 | return new Error(`${message} - did you run \`npx install-pkmn-engine\`?\n${err.message}`); 70 | } 71 | -------------------------------------------------------------------------------- /src/pkg/addon/wasm.ts: -------------------------------------------------------------------------------- 1 | import type {Binding, Bindings} from '../addon'; 2 | import {LAYOUT} from '../data'; 3 | 4 | export function toBindings(w: WebAssembly.Exports): Bindings { 5 | const memory = new Uint8Array((w.memory as WebAssembly.Memory).buffer); 6 | return { 7 | options: { 8 | showdown: !!memory[w.SHOWDOWN.valueOf()] as T, 9 | log: !!memory[w.LOG.valueOf()], 10 | chance: !!memory[w.CHANCE.valueOf()], 11 | calc: !!memory[w.CALC.valueOf()], 12 | }, 13 | bindings: [toBinding(1, w)], 14 | }; 15 | } 16 | 17 | function toBinding(gen: number, w: WebAssembly.Exports): Binding { 18 | const prefix = `GEN${gen}`; 19 | const buf = (w.memory as WebAssembly.Memory).buffer; 20 | 21 | const constants = new Uint32Array(buf); 22 | const CHOICES_SIZE = constants[w[`${prefix}_CHOICES_SIZE`].valueOf() / 4]; 23 | const LOGS_SIZE = constants[w[`${prefix}_LOGS_SIZE`].valueOf() / 4]; 24 | 25 | const size = LAYOUT[gen - 1].sizes.Battle; 26 | const update = w[`${prefix}_update`] as CallableFunction; 27 | const choices = w[`${prefix}_choices`] as CallableFunction; 28 | const memory = new Uint8Array(buf); 29 | 30 | return { 31 | CHOICES_SIZE, 32 | LOGS_SIZE, 33 | update(battle: ArrayBuffer, c1: number, c2: number, log: ArrayBuffer | undefined): number { 34 | const bytes = new Uint8Array(battle); 35 | memory.set(bytes, 0); 36 | 37 | let result: number; 38 | if (log) { 39 | result = update(0, c1, c2, size); 40 | new Uint8Array(log).set(memory.subarray(size, size + LOGS_SIZE)); 41 | } else { 42 | result = update(0, c1, c2, 0); 43 | } 44 | 45 | bytes.set(memory.subarray(0, size)); 46 | return result; 47 | }, 48 | choices(battle: ArrayBuffer, player: number, request: number, options: ArrayBuffer): number { 49 | const opts = new Uint8Array(options); 50 | memory.set(new Uint8Array(battle)); 51 | const n = choices(0, player, request, size); 52 | opts.set(memory.subarray(size, size + n)); 53 | return n; 54 | }, 55 | }; 56 | } 57 | -------------------------------------------------------------------------------- /src/pkg/common.test.ts: -------------------------------------------------------------------------------- 1 | import {Choice, Result} from './common'; 2 | 3 | test('Choice.decode', () => { 4 | expect(Choice.decode(0b0001_0001)).toEqual(Choice.move(4)); 5 | expect(Choice.decode(0b0001_0110)).toEqual(Choice.switch(5)); 6 | }); 7 | 8 | test('Choice.encode', () => { 9 | expect(Choice.encode()).toBe(Choice.encode(Choice.pass)); 10 | expect(Choice.encode(Choice.move(4))).toBe(0b0001_0001); 11 | expect(Choice.encode(Choice.switch(5))).toBe(0b0001_0110); 12 | }); 13 | 14 | test('Choice.parse', () => { 15 | expect(() => Choice.parse('foo')).toThrow('Invalid choice'); 16 | expect(Choice.parse('pass')).toEqual(Choice.pass); 17 | expect(() => Choice.parse('pass 2')).toThrow('Invalid choice'); 18 | expect(Choice.parse('move 2')).toEqual(Choice.move(2)); 19 | expect(Choice.parse('move 0')).toEqual(Choice.move(0)); 20 | expect(() => Choice.parse('move 5')).toThrow('Invalid choice'); 21 | expect(Choice.parse('switch 4')).toEqual(Choice.switch(4)); 22 | expect(() => Choice.parse('switch 1')).toThrow('Invalid choice'); 23 | }); 24 | 25 | test('Choice.format', () => { 26 | expect(Choice.format(Choice.pass)).toBe('pass'); 27 | expect(Choice.format(Choice.move(2))).toBe('move 2'); 28 | expect(Choice.format(Choice.switch(4))).toBe('switch 4'); 29 | }); 30 | 31 | test('Result.decode', () => { 32 | expect(Result.decode(0b0101_0000)).toEqual({type: undefined, p1: 'move', p2: 'move'}); 33 | expect(Result.decode(0b1000_0000)).toEqual({type: undefined, p1: 'pass', p2: 'switch'}); 34 | }); 35 | 36 | test('Result.encode', () => { 37 | expect(Result.encode({type: undefined, p1: 'move', p2: 'move'})).toBe(0b0101_0000); 38 | expect(Result.encode({type: undefined, p1: 'pass', p2: 'switch'})).toBe(0b1000_0000); 39 | expect(Result.encode({type: 'win', p1: 'pass', p2: 'pass'})).toBe(0b0000_0001); 40 | }); 41 | -------------------------------------------------------------------------------- /src/pkg/data.test.ts: -------------------------------------------------------------------------------- 1 | import {Generations, ID} from '@pkmn/data'; 2 | import {Dex} from '@pkmn/sim'; 3 | 4 | import {Lookup} from './data'; 5 | 6 | for (const gen of new Generations(Dex as any)) { 7 | if (gen.num > 2) break; 8 | 9 | const lookup = Lookup.get(gen); 10 | describe(`Gen ${gen.num}`, () => { 11 | test('Lookup.sizes', () => { 12 | const i = gen.num - 1; 13 | expect(lookup.sizes).toEqual({ 14 | types: [15, 18][i], 15 | species: [151, 251][i], 16 | moves: [165, 251][i], 17 | items: [0, 195][i], 18 | }); 19 | }); 20 | 21 | test('Lookup.type', () => { 22 | expect(lookup.typeByName('Rock')).toBe(gen.num === 1 ? 5 : 1); 23 | expect(lookup.typeByNum(14)).toBe(gen.num === 1 ? 'Dragon' : 'Psychic'); 24 | }); 25 | 26 | test('Lookup.species', () => { 27 | expect(lookup.speciesByID('gengar' as ID)).toBe(94); 28 | expect(lookup.speciesByNum(151)).toBe('mew'); 29 | }); 30 | 31 | test('Lookup.move', () => { 32 | expect(lookup.moveByID('lowkick' as ID)).toBe(67); 33 | expect(lookup.moveByNum(133)).toBe('amnesia'); 34 | }); 35 | 36 | if (gen.num > 1) { 37 | test('Lookup.item', () => { 38 | expect(lookup.itemByID('leftovers' as ID)).toBe(27); 39 | expect(lookup.itemByNum(24)).toBe('thickclub'); 40 | expect(lookup.itemByID('mail' as ID)).toBe(61); 41 | expect(lookup.itemByNum(61)).toBe('mail'); 42 | }); 43 | } 44 | }); 45 | } 46 | -------------------------------------------------------------------------------- /src/pkg/data/layout.json: -------------------------------------------------------------------------------- 1 | ../../data/layout.json -------------------------------------------------------------------------------- /src/pkg/data/mapping.json: -------------------------------------------------------------------------------- 1 | { 2 | "base": { 3 | "Cant": [ 4 | "slp", 5 | "frz", 6 | "par", 7 | "partiallytrapped", 8 | "flinch", 9 | "recharge", 10 | "nopp", 11 | "Attract" 12 | ], 13 | "Damage": [ 14 | "", 15 | "psn", 16 | "brn", 17 | "confusion", 18 | "Leech Seed", 19 | "Recoil" 20 | ], 21 | "Boosts": [ 22 | "atk", 23 | "atk", 24 | "def", 25 | "spe", 26 | "spa", 27 | "spd", 28 | "accuracy", 29 | "evasion" 30 | ], 31 | "Fail": [ 32 | "", 33 | "slp", 34 | "psn", 35 | "brn", 36 | "frz", 37 | "par", 38 | "tox", 39 | "move: Substitute", 40 | "move: Substitute" 41 | ], 42 | "Activate": [ 43 | "Bide", 44 | "confusion", 45 | "move: Haze", 46 | "move: Mist", 47 | "move: Struggle", 48 | "move: Substitute", 49 | "move: Splash" 50 | ], 51 | "Start": [ 52 | "Bide", 53 | "confusion", 54 | "confusion", 55 | "move: Focus Energy", 56 | "move: Leech Seed", 57 | "Light Screen", 58 | "Mist", 59 | "Reflect", 60 | "Substitute", 61 | "typechange", 62 | "Disable", 63 | "Mimic" 64 | ], 65 | "End": [ 66 | "Disable", 67 | "confusion", 68 | "Bide", 69 | "Substitute", 70 | "Disable", 71 | "confusion", 72 | "Mist", 73 | "move: Focus Energy", 74 | "move: Leech Seed", 75 | "Toxic counter", 76 | "Light Screen", 77 | "Reflect", 78 | "move: Bide" 79 | ], 80 | "Side": [ 81 | "Safeguard", 82 | "Reflect", 83 | "move: Light Screen", 84 | "Spikes" 85 | ] 86 | }, 87 | "diffs": [ 88 | { 89 | "Activate": [ 90 | [0, "move: Bide"] 91 | ], 92 | "Start": [ 93 | [0, "move: Bide"] 94 | ], 95 | "End": [ 96 | [0, "move: Disable"], 97 | [2, "move: Bide"] 98 | ] 99 | } 100 | ] 101 | } -------------------------------------------------------------------------------- /src/pkg/data/protocol.json: -------------------------------------------------------------------------------- 1 | ../../data/protocol.json -------------------------------------------------------------------------------- /src/pkg/fixtures/p1.txt: -------------------------------------------------------------------------------- 1 | Fushigidane (Bulbasaur) 2 | - Sleep Powder 3 | - Swords Dance 4 | - Razor Leaf 5 | - Body Slam 6 | 7 | Hitokage (Charmander) 8 | - Fire Blast 9 | - Fire Spin 10 | - Slash 11 | - Counter 12 | 13 | Zenigame (Squirtle) 14 | - Surf 15 | - Blizzard 16 | - Body Slam 17 | - Rest 18 | 19 | Pikachuu (Pikachu) 20 | - Thunderbolt 21 | - Thunder Wave 22 | - Surf 23 | - Seismic Toss 24 | 25 | Koratta (Rattata) 26 | - Super Fang 27 | - Body Slam 28 | - Blizzard 29 | - Thunderbolt 30 | 31 | Poppo (Pidgey) 32 | - Double-Edge 33 | - Quick Attack 34 | - Wing Attack 35 | - Mirror Move 36 | -------------------------------------------------------------------------------- /src/pkg/fixtures/p2.txt: -------------------------------------------------------------------------------- 1 | Kentarosu (Tauros) 2 | - Body Slam 3 | - Hyper Beam 4 | - Blizzard 5 | - Earthquake 6 | 7 | Rakkii (Chansey) 8 | - Reflect 9 | - Seismic Toss 10 | - Soft-Boiled 11 | - Thunder Wave 12 | 13 | Kabigon (Snorlax) 14 | - Body Slam 15 | - Reflect 16 | - Rest 17 | - Ice Beam 18 | 19 | Nasshii (Exeggutor) 20 | - Sleep Powder 21 | - Psychic 22 | - Explosion 23 | - Double-Edge 24 | 25 | Sutaamii (Starmie) 26 | - Recover 27 | - Thunder Wave 28 | - Blizzard 29 | - Thunderbolt 30 | 31 | Fuudin (Alakazam) 32 | - Psychic 33 | - Seismic Toss 34 | - Thunder Wave 35 | - Recover 36 | -------------------------------------------------------------------------------- /src/pkg/index.test.ts: -------------------------------------------------------------------------------- 1 | import {Generations} from '@pkmn/data'; 2 | import {Dex, PRNG} from '@pkmn/sim'; 3 | 4 | import {Options} from '../test/benchmark'; 5 | 6 | import {Battle} from './index'; 7 | 8 | for (const gen of new Generations(Dex as any)) { 9 | if (gen.num > 1) { 10 | describe(`Gen ${gen.num}`, () => { 11 | test('Battle.create/restore', () => { 12 | const options = {showdown: true} as any; 13 | expect(() => Battle.create(gen, options)).toThrow('Unsupported gen'); 14 | expect(() => Battle.restore(gen, {} as any, options)).toThrow('Unsupported gen'); 15 | }); 16 | }); 17 | continue; 18 | } 19 | 20 | describe(`Gen ${gen.num}`, () => { 21 | test('Battle.create/restore', () => { 22 | const options = Options.get(gen, PRNG.get('1,2,3,4')); 23 | const battle = Battle.create(gen, options); 24 | const restored = Battle.restore(gen, battle, options); 25 | expect(restored.toJSON()).toEqual(battle.toJSON()); 26 | }); 27 | }); 28 | } 29 | -------------------------------------------------------------------------------- /src/test/README.md: -------------------------------------------------------------------------------- 1 | ../../docs/TESTING.md -------------------------------------------------------------------------------- /src/test/benchmark.test.ts: -------------------------------------------------------------------------------- 1 | import {Generations} from '@pkmn/data'; 2 | import {Dex} from '@pkmn/sim'; 3 | 4 | import * as addon from '../pkg/addon'; 5 | 6 | import {comparison, iterations} from './benchmark'; 7 | 8 | // Simple smoke tests just to confirm things are wired up correctly and actually execute 9 | describe('benchmark', () => { 10 | const gens = new Generations(Dex as any); 11 | 12 | test('iterations', () => { 13 | expect(() => iterations(gens, 10, 10, [1, 2, 3, 4])).not.toThrow(); 14 | }); 15 | 16 | (addon.supports(true) ? test : test.skip)('comparison', () => 17 | expect(comparison(gens, 10, [1, 2, 3, 4])).resolves.toBeDefined()); 18 | }); 19 | -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x130C2A0BF1934A4C.showdown.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x130C2A0BF1934A4C.showdown.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x138CA5166EFF6A9.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[312,51793,26351,63145]} 2 | >player p1 {"name":"Bot 1","team":"Jigglypuff|||None|leer,thundershock,conversion,quickattack||241,160,234,175,175,252|N|2,17,0,21,21,7||64|172]Persian|||None|peck,minimize,doubleedge,thunderpunch||209,84,55,156,156,225|N|1,25,1,27,27,17||71|37]Snorlax|||None|thunderbolt,flash,horndrill,poisongas||174,151,164,72,72,56|N|8,10,8,16,16,0||72|109]Wartortle|||None|acid,vinewhip,dreameater,smog||221,121,125,176,176,37|N|14,30,27,5,5,30||69|164]Venonat|||None|waterfall,meditate,supersonic,strength||96,65,222,97,97,129|N|13,22,2,,,1||72|40]Marowak|||None|blizzard,focusenergy,roar,thunderwave||94,151,18,197,197,95|N|2,24,17,0,0,19||94|11"} 3 | >player p2 {"name":"Bot 2","team":"Nidorino|||None|screech,toxic,thunder,pound||173,17,5,249,249,131|N|5,0,19,3,3,9||80|36]Poliwhirl|||None|substitute,rage,solarbeam,doublekick||16,236,232,231,231,182|N|11,7,25,26,26,14||80|45]Parasect|||None|bite,sludge,disable,whirlwind||2,93,3,149,149,134|N|8,15,13,8,8,20||54|236]Weedle|||None|jumpkick,fireblast,leer,meditate||49,36,196,30,30,228|N|6,21,11,16,16,15||67|210]Porygon|||None|doubleslap,megapunch,conversion,wingattack||19,237,57,244,244,239|N|9,10,1,11,11,16||99|107]Ninetales|||None|cometpunch,thrash,razorleaf,earthquake||242,63,168,72,72,205|N|10,23,16,0,0,14||78|31"} 4 | >p1 move leer 5 | >p2 switch 2 6 | >p1 move thundershock 7 | >p2 move substitute 8 | >p1 move conversion 9 | >p2 move rage 10 | >p1 move quickattack 11 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x166525E4E3DD0132.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[5733,9700,58333,306]} 2 | >player p1 {"name":"Bot 1","team":"Charizard|||None|scratch,supersonic,quickattack,cut||165,48,50,96,96,135|N|15,14,3,2,2,3||55|94]Poliwrath|||None|poisongas,agility,smog,splash||222,48,76,50,50,71|N|12,27,23,16,16,20||82|176]Zapdos|||None|stringshot,slash,confusion,hyperfang||184,199,171,84,84,102|N|13,22,6,26,26,8||50|65]Kabuto|||None|haze,spore,poisonpowder,lightscreen||250,32,10,152,152,29|N|1,16,25,15,15,8||71|185]Exeggutor|||None|psywave,withdraw,strength,thunderpunch||151,25,38,4,4,159|N|4,8,26,28,28,16||97|193]Dragonair|||None|petaldance,watergun,meditate,bonemerang||52,113,72,246,246,226|N|13,10,,7,7,12||87|44"} 3 | >player p2 {"name":"Bot 2","team":"Porygon|||None|conversion,harden,highjumpkick,fissure||65,124,3,125,125,93|N|11,6,8,3,3,7||94|153]Mewtwo|||None|recover,karatechop,icebeam,thunderwave||30,44,117,135,135,204|N|5,1,27,11,11,4||64|140]Kakuna|||None|barrage,screech,megakick,doubleteam||11,154,134,28,28,55|N|15,26,19,3,3,||81|10]Bellsprout|||None|vinewhip,payday,leechlife,hydropump||96,44,193,174,174,122|N|12,19,27,20,20,4||88|194]Venusaur|||None|acidarmor,sleeppowder,thrash,superfang||113,150,210,77,77,239|N|3,9,16,11,11,26||93|71]Mew|||None|lowkick,doubleslap,constrict,nightshade||5,240,100,15,15,117|N|14,18,7,21,21,26||70|251"} 4 | >p1 move scratch 5 | >p2 switch 2 6 | >p1 move supersonic 7 | >p2 move recover 8 | >p1 move quickattack 9 | >p2 move karatechop 10 | >p1 move cut 11 | >p2 move icebeam 12 | >p1 switch 2 13 | >p2 move thunderwave 14 | >p1 switch 2 15 | >p2 move thunderwave 16 | >p1 move scratch 17 | >p2 switch 2 18 | >p1 switch 3 19 | >p2 move conversion 20 | >p1 move stringshot 21 | >p2 move harden 22 | >p1 switch 4 23 | >p2 move highjumpkick 24 | >p1 move haze 25 | >p2 move fissure -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x1A2182BB0BBD9E64.showdown.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x1A2182BB0BBD9E64.showdown.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x1C6394FF9C3565F4.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x1C6394FF9C3565F4.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x1EE16974B4257C8E.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[7905,26996,46117,31886]} 2 | >player p1 {"name":"Bot 1","team":"Charmander|||None|stunspore,thundershock,ember,teleport||67,250,50,187,187,67|N|7,25,23,27,27,22||53|21]Mr. Mime|||None|explosion,hornattack,wingattack,payday||30,180,35,129,129,57|N|15,2,7,,,||75|53]Primeape|||None|tackle,spikecannon,hypnosis,barrage||200,109,35,135,135,176|N|12,19,2,1,1,8||53|230]Squirtle|||None|bodyslam,solarbeam,flamethrower,sonicboom||182,116,124,220,220,183|N|2,25,5,25,25,14||93|73]Graveler|||None|stomp,flash,defensecurl,glare||75,24,80,33,33,65|N|13,23,27,7,7,9||85|90]Jynx|||None|growl,blizzard,tailwhip,leechlife||144,22,118,154,154,239|N|4,20,19,5,5,13||96|224"} 3 | >player p2 {"name":"Bot 2","team":"Horsea|||None|scratch,acidarmor,swift,lovelykiss||153,13,83,83,83,1|N|14,7,7,4,4,14||78|240]Mankey|||None|substitute,rage,cut,horndrill||36,76,152,95,95,115|N|0,25,13,29,29,25||95|49]Oddish|||None|megapunch,karatechop,quickattack,visegrip||37,131,25,177,177,113|N|1,28,8,11,11,5||78|22]Ninetales|||None|razorwind,dizzypunch,spore,waterfall||176,159,222,104,104,162|N|2,5,24,1,1,11||56|103]Magnemite|||None|kinesis,recover,aurorabeam,slam||70,74,237,68,68,191|N|4,5,22,29,29,5||62|69]Nidorino|||None|earthquake,lightscreen,splash,petaldance||165,238,227,96,96,82|N|0,21,24,29,29,4||65|60"} 4 | >p1 move stunspore 5 | >p2 move scratch 6 | >p1 move thundershock 7 | >p2 move acidarmor 8 | >p1 move ember 9 | >p2 move swift 10 | >p1 move teleport 11 | >p2 move lovelykiss 12 | >p1 move thundershock 13 | >p2 switch 2 14 | >p1 move thundershock 15 | >p2 move substitute 16 | >p1 move teleport 17 | >p2 move rage 18 | >p1 switch 2 19 | >p1 move explosion 20 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x20C2659866E5ED21.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[8386,26008,26341,60705]} 2 | >player p1 {"name":"Bot 1","team":"Raichu|||None|stringshot,firepunch,strength,poisonsting||,229,73,106,106,49|N|14,26,10,1,1,27||60|23]Weepinbell|||None|hypnosis,psybeam,superfang,jumpkick||37,240,83,99,99,55|N|0,20,8,21,21,21||67|201]Beedrill|||None|reflect,doubleteam,roar,thunderwave||93,131,52,68,68,173|N|4,1,15,28,28,20||52|158]Mew|||None|twineedle,bubble,thunderbolt,toxic||184,141,159,25,25,67|N|2,21,12,4,4,22||56|237]Flareon|||None|dizzypunch,hyperbeam,teleport,whirlwind||18,121,181,38,38,221|N|1,1,20,30,30,17||52|245]Ponyta|||None|absorb,icepunch,megakick,slam||120,238,179,178,178,144|N|9,2,29,10,10,28||82|178"} 3 | >player p2 {"name":"Bot 2","team":"Weedle|||None|wingattack,flash,doubleedge,tackle||192,60,219,234,234,82|N|3,0,16,7,7,15||78|56]Electrode|||None|slash,psywave,recover,dragonrage||213,115,149,154,154,111|N|9,10,16,26,26,29||98|52]Slowbro|||None|rage,kinesis,sleeppowder,spikecannon||9,90,96,147,147,57|N|10,,21,28,28,3||77|213]Tangela|||None|drillpeck,skullbash,watergun,cometpunch||173,213,219,227,227,90|N|6,9,18,20,20,15||61|254]Rattata|||None|payday,lowkick,icebeam,leechlife||60,223,69,26,26,73|N|8,27,16,9,9,13||70|242]Electabuzz|||None|acidarmor,sludge,barrier,doublekick||179,215,188,14,14,176|N|7,24,6,11,11,14||50|121"} 4 | >p1 move stringshot 5 | >p2 move doubleedge 6 | >p1 move poisonsting 7 | >p2 switch 2 8 | >p1 switch 2 9 | >p2 switch 2 10 | >p1 move hypnosis 11 | >p2 move tackle 12 | >p1 move superfang 13 | >p2 move tackle 14 | >p1 move jumpkick 15 | >p2 switch 3 16 | >p1 switch 2 17 | >p2 move rage 18 | >p1 move strength 19 | >p2 move rage 20 | >p1 move firepunch 21 | >p2 move rage 22 | >p1 switch 3 23 | >p1 switch 4 24 | >p2 move rage 25 | >p1 switch 5 26 | >p2 move rage 27 | >p1 switch 6 28 | >p2 move rage 29 | >p1 switch 6 30 | >p2 move rage 31 | >p1 switch 2 32 | >p2 move rage 33 | >p1 move superfang 34 | >p2 move rage 35 | >p1 switch 2 36 | >p2 move rage 37 | >p1 move hyperbeam 38 | >p2 move rage 39 | >p1 switch 2 40 | >p1 move hypnosis 41 | >p2 move rage 42 | >p1 switch 6 43 | >p1 move megakick 44 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x219E8F9B8DFA3E50.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x219E8F9B8DFA3E50.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x2E41948934F9D949.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[11841,38025,13561,55625]} 2 | >player p1 {"name":"Bot 1","team":"Sandslash|||None|karatechop,crabhammer,jumpkick,payday||159,83,158,1,1,141|N|6,20,7,17,17,22||69|224]Clefairy|||None|thrash,gust,cometpunch,disable||36,142,165,112,112,65|N|1,9,20,10,10,5||66|26]Electrode|||None|pound,hornattack,leechseed,ember||228,218,176,198,198,121|N|4,0,11,0,0,24||55|221]Flareon|||None|thunderwave,glare,supersonic,spore||67,34,29,218,218,169|N|1,28,8,10,10,28||65|87]Sandshrew|||None|takedown,absorb,swordsdance,fly||171,74,,18,18,242|N|7,0,7,15,15,27||53|38]Marowak|||None|peck,sandattack,rollingkick,psybeam||39,236,252,135,135,163|N|11,23,13,26,26,||58|98"} 3 | >player p2 {"name":"Bot 2","team":"Venusaur|||None|icepunch,furyattack,dreameater,substitute||91,173,205,251,251,83|N|9,11,29,3,3,28||97|10]Nidoran-M|||None|leechlife,eggbomb,furyswipes,lovelykiss||58,182,10,127,127,|N|1,5,25,22,22,17||93|252]Krabby|||None|sonicboom,stomp,surf,amnesia||233,246,27,43,43,40|N|6,0,22,8,8,7||58|118]Charizard|||None|bonemerang,spikecannon,thunder,minimize||206,105,63,241,241,6|N|4,0,27,29,29,1||69|193]Moltres|||None|poisonpowder,stringshot,petaldance,bite||51,163,84,251,251,223|N|15,14,19,,,10||89|63]Nidoran-F|||None|conversion,explosion,thunderpunch,bubble||87,61,149,196,196,66|N|1,17,1,6,6,17||67|83"} 4 | >p1 switch 2 5 | >p2 move icepunch 6 | >p1 move thrash 7 | >p2 move furyattack 8 | >p1 move thrash 9 | >p2 switch 2 10 | >p1 move thrash 11 | >p2 move leechlife 12 | >p1 switch 2 13 | >p2 move eggbomb 14 | >p1 switch 3 15 | >p2 switch 2 16 | >p1 move pound 17 | >p2 switch 3 18 | >p1 move hornattack 19 | >p2 move sonicboom 20 | >p1 move leechseed 21 | >p2 move stomp 22 | >p1 move ember 23 | >p2 move surf 24 | >p1 move leechseed 25 | >p2 move amnesia 26 | >p1 move ember 27 | >p2 move amnesia 28 | >p1 switch 4 29 | >p2 move sonicboom 30 | >p2 switch 4 31 | >p1 move thunderwave 32 | >p2 move bonemerang 33 | >p1 switch 5 34 | >p1 switch 6 35 | >p2 move spikecannon 36 | >p1 switch 4 37 | >p2 switch 5 38 | >p1 move hornattack 39 | >p2 switch 6 40 | >p1 move leechseed 41 | >p2 move conversion 42 | >p1 switch 3 43 | >p2 switch 3 44 | >p1 move karatechop 45 | >p2 move dreameater 46 | >p1 switch 6 47 | >p2 move substitute 48 | >p1 move takedown 49 | >p2 move substitute 50 | >p1 move absorb 51 | >p2 move furyattack -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x30B477546C73D7BC.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[12468,30548,27763,55228]} 2 | >player p1 {"name":"Bot 1","team":"Jolteon|||None|sonicboom,hornattack,thunderbolt,jumpkick||22,164,109,207,207,169|N|5,8,7,18,18,12||95|95]Rattata|||None|eggbomb,growl,scratch,vinewhip||170,70,153,63,63,74|N|7,0,27,,,26||93|44]Vaporeon|||None|disable,whirlwind,rage,tailwhip||59,219,224,155,155,83|N|2,21,24,8,8,2||85|147]Cubone|||None|psywave,conversion,leechlife,headbutt||183,45,202,74,74,76|N|13,26,11,3,3,0||60|71]Mewtwo|||None|explosion,teleport,dragonrage,lightscreen||126,78,32,250,250,75|N|1,25,21,22,22,25||70|206]Nidorino|||None|sing,toxic,thunderwave,watergun||246,170,134,216,216,179|N|14,7,22,20,20,2||59|220"} 3 | >player p2 {"name":"Bot 2","team":"Nidoqueen|||None|psybeam,selfdestruct,constrict,growl||104,242,247,72,72,145|N|12,26,2,9,9,28||66|170]Flareon|||None|pound,roar,teleport,petaldance||32,101,14,156,156,238|N|10,27,9,29,29,14||69|235]Farfetch’d|||None|meditate,sleeppowder,gust,thrash||76,166,59,160,160,7|N|4,25,30,0,0,5||81|166]Voltorb|||None|icepunch,smokescreen,doubleslap,whirlwind||93,126,120,196,196,126|N|1,17,25,3,3,13||98|113]Pidgey|||None|thunder,crabhammer,agility,headbutt||216,178,4,126,126,24|N|2,28,24,12,12,2||83|218]Hypno|||None|razorleaf,toxic,lowkick,skyattack||80,12,85,154,154,130|N|6,16,2,8,8,19||76|136"} 4 | >p1 switch 2 5 | >p2 switch 2 6 | >p1 switch 2 7 | >p2 switch 2 8 | >p1 move sonicboom 9 | >p2 move growl 10 | >p1 move hornattack 11 | >p2 switch 3 12 | >p1 move thunderbolt 13 | >p2 switch 4 14 | >p1 move jumpkick 15 | >p2 move whirlwind 16 | >p2 switch 5 17 | >p1 switch 3 18 | >p2 move headbutt 19 | >p1 switch 4 20 | >p2 switch 6 21 | >p1 move psywave 22 | >p2 move toxic 23 | >p1 switch 5 24 | >p2 move skyattack 25 | >p1 move explosion 26 | >p2 move skyattack 27 | >p1 switch 6 28 | >p2 switch 6 29 | >p1 move sing 30 | >p2 move agility 31 | >p1 move thunderwave 32 | >p2 switch 2 33 | >p1 move toxic 34 | >p2 switch 4 35 | >p1 move sing 36 | >p2 switch 4 37 | >p1 move thunderwave 38 | >p2 move teleport 39 | >p1 switch 3 40 | >p2 switch 3 41 | >p1 move thunderbolt 42 | >p2 move growl 43 | >p1 switch 2 44 | >p2 move constrict 45 | >p1 move eggbomb 46 | >p2 move growl 47 | >p1 move scratch 48 | >p2 switch 3 49 | >p1 move vinewhip 50 | >p2 move roar 51 | >p1 move vinewhip 52 | >p2 switch 3 53 | >p1 switch 2 54 | >p2 move selfdestruct 55 | >p1 switch 5 56 | >p2 switch 4 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x317C2C25C222F280.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[12668,11301,49698,62080]} 2 | >player p1 {"name":"Bot 1","team":"Omanyte|||None|growth,skyattack,razorwind,skullbash||168,99,243,115,115,75|N|2,0,29,20,20,18||81|88]Zapdos|||None|explosion,vinewhip,doubleteam,swordsdance||126,110,186,29,29,95|N|11,3,16,30,30,26||76|]Magnemite|||None|barrage,glare,icebeam,whirlwind||89,46,90,200,200,24|N|10,30,12,21,21,14||98|206]Cubone|||None|eggbomb,doubleedge,rockthrow,twineedle||125,50,172,207,207,179|N|2,20,29,1,1,7||98|143]Arcanine|||None|rage,boneclub,surf,hydropump||247,197,17,22,22,114|N|12,6,26,16,16,8||83|191]Koffing|||None|growl,thunderpunch,recover,watergun||154,54,93,52,52,77|N|15,19,,2,2,26||58|27"} 3 | >player p2 {"name":"Bot 2","team":"Magikarp|||None|bide,doublekick,bonemerang,kinesis||229,64,57,176,176,158|N|15,22,7,,,10||90|162]Raticate|||None|lovelykiss,poisonpowder,sharpen,strength||61,107,23,159,159,169|N|10,19,8,25,25,2||88|213]Weedle|||None|swift,bubblebeam,rollingkick,flamethrower||162,194,122,39,39,153|N|4,13,,9,9,5||51|231]Tentacool|||None|softboiled,withdraw,stomp,conversion||33,126,86,122,122,251|N|0,24,16,21,21,4||85|177]Gastly|||None|poisongas,guillotine,barrier,megadrain||71,33,84,158,158,157|N|2,4,5,24,24,||80|56]Sandslash|||None|stunspore,bite,drillpeck,hornattack||159,91,26,24,24,119|N|5,1,30,,,16||71|63"} 4 | >p1 switch 2 5 | >p2 switch 2 6 | >p1 move explosion 7 | >p2 move lovelykiss 8 | >p1 move vinewhip 9 | >p2 move poisonpowder 10 | >p1 switch 2 11 | >p2 move sharpen 12 | >p1 switch 3 13 | >p2 move strength 14 | >p1 move barrage 15 | >p2 move lovelykiss 16 | >p1 switch 4 17 | >p2 switch 2 18 | >p1 switch 5 19 | >p2 move bide 20 | >p1 switch 6 21 | >p2 move bide 22 | >p1 move growl 23 | >p2 move bide 24 | >p1 switch 3 25 | >p2 switch 3 26 | >p1 move growth 27 | >p2 switch 4 28 | >p1 switch 3 29 | >p2 move softboiled 30 | >p1 move thunderpunch 31 | >p2 move withdraw 32 | >p1 move recover 33 | >p2 move stomp 34 | >p1 move watergun 35 | >p2 switch 5 36 | >p1 move growl 37 | >p2 move poisongas 38 | >p1 move thunderpunch 39 | >p2 move guillotine 40 | >p1 switch 2 41 | >p1 move doubleteam 42 | >p2 switch 6 43 | >p1 switch 6 44 | >p2 switch 5 45 | >p1 switch 6 46 | >p2 move conversion 47 | >p1 switch 4 48 | >p2 move softboiled 49 | >p1 move glare 50 | >p2 move conversion 51 | >p1 move icebeam 52 | >p2 move softboiled 53 | >p1 switch 4 54 | >p2 move stomp 55 | >p1 move swordsdance 56 | >p2 switch 6 57 | >p1 move doubleteam 58 | >p2 switch 3 59 | >p1 switch 6 60 | >p2 move doublekick 61 | >p1 move rage 62 | >p2 move bonemerang 63 | >p1 move rage 64 | >p2 move kinesis 65 | >p1 move rage 66 | >p2 move bide 67 | >p1 move rage 68 | >p2 move bide 69 | >p1 move rage 70 | >p2 move bide 71 | >p1 move rage 72 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x39CCE4D290A254CD.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[14796,58578,37026,21709]} 2 | >player p1 {"name":"Bot 1","team":"Victreebel|||None|furyattack,clamp,doublekick,rollingkick||143,57,235,30,30,240|N|14,10,3,1,1,22||99|61]Flareon|||None|counter,selfdestruct,waterfall,twineedle||22,197,176,171,171,217|N|13,7,30,14,14,13||86|107]Exeggcute|||None|metronome,crabhammer,takedown,kinesis||169,202,48,28,28,21|N|1,0,8,10,10,1||63|200]Pidgeot|||None|disable,confuseray,megapunch,megadrain||250,246,68,128,128,66|N|10,10,13,12,12,18||52|194]Pinsir|||None|whirlwind,hyperbeam,psychic,jumpkick||92,73,252,86,86,164|N|2,5,28,9,9,26||93|244]Nidoran-M|||None|fissure,explosion,scratch,sludge||149,213,33,145,145,148|N|0,4,28,29,29,5||79|117"} 3 | >player p2 {"name":"Bot 2","team":"Charizard|||None|solarbeam,eggbomb,surf,thunderpunch||59,209,244,241,241,106|N|1,4,28,18,18,28||78|239]Dratini|||None|thunderbolt,skullbash,karatechop,horndrill||119,131,30,81,81,31|N|12,,2,21,21,1||84|107]Graveler|||None|thunderwave,hornattack,fly,toxic||69,32,232,125,125,218|N|14,30,30,20,20,7||91|232]Poliwag|||None|boneclub,hydropump,bubblebeam,furyswipes||95,65,203,65,65,128|N|0,13,9,4,4,1||73|207]Hitmonchan|||None|splash,haze,peck,strength||132,199,91,114,114,136|N|10,11,24,16,16,18||66|78]Koffing|||None|leechlife,headbutt,bonemerang,dragonrage||19,244,146,93,93,4|N|0,12,12,12,12,25||66|85"} 4 | >p1 move furyattack 5 | >p2 move solarbeam 6 | >p1 move clamp 7 | >p2 move solarbeam 8 | >p1 move doublekick 9 | >p2 move eggbomb 10 | >p1 switch 2 11 | >p2 move surf 12 | >p1 move counter 13 | >p2 switch 2 14 | >p1 move selfdestruct 15 | >p2 move thunderbolt 16 | >p1 switch 2 17 | >p2 switch 2 18 | >p1 move rollingkick 19 | >p2 move thunderpunch 20 | >p1 move furyattack 21 | >p2 move surf 22 | >p1 move clamp 23 | >p2 switch 3 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x43952058CEDD7279.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[17301,8280,52957,29305]} 2 | >player p1 {"name":"Bot 1","team":"Vaporeon|||None|nightshade,confusion,constrict,icebeam||228,149,98,207,207,36|N|2,16,13,5,5,7||53|234]Charizard|||None|flamethrower,headbutt,megakick,boneclub||48,119,29,220,220,240|N|5,20,,18,18,4||81|143]Tentacool|||None|teleport,megapunch,acid,swordsdance||74,159,3,240,240,208|N|8,,20,0,0,9||75|122]Poliwhirl|||None|fly,doubleslap,roar,hornattack||165,83,43,206,206,189|N|0,21,5,8,8,12||73|194]Weepinbell|||None|lick,thrash,kinesis,agility||185,128,11,94,94,214|N|8,22,12,9,9,9||86|183]Wartortle|||None|icepunch,firepunch,pound,tailwhip||29,49,235,72,72,173|N|3,12,1,3,3,30||61|227"} 3 | >player p2 {"name":"Bot 2","team":"Clefairy|||None|eggbomb,earthquake,surf,amnesia||229,55,153,80,80,157|N|12,23,3,21,21,16||67|118]Tangela|||None|conversion,glare,rockthrow,stunspore||140,108,52,3,3,208|N|13,10,26,23,23,9||96|71]Zapdos|||None|karatechop,vinewhip,blizzard,guillotine||16,238,243,143,143,219|N|4,8,26,16,16,13||90|157]Koffing|||None|bubblebeam,jumpkick,bubble,sharpen||101,23,103,226,226,174|N|0,21,5,20,20,29||57|70]Ivysaur|||None|takedown,focusenergy,quickattack,stringshot||246,89,238,147,147,33|N|11,23,17,10,10,||81|229]Golem|||None|supersonic,disable,doublekick,ember||112,118,214,188,188,177|N|12,18,22,25,25,21||52|249"} 4 | >p1 move nightshade 5 | >p2 move eggbomb 6 | >p1 move confusion 7 | >p2 move earthquake 8 | >p1 move constrict 9 | >p2 switch 2 10 | >p1 switch 2 11 | >p2 move conversion 12 | >p1 move flamethrower 13 | >p2 move glare 14 | >p1 move headbutt 15 | >p2 move rockthrow 16 | >p1 move megakick 17 | >p2 move stunspore 18 | >p1 switch 2 19 | >p2 move conversion 20 | >p1 switch 3 21 | >p2 move glare 22 | >p1 move teleport 23 | >p2 move stunspore 24 | >p1 switch 4 25 | >p2 move rockthrow 26 | >p1 move fly 27 | >p2 switch 2 28 | >p1 move fly 29 | >p2 move surf 30 | >p1 move doubleslap 31 | >p2 move amnesia 32 | >p1 move roar 33 | >p2 move surf 34 | >p1 switch 5 35 | >p2 move earthquake 36 | >p1 move lick 37 | >p2 move surf 38 | >p1 switch 6 39 | >p2 switch 3 40 | >p1 move icepunch 41 | >p2 move karatechop 42 | >p1 move firepunch 43 | >p2 move vinewhip 44 | >p1 switch 5 45 | >p1 move hornattack 46 | >p2 move blizzard 47 | >p1 switch 2 48 | >p1 move boneclub 49 | >p2 switch 4 50 | >p1 move megakick 51 | >p2 move bubblebeam 52 | >p2 switch 5 53 | >p1 move headbutt 54 | >p2 switch 6 55 | >p1 move flamethrower 56 | >p2 move supersonic 57 | >p1 move boneclub 58 | >p2 move disable -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x46C1FA4F5C3A1B4B.showdown.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x46C1FA4F5C3A1B4B.showdown.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x479DCF7B406B5186.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[18333,53115,16491,20870]} 2 | >player p1 {"name":"Bot 1","team":"Geodude|||None|sharpen,psywave,psychic,petaldance||105,173,109,69,69,137|N|10,7,13,4,4,23||67|68]Lickitung|||None|lowkick,wingattack,hornattack,leechlife||161,180,18,24,24,119|N|2,4,9,5,5,22||83|28]Growlithe|||None|bite,conversion,payday,headbutt||219,227,222,113,113,|N|0,16,8,29,29,17||73|17]Graveler|||None|poisonpowder,eggbomb,stomp,doubleteam||167,47,215,105,105,173|N|10,22,29,16,16,23||81|134]Hitmonchan|||None|razorwind,fireblast,surf,furyattack||231,3,174,183,183,143|N|15,10,,7,7,15||61|89]Gengar|||None|hypnosis,superfang,kinesis,blizzard||174,216,55,103,103,178|N|11,30,21,27,27,11||63|92"} 3 | >player p2 {"name":"Bot 2","team":"Cloyster|||None|bide,sing,hydropump,nightshade||60,217,136,221,221,18|N|0,29,9,12,12,12||97|70]Caterpie|||None|bonemerang,pound,minimize,icebeam||183,64,178,35,35,78|N|14,6,,5,5,27||99|196]Starmie|||None|lightscreen,bubble,splash,firepunch||27,30,235,251,251,158|N|15,,26,19,19,15||77|134]Pidgeotto|||None|smokescreen,thunderbolt,stringshot,highjumpkick||64,28,190,16,16,180|N|14,30,15,0,0,19||70|57]Omanyte|||None|screech,teleport,psywave,wingattack||99,178,196,201,201,63|N|2,5,28,4,4,23||79|68]Muk|||None|focusenergy,fissure,spore,quickattack||198,169,16,132,132,162|N|11,6,25,18,18,10||55|2"} 4 | >p1 move sharpen 5 | >p2 switch 2 6 | >p1 move psywave 7 | >p2 move pound 8 | >p1 move psychic 9 | >p2 move minimize 10 | >p1 switch 2 11 | >p2 move minimize 12 | >p1 switch 2 13 | >p2 move bonemerang 14 | >p1 move petaldance 15 | >p2 move minimize 16 | >p1 move petaldance 17 | >p2 move pound 18 | >p1 move petaldance 19 | >p2 move pound 20 | >p1 move psychic 21 | >p2 move bonemerang 22 | >p1 move petaldance 23 | >p2 switch 2 24 | >p1 move petaldance 25 | >p2 move nightshade 26 | >p1 move petaldance 27 | >p2 move bide 28 | >p1 move psychic 29 | >p2 move bide 30 | >p1 switch 3 31 | >p1 move payday 32 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x490175968B905049.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[18689,30102,35728,20553]} 2 | >player p1 {"name":"Bot 1","team":"Mankey|||None|minimize,fly,softboiled,poisongas||185,250,135,122,122,23|N|11,11,25,26,26,3||71|146]Rhyhorn|||None|superfang,bubble,bind,solarbeam||32,230,75,99,99,167|N|8,6,20,25,25,25||89|215]Zapdos|||None|mimic,smog,recover,rockslide||60,218,101,248,248,81|N|7,25,23,22,22,11||67|182]Poliwhirl|||None|megakick,barrier,skyattack,megapunch||228,158,97,78,78,133|N|4,13,,5,5,1||90|217]Omastar|||None|watergun,seismictoss,stomp,thunderwave||222,74,154,133,133,176|N|5,13,10,14,14,13||55|120]Kakuna|||None|lovelykiss,clamp,mist,sleeppowder||237,76,168,91,91,144|N|8,30,25,0,0,29||58|158"} 3 | >player p2 {"name":"Bot 2","team":"Arcanine|||None|growth,twineedle,withdraw,rage||78,61,172,229,229,13|N|1,17,1,14,14,16||76|11]Clefairy|||None|triattack,pinmissile,acidarmor,flamethrower||187,153,82,244,244,195|N|4,17,3,29,29,24||79|32]Jynx|||None|fissure,jumpkick,eggbomb,flash||216,108,11,17,17,202|N|6,24,14,5,5,7||74|28]Nidoran-M|||None|blizzard,roar,psychic,growl||111,69,81,63,63,249|N|8,3,5,5,5,12||64|49]Gastly|||None|icebeam,skullbash,cometpunch,rest||75,58,168,36,36,151|N|11,18,12,27,27,19||59|240]Cloyster|||None|hypnosis,confuseray,fireblast,razorwind||252,6,19,132,132,220|N|12,15,,25,25,16||65|29"} 4 | >p1 move minimize 5 | >p2 move growth 6 | >p1 switch 2 7 | >p2 move twineedle 8 | >p1 move superfang 9 | >p2 move withdraw 10 | >p1 move bubble 11 | >p2 move rage 12 | >p1 move bind 13 | >p2 move rage 14 | >p1 move bind 15 | >p2 move rage 16 | >p1 switch 2 17 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x4AE7643BF1626D6C.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[19175,25659,61794,28012]} 2 | >player p1 {"name":"Bot 1","team":"Tentacruel|||None|thunderbolt,psychic,toxic,nightshade||178,103,138,163,163,227|N|8,19,28,12,12,1||92|105]Exeggcute|||None|fissure,stringshot,fireblast,poisonsting||6,100,204,60,60,18|N|1,20,24,10,10,12||96|144]Ditto|||None|conversion,roar,disable,bite||97,155,80,85,85,89|N|15,11,14,23,23,23||86|194]Oddish|||None|jumpkick,superfang,tailwhip,teleport||162,222,197,226,226,185|N|11,3,28,10,10,3||53|139]Poliwhirl|||None|solarbeam,acidarmor,dragonrage,swordsdance||146,114,180,139,139,242|N|9,,21,30,30,24||72|81]Flareon|||None|glare,stunspore,slam,skullbash||133,173,116,51,51,108|N|2,29,29,28,28,14||77|37"} 3 | >player p2 {"name":"Bot 2","team":"Omanyte|||None|rockthrow,sludge,watergun,twineedle||42,155,60,160,160,219|N|9,11,4,3,3,12||90|166]Charmeleon|||None|thunderpunch,dreameater,rage,kinesis||203,247,213,124,124,193|N|15,6,6,19,19,14||88|47]Staryu|||None|lightscreen,drillpeck,stomp,poisonpowder||248,17,200,7,7,232|N|12,19,11,9,9,1||55|141]Graveler|||None|splash,skyattack,quickattack,sonicboom||238,44,54,162,162,238|N|12,7,18,9,9,4||50|190]Nidorino|||None|ember,leechlife,flamethrower,crabhammer||85,52,51,1,1,103|N|15,19,30,7,7,22||74|105]Voltorb|||None|eggbomb,hypnosis,doubleedge,spore||238,3,124,161,161,142|N|14,22,15,20,20,11||74|31"} 4 | >p1 switch 2 5 | >p2 move rockthrow 6 | >p1 move fissure 7 | >p2 move sludge 8 | >p1 move stringshot 9 | >p2 move watergun 10 | >p1 move fireblast 11 | >p2 move twineedle 12 | >p1 move poisonsting 13 | >p2 move sludge 14 | >p1 switch 2 15 | >p1 switch 3 16 | >p2 switch 2 17 | >p1 move conversion 18 | >p2 move thunderpunch 19 | >p1 move roar 20 | >p2 move dreameater 21 | >p1 move disable 22 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x510BC88B7E670BB9.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x510BC88B7E670BB9.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x582807711B0A22D.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x582807711B0A22D.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x5BB7D44744B7DDB5.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[23479,54343,17591,56757]} 2 | >player p1 {"name":"Bot 1","team":"Oddish|||None|confuseray,sludge,teleport,growl||241,111,160,169,169,95|N|13,11,6,15,15,12||66|250]Gyarados|||None|megapunch,furyattack,smokescreen,surf||134,59,70,44,44,192|N|11,7,0,11,11,26||72|172]Butterfree|||None|aurorabeam,gust,boneclub,thunderpunch||168,21,245,45,45,211|N|2,16,8,17,17,18||89|131]Hypno|||None|payday,fly,bubblebeam,vinewhip||115,246,30,246,246,74|N|8,14,9,16,16,0||79|209]Mankey|||None|triattack,rest,thunder,megadrain||139,90,234,160,160,97|N|4,21,6,25,25,5||92|252]Nidoran-F|||None|hydropump,smog,dizzypunch,strength||192,97,131,152,152,174|N|5,12,18,22,22,16||88|205"} 3 | >player p2 {"name":"Bot 2","team":"Primeape|||None|reflect,acid,recover,nightshade||232,84,195,7,7,52|N|5,28,27,,,13||57|56]Gengar|||None|hyperfang,earthquake,icebeam,bind||22,52,195,211,211,87|N|3,28,28,19,19,15||61|181]Voltorb|||None|mist,dreameater,sing,skullbash||190,14,46,88,88,172|N|0,25,25,28,28,5||81|102]Kadabra|||None|watergun,thunderwave,seismictoss,rockslide||182,56,91,29,29,181|N|11,14,25,2,2,||61|203]Hitmonchan|||None|wrap,substitute,sharpen,disable||165,10,247,133,133,153|N|6,25,30,29,29,10||77|126]Bulbasaur|||None|razorleaf,solarbeam,withdraw,psychic||161,87,189,17,17,73|N|10,19,16,5,5,14||62|47"} 4 | >p1 move confuseray 5 | >p2 switch 2 6 | >p1 switch 2 7 | >p2 move hyperfang 8 | >p1 move furyattack 9 | >p2 move earthquake 10 | >p1 move smokescreen 11 | >p2 switch 2 12 | >p1 move smokescreen 13 | >p2 move reflect 14 | >p1 move smokescreen 15 | >p2 move reflect 16 | >p1 move smokescreen 17 | >p2 move recover 18 | >p1 switch 2 19 | >p2 move recover 20 | >p1 switch 3 21 | >p2 switch 3 22 | >p1 move boneclub 23 | >p2 move sing 24 | >p1 move boneclub 25 | >p2 switch 4 26 | >p1 move gust 27 | >p2 move thunderwave 28 | >p1 move gust 29 | >p2 move thunderwave 30 | >p1 move aurorabeam 31 | >p2 switch 5 32 | >p1 move boneclub 33 | >p2 move wrap 34 | >p1 move gust 35 | >p2 move wrap 36 | >p1 move thunderpunch 37 | >p2 move wrap 38 | >p1 switch 4 39 | >p2 move wrap 40 | >p1 move bubblebeam 41 | >p2 move wrap 42 | >p1 move payday 43 | >p2 move wrap 44 | >p1 move fly 45 | >p2 switch 6 46 | >p1 move vinewhip 47 | >p2 move razorleaf 48 | >p1 move vinewhip 49 | >p2 switch 2 50 | >p1 switch 5 51 | >p2 move earthquake 52 | >p1 move thunder 53 | >p2 switch 6 54 | >p1 move rest 55 | >p2 move substitute 56 | >p1 move megadrain 57 | >p2 move substitute 58 | >p1 move rest 59 | >p2 move sharpen 60 | >p1 move thunder 61 | >p2 move disable 62 | >p1 move rest 63 | >p2 move wrap 64 | >p1 move thunder 65 | >p2 move wrap 66 | >p1 move rest 67 | >p2 move wrap 68 | >p1 move rest 69 | >p2 move sharpen 70 | >p1 move rest 71 | >p2 switch 6 72 | >p1 move rest 73 | >p2 switch 5 74 | >p1 move rest 75 | >p2 switch 6 76 | >p1 move megadrain 77 | >p2 switch 4 78 | >p1 move megadrain 79 | >p2 switch 4 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x5F4C27C3C400CCEF.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[24396,10179,50176,52463]} 2 | >player p1 {"name":"Bot 1","team":"Squirtle|||None|mirrormove,rest,wingattack,doubleteam||153,38,144,96,96,129|N|6,5,7,1,1,14||71|59]Golduck|||None|counter,horndrill,leechseed,bodyslam||106,154,81,227,227,246|N|13,2,11,27,27,1||59|67]Charmander|||None|stomp,peck,leechlife,triattack||39,27,170,36,36,245|N|14,6,27,8,8,7||91|55]Jolteon|||None|lightscreen,rollingkick,smokescreen,aurorabeam||231,85,139,122,122,30|N|10,2,8,21,21,23||98|78]Dugtrio|||None|stunspore,sharpen,icepunch,thunder||213,81,93,150,150,25|N|11,22,16,22,22,30||61|156]Gyarados|||None|submission,bonemerang,confuseray,megapunch||31,4,115,36,36,149|N|0,16,25,16,16,0||90|90"} 3 | >player p2 {"name":"Bot 2","team":"Kangaskhan|||None|guillotine,psychic,harden,boneclub||252,35,4,84,84,3|N|13,10,11,14,14,13||87|17]Charmeleon|||None|quickattack,eggbomb,leer,thunderwave||149,234,208,156,156,92|N|1,8,9,14,14,9||69|29]Fearow|||None|toxic,constrict,furyattack,petaldance||106,155,116,197,197,45|N|13,,30,30,30,8||86|221]Zapdos|||None|solarbeam,furyswipes,rage,karatechop||214,129,241,78,78,112|N|0,24,17,1,1,1||67|139]Golem|||None|bite,razorleaf,whirlwind,poisongas||91,58,56,167,167,100|N|1,9,29,14,14,24||81|249]Arbok|||None|payday,flash,dig,agility||204,81,127,117,117,211|N|13,18,15,3,3,5||83|"} 4 | >p1 move mirrormove 5 | >p2 switch 2 6 | >p1 move rest 7 | >p2 move quickattack 8 | >p1 switch 2 9 | >p2 move eggbomb 10 | >p1 move counter 11 | >p2 move leer 12 | >p1 move horndrill 13 | >p2 switch 2 14 | >p1 move leechseed 15 | >p2 switch 3 16 | >p1 move bodyslam 17 | >p2 move toxic 18 | >p1 switch 2 19 | >p2 switch 4 20 | >p1 move wingattack 21 | >p2 move solarbeam 22 | >p1 move doubleteam 23 | >p2 move solarbeam 24 | >p1 switch 3 25 | >p1 move stomp 26 | >p2 move furyswipes 27 | >p1 move peck 28 | >p2 move rage 29 | >p1 move leechlife 30 | >p2 move rage 31 | >p1 move triattack 32 | >p2 move rage 33 | >p1 switch 4 34 | >p2 move rage 35 | >p1 move lightscreen 36 | >p2 move rage 37 | >p1 switch 5 38 | >p2 move rage 39 | >p1 move stunspore 40 | >p2 move rage 41 | >p1 move sharpen 42 | >p2 move rage 43 | >p1 move icepunch 44 | >p2 move rage 45 | >p1 switch 6 46 | >p1 switch 5 47 | >p2 move rage 48 | >p1 switch 2 49 | >p2 move rage 50 | >p1 move counter 51 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x63F75EBC9E2B6DF8.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[25591,24252,40491,28152]} 2 | >player p1 {"name":"Bot 1","team":"Ekans|||None|sharpen,poisonsting,earthquake,furyswipes||14,87,176,225,225,43|N|5,1,7,2,2,12||71|104]Exeggcute|||None|horndrill,rollingkick,explosion,nightshade||118,75,27,38,38,147|N|5,4,14,6,6,4||72|75]Eevee|||None|roar,spore,pinmissile,wingattack||123,169,146,15,15,120|N|1,25,1,10,10,20||99|131]Nidoking|||None|furyattack,thunderbolt,dreameater,thunderpunch||216,178,70,247,247,59|N|1,9,1,6,6,17||92|59]Gastly|||None|screech,growth,poisonpowder,lightscreen||159,171,223,137,137,31|N|14,22,11,4,4,11||60|144]Persian|||None|hyperbeam,sleeppowder,substitute,karatechop||126,162,8,44,44,4|N|1,21,9,14,14,29||89|118"} 3 | >player p2 {"name":"Bot 2","team":"Nidoqueen|||None|guillotine,thunder,hornattack,poisongas||247,201,64,221,221,131|N|12,30,27,24,24,29||95|199]Clefable|||None|bide,defensecurl,stunspore,watergun||98,238,141,94,94,95|N|3,16,16,7,7,7||78|59]Growlithe|||None|megapunch,swordsdance,flash,razorwind||184,150,10,88,88,226|N|1,13,8,10,10,8||52|143]Starmie|||None|strength,sandattack,confusion,bodyslam||125,193,190,135,135,86|N|3,13,29,3,3,18||69|244]Venusaur|||None|sonicboom,seismictoss,acidarmor,growl||67,4,180,161,161,148|N|4,21,11,12,12,12||89|151]Omanyte|||None|mist,focusenergy,stomp,acid||61,219,155,158,158,221|N|11,11,5,23,23,19||75|96"} 4 | >p1 switch 2 5 | >p2 move guillotine 6 | >p1 move horndrill 7 | >p2 move thunder 8 | >p1 move rollingkick 9 | >p2 move hornattack 10 | >p1 switch 2 11 | >p2 move poisongas 12 | >p1 move sharpen 13 | >p2 switch 2 14 | >p1 move poisonsting 15 | >p2 move bide 16 | >p1 switch 3 17 | >p2 move bide 18 | >p1 move roar 19 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x6EFF8B7677077FE6.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[28415,35702,30471,32742]} 2 | >player p1 {"name":"Bot 1","team":"Magmar|||None|superfang,stomp,rollingkick,leechseed||160,139,191,165,165,159|N|9,30,16,27,27,8||90|105]Golem|||None|vinewhip,psywave,minimize,screech||73,87,202,103,103,18|N|13,2,23,14,14,24||61|141]Tentacool|||None|highjumpkick,bubble,headbutt,reflect||147,181,165,239,239,21|N|1,21,25,2,2,24||95|196]Gyarados|||None|spikecannon,meditate,lowkick,poisonpowder||44,215,201,186,186,166|N|4,4,3,9,9,17||98|158]Nidoran-M|||None|conversion,crabhammer,lovelykiss,doublekick||84,84,196,180,180,228|N|14,11,22,24,24,2||62|41]Lickitung|||None|dreameater,leer,eggbomb,takedown||18,173,153,80,80,18|N|1,9,4,14,14,16||74|135"} 3 | >player p2 {"name":"Bot 2","team":"Scyther|||None|amnesia,supersonic,barrage,bide||26,165,22,71,71,93|N|0,4,5,17,17,17||81|201]Rapidash|||None|twineedle,bodyslam,leechlife,razorwind||32,2,48,158,158,99|N|15,27,2,30,30,7||93|96]Slowpoke|||None|bonemerang,petaldance,surf,scratch||164,114,172,163,163,247|N|6,0,27,20,20,15||80|205]Ivysaur|||None|submission,icepunch,earthquake,hydropump||59,126,234,16,16,247|N|14,14,14,8,8,3||75|30]Parasect|||None|selfdestruct,smog,aurorabeam,thunderbolt||38,180,59,188,188,96|N|5,16,3,15,15,5||57|136]Arcanine|||None|harden,furyswipes,thrash,furyattack||52,157,191,179,179,190|N|1,21,16,2,2,0||90|197"} 4 | >p1 switch 2 5 | >p2 move amnesia 6 | >p1 move vinewhip 7 | >p2 switch 2 8 | >p1 move psywave 9 | >p2 move twineedle 10 | >p1 switch 2 11 | >p2 move bodyslam 12 | >p1 switch 3 13 | >p2 switch 2 14 | >p1 move highjumpkick 15 | >p2 move supersonic 16 | >p1 switch 4 17 | >p2 switch 3 18 | >p1 switch 5 19 | >p2 move bonemerang 20 | >p1 switch 6 21 | >p1 switch 3 22 | >p2 move petaldance 23 | >p1 move superfang 24 | >p2 move petaldance 25 | >p1 move stomp 26 | >p2 move petaldance 27 | >p1 switch 4 28 | >p2 move petaldance 29 | >p1 move bubble 30 | >p2 move surf 31 | >p1 move headbutt 32 | >p2 move scratch 33 | >p2 switch 4 34 | >p1 switch 2 35 | >p2 move submission 36 | >p1 switch 3 37 | >p2 move icepunch 38 | >p1 move dreameater 39 | >p2 move earthquake 40 | >p1 move leer 41 | >p2 move hydropump 42 | >p1 move eggbomb 43 | >p2 move submission 44 | >p1 switch 3 45 | >p2 move submission 46 | >p1 move minimize 47 | >p2 switch 5 48 | >p1 switch 2 49 | >p2 move selfdestruct 50 | >p2 switch 6 51 | >p1 move reflect 52 | >p2 move harden 53 | >p1 move reflect 54 | >p2 move furyswipes 55 | >p1 switch 4 56 | >p2 switch 5 57 | >p1 move rollingkick 58 | >p2 switch 2 59 | >p1 switch 4 60 | >p2 switch 2 61 | >p1 move bubble 62 | >p2 switch 3 63 | >p1 move bubble 64 | >p2 move barrage 65 | >p1 switch 3 66 | >p1 switch 4 67 | >p2 move bide 68 | >p1 move leechseed 69 | >p2 move bide 70 | >p1 switch 4 71 | >p2 move bide 72 | >p1 move takedown 73 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x7DE5A2DD96BA07A5.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[32229,41693,38586,1957]} 2 | >player p1 {"name":"Bot 1","team":"Jynx|||None|dizzypunch,mist,confuseray,gust||135,197,88,76,76,27|N|1,20,24,2,2,12||98|246]Doduo|||None|boneclub,highjumpkick,seismictoss,visegrip||191,97,133,131,131,231|N|10,,0,4,4,23||58|21]Slowpoke|||None|submission,thunderpunch,mist,icepunch||133,168,228,109,109,185|N|1,12,4,26,26,25||67|136]Snorlax|||None|bonemerang,lightscreen,superfang,sludge||250,28,171,222,222,113|N|7,8,23,6,6,6||91|70]Rattata|||None|triattack,psybeam,thundershock,barrier||171,171,125,160,160,57|N|3,1,8,15,15,22||98|117]Ninetales|||None|slash,smog,bubble,hydropump||70,203,206,80,80,133|N|2,29,17,0,0,15||73|163"} 3 | >player p2 {"name":"Bot 2","team":"Voltorb|||None|slam,skyattack,guillotine,doubleteam||165,35,97,4,4,58|N|3,12,1,23,23,18||78|177]Magmar|||None|smokescreen,flamethrower,surf,dig||79,90,38,224,224,26|N|13,15,26,10,10,9||92|195]Bellsprout|||None|flash,firepunch,fly,dragonrage||4,92,204,202,202,103|N|4,1,26,8,8,28||74|16]Machamp|||None|amnesia,eggbomb,sandattack,tailwhip||77,24,202,85,85,223|N|6,21,19,17,17,14||77|173]Gyarados|||None|rockthrow,poisonpowder,harden,substitute||60,166,123,151,151,216|N|2,13,1,29,29,2||71|110]Kakuna|||None|furyattack,bubblebeam,cometpunch,doubleedge||176,69,161,61,61,169|N|10,26,28,17,17,15||59|209"} 4 | >p1 switch 2 5 | >p2 move doubleteam 6 | >p1 switch 2 7 | >p2 switch 2 8 | >p1 move dizzypunch 9 | >p2 move smokescreen 10 | >p1 move mist 11 | >p2 move surf 12 | >p1 switch 3 13 | >p2 move smokescreen 14 | >p1 move icepunch 15 | >p2 move smokescreen 16 | >p1 move thunderpunch 17 | >p2 switch 2 18 | >p1 switch 4 19 | >p2 move slam 20 | >p1 move bonemerang 21 | >p2 switch 3 22 | >p1 move lightscreen 23 | >p2 move fly 24 | >p1 move sludge 25 | >p2 move fly 26 | >p2 switch 4 27 | >p1 move lightscreen 28 | >p2 move amnesia 29 | >p1 switch 5 30 | >p2 switch 5 31 | >p1 move triattack 32 | >p2 move substitute 33 | >p1 move psybeam 34 | >p2 move harden -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x842EFA1D879EC636.showdown.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x842EFA1D879EC636.showdown.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x87CB47D78C9E83DB.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[34763,18391,35998,33755]} 2 | >player p1 {"name":"Bot 1","team":"Charmeleon|||None|seismictoss,sing,poisongas,strength||59,114,126,59,59,163|N|11,11,25,11,11,11||76|217]Eevee|||None|sandattack,thrash,razorleaf,bite||37,98,229,190,190,143|N|10,7,13,0,0,3||77|213]Rattata|||None|highjumpkick,acid,tailwhip,blizzard||78,125,76,132,132,187|N|13,,14,7,7,13||90|65]Meowth|||None|swordsdance,dreameater,explosion,slash||99,232,221,87,87,119|N|1,1,8,14,14,28||69|41]Hitmonlee|||None|growth,growl,thunderpunch,furyswipes||149,180,106,49,49,119|N|11,2,4,23,23,2||88|45]Doduo|||None|eggbomb,horndrill,softboiled,cometpunch||238,249,88,121,121,169|N|12,10,11,21,21,20||70|150"} 3 | >player p2 {"name":"Bot 2","team":"Venonat|||None|rest,minimize,poisonpowder,peck||182,136,200,137,137,179|N|10,30,8,1,1,14||77|223]Rapidash|||None|fireblast,constrict,roar,superfang||30,10,132,53,53,216|N|5,13,6,11,11,9||65|58]Metapod|||None|skyattack,icepunch,megadrain,flamethrower||76,23,252,140,140,76|N|8,30,8,12,12,21||62|249]Weedle|||None|sonicboom,karatechop,lightscreen,vinewhip||246,25,114,215,215,78|N|3,8,4,3,3,7||91|196]Beedrill|||None|doublekick,hyperbeam,payday,sleeppowder||86,224,88,117,117,99|N|14,30,11,12,12,||98|75]Venusaur|||None|skullbash,smog,furyattack,visegrip||213,188,210,146,146,78|N|5,21,11,2,2,28||64|162"} 4 | >p1 move seismictoss 5 | >p2 move rest 6 | >p1 move sing 7 | >p2 move minimize 8 | >p1 switch 2 9 | >p2 move poisonpowder 10 | >p1 switch 2 11 | >p2 move peck 12 | >p1 move poisongas 13 | >p2 switch 2 14 | >p1 switch 3 15 | >p2 switch 2 16 | >p1 switch 4 17 | >p2 move minimize 18 | >p1 move swordsdance 19 | >p2 switch 3 20 | >p1 switch 5 21 | >p2 switch 4 22 | >p1 move growth 23 | >p2 move sonicboom 24 | >p1 move growl 25 | >p2 move karatechop 26 | >p1 switch 6 27 | >p2 switch 5 28 | >p1 move eggbomb 29 | >p2 move doublekick 30 | >p1 move horndrill 31 | >p2 move hyperbeam 32 | >p1 switch 4 33 | >p1 switch 5 34 | >p2 move payday 35 | >p1 move dreameater 36 | >p2 move sleeppowder 37 | >p1 move explosion 38 | >p2 move doublekick 39 | >p1 switch 5 40 | >p1 switch 6 41 | >p2 move payday 42 | >p1 move thunderpunch 43 | >p2 switch 6 44 | >p1 move furyswipes 45 | >p2 move skullbash 46 | >p1 move furyswipes 47 | >p2 move skullbash 48 | >p1 move growth 49 | >p2 move smog 50 | >p1 switch 3 51 | >p2 move furyattack 52 | >p1 switch 3 53 | >p2 move visegrip 54 | >p1 switch 3 55 | >p1 move strength 56 | >p2 move furyattack 57 | >p1 move poisongas 58 | >p2 switch 4 59 | >p1 move sing 60 | >p2 move skyattack 61 | >p1 switch 6 62 | >p2 move skyattack 63 | >p1 move highjumpkick 64 | >p2 switch 4 65 | >p1 move acid 66 | >p2 move smog 67 | >p2 switch 4 68 | >p1 move tailwhip 69 | >p2 switch 5 70 | >p1 switch 2 71 | >p2 move lightscreen 72 | >p1 move sandattack 73 | >p2 move vinewhip 74 | >p1 move thrash 75 | >p2 move vinewhip 76 | >p1 move thrash 77 | >p2 move karatechop -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x891A4DEC2DA0D04A.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[35098,19948,11680,53322]} 2 | >player p1 {"name":"Bot 1","team":"Horsea|||None|razorleaf,absorb,lovelykiss,doublekick||222,37,81,97,97,11|N|5,29,2,3,3,29||90|136]Hitmonlee|||None|horndrill,aurorabeam,jumpkick,thunderwave||94,129,66,89,89,241|N|5,21,3,,,28||62|67]Ditto|||None|vinewhip,slash,dreameater,ember||3,176,142,43,43,98|N|12,27,27,0,0,4||50|196]Dodrio|||None|leechlife,leechseed,psywave,supersonic||92,199,122,202,202,113|N|3,4,28,26,26,10||92|2]Gyarados|||None|crabhammer,whirlwind,substitute,bite||222,124,93,45,45,200|N|9,18,24,15,15,17||74|118]Farfetch’d|||None|dragonrage,seismictoss,sludge,strength||50,172,199,,,215|N|2,1,5,9,9,22||93|37"} 3 | >player p2 {"name":"Bot 2","team":"Vulpix|||None|solarbeam,swift,razorwind,splash||231,60,106,81,81,96|N|15,15,15,18,18,15||86|130]Charmander|||None|explosion,toxic,rollingkick,quickattack||187,199,107,73,73,247|N|5,5,30,22,22,21||72|117]Jigglypuff|||None|growth,karatechop,superfang,wingattack||2,95,182,64,64,181|N|1,0,13,7,7,20||88|56]Metapod|||None|megadrain,doubleedge,sonicboom,confusion||8,13,208,126,126,246|N|14,,18,24,24,30||97|253]Tentacruel|||None|leer,furyattack,rest,focusenergy||43,100,98,240,240,101|N|6,8,15,29,29,27||59|51]Sandslash|||None|eggbomb,rest,poisonpowder,scratch||91,185,195,198,198,241|N|4,17,14,8,8,4||96|160"} 4 | >p1 move razorleaf 5 | >p2 switch 2 6 | >p1 move absorb 7 | >p2 move explosion 8 | >p1 switch 2 9 | >p2 switch 2 10 | >p1 switch 3 11 | >p2 switch 3 12 | >p1 move vinewhip 13 | >p2 move growth 14 | >p1 move slash 15 | >p2 move karatechop 16 | >p1 move dreameater 17 | >p2 switch 4 18 | >p1 move ember 19 | >p2 move megadrain 20 | >p1 switch 4 21 | >p1 move leechlife 22 | >p2 switch 5 23 | >p1 switch 5 24 | >p2 move leer 25 | >p1 move crabhammer 26 | >p2 move furyattack 27 | >p2 switch 6 28 | >p1 move whirlwind 29 | >p2 move eggbomb 30 | >p1 move substitute 31 | >p2 move rest -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x895A570B71E79B86.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[35162,22283,29159,39814]} 2 | >player p1 {"name":"Bot 1","team":"Machoke|||None|blizzard,defensecurl,visegrip,smog||169,101,77,96,96,108|N|9,2,28,2,2,4||72|115]Nidorino|||None|growth,dizzypunch,tailwhip,stomp||35,38,177,32,32,18|N|7,4,26,27,27,3||56|53]Charmander|||None|crabhammer,razorleaf,disable,doubleedge||100,247,213,53,53,210|N|7,9,19,19,19,23||78|27]Ditto|||None|doubleslap,headbutt,tackle,firepunch||156,97,197,43,43,152|N|9,2,0,7,7,28||88|204]Dugtrio|||None|thunder,harden,nightshade,sing||93,130,176,59,59,231|N|13,19,30,10,10,21||68|54]Magneton|||None|bide,poisongas,smokescreen,screech||205,142,219,198,198,182|N|2,5,12,24,24,15||73|60"} 3 | >player p2 {"name":"Bot 2","team":"Seel|||None|swordsdance,megakick,whirlwind,flamethrower||211,9,49,230,230,17|N|15,6,10,27,27,2||74|9]Koffing|||None|rollingkick,spikecannon,rage,sharpen||11,34,161,208,208,69|N|11,6,9,10,10,23||98|24]Nidorina|||None|seismictoss,hypnosis,lightscreen,amnesia||193,157,153,158,158,139|N|0,29,4,21,21,21||92|105]Jynx|||None|razorwind,lowkick,pinmissile,roar||208,19,100,74,74,155|N|4,1,26,17,17,28||66|45]Weezing|||None|confuseray,surf,thundershock,waterfall||182,101,102,49,49,26|N|15,,27,6,6,6||72|247]Raichu|||None|thrash,triattack,agility,focusenergy||10,181,176,51,51,75|N|4,21,26,0,0,1||72|178"} 4 | >p1 move blizzard 5 | >p2 move swordsdance 6 | >p1 switch 2 7 | >p2 move megakick 8 | >p1 switch 2 9 | >p2 switch 2 10 | >p1 move defensecurl 11 | >p2 move rollingkick 12 | >p1 move visegrip 13 | >p2 move spikecannon 14 | >p1 switch 3 15 | >p2 move rage 16 | >p1 move crabhammer 17 | >p2 move rage 18 | >p1 switch 4 19 | >p2 move rage 20 | >p1 move doubleslap 21 | >p2 move rage 22 | >p1 move headbutt 23 | >p2 move rage 24 | >p1 move tackle 25 | >p2 move rage 26 | >p1 switch 5 27 | >p2 move rage 28 | >p1 switch 6 29 | >p2 move rage 30 | >p1 move bide 31 | >p2 move rage 32 | >p1 move bide 33 | >p2 move rage 34 | >p1 move bide 35 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x898990C029C4E108.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[35209,37056,10692,57608]} 2 | >player p1 {"name":"Bot 1","team":"Sandslash|||None|disable,glare,solarbeam,megadrain||197,252,137,181,181,125|N|11,26,1,19,19,26||58|130]Ponyta|||None|wingattack,thunderwave,fly,barrier||107,137,54,244,244,244|N|15,3,22,10,10,30||79|232]Kingler|||None|explosion,poisonsting,ember,seismictoss||2,212,22,174,174,119|N|6,8,7,17,17,19||96|206]Onix|||None|thunderbolt,headbutt,smog,swift||225,242,224,243,243,129|N|9,27,20,10,10,16||78|63]Charizard|||None|bodyslam,whirlwind,dizzypunch,quickattack||226,171,146,222,222,94|N|1,8,12,2,2,20||69|219]Dragonite|||None|poisonpowder,furyswipes,surf,constrict||237,119,223,64,64,213|N|11,15,21,3,3,18||99|174"} 3 | >player p2 {"name":"Bot 2","team":"Squirtle|||None|reflect,leer,mist,aurorabeam||12,175,110,211,211,107|N|15,27,30,10,10,15||99|250]Muk|||None|eggbomb,peck,disable,bide||34,61,116,156,156,113|N|15,14,14,30,30,15||97|223]Rapidash|||None|thrash,waterfall,horndrill,highjumpkick||136,50,243,171,171,185|N|0,13,9,17,17,24||91|86]Hitmonchan|||None|boneclub,stunspore,barrage,payday||71,209,30,249,249,175|N|10,,0,29,29,||69|83]Starmie|||None|crabhammer,teleport,thunderpunch,hornattack||166,107,51,8,8,59|N|2,24,1,21,21,18||62|102]Mankey|||None|sharpen,hyperfang,psychic,focusenergy||214,126,198,77,77,75|N|9,11,8,27,27,24||70|48"} 4 | >p1 move disable 5 | >p2 switch 2 6 | >p1 switch 2 7 | >p2 move disable 8 | >p1 move wingattack 9 | >p2 move peck 10 | >p1 switch 2 11 | >p2 move bide 12 | >p1 move disable 13 | >p2 move bide 14 | >p1 move megadrain 15 | >p2 move struggle 16 | >p1 move glare 17 | >p2 move struggle 18 | >p1 move solarbeam 19 | >p2 move struggle -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x89A935237DDA962E.showdown.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0x89A935237DDA962E.showdown.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x924FD037527C65A3.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[37455,53303,21116,26019]} 2 | >player p1 {"name":"Bot 1","team":"Pidgeotto|||None|lowkick,visegrip,toxic,sludge||51,232,15,191,191,8|N|14,6,30,0,0,2||79|66]Magnemite|||None|karatechop,absorb,focusenergy,watergun||130,172,122,81,81,154|N|2,21,0,8,8,6||82|220]Hitmonlee|||None|bind,supersonic,bite,doubleedge||137,219,32,11,11,185|N|0,24,17,13,13,20||84|168]Vulpix|||None|nightshade,hydropump,bubblebeam,fly||34,181,87,102,102,22|N|10,22,5,13,13,14||64|128]Nidorino|||None|counter,barrier,waterfall,confuseray||131,112,149,55,55,78|N|2,8,25,24,24,7||99|235]Ditto|||None|wrap,mist,lick,sandattack||151,117,154,251,251,35|N|2,1,9,21,21,11||97|27"} 3 | >player p2 {"name":"Bot 2","team":"Rhyhorn|||None|razorwind,psybeam,skullbash,psychic||53,3,90,243,243,139|N|1,29,20,23,23,12||62|19]Haunter|||None|highjumpkick,hornattack,stunspore,firepunch||78,131,228,59,59,150|N|9,15,1,30,30,0||92|22]Oddish|||None|poisonpowder,sharpen,doubleslap,surf||144,150,43,249,249,130|N|5,20,3,,,9||86|124]Bellsprout|||None|quickattack,leechlife,swordsdance,jumpkick||12,9,238,119,119,250|N|6,20,6,1,1,26||74|16]Zapdos|||None|rockthrow,thundershock,leer,haze||169,104,250,32,32,234|N|1,5,25,10,10,21||69|25]Marowak|||None|stringshot,rockslide,poisongas,bubble||214,228,150,65,65,22|N|9,6,9,19,19,12||54|178"} 4 | >p1 move lowkick 5 | >p2 switch 2 6 | >p1 switch 2 7 | >p2 move highjumpkick 8 | >p1 switch 2 9 | >p2 switch 2 10 | >p1 move visegrip 11 | >p2 switch 3 12 | >p1 move toxic 13 | >p2 move poisonpowder 14 | >p1 move sludge 15 | >p2 switch 4 16 | >p1 move visegrip 17 | >p2 move quickattack 18 | >p1 move sludge 19 | >p2 move leechlife 20 | >p1 move toxic 21 | >p2 move swordsdance 22 | >p1 move sludge 23 | >p2 move jumpkick 24 | >p2 switch 5 25 | >p1 switch 3 26 | >p2 move rockthrow 27 | >p1 move bind 28 | >p2 move thundershock 29 | >p1 move bind 30 | >p2 switch 6 31 | >p1 switch 4 32 | >p2 move stringshot 33 | >p1 move nightshade 34 | >p2 move rockslide 35 | >p1 move hydropump 36 | >p2 move poisongas 37 | >p2 switch 6 38 | >p1 move bubblebeam 39 | >p2 move leer 40 | >p1 move fly 41 | >p2 move haze 42 | >p1 move fly 43 | >p2 switch 3 44 | >p1 move nightshade 45 | >p2 switch 3 46 | >p1 move nightshade 47 | >p2 switch 4 48 | >p1 switch 5 49 | >p2 move sharpen 50 | >p1 switch 6 51 | >p2 move doubleslap 52 | >p1 move wrap 53 | >p2 move surf 54 | >p1 move wrap 55 | >p2 move doubleslap 56 | >p1 move mist 57 | >p2 move surf 58 | >p1 move lick 59 | >p2 move poisonpowder 60 | >p1 move sandattack 61 | >p2 switch 4 62 | >p1 move wrap 63 | >p2 move leer 64 | >p1 move wrap 65 | >p2 switch 4 66 | >p2 switch 4 67 | >p1 move wrap 68 | >p2 move rockthrow 69 | >p1 move wrap 70 | >p2 switch 2 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x973C10A9C58D94FD.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[38716,4265,50573,38141]} 2 | >player p1 {"name":"Bot 1","team":"Vulpix|||None|eggbomb,poisonsting,stringshot,dragonrage||17,17,208,199,199,154|N|10,11,1,13,13,23||98|177]Venusaur|||None|confusion,solarbeam,reflect,sludge||109,5,148,171,171,63|N|8,3,17,21,21,28||80|118]Goldeen|||None|selfdestruct,hornattack,megakick,focusenergy||165,242,247,32,32,12|N|5,16,30,19,19,9||99|172]Articuno|||None|furyattack,hyperfang,superfang,crabhammer||33,,41,95,95,1|N|14,2,10,12,12,3||63|213]Graveler|||None|leechseed,splash,barrage,watergun||104,221,56,119,119,197|N|3,20,28,,,6||75|238]Metapod|||None|swift,seismictoss,rockthrow,smog||116,186,24,14,14,234|N|4,24,30,25,25,29||79|25"} 3 | >player p2 {"name":"Bot 2","team":"Clefairy|||None|hypnosis,waterfall,stringshot,skyattack||115,42,110,219,219,27|N|8,11,4,8,8,25||52|8]Pidgeot|||None|furyswipes,lightscreen,sleeppowder,rollingkick||35,234,41,48,48,51|N|15,7,14,2,2,3||65|124]Bellsprout|||None|tailwhip,acid,substitute,selfdestruct||241,219,70,62,62,166|N|12,,18,13,13,1||50|204]Machop|||None|rockslide,rage,headbutt,doubleslap||130,50,148,111,111,194|N|4,20,26,1,1,24||78|84]Kangaskhan|||None|spikecannon,growl,tackle,swordsdance||21,73,191,101,101,153|N|3,1,13,2,2,27||84|28]Mr. Mime|||None|flash,stomp,pinmissile,slash||182,135,61,163,163,25|N|10,30,5,13,13,26||60|239"} 4 | >p1 move eggbomb 5 | >p2 move stringshot 6 | >p1 move poisonsting 7 | >p2 move hypnosis 8 | >p1 switch 2 9 | >p2 switch 2 10 | >p1 switch 2 11 | >p2 move sleeppowder 12 | >p1 switch 3 13 | >p2 move lightscreen 14 | >p1 move selfdestruct 15 | >p2 move rollingkick 16 | >p1 switch 4 17 | >p2 switch 2 18 | >p1 move furyattack 19 | >p2 move stringshot 20 | >p1 move hyperfang 21 | >p2 switch 3 22 | >p1 switch 5 23 | >p2 switch 4 24 | >p1 move leechseed 25 | >p2 move doubleslap 26 | >p1 move splash 27 | >p2 switch 5 28 | >p1 move barrage 29 | >p2 switch 6 30 | >p1 move watergun 31 | >p2 switch 4 32 | >p2 switch 6 33 | >p1 move leechseed 34 | >p2 move spikecannon 35 | >p1 move splash 36 | >p2 move spikecannon 37 | >p1 move barrage 38 | >p2 move spikecannon 39 | >p1 move splash 40 | >p2 move spikecannon 41 | >p1 move barrage 42 | >p2 move swordsdance 43 | >p1 move barrage 44 | >p2 move swordsdance 45 | >p1 move splash 46 | >p2 switch 4 47 | >p1 move splash 48 | >p2 switch 3 49 | >p1 move leechseed 50 | >p2 move skyattack 51 | >p1 move watergun 52 | >p2 move skyattack 53 | >p1 move leechseed 54 | >p2 move waterfall 55 | >p1 switch 6 56 | >p2 move waterfall 57 | >p2 switch 4 58 | >p1 move seismictoss 59 | >p2 move tackle 60 | >p1 move swift 61 | >p2 switch 5 62 | >p1 move swift 63 | >p2 move rage 64 | >p1 move rockthrow 65 | >p2 move rage 66 | >p1 move rockthrow 67 | >p2 move rage 68 | >p1 move seismictoss 69 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x973EF0823E0530B9.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[38718,61570,15877,12473]} 2 | >player p1 {"name":"Bot 1","team":"Charizard|||None|thunder,blizzard,thundershock,counter||153,33,196,141,141,27|N|5,8,3,27,27,8||95|228]Golbat|||None|kinesis,metronome,pinmissile,glare||37,88,142,68,68,4|N|0,0,5,24,24,8||95|21]Staryu|||None|doubleteam,cometpunch,seismictoss,ember||40,63,185,117,117,218|N|6,21,23,8,8,6||67|82]Magikarp|||None|fireblast,furyswipes,vinewhip,recover||154,25,249,114,114,233|N|11,,1,6,6,||93|247]Cubone|||None|acid,bide,skullbash,fissure||228,158,100,8,8,36|N|9,15,21,2,2,13||80|114]Spearow|||None|doublekick,toxic,boneclub,drillpeck||98,101,68,69,69,222|N|8,10,13,12,12,21||50|82"} 3 | >player p2 {"name":"Bot 2","team":"Articuno|||None|hyperfang,leechlife,karatechop,waterfall||248,25,12,95,95,123|N|2,9,24,4,4,6||97|158]Tauros|||None|slash,acidarmor,mist,razorleaf||33,198,129,91,91,14|N|5,16,27,18,18,21||89|245]Charmeleon|||None|bite,jumpkick,megapunch,takedown||36,61,195,85,85,145|N|8,7,28,28,28,24||67|138]Golem|||None|mimic,sandattack,wrap,scratch||196,189,124,55,55,4|N|7,9,7,26,26,2||69|54]Voltorb|||None|thunderwave,superfang,confuseray,poisonsting||75,104,31,44,44,246|N|13,11,26,10,10,21||52|235]Gloom|||None|psywave,transform,rockthrow,quickattack||16,90,137,59,59,210|N|13,14,22,,,0||65|168"} 4 | >p1 switch 2 5 | >p2 move hyperfang 6 | >p1 move kinesis 7 | >p2 switch 2 8 | >p1 move metronome 9 | >p2 switch 2 10 | >p1 move pinmissile 11 | >p2 move leechlife 12 | >p1 switch 2 13 | >p2 switch 3 14 | >p1 move thunder 15 | >p2 switch 4 16 | >p1 move blizzard 17 | >p2 switch 5 18 | >p2 switch 6 19 | >p1 move thundershock 20 | >p2 move psywave 21 | >p1 move counter 22 | >p2 move transform 23 | >p1 move counter 24 | >p2 move counter 25 | >p1 switch 3 26 | >p2 switch 5 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x9C329D229CD33ED7.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[39986,40226,40147,16087]} 2 | >player p1 {"name":"Bot 1","team":"Fearow|||None|takedown,rollingkick,swordsdance,confusion||147,123,58,97,97,203|N|5,8,11,11,11,9||86|176]Krabby|||None|thunderbolt,swordsdance,glare,bide||137,70,163,102,102,234|N|6,9,15,28,28,14||85|105]Raticate|||None|headbutt,fireblast,waterfall,furyattack||161,10,219,133,133,199|N|13,23,3,7,7,17||71|52]Onix|||None|doubleedge,bonemerang,scratch,seismictoss||126,71,96,58,58,43|N|11,23,8,14,14,6||79|13]Pidgey|||None|poisongas,lightscreen,jumpkick,psywave||13,93,174,45,45,240|N|12,19,19,29,29,25||72|58]Dragonair|||None|eggbomb,barrier,stunspore,vinewhip||241,114,155,135,135,70|N|5,13,19,22,22,8||57|128"} 3 | >player p2 {"name":"Bot 2","team":"Rhyhorn|||None|thunderwave,sludge,acidarmor,meditate||40,208,179,13,13,76|N|4,4,23,4,4,20||63|0]Spearow|||None|megadrain,solarbeam,withdraw,crabhammer||34,65,252,96,96,47|N|1,12,24,6,6,8||79|238]Gastly|||None|hyperbeam,strength,bodyslam,gust||156,105,157,135,135,164|N|9,23,20,26,26,25||98|95]Kingler|||None|screech,growl,conversion,defensecurl||49,129,98,155,155,169|N|7,13,23,3,3,27||90|254]Horsea|||None|horndrill,growth,megakick,minimize||48,193,53,69,69,143|N|14,30,11,13,13,||95|9]Kangaskhan|||None|teleport,fissure,peck,petaldance||85,248,61,112,112,104|N|6,16,22,29,29,7||58|174"} 4 | >p1 move takedown 5 | >p2 move meditate 6 | >p1 move rollingkick 7 | >p2 move acidarmor 8 | >p1 move swordsdance 9 | >p2 switch 2 10 | >p1 switch 2 11 | >p2 move solarbeam 12 | >p1 switch 2 13 | >p2 move solarbeam 14 | >p1 move rollingkick 15 | >p2 switch 2 16 | >p2 switch 3 17 | >p1 move takedown 18 | >p2 move bodyslam 19 | >p1 switch 3 20 | >p2 move bodyslam 21 | >p1 move headbutt 22 | >p2 switch 4 23 | >p1 switch 4 24 | >p2 switch 5 25 | >p1 move doubleedge 26 | >p2 move megakick 27 | >p1 move bonemerang 28 | >p2 move megakick 29 | >p1 move seismictoss 30 | >p2 move megakick 31 | >p2 switch 6 32 | >p1 move doubleedge 33 | >p2 move teleport 34 | >p1 switch 5 35 | >p2 move fissure 36 | >p1 move lightscreen 37 | >p2 switch 4 38 | >p1 move jumpkick 39 | >p2 move gust 40 | >p1 move lightscreen 41 | >p2 switch 4 42 | >p1 switch 6 43 | >p2 move teleport 44 | >p1 switch 5 45 | >p2 move teleport 46 | >p1 move scratch 47 | >p2 switch 2 48 | >p1 switch 4 49 | >p2 switch 2 50 | >p1 move headbutt 51 | >p2 move petaldance 52 | >p1 move headbutt 53 | >p2 move peck 54 | >p1 switch 2 55 | >p2 move petaldance 56 | >p1 switch 4 57 | >p2 move petaldance 58 | >p1 switch 4 59 | >p1 move bide 60 | >p2 move petaldance 61 | >p1 move bide 62 | >p2 move teleport -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x9E2B535EAB26BB7E.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[40491,21342,43814,47998]} 2 | >player p1 {"name":"Bot 1","team":"Alakazam|||None|submission,absorb,smokescreen,softboiled||214,234,213,222,222,35|N|11,15,8,18,18,||55|122]Nidorino|||None|doubleslap,hyperfang,fissure,dragonrage||48,22,6,80,80,91|N|7,17,,22,22,23||98|79]Sandslash|||None|firepunch,fireblast,icebeam,rest||248,28,109,230,230,166|N|4,20,26,28,28,12||75|231]Goldeen|||None|bodyslam,gust,supersonic,doubleedge||137,127,164,65,65,67|N|8,30,12,5,5,29||50|50]Nidoking|||None|earthquake,bubble,selfdestruct,growth||160,114,37,24,24,106|N|3,20,1,26,26,27||95|114]Lapras|||None|spikecannon,rage,quickattack,amnesia||43,51,90,37,37,22|N|15,7,7,23,23,11||65|106"} 3 | >player p2 {"name":"Bot 2","team":"Electabuzz|||None|confuseray,swift,bide,substitute||186,241,209,44,44,70|N|4,8,6,20,20,29||90|237]Charmeleon|||None|payday,barrier,nightshade,thrash||2,75,157,237,237,43|N|12,18,11,20,20,29||94|231]Tentacool|||None|pound,thunderwave,haze,thunder||70,37,159,156,156,216|N|2,1,4,12,12,19||81|191]Cubone|||None|rockthrow,bite,leechlife,amnesia||33,193,151,234,234,45|N|14,6,7,9,9,26||57|72]Dodrio|||None|strength,cometpunch,focusenergy,confusion||232,160,43,232,232,9|N|15,22,19,2,2,||57|206]Slowpoke|||None|rockthrow,acidarmor,hyperfang,dizzypunch||97,115,45,3,3,148|N|6,0,11,5,5,6||67|230"} 4 | >p1 switch 2 5 | >p2 move confuseray 6 | >p1 move doubleslap 7 | >p2 move swift 8 | >p1 move hyperfang 9 | >p2 move bide 10 | >p1 move fissure 11 | >p2 move bide 12 | >p1 move dragonrage 13 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0x9FFAFACA6FEECB03.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[40954,64202,28654,51971]} 2 | >player p1 {"name":"Bot 1","team":"Cloyster|||None|razorwind,focusenergy,dragonrage,barrier||66,176,229,189,189,175|N|4,24,26,8,8,17||93|150]Farfetch’d|||None|roar,confusion,tackle,agility||90,60,248,67,67,47|N|15,18,19,2,2,15||61|169]Machamp|||None|solarbeam,recover,stringshot,payday||100,68,61,205,205,106|N|11,30,12,18,18,23||65|170]Charmander|||None|teleport,smog,poisonsting,psybeam||178,,58,243,243,54|N|12,7,19,21,21,25||70|39]Cubone|||None|bubblebeam,sharpen,skyattack,disable||39,54,23,44,44,29|N|8,3,0,16,16,13||93|227]Aerodactyl|||None|substitute,acid,constrict,slash||82,191,9,226,226,159|N|13,11,11,7,7,25||91|12"} 3 | >player p2 {"name":"Bot 2","team":"Gengar|||None|harden,pound,megakick,wingattack||249,89,140,119,119,167|N|4,28,19,9,9,24||63|104]Charmeleon|||None|submission,vinewhip,skullbash,doubleedge||142,123,166,134,134,185|N|13,22,2,26,26,12||66|53]Clefable|||None|spore,rest,psychic,megapunch||186,35,10,165,165,252|N|12,15,,28,28,16||97|187]Magikarp|||None|explosion,petaldance,supersonic,thunderwave||135,122,202,23,23,94|N|9,26,4,3,3,13||88|32]Tentacool|||None|takedown,icebeam,splash,selfdestruct||75,99,241,167,167,48|N|4,25,7,25,25,25||88|61]Pikachu|||None|cometpunch,haze,eggbomb,reflect||101,248,125,81,81,202|N|15,22,15,11,11,11||84|231"} 4 | >p1 move razorwind 5 | >p2 switch 2 6 | >p1 move razorwind 7 | >p2 move submission 8 | >p1 move focusenergy 9 | >p2 move vinewhip 10 | >p1 switch 2 11 | >p2 switch 2 12 | >p1 move roar 13 | >p2 move harden 14 | >p1 move confusion 15 | >p2 move pound 16 | >p1 switch 2 17 | >p2 move megakick 18 | >p1 switch 3 19 | >p2 switch 3 20 | >p1 move solarbeam 21 | >p2 move spore 22 | >p1 move recover 23 | >p2 move rest 24 | >p1 move stringshot 25 | >p2 move psychic 26 | >p1 switch 4 27 | >p1 move teleport 28 | >p2 move megapunch 29 | >p1 switch 5 30 | >p2 move rest 31 | >p1 switch 6 32 | >p2 move megapunch 33 | >p1 switch 5 34 | >p2 switch 4 35 | >p1 switch 2 36 | >p2 switch 2 37 | >p1 move tackle 38 | >p2 move skullbash 39 | >p1 move agility 40 | >p2 move skullbash 41 | >p1 move roar 42 | >p2 move doubleedge 43 | >p1 switch 6 44 | >p2 switch 6 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xA0406E4B3AA33F5E.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[41024,28235,15011,16222]} 2 | >player p1 {"name":"Bot 1","team":"Jynx|||None|psywave,pound,dreameater,waterfall||44,119,8,167,167,123|N|14,15,22,16,16,6||55|145]Kadabra|||None|bodyslam,superfang,reflect,karatechop||125,21,102,140,140,63|N|1,4,0,7,7,28||59|182]Raticate|||None|icebeam,gust,doublekick,poisonsting||10,237,150,61,61,34|N|3,13,4,10,10,2||81|253]Dragonite|||None|firepunch,peck,focusenergy,slam||141,106,3,169,169,33|N|11,10,1,10,10,10||99|122]Sandslash|||None|hyperbeam,submission,growth,furyattack||194,183,44,1,1,199|N|2,24,0,21,21,30||71|196]Victreebel|||None|rest,surf,psychic,rage||177,88,83,229,229,16|N|6,1,11,28,28,19||80|192"} 3 | >player p2 {"name":"Bot 2","team":"Rhyhorn|||None|swift,disable,bubblebeam,poisonpowder||87,185,160,21,21,31|N|3,13,0,30,30,23||58|115]Jolteon|||None|fissure,bide,eggbomb,spore||94,18,52,232,232,173|N|6,9,18,9,9,14||66|63]Staryu|||None|thrash,stringshot,headbutt,smog||226,22,60,,,98|N|12,22,2,0,0,8||93|246]Tentacool|||None|bite,kinesis,visegrip,recover||136,12,73,188,188,114|N|3,29,5,,,23||84|186]Bellsprout|||None|withdraw,harden,furyswipes,sharpen||197,219,203,22,22,188|N|3,28,1,18,18,22||85|220]Metapod|||None|megakick,megapunch,swordsdance,splash||168,146,116,198,198,216|N|12,2,30,1,1,5||57|55"} 4 | >p1 move psywave 5 | >p2 move swift 6 | >p1 switch 2 7 | >p2 move disable 8 | >p1 switch 2 9 | >p2 move bubblebeam 10 | >p1 move pound 11 | >p2 move poisonpowder 12 | >p1 switch 3 13 | >p2 move poisonpowder 14 | >p1 move icebeam 15 | >p2 move bubblebeam 16 | >p2 switch 2 17 | >p1 move gust 18 | >p2 switch 3 19 | >p1 switch 4 20 | >p2 move thrash 21 | >p1 switch 5 22 | >p2 move thrash 23 | >p1 move hyperbeam 24 | >p2 move thrash 25 | >p2 switch 4 26 | >p1 move submission 27 | >p2 move bite 28 | >p1 move growth 29 | >p2 switch 5 30 | >p1 move furyattack 31 | >p2 move withdraw 32 | >p1 move growth 33 | >p2 move harden 34 | >p1 switch 6 35 | >p2 move furyswipes 36 | >p1 switch 4 37 | >p2 switch 6 38 | >p1 move doublekick 39 | >p2 move megakick 40 | >p1 switch 2 41 | >p2 move megapunch 42 | >p1 move bodyslam 43 | >p2 move swordsdance 44 | >p1 move superfang 45 | >p2 move splash 46 | >p1 move reflect 47 | >p2 switch 5 48 | >p1 move karatechop 49 | >p2 move kinesis 50 | >p1 move bodyslam 51 | >p2 switch 3 52 | >p1 switch 5 53 | >p2 move fissure 54 | >p1 move firepunch 55 | >p2 move bide 56 | >p1 switch 6 57 | >p2 move bide 58 | >p1 move growth 59 | >p2 move bide 60 | >p1 move furyattack 61 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xA0F50070ADB32DED.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[41205,112,44467,11757]} 2 | >player p1 {"name":"Bot 1","team":"Primeape|||None|cut,megakick,sandattack,acid||46,188,124,176,176,141|N|4,4,,0,0,20||85|220]Gastly|||None|kinesis,scratch,razorwind,splash||63,205,138,200,200,199|N|6,16,10,8,8,3||72|210]Exeggutor|||None|strength,poisonpowder,stringshot,mist||115,216,240,117,117,252|N|9,6,20,14,14,1||64|210]Staryu|||None|hornattack,gust,swift,clamp||188,8,113,185,185,130|N|7,5,26,2,2,15||98|241]Nidorina|||None|spore,thundershock,superfang,defensecurl||86,116,25,116,116,242|N|13,18,15,30,30,25||70|133]Mew|||None|agility,psychic,eggbomb,bubble||86,49,227,16,16,96|N|10,2,17,17,17,26||62|13"} 3 | >player p2 {"name":"Bot 2","team":"Vileplume|||None|sleeppowder,sonicboom,fireblast,splash||127,200,218,189,189,62|N|1,21,1,6,6,1||72|190]Rhydon|||None|mimic,tailwhip,substitute,pinmissile||109,17,206,23,23,114|N|7,12,3,,,14||58|74]Hitmonchan|||None|barrier,roar,absorb,wingattack||57,90,84,150,150,170|N|1,12,17,26,26,29||79|195]Rattata|||None|watergun,psychic,wrap,triattack||150,50,148,199,199,166|N|3,0,8,7,7,11||64|30]Magneton|||None|fly,barrage,petaldance,eggbomb||29,151,148,128,128,144|N|13,23,22,26,26,12||57|64]Magnemite|||None|counter,surf,bite,skullbash||142,249,29,84,84,212|N|7,29,23,19,19,||63|177"} 4 | >p1 switch 2 5 | >p2 move sonicboom 6 | >p1 move razorwind 7 | >p2 switch 2 8 | >p1 move razorwind 9 | >p2 move pinmissile 10 | >p1 move razorwind 11 | >p2 move tailwhip 12 | >p1 move razorwind 13 | >p2 move mimic 14 | >p1 switch 2 15 | >p2 switch 2 16 | >p1 move cut 17 | >p2 switch 3 18 | >p1 switch 3 19 | >p2 switch 4 20 | >p1 move stringshot 21 | >p2 move wrap 22 | >p1 move mist 23 | >p2 move wrap 24 | >p1 move stringshot 25 | >p2 switch 5 26 | >p1 move poisonpowder 27 | >p2 move fly 28 | >p1 move poisonpowder 29 | >p2 move fly 30 | >p1 move poisonpowder 31 | >p2 move fly 32 | >p1 move stringshot 33 | >p2 move fly 34 | >p1 switch 4 35 | >p2 move petaldance 36 | >p1 switch 5 37 | >p2 move petaldance 38 | >p1 switch 6 39 | >p2 move petaldance 40 | >p1 switch 6 41 | >p2 move petaldance 42 | >p1 move superfang 43 | >p2 move eggbomb 44 | >p1 switch 3 45 | >p2 move petaldance 46 | >p1 move megakick 47 | >p2 move petaldance 48 | >p1 move acid 49 | >p2 move petaldance 50 | >p2 switch 6 51 | >p1 switch 4 52 | >p2 move counter 53 | >p1 move stringshot 54 | >p2 move surf 55 | >p1 move stringshot 56 | >p2 move surf 57 | >p1 move strength 58 | >p2 switch 2 59 | >p1 switch 2 60 | >p2 switch 4 61 | >p1 move splash 62 | >p2 switch 2 63 | >p1 move razorwind 64 | >p2 move counter -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xA31F27EAF9BF4E3B.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[41759,10218,63935,20027]} 2 | >player p1 {"name":"Bot 1","team":"Weedle|||None|razorwind,slash,eggbomb,icebeam||200,126,188,93,93,82|N|5,12,23,18,18,13||70|211]Blastoise|||None|highjumpkick,acidarmor,dig,counter||206,111,13,192,192,100|N|0,28,29,25,25,28||92|159]Bulbasaur|||None|hyperbeam,absorb,psywave,swift||107,239,29,1,1,189|N|3,13,13,19,19,18||98|88]Arbok|||None|sing,horndrill,submission,poisonsting||100,121,81,123,123,241|N|9,26,16,2,2,29||57|67]Pidgeot|||None|bonemerang,psybeam,doublekick,firepunch||138,12,55,79,79,101|N|14,15,,12,12,19||99|107]Flareon|||None|doubleteam,flamethrower,hornattack,barrage||200,88,206,126,126,141|N|1,1,16,18,18,12||52|64"} 3 | >player p2 {"name":"Bot 2","team":"Arcanine|||None|scratch,furyswipes,skullbash,pinmissile||164,3,93,23,23,49|N|15,30,7,6,6,19||72|10]Omanyte|||None|sandattack,seismictoss,withdraw,lightscreen||60,152,138,29,29,117|N|10,14,8,13,13,19||50|178]Raichu|||None|aurorabeam,toxic,headbutt,megadrain||128,210,34,22,22,214|N|11,18,25,10,10,||84|16]Oddish|||None|stunspore,amnesia,growth,sonicboom||89,120,65,74,74,18|N|3,20,9,18,18,11||99|32]Primeape|||None|drillpeck,crabhammer,glare,hydropump||72,153,78,142,142,148|N|12,23,3,0,0,16||91|83]Magmar|||None|bodyslam,softboiled,disable,karatechop||108,35,113,94,94,28|N|11,10,5,23,23,15||71|77"} 4 | >p1 switch 2 5 | >p2 switch 2 6 | >p1 move highjumpkick 7 | >p2 move sandattack 8 | >p1 move acidarmor 9 | >p2 move seismictoss 10 | >p1 move dig 11 | >p2 move withdraw 12 | >p1 move dig 13 | >p2 switch 2 14 | >p1 switch 2 15 | >p2 move scratch 16 | >p1 switch 3 17 | >p2 move furyswipes 18 | >p1 move hyperbeam 19 | >p2 move skullbash 20 | >p1 move recharge 21 | >p2 move skullbash 22 | >p1 switch 4 23 | >p2 move pinmissile 24 | >p1 switch 5 25 | >p2 switch 3 26 | >p1 move bonemerang 27 | >p2 move aurorabeam 28 | >p2 switch 4 29 | >p1 move psybeam 30 | >p2 switch 5 31 | >p1 switch 6 32 | >p2 move drillpeck 33 | >p1 move doubleteam 34 | >p2 switch 6 35 | >p1 move flamethrower 36 | >p2 move bodyslam 37 | >p1 move hornattack 38 | >p2 move softboiled 39 | >p1 switch 2 40 | >p2 move disable 41 | >p1 move counter 42 | >p2 move karatechop 43 | >p1 move acidarmor 44 | >p2 switch 2 45 | >p1 move highjumpkick 46 | >p2 switch 2 47 | >p2 switch 5 48 | >p1 move highjumpkick 49 | >p2 move stunspore 50 | >p1 move acidarmor 51 | >p2 move amnesia 52 | >p1 move dig 53 | >p2 move growth 54 | >p1 move dig 55 | >p2 switch 3 56 | >p1 move highjumpkick 57 | >p2 move skullbash 58 | >p1 move counter 59 | >p2 move skullbash -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xA99BCE90DBE18670.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xA99BCE90DBE18670.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xAF52B504F51A337C.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xAF52B504F51A337C.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xB265471DCC2DDDC8.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[45669,18205,52269,56776]} 2 | >player p1 {"name":"Bot 1","team":"Blastoise|||None|furyattack,explosion,razorwind,guillotine||34,155,140,2,2,98|N|3,29,5,19,19,19||54|182]Onix|||None|harden,acidarmor,doubleteam,withdraw||226,95,83,116,116,84|N|10,27,17,25,25,6||65|0]Nidoran-F|||None|constrict,megadrain,smokescreen,doubleedge||140,137,97,80,80,20|N|4,12,18,4,4,1||68|120]Golduck|||None|headbutt,recover,thunder,icepunch||156,8,4,47,47,141|N|5,16,18,18,18,28||77|94]Dragonite|||None|leechseed,toxic,thunderbolt,screech||32,159,156,49,49,194|N|10,7,24,12,12,10||76|71]Bulbasaur|||None|barrier,sludge,guillotine,selfdestruct||34,227,130,137,137,110|N|0,16,28,13,13,4||68|7"} 3 | >player p2 {"name":"Bot 2","team":"Arcanine|||None|swordsdance,karatechop,watergun,minimize||117,100,210,184,184,228|N|6,9,23,8,8,15||67|249]Farfetch’d|||None|thrash,megadrain,flash,skyattack||119,218,26,137,137,211|N|14,11,18,21,21,15||67|57]Eevee|||None|doublekick,drillpeck,fissure,tailwhip||211,136,113,205,205,36|N|14,,7,21,21,11||71|6]Flareon|||None|firepunch,tackle,harden,poisonpowder||79,134,251,220,220,68|N|11,,0,23,23,27||89|0]Nidoking|||None|sonicboom,sing,solarbeam,confusion||87,86,217,143,143,2|N|8,14,8,20,20,8||72|136]Sandslash|||None|takedown,explosion,thunderpunch,psywave||223,215,46,238,238,240|N|15,6,15,3,3,||88|125"} 4 | >p1 switch 2 5 | >p2 switch 2 6 | >p1 move harden 7 | >p2 switch 2 8 | >p1 switch 2 9 | >p2 switch 3 10 | >p1 switch 3 11 | >p2 move doublekick 12 | >p1 move constrict 13 | >p2 move fissure 14 | >p1 move megadrain 15 | >p2 move drillpeck 16 | >p1 switch 4 17 | >p2 move tailwhip 18 | >p1 move headbutt 19 | >p2 move drillpeck 20 | >p1 move icepunch 21 | >p2 switch 4 22 | >p1 switch 5 23 | >p2 move harden 24 | >p1 move screech 25 | >p2 move poisonpowder 26 | >p1 move leechseed 27 | >p2 move harden 28 | >p1 move screech 29 | >p2 switch 2 30 | >p1 move toxic 31 | >p2 move skyattack 32 | >p1 move screech 33 | >p2 move skyattack 34 | >p1 move toxic 35 | >p2 move megadrain 36 | >p1 switch 6 37 | >p2 switch 2 38 | >p1 switch 3 39 | >p2 move poisonpowder 40 | >p1 move furyattack 41 | >p2 move poisonpowder 42 | >p1 move explosion 43 | >p2 move poisonpowder 44 | >p1 switch 3 45 | >p2 switch 2 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xB758AB5F9D7AD36D.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[46936,43871,40314,54125]} 2 | >player p1 {"name":"Bot 1","team":"Bulbasaur|||None|thunderpunch,rockthrow,leechlife,meditate||204,93,86,235,235,243|N|6,16,7,1,1,26||89|167]Grimer|||None|swordsdance,bite,supersonic,whirlwind||91,226,196,103,103,145|N|10,15,4,1,1,7||77|206]Kabutops|||None|amnesia,karatechop,doubleslap,hydropump||136,114,195,139,139,155|N|11,23,5,11,11,23||94|77]Nidoran-F|||None|sleeppowder,aurorabeam,hyperbeam,softboiled||42,28,220,217,217,203|N|0,24,25,9,9,8||98|91]Nidoking|||None|firepunch,bubble,metronome,sing||44,108,132,220,220,208|N|10,14,25,29,29,15||95|56]Jolteon|||None|twineedle,tackle,thunderwave,recover||70,103,129,145,145,41|N|4,4,3,1,1,24||74|251"} 3 | >player p2 {"name":"Bot 2","team":"Magneton|||None|screech,solarbeam,megadrain,rage||228,93,200,53,53,185|N|4,0,23,17,17,24||80|185]Dodrio|||None|lightscreen,thunderbolt,ember,highjumpkick||139,14,230,93,93,171|N|14,14,11,20,20,22||84|89]Lickitung|||None|waterfall,growth,superfang,transform||246,151,97,158,158,228|N|14,7,11,12,12,27||91|57]Vileplume|||None|teleport,skullbash,hyperfang,cometpunch||188,132,199,251,251,166|N|10,11,0,12,12,3||62|142]Exeggutor|||None|sludge,leechseed,strength,smog||104,33,58,167,167,12|N|1,9,24,19,19,28||60|188]Oddish|||None|confuseray,guillotine,furyswipes,psychic||187,13,237,206,206,62|N|0,4,12,29,29,9||76|123"} 4 | >p1 switch 2 5 | >p2 move screech 6 | >p1 switch 2 7 | >p2 switch 2 8 | >p1 switch 3 9 | >p2 move lightscreen 10 | >p1 move amnesia 11 | >p2 switch 2 12 | >p1 move karatechop 13 | >p2 move solarbeam 14 | >p1 move doubleslap 15 | >p2 move solarbeam 16 | >p1 move hydropump 17 | >p2 move megadrain 18 | >p1 switch 4 19 | >p1 switch 5 20 | >p2 move rage 21 | >p1 move firepunch 22 | >p2 move rage 23 | >p2 switch 3 24 | >p1 switch 6 25 | >p2 move waterfall 26 | >p1 move twineedle 27 | >p2 move growth 28 | >p1 move tackle 29 | >p2 switch 4 30 | >p1 move thunderwave 31 | >p2 switch 5 32 | >p1 move recover 33 | >p2 move sludge 34 | >p1 switch 2 35 | >p2 switch 6 36 | >p1 move swordsdance 37 | >p2 switch 2 38 | >p1 switch 2 39 | >p2 switch 4 40 | >p1 move twineedle 41 | >p2 move superfang 42 | >p1 move twineedle 43 | >p2 move transform 44 | >p1 move thunderwave 45 | >p2 move tackle 46 | >p1 move thunderwave 47 | >p2 move twineedle 48 | >p1 switch 5 49 | >p1 move sleeppowder 50 | >p2 move twineedle 51 | >p1 move aurorabeam 52 | >p2 move tackle 53 | >p1 move hyperbeam 54 | >p2 move tackle 55 | >p1 move recharge 56 | >p2 move thunderwave 57 | >p1 switch 6 58 | >p2 move recover 59 | >p1 move bubble 60 | >p2 move tackle 61 | >p1 move metronome 62 | >p2 move recover 63 | >p1 move sing 64 | >p2 move thunderwave 65 | >p1 switch 3 66 | >p2 move thunderwave 67 | >p1 switch 3 68 | >p2 switch 5 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xB9131B7324E482AD.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[47379,7027,9444,33453]} 2 | >player p1 {"name":"Bot 1","team":"Abra|||None|pinmissile,substitute,softboiled,crabhammer||143,52,149,5,5,99|N|6,5,27,24,24,14||89|50]Jigglypuff|||None|meditate,glare,flash,fireblast||215,157,209,209,209,240|N|1,8,13,27,27,5||89|179]Dugtrio|||None|poisongas,leechlife,seismictoss,skyattack||224,36,161,150,150,124|N|1,29,0,7,7,5||97|120]Rattata|||None|supersonic,hornattack,psychic,acid||241,43,244,117,117,168|N|5,20,19,10,10,0||55|244]Horsea|||None|quickattack,constrict,stunspore,toxic||142,203,154,211,211,149|N|2,13,17,5,5,23||79|254]Magikarp|||None|megapunch,conversion,bite,thunderpunch||66,158,73,2,2,24|N|6,9,26,29,29,2||73|45"} 3 | >player p2 {"name":"Bot 2","team":"Charizard|||None|defensecurl,firepunch,razorwind,disable||50,247,61,1,1,200|N|9,3,28,11,11,5||96|141]Bellsprout|||None|sonicboom,psywave,acidarmor,smokescreen||79,204,,31,31,133|N|0,1,13,8,8,12||81|179]Raichu|||None|petaldance,bonemerang,blizzard,growl||194,115,12,72,72,244|N|5,25,3,27,27,1||90|171]Nidoran-M|||None|sharpen,lick,swordsdance,megakick||85,244,43,237,237,151|N|12,26,19,9,9,1||86|125]Rapidash|||None|leechseed,poisonsting,bodyslam,doubleteam||80,165,210,210,210,85|N|3,17,21,10,10,15||86|204]Blastoise|||None|reflect,flamethrower,furyswipes,focusenergy||181,67,149,147,147,251|N|2,25,28,9,9,19||58|97"} 4 | >p1 switch 2 5 | >p2 move defensecurl 6 | >p1 move meditate 7 | >p2 move firepunch 8 | >p1 move glare 9 | >p2 move razorwind 10 | >p1 switch 2 11 | >p2 move razorwind 12 | >p1 move pinmissile 13 | >p2 move disable -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xB9A1A38FCBBF6648.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[47521,41871,52159,26184]} 2 | >player p1 {"name":"Bot 1","team":"Primeape|||None|slam,fly,teleport,thunderpunch||101,211,13,97,97,229|N|15,18,10,15,15,10||56|23]Tangela|||None|nightshade,icebeam,visegrip,psywave||54,123,175,138,138,87|N|1,16,0,23,23,16||81|205]Cloyster|||None|lovelykiss,strength,focusenergy,hydropump||210,43,93,33,33,64|N|6,1,,1,1,2||59|48]Arbok|||None|bubblebeam,confuseray,stomp,furyswipes||16,172,190,50,50,48|N|13,7,3,14,14,8||65|228]Dratini|||None|flash,withdraw,stunspore,fissure||115,216,202,22,22,167|N|11,3,29,7,7,6||55|8]Venonat|||None|dreameater,horndrill,spore,scratch||206,18,77,23,23,160|N|2,8,8,13,13,15||50|204"} 3 | >player p2 {"name":"Bot 2","team":"Mankey|||None|minimize,swift,lightscreen,sing||203,194,103,75,75,61|N|6,20,22,29,29,||82|182]Meowth|||None|fireblast,leechseed,vinewhip,hornattack||13,152,98,111,111,38|N|3,12,1,10,10,6||87|223]Poliwhirl|||None|crabhammer,thrash,disable,petaldance||126,2,12,200,200,12|N|5,28,22,27,27,1||76|194]Raticate|||None|glare,lowkick,smokescreen,highjumpkick||85,189,22,137,137,190|N|8,26,20,9,9,4||70|81]Poliwrath|||None|leechlife,lick,barrier,leer||207,101,174,234,234,42|N|8,14,9,9,9,0||69|51]Moltres|||None|bodyslam,seismictoss,splash,gust||72,166,111,61,61,50|N|3,13,17,2,2,27||69|131"} 4 | >p1 move slam 5 | >p2 move minimize 6 | >p1 move fly 7 | >p2 move swift 8 | >p1 move fly 9 | >p2 move lightscreen 10 | >p1 move teleport 11 | >p2 move sing 12 | >p1 move thunderpunch 13 | >p2 move minimize 14 | >p1 move teleport 15 | >p2 move swift 16 | >p1 switch 2 17 | >p1 move nightshade 18 | >p2 move lightscreen 19 | >p1 move icebeam 20 | >p2 move minimize 21 | >p1 switch 3 22 | >p2 move minimize 23 | >p1 move lovelykiss 24 | >p2 move minimize 25 | >p1 switch 4 26 | >p2 move swift 27 | >p1 switch 5 28 | >p2 switch 2 29 | >p1 move flash 30 | >p2 move fireblast 31 | >p1 move withdraw 32 | >p2 switch 2 33 | >p1 move stunspore 34 | >p2 move minimize 35 | >p1 move fissure 36 | >p2 move minimize 37 | >p1 switch 6 38 | >p2 move lightscreen 39 | >p1 switch 4 40 | >p2 move lightscreen 41 | >p1 move strength 42 | >p2 move minimize 43 | >p1 move focusenergy 44 | >p2 move lightscreen 45 | >p1 switch 5 46 | >p2 move swift 47 | >p1 switch 4 48 | >p2 switch 3 49 | >p1 move dreameater 50 | >p2 move crabhammer 51 | >p1 switch 3 52 | >p1 move visegrip 53 | >p2 move thrash 54 | >p1 switch 5 55 | >p2 move thrash 56 | >p1 move hydropump 57 | >p2 move thrash 58 | >p1 move lovelykiss 59 | >p2 move disable 60 | >p1 move hydropump 61 | >p2 switch 4 62 | >p1 move strength 63 | >p2 move glare 64 | >p1 move lovelykiss 65 | >p2 move lowkick -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xBABA377EE1638987.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[47802,14206,57699,35207]} 2 | >player p1 {"name":"Bot 1","team":"Golbat|||None|spikecannon,solarbeam,toxic,leechseed||234,49,195,245,245,173|N|3,24,16,30,30,7||78|147]Horsea|||None|megadrain,headbutt,razorleaf,roar||137,185,43,142,142,195|N|15,23,6,,,14||66|167]Articuno|||None|thunder,waterfall,bite,tailwhip||39,55,81,208,208,185|N|6,8,2,13,13,19||64|135]Nidoran-M|||None|rage,payday,gust,cut||132,55,48,99,99,225|N|9,10,25,11,11,20||80|154]Poliwag|||None|psybeam,sing,thrash,eggbomb||12,70,68,170,170,|N|2,24,0,8,8,6||74|203]Weepinbell|||None|dizzypunch,karatechop,hydropump,mist||53,104,184,197,197,71|N|2,13,28,9,9,18||71|90"} 3 | >player p2 {"name":"Bot 2","team":"Nidorino|||None|horndrill,hyperbeam,rockslide,doubleteam||89,58,154,220,220,1|N|3,29,9,10,10,27||52|146]Porygon|||None|swift,rockthrow,lightscreen,doublekick||197,187,38,45,45,62|N|10,,20,25,25,7||76|197]Mew|||None|absorb,lick,barrage,boneclub||202,12,127,79,79,178|N|7,4,22,14,14,||96|180]Staryu|||None|cometpunch,guillotine,rest,flash||128,89,44,234,234,163|N|15,,30,10,10,19||55|128]Eevee|||None|icebeam,leechlife,earthquake,dig||54,19,183,203,203,84|N|4,21,2,8,8,17||89|10]Golem|||None|smog,icepunch,screech,doubleslap||41,104,3,171,171,91|N|7,4,26,19,19,26||54|77"} 4 | >p1 move spikecannon 5 | >p2 move horndrill 6 | >p1 switch 2 7 | >p2 move hyperbeam 8 | >p1 switch 2 9 | >p2 move recharge 10 | >p1 move solarbeam 11 | >p2 switch 2 12 | >p1 move solarbeam 13 | >p2 move swift 14 | >p1 move toxic 15 | >p2 switch 2 16 | >p1 move leechseed 17 | >p2 move rockslide 18 | >p1 switch 3 19 | >p2 switch 3 20 | >p1 switch 4 21 | >p2 move absorb 22 | >p1 move rage 23 | >p2 switch 4 24 | >p1 move rage 25 | >p2 switch 5 26 | >p1 move rage 27 | >p2 switch 6 28 | >p1 move rage 29 | >p2 move smog 30 | >p1 move rage 31 | >p2 switch 6 32 | >p1 move rage 33 | >p2 switch 6 34 | >p1 move rage 35 | >p2 move smog 36 | >p1 move rage 37 | >p2 move smog 38 | >p1 move rage 39 | >p2 move smog 40 | >p1 move rage 41 | >p2 move icepunch 42 | >p1 move rage 43 | >p2 move smog 44 | >p1 move rage 45 | >p2 move doubleslap 46 | >p1 move rage 47 | >p2 move smog 48 | >p1 move rage 49 | >p2 move icepunch 50 | >p1 move rage 51 | >p2 move doubleslap 52 | >p1 move rage 53 | >p2 move screech 54 | >p1 move rage 55 | >p2 move smog 56 | >p2 switch 3 57 | >p1 move rage 58 | >p2 switch 2 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xBB75F6633DBA4C08.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[47989,63075,15802,19464]} 2 | >player p1 {"name":"Bot 1","team":"Kabuto|||None|blizzard,sludge,lowkick,tailwhip||237,66,170,170,170,168|N|14,11,10,13,13,10||66|107]Dratini|||None|vinewhip,strength,rage,doubleslap||218,21,234,163,163,250|N|2,29,4,21,21,10||71|36]Mewtwo|||None|spikecannon,amnesia,smokescreen,watergun||47,64,82,104,104,220|N|12,15,,5,5,0||79|56]Seaking|||None|visegrip,rollingkick,dig,fissure||110,55,32,215,215,236|N|9,6,4,,,21||62|37]Tentacruel|||None|highjumpkick,peck,sing,waterfall||105,74,75,218,218,58|N|0,20,4,25,25,25||68|183]Omanyte|||None|lightscreen,sonicboom,triattack,cut||248,103,38,230,230,156|N|0,25,5,28,28,5||93|169"} 3 | >player p2 {"name":"Bot 2","team":"Nidoking|||None|disable,growth,rockthrow,karatechop||233,132,50,189,189,17|N|15,2,11,2,2,7||98|26]Vaporeon|||None|teleport,bubble,furyswipes,conversion||124,29,97,224,224,56|N|3,13,13,7,7,14||91|37]Magmar|||None|swordsdance,fireblast,bonemerang,thrash||138,111,222,200,200,113|N|3,20,24,10,10,6||60|171]Slowpoke|||None|dragonrage,razorleaf,thunder,supersonic||59,52,42,249,249,36|N|8,30,29,24,24,8||58|126]Raticate|||None|quickattack,boneclub,constrict,slam||207,87,143,104,104,237|N|3,0,4,23,23,3||65|89]Nidorino|||None|slash,barrier,psywave,confuseray||59,83,117,30,30,228|N|10,26,24,28,28,11||96|39"} 4 | >p1 switch 2 5 | >p2 switch 2 6 | >p1 move vinewhip 7 | >p2 move teleport 8 | >p1 move strength 9 | >p2 switch 2 10 | >p1 switch 2 11 | >p2 move disable 12 | >p1 switch 3 13 | >p2 move growth 14 | >p1 move spikecannon 15 | >p2 move rockthrow 16 | >p1 switch 4 17 | >p2 switch 3 18 | >p1 switch 5 19 | >p2 move swordsdance 20 | >p1 switch 6 21 | >p2 switch 4 22 | >p1 switch 4 23 | >p2 move dragonrage 24 | >p1 move amnesia 25 | >p2 move razorleaf 26 | >p1 switch 6 27 | >p2 move thunder 28 | >p1 move highjumpkick 29 | >p2 move supersonic 30 | >p1 move peck 31 | >p2 move razorleaf 32 | >p1 move sing 33 | >p2 move dragonrage 34 | >p1 move waterfall 35 | >p2 move supersonic 36 | >p1 move peck 37 | >p2 move supersonic 38 | >p1 move highjumpkick 39 | >p2 move razorleaf 40 | >p2 switch 5 41 | >p1 move waterfall 42 | >p2 move quickattack 43 | >p1 move peck 44 | >p2 move boneclub 45 | >p1 switch 6 46 | >p1 move smokescreen 47 | >p2 move constrict 48 | >p1 move watergun 49 | >p2 move slam 50 | >p2 switch 6 51 | >p1 switch 2 52 | >p2 move slash 53 | >p1 move rage 54 | >p2 move barrier 55 | >p1 move rage 56 | >p2 move psywave -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xBC867937B5A262F8.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[48262,31031,46498,25336]} 2 | >player p1 {"name":"Bot 1","team":"Kakuna|||None|firepunch,bubble,sludge,thrash||122,225,222,2,2,178|N|3,4,9,3,3,||57|189]Bellsprout|||None|leechseed,rest,megapunch,focusenergy||74,219,77,78,78,160|N|13,10,15,30,30,8||73|111]Paras|||None|leer,stunspore,dig,petaldance||97,40,79,159,159,112|N|2,16,21,0,0,10||73|247]Magikarp|||None|screech,leechlife,spikecannon,acid||164,31,15,198,198,124|N|3,21,12,22,22,22||88|136]Psyduck|||None|fireblast,blizzard,watergun,psybeam||25,47,190,236,236,143|N|11,10,0,27,27,||68|60]Dodrio|||None|bodyslam,triattack,rest,megapunch||116,156,172,182,182,106|N|2,1,1,24,24,10||79|240"} 3 | >player p2 {"name":"Bot 2","team":"Victreebel|||None|thunder,mist,confusion,eggbomb||76,99,206,4,4,24|N|0,9,13,16,16,17||53|152]Nidoking|||None|sonicboom,aurorabeam,softboiled,flamethrower||120,119,63,203,203,112|N|14,,6,25,25,30||89|55]Farfetch’d|||None|earthquake,dreameater,quickattack,furyswipes||192,212,156,103,103,215|N|1,8,20,27,27,13||54|130]Chansey|||None|barrage,sleeppowder,lowkick,selfdestruct||70,88,153,90,90,86|N|14,6,30,21,21,7||90|84]Kangaskhan|||None|doubleteam,leechseed,growl,doubleslap||24,34,99,68,68,231|N|12,23,10,20,20,1||54|216]Dragonite|||None|cometpunch,seismictoss,bubblebeam,razorwind||205,27,206,168,168,103|N|6,12,3,8,8,23||79|44"} 4 | >p1 switch 2 5 | >p2 move mist 6 | >p1 move leechseed 7 | >p2 move eggbomb 8 | >p1 move rest 9 | >p2 move eggbomb 10 | >p1 move megapunch 11 | >p2 move thunder 12 | >p1 move megapunch 13 | >p2 move thunder 14 | >p1 switch 2 15 | >p2 switch 2 16 | >p1 move firepunch 17 | >p2 move softboiled 18 | >p1 move bubble 19 | >p2 switch 2 20 | >p1 move sludge 21 | >p2 switch 3 22 | >p1 move thrash 23 | >p2 switch 4 24 | >p1 move thrash 25 | >p2 move lowkick 26 | >p1 move thrash 27 | >p2 move selfdestruct 28 | >p2 switch 5 29 | >p1 move thrash 30 | >p2 move leechseed 31 | >p1 move bubble 32 | >p2 move growl -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xBCC4F5F803A4C0C5.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[48324,62968,932,49349]} 2 | >player p1 {"name":"Bot 1","team":"Parasect|||None|reflect,confusion,bide,supersonic||215,90,165,76,76,15|N|6,21,7,9,9,10||53|225]Jolteon|||None|wrap,tailwhip,thunderpunch,hornattack||217,32,44,49,49,183|N|4,21,18,0,0,17||60|127]Koffing|||None|teleport,defensecurl,splash,stunspore||34,171,67,106,106,53|N|6,0,3,9,9,2||82|113]Machamp|||None|constrict,dizzypunch,lightscreen,dreameater||143,165,206,159,159,10|N|9,11,20,11,11,28||99|204]Pidgeot|||None|psywave,hypnosis,conversion,acidarmor||9,197,215,39,39,103|N|8,23,29,20,20,24||58|55]Raticate|||None|firespin,explosion,lick,flamethrower||121,131,57,2,2,45|N|3,13,21,18,18,23||65|146"} 3 | >player p2 {"name":"Bot 2","team":"Bellsprout|||None|mimic,surf,lovelykiss,solarbeam||112,34,78,250,250,199|N|11,3,1,11,11,30||88|190]Pidgeotto|||None|rage,metronome,ember,doubleteam||102,125,76,198,198,30|N|9,26,24,6,6,28||53|113]Electabuzz|||None|confuseray,bodyslam,poisongas,icebeam||60,33,200,5,5,200|N|11,15,9,10,10,23||96|215]Hitmonlee|||None|twineedle,swordsdance,rest,sludge||78,13,99,165,165,78|N|5,5,15,26,26,0||86|136]Blastoise|||None|screech,rockslide,dig,scratch||18,148,40,11,11,20|N|13,14,,6,6,25||83|249]Arbok|||None|doubleedge,sonicboom,leer,rockslide||234,10,137,191,191,35|N|13,2,3,7,7,24||74|22"} 4 | >p1 move reflect 5 | >p2 switch 2 6 | >p1 move confusion 7 | >p2 move rage 8 | >p1 switch 2 9 | >p2 move rage 10 | >p1 move wrap 11 | >p2 move rage 12 | >p1 move wrap 13 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xC1F3A1A3CBF66E2B.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[49651,41379,52214,28203]} 2 | >player p1 {"name":"Bot 1","team":"Pidgeotto|||None|bite,tailwhip,reflect,icebeam||86,160,146,128,128,68|N|10,22,24,9,9,19||93|56]Clefairy|||None|firepunch,doublekick,psybeam,amnesia||14,57,218,148,148,82|N|8,26,20,24,24,12||86|251]Beedrill|||None|whirlwind,furyswipes,megapunch,razorleaf||206,234,25,51,51,2|N|3,25,24,22,22,10||78|73]Vileplume|||None|conversion,doubleslap,barrier,rest||126,115,202,100,100,70|N|7,13,23,18,18,23||84|181]Cubone|||None|megakick,leechlife,rage,stomp||201,26,189,242,242,34|N|0,5,8,13,13,21||52|149]Raichu|||None|hornattack,earthquake,swift,splash||151,171,54,59,59,13|N|11,26,8,26,26,14||96|246"} 3 | >player p2 {"name":"Bot 2","team":"Weezing|||None|seismictoss,solarbeam,kinesis,ember||173,215,163,196,196,112|N|0,20,0,13,13,8||66|13]Charmander|||None|swordsdance,recover,peck,thundershock||189,206,197,246,246,115|N|0,21,9,25,25,0||84|5]Drowzee|||None|vinewhip,doubleteam,bonemerang,focusenergy||112,184,81,65,65,113|N|10,15,16,13,13,3||82|165]Kadabra|||None|poisonsting,screech,bide,icepunch||229,63,16,175,175,2|N|1,25,17,6,6,29||87|155]Machop|||None|fly,selfdestruct,blizzard,pound||195,,127,56,56,152|N|3,20,4,,,3||58|225]Slowpoke|||None|skullbash,acidarmor,dig,disable||32,31,3,124,124,86|N|7,28,14,27,27,23||69|18"} 4 | >p1 move bite 5 | >p2 move seismictoss 6 | >p1 move tailwhip 7 | >p2 move solarbeam 8 | >p1 move reflect 9 | >p2 move solarbeam 10 | >p1 move icebeam 11 | >p2 move kinesis 12 | >p2 switch 4 13 | >p1 switch 2 14 | >p2 move poisonsting 15 | >p1 move firepunch 16 | >p2 move screech 17 | >p1 move doublekick 18 | >p2 move bide 19 | >p1 move psybeam 20 | >p2 move bide 21 | >p1 move amnesia 22 | >p2 move bide 23 | >p1 move psybeam 24 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xC40D2C12D0F8185D.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[50189,11282,53496,6237]} 2 | >player p1 {"name":"Bot 1","team":"Kangaskhan|||None|surf,fireblast,guillotine,absorb||159,149,170,95,95,55|N|8,7,5,21,21,9||82|42]Alakazam|||None|substitute,teleport,mist,megapunch||66,129,38,128,128,202|N|12,30,2,29,29,17||85|139]Koffing|||None|softboiled,stringshot,splash,spikecannon||181,160,218,184,184,68|N|1,24,13,11,11,5||93|68]Drowzee|||None|doubleedge,crabhammer,submission,dragonrage||219,159,58,104,104,53|N|12,,15,8,8,4||90|28]Poliwhirl|||None|dig,bodyslam,psybeam,swordsdance||212,93,239,67,67,157|N|0,16,8,24,24,0||89|108]Exeggcute|||None|karatechop,doublekick,bubble,sandattack||43,152,124,147,147,143|N|6,8,6,8,8,7||66|209"} 3 | >player p2 {"name":"Bot 2","team":"Venusaur|||None|megadrain,screech,payday,earthquake||169,219,250,222,222,90|N|8,14,1,16,16,28||96|173]Raichu|||None|takedown,thrash,seismictoss,razorwind||193,80,107,91,91,80|N|13,19,10,3,3,17||70|229]Squirtle|||None|whirlwind,scratch,flamethrower,withdraw||80,76,123,132,132,31|N|12,,30,12,12,16||57|37]Charmeleon|||None|megakick,gust,fissure,sharpen||78,136,222,91,91,4|N|7,9,27,11,11,14||91|35]Pidgeotto|||None|leechseed,skyattack,psychic,defensecurl||20,35,100,197,197,135|N|12,2,10,13,13,12||55|236]Machamp|||None|constrict,focusenergy,icepunch,glare||74,67,221,170,170,213|N|0,9,4,17,17,21||64|162"} 4 | >p1 move surf 5 | >p2 switch 2 6 | >p1 switch 2 7 | >p2 move takedown 8 | >p1 move substitute 9 | >p2 switch 2 10 | >p1 move teleport 11 | >p2 move megadrain 12 | >p1 move mist 13 | >p2 move screech -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xC468FF6E1CEE314D.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xC468FF6E1CEE314D.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xC8524A847B4AF353.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[51282,19076,31562,62291]} 2 | >player p1 {"name":"Bot 1","team":"Rhydon|||None|smokescreen,firepunch,boneclub,doublekick||110,186,29,86,86,51|N|5,16,30,,,5||99|80]Fearow|||None|sleeppowder,tackle,thunderbolt,bide||46,90,200,175,175,180|N|1,12,21,30,30,20||90|93]Omanyte|||None|surf,cometpunch,selfdestruct,submission||50,172,207,36,36,225|N|1,29,1,2,2,17||78|46]Zapdos|||None|absorb,twineedle,recover,drillpeck||197,17,22,196,196,245|N|8,26,16,20,20,16||87|228]Magnemite|||None|thunderpunch,reflect,dizzypunch,wingattack||54,93,52,203,203,143|N|15,,2,7,7,27||55|63]Cubone|||None|guillotine,quickattack,slash,barrier||64,57,176,36,36,39|N|15,7,,30,30,15||81|60"} 3 | >player p2 {"name":"Bot 2","team":"Arcanine|||None|focusenergy,acid,lick,slam||107,23,159,250,250,214|N|0,8,25,24,24,8||91|89]Koffing|||None|sharpen,fissure,bonemerang,furyattack||194,122,39,137,137,164|N|8,,9,17,17,0||95|243]Magikarp|||None|aurorabeam,triattack,sludge,visegrip||126,86,122,170,170,135|N|0,16,21,29,29,8||84|108]Raticate|||None|pound,substitute,fireblast,kinesis||33,84,158,251,251,129|N|2,5,24,0,0,19||60|14]Weedle|||None|confusion,gust,roar,thrash||91,26,24,72,72,150|N|15,30,,,,||62|49]Tentacool|||None|swift,megadrain,cut,flamethrower||98,30,5,51,51,126|N|1,0,29,18,18,25||72|62"} 4 | >p1 move smokescreen 5 | >p2 move focusenergy 6 | >p1 move firepunch 7 | >p2 switch 2 8 | >p1 move boneclub 9 | >p2 move sharpen 10 | >p2 switch 2 11 | >p1 move doublekick 12 | >p2 move acid 13 | >p1 move firepunch 14 | >p2 move lick 15 | >p1 switch 2 16 | >p2 switch 3 17 | >p1 move sleeppowder 18 | >p2 move aurorabeam 19 | >p1 move tackle 20 | >p2 move triattack 21 | >p1 move thunderbolt 22 | >p2 move sludge 23 | >p2 switch 4 24 | >p1 move bide 25 | >p2 move pound 26 | >p1 move bide 27 | >p2 switch 5 28 | >p1 move bide 29 | >p2 move confusion -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xCA20018840CC123.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xCA20018840CC123.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xCC64741157FC11DB.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xCC64741157FC11DB.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xCDE87ADE2DEA69C.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[3294,34733,58078,42652]} 2 | >player p1 {"name":"Bot 1","team":"Ninetales|||None|growl,gust,conversion,nightshade||9,192,160,180,180,190|N|5,16,3,27,27,16||83|54]Pikachu|||None|megadrain,bide,rage,spikecannon||231,193,54,182,182,45|N|2,16,16,24,24,19||82|138]Slowpoke|||None|selfdestruct,thunderwave,thundershock,bind||227,108,140,46,46,53|N|10,23,8,0,0,14||70|0]Diglett|||None|barrier,bodyslam,recover,thunder||135,8,188,218,218,126|N|6,1,6,13,13,22||55|194]Dodrio|||None|whirlwind,kinesis,hyperfang,megakick||178,188,74,34,34,110|N|11,30,24,27,27,6||83|217]Kabuto|||None|pound,glare,superfang,poisonpowder||105,86,58,127,127,245|N|13,,22,26,26,24||81|26"} 3 | >player p2 {"name":"Bot 2","team":"Lapras|||None|roar,poisonsting,triattack,rockslide||91,187,177,157,157,187|N|12,15,19,0,0,8||91|59]Hitmonlee|||None|teleport,furyattack,payday,sludge||30,178,51,206,206,168|N|9,7,12,14,14,9||94|236]Kakuna|||None|softboiled,icepunch,withdraw,acid||165,42,149,124,124,232|N|15,19,2,15,15,23||65|254]Metapod|||None|ember,substitute,meditate,sleeppowder||53,210,33,213,213,15|N|11,19,29,30,30,7||81|237]Mew|||None|lightscreen,solarbeam,rockthrow,doublekick||54,201,48,163,163,4|N|8,22,17,28,28,12||72|20]Koffing|||None|leechseed,wrap,counter,splash||54,116,4,54,54,82|N|1,28,20,22,22,4||65|180"} 4 | >p1 move growl 5 | >p2 switch 2 6 | >p1 move gust 7 | >p2 move teleport 8 | >p1 move conversion 9 | >p2 move furyattack 10 | >p1 move nightshade 11 | >p2 move payday 12 | >p1 switch 2 13 | >p2 switch 2 14 | >p1 move megadrain 15 | >p2 switch 3 16 | >p1 move bide 17 | >p2 switch 4 18 | >p1 switch 2 19 | >p2 move ember 20 | >p1 switch 3 21 | >p2 move substitute 22 | >p1 move selfdestruct 23 | >p2 move meditate 24 | >p1 switch 4 25 | >p2 move sleeppowder 26 | >p1 switch 5 27 | >p2 switch 5 28 | >p1 move whirlwind 29 | >p2 move lightscreen 30 | >p1 switch 6 31 | >p2 move solarbeam 32 | >p1 switch 5 33 | >p2 move solarbeam 34 | >p1 switch 3 35 | >p1 switch 4 36 | >p2 move rockthrow 37 | >p1 move thunderwave 38 | >p2 move doublekick 39 | >p1 switch 4 40 | >p2 move rockthrow 41 | >p1 switch 5 42 | >p2 move solarbeam 43 | >p1 move pound 44 | >p2 move solarbeam 45 | >p1 move glare 46 | >p2 move solarbeam 47 | >p1 move superfang 48 | >p2 move rockthrow 49 | >p1 move poisonpowder 50 | >p2 move solarbeam 51 | >p1 move superfang 52 | >p2 move solarbeam 53 | >p1 switch 5 54 | >p2 switch 6 55 | >p1 move gust 56 | >p2 move leechseed 57 | >p1 move conversion 58 | >p2 move wrap 59 | >p1 move growl 60 | >p2 move wrap -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xCE3086F839722570.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[52784,34552,14706,9584]} 2 | >player p1 {"name":"Bot 1","team":"Mewtwo|||None|furyswipes,stomp,cometpunch,blizzard||43,151,139,35,35,116|N|12,6,30,1,1,21||55|219]Charizard|||None|doubleslap,sandattack,razorwind,fissure||85,192,123,26,26,238|N|0,29,25,12,12,29||62|180]Sandslash|||None|cometpunch,megadrain,conversion,lightscreen||70,63,242,186,186,29|N|4,9,23,8,8,17||54|230]Omanyte|||None|focusenergy,haze,absorb,bubblebeam||58,9,135,114,114,152|N|0,16,12,4,4,20||53|138]Articuno|||None|splash,fly,firepunch,stunspore||62,25,230,175,175,237|N|5,1,7,27,27,21||99|167]Eevee|||None|fireblast,swift,hypnosis,rockslide||37,188,151,192,192,207|N|3,29,20,2,2,7||50|223"} 3 | >player p2 {"name":"Bot 2","team":"Bellsprout|||None|bubble,hydropump,drillpeck,ember||225,252,25,35,35,60|N|12,7,2,12,12,16||72|251]Machoke|||None|swordsdance,softboiled,lowkick,leechseed||87,234,205,193,193,185|N|10,,24,13,13,19||61|12]Snorlax|||None|triattack,selfdestruct,icepunch,pound||41,244,185,69,69,146|N|11,11,4,6,6,11||79|9]Tentacool|||None|rockthrow,furyswipes,acid,confusion||44,202,23,9,9,179|N|8,2,24,9,9,4||72|113]Dugtrio|||None|hyperfang,leer,twineedle,toxic||84,91,199,100,100,15|N|7,13,22,18,18,2||95|233]Spearow|||None|jumpkick,hyperbeam,sonicboom,barrage||103,91,52,128,128,74|N|14,14,2,13,13,27||93|165"} 4 | >p1 move furyswipes 5 | >p2 move ember 6 | >p1 move stomp 7 | >p2 switch 2 8 | >p1 move cometpunch 9 | >p2 switch 2 10 | >p1 switch 2 11 | >p2 switch 3 12 | >p1 switch 2 13 | >p2 move selfdestruct 14 | >p1 switch 3 15 | >p2 switch 4 16 | >p1 move conversion 17 | >p2 move rockthrow 18 | >p1 move cometpunch 19 | >p2 move acid 20 | >p1 move cometpunch 21 | >p2 switch 5 22 | >p1 move lightscreen 23 | >p2 move twineedle 24 | >p1 switch 4 25 | >p1 move focusenergy 26 | >p2 move hyperfang 27 | >p1 move absorb 28 | >p2 switch 6 29 | >p1 switch 5 30 | >p2 move sonicboom 31 | >p1 switch 6 32 | >p2 move jumpkick 33 | >p1 switch 6 34 | >p1 move fly 35 | >p2 move sonicboom 36 | >p1 move fly 37 | >p2 move hyperbeam 38 | >p2 switch 6 39 | >p1 move splash 40 | >p2 move toxic 41 | >p1 switch 2 42 | >p2 move twineedle 43 | >p1 move fissure 44 | >p2 move hyperfang 45 | >p1 switch 2 46 | >p2 switch 2 47 | >p1 switch 5 48 | >p2 switch 2 49 | >p1 switch 5 50 | >p2 move hyperfang 51 | >p1 move fly 52 | >p2 move leer 53 | >p1 move fly 54 | >p2 move toxic 55 | >p1 move firepunch 56 | >p2 switch 5 57 | >p1 switch 5 58 | >p2 switch 5 59 | >p1 move focusenergy 60 | >p2 move toxic 61 | >p1 move haze 62 | >p2 switch 5 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xCE87A7774C1AAB24.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[52871,42871,19482,43812]} 2 | >player p1 {"name":"Bot 1","team":"Poliwhirl|||None|disable,nightshade,thunderpunch,waterfall||3,43,70,20,20,243|N|5,17,3,3,3,13||75|118]Bulbasaur|||None|poisonsting,hyperbeam,rest,tackle||18,153,166,250,250,58|N|11,2,12,19,19,15||55|26]Chansey|||None|screech,doubleslap,earthquake,rockslide||128,215,120,83,83,|N|11,26,5,27,27,15||80|222]Wartortle|||None|quickattack,thrash,smokescreen,explosion||81,97,244,241,241,21|N|11,11,16,6,6,26||81|222]Mankey|||None|aurorabeam,pound,supersonic,sing||244,35,66,117,117,27|N|6,1,14,4,4,2||74|210]Electrode|||None|guillotine,whirlwind,vinewhip,leechlife||204,86,130,5,5,108|N|9,22,21,15,15,8||71|134"} 3 | >player p2 {"name":"Bot 2","team":"Ekans|||None|defensecurl,doublekick,glare,hypnosis||155,9,111,8,8,166|N|8,6,13,21,21,17||52|179]Oddish|||None|petaldance,smog,flamethrower,dig||13,171,213,167,167,197|N|3,13,13,2,2,2||55|156]Magnemite|||None|swift,psybeam,thunderwave,swordsdance||153,101,206,48,48,164|N|4,1,3,16,16,0||61|167]Pinsir|||None|bide,rollingkick,surf,payday||246,1,238,61,61,54|N|9,7,5,19,19,1||97|75]Magikarp|||None|dizzypunch,haze,sleeppowder,eggbomb||132,164,180,14,14,69|N|9,18,8,14,14,29||97|128]Haunter|||None|recover,reflect,icebeam,teleport||230,158,229,69,69,100|N|0,17,5,9,9,13||85|156"} 4 | >p1 switch 2 5 | >p2 move defensecurl 6 | >p1 move poisonsting 7 | >p2 switch 2 8 | >p1 move hyperbeam 9 | >p2 move petaldance 10 | >p1 move recharge 11 | >p2 move petaldance 12 | >p1 move rest 13 | >p2 move petaldance 14 | >p1 move tackle 15 | >p2 move smog 16 | >p1 switch 2 17 | >p2 switch 2 18 | >p1 move disable 19 | >p2 switch 3 20 | >p1 move nightshade 21 | >p2 switch 4 22 | >p1 move thunderpunch 23 | >p2 switch 6 24 | >p1 switch 3 25 | >p2 move recover 26 | >p1 switch 4 27 | >p2 switch 6 28 | >p1 move quickattack 29 | >p2 move bide 30 | >p1 move thrash 31 | >p2 move bide 32 | >p1 move thrash 33 | >p2 move bide -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xCF83C12D71CE716D.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xCF83C12D71CE716D.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xD2B1817739AAF4B3.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[53937,33143,14762,62643]} 2 | >player p1 {"name":"Bot 1","team":"Mew|||None|softboiled,acidarmor,doubleslap,swordsdance||25,152,181,248,248,86|N|12,19,2,28,28,12||64|182]Nidorina|||None|headbutt,roar,blizzard,tackle||42,251,54,217,217,39|N|4,20,,20,20,24||75|205]Mankey|||None|splash,boneclub,icepunch,furyattack||108,34,158,226,226,33|N|4,8,3,25,25,9||88|249]Vileplume|||None|toxic,gust,poisonpowder,haze||192,68,170,199,199,144|N|8,22,25,8,8,5||72|153]Eevee|||None|thunderpunch,sleeppowder,rollingkick,jumpkick||163,197,21,137,137,210|N|4,25,11,12,12,29||99|184]Primeape|||None|ember,rest,razorleaf,pinmissile||171,52,24,188,188,45|N|9,10,16,7,7,24||69|53"} 3 | >player p2 {"name":"Bot 2","team":"Kakuna|||None|psybeam,eggbomb,supersonic,swordsdance||165,104,76,247,247,151|N|7,8,23,10,10,18||81|61]Dratini|||None|focusenergy,skyattack,minimize,lowkick||71,67,164,131,131,224|N|6,25,14,1,1,22||73|86]Exeggcute|||None|doubleteam,growth,barrier,meditate||206,112,241,15,15,204|N|12,,18,1,1,25||77|81]Clefairy|||None|bubblebeam,flash,tailwhip,thunderbolt||142,145,21,220,220,8|N|0,20,21,28,28,0||81|146]Abra|||None|sleeppowder,hydropump,sludge,constrict||230,231,222,166,166,116|N|6,8,6,0,0,7||60|123]Poliwhirl|||None|harden,bite,lightscreen,psywave||249,198,48,251,251,14|N|6,16,27,16,16,19||89|57"} 4 | >p1 move softboiled 5 | >p2 switch 2 6 | >p1 move acidarmor 7 | >p2 switch 2 8 | >p1 switch 2 9 | >p2 move swordsdance 10 | >p1 switch 2 11 | >p2 switch 3 12 | >p1 switch 3 13 | >p2 switch 4 14 | >p1 move splash 15 | >p2 move bubblebeam 16 | >p1 move boneclub 17 | >p2 move flash 18 | >p1 move icepunch 19 | >p2 switch 5 20 | >p1 move furyattack 21 | >p2 move sleeppowder 22 | >p1 move furyattack 23 | >p2 switch 6 24 | >p1 move icepunch 25 | >p2 move lightscreen 26 | >p1 move furyattack 27 | >p2 move lightscreen 28 | >p1 move furyattack 29 | >p2 move psywave 30 | >p1 move boneclub 31 | >p2 move psywave 32 | >p1 switch 4 33 | >p2 move lightscreen 34 | >p1 move toxic 35 | >p2 move bite 36 | >p1 move gust 37 | >p2 move lightscreen 38 | >p1 move poisonpowder 39 | >p2 move bite 40 | >p1 move haze 41 | >p2 move psywave -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xD463BA4C49D333F3.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[54371,47692,18899,13299]} 2 | >player p1 {"name":"Bot 1","team":"Flareon|||None|skullbash,strength,pinmissile,visegrip||147,171,179,73,73,2|N|12,3,27,29,29,17||99|217]Golduck|||None|nightshade,sonicboom,thunderwave,quickattack||235,8,176,12,12,45|N|3,29,8,10,10,27||86|113]Dratini|||None|jumpkick,substitute,twineedle,softboiled||204,175,172,123,123,34|N|8,3,12,0,0,29||99|120]Clefairy|||None|swordsdance,fireblast,triattack,thunderpunch||30,229,206,15,15,230|N|14,10,2,5,5,11||59|204]Sandshrew|||None|substitute,amnesia,bide,earthquake||189,80,156,132,132,193|N|12,26,23,9,9,25||74|10]Tauros|||None|megapunch,guillotine,spore,furyswipes||195,135,126,63,63,228|N|9,11,5,6,6,17||90|253"} 3 | >player p2 {"name":"Bot 2","team":"Tangela|||None|wrap,ember,vinewhip,razorwind||106,62,90,100,100,177|N|9,23,25,19,19,12||76|39]Slowpoke|||None|fly,doubleslap,flash,psychic||231,226,118,108,108,90|N|13,3,7,3,3,21||82|188]Jynx|||None|blizzard,bubble,hyperfang,teleport||110,85,79,9,9,228|N|11,30,28,,,26||74|199]Lickitung|||None|softboiled,stringshot,scratch,skyattack||170,21,57,231,231,111|N|0,4,17,20,20,13||60|50]Venonat|||None|tailwhip,recover,eggbomb,surf||10,124,78,177,177,250|N|14,23,26,13,13,14||55|71]Gastly|||None|horndrill,pound,haze,swift||130,189,77,237,237,140|N|4,28,6,12,12,1||99|87"} 4 | >p1 switch 2 5 | >p2 move razorwind 6 | >p1 move nightshade 7 | >p2 move razorwind 8 | >p1 move sonicboom 9 | >p2 switch 2 10 | >p1 switch 2 11 | >p2 move psychic 12 | >p1 move skullbash 13 | >p2 switch 2 14 | >p1 move skullbash 15 | >p2 switch 3 16 | >p2 switch 4 17 | >p1 move strength 18 | >p2 move softboiled 19 | >p1 move pinmissile 20 | >p2 move stringshot 21 | >p2 switch 5 22 | >p1 move visegrip 23 | >p2 move eggbomb 24 | >p2 switch 6 25 | >p1 switch 3 26 | >p2 move swift 27 | >p1 switch 4 28 | >p2 move pound 29 | >p1 switch 5 30 | >p2 move swift 31 | >p1 switch 6 32 | >p2 move swift 33 | >p1 switch 6 34 | >p2 move swift 35 | >p1 move substitute 36 | >p2 move swift 37 | >p1 move substitute 38 | >p2 move swift 39 | >p1 move bide 40 | >p2 move haze 41 | >p1 move bide 42 | >p2 move horndrill 43 | >p1 move bide 44 | >p2 move haze 45 | >p1 move bide 46 | >p2 move pound -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xDAF1C0765173FF0F.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[56049,49270,20851,65295]} 2 | >player p1 {"name":"Bot 1","team":"Persian|||None|defensecurl,guillotine,strength,selfdestruct||85,233,240,216,216,169|N|14,23,27,21,21,11||74|132]Dewgong|||None|crabhammer,nightshade,reflect,rest||106,70,142,239,239,232|N|8,3,25,28,28,1||73|33]Paras|||None|sing,smokescreen,hydropump,pinmissile||213,183,225,42,42,152|N|9,26,8,11,11,0||81|120]Zapdos|||None|surf,psychic,furyattack,swift||156,4,69,61,61,119|N|1,25,24,15,15,12||68|124]Squirtle|||None|thundershock,horndrill,megapunch,fly||205,241,74,215,215,152|N|12,7,30,5,5,4||80|41]Vileplume|||None|teleport,rollingkick,confuseray,submission||16,189,43,127,127,44|N|6,4,7,20,20,7||55|170"} 3 | >player p2 {"name":"Bot 2","team":"Jolteon|||None|skullbash,flamethrower,waterfall,amnesia||128,12,249,169,169,14|N|13,,23,18,18,16||71|249]Dodrio|||None|rockslide,scratch,stringshot,blizzard||236,139,95,25,25,4|N|9,22,9,19,19,1||51|98]Mewtwo|||None|solarbeam,withdraw,thunderwave,barrage||126,19,195,42,42,157|N|6,20,10,28,28,10||81|168]Pidgeotto|||None|cometpunch,thrash,firepunch,seismictoss||33,11,147,31,31,170|N|15,6,7,19,19,2||80|88]Drowzee|||None|thunderbolt,psybeam,lick,bubblebeam||127,235,93,7,7,231|N|2,8,16,1,1,10||60|233]Slowbro|||None|furyswipes,confusion,karatechop,peck||151,230,204,98,98,23|N|12,27,,8,8,24||80|20"} 4 | >p1 switch 2 5 | >p2 switch 2 6 | >p1 move crabhammer 7 | >p2 switch 2 8 | >p1 move nightshade 9 | >p2 move skullbash 10 | >p2 switch 3 11 | >p1 switch 2 12 | >p2 move solarbeam 13 | >p1 switch 3 14 | >p2 move solarbeam 15 | >p1 switch 4 16 | >p2 move withdraw 17 | >p1 switch 5 18 | >p2 switch 4 19 | >p1 move thundershock 20 | >p2 move cometpunch 21 | >p1 switch 6 22 | >p2 move thrash 23 | >p1 switch 4 24 | >p2 move thrash 25 | >p1 move sing 26 | >p2 move thrash 27 | >p1 move smokescreen 28 | >p2 move thrash 29 | >p1 move hydropump 30 | >p2 move thrash 31 | >p1 move pinmissile 32 | >p2 move thrash 33 | >p1 switch 2 34 | >p2 move thrash 35 | >p1 move reflect 36 | >p2 move thrash 37 | >p1 move rest 38 | >p2 move thrash 39 | >p1 move reflect 40 | >p2 move firepunch 41 | >p1 move crabhammer 42 | >p2 move seismictoss 43 | >p2 switch 5 44 | >p1 move rest 45 | >p2 move thunderbolt 46 | >p1 switch 4 47 | >p2 move psybeam 48 | >p1 switch 4 49 | >p1 move rest 50 | >p2 switch 6 51 | >p1 switch 5 52 | >p2 move furyswipes 53 | >p1 move surf 54 | >p2 move confusion 55 | >p1 move psychic 56 | >p2 switch 4 57 | >p1 move furyattack 58 | >p2 move thunderwave 59 | >p1 switch 2 60 | >p2 move barrage 61 | >p1 move pinmissile 62 | >p2 move thunderwave 63 | >p1 move smokescreen 64 | >p2 move thunderwave 65 | >p1 move hydropump 66 | >p2 move barrage 67 | >p1 move hydropump 68 | >p2 move thunderwave 69 | >p1 move pinmissile 70 | >p2 switch 4 71 | >p1 switch 3 72 | >p2 switch 2 73 | >p1 move defensecurl 74 | >p2 move rockslide 75 | >p1 move guillotine 76 | >p2 switch 2 77 | >p2 switch 2 78 | >p1 switch 3 79 | >p2 move scratch 80 | >p1 switch 6 81 | >p1 move horndrill 82 | >p2 move stringshot -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xE1C1F3089C963B91.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[57793,62216,40086,15249]} 2 | >player p1 {"name":"Bot 1","team":"Ditto|||None|submission,fly,sharpen,solarbeam||49,16,44,9,9,41|N|11,30,13,23,23,2||84|156]Poliwhirl|||None|supersonic,leechlife,eggbomb,doubleedge||25,122,3,130,130,184|N|0,1,12,4,4,28||96|157]Nidoran-F|||None|sonicboom,thunderbolt,psywave,scratch||224,150,23,173,173,131|N|3,20,0,26,26,11||60|45]Tentacool|||None|swordsdance,jumpkick,karatechop,clamp||62,200,41,181,181,191|N|1,24,24,22,22,21||86|27]Moltres|||None|bubble,earthquake,surf,horndrill||77,72,90,16,16,24|N|1,25,24,6,6,9||78|126]Meowth|||None|absorb,rockslide,wrap,stomp||111,208,163,134,134,237|N|11,15,5,22,22,26||82|156"} 3 | >player p2 {"name":"Bot 2","team":"Dugtrio|||None|highjumpkick,roar,confusion,aurorabeam||206,55,250,220,220,41|N|7,29,,11,11,18||79|23]Electabuzz|||None|defensecurl,bodyslam,cometpunch,hypnosis||156,242,206,198,198,210|N|6,20,26,17,17,3||83|19]Lickitung|||None|thunder,sleeppowder,bide,razorwind||96,193,173,227,227,78|N|12,3,18,21,21,28||52|11]Raticate|||None|reflect,doublekick,slam,haze||217,98,66,209,209,200|N|9,26,28,14,14,20||88|200]Porygon|||None|rage,skyattack,pinmissile,hyperbeam||237,50,91,192,192,147|N|8,7,5,16,16,8||70|70]Electrode|||None|icepunch,teleport,splash,peck||4,193,84,39,39,159|N|2,1,16,5,5,23||97|91"} 4 | >p1 move submission 5 | >p2 move highjumpkick 6 | >p1 switch 2 7 | >p2 switch 2 8 | >p1 switch 2 9 | >p2 move defensecurl 10 | >p1 switch 3 11 | >p2 move bodyslam 12 | >p1 move sonicboom 13 | >p2 move cometpunch 14 | >p1 switch 4 15 | >p1 switch 5 16 | >p2 move hypnosis 17 | >p1 move bubble 18 | >p2 move hypnosis 19 | >p1 move earthquake 20 | >p2 move bodyslam 21 | >p1 move surf 22 | >p2 switch 2 23 | >p2 switch 3 24 | >p1 move horndrill 25 | >p2 move thunder 26 | >p1 switch 6 27 | >p2 move sleeppowder 28 | >p1 move absorb 29 | >p2 switch 4 30 | >p1 move rockslide 31 | >p2 switch 5 32 | >p1 move wrap 33 | >p2 move rage 34 | >p1 move stomp 35 | >p2 move rage 36 | >p1 move absorb 37 | >p2 move rage 38 | >p1 move absorb 39 | >p2 move rage 40 | >p1 move absorb 41 | >p2 move rage 42 | >p1 switch 5 43 | >p2 move rage 44 | >p1 move swordsdance 45 | >p2 move rage 46 | >p1 move jumpkick 47 | >p2 move rage 48 | >p1 switch 5 49 | >p2 move rage 50 | >p1 switch 2 51 | >p2 move rage 52 | >p1 switch 2 53 | >p2 move rage 54 | >p1 move wrap 55 | >p2 move rage 56 | >p1 move wrap 57 | >p2 move rage -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xE26C9A0D11C52B93.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[57964,39437,4549,11155]} 2 | >player p1 {"name":"Bot 1","team":"Golem|||None|slash,thundershock,rest,eggbomb||195,138,96,184,184,162|N|8,19,16,13,13,5||61|211]Paras|||None|psywave,bodyslam,skyattack,leechlife||220,51,219,42,42,123|N|3,9,21,18,18,3||93|225]Blastoise|||None|metronome,recover,toxic,waterfall||34,86,27,177,177,154|N|5,17,6,3,3,29||52|180]Mew|||None|selfdestruct,stomp,lovelykiss,smog||177,3,20,221,221,99|N|0,25,9,4,4,21||87|190]Ekans|||None|pinmissile,submission,rage,peck||88,19,149,233,233,222|N|5,5,27,18,18,17||69|153]Machop|||None|absorb,jumpkick,doubleedge,bide||94,146,158,29,29,122|N|4,16,18,12,12,5||66|131"} 3 | >player p2 {"name":"Bot 2","team":"Psyduck|||None|hypnosis,megapunch,fissure,softboiled||18,156,126,35,35,155|N|3,13,5,26,26,23||90|167]Sandshrew|||None|clamp,fly,pound,slam||176,202,77,53,53,51|N|4,1,,8,8,28||64|53]Weepinbell|||None|whirlwind,poisonsting,kinesis,sludge||137,104,107,128,128,155|N|9,23,9,3,3,28||99|203]Flareon|||None|doubleslap,poisongas,hyperbeam,twineedle||183,172,110,9,9,4|N|5,1,,30,30,20||97|33]Kabutops|||None|spikecannon,wingattack,dreameater,crabhammer||28,52,218,124,124,77|N|13,23,,10,10,4||83|100]Venomoth|||None|mist,poisonpowder,boneclub,wrap||171,97,218,94,94,63|N|15,22,,18,18,18||77|53"} 4 | >p1 switch 2 5 | >p2 move hypnosis 6 | >p1 move psywave 7 | >p2 switch 2 8 | >p1 switch 2 9 | >p2 move clamp 10 | >p1 move slash 11 | >p2 move clamp 12 | >p1 move thundershock 13 | >p2 move fly 14 | >p1 move rest 15 | >p2 move fly 16 | >p1 move eggbomb 17 | >p2 move pound 18 | >p1 switch 3 19 | >p2 move slam 20 | >p1 move metronome 21 | >p2 move clamp 22 | >p1 move recharge 23 | >p2 move clamp 24 | >p1 move recharge 25 | >p2 switch 2 -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xE2D929DD7D14C5F4.showdown.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xE2D929DD7D14C5F4.showdown.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xE47319978AD041B1.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[58483,6551,35536,16817]} 2 | >player p1 {"name":"Bot 1","team":"Bellsprout|||None|thundershock,guillotine,growth,megadrain||66,170,74,216,216,110|N|7,24,22,19,19,27||69|200]Kingler|||None|triattack,cometpunch,twineedle,rest||59,161,152,147,147,93|N|10,23,28,13,13,30||74|111]Magikarp|||None|barrier,pound,doubleedge,nightshade||227,226,236,36,36,189|N|12,6,23,8,8,5||68|186]Muk|||None|leechlife,razorwind,amnesia,toxic||5,146,249,39,39,50|N|0,4,20,8,8,25||98|151]Oddish|||None|payday,thunderpunch,crabhammer,bubblebeam||173,238,10,34,34,221|N|15,19,15,14,14,10||55|126]Tentacool|||None|doubleslap,defensecurl,strength,smog||196,33,111,203,203,150|N|9,26,20,15,15,24||88|88"} 3 | >player p2 {"name":"Bot 2","team":"Kabuto|||None|bubble,vinewhip,disable,dizzypunch||38,29,30,44,44,227|N|5,16,27,3,3,29||50|1]Farfetch’d|||None|thrash,visegrip,fireblast,stomp||201,126,164,230,230,75|N|8,26,12,12,12,25||68|65]Venomoth|||None|sludge,lovelykiss,headbutt,conversion||127,231,124,202,202,140|N|10,2,8,29,29,15||72|241]Psyduck|||None|glare,confuseray,thunder,sonicboom||80,112,242,187,187,39|N|9,6,17,27,27,28||57|145]Wigglytuff|||None|seismictoss,tailwhip,confusion,substitute||1,230,139,203,203,60|N|8,10,8,24,24,24||93|72]Rapidash|||None|psybeam,horndrill,sharpen,takedown||167,41,7,210,210,13|N|15,2,19,11,11,6||70|233"} 4 | >p1 switch 2 5 | >p2 move bubble 6 | >p1 switch 2 7 | >p2 switch 2 8 | >p1 move thundershock 9 | >p2 move thrash 10 | >p1 move guillotine 11 | >p2 move thrash 12 | >p1 switch 3 13 | >p1 move barrier 14 | >p2 move thrash 15 | >p1 move pound 16 | >p2 move thrash 17 | >p1 move doubleedge 18 | >p2 switch 2 19 | >p1 move nightshade 20 | >p2 move vinewhip 21 | >p1 move pound 22 | >p2 move disable 23 | >p1 move doubleedge 24 | >p2 move dizzypunch 25 | >p2 switch 3 26 | >p1 switch 4 27 | >p2 switch 4 28 | >p1 switch 5 29 | >p2 switch 5 30 | >p1 switch 6 31 | >p2 move seismictoss 32 | >p1 move doubleslap 33 | >p2 switch 6 34 | >p1 switch 6 35 | >p2 move psybeam 36 | >p1 move payday 37 | >p2 move horndrill 38 | >p1 move thunderpunch 39 | >p2 move sharpen 40 | >p1 switch 4 41 | >p2 move takedown 42 | >p1 switch 2 43 | >p1 move triattack 44 | >p2 move takedown 45 | >p1 move cometpunch 46 | >p2 move takedown 47 | >p1 move twineedle 48 | >p2 move sharpen 49 | >p2 switch 2 50 | >p1 switch 6 51 | >p2 move visegrip 52 | >p1 switch 6 53 | >p2 move fireblast 54 | >p1 switch 6 55 | >p2 move stomp 56 | >p1 switch 5 57 | >p1 move leechlife 58 | >p2 move stomp 59 | >p1 switch 6 60 | >p2 move thrash 61 | >p1 switch 6 62 | >p1 move razorwind 63 | >p2 move thrash 64 | >p1 move razorwind 65 | >p2 move thrash 66 | >p2 switch 6 67 | >p1 move amnesia 68 | >p2 move tailwhip 69 | >p1 move toxic 70 | >p2 move confusion 71 | >p1 move amnesia 72 | >p2 move substitute 73 | >p1 move toxic 74 | >p2 move substitute -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xE6412ECA6071C6D4.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xE6412ECA6071C6D4.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xE7E6B0F82286A08B.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[59366,45304,8838,41099]} 2 | >player p1 {"name":"Bot 1","team":"Sandshrew|||None|splash,superfang,disable,screech||161,247,221,222,222,126|N|0,5,16,21,21,4||91|170]Charmander|||None|tailwhip,watergun,scratch,minimize||211,113,64,95,95,174|N|10,27,28,17,17,23||57|210]Sandslash|||None|teleport,pinmissile,swift,rockslide||25,226,16,247,247,102|N|3,16,24,19,19,14||96|243]Magneton|||None|stomp,megakick,lovelykiss,lightscreen||197,24,189,111,111,147|N|14,10,18,20,20,3||55|195]Cubone|||None|sonicboom,nightshade,stringshot,dragonrage||123,91,229,18,18,140|N|2,20,13,12,12,23||72|95]Moltres|||None|confusion,bite,absorb,flash||66,173,84,108,108,187|N|12,18,14,21,21,12||97|192"} 3 | >player p2 {"name":"Bot 2","team":"Dragonite|||None|bubble,sludge,submission,mist||50,187,141,242,242,5|N|1,1,5,19,19,28||83|68]Nidoran-M|||None|jumpkick,wingattack,poisongas,ember||230,12,54,218,218,84|N|11,22,24,,,22||58|98]Jynx|||None|amnesia,cut,psybeam,strength||160,100,238,62,62,27|N|11,11,5,27,27,26||77|74]Caterpie|||None|skullbash,horndrill,thunderbolt,acid||61,63,80,2,2,13|N|9,30,13,23,23,8||50|130]Omastar|||None|growl,thunderwave,withdraw,seismictoss||76,159,174,107,107,176|N|15,19,15,23,23,23||58|75]Clefable|||None|hyperbeam,visegrip,doubleedge,leer||179,232,172,129,129,238|N|9,23,29,26,26,25||64|102"} 4 | >p1 move splash 5 | >p2 move bubble 6 | >p1 move superfang 7 | >p2 switch 2 8 | >p1 switch 2 9 | >p2 move jumpkick 10 | >p1 move tailwhip 11 | >p2 move wingattack 12 | >p1 switch 2 13 | >p2 move poisongas 14 | >p1 switch 3 15 | >p2 move ember 16 | >p1 switch 4 17 | >p2 move wingattack 18 | >p1 move stomp 19 | >p2 move ember 20 | >p1 switch 5 21 | >p2 move ember 22 | >p1 move sonicboom 23 | >p2 switch 2 24 | >p1 move nightshade 25 | >p2 switch 3 26 | >p1 move stringshot 27 | >p2 move amnesia 28 | >p1 move dragonrage 29 | >p2 move cut 30 | >p1 move nightshade 31 | >p2 move psybeam 32 | >p1 switch 6 33 | >p1 switch 5 34 | >p2 move strength 35 | >p1 move megakick 36 | >p2 move psybeam 37 | >p1 switch 4 38 | >p1 move teleport 39 | >p2 switch 4 40 | >p1 move pinmissile 41 | >p2 switch 5 42 | >p1 move swift 43 | >p2 move growl 44 | >p1 move rockslide 45 | >p2 move thunderwave 46 | >p1 move pinmissile 47 | >p2 switch 6 48 | >p1 move pinmissile 49 | >p2 move hyperbeam 50 | >p1 move pinmissile 51 | >p2 move recharge 52 | >p1 switch 2 53 | >p2 move visegrip 54 | >p1 switch 3 55 | >p1 move disable 56 | >p2 move doubleedge 57 | >p1 move screech 58 | >p2 switch 5 59 | >p1 move disable 60 | >p2 move skullbash 61 | >p1 move splash 62 | >p2 move skullbash 63 | >p1 switch 2 64 | >p2 move horndrill 65 | >p1 move pinmissile 66 | >p2 switch 2 67 | >p2 switch 3 68 | >p1 move rockslide 69 | >p2 move sludge 70 | >p1 move rockslide 71 | >p2 switch 2 72 | >p2 switch 2 73 | >p1 switch 2 74 | >p2 move submission 75 | >p1 move screech 76 | >p2 move mist -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xEBEC48B906A37945.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xEBEC48B906A37945.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xEC4103CD675CDAA1.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[60481,973,26460,55969]} 2 | >player p1 {"name":"Bot 1","team":"Pidgeot|||None|megadrain,headbutt,crabhammer,agility||247,208,241,43,43,113|N|5,28,23,3,3,12||54|25]Magikarp|||None|icepunch,psybeam,explosion,smog||73,188,41,101,101,90|N|5,4,18,,,24||66|163]Aerodactyl|||None|twineedle,acid,withdraw,thunderbolt||142,70,156,61,61,75|N|13,23,22,,,1||96|71]Golduck|||None|reflect,spore,bubble,bite||100,222,138,113,113,49|N|11,10,8,10,10,||57|7]Ninetales|||None|slam,selfdestruct,superfang,skyattack||10,136,17,21,21,164|N|1,5,24,10,10,24||66|228]Gastly|||None|fly,whirlwind,doubleteam,minimize||136,7,152,120,120,215|N|0,13,5,20,20,28||96|41"} 3 | >player p2 {"name":"Bot 2","team":"Mewtwo|||None|quickattack,splash,leechseed,swift||152,12,223,210,210,4|N|14,3,7,17,17,23||74|205]Starmie|||None|megadrain,smokescreen,bonemerang,bubblebeam||63,142,63,35,35,184|N|7,20,7,27,27,18||69|131]Zubat|||None|psychic,earthquake,slash,karatechop||87,124,247,12,12,229|N|7,21,15,23,23,27||56|186]Omanyte|||None|swordsdance,leechlife,toxic,bodyslam||73,211,71,202,202,233|N|5,24,23,3,3,0||82|25]Electabuzz|||None|supersonic,ember,aurorabeam,stringshot||86,169,47,186,186,41|N|2,1,0,24,24,27||89|21]Dragonite|||None|focusenergy,headbutt,dreameater,megapunch||32,231,75,102,102,59|N|14,23,23,0,0,18||62|156"} 4 | >p1 move megadrain 5 | >p2 switch 2 6 | >p1 switch 2 7 | >p2 move megadrain 8 | >p1 move explosion 9 | >p2 switch 2 10 | >p1 switch 2 11 | >p1 move headbutt 12 | >p2 move swift 13 | >p1 move crabhammer 14 | >p2 move quickattack 15 | >p1 move crabhammer 16 | >p2 move quickattack 17 | >p1 switch 3 18 | >p2 move quickattack 19 | >p1 move thunderbolt 20 | >p2 move swift 21 | >p1 move acid 22 | >p2 move leechseed 23 | >p1 move acid 24 | >p2 switch 3 25 | >p1 move acid 26 | >p2 switch 4 27 | >p1 switch 4 28 | >p2 move toxic 29 | >p1 move bite 30 | >p2 move swordsdance 31 | >p1 switch 5 32 | >p2 move toxic 33 | >p1 move superfang 34 | >p2 switch 5 35 | >p1 switch 6 36 | >p2 move aurorabeam 37 | >p1 move fly 38 | >p2 switch 6 39 | >p1 move fly 40 | >p2 move headbutt 41 | >p1 move minimize 42 | >p2 move dreameater 43 | >p1 move doubleteam 44 | >p2 move headbutt 45 | >p1 move fly 46 | >p2 move headbutt 47 | >p1 move fly 48 | >p2 move megapunch 49 | >p1 move fly 50 | >p2 move dreameater 51 | >p1 move fly 52 | >p2 move megapunch 53 | >p1 move minimize 54 | >p2 switch 3 55 | >p1 move fly 56 | >p2 move swift -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xEC906D7B433288F0.pkmn.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xEC906D7B433288F0.pkmn.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xED1F32123199F701.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[60703,12818,12697,63233]} 2 | >player p1 {"name":"Bot 1","team":"Pikachu|||None|rockthrow,toxic,lightscreen,thunderpunch||8,57,32,186,186,13|N|3,20,0,23,23,3||72|165]Dugtrio|||None|hornattack,dizzypunch,tackle,poisongas||190,86,117,158,158,4|N|4,5,6,0,0,0||81|124]Cloyster|||None|peck,jumpkick,lovelykiss,dig||206,130,23,152,152,60|N|9,14,13,27,27,28||97|156]Arcanine|||None|drillpeck,rage,megakick,tailwhip||90,60,173,103,103,218|N|11,2,17,3,3,23||62|129]Slowpoke|||None|substitute,teleport,glare,boneclub||223,238,11,10,10,77|N|2,28,21,21,21,14||89|197]Dewgong|||None|barrage,swift,confuseray,psybeam||97,139,132,214,214,65|N|5,24,26,18,18,25||93|215"} 3 | >player p2 {"name":"Bot 2","team":"Kadabra|||None|thundershock,barrier,reflect,spore||99,141,213,191,191,113|N|15,11,3,14,14,10||84|242]Squirtle|||None|rockslide,rollingkick,flash,hypnosis||191,215,2,173,173,140|N|6,8,18,9,9,3||84|114]Lickitung|||None|firepunch,teleport,selfdestruct,minimize||63,111,208,226,226,163|N|12,19,10,16,16,21||73|77]Snorlax|||None|megakick,conversion,dragonrage,solarbeam||91,81,148,239,239,25|N|15,19,3,10,10,26||86|212]Seadra|||None|razorleaf,harden,furyswipes,rockthrow||60,163,21,210,210,80|N|6,25,26,29,29,22||98|210]Bellsprout|||None|thunderbolt,stunspore,sandattack,nightshade||50,206,205,132,132,20|N|7,21,22,2,2,27||77|42"} 4 | >p1 switch 2 5 | >p2 move thundershock 6 | >p1 move hornattack 7 | >p2 move reflect 8 | >p1 move dizzypunch 9 | >p2 move barrier 10 | >p1 move tackle 11 | >p2 move reflect 12 | >p1 switch 2 13 | >p2 move thundershock 14 | >p1 switch 3 15 | >p2 move spore 16 | >p1 move peck 17 | >p2 switch 2 18 | >p1 switch 4 19 | >p2 move hypnosis 20 | >p1 switch 5 21 | >p2 switch 2 22 | >p1 switch 6 23 | >p2 move spore 24 | >p1 move barrage 25 | >p2 move reflect 26 | >p1 move swift 27 | >p2 move barrier 28 | >p1 move confuseray 29 | >p2 move thundershock 30 | >p1 move psybeam 31 | >p2 move reflect 32 | >p1 switch 5 33 | >p2 move thundershock 34 | >p1 switch 6 35 | >p2 move reflect 36 | >p1 switch 4 37 | >p2 switch 3 38 | >p1 move jumpkick 39 | >p2 move teleport 40 | >p1 move lovelykiss 41 | >p2 switch 4 42 | >p1 move dig 43 | >p2 move megakick 44 | >p1 move dig 45 | >p2 move megakick 46 | >p1 move peck 47 | >p2 move conversion 48 | >p1 switch 3 49 | >p2 move dragonrage 50 | >p1 move rockthrow 51 | >p2 move solarbeam 52 | >p1 move toxic 53 | >p2 move solarbeam 54 | >p1 switch 5 55 | >p1 switch 2 56 | >p2 move conversion 57 | >p1 move poisongas 58 | >p2 move dragonrage 59 | >p1 move dizzypunch 60 | >p2 switch 5 61 | >p1 move dizzypunch 62 | >p2 move furyswipes 63 | >p1 move hornattack 64 | >p2 move rockthrow 65 | >p1 move tackle 66 | >p2 move razorleaf 67 | >p1 switch 2 68 | >p1 switch 4 69 | >p2 switch 6 70 | >p1 move substitute 71 | >p2 move stunspore 72 | >p1 move glare 73 | >p2 move thunderbolt 74 | >p1 switch 6 75 | >p2 move nightshade 76 | >p1 move drillpeck 77 | >p2 move stunspore 78 | >p1 move rage 79 | >p2 move sandattack 80 | >p1 move rage 81 | >p2 move nightshade 82 | >p1 move rage 83 | >p2 move stunspore 84 | >p1 move rage 85 | >p2 move thunderbolt 86 | >p1 move rage 87 | >p2 move sandattack -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xED964909377B7E8E.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[60822,18697,14203,32398]} 2 | >player p1 {"name":"Bot 1","team":"Mewtwo|||None|cut,surf,rage,smokescreen||225,24,237,237,237,33|N|1,28,8,11,11,28||97|65]Kabuto|||None|furyswipes,reflect,poisongas,firepunch||172,221,110,237,237,210|N|0,29,12,16,16,4||68|45]Cloyster|||None|crabhammer,stringshot,barrage,selfdestruct||86,5,238,173,173,232|N|14,11,15,25,25,14||75|100]Fearow|||None|bodyslam,bubblebeam,roar,wingattack||68,10,132,102,102,200|N|7,20,30,,,27||73|20]Pikachu|||None|dizzypunch,sing,meditate,seismictoss||13,186,198,189,189,246|N|12,10,15,8,8,13||62|79]Porygon|||None|defensecurl,fly,superfang,rest||40,199,240,234,234,219|N|15,7,22,7,7,19||61|209"} 3 | >player p2 {"name":"Bot 2","team":"Weepinbell|||None|growl,ember,leechseed,selfdestruct||128,164,127,214,214,183|N|14,27,18,1,1,23||51|141]Machop|||None|swordsdance,strength,whirlwind,twineedle||139,164,43,217,217,60|N|11,30,4,22,22,2||90|0]Pidgeotto|||None|rockthrow,splash,constrict,agility||32,245,119,57,57,41|N|9,11,21,22,22,8||51|207]Poliwag|||None|dig,stringshot,roar,nightshade||36,202,210,189,189,114|N|15,7,15,27,27,19||75|196]Arcanine|||None|fissure,softboiled,counter,acid||221,177,249,123,123,237|N|14,14,27,21,21,14||50|26]Magnemite|||None|barrier,toxic,wrap,triattack||18,112,132,195,195,41|N|2,1,24,21,21,22||92|57"} 4 | >p1 move cut 5 | >p2 move growl 6 | >p1 move surf 7 | >p2 move ember 8 | >p2 switch 2 9 | >p1 move rage 10 | >p2 move whirlwind 11 | >p1 move rage 12 | >p2 move whirlwind 13 | >p1 move rage 14 | >p2 switch 3 15 | >p1 move rage 16 | >p2 move agility 17 | >p1 move rage 18 | >p2 move splash 19 | >p2 switch 4 20 | >p1 move rage 21 | >p2 move stringshot 22 | >p1 move rage 23 | >p2 switch 6 24 | >p1 move rage 25 | >p2 switch 5 26 | >p1 move rage 27 | >p2 move counter -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xEFAA766A8ED2D5BF.showdown.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pkmn/engine/a27b3ff330f57cd923d83f21832db2fcc0eac3a9/src/test/fixtures/gen1/0xEFAA766A8ED2D5BF.showdown.bin -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xF091D4934DA9A368.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[61585,54419,19881,41832]} 2 | >player p1 {"name":"Bot 1","team":"Dewgong|||None|teleport,hyperfang,leechlife,highjumpkick||249,242,123,94,94,245|N|14,2,27,17,17,||55|173]Drowzee|||None|poisongas,harden,petaldance,superfang||155,133,132,35,35,199|N|15,26,26,10,10,22||97|110]Lapras|||None|dizzypunch,megadrain,sludge,absorb||56,229,189,155,155,113|N|4,12,27,1,1,28||87|247]Magmar|||None|vinewhip,agility,psywave,scratch||44,220,43,,,141|N|10,7,29,25,25,23||51|108]Growlithe|||None|slam,boneclub,megakick,doubleslap||247,112,74,124,124,159|N|6,1,11,5,5,15||54|201]Meowth|||None|doubleteam,ember,wingattack,softboiled||81,14,119,135,135,172|N|12,30,18,25,25,1||84|205"} 3 | >player p2 {"name":"Bot 2","team":"Jolteon|||None|growl,fireblast,drillpeck,selfdestruct||58,118,109,219,219,245|N|7,1,,7,7,27||70|151]Pinsir|||None|cut,poisonpowder,thunderbolt,rest||64,216,167,10,10,171|N|14,7,6,1,1,30||57|206]Zubat|||None|mimic,splash,strength,razorwind||175,235,198,78,78,107|N|15,11,19,7,7,10||96|227]Caterpie|||None|mirrormove,sharpen,defensecurl,gust||84,17,89,50,50,22|N|7,1,15,7,7,6||66|85]Dugtrio|||None|payday,pinmissile,toxic,takedown||147,186,247,126,126,162|N|10,15,13,21,21,26||79|152]Pidgeot|||None|sleeppowder,explosion,quickattack,stunspore||104,215,221,137,137,162|N|2,9,20,25,25,||82|54"} 4 | >p1 switch 2 5 | >p2 switch 2 6 | >p1 switch 2 7 | >p2 move cut 8 | >p1 move teleport 9 | >p2 move poisonpowder 10 | >p1 move hyperfang 11 | >p2 switch 2 12 | >p1 move leechlife 13 | >p2 move growl 14 | >p1 switch 3 15 | >p2 switch 3 16 | >p1 move dizzypunch 17 | >p2 move mimic 18 | >p1 switch 4 19 | >p2 switch 4 20 | >p1 move vinewhip 21 | >p2 switch 5 22 | >p1 move agility 23 | >p2 move payday 24 | >p1 move psywave 25 | >p2 move pinmissile 26 | >p1 move scratch 27 | >p2 move toxic 28 | >p1 move scratch 29 | >p2 move takedown 30 | >p1 switch 5 31 | >p1 move slam 32 | >p2 move pinmissile 33 | >p1 move boneclub 34 | >p2 move payday 35 | >p1 switch 6 36 | >p2 move toxic 37 | >p1 move doubleteam 38 | >p2 move takedown 39 | >p1 move ember 40 | >p2 move toxic 41 | >p2 switch 6 42 | >p1 switch 3 43 | >p2 move sleeppowder 44 | >p1 move highjumpkick 45 | >p2 move explosion 46 | >p1 switch 2 47 | >p2 switch 3 48 | >p1 switch 6 49 | >p2 move fireblast 50 | >p1 move megakick 51 | >p2 move drillpeck 52 | >p1 switch 6 53 | >p1 move poisongas 54 | >p2 switch 4 55 | >p1 move harden 56 | >p2 move splash 57 | >p1 move petaldance 58 | >p2 switch 4 59 | >p1 move petaldance 60 | >p2 move selfdestruct 61 | >p2 switch 5 62 | >p1 move petaldance 63 | >p2 move mirrormove -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xF12F2AB7B055F0E7.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[61743,10935,45141,61671]} 2 | >player p1 {"name":"Bot 1","team":"Horsea|||None|dig,visegrip,furyswipes,watergun||120,1,209,174,174,72|N|5,21,7,18,18,5||58|54]Hitmonlee|||None|icebeam,doubleteam,bite,fissure||220,13,119,229,229,111|N|11,6,21,18,18,30||81|179]Starmie|||None|lightscreen,fly,poisonsting,selfdestruct||237,20,240,11,11,63|N|15,2,,19,19,30||82|140]Ivysaur|||None|thunderwave,stunspore,superfang,submission||194,123,168,91,91,142|N|6,1,23,8,8,30||98|11]Pikachu|||None|sonicboom,lick,disable,substitute||147,205,139,143,143,105|N|10,7,9,21,21,6||57|62]Kadabra|||None|drillpeck,sludge,wingattack,hyperfang||133,218,55,116,116,200|N|8,14,9,28,28,12||54|216"} 3 | >player p2 {"name":"Bot 2","team":"Kabutops|||None|gust,toxic,dizzypunch,bonemerang||162,195,66,81,81,51|N|11,26,25,23,23,27||90|32]Charmander|||None|quickattack,nightshade,thunderbolt,cut||107,176,39,126,126,233|N|12,18,27,0,0,17||68|2]Rapidash|||None|withdraw,razorleaf,sing,icepunch||76,149,61,57,57,15|N|7,9,11,15,15,2||89|144]Snorlax|||None|substitute,constrict,furyswipes,smog||115,142,51,163,163,73|N|2,8,21,25,25,15||98|227]Cloyster|||None|thunderpunch,leechlife,drillpeck,barrage||83,72,243,48,48,126|N|6,13,18,1,1,30||68|219]Golduck|||None|skullbash,sludge,hornattack,skyattack||140,172,79,6,6,7|N|15,14,10,19,19,15||76|158"} 4 | >p1 move dig 5 | >p2 switch 2 6 | >p1 move dig 7 | >p2 switch 2 8 | >p1 move visegrip 9 | >p2 move gust 10 | >p1 move furyswipes 11 | >p2 move toxic 12 | >p1 switch 2 13 | >p2 move dizzypunch 14 | >p1 move icebeam 15 | >p2 move bonemerang 16 | >p1 switch 2 17 | >p1 move watergun 18 | >p2 switch 3 19 | >p1 move dig 20 | >p2 move withdraw 21 | >p1 move dig 22 | >p2 move withdraw 23 | >p1 switch 3 24 | >p2 move sing 25 | >p1 move lightscreen 26 | >p2 switch 4 27 | >p1 move fly 28 | >p2 move substitute 29 | >p1 move fly 30 | >p2 switch 5 31 | >p1 move poisonsting 32 | >p2 move drillpeck 33 | >p1 move selfdestruct 34 | >p2 move barrage 35 | >p1 switch 4 36 | >p1 move thunderwave 37 | >p2 move leechlife 38 | >p1 switch 5 39 | >p2 switch 6 40 | >p1 move sonicboom 41 | >p2 move sludge 42 | >p1 move lick 43 | >p2 move skyattack 44 | >p1 move disable 45 | >p2 move skyattack 46 | >p1 move substitute 47 | >p2 move sludge -------------------------------------------------------------------------------- /src/test/fixtures/gen1/0xF9035DA297392F5D.input.log: -------------------------------------------------------------------------------- 1 | >start {"formatid":"gen1customgame@@@Endless Battle Clause,Sleep Clause Mod,Freeze Clause Mod","seed":[63747,23970,38713,12125]} 2 | >player p1 {"name":"Bot 1","team":"Kabuto|||None|confusion,fly,swordsdance,whirlwind||184,194,197,60,60,68|N|10,10,24,17,17,3||88|156]Hitmonchan|||None|substitute,pound,haze,lick||67,94,169,4,4,219|N|14,18,7,24,24,7||65|120]Goldeen|||None|agility,firepunch,megadrain,submission||222,78,55,239,239,201|N|0,24,1,16,16,4||54|157]Horsea|||None|psychic,skyattack,selfdestruct,quickattack||151,150,209,14,14,199|N|11,15,1,3,3,11||59|161]Flareon|||None|barrage,growth,disable,bubblebeam||185,92,187,152,152,185|N|5,20,,10,10,13||79|110]Kangaskhan|||None|thundershock,poisongas,kinesis,thunderpunch||154,82,27,160,160,10|N|0,4,20,1,1,4||68|138"} 3 | >player p2 {"name":"Bot 2","team":"Bellsprout|||None|dreameater,earthquake,slam,jumpkick||8,122,243,243,243,152|N|0,28,29,17,17,13||81|46]Charizard|||None|defensecurl,sleeppowder,stringshot,fireblast||178,68,87,94,94,187|N|6,25,15,1,1,22||60|15]Nidoran-F|||None|leechseed,bind,psybeam,visegrip||226,63,90,128,128,11|N|0,0,5,16,16,25||82|171]Kingler|||None|teleport,highjumpkick,aurorabeam,seismictoss||32,94,26,122,122,174|N|9,27,12,14,14,17||53|252]Persian|||None|smokescreen,leer,icepunch,acidarmor||77,171,180,106,106,14|N|4,13,23,12,12,4||84|84]Kabutops|||None|sludge,flamethrower,recover,toxic||167,16,203,252,252,251|N|13,10,,10,10,28||70|36"} 4 | >p1 move confusion 5 | >p2 move dreameater 6 | >p1 switch 2 7 | >p2 move earthquake 8 | >p1 switch 2 9 | >p2 switch 2 10 | >p1 move fly 11 | >p2 move defensecurl 12 | >p1 move fly 13 | >p2 switch 2 14 | >p2 switch 3 15 | >p1 switch 3 16 | >p2 move leechseed 17 | >p1 move agility 18 | >p2 move bind 19 | >p1 switch 4 20 | >p2 move psybeam 21 | >p1 move psychic 22 | >p2 move visegrip 23 | >p1 move skyattack 24 | >p2 move bind 25 | >p1 move skyattack 26 | >p2 switch 4 -------------------------------------------------------------------------------- /src/test/fuzz.test.ts: -------------------------------------------------------------------------------- 1 | import {Generations} from '@pkmn/data'; 2 | import {Dex} from '@pkmn/sim'; 3 | 4 | import {run} from './fuzz'; 5 | 6 | // Simple smoke tests just to confirm things are wired up correctly and actually execute 7 | const gens = new Generations(Dex as any); 8 | for (const gen of gens) { 9 | if (gen.num > 1) break; 10 | for (const showdown of [false, true]) { 11 | describe(`Gen ${gen.num} (${showdown ? 'showdown' : 'pkmn'})`, () => { 12 | test('run', () => 13 | expect(run(gens, gen.num, showdown, true, '1s', 123456789n)).resolves.toBe(true), 14 | 60 * 1000); 15 | }); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/test/fuzz.ts: -------------------------------------------------------------------------------- 1 | import 'source-map-support/register'; 2 | 3 | import {execFile} from 'child_process'; 4 | import * as fs from 'fs'; 5 | import * as path from 'path'; 6 | 7 | import {Generations} from '@pkmn/data'; 8 | import {Dex} from '@pkmn/sim'; 9 | 10 | import {LE} from '../pkg/data'; 11 | import * as debug from '../tools/debug'; 12 | 13 | const ROOT = path.resolve(__dirname, '..', '..'); 14 | 15 | const usage = (msg?: string): void => { 16 | if (msg) console.error(msg); 17 | console.error('Usage: fuzz '); 18 | process.exit(1); 19 | }; 20 | 21 | export async function run( 22 | gens: Generations, 23 | gen: number | string, 24 | showdown: boolean, 25 | testing?: boolean, 26 | duration?: string, 27 | seed?: bigint 28 | ) { 29 | const args = ['build', '--summary', 'failures', 'fuzz', '-Dlog', '-Dchance', '-Dcalc']; 30 | if (showdown) args.push('-Dshowdown'); 31 | 32 | let input = undefined; 33 | if (typeof duration !== 'undefined') { 34 | args.push('--', gen.toString(), duration); 35 | if (seed) args.push(seed.toString()); 36 | } else { 37 | input = fs.readFileSync(gen); 38 | } 39 | 40 | try { 41 | await new Promise((resolve, reject) => { 42 | const child = execFile('zig', args, {encoding: 'buffer'}, (error, stdout, stderr) => { 43 | if (error) return reject({error, stdout, stderr}); 44 | resolve(); 45 | }); 46 | if (child.stdin && input) { 47 | child.stdin.write(input); 48 | child.stdin.end(); 49 | } 50 | }); 51 | return true; 52 | } catch (err: any) { 53 | const {stdout, stderr} = err as {stdout: Buffer; stderr: Buffer}; 54 | const raw = stderr.toString('utf8'); 55 | const panic = raw.indexOf('panic: '); 56 | if (testing || !stdout.length) throw new Error(raw); 57 | 58 | console.error(raw); 59 | 60 | const dir = path.join(ROOT, 'logs'); 61 | try { 62 | fs.mkdirSync(dir, {recursive: true}); 63 | } catch (e: any) { 64 | if (e.code !== 'EEXIST') throw e; 65 | } 66 | 67 | seed = LE ? stdout.readBigUInt64LE(0) : stdout.readBigUInt64BE(0); 68 | const hex = `0x${seed.toString(16).toUpperCase()}`; 69 | const file = path.join(dir, `${hex}.fuzz.html`); 70 | const link = path.join(dir, 'fuzz.html'); 71 | 72 | fs.writeFileSync(file, debug.render(gens, stdout.subarray(8), raw.slice(panic), seed)); 73 | fs.rmSync(link, {force: true}); 74 | fs.symlinkSync(file, link); 75 | 76 | return false; 77 | } 78 | } 79 | 80 | if (require.main === module) { 81 | (async () => { 82 | if (process.argv.length < 4 || process.argv.length > 6) usage(process.argv.length.toString()); 83 | const mode = process.argv[2]; 84 | if (mode !== 'pkmn' && mode !== 'showdown') { 85 | usage(`Mode must be either 'pkmn' or 'showdown', received '${mode}'`); 86 | } 87 | const gens = new Generations(Dex as any); 88 | const seed = process.argv.length > 5 ? BigInt(process.argv[5]) : undefined; 89 | await run(gens, process.argv[3], mode === 'showdown', false, process.argv[4], seed); 90 | })().catch(err => { 91 | console.error(err); 92 | process.exit(1); 93 | }); 94 | } 95 | -------------------------------------------------------------------------------- /src/test/integration.test.ts: -------------------------------------------------------------------------------- 1 | import {Generations} from '@pkmn/data'; 2 | import {Dex} from '@pkmn/sim'; 3 | 4 | import * as addon from '../pkg/addon'; 5 | 6 | import {run} from './integration'; 7 | 8 | describe('integration', () => { 9 | (addon.supports(true, true) ? test : test.skip)('test', async () => { 10 | const gens = new Generations(Dex as any); 11 | expect(await run(gens, {prng: '1,2,3,4'})).toBe(0); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /src/test/regression.test.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | 4 | import {Generations} from '@pkmn/data'; 5 | import {Dex} from '@pkmn/sim'; 6 | 7 | import * as addon from '../pkg/addon'; 8 | 9 | import * as fuzz from './fuzz'; 10 | import * as integration from './integration'; 11 | 12 | const FIXTURES = path.join(__dirname, 'fixtures'); 13 | const SKIP: string[] = []; 14 | 15 | const gens = new Generations(Dex as any); 16 | for (const gen of gens) { 17 | if (gen.num > 1) break; 18 | (addon.supports(true, true) ? describe : describe.skip)(`Gen ${gen.num}`, () => { 19 | const dir = path.join(FIXTURES, `gen${gen.num}`); 20 | for (const file of fs.readdirSync(path.join(dir))) { 21 | const name = file.slice(0, file.indexOf('.')); 22 | (SKIP.includes(name) ? test.skip : test)(`${name}`, async () => { 23 | if (file.endsWith('log')) { 24 | expect(await integration.run(gens, path.join(dir, file))).toBe(0); 25 | } else { 26 | const showdown = file.includes('showdown'); 27 | expect(await fuzz.run(gens, path.join(dir, file), showdown, true)).toBe(true); 28 | } 29 | }); 30 | } 31 | }); 32 | } 33 | -------------------------------------------------------------------------------- /src/test/showdown.html.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Pokémon Showdown 8 | 9 | 10 | 11 | 12 |
13 | {{{ seed }}} 14 |
15 |
16 |
17 |
18 |
19 |
20 |
{{{ content }}}
21 |
22 | 87 | 90 | 91 | -------------------------------------------------------------------------------- /src/tools/debug.ts: -------------------------------------------------------------------------------- 1 | import {execFileSync} from 'child_process'; 2 | import * as fs from 'fs'; 3 | import * as path from 'path'; 4 | 5 | import {Generation, Generations} from '@pkmn/data'; 6 | 7 | import * as data from '../pkg/data'; 8 | import * as gen1 from '../pkg/gen1'; 9 | 10 | import * as display from './display'; 11 | 12 | const ROOT = path.resolve(__dirname, '..', '..'); 13 | const ZIG = path.dirname(JSON.parse(execFileSync('zig', ['env'], {encoding: 'utf8'})).lib_dir); 14 | 15 | export function error(err: string) { 16 | return (err 17 | .replaceAll(ROOT + path.sep, '') 18 | .replaceAll(ZIG, '$ZIG') 19 | .split('\n').slice(0, -3).join('\n')); 20 | } 21 | 22 | export function render( 23 | gens: Generation | Generations, 24 | buffer: Buffer, 25 | err?: string, 26 | seed?: bigint 27 | ) { 28 | if (!buffer.length) throw new Error('Invalid input'); 29 | 30 | // Peek at the start of the data buffer just to figure out whether showdown is enabled, what 31 | // generation it is, and the intial state of the Battle 32 | const view = data.Data.view(buffer); 33 | 34 | let offset = 0; 35 | const showdown = !!view.getUint8(offset++); 36 | const num = view.getUint8(offset++); 37 | const gen = 'get' in gens ? gens.get(num) : gens; 38 | if (gen.num !== num) { 39 | throw new Error(`Require generation ${num} but was passed generation ${gen.num}`); 40 | } 41 | offset += 6; 42 | 43 | const lookup = data.Lookup.get(gen); 44 | const size = data.LAYOUT[gen.num - 1].sizes.Battle; 45 | 46 | const deserialize = (buf: Buffer) => { 47 | switch (gen.num) { 48 | case 1: return new gen1.Battle(lookup, data.Data.view(buf), {inert: true, showdown}); 49 | default: throw new Error(`Unsupported gen: ${gen.num}`); 50 | } 51 | }; 52 | const battle = deserialize(buffer.subarray(offset, offset += size)); 53 | 54 | return display.render(path.join(ROOT, 'build', 'tools', 'display', 'debug.jsx'), { 55 | gen: display.prune(gen, battle), 56 | buf: buffer.toString('base64'), 57 | error: err && error(err), 58 | seed: seed?.toString(), 59 | }, {styles: [path.join(ROOT, 'src', 'tools', 'display', 'debug.css')]}); 60 | } 61 | 62 | export async function run(gens: Generations) { 63 | let input; 64 | if (process.argv.length > 2) { 65 | if (process.argv.length > 3) { 66 | console.error('Invalid input'); 67 | process.exit(1); 68 | } 69 | input = fs.readFileSync(process.argv[2]); 70 | } else { 71 | let length = 0; 72 | const result: Uint8Array[] = []; 73 | for await (const chunk of process.stdin) { 74 | result.push(chunk); 75 | length += chunk.length; 76 | } 77 | input = Buffer.concat(result, length); 78 | } 79 | process.stdout.write(render(gens, input)); 80 | } 81 | 82 | if (require.main === module) { 83 | run(new Generations(require('@pkmn/sim').Dex)).catch(err => { 84 | console.error(err.message); 85 | process.exit(1); 86 | }); 87 | } 88 | -------------------------------------------------------------------------------- /src/tools/display/autocomplete.old.css: -------------------------------------------------------------------------------- 1 | /** @license MIT modified from Pixabay's https://github.com/Pixabay/JavaScript-autoComplete */ 2 | .autocomplete-suggestions { 3 | text-align: left; 4 | cursor: default; 5 | border: 1px solid #ccc; 6 | border-top: 0; 7 | background: #fff; 8 | box-shadow: -1px 1px 3px rgba(0, 0, 0, .1); 9 | 10 | position: absolute; 11 | display: none; 12 | z-index: 9999; 13 | max-height: 254px; 14 | overflow: hidden; 15 | overflow-y: auto; 16 | box-sizing: border-box; 17 | } 18 | .autocomplete-suggestion { 19 | position: relative; 20 | padding: 0 .6em; 21 | line-height: 23px; 22 | white-space: nowrap; 23 | overflow: hidden; 24 | text-overflow: ellipsis; 25 | font-size: 1.02em; 26 | color: #333; 27 | } 28 | .autocomplete-suggestion b { 29 | font-weight: normal; 30 | color: #1f8dd6; 31 | } 32 | .autocomplete-suggestion.selected { 33 | background: #f0f0f0; 34 | } -------------------------------------------------------------------------------- /src/tools/display/debug.css: -------------------------------------------------------------------------------- 1 | .log { 2 | display: flex; 3 | justify-content: center; 4 | padding-bottom: 2em; 5 | } -------------------------------------------------------------------------------- /src/tools/display/select.css: -------------------------------------------------------------------------------- 1 | /** @license MIT modified from Pixabay's https://github.com/Pixabay/JavaScript-autoComplete */ 2 | .select.options { 3 | text-align: left; 4 | cursor: default; 5 | border: 1px solid #ccc; 6 | border-top: 0; 7 | background: #fff; 8 | box-shadow: -1px 1px 3px rgba(0, 0, 0, .1); 9 | 10 | position: absolute; 11 | display: none; 12 | z-index: 9999; 13 | max-height: 254px; 14 | overflow: hidden; 15 | overflow-y: auto; 16 | scrollbar-width: thin; 17 | box-sizing: border-box; 18 | } 19 | .select.option { 20 | position: relative; 21 | padding: 0 .6em; 22 | line-height: 23px; 23 | white-space: nowrap; 24 | overflow: hidden; 25 | text-overflow: ellipsis; 26 | font-size: 1.02em; 27 | color: #333; 28 | } 29 | .select.option strong { 30 | font-weight: normal; 31 | color: #1f8dd6; 32 | } 33 | .select.option.selected { 34 | background: #f0f0f0; 35 | } -------------------------------------------------------------------------------- /src/tools/display/util.ts: -------------------------------------------------------------------------------- 1 | import {GenderName, MoveName, SpeciesName, TypeName} from '@pkmn/data'; 2 | 3 | import {Battle, Choice, Data, ParsedLine, Result} from '../../pkg'; 4 | 5 | export interface Frame { 6 | result: Result; 7 | c1: Choice; 8 | c2: Choice; 9 | battle: Data; 10 | parsed: ParsedLine[]; 11 | } 12 | 13 | export interface Species { 14 | name: SpeciesName; 15 | num: number; 16 | genderRatio: {M: number; F: number}; 17 | gender?: GenderName; 18 | } 19 | 20 | export interface Move { 21 | name: MoveName; 22 | num: number; 23 | maxpp: number; 24 | basePower: number; 25 | type: TypeName; 26 | } 27 | 28 | const format = (kwVal: any) => typeof kwVal === 'boolean' ? '' : ` ${kwVal as string}`; 29 | const trim = (args: string[]) => { 30 | while (args.length && !args[args.length - 1]) args.pop(); 31 | return args; 32 | }; 33 | 34 | const compact = (line: ParsedLine) => 35 | [...trim(line.args.slice(0) as string[]), ...Object.keys(line.kwArgs) 36 | .map(k => `[${k}]${format((line.kwArgs as any)[k])}`)].join('|'); 37 | 38 | export const toText = (parsed: ParsedLine[]) => 39 | parsed.length ? `|${parsed.map(compact).join('\n|')}` : ''; 40 | 41 | export const pretty = (choice?: Choice) => choice 42 | ? choice.type === 'pass' ? choice.type : `${choice.type} ${choice.data}` 43 | : '???'; 44 | 45 | export const imports = (memory: [WebAssembly.Memory], decoder: TextDecoder) => ({ 46 | js: { 47 | log(ptr: number, len: number) { 48 | if (len === 0) return console.log(''); 49 | const msg = decoder.decode(new Uint8Array(memory[0].buffer, ptr, len)); 50 | console.log(msg); 51 | }, 52 | panic(ptr: number, len: number) { 53 | const msg = decoder.decode(new Uint8Array(memory[0].buffer, ptr, len)); 54 | throw new Error('panic: ' + msg); 55 | }, 56 | }, 57 | }); 58 | -------------------------------------------------------------------------------- /src/tools/serde.ts: -------------------------------------------------------------------------------- 1 | import 'source-map-support/register'; 2 | 3 | import {execFile} from 'child_process'; 4 | 5 | const run = async (cmd: string, args: string[]): Promise => 6 | new Promise((resolve, reject) => { 7 | execFile(cmd, args, {encoding: 'buffer'}, (error, stdout) => 8 | error ? reject(error) : resolve(stdout)); 9 | }); 10 | 11 | const partition = (array: string[], n: number): string[][] => 12 | array.length ? [array.splice(0, n)].concat(partition(array, n)) : []; 13 | 14 | (async () => { 15 | const buf = await run('zig', ['build', 'serde', '--', process.argv[2].toString()]); 16 | const arr = Array.from(buf); 17 | const lines = partition(arr.map(x => `0x${x.toString(16).padStart(2, '0')}`), 16); 18 | console.log(lines.map(line => line.join(', ')).join(',\n')); 19 | })().catch(err => { 20 | console.error(err); 21 | process.exit(1); 22 | }); 23 | -------------------------------------------------------------------------------- /src/tools/version.zig: -------------------------------------------------------------------------------- 1 | const builtin = @import("builtin"); 2 | const std = @import("std"); 3 | 4 | pub fn main() !void { 5 | const version = try std.SemanticVersion.parse("0.12.0-dev.2036+fc79b22a9"); 6 | const modern = builtin.zig_version.order(version) != .lt; 7 | try std.io.getStdOut().writer().writeAll(if (modern) "modern" else "legacy"); 8 | } 9 | -------------------------------------------------------------------------------- /src/tools/vscode/LICENSE: -------------------------------------------------------------------------------- 1 | ../../../LICENSE -------------------------------------------------------------------------------- /src/tools/vscode/README.md: -------------------------------------------------------------------------------- 1 | In order to view the `.bin` files present in the regression test [fixtures](../../test/regression/fixtures/) in Visual Studio Code: 2 | 3 | 1. Add [`pkmn-debug`](../../bin/pkmn-debug) to the path `PATH` 4 | 2. Package the extension into a `.vsix`: 5 | ```sh 6 | $ npm run extension 7 | ``` 8 | 3. Install the extension in Visual Studio Code via "**Extensions: Install from VSIX...**" 9 | 4. Restart Visual Studio Code -------------------------------------------------------------------------------- /src/tools/vscode/extension.ts: -------------------------------------------------------------------------------- 1 | import {execFile} from 'child_process'; 2 | 3 | import * as vscode from 'vscode'; 4 | 5 | type RenderedDocument = vscode.CustomDocument & {readonly preview: string}; 6 | 7 | class PkmnDebugEditorProvider implements vscode.CustomReadonlyEditorProvider { 8 | async openCustomDocument( 9 | uri: vscode.Uri, 10 | context: vscode.CustomDocumentOpenContext, 11 | token: vscode.CancellationToken 12 | ): Promise { 13 | return {uri, preview: await preview(uri, token), dispose() {}}; 14 | } 15 | 16 | resolveCustomEditor(document: RenderedDocument, webviewPanel: vscode.WebviewPanel) { 17 | try { 18 | webviewPanel.webview.options = {enableScripts: true}; 19 | webviewPanel.webview.html = document.preview; 20 | } catch (error: unknown) { 21 | if (!(error instanceof Error)) throw error; 22 | vscode.window.showErrorMessage(`Error running pkmn-debug: ${error.message}`); 23 | } 24 | } 25 | } 26 | 27 | function preview(uri: vscode.Uri, token?: vscode.CancellationToken) { 28 | return new Promise((resolve, reject) => { 29 | const child = execFile('pkmn-debug', [uri.fsPath]); 30 | token?.onCancellationRequested(() => { 31 | child.kill(); 32 | }); 33 | let stdout = ''; 34 | child.stdout?.on('data', (data: Buffer) => { 35 | stdout += data.toString(); 36 | }); 37 | let stderr = ''; 38 | child.stderr?.on('data', (data: Buffer) => { 39 | stderr += data.toString(); 40 | }); 41 | child.on('error', error => { 42 | reject(error); 43 | }); 44 | child.on('exit', code => { 45 | if (code === 0) { 46 | resolve(stdout); 47 | } else { 48 | reject(new Error(`pkmn-debug exited with code: ${code}\n${stderr}`)); 49 | } 50 | }); 51 | }); 52 | } 53 | 54 | export function activate(context: vscode.ExtensionContext) { 55 | context.subscriptions.push(vscode.window.registerCustomEditorProvider( 56 | 'pkmn-debug', 57 | new PkmnDebugEditorProvider(), 58 | {webviewOptions: { 59 | enableFindWidget: true, 60 | retainContextWhenHidden: true, 61 | }}, 62 | )); 63 | } 64 | 65 | export function deactivate() {} 66 | -------------------------------------------------------------------------------- /src/tools/vscode/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pkmn-debug", 3 | "version": "0.1.0", 4 | "publisher": "pkmn", 5 | "repository": "github:pkmn/engine", 6 | "main": "extension.js", 7 | "files": ["extension.js", "LICENSE"], 8 | "scripts": { 9 | "build": "esbuild extension.ts --format=cjs --outfile=extension.js && vsce package" 10 | }, 11 | "engines": {"vscode": "^1.93.0"}, 12 | "activationEvents": [], 13 | "contributes": { 14 | "customEditors": [{ 15 | "viewType": "pkmn-debug", 16 | "displayName": "pkmn-debug", 17 | "selector": [{ "filenamePattern": "*.bin" }] 18 | }] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src"], 3 | "compilerOptions": { 4 | "allowUnreachableCode": false, 5 | "allowUnusedLabels": false, 6 | "baseUrl": ".", 7 | "declaration": true, 8 | "esModuleInterop": true, 9 | "forceConsistentCasingInFileNames": true, 10 | "incremental": true, 11 | "isolatedModules": true, 12 | "jsx": "preserve", 13 | "jsxFactory": "h", 14 | "jsxFragmentFactory": "Fragment", 15 | "lib": ["es2022", "dom", "dom.iterable"], 16 | "module": "nodenext", 17 | "moduleResolution": "nodenext", 18 | "noEmitOnError": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "noImplicitReturns": true, 21 | "outDir": "build", 22 | "resolveJsonModule": true, 23 | "skipLibCheck": true, 24 | "sourceMap": true, 25 | "strict": true, 26 | "target": "esnext", 27 | "tsBuildInfoFile": ".tsbuildinfo", 28 | "paths": { 29 | "@pkmn/sim/*": ["node_modules/@pkmn/sim/build/types/sim/*"] 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /vite.config.mts: -------------------------------------------------------------------------------- 1 | import {defineConfig} from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | watch: false, 6 | globals: true, 7 | testTimeout: 60_000, 8 | exclude: ['node_modules', 'build', 'examples'], 9 | coverage: {reportsDirectory: 'coverage/js', exclude: ['src/test', '**/*.test.ts']}, 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /zig.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig 2 | index f8aeface59..14f3027e6c 100644 3 | --- a/src/codegen/llvm.zig 4 | +++ b/src/codegen/llvm.zig 5 | @@ -6741,7 +6741,8 @@ pub const FuncGen = struct { 6 | } else { 7 | const elem_ptr = 8 | try self.wip.gep(.inbounds, array_llvm_ty, array_llvm_val, &indices, ""); 9 | - return self.loadTruncate(.normal, elem_ty, elem_ptr, .default); 10 | + const elem_llvm_ty = try o.lowerType(elem_ty); 11 | + return self.wip.load(.normal, elem_llvm_ty, elem_ptr, .default, ""); 12 | } 13 | } 14 | 15 | @@ -6912,12 +6913,13 @@ pub const FuncGen = struct { 16 | const payload_index = @intFromBool(layout.tag_align.compare(.gte, layout.payload_align)); 17 | const field_ptr = 18 | try self.wip.gepStruct(union_llvm_ty, struct_llvm_val, payload_index, ""); 19 | + const llvm_field_ty = try o.lowerType(field_ty); 20 | const payload_alignment = layout.payload_align.toLlvm(); 21 | if (isByRef(field_ty, zcu)) { 22 | if (canElideLoad(self, body_tail)) return field_ptr; 23 | return self.loadByRef(field_ptr, field_ty, payload_alignment, .normal); 24 | } else { 25 | - return self.loadTruncate(.normal, field_ty, field_ptr, payload_alignment); 26 | + return self.wip.load(.normal, llvm_field_ty, field_ptr, payload_alignment, ""); 27 | } 28 | }, 29 | else => unreachable, 30 | @@ -10915,7 +10917,8 @@ pub const FuncGen = struct { 31 | 32 | return fg.loadByRef(payload_ptr, payload_ty, payload_alignment, .normal); 33 | } 34 | - return fg.loadTruncate(.normal, payload_ty, payload_ptr, payload_alignment); 35 | + const payload_llvm_ty = try o.lowerType(payload_ty); 36 | + return fg.wip.load(.normal, payload_llvm_ty, payload_ptr, payload_alignment, ""); 37 | } 38 | 39 | assert(!isByRef(payload_ty, zcu)); 40 | @@ -11129,7 +11132,7 @@ pub const FuncGen = struct { 41 | if (isByRef(elem_ty, zcu)) { 42 | return self.loadByRef(ptr, elem_ty, ptr_alignment, access_kind); 43 | } 44 | - return self.loadTruncate(access_kind, elem_ty, ptr, ptr_alignment); 45 | + return self.wip.load(access_kind, try o.lowerType(elem_ty), ptr, ptr_alignment, ""); 46 | } 47 | 48 | const containing_int_ty = try o.builder.intType(@intCast(info.packed_offset.host_size * 8)); 49 | --------------------------------------------------------------------------------