I play in a fantastic sandbox tower-defence game Mindustry.
The cool thing is that you can use Game-embedded Processors blocks to control units. You can order them to build blocks, patrol the Map, surround the weakest enemy, heal friends and bring ammunition to turrets.
There are some examples how "programming" of such blocks looks like:
- https://www.youtube.com/watch?v=6v8Fnt1NEs8
- https://www.youtube.com/watch?v=ldkwofrGxyE
- https://www.youtube.com/watch?v=UFK5m6qKT6U
Some "documentation" can be found here:
- https://www.reddit.com/r/Mindustry/comments/ic9wrm/logic_in_60/
- https://mindustrygame.github.io/wiki/logic/3-variables/
- https://www.youtube.com/watch?v=EDfv_oM_TbE
The problem is that the Processor "language" is extremely primitive.
There is only one control statement: jump-to-line-if-statement-is-true.
There are no if/else statements, no for-loop, no functions and classes. So it's almost impossible to write anything complex using these instructions.
So my idea is to make my own simple compiler from "real" programming language (with if, else, for, function, struct/class) to these primitive instructions and then export it in the Game.
My first idea was to implement JVM or LLVM-IR VirtualMachine to run compiled bytecode in Mindustry, but it looks complex. There are a lot of instructions in these byte-codes.
Then I thought about implementing Lua or simplified Python interpreter, it looks possible but anyway it's a big work :-)
I'm curious about the easiest approach to do it :-) Maybe there are simplified JVM/LLVM-bytecode based on ~10 instructions or some example projects or running Lua/Python on Brainfuck or some limited architecture :-)
==== embedded cpu language ====
so control instructions set are:
- read - read data from PermanentStorage address to the variable
- write - write data from variable to PermanentStorage
- set - set variable data
- link - to get the i-th element from the array
- operator
op add result x y~result=x+y- set variable to the result of arifmethics operation + - * / < > % == min max etc - special variable
@counterwhich is a line to the executing line, you can also set the value of this variable to jump to any specific line jump cond lineNo- jump to linelineNoifcondis true
Also it's possible to do some sort of reusable procedures like
op add retAddr @counter 1 # Save where we will continue after the function returns by adding 1 to the counter
set @counter myFunc # Jump to the line representing myFunc
...
set @counter retAddr # Return to the line set earlier after the function is called