- Research the data structures and code flow
- Add a
data.zigfile with basic data types (Battle,Side,Pokemon, ...) and fields- un-optimized - exact layout tweaked in step 11
- Generate data files
- reorder enums for performance
- update
Lookupif necessary
- Generate test files
- reorganize logically and to match previous generations
- add in cases for known Pokémon Showdown bugs and cartridge glitches
- Copy over shared code/files
- copy over
README.mdfor new generation - copy over imports and public function skeletons in
mechanics.zig - copy
Testinfrastructure and rolls intotest.zig - copy over
helpers.zig
- copy over
- Implement unit tests against Pokémon Showdown behavior
- update Bugs section of generation documentation as bugs are discovered
- Implement mechanics in
mechanics.zigbased on cartridge research- update protocol as necessary, also updating documentation, driver, and tests
- generate updated
protocol.json
- Adjust mechanics for Pokémon Showdown compatibility
- track RNG differences and update generation documentation (group all RNG is in
Rolls) - ensure all bugs are tracked in documentation
- add logic to tests to block any unimplementable effects
- track RNG differences and update generation documentation (group all RNG is in
- Unit test the engine in both cartridge and Pokémon Showdown compatibility mode
- Implement a
MAX_LOGSunit test- document in
PROTOCOL.md - validate with Z3
- document in
- Optimize data structures
- generate updated
layout.jsonanddata.json
- generate updated
- Implement driver serialization/deserialization and writes tests
- Expose API for new generation
- Write
helper.zigand implementchoicesmethod- matching
Choicescode required in showdown
- matching
- Ensure fuzz tests pass
- Ensure integration tests pass
- Add
chance.zigandcalc.zigfiles with data types - Instrument code with
ChanceandCalccalls - Update unit tests with
expectProbabilityand ensure chance/calc overrides roundtrip - Implement
transitionsfunction
- add
Rollshelpers for new generation - include
transitionsfunction call in fuzz tests - determine
MAX_FRONTIER_SIZEand add constants to API
- Add support to the JS driver for
calcandchance
- update
layout.jsonto include offsets required
- Benchmark new generation
- Finalize documentation for generation
- Bump pinned
@pkmn/simversion inpackage.jsonand runnpm install - Run
npm run test:integration, update rolls and behavior of Pokémon Showdown tests insrc/test/showdown - Update Zig mechanics tests to match the updates applied to the integration tests
- Update Zig engine code to cause the updated mechanics tests to pass
- Update documentation to match new behavior/bugs
- Remove effects from blocklists and helpers if necessary
When debugging a specific regression test, remove the logic from the final catch block of the play function in integration.ts preventing replays from generating the logs/pkmn.html and logs/showdown.html UIs:
-if (!replay) {
const num = toBigInt(seed);
const stack = err.stack.replace(ANSI, '');
errors?.seeds.push(num);
errors?.stacks.push(stack);
try {
console.error('');
dump(
gen,
stack,
num,
rawInputLog,
frames,
partial,
);
} catch (e) {
console.error(e);
}
-}Modify patch.battle within showdown.ts:
battle: (battle: Battle, prng = false, debug = false) => {
+ const run = battle.runEvent.bind(battle);
+ battle.runEvent = (...args) => {
+ console.debug(args[0]);
+ return run(...args);
+ };
battle.trunc = battle.dex.trunc.bind(battle.dex);After you have determined the problematic effects which speed tie you can assign them a priority in patch.generation.
You can determine RNG advances in the engine by modifying the Gen56 RNG within rng.zig to log:
pub fn advance(self: *Gen56) void {
+ DEBUG(self.seed);
self.seed = 0x5D588B656C078965 *% self.seed +% 0x0000000000269EC3;
}Note that the numbers printed here will not match the seeds from Pokémon Showdown as they are in
little-endian instead of Pokémon Showdown's big-endian convention. Alternatively, if you wish to see
where the advances are occurring you can add debug prints to each of the Rolls at the bottom of
the appropriate mechanics.zig:
pub const Rolls = struct {
fn speedTie(battle: anytype, options: anytype) !bool {
+ DEBUG(@src());