I’ve heard from a few people who are just getting started with entity component systems (ECS) that implementing logic for a turn-based game seems more complicated than it should be. I thought that seemed odd, but I just recently ran into this problem myself. While certainly not insurmountable, implementing turn-based logic in an ECS just doesn’t feel great. I think the reason is that no one likes to implement a loop via distributed state machines.

Consider this pseudo-code that you might expect for a turn-based game.

current player = first player

while game is not over:

actions = current player decides what to do

for action in actions:

player does action

current player = next player

That’s super simple! But wait, how would you do this in an ECS? Well… each of your players (or NPCs) is probably an entity. Then each action they could do is probably a component that’s only present while they’re doing that action. Then for a sequence of actions they’ll need another component. Oh and you’ll need a system for each of those components to run through the state machine of doing that action and presenting it to the player in a nice way. Each of those systems probably has to wait on some core subsystems to finish animations, physics updates, etc. Don’t even get me started on letting multiple players take their turns at the same time! You start to see how it’s state machines all the way down.

This isn’t totally surprising though. State machines are essential! They’re just not as nice as our higher-level abstractions that we used in the pseudo-code. Loops! Why can’t we loop like that in our ECS?