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("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)
$Undo = new Games::Cards::Undo(100); # Make undo engine to save 100 moves
$Undo->undo; # undo last move
$Undo->redo; # redo last undone move
$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(NAME)
-
creates an unshuffled deck of cards. For each card in the deck it creates a name, suit, value, and suit value. NAME is the name to give the deck, e.g. "Deck" (it is passed to the "new" call that creates the deck.) The number of cards in the deck, etc. is stipulated by the argument, which is a Games::Cards::Game object. Returns the deck, which is a Games::Cards::Queue object.
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.
- new(NAME)
-
create a new (empty) CardSet. NAME is a string that e.g. can be output when you print the CardSet.
- 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.
- clone
-
Create a copy of this CardSet. That is, create an object with the same class as arg0. Then make a copy of each Card in the CardSet (true copy, not a reference). arg1 is the name to give the new CardSet.
- 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".
- clone
-
makes a copy of the Card (not just a reference to it).
- 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:
- new(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 349:
You forgot a '=back' before '=head2'
- Around line 508:
You forgot a '=back' before '=head2'