The story so far: not sure if anybody noticed, but in current master we have a feature that allows making scripted maps without turning them into a map-mod. We can include an ini file multiplay/maps/<map>.ini and specify custom map rules in it. Documented only here.

Well, i just tried to use this and it works! But there was one bell that rings.

Right now there is quite a few stuff unhardcoded into rules.js, which is a good thing. For example, we have GUI button code, tileset-specific texture code, upgrades code, oil drum spawning code, command center code, victory conditions code.

Now suppose i want to make a custom rules script. Then i have a choice of

either running my script as "extra", alongside existing rules.js, and then i cannot override existing functions, eg. change victory conditions so that game didn't end when all enemy units are destroyed,

or running my script as "rules", replacing existing rules.js, and then my script would have to re-implement all the things, eg. i wanted to only change victory conditions, but i have to carry the whole GUI and textures and upgrades code along with my mod and update it whenever it changes in the base game.

This problem would not have existed if the base game's rules.js was composed of different files, for example:

Then my map automatically stays up to date whenever anything changes in the base game's rules.js, breaking only in very rare situations when more functionality is pushed into the base game's rules.js in a separate file i did not include yet. I think we can easily avoid that in minor releases.

Another idea is to add extra lines in the <map name>.ini file that have the include script functionality. That way you avoid the problem of missing include files when new files are added, since defaults are used for anything not specified. Eg the section could be

[scripts]
extra = path to script to run on every player in addition to rules.js; this is identical to challenge format
rules = path to script to run instead of standard rules.js on every player; this is identical to challenge format
upgrades = path to script to run to replace upgrade code, runs in the same context as rules.js
victory = path to script to run to replace victory conditions, runs in the same context as rules.js
gui = path script to run to replace GUI scripting, runs in the same context as rules.js
etc = and so on

We don't need to run each in a separate context (engine). We can use the same function that implements include('file.js') to load the script, which puts it into an existing context (the one used by rules.js).