Loop structure

My question is generic since I’m a totally noob and trying to understand how these games are structured. But I’m curious to know how Cataclysm handles this.

My problem is that I have a tendency to create loop branches to handle different program flows. So while I have a continuous loop normally, whenever combat comes up the main loop is halted and the game enters a sub-loop for combat. And whenever combat is over the control is returned to the standard loop.

So for example if I now implement some inventory system I’d have to spawn a new loop that handles inventory and when all it’s done control returns once again to the main loop.

This obviously is not the proper way to do things.

Especially, I can’t figure out a simple problem: it’s all fine if game logic in my main loop has to always do the same thing and be refreshed completely for every new cycle. So you look at the keyboard events, handle them, and then reiterate. BUT WHAT IF some event that is triggered creates influences on more than a single cycle/frame?

Say that an attack has to trigger some visual effect, and so the display is affected for more than a single frame, and the player can’t issue new commands in that time frame. This all means that this event has to “rig” the main loop for more than 1 cycle. How do you handle that properly? The non-proper but intuitive way I’m using is about creating sub-loops within the main loop. I know this is not how I SHOULD handle stuff.

What happens in regards to main loop and program flow, in Cataclysm, when you enter the inventory screen, for example?

[quote=“HRose, post:1, topic:2556”]My question is generic since I’m a totally noob and trying to understand how these games are structured. But I’m curious to know how Cataclysm handles this.

My problem is that I have a tendency to create loop branches to handle different program flows. So while I have a continuous loop normally, whenever combat comes up the main loop is halted and the game enters a sub-loop for combat. And whenever combat is over the control is returned to the standard loop.

So for example if I now implement some inventory system I’d have to spawn a new loop that handles inventory and when all it’s done control returns once again to the main loop.

This obviously is not the proper way to do things.[/quote]
Obviously, this is a terrible idea… <<
.
.
.
This is precisely what Cataclysm does. ;
;

[quote=“HRose, post:1, topic:2556”]Especially, I can’t figure out a simple problem: it’s all fine if game logic in my main loop has to always do the same thing and be refreshed completely for every new cycle. So you look at the keyboard events, handle them, and then reiterate. BUT WHAT IF some event that is triggered creates influences on more than a single cycle/frame?

Say that an attack has to trigger some visual effect, and so the display is affected for more than a single frame, and the player can’t issue new commands in that time frame. This all means that this event has to “rig” the main loop for more than 1 cycle. How do you handle that properly? The non-proper but intuitive way I’m using is about creating sub-loops within the main loop. I know this is not how I SHOULD handle stuff.

[quote=“HRose, post:1, topic:2556”]I’m not totally sure that an independent loop isn’t the proper way to do an animated sequence like this, at least in curses. If you DO want to run it through the main loop, you’d probably want to have some infrastructure for diverting control flow away from the usual keyboard input, meaning either a flag or possibly an event queue that you check before checking keyboard input.

A system that uses this model in Cataclysm is “long work”, such as crafting, waiting, sleeping, etc, what happens there is when you start crafting an item, we bundle up all your decisions into a structure called an “activity” that says what you’re making, how long it will take, etc… and put it on a “actions” queue attached to the player. Then we set player moves to 0 because that’s how we exit the player action loop. The game processes the rest of the turn (NPC, monster turns, field updates, etc) and loops around to player actions. The first thing we do is check the actions queue, and if there’s an action on it, we process it, which will generally result in zeroing out the player’s moves, then when we get to the player input loop, it skips it because we’re out of moves. (actually it doesn’t because it checks for a cancel key, but it won’t accept anything else)[/quote]
What happens in regards to main loop and program flow, in Cataclysm, when you enter the inventory screen, for example?[/quote]
I outlined a crafting session above, which works more or less how it should, but inventory handling and similar we handle inline, but we shouldn’t.
What we SHOULD do is use the same framework, where if you chose an action that requires further input, it sticks the details of the action on a queue and exists to the main loop, where it can go to a dedicated part of the main loop, possibly triggering screen redraws and such as its drawing menus and then restoring the map.

The real bad guy as far as this is concerned is how we handle targeting, when selecting a target to shoot at or throw something at, it has a completely independent loop and display that it enters and stays in until you pick your target, it replicates some of the drawing logic from the main loop since it has to draw things on top of the map, and we’ve had issues where it didn’t work the same and caused problems.
Now I’m looking at setting it up with a system where you can spend moves to steady your aim, which might mean your turn ending while you’re doing it, so it has to store up all its state, exit to the main loop, handle a turn of activities, and re-enter the menu. Now that all works surprisingly well, but it shouldn’t be necessary at all, and the duplicated draw code is the real problem.

I think there’s a point where stuff like this just needs to be handled inline though, such as “really step on that landmine? Y/N”, because if every point of input like that exits back to the main loop, it seems like you’re going to have a mess of events piling up that will be more trouble than what you’re gaining by centralizing control flow, especially since that splits a lot of actions into an “upper half” and “lower half”, which makes the code very hard to read. We have a problem like that with gun reloading actually, it bounces around between about 5 different methods, with some of them happening when you issue the command, and some of them triggering from the slow work system I outlined above. It makes everything much harder to follow.

It’s kinda encouraging that the problems I’m finding aren’t that trivial, after all. I guess the blame in this case is more on Whales than you :wink:

In my case I’m using libtcod, so the use of a continue loop was “forced” on me because I wanted to use the mouse, and the mouse in libtcod only works if it’s sampled frequently.

Otherwise I think I would have done with “waiting for command” for much longer.

To be fair, this interactivity-vs-clarity is a really hard problem in general. It’s not that bad when you have a single event loop and a single input triggers a single event, but when you start layering in multi-step command entry with interdependencies and dependencies on game state (for example craft->select item->select ingredients) it starts getting hairy really fast, and when you have an event loop that has to be fed (for example if you’re tracking mouse events) it becomes even more complex.

A general approach I’d like to move Cataclysm toward is having an input subsystem that handles all the inputs and menu like activity, which gathers any resources needed to make decisions like what items to use with a given action, etc, and then dispatches an action as a self-contained unit. Currently this logic is scattered throughout the code, and is cited as a major inpediment to new contributors being aboe to understand the code. Unfortunatly it’s a rather gnarly knot to unwind, so it’s going to take a while.

So basically, if I may add a question, you’re trying to ensure the input is somehow snatched by _listen, and so stays off the behavior of the game - occurrences, NPCs, hazards and wholegoods introduced?
I always thought of conventional games to have a default sort of handler of things like keypresses, with different procedures loaded for menus and choices, respectfully or at-once (it really differs).
If you’ve looked up .net and C#, all menus call upon extensions that are fairly friendly to either combine or just, well, edit. Just saying, if you had a mouse pointer wrapped in code it’d have to be in main as its behavior isn’t segmented, stroke-like - but smooth and movement-dependent.
I don’t really know what kinds of different handling as of ‘overlay’ Cpp has for mouse pointer; the common thing would probably be the x-y position, but I do not know of much more. Sorry if any of this got you confused in one way or another.

The main driving force for having an input layer is remapping keys, if you hard-code which ASCII character does what in each menu, and enumerate all the keys that do various things in those contexts, it’s fairly straightforward, but that’s not a good solution for i18n and different input devices, where different people have different keys available.

In order to handle key remapping in a clean way, you need to intercept all input and remap it in a table of some kind, and offer a context-aware menu that the user can use to remap keys. Or at least that’s one approach. CIB is prototyping this right now, and it’s looking really good so far.

The key inputs get remapped to internal representations, like “look around” or “move north” instead of ‘;’ or ‘k’.

Normal windowing toolkits have a lot of this processing handled through built-in inpu processing loops, event queues, and menu-specific event-handling code, but we aren’t using one, so we get to implement it all ourselves.

I think I understand what you’re guys doing; defining actions that could be employed for each and every segment the game has to offer, and sorting code so if another handler method is introduced, it will be more relevant and less clogged in main {}.
Already loving it, also - you can have a distinctful set for a roguelike type, with deviations (for example, when entering deep water with various depths for bottom tiles) for each and every phase of the game, overlapping each other with ease. Or maybe even the old style a=thrust/z=slow, mouse pointer for rotation, and l_button for diving in whilst r_button is for diving out.