/blog/2024/02/20/time-management-system.gmi
There can be wrinkles with an energy system, notably to not run any new agents (until the next go-round) and also if two agents move at the same time, and the first kills the other, does the other still get to move? These issues can be worked around in various ways; like, maybe new agents that are spawned go onto a "new agents" list, and that list gets merged with the main list the next time around. Also agents could be collected, and those that run at the same instant could all be run through, possibly after sorting them somehow (rolling for initiative), or like in other games applying the results after everything act that instant.
C is notably lacking in "push agents to a list" and that sort of thing, so an alternative is the tricky use of "alive" and "newbie" flags: agents only are considered for action if they are alive. Next, all agents with zero energy have their update function run, but only if they are alive XOR newbie. After all agents have been gone through, the newbie flag is cleared, so that the next time around those previous newbies will be considered, have their energy number checked and decreased, etc.
A key point is that new agents get the alive and newbie flags set, and dead agents unset alive but do set newbie. They are new at being dead, see? This means agents only update if they are alive (but are not a newbie) are dead (but are new at being dead. All this complication works around one edge case where a new agent can be put into an array after the agent that spawned it, and we do not want that agent to be considered, as it's a newbie. Another edge case is where an agent kills some other agent next in the array that would have gotten a move at the same instant; we want that dead-but-has-an-action agent to have their last move. Now if the player dies the game is probably over, but one could see an unfairness if the player gets to move first, and always moves before something that moves at the exact same time they do.
A good way to work out these edge cases is with a notebook (graph paper is great) and consider things like
012345678 H.M..S...
where the hero "H" kills the mook-maker "M" which at that same instant or game turn (because the energy of "H" and "M" hit zero at the same time) spawned the snek "S", who must not be considered until the next loop. Then also consider what happens if "S" get put before "M" in the array, or "H" moves after "M", etc.
Including a "screw you, future me" comment as I suspect that sucker won't have a clue what is going on with the code. Probably this needs some like tests for all the different edge cases.
https://thrig.me/src/ministry-of-silly-vaults.git
P.S. there's some 7DRL challenge thing about to start? Downside: needs a chonky browser to access: