Game architecture and design strategy for a multiplayer card game

John Rasch picture John Rasch · Mar 3, 2009 · Viewed 10.4k times · Source

I am relatively new to game development so I decided I wanted to create a hobby project from scratch for both experience and entertainment. The specific game is similar to poker known as Three Card Brag. The game is played in the movie Lock, Stock and Two Smoking Barrels.

I have been reading up on some of the topics on SO regarding game development, though mostly this question. This has helped revamp the original way I was creating the objects.

One particular problem I am having is defining game state. My initial approach was to separate everything (e.g. keeping chip stacks inside a Player class) but after reading the responses to the question I mentioned previously, it seems as though all possible states of the game should be maintained within a GameState object. What I came up with is essentially this:

abstract class CardGameState
{
    protected List<Player> _Players;
    protected Player _CurrentPlayer;
    protected Dictionary<Player, int> _Chips;
    protected Dictionary<Player, Hand> _CurrentHand;
    protected Dictionary<Player, PlayerStatuses> _PlayerStatus; // PlayerStatuses.InHand, PlayerStatuses.Folded, PlayerStatuses.SittingOut, etc.
    /* etc. */

where each CardGameState is modified by some action:

public interface IAction
{
    string Name { get; }

    CardGameState Apply(CardGameState state);
    bool IsLegal(CardGameState state);
}

Now I'm feeling very strongly that this is defeating the purpose of object-oriented programming, because the data specifically related to the player (in this case, his chip stack, hand, and current status) is not encapsulated by the Player object.

On the other hand, if a player were to raise the bet, I would be creating a RaiseAction that implements IAction, but the IAction interface only accepts the current game state, which I don't believe would be ideal if the chip stacks were stored within the Player class.

Basically, my question is: can I have the best of both worlds such that I can have an exact representation of the game state while simultaneously keeping all data related specifically to an object within the game state inside its given object?

Answer

Robert Gould picture Robert Gould · Mar 3, 2009

In online-games using the command-pattern (your IAction) is the standard, and proven, way to do it. It's not Object Oriented in the sense of the player, but the actions are Object Oriented, so from a purely theoretical point of view its a solid design pattern, I guess. And in practice thats how every successful online game I've seen implements it, but note that action games normally use very small discreet actions/packets, until it practically becomes a stream of sorts.

Edit:

A long time after I answering this, I came back here and realized another solution to this problem is to implement GameState's Players, Decks, etc... as derived from an IState class with an Apply(IAction action) member. This way objects apply actions on themselves, instead of having the application apply actions on objects, this would map actions and state to a visitor-pattern instead of a command pattern. Either solution will work, where visitor has the larger overhead and more encapsulation, while command is the easier solution with less encapsulation.