Page 1 of 1

Hearts tutorial: setSelectionMode() to restrict playable cards list doesn't work as coded

Posted: 16 August 2026, 23:42
by Reyvolution
The good news is I survived the rest of the tutorial and have a working game. :P However, I couldn't get the client-side control for setSelectionMode() to work correctly. I'm following the code samples in the Rule Enforcements section:

The server-side logic correctly determines playable cards in the current player's hand and throws an exception if they attempt to play a disallowed card. I have it working with a call to this.game.handStock.setSelectionMode("single"); to just limit selection to one card, but anytime I try to send in a 2nd parameter for selectable cards, the result is the full hand grayed out with nothing selectable.

Here's the code from the tutorial:

Code: Select all

onEnteringState(args, isCurrentPlayerActive) {
      console.log("Entering state: " + this.bga.states.currentStateName, args);

      this.bga.statusBar.setTitle(
        isCurrentPlayerActive
          ? _("${you} must play a card")
          : _("${actplayer} must play a card"),
      );

      switch (stateName) {
        case "PlayerTurn":
          if (isCurrentPlayerActive) {
            const playableCardsIds = args.playableCardsIds; // returned by the PlayerTurn::getArgs
            const allCards = this.game.handStock.getCards();
            const playableCards = allCards.filter(
              (card) => playableCardIds.includes(parseInt(card.id)) // never know if we get int or string, this method cares
            );
            this.game.handStock.setSelectionMode("single", playableCards);
          }
          break;
      }
    },
I already had to do some tweaks to this:
  • Explicitly set stateName to trigger the switch statement: var stateName = this.bga.states.currentStateName;
  • Loaded the playable cards list from args._private.playableCards instead of args.playableCardsIds since it seems to be nested one level down and have a slightly different name
  • Corrected typo playableCardIds vs playableCardsIds (extra 's')
Walking through the debugger, this gets me into the correct switch case and creates a local playableCardsIds array that holds a set of string values for the card IDs.

If I pass that array of strings as the 2nd param in setSelectionMode, I get all grayed-out cards.

If I pass an array of integers as a hack, I still get all grayed-out cards.

Is it supposed to take an array of a different object type? The provided code seems to just expect it to work with an array of strings.

Looking at the documentation for setSelectionMode I'm having trouble understanding what a valid format for CardsInput should be.

Any ideas why this keeps failing and setting 0 cards as selectable?

Re: Hearts tutorial: setSelectionMode() to restrict playable cards list doesn't work as coded

Posted: 17 August 2026, 11:09
by nalka
You have to send an array of cards (or at least objects with the property used in your manager's settings' getId) for it to work. For example, if you did

Code: Select all

playableCards = this.game.handStock.getCards();
it'd do the same as when you don't provide setSelectionMode's second parameter (all cards selectable)

In your snippet, if the local playableCardsIds contains strings, I think it fails because you send an int to .includes and includes surely does === instead of ==.

Re: Hearts tutorial: setSelectionMode() to restrict playable cards list doesn't work as coded

Posted: 18 August 2026, 00:19
by Reyvolution
Thank you, that's helpful! I can see that if I pass an array of 'card' objects it works. And I can get the 'filter' function to work by passing integers instead of strings.

I did this using map(parseInt) on my array of strings, and for some reason, some of the values will map to 'NaN' instead of an integer, even though all of the strings are just representing numeric IDs. For example, map(parseInt) given ['26', '32'] will create an array with values [26, NaN]. So that's the remaining reason why I can't reliably get this to show the correct "playable" cards. :?

Re: Hearts tutorial: setSelectionMode() to restrict playable cards list doesn't work as coded

Posted: 18 August 2026, 17:54
by Reyvolution
Well, I found a workaround: for some reason Number() works when parseInt() does not.

It's also possible to tighten up the switch case to use one fewer variable. Here's what I ended up using:

Code: Select all

switch (stateName) {
        case "PlayerTurn":
          if (isCurrentPlayerActive) {
            // Visually limits available cards and prevents clicking on non-playable cards. 
            // Philosophically, should the game show this constraint or let the player make a mistake and then explain?
            
            const allCards = this.game.handStock.getCards();
            const playableCardsInts = args._private.playableCards.map(Number);

            const playableCards = allCards.filter(
              (card) => playableCardsInts.includes(card.id) // Needs to be provided int values, not strings
            );
            this.game.handStock.setSelectionMode("single", playableCards);
          }
          break;
      }
Thanks again for the help thinking this one through! :)