Although i was prpgramming in pretty much every higher level language since the early 90s I have very much switched to PLC programming in the past years. With that change i had to unlearn a lot of stuff i have done in the years before and completely rethink testing and verifying.
Since most people here are not familiar with PLC/RealTime programming, even though hardware like the Arduino and the countless ESP boards might have brought that to hobbyists.. but thanks to the Arduino team this hardware can, and in most circumstances is, programmed like any piece of software for the PC.
Anyway... in real time programming your code has to follow a "flow" from start to finish. You normally dont react to events, you basically have no parallelism and whatever you do the code should be deterministic. That means - if you ever have to stop the execution of the code you have to be able to fully understand how you got to that point and predict how it goes on from there. Therefore a lot of programs for PLCs are built in the simple sceme (Pseudocode)
void main()
{
int[] all_my_variables;
while(true){
readallinputs();
dothelogic();
writealloutputs();
}
}
There is very little branching. Most of code is organised into step sequences. Branching is most of time not in use at all.
So..
Why do i write this?
In normal programming people tend to use very little testing. Unit tests are pretty common these days and using languages like my beloved GO make it very easy to use them.. but there is only so much unit testing can do for you. You can check if certain functions return exactly the result you expect for a given set of parameters and while that is sufficient to test that single function your program may still misbehave because the expected result may not be what you need as parameter for the next function and so on.. Dont get me wrong. I love unit testing.. as far as i can tell RoaK has basically no function that is not unit tested but this is not an overall picture.
To those who still read this post.. PLC programming is mostly dont to program physical machines.. and now imagine a large manipulator - a crane - strong enough to lift a few metric tons of steel and concrete while moving 50mm/s and people working close by. You dont want to rely on unit tests only if you could endanger people. if you divide by 0 in a program you end up crashing it. If you divide by 0 on a plc and the plc is crashing you may end up destroying costly equipment and harming real humans. As a nice reminder: The unfortunate and costly fireworks at the first launch auf Ariane5 was basically a variable casting error..
So how can you test a program end-to-end without the fear of doing something very wrong? You simulate it.
For our machines we have simulation tools to fully simulate all sensors and actors and make sure that with any given set varables the code executes the way you want.
Why would that be of interest to game programming?
In a way we can automate quite a lot in our games as well.. we can simulate inputs and see the outcomes on screen. For RoaK i use this extensively. I have a hand full of maps, of scenes i build on the "Green acres" and saved them in a known state. As it is pretty simple to do so on a city builder i have also added a rigged camera that moves along a known path and toggle actions as if i was using my mouse. That way i can precisely see an ingame scene and see if i have introduced game breaking changes. That is why my "PreAlpha" Videos always show basically the same sequence.. just with changing content. Sometimes there are more workbenches, sometimes you will notice lighting changes and so on..
But if i cant make it through this short sequence because some major screwup happens I know something bad has happened in the code.
I know that was a lot of writing for a simple statement on how i test my stuff.. but since this board should not have all too many PLC programmers i wanted to share the reasoning behind my design choices and maybe someone here might find it enlightening and useful that there is this approach.
Some evolution of the same sequence:
0.1.0:
0.2.0:
0.2.5: