boardgameio / boardgame.io

State Management and Multiplayer Networking for Turn-Based Games
https://boardgame.io
MIT License
10.04k stars 709 forks source link

Hooks for stages? #1020

Open pardahlman opened 3 years ago

pardahlman commented 3 years ago

I'm trying to migrate my game's turns from using phases and turns to using turn and stages. I'm struggling with the following state transitions:

In the main stage, all players are active until they either overreach (checked by onMove hook) or they actively do the move pass that ends the stage in a controlled way:

pass: (G, ctx) => ctx.events.endStage()

Here's my first issue: the ctx to the onMove hook does not reflect changes in active players. This means that the game can't detect if the last active player did the pass move, or any other move that did not evict them from the main stage. I thought that perhaps I could use the nested next option when settingActivePlayer for the main stage, but...

When the main stage is over, eligible players are moved to the bonus stage. Who gets to enter this stage is based based on their performance in the main stage. Theoretically, all or none of the players should enter this stage. If no players should enter, all players are moved to the end stage.

Some wild ideas:

Not sure if any of the above is desired or doable, but a combination of these would solve my issues. I'm also more than happy for other approaches that does not involve changes in the framework 🙂

delucis commented 3 years ago

Yes, this has come up before — see the feature request in #608 and also #561, which I see now, was actually your own proposal last year!

The one thing we probably wouldn’t want to do is to update activePlayers between a move and onMove, but the hooks are a possibility. See those linked issues for some thoughts around this.

pardahlman commented 3 years ago

Thanks as always for a quick and precise answer 🙏 I've read up on the issues you linked (including mine 😅 ), and think that there are indeed things to consider to get an easy-to-understand API. One suggestion is to implement the following:

onBegin: called for each player entering a stage endIf: predicate that if returns true ends the stage for player with corresponding playerID onEnd: called for each player ending a stage

If we have all of the above, it feels stage to leave out onMove. Would this override onMove, similar to on how moves can be overridden? Or should they be also be called. In which order, in that case.

(I think that onBegin and endIf would suffice for me, as I would set the next stage to bonus for everyone, and have the bonus stage's onBegin end the stage for non-eligible players)