I'm currently writing some scripts for Bot Land. Bot Land is a real-time strategy game where instead of controlling your units with a mouse and keyboard, you write code to control your bots via an API, and then your bots go fight others' bots. If you're familiar with units in SC2, you can create bots that are similar to blink stalkers, siege tanks, medics, and ultralisks. (It's quite a fun game for software engineers, but that's outside the scope of this question.)
Bot control has three levels of increasing complexity: a default AI, a Scratch-like programming language, and a reduced set of JavaScript called BotLandScript. Although the built-in editor for BotLandScript is reasonable, you have to upload all your code as one single file with global top-level functions everywhere. Naturally, this starts getting painful after a while if your code starts to get long and different bots share the same functions.
To facilitate writing code for multiple bots, reduce the chance for unintentional errors when coding in bare JS, and increase my chances of beating other players, I set up the above TypeScript project to provide a common library as well as code for each of my bots. The current directory structure looks like approximately like the following:
lib/
bot.land.d.ts
common.ts
BlinkStalker/
BlinkStalker.ts
tsconfig.json
Artillery/
Artillery.ts
tsconfig.json
SmartMelee/
SmartMelee.ts
tsconfig.json
lib is the common code that is shared among bots, and provides TypeScript definitions for the (non-TS) Bot Land API. Each bot then gets its own folder, with one file containing the bot code and the other a boilerplate tsconfig.json:
{
"compilerOptions": {
"target": "es3",
"module": "none",
"sourceMap": false,
"outFile": "bot.js"
},
"files": [
"MissileKite.ts"
],
"include": [
"../lib/**/*"
]
}
When each tsconfig.json is built, it creates a corresponding bot.js that contains transpiled code from the bot itself as well as all the code in common.js. This setup is suboptimal for a few reasons, among others: it requires a lot of duplicate boilerplate, makes it hard to add new bots, includes a lot of unnecessary code for each bot, and requires each bot to be built separately.
However, based on my research so far, it doesn't seem like there's an easy way to do what I want. In particular, using the new tsc -b option and references does not work, because that requires the code to be modularized and Bot Land requires a single file with all functions defined at the top level.
What's the best way to achieve as many of the following as possible?
- No new boilerplate required to add a new bot (e.g. no
tsconfig.jsonper bot) - Use
importfor common functions to avoid outputting unused code, but then... - Still output all functions as one single file in Bot Land's specific format
- A single build step that produces multiple output files, one for each bot
- Bonus: integrating the build process with VS Code. There is a currently correspondingly boilerplate
tasks.jsonfor building each sub-project.
I vaguely surmise the answer probably involves something like Grunt in addition to tsc, but I don't know enough about that to be sure.


<root>/MissileKite.ts)bot.js?tsconfig.json. Transpiled bot files can be named anything, preferably the .js version of the original file. I have it set up this way now in the repo outputting tobuild/MissileKite.js.tsconfig-gas.jsonthe relevant thing to look at there?