Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transitioning between stages #447

Closed
nicolodavis opened this issue Aug 28, 2019 · 8 comments · Fixed by #458
Closed

transitioning between stages #447

nicolodavis opened this issue Aug 28, 2019 · 8 comments · Fixed by #458
Labels

Comments

@nicolodavis
Copy link
Member

nicolodavis commented Aug 28, 2019

In the phases-overhaul branch, the only way to manipulate a player's stage is the setActivePlayers event.

For example, to set the current player's stage to 'A', you can do:

ctx.events.setActivePlayers({ currentPlayer: 'A' });

However, this has two problems:

  1. It clobbers the state in activePlayers (if some other player was in there, they would be removed).

  2. It cannot set the stage of the player that made the move (it only works on the "current player").

We could change the semantics of setActivePlayers to overcome these, or split it into multiple events that do different things.

@delucis
Copy link
Member

delucis commented Aug 28, 2019

IIRC isn't there the possibility to pass a value directly?

setActivePlayers({
  value: {
    ...ctx.activePlayers,
    [playerID]: 'stage'
  }
})

That said, obvious candidates would include:

  • addActivePlayer
  • removeActivePlayer

(Side note: keep meaning to write a test for this, but I think I saw that setActivePlayers({ others: 'stage’ }) was preserving currentPlayer if it was already in activePlayers)

@nicolodavis
Copy link
Member Author

Another idea that's been growing on me is to have a simple endStage event that's analogous to endPhase.

All this does is that it removes the player from activePlayers.

However, if the stage config contains a next, or if next is passed to endStage, then we just take the player to that stage instead. This is exactly how phases work and I think having the same concept for stages will reduce the cognitive overhead of having to grok different APIs.

I think if we arrange things so that we just have endTurn, endPhase, endStage and setActivePlayers, that would be a nice elegant API.

@delucis
Copy link
Member

delucis commented Sep 10, 2019

Now that I’m working on moveLimit (#452), I think setStage would probably also need a way to set a moveLimit, perhaps via a second options argument:

setStage('main', { moveLimit: 2 })

Otherwise users would only be able to set move limits inside setActivePlayers.

@nicolodavis
Copy link
Member Author

nicolodavis commented Sep 10, 2019 via email

@nicolodavis
Copy link
Member Author

I think of setStage as a simple "get me to this other stage". I'd prefer to have it as minimal as possible. I'm open to adding more options to it in the future, but let's wait and see how people use the new API first.

setActivePlayers can be the swiss-army knife with all the fancy options.

@delucis
Copy link
Member

delucis commented Sep 11, 2019

@nicolodavis Totally understand.

I’ve finished work on moveLimit in #452. My concern was that with this implementation we reset move counts when calling setActivePlayers, so a scenario where one player’s stage changes but the others stay the same would not currently support move limits for that one player. Otherwise, you’d have to use setActivePlayers and do something like moveLimit - numMoves for each other player, which would be pretty complicated.

@delucis
Copy link
Member

delucis commented Sep 11, 2019

An example of just how complicated that would be:

const turn = {
  activePlayers: {
    all: true,
    moveLimit: 4,
  },

  moves: {
    move: (G, ctx) => {},

    changeStage: (G, ctx) => {
      ctx.events.setActivePlayers({
        value: {
          ...ctx.activePlayers,
          [ctx.playerID]: 'newStage',
        },
        moveLimit: {
          value: {
            ...Object.keys(ctx._activePlayersMoveLimit).reduce((obj, key) => {
              obj[key] =
                ctx._activePlayersMoveLimit[key] -
                ctx._activePlayersNumMoves[key];
              return obj;
            }, {}),
            [ctx.playerID]: 2,
          },
        },
      });
    },
  },
};

Whereas setStage could support the same scenario like this:

const turn = {
  activePlayers: {
    all: true,
    moveLimit: 4,
  },

  moves: {
    move: (G, ctx) => {},

    changeStage: (G, ctx) => {
      ctx.events.setStage('newStage', { moveLimit: 2 });
    },
  },
};

@nicolodavis
Copy link
Member Author

OK, you've convinced me :)

Let's also support an additional argument in setStage that accepts an object that can carry things like moveLimit etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants