Contents
In short: Game scripts build loops, scan collections, chain actions together and run mods. MKA Engine gives each of these a script limit counted in rounds, members, levels and instructions; only the game's manifest sets the limits, and mods cannot change them. When a limit is passed, the effect or evaluation that was running stops and the problem is logged; the engine does not crash, and the result is the same on every machine.
What happens without a limit?
Without a limit, a badly written loop that never ends would freeze the game even for a single player. In a multiplayer game it is worse: every machine runs the same step on its own, and one slow step holds everyone back. That is why the limit is part of the engine, not something left to the script's author.
Which limits exist?
| Limit | Default | When it is passed |
|---|---|---|
Loop (loop) | 1000 rounds per while | A constant count above this limit is a load error; at run time the effect stops and a script error is logged |
Scan (scan) | At most 1,000,000 collection members per evaluation | The evaluation stops; what was written before it stays |
Action depth (action_depth) | An action chain goes at most 8 levels deep | The chain stops and a script error is logged |
Mod fuel (mod_fuel) | 10,000,000 instructions per call into a wasm mod | The call stops and the mod is stopped |
Mod memory (mod_memory_mb) | 16 MB per wasm mod instance | The mod is stopped |
The limits are written in the game's project.bsm file with the limits key. If a mod writes this key, the engine reports it as a diagnostic. Limits change the result, so when one changes, the summary of the mod set changes too.
Why count and not seconds?
A time limit is the first solution that comes to mind. But the result of a job cut by time depends on the speed of the machine: a step left unfinished on a slow computer differs from a step completed on a fast one. So the limits are measured in rounds, members, levels and instructions; every machine stops at the same place.
The game's time target (step_target_ms) is a measuring target. bsm run compares the step time with it and writes the steps that exceed it; it never cuts a step.
How is an expensive script found?
There are two tools. bsm check warns about expensive patterns with a file, line and column: scans that visit every row on each step, and conditions of events that run often. The warning does not change the exit code; it is not a build error. bsm run --script-cost N writes, after the run's day lines, the N most expensive scripts with their event and action names, call counts and time.
What the tests checked
- When a loop passes its limit, the effect stops and a script error is logged; when a constant count is above the limit, the load gives an error.
- Nested scans stop at the budget and the writes made before that point remain.
- An action chain deeper than the limit gives one script error.
- The game's manifest sets the limits; when the mod fuel changes, the summary of the mod set changes.
bsm checkwarns about the expensive patterns with the expected text, and its exit code does not change.
What does it cost?
- A limit also cuts work that was meant to run: a loop longer than 1000 rounds cannot finish its work. The author has to shorten the loop, or narrow it with
countandmax. - The defaults are an estimate; if a measured need is higher, the game's limit is raised in its manifest.
- This diary has no measurement. It describes how the limits behave; it does not time how long a script takes.
Frequently asked questions
Where is a script limit set?
Only in the game's project.bsm file, with the limits key. A mod cannot change these limits.
Does the game crash when a loop limit is passed?
No. At run time the effect that holds the loop stops and a script error is logged. If a constant count is above the limit, the error is given while the game loads.
Why are limits counted in numbers and not seconds?
Time differs from machine to machine, and an unfinished step would be cut at a different place on each one. Counts of rounds, members, levels and instructions cut at the same place on every machine.
How do I find an expensive script?
bsm check warns about expensive patterns with the file, line and column. bsm run --script-cost N writes, after the run's day lines, the N most expensive scripts with their call counts and time.
Sources and records
Related diaries: Dev Diary #7, Mods in the engine.
If you have questions or suggestions about this diary, write to us through the contact page. For an overview of the engine, see the MKA Engine page; for all diaries, see the Developer Diaries list.
Sources and related docs
You may also like
- How is a strategy game's world map made?
For MKA Engine we built a 27,357-location world map of 1337 from real data: how terrain, rivers, straits, population and location borders were made.
- The road to a game engine
How we started MKA Engine: reading four games, treating determinism as law, moving phase by phase with measurements, and where we are now.