The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

Name

Game::Deckar - a module for wrangling decks of cards

SYNOPSIS

  use Game::Deckar;
  
  # Card object (optional)
  my $card = Game::Deckar::Card->new( data => "Turn Left" );
  
  my $undo = $card->set_meta( hidden => 1 );
  
  say for $card->data, $card->meta('hidden');    # "Turn Left", 1
  
  $undo->() say $card->meta('hidden');           # undef
  
  
  # Deck object
  my $deck = Game::Deckar->new(
      decks   => [qw/new player1 player2 discard/],
      initial => { new => [ "Turn Left", "Stand Up" ] },
  );
  
  $deck->shuffle('new');
  
  ( $card, $undo ) = $deck->deal( new => 'player1' );
  say $card;
  
  $undo->();    # undeal the card
  
  
  # Deck with card object wrapping (all not visible)
  $deck = Game::Deckar->new(
      decks         => [qw/new player1 player2 discard/],
      initial_cards => { new     => [ 'A' .. 'F' ] },
      meta          => { visible => 0 },
  );
  
  ( $card, $undo ) = $deck->deal( new => 'player1' );
  $card->set_meta( visible => 1 );

DESCRIPTION

Deckar provides for arrays of cards and various supporting methods to deal with them. An optional card object allows metadata such as card visibility or whatever to be associated with cards. Means to undo changes are provided.

The various "decks" represent stacks (or queues) of cards, so a "deck of cards" might be split into various named decks such as a pile to draw from, individual decks for each of the player's hands, discard piles, etc. Naming of these decks is left to the caller. The deck names are assumed to be strings.

The "top" of a deck is arbitrarily index 0, and the bottom the last element of the array. Therefore interactions with the top involve shift, unshift, or splicing at index 0; interactions with the bottom use push, pop, or splicing at @array or $#array.

CLASSES

Game::Deckar::Card

An optional container object for cards (of whatever content) that also provides for metadata about a card, such as whether the card is visible, counters on the card, etc.

data

Returns the card data.

new data => card-data, [ meta => { default metadata } ]

Constructor. Card data must be provided. This could be a number, text such as "Ace of Spades" or "Repulse the Monkey", or a reference to an object or data structure. This data is only held onto by this module.

Changes made by the constructor are not available for undo.

meta key

Returns the value for the meta key associated with the card.

set_meta key value

Sets metadata for a card. Returns an undo code reference.

Game::Deckar

This class organizes cards into decks and provides methods for moving and shuffling cards. The caller can either use their own card data or instead host that data within Game::Deckar::Card objects.

add_deck name

Adds an empty named deck. Returns an undo code reference.

collect target source1 [source2 ..]

Moves all cards from the source deck(s) onto the top of the target deck. The target deck can be specified in the source list and will be ignored. Returns an undo code reference.

del_deck name

Deletes a named deck. Decks must be empty to be deleted. Returns an undo code reference.

deal source-deck dest-deck [ index ] [ to-top? ]

Deals from by default the top of the source deck to the destination deck. index specifies the index used to pick from the source deck, 0 or the top by default. The to-top? boolean controls whether the card goes to the top of the destination (the default) or to the bottom.

Returns the card dealt (so that card metadata can be changed, if need be) and an undo code reference.

empty name

Removes all cards from the named deck. Returns an undo code reference.

get name

Returns an array reference to the cards in the deck name. The contents of the array should not be modified; if you do modify it, undo code references may do unexpected things, unless you also handle that yourself.

The count of elements in a deck can be obtained by using the array reference in scalar context.

  my $hand  = $deck->get('player1');
  my $count = @$hand;

Pains are taken to preserve the array reference through the various methods, so it should be safe for a caller to hold onto a deck reference over time.

get_decks

Returns a sorted list of the decks present in the object.

move src dst count [ index ] [ to-top? ]

Like deal but instead moves count cards from src to dst, starting from index and going by default to the top of dst. Returns a reference to the list of cards moved and an undo code reference.

Since version 0.02.

new

Constructor. With decks creates those deck names from the list given. With initial puts the given card lists into the given deck name. With initial-card and possibly also meta does the same as initial but wraps the cards in Game::Deckar::Card objects.

See the "SYNOPSIS" or the t/ directory code for examples.

Changes made by the constructor are not available for undo.

pick src dst indices [ to-top? ]

Picks a number of cards out of src and places them at either the top (the default) or the bottom of dst. Returns the cards picked and an undo code reference. The returned cards will be in the same order as the indices provided.

  my ( $cards, $undo ) = $deck->pick( hand => 'played', [ 3, 5, 0 ] );
  for my $c (@$cards) { ...

Since version 0.02.

shuffle name

Shuffles the deck. Returns an undo code reference.

FUNCTION

Not exported.

fisher_yates_shuffle

Used to in-place shuffle decks. Uses Perl's rand() for the "random" numbers.

BUGS

It's new code, so various necessary methods are likely missing.

SEE ALSO

Games::Cards however the documentation claimed that undo was not available following a desk shuffle, and the module looked biased towards a conventional deck of cards.

COPYRIGHT AND LICENSE

Copyright 2023 Jeremy Mates

This program is distributed under the (Revised) BSD License: https://opensource.org/licenses/BSD-3-Clause