(I apologise for the length hereof, but I'd like to clarify a few things to give you solid footing.)
All digital computer simulations are actually discrete in nature. This includes everything from a non-interactive fluid simulation to an OS with its reactive UI, to a game. Just as the refresh rate of your monitor is a discrete 60 fps, so are the operations run on a processor, also discrete. We don't use analog computers (anymore?). So the very idea of truly "continuous" simulations is debatable at this time. Nevertheless I know that you are trying to draw a distinction between turn-based and real-time.
Let's focus on real-time first. I must pose the question, real-time at what level in the code? It matters what the core language/platform provides, and what 3rd party engine libraries you are using, because those things totally alter the development landscape. But let's start at the most basic level.
Loop-based/real-time: Discrete stepping via for/while
At the foundation of any real-time code is the idea that the program moves screen elements in discrete steps, enough times per second that in the average case it appears like something moving smoothly as in real life. This can be as simple as moving a sprite from left to right, across the screen. If you were to look at the source code of any high level engine like Unity or UE or whatever, you'd find, in native code (C, C++) this fundamental
while loop upon which the basic simulation occurs. Unity, for example, wraps this up under the hood, then you write your C# classes/methods which are called by that underlying native loop (UnityEngine). Most modern engines thus hide the loop from you, but you still know your logic is called every frame, even if you never get to see the loop code that does so. If you're using raw C and no libraries, you will on the other hand have to write that loop yourself, usually in
main(), i.e. the root of your C application, and everything else follows from there.
Event-based, Automated interpolations etc.
Now that those representations have been made...
Flight Simulator, Wolfenstein, and classic Pong are purely real-time simulations. There is no turn-based element here. They are typically as fine-grained as you can get, often using every one of 60 frames of 16.6ms period each in a second, to perform new logic. Of course, this doesn't mean they always do; they can also wait to do certain tasks only periodically, such as AI updates.
Angband, Nethack are a good example of a very simple turn-based game. These require no loop whatsoever in your code. User input comes from the keyboard which is handled by the OS, so you just let the OS notify your application and when a keyboard event occurs, and your functions otherwise know nothing about timing loops, and need not do so.
Battle Chess is a turn based game with real time animation, movement etc. Clearly, a loop is once again the basis for responding to user interaction. In this case it is also used for animation, gradual moves between tiles, special effects, etc. (possibly even for sound). But the difference here is that while such a game is fundamentally loop-based, it is preventing you from supplying user input for those periods when a move has just been made and your knight is fighting the enemy bishop: it just controls when & how you are allowed to supply input. Otherwise, it operates much like Pong, CoD etc.
World of Warcraft is another interesting example, being (I believe) (semi) turn-based on the server, and real-time on the client. One might also call this semi turn-based, although here we are getting into the more complex realm of distributed computing. It's certainly open to debate.
I want to say something more about such a system. We find constructs in many platforms / languages that do interpolations / animations over time, then fire an event on complete. What is crucial to understand here is that this is still loop-based under the hood, but from the end-developer's perspective, all you are doing is calling something like
pawn.InterpolateTo(x, y, 5) to cause the real-time stuff to start happening under the hood, and once it has smoothly moved your pawn to the target location, it fires off a callback that notifies your code that the interpolation has completed 5 seconds later and this then ties back into your own higher level logic. This is crucial to understand: It is event based - but there is still a loop in action at some lower level! It may even be that if this is your own code, that loop is exposed both for step-wise use and for specialised interpolation subsystems.
Loop-based / real-time systems are required for any reactive/interactive system. Event-based systems, while often appearing very different to real-time systems, are often fundamentally associate with, if not driven by loops, and co-exist alongside loops in various different forms.
For a Dwarf Fortress style game, I'd start with the following timing mechanism, see Fix your Timestep. Some here may be your code, some like the loop or vsync event mechanism may be 3rd party:
bool isRunning = true;
//assume milliseconds for all time* variables
int timeAccumulated = 0;
int timeStep = 1000; //period = 1000ms : frequency = 1fps
while (isRunning) //cpu
//...or don't use such a loop, and instead call tick() on vsync event.
timeDelta = SomeMethod(); //may be yours, system's, or library's
timeAccumulated += timeDelta; //see "Fix your Timestep"
if (timeAccumulated <= timeStep)
timeAccumulated -= timeStep;
turn(); //call all your custom turn logic here
//inputs must have immediate effect, so are not called in turn()...
isRunning = CheckKeyPressed("ESCAPE"); //for example
...So the outer block (
while) controls actions which must have an immediate response, like queuing up input for use in the next turn, handling loads etc. OTOH the inner block (
if) only allows this loop iteration to make game logic happen once a second has passed since the last turn was enacted.