Page 1 of 2

Implementing team settings: your go!

Posted: 18 November 2019, 19:16
by Woodruff
Hi everybody :)

(sorry that message is very long but if you are willing to read the beginning you will soon understand why ;) )

I am struggling with something which has pissed me of for a long time: setting teams in a game I developed and which is now already in production. This game is the Toc.
Why is it such a trouble? Because I implemented it on Studio and everything works fine for each test I have run (no bug + teams set correctly), whereas on the mainsite, when I activate that feature, bugs come very soon and very often in the very beginning of the game: https://boardgamearena.com/bug?id=13713. That's it, it is a bug I do not manage to reproduce on Studio.

I have changed my approach and my code many times, but I am still stuck and I think I am missing the same thing all along. In order to eventually solve this problem once and for all, I think it would be wise to ask YOU how you would do that from scratch, instead of doing bug hunting for ever (which is difficult since I cannot reproduce that bug).
So if you are willing to propose your method and even your code I think that would help me a lot. No knowledge on the game itself is needed, I now give every details of what I want functionnally.

Situation
This is a game for 2 to 6 players. When there are 4 or 6 players, the admin can set the team mode (2 vs 2 with 4 players and 2 vs 2 vs 2 with 6). This part is OK., and we don't care about free-for-all games.
Now, I have set the game options to give the admin the possibility to set fixed teams (according to the position of the player in the table lobby) or leave them random or even do a combination of both (for example: in 2 vs 2 vs 2, two players in particular want to play together, leaving the four remaining spots random).
You can open a new table to see what these options are: https://boardgamearena.com/gamepanel?game=toc
One option for each teammate to set. In 4 players: Team A - player / Team A - teammate / Team B - player / Team B - teammate. And one Team C so two more options to set Team C. All of these can be set on Random (this is the default) or set on a particular player based on its order in the table (1 to 4 or 1 to 6 depending of the case).

Constraints
All teammates must sit in front of each other. That means in a 4 player game, if one teammate is now playing, an opponent will play after that, then the other teammate, then the other opponent. With 6 players, 2 opponents will play after the current player before his teammate plays.
This constraint must be honoured in the creation and the game and reflected in the turn order which is fixed then (so visible in the succession of player panels).
However, the position of the players in the team must remain random and also the order of the teams to play.
For example, if the settings are those: Team A : player 1, Team A : player 2, Team B : player 3, Team C : player 4, there is no reason that the succession in play is 1 > 3 > 2 > 4. Other valid examples are 4 > 1 > 2 > 3 or 2 > 3 > 1 > 4 for instance.
In a 6 player game, there is no reason that team A plays first then team B then team C, the succession can be A > B > C or B > A > C and the team who begins is also random.

Variables in code
  • One global variable, game_type, which is set to 2 in a 2 vs 2 game, and to 3 in a 2 vs 2 vs 2 player game. (1 is for free-for-all but we don't care)
  • A set of 4 or 6 global variables used for team settings. Their value is 0 if that teammate is random, or indicates a player based on his order (player_table_no) in the table lobby. A control ensures that no player can appear twice.
    • For a 2 vs 2 game, these variables are
      • team_A1_2vs2
      • team_A2_2vs2
      • team_B1_2vs2
      • team_B2_2vs2
    • For a 2 vs 2 vs 2 game:
      • team_A1_2vs2vs2
      • team_A2_2vs2vs2
      • team_B1_2vs2vs2
      • team_B2_2vs2vs2
      • team_C1_2vs2vs2
      • team_C2_2vs2vs2
      (depending on the value of game_type, only one set is used and the other is not)
  • The array $players is the associative array that stores all players to be written in the database. As you may know, it is passed as a parameter to the self::setupNewGame fonction. It has been shuffled by the BGA framework first. The keys are the player_id, the values stores the informations about the player, and specifically its order in the table lobby: player_table_no. This is that value which is referenced by the team settings when it is not set to random.
  • A function self::rearrangePlayersForTeams, which is called once in the game setup, and with $players as a parameter. Its sole purpose is to change the order of the $player array in a way that is valid according to the team settings described above. THIS is the function I would like you to propose a code for, since my version is buggy. It is called with that line of code inside self::setupNewGame:

    Code: Select all

    $players = self::rearrangePlayersForTeams($players, $player_table_orders_by_team);
    (That function is called if and only if :
    • This is really a team game (game_typeequals 2 or 3)
    • At least two options to define the teammates are not set on random (ie not zero). Indeed, if there is none or only one player specified, there is no point in shuffling the array since it has already be done before by the BGA framework and the result is valid.
    but there is no need to worry about this, this is already done sooner in the code).

Goal
Write your valid version of self::rearrangePlayersForTeams($players). I intentionnaly give no details about what I know about the bug of my version because I rather would like to see what come out from scratch, without a bias point of view like mine. I will give details later if that approach does not work.

Thanks really, really a lot if you have time to look at this. Don't hesitate to ask me questions if I am not clear.
That's a big thing I know, but I cannot tell you all valuable your help with that can be :)
I would not have posted that monster if I had not run out of other options...

Cheers,
Woodruff

Re: Implementing team settings: your go!

Posted: 18 November 2019, 19:56
by RicardoRix
I think I would not rearrange the $players array at all.

Given though this would need to be stored, the best situation would probably be best to add a new DB field(s) to the player table, maybe 'player_team'.
For the order: player_order: 1 - 6.
And possibly next player$id if I thought that would come in handy. [$this->gamestate->changeActivePlayer($nextPlayerId);]

The most problematic things seems to be that the table creator will not set the options correctly, and likely duplicate players.
The easy way of getting round this would be just to take the table_order as is and always join 1 and 2, 3 and 4, 5 and 6.
If the settings aren't set correctly then I would leave the setting that player altogether. And then re go around setting each player left into the next available slot, or is it possible to throw an exception and stop the game being created at all..?

Re: Implementing team settings: your go!

Posted: 18 November 2019, 20:42
by Jest Phulin
Player order does not need to be set at table creation. See Hawaii for player order changing each round.

With that in mind, setting teams may be options for table setup (first two to sign up are on one team, next two on next, etc.), or you could even implement the first "move" of the game to be choose teams. If teams are to be randomized, this move is done automatically.

Once teams are chosen, it should be fairly easy to then set player order how you want: Choose a random team that hasn't been chosen, choose a player that hasn't been chosen. They are player 1. Repeat until out of teams. Then, go through team order, assigning the other player to 'next player' status.

Re: Implementing team settings: your go!

Posted: 19 November 2019, 00:59
by DrKarotte
Like RicardoRix I would not mess with the original table and player settings but add the values you need. If you add some fields to the players database (like a team indicator, and a value storing the next player in playing order after setting your teams) you probably won't need the globals. You would have to active the next player using this value instead of using the standard functions.

The real playing order would not reflect the original order on which the game still is based (seen in the order of the player panels), but this would not be a real problem.

Concerning the team setup: It is possible to get the id of the player who made the table setup (admin), you could make him active in the beginning and start with a setup state; this could offer a table with the names of all players and some checkboxes (team A, team B, team C), and after submitting this there could be proper validity checks. If there are random teams or none at all this state could be skipped or done automatically.

Re: Implementing team settings: your go!

Posted: 19 November 2019, 11:50
by Woodruff
Hi thanks for your answers!
  • I get that it would be better to introduce new Db fields to manage the new player order. There is already a field that indicates the team (player_team), it would require to introduce a next_player_id field. However:
    • This would require to change the order of player panels in JS, no?
    • What make you think it is not safe to change the order of the $players array in setup?
  • You also pinpoint the fact that setting up the fields could be done after the game setup, in a dedicated state. Why would be the advantages of doing that, I have troubles to understand that right now...
Thanks, I am confident I progress in my reflexion with your help, that's cool :)

Re: Implementing team settings: your go!

Posted: 19 November 2019, 12:36
by fafa-fr
Woodruff wrote: This would require to change the order of player panels in JS, no?
I don't think that it is required that the order of player panels follows playing turn order. But it could be more convenient for players, especially if there are useful informations for gameplay in these panels (i.e. if you often have to look at them). And I think it's not a problem to rearrange the order of these panels in js setup(). Maybe greg or emmanuel could confirm.

Re: Implementing team settings: your go!

Posted: 19 November 2019, 16:17
by RicardoRix
The player panels tend to move around depending upon page width.

You could colour the background according to team, or place a 'TEAM X' label inside.

If you were to rewrite the player table, then I would only think you need to read all the data first before then committing the UPDATE changes.
And be careful not to duplicate any identity key.

Re: Implementing team settings: your go!

Posted: 19 November 2019, 18:38
by Woodruff
This sounds more complicated and susceptible to bug to rewrite in Db than trying to reorganise the player array before.
Can you see any benefit in doing that?

Re: Implementing team settings: your go!

Posted: 19 November 2019, 20:18
by RicardoRix
Oh right, I'm not sure. I am only speculating on how you get to re-arrange the player panels (and / or natural turn order) to the order you like. Any array is just temporarily in memory for your own benefit. Were you planning on calling this rearrangePlayersForTeams function each and every server call?

All comments are just 'food for thought' rather than real advice, ultimately it's your responsibility. There's always more than one way to skin the cat, and everyone has their own preferred way of doing things. Also you have the benefit of knowing exactly what you're trying to fix, while we're all just guessing.

Re: Implementing team settings: your go!

Posted: 19 November 2019, 21:34
by DrKarotte
Unless you fully understand how the frameworks works, I would try to avoid to change something of the initial data, e.g. the playing order or the reserved globals. On the other hand: you may try some changes in a studio project. I have never tried what happens when I manually change the values of "player_no". Maybe it is possible to change the order, but it can also happen that there are some other values set according to the initial values which cause something like undefined offset later.

The strange thing is, if I got that right, that the whole thing works flawlessly in the studio, but turns out buggy on prod?