Seats

Seats are basically informational containers for players at a table. Every player who is actually participating in the game at hand is in a seat. A seat will usually contain only one player acting alone, but can contain multiple players -- and it is this player-containing ability that makes them useful.

A seat acts as a single playing entity during a game -- you can think of all the players sharing a seat as a sort of ad-hoc team. For example, a game of chess will always involve exactly two seats, but the "black" seat might contain one player while the "white" one contains five, all working together to defeat black. This does not mean that the white seat gets to move five times for every black move, or anything of the sort; it simply means that five people happen to be at the controls of white's pieces, but they must all still follow chess rules and (somehow) agree, once per turn, on a move to make.

Simialrly, referees always address game-specific RPC requests to seats, not individual players. This really just means that a referee will mirror all of its outgoing RPC requests to every player in the seat it wishes to address.

Players at tables but not in seats are actually observers.

Seat properties

Identifier

Every seat has an id, a text string that serves as its primary identifier. This string is not internationalized; it does not have to be human-readable. (The UI file will have provisions for translating seat IDs to the player's language.) However, it's good practice to make the IDs minimally readable: "black" and "white" for a Chess game, for example.

The seat IDs are prescribed by the ruleset.

Players

Every seat contains zero or more players. The players in a seat act upon the game as a single, cohesive unit.

Using seats

Sitting down

A player can request to sit in a seat through the two different sit RPC requests -- one specifies a desired seat by name, and one does not. (In this latter case, the player is effectively asking the referee to assign it a new seat by itself.) The referee, if it agrees with the request, repsonds to the call with the name of the seat the player has taken, and then calls the player_sat request on all of the players at the table in order to announce the first player's new seat.

The stand and player_stood calls are used when a player chooses to forego the whole business of seats and become a mere observer once more.

These calls can be called only before a game begins, or while a game is suspended. Players' choosing their seats is considered a part of the table configuration process, and all players must agree to the seating setup (by signaling readiness) before the referee will start the game.

The exception is that, if a player leaves a seat (voluntarily or otherwise) after a game starts, the referee will continue to consider the departed player a part of that seat. That player can return to that one seat at any time afterwards. If the sole player in a seat leaves while a game is in progress, however, it introduces a potentially game-breaking situation. The referee enters user departure mode in an attempt to save the game, or at least exit cleanly.

Playing

All of the players in a seat have equal voice to the referee. In other words, the referee will assume that every RPC request it receives from a seated player speaks for every other player in the seat, and act appropriately.

The players should be aware of this, and perhaps work out a system amongst themselves for who is "driving" the seat to avoid seat-internal race conditions and other disagreements about moves made. The Volity protocol does not prescribe any way of choosing "team captains" or the like.

Rulesets and seats

A ruleset's RPC requests should always make reference to seats, not individual players. For example, the crazy eights ruleset defines a game.player_played_card(player, card) method, where the value of player is always the name of a seat. Actually, at the time of this writing, it doesn't. But it will as soon as I get around to tweaking it. --jmac

(Note that "player" can used as a synonym for "seat" when working at the ruleset level, just to keep things simple. For a ruleset, there simply is no distinction between seats and the actual players who make them up; each seat functions as a single player of the game.)

Benefits of multi-player seats

Player-specific observation

While any user standing at a table can observe all of the public information that the referee offers, that user will have to join a player in order to see any information private to that player. Upon doing so, that user can remain passive, letting the user(s) who were already in the role continue to actively play. This can be a great human-to-human teaching tool.

Ad-hoc Team play

Through multi-user players, any game can be turned into a competition between teams of players. (Not that we claim that every game actually works when played with teams.)

Advisor bots

An "advisor" bot could. This program would pay attention to the game from the player's perspective and offer advice.

Player Replacement

If a user has to leave (or vanishes unexpectedly) then another user, either human or bot, can take its place. Even though one user might be controlling the player at a time in this case, it will still duly noted as a shared player in the final game record.