This is a documentation for Board Game Arena: play board games online !

Deck

提供:Board Game Arena
ナビゲーションに移動 検索に移動

"Deck" is one of the most useful component on PHP side. With "Deck", you can manage cards of your game on server side.

Using "deck", you will be able to use the following features without writing a single SQL database request:

  • Place cards in pile, shuffle cards, draw cards one by one or many by many.
  • "Auto-reshuffle" discard pile into deck when deck is empty.
  • Move cards between different locations: hands of players, the table, ...


Using Deck: Hearts example

Deck component is massively used in "Hearts" example game - a card game. You can find in "hearts.game.php" that the object "$this->cards" is used many times.

Deck overview

With Deck component, you manage all cards of your game.

The 5 properties of each card

Using Deck component, each card will have 5 properties:

  • id: This is the unique ID of each card.
  • type and type_arg: These two values defines the type of your card (=what sort of card this is?).
  • location and location_arg: These two values defines where is the card at now.

id, type and type_arg properties are constants during the game. location and location_arg are changing when your cards are moving from places to places on the game area.

id is the unique ID of each card. Two cards can't get the same ID. IDs are generated automatically by the Deck component when you create cards during the Setup phase of your game.

type and type_arg defines the type of your card. type is a short string, and type_arg is an integer. You can use these two values as you want to make sure you will be able to identify the different cards of the game. See usage of "type" and "type_arg" below.

Examples of usage of "type" and "type_arg":

  • In "Hearts", "type" is the color of the card (1 to 4) and "type_arg" is the value of the card (1, 2, ... 10, J, Q, K).
  • In "Seasons", "type" is the type of the card (ex: 1 is Amulet of Air, 2 is Amulet of Fire, etc...). type_arg is not used.
  • In "Takenoko", a Deck component is used for objective cards. "type" is the kind of objective (irrigation/panda/plot) and "type_arg" is the ID of the specific objective to realize (ex: "a green bamboo x4"). Note that a second Deck component is used in Takenoko to manage the "garden plot" pile.


location and location_arg defines where is the card at now. location is a short string, and location_arg is an integer.

You can use 'location' and 'location_arg' as you want, to move your card on the game area. Although, there are 3 special 'location' that Deck manage specifically. You can choose to use - or not to use - these locations depending of your needs:

  • 'deck': in 'deck' location, cards are placed face down in a pile and are drawn during the game. 'location_arg' is used to specify where the card is in the deck pile (the card with the biggest location_arg is the next to be drawn).
  • 'hand': in 'hand' location, cards are in the hand of a player. 'location_arg' is set to the ID of this player.
  • 'discard': in 'discard' location, cards are discarded, and are ready to be shuffled into the deck if needed (see "autoreshuffle").


Tips: using Deck component, you are going to use generic properties ("location", "type_arg",...) for specific purposes of your game. Thus, during the design step before realizing your game, take 2 minutes to write down what is the meaning of each of this generic properties in the context of your game.

Create a new Deck component

For each Deck component in your game, you need to create a dedicated table in database. This table has a standard format. In practical, if you want to have a Deck component named "card", you just have to copy/paste the following in your "dbmodel.sql":

CREATE TABLE IF NOT EXISTS `card` (
  `card_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `card_type` varchar(16) NOT NULL,
  `card_type_arg` int(11) NOT NULL,
  `card_location` varchar(16) NOT NULL,
  `card_location_arg` int(11) NOT NULL,
  PRIMARY KEY (`card_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Once you did this (and restart your game), you can declare your Deck component in your PHP code in your class constructor. For Hearts for example, I added to "Hearts()" method:

        $this->cards = self::getNew( "module.common.deck" );
        $this->cards->init( "card" );

Note that we specify "card" here, the name of our previously created table. It means you can create several "Deck" with several tables. Most of the time this is unuseful: a Deck component should manage all objects of the same kind (ex: all cards of the game).

Afterwards, we can initialize your "Deck" by creating all the cards of the game. Generally, this is done only once during the game, during the "setupNewGame" method.

"Deck" component provides you a fast way to initialize all your cards at once: createCards. Here is how it is used for "Hearts":

        // Create cards
        $cards = array();
        foreach( $this->colors as  $color_id => $color ) // spade, heart, diamond, club
        {
            for( $value=2; $value<=14; $value++ )   //  2, 3, 4, ... K, A
            {
                $cards[] = array( 'type' => $color_id, 'type_arg' => $value, 'nbr' => 1);
            }
        }

        $this->cards->createCards( $cards, 'deck' );

As you can see, "createCards" takes a description of all cards of the game. For each type of card, you have to specify its "type", "type_arg" and the number of card to create. "createCards" create all cards and place them into the "deck" location (as specified in the second argument).

Now, you are ready to use "Deck"!

Simple examples using Deck

(Most examples are from "Hearts" game)

     // In "getAllDatas', we need to send to the current player all the cards he has in hand:
     $result['hand'] = $this->cards->getCardsInLocation( 'hand', $player_id );
     // At some time we want to check if all the cards (52) are in player's hands:
     if( $this->cards->countCardInLocation( 'hand' ) == 52 )
           // do something
     // When a player plays a card in front of him on the table:
     $this->cards->moveCard( $card_id, 'cardsontable', $player_id );

     // Note the use of the custom location 'cardsontable' here to keep track of cards on the table.


     // This is a new hand: let's gather all cards from everywhere in the deck:
     $this->cards->moveAllCardsInLocation( null, "deck" );

     // And then shuffle the deck
     $this->cards->shuffle( 'deck' );

     // And then deal 13 cards to each player
     // Deal 13 cards to each players
     // Create deck, shuffle it and give 13 initial cards
     $players = self::loadPlayersBasicInfos();
     foreach( $players as $player_id => $player )
     {
        $cards = $this->cards->pickCards( 13, 'deck', $player_id );
           
        // Notify player about his cards
        self::notifyPlayer( $player_id, 'newHand', '', array( 
            'cards' => $cards
         ) );
     }  

     // Note the use of "notifyPlayer" instead of "notifyAllPlayers": new cards is a private information ;)