-
Notifications
You must be signed in to change notification settings - Fork 1
Tutorial Modern Individuals
Give every monster a nature, ability, held item, IVs, EVs, gender, and a shiny flag -- as an opt-in wire upgrade that migrates existing saves deterministically.
1. Declare the wire in data/ruleset.json: {"mon_wire": 2}
2. Provide natures -- data/natures.json:
{
"natures": ["nature:bold", "nature:brave", "nature:calm"],
"effects": {"nature:brave": {"up": "atk", "down": "spd"}}
}(mon_wire: 2 without this file refuses at boot -- the wire names natures, so it needs the vocabulary. The modern recipe imports all 25 for you.)
3. That's it. Every existing save backfills on load -- one loud line reports the count -- and every field derives deterministically from the monster's own DNA: IVs from its DVs, gender from the species ratio, shininess from the classic DV pattern, its nature from a stable hash. Two loads agree; two link partners agree. Trades refuse cleanly at hello if the other copy speaks a different wire or nature table, instead of desyncing mid-battle.
Species gain an optional gender_ratio byte (0 = all male ... 254 = all female, absent = genderless), moves an optional category (physical/special/status), and the ruleset config a shiny_odds knob. Nothing about battle math changes until a modern formulas provider engages -- declaring the wire alone is provably inert (that's a release gate).
If you bind stat kernels (stat_calc2 for the modern formula, stat_base_scale for a per-individual pre-scale), you can assert what the engine actually computes -- no inference, no reimplementation. Write a fixture:
{"species": "snorlax", "level": 50,
"ivs": {"hp": 31, "atk": 31, "def": 31, "spd": 31, "spc": 31},
"evs": {"hp": 252, "atk": 252}, "nature": "brave",
"ext": {"grade": 4}}and run:
python tools/run.py --project=path/to/yourgame --statread=fixture.jsonEvery input is pinned (absent fields take the pipeline's documented defaults: DV 0, IV = DV*2, EV 0, stat exp 0, neutral nature; a sexp bag pins Gen-1 stat experience for faithful-formula vectors), and the output is one line per stat -- base / prescale / final -- where prescale is your stat_base_scale's answer and final is the whole pipeline's. The same fixture always prints the same bytes, so a reference oracle's test vectors drop straight in as acceptance fixtures. A typo'd species, stat key, or nature, an ext field you never declared in mon_fields, or an ext value outside its declared schema fragment refuses loudly instead of computing something you didn't ask about.
Reading EVs is only half an economy — ev_gain is the other half. Declare a
yield on any species and bind the kernel, and every way a mon earns stat
experience routes through your script instead (battles and vitamins); the
Gen-1 sexp pool freezes while it's bound, so there is never double
bookkeeping.
In a species record:
"ev_yield": {"hp": 0, "atk": 2, "def": 0, "spd": 1, "spc": 0}In data/ruleset.json:
"formula_scripts": {"ev_gain": "script:ev_award"}And the script — this one is the classic 252-per-stat / 510-total rule, but the point is that your kernel owns every cap, because the award path is the only place a total-spread rule can live:
let total = ev_hp + ev_atk + ev_def + ev_spd + ev_spc
let room = 510 - total
if room <= 0 { return true }
out("atk", ev_atk + yield_atk)
out("spd", ev_spd + yield_spd)
return true
Your script sees the current spread (ev_hp …), the defeated species' declared
yield (yield_hp …, zeros if undeclared), its base stats (base_hp …), the
exp-split participants, and a provenance string — "battle",
"battle:expall" under EXP.ALL, or "vitamin:atk"-style for vitamins (a +10
yield to that stat). out() only the stats you change; outing nothing refuses
the award (a refused vitamin is "it won't have any effect" and the item is
kept). No randomness is allowed in or needed by the kernel, which is what keeps
link battles and trades in lockstep for free. Verify the whole economy with
--statread fixtures before and after an award, and run
python tools/run.py --evgaintest to see the engine's own eleven checks.
Monworks: MIT code · CC0 samples · everything pictured is original content. The faithful Pokémon Red build derives from your own local pokered clone and is never distributed. Pokémon is © Nintendo/Creatures/GAME FREAK; this is an unaffiliated fan engineering project.
Play
Create
Tutorials
- Writing Text
- Battle Backdrops
- Colors and Palettes
- Display Filters and Shaders
- Widescreen and Scaling
- Quality-of-Life Knobs
- Overlays (Recipes)
- Abilities & Battle Hooks
- Modern Individuals
- Per-Individual Fields
- Field Effects
- The Modern Ruleset
- Per-Save Rulesets
- Six Stats
- The Clock
- Conditioned Bindings
- Day and Night
- Sprite Variants
- Overworld Spawns
- Language Packs
- Set-Piece Battles & Narration
- Run a Server
- Join a Server
Elsewhere