My own .02$ (or perhaps a bit more)
This is completely dependent on the nature of the entities you’re trying to model and the game (in this case) itself. For instance I have only modelled a complex type of game state, and that was for a sequential, turn-based, limited “entities” type of game, a TCG.
In that case I believe modelling each game as a single genserver is what you want, because the actions are sequential and non-concurrent. The scope being limited, e.g. the resources (translated as keys and sections in a map) can’t grow indefinitely, also makes it a good fit for this type of structuring. Only one player at any given time is the “active” player, so holding everything in the state of one game genserver plays well with this.
I still want to be able to have the sequential message processing offered by process mailboxes, in this case genservers, so I use a that to hold state. This lets me have an entry point where to retrieve the current state, and then check for legality, and then proceed to transform the existing state into a new state reflecting the player action, bypassing more expensive calls to the DB. I end up dumping the state after each valid action into a db record, but usually the game is played out only through the genserver.
If on the other hand I was trying to model a complex world, where many different entities (regions, creatures, planets, wtv) can be interacted with by more than a player at the same time (say you have a planet that can be harvested for something by multiple players at the same time), then I would probably work on structuring those entities as independent servers. I would probably use named genservers (e.g. {:global, {:planet, “Some Cool Name”, game_id}}, {:global, {:player, player_id, game_id}}), that I could reconstruct whenever I needed to either retrieve state from the entity, mutate its state, or tell it to do something.
Then have these processes message each other accordingly. For instance a player does an action, “harvest”, in “Some Cool Name Planet”, by player_id, in game_id. I would pick up the genserver for the player, and send it a message for the corresponding action, in the corresponding game. It could check if it was valid, and if so, send then a message to the “planet entity” to receive the corresponding result of the action, then the “planet entity” could emit a message to the caller with “here you have 100 of iron”, adjust its state and stay there, or “there’s no more iron” (you would need to weight using calls, casting or messaging, although probably you would want messaging and build the remaining structure to be totally asynchronous).
Then the player genserver would take care of emitting this back to whatever needs (say the browser client). But not all entities should (as in they don’t benefit directly and will increase complexity without any added benefit) be modelled as processes. For instance if it’s a static inventory item you don’t want to model that as a process (unless its properties resemble that of an independent process). The reasons that should tip you over to structuring entities as genservers are relative to the type of interactions they should support and not any hard defined rule.
For instance if you have a single genserver that holds state of a world, and this world has many entities, let’s say planets to keep in line with the previous example, and there’s like 500 planets, and 500 players in this single game, this means that if you model it as a single genserver, any and each single interaction of any player on any planet would require the interaction to go through this single genserver, mutate it, etc, the same for data retrieval., even if they’re asking/messaging about totally different things, that in this case are only related because of they way you packed all the data in a single point and not because they’re naturally interdependent. This could become a bottleneck easily and as such probably a different structure would benefit it. But then you need to be more careful in structuring the game and entities, since they will need to work in tandem and does require a decent grasp on the semantics of message passing.