NAME

Games::Cards -- Perl module for playing card games

SYNOPSIS

    use Games::Cards;
    my $Rummy = new Games::Cards::Game;

    # Create and shuffle the deck and create the discard pile
    my $Deck = $Rummy->create_deck; # creates correct deck for this game
    $Deck->shuffle;
    my $Discard = new Games::Cards::Queue "Discard Pile";

    # Deal out the hands
    foreach my $i (1 .. 3) {
	my $hand = new Games::Cards::Hand "Player $i" ;
	$Deck->give_cards($hand, 7);
	$hand->sort_by_value;
	push @Hands, $hand;
    }

    # print hands (e.g. "Player 1: AS  2C  3C  3H 10D  QS  KH")
    foreach (@Hands) { print ($_->print("short"), "\n") }
    
    $Hands[1]->give_a_card ($Discard, "8D"); # discard 8 of diamonds
    
    # Undo stuff (e.g. for solitaire, not rummy)
    Games::Cards::Undo->initialize(100); # Make undo engine to save 100 moves
    Games::Cards::Undo->undo; # undo last move
    Games::Cards::Undo->redo; # redo last undone move
    Games::Cards::Undo->end_move; # tell undo engine we're done with a move

DESCRIPTION

This module creates objects to allow easier programming of card games.

Class Games::Cards::Game

This class represents a certain game, like War, or Solitaire. This is necessary to store the various rules for a given game, like the ranking of the cards. (Or, for more exotic games, how many cards of what type are in the deck.) Methods:

new(HASHREF)

creates a new game. HASHREF is a reference to a hash containing zero or more of the keys "suits" and "cards_in_suit". "suits" is a list of the suits in a deck, "cards_in_suit" is a reference to a hash whose keys are the names of the cards in one suit and whose values are the values (or ranks) of those cards. If "suits" is not given, the default suits (Clubs, Diamonds, Hearts, Spades) are used. If "cards_in_suit" is not given, the default cards (Ace, 2..10, Jack, Queen, King with values 1..13) are used. For example, war would require "Ace"=>14.

create_deck

creates an unshuffled deck of cards. For each card in the deck it creates a name, suit, value, and suit value. The makeup of the deck was stipulated by the 'new Games::Cards' command. Returns the deck.

Class Games::Cards::Queue

A Queue (cf. computer science terminology, or the C++ stdlib) is a first-in first-out pile of cards. Cards are removed from the top of the pile, but new cards are added to the bottom of the pile. This might represent, say, a pile of face-down cards, like the player's hand in War.

Class Games::Cards::Stack

A stack (cf. computer science terminology, or the C++ stdlib) is a last-in first-out pile of cards. Cards are removed from the top of the pile, and new cards are also added to the top of the pile. This would usually represent a pile of cards with its top card (and perhaps all cards) face up.

Class Games::Cards::Pile

A Pile is a pile of cards. That is, it is a CardSet where we will only access the beginning or end of the set. (This may include the first N cards in the set, but we will never reference the 17'th card.) This is a super class of Queue and Stack, and those classes should be used instead, so that we know whether the cards in the pile are FIFO or LIFO. Methods:

give_cards(RECEIVER, NUMBER)

Transfers NUMBER cards from the donor (the object on which this method was called) to the CardSet RECEIVER. This method can used for dealing cards from a deck, giving cards to another player (Go Fish), putting cards on the table (War), or transferring a card or cards between piles in solitaire.

If NUMBER is "all", then the donor gives all of its cards.

Returns 1 usually. If the donor has too few cards, it returns 0 and does not transfer any cards.

top_card

Returns the top Card in the CardSet (or 0 if CardSet is empty)

Class Games::Cards::Hand

A Hand represents a player's hand. Most significantly, it's a CardSet which is different from a Pile because the Cards in it are unordered. We may reference any part of the CardSet, not just the top or bottom. Methods:

give_a_card(RECEIVER, DESCRIPTION)

Transfers Card described by DESCRIPTION from the donor (the object on which this method was called) to the CardSet RECEIVER. This method can used for discarding a card from a hand, e.g.

If DESCRIPTION matches /^-?\d+$/, then it is the index in the cards array of the Card to give. Otherwise, DESCRIPTION is passed to Hand::index.

Returns 1 usually. If the donor does not have the card, it returns 0 and does not transfer anything.

move_card(DESCRIPTION, INDEX)

Rearrange a Hand by putting Card described by DESCRIPTION at index INDEX.

If DESCRIPTION matches /^-?\d+$/, then it is the index in the cards array of the Card to give. Otherwise, DESCRIPTION is passed to Hand::index.

Returns 1 usually. If the donor does not have the card, it returns 0 and does not transfer anything.

index(DESCRIPTION)

Given a card description DESCRIPTION return the index of that Card in the Hand, or undef if it was not found. DESCRIPTION may be a Card or a string (like "8H" or "KC").

Class Games::Cards::CardSet

A CardSet is just an array of cards (stored in the "cards" field). It could be a player's hand, a deck, or a discard pile, for instance. This is a super class of a number of other classes, and those subclasses should be used instead.

shuffle

shuffles the cards in the CardSet. Shuffling is not undoable.

sort_by_value

Sorts the Set by value. This and other sort routines will probably be used mostly on Hands, which are "ordered sets", but you might want to reorder a deck or something. Sorting is not undoable.

sort_by_suit

Sorts the Set by suit, but not by value within the suit.

sort_by_suit_and_value

Sorts the Set by suit, then by value within the suit.

face_down

Makes a whole CardSet face down

face_up

Makes a whole CardSet face up

print(LENGTH)

Returns a string containing a printout of the Cards in the CardSet. Prints a long printout if LENGTH is "long", short if "short" (or nothing). The CardSet is printed out in reverse order, so that the top card of the set is printed first.

name

Returns the name of the Set

cards

Returns a reference to the array of Cards in the set

size

Tells how many cards are in the set

Class Games::Cards::Card

A Card is a playing card. Methods:

new(HASHREF)

creates a new card. HASHREF references a hash with keys "suit" and "name".

print(LENGTH)

returns a string with the whole card name ("King of Hearts") if LENGTH is "long", otherwise a short version ("KH").

name(LENGTH)

prints the name of the card. The full name if LENGTH is "long"; otherwise a short version ("K");

suit(LENGTH)

Returns the suit of the card. Returns the long version ("Diamonds") if LENGTH is "long", else a short version ("D").

color

Is the card "red" or "black"? Returns the color or undef for unknown color.

value

Calculates the value of a card

suit_value

Returns the suit_value of a card (1..number of suits)

is_face_up

Returns true if a card is face up

is_face_down

Returns true if a card is face down

face_up

Makes a card face up

face_down

Makes a card face down

Class Games::Cards::Undo

This is the package for methods to undo & redo moves. There is no CG::Undo object. But there is a (private) array of the preceding moves (private CG::Undo::Move objects). Note that a "move" is made up of several "atoms". For example, moving a card from one column to another in solitaire involves one or more Splice atoms (removing or adding card(s) to a CardSet) and possibly a Face atom (turning a card over).

Generally, these methods will be called by other Games::Cards methods, but not by the actual games. Methods:

initialize(MOVES)

Initialize the Undo engine. MOVES is the number of atoms to save. 0 (or no argument) allows infinite undo.

This method must be called before any undo-able moves are made (i.e., it can be called after the hands are dealt). This method will also re-initialize the engine for a new game.

end_move

End the current move. Everything between the last call to end_move and now is considered one move. This tells undo how much to undo.

undo

Undo a move.

redo

Redo a move that had been undone with undo.

EXAMPLES

An implementation of Klondike (aka standard solitaire) demonstrates how to use this module in a simple game. Other card game examples are included as well.

NOTES

Public and Private

This module contains a bunch of methods. The public methods are documented here. That means any method not documented here is probably private, which means you shouldn't call it directly.

There are also a bunch of classes. Most private classes are not documented here. A couple private classes are mentioned, since they have methods which public classes inherit. In that case, the privateness is mentioned.

TODO

  • Networking games, so that multiple players on different computers can play games (using sockets). This is currently under active development. (gin.pl has already been written, and it should require very little changing, other than 'use Games::Cards::Server' and a bit more I/O.

  • ExtraCards. In addition to Suits * Cards_In_Suit, have this field of cards added to the deck. E.g., jokers. (Or a "color card" for a dealer's card shoe.) These probably need values too.

  • Allow user to change more things. E.g. create an AUTOLOAD which returns that field, or changes it if there's an argument (cf. Cookbook).

Maybe TODO

  • CGI support should be easy to add, so people could play multiplayer games in their web browsers. That is further in the future than socket-based Client/Server games, however.

  • Clone/deep copy method for a CardSet. This would allow e.g. saving a deck to restart the same game of solitaire.

Not TODO

Computer AI and GUI display are left as exercises for the reader.

BUGS

You betcha. It's still alpha.

AUTHOR

Amir Karger, karger@post.harvard.edu

SEE ALSO

perl(1).

3 POD Errors

The following errors were encountered while parsing the POD:

Around line 180:

You forgot a '=back' before '=head2'

Around line 348:

You forgot a '=back' before '=head2'

Around line 507:

You forgot a '=back' before '=head2'