card_nine 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 854dfb09dcd2e62f7ec6b5c965862bb9f962753b
4
+ data.tar.gz: 9f052c35d78081007e70e590297399bd45aea9f9
5
+ SHA512:
6
+ metadata.gz: 84002ce61aa852ffd44c0d75e20fa0718595248bd02175d78ad3fab7ceda2ab3f8a6b3d5d9a28d779809ee2000e263c8aafa8de768be3c82cf2f29b281220b9e
7
+ data.tar.gz: 9d195cbcb17037dab55d72f8fa4f3180525342f242ba1c608d18f4315371864161827ce355d0f34bbac8e5d7b8d968bc925b50a2af468bcaa335b3a9d5ec681d
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ before_install:
3
+ - gem uninstall bundler
4
+ - gem install bundler --version '1.7.6'
5
+ rvm:
6
+ - 2.1
7
+ script: bundle exec rake
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in card_nine.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'pullreview-coverage', require: false
8
+ end
data/Guardfile ADDED
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :bundler do
5
+ watch('Gemfile')
6
+
7
+ watch(/^.+\.gemspec/)
8
+ end
9
+
10
+ # Note: The cmd option is now required due to the increasing number of ways
11
+ # rspec may be run, below are examples of the most common uses.
12
+ # * bundler: 'bundle exec rspec'
13
+ # * bundler binstubs: 'bin/rspec'
14
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
15
+ # installed the spring binstubs per the docs)
16
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
17
+ # * 'just' rspec: 'rspec'
18
+ guard :rspec, cmd: 'bundle exec rspec' do
19
+ watch(%r{^spec/.+_spec\.rb$})
20
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
21
+ watch('spec/spec_helper.rb') { "spec" }
22
+
23
+ end
24
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Scott M Parrish
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # CardNine
2
+ [![Build Status](https://travis-ci.org/anithri/card_nine.svg?branch=master)](https://travis-ci.org/anithri/card_nine)
3
+ [![PullReview stats](https://www.pullreview.com/github/anithri/card_nine/badges/master.svg?)](https://www.pullreview.com/github/anithri/card_nine/reviews/master)
4
+ [![Dependency Status](https://gemnasium.com/anithri/card_nine.svg)](https://gemnasium.com/anithri/card_nine)
5
+
6
+ A Small set of classes to help model decks of cards for board games. Cards,
7
+ Decks and Deals to help you make your games.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'card_nine'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install card_nine
24
+
25
+ ## Usage
26
+
27
+ TODO: Write usage instructions here
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it ( https://github.com/[my-github-username]/card_nine/fork )
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/version_task'
3
+ require 'rspec/core/rake_task'
4
+
5
+ Rake::VersionTask.new
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => :spec
10
+
data/Thorfile ADDED
@@ -0,0 +1,39 @@
1
+ require 'facets/string/pathize'
2
+ require 'facets/string/camelcase'
3
+ class NewMethod < Thor::Group
4
+ include Thor::Actions
5
+
6
+ # Define arguments and options
7
+ argument :name
8
+
9
+ def self.source_root
10
+ File.dirname(__FILE__)
11
+ end
12
+
13
+ def create_lib_file
14
+ file_name = name.pathize
15
+ parts = name.split('::')
16
+ create_file "lib/#{file_name}.rb" do
17
+ out = ''
18
+ parts.each_with_index do |part, i|
19
+ keyword = (i == parts.length - 1) ? 'class' : 'module'
20
+ indent = ' ' * i
21
+ out += indent + keyword + ' ' + part.camelcase(:upper) + "\n"
22
+ end
23
+ parts.length.times do |i|
24
+ indent = ' ' * (parts.length - i - 1)
25
+ out += "#{indent}end\n"
26
+ end
27
+ out
28
+ end
29
+ end
30
+
31
+ def create_spec_file
32
+ file_name = name.pathize
33
+ create_file "spec/#{file_name}_spec.rb" do
34
+ "require 'rspec'\nrequire '#{file_name}'\n\ndescribe #{name} do\n\nend\n"
35
+
36
+ end
37
+ end
38
+ end
39
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.1
data/card_nine.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'card_nine'
7
+ spec.version = File.read('VERSION')
8
+ spec.authors = ['Scott M Parrish']
9
+ spec.email = ['anithri@gmail.com']
10
+ spec.summary = %q{Game Dev Toolbox. Cards }
11
+ spec.description = %q{A Toolbox to help me build a board game.}
12
+ spec.homepage = ''
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_runtime_dependency 'virtus', '~> 1.0.3'
21
+ spec.add_runtime_dependency 'facets', '~> 2.9.3'
22
+ spec.add_runtime_dependency 'hashie', '~> 3.3.1'
23
+
24
+ spec.add_development_dependency 'bundler', '~> 1.7.6'
25
+ spec.add_development_dependency 'rake', '~> 10.3.2'
26
+ spec.add_development_dependency 'thor', '~> 0.19.1'
27
+ spec.add_development_dependency 'rspec', '~> 3.1.0'
28
+ spec.add_development_dependency 'guard-rspec', '~> 4.3.1'
29
+ spec.add_development_dependency 'guard-bundler', '~> 2.0.0'
30
+ spec.add_development_dependency 'version', '~> 1.0.0'
31
+ spec.add_development_dependency 'fuubar', '~> 2.0.0'
32
+ spec.add_development_dependency 'pry'
33
+ end
@@ -0,0 +1,22 @@
1
+ require 'virtus'
2
+
3
+ module CardNine
4
+ # provides the base functionality required of a card
5
+ module Card
6
+ # @!method initialize(args = nil)
7
+ # will set the instance vars using the keys of args as a attribute name
8
+ # @param [Hash, Nil] args
9
+
10
+ include Virtus.module
11
+
12
+ attribute :name
13
+ attribute :id
14
+
15
+ # @!attribute [rw] name
16
+ # @return [String,Symbol,#to_s,Object] name of the card
17
+ # @!attribute [rw] id
18
+ # @return [String,Symbol,Object] id of the card
19
+
20
+ end
21
+
22
+ end
@@ -0,0 +1,46 @@
1
+ require 'card_nine/card'
2
+
3
+ module CardNine
4
+ module Cards
5
+ class PlayingCard
6
+ # @note implements comparable
7
+ include Comparable
8
+
9
+ # @!method initialize(args = nil)
10
+ # will set the instance vars using the keys of args as a attribute name
11
+ # @param [Hash, Nil] args
12
+ include Card
13
+
14
+ # ALL Suits of cards
15
+ SUITS = %w|Clubs Hearts Diamonds Spades|.freeze
16
+ # All Ranks of cards
17
+ RANKS = %w|2 3 4 5 6 7 8 9 10 Jack Queen King Ace|.freeze
18
+
19
+ # @!attribute [rw] suit
20
+ # @return [String] suit of card
21
+ attribute :suit, String
22
+ # @!attribute [rw] rank
23
+ # @return [String] rank of card
24
+ attribute :rank, String
25
+
26
+ # implement sort based on rank of the card, 2 low ace high
27
+ def <=>(other)
28
+ RANKS.find_index(rank) <=> RANKS.find_index(other.rank)
29
+ end
30
+
31
+ # create and return a standard 52 card deck of playing cards
32
+ def self.deck(rng = Random.new)
33
+ all = []
34
+ SUITS.each do |suit|
35
+ RANKS.each do |rank|
36
+ id = rank.to_i > 0 ? rank : rank[0]
37
+ id += suit[0]
38
+ all << { rank: rank, suit: suit, id: id, name: "#{rank} of #{suit}" }
39
+ end
40
+ end
41
+ Deck.new(cards: all.map { |c| self.new(c) }, rng: rng)
42
+
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,11 @@
1
+ module CardNine
2
+ module Cards
3
+ # The simplest card possible. A Nothing added class with Card included
4
+ class SimpleCard
5
+ # @!method initialize(args = nil)
6
+ # will set the instance vars using the keys of args as a attribute name
7
+ # @param [Hash, Nil] args
8
+ include Card
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module CardNine
2
+ class Dealer
3
+ end
4
+ end
@@ -0,0 +1,46 @@
1
+ require 'card_nine/cards/playing_card'
2
+ module CardNine
3
+ module Dealers
4
+ # implements a CardNine::Dealer for the game of Texas Holdem. This is only
5
+ # the card movement, the betting, UI, and hand evaluation are out of the
6
+ # scope of this library
7
+ # @example
8
+ # card_eval = PretendCardEval.new
9
+ # ui = PretendUI.new
10
+ # wagering = PretendTexasHoldemBettingService.new
11
+ # players = %w|Bruce Barbera Dick|
12
+ # dealer = CardNine::Dealers::TexasHoldem.new(players: players)
13
+ # hand = dealer.new_hand
14
+ # ui.update(hand)
15
+ # wagering(:ante, hand)
16
+ # [:deal_hole_cards, :flop, :turn, :river].each do |stage|
17
+ # ui.update(hand.deal_stage(stage))
18
+ # wagering(:round, hand)
19
+ # end
20
+ # wager(:resolve, hand)
21
+ class TexasHoldem
22
+
23
+ attr_accessor :players, :deck
24
+
25
+ STAGES = {
26
+ deal_hole_cards: ->(h) { h.deal_players(2) },
27
+ flop: ->(h) { h.discard; h.deal(3, to: :community) },
28
+ turn: ->(h) { h.discard; h.deal(to: :community) },
29
+ river: ->(h) { h.discard; h.deal(to: :community) }
30
+ }
31
+
32
+ def initialize(players:, deck: CardNine::Cards::PlayingCard.deck)
33
+ @players = players
34
+ @deck = deck
35
+ end
36
+
37
+ # generate a new hand from this dealer
38
+ # @return [CardNine::Hand]
39
+ def new_hand
40
+ players.rotate!
41
+ Hand.start(players: players, deck: deck, stages: STAGES)
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,21 @@
1
+ module CardNine
2
+ class Deck
3
+ # @!method initialize(args = nil)
4
+ # will set the instance vars using the keys of args as a attribute name
5
+ # @param [Hash, Nil] args
6
+ include Virtus.model
7
+
8
+ # @!attribute [rw] cards
9
+ # @return [Array<Card>] all cards in the deck
10
+ attribute :cards, Array[Card], default: []
11
+
12
+ # @!attribute [rw] rng
13
+ # @return [Random,#rand]
14
+ attribute :rng, Random, default: ->(*a) { Random.new }
15
+
16
+ # @return Array[Card] randomized
17
+ def shuffle
18
+ cards.shuffle(random: rng)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,63 @@
1
+ require 'virtus'
2
+ require 'card_nine/deck'
3
+ require 'card_nine/table'
4
+ module CardNine
5
+ class Hand
6
+ include Virtus.model
7
+
8
+ # @!attribute [rw] deck
9
+ # @return [CardNine::Deck]
10
+ attribute :deck, CardNine::Deck
11
+
12
+ # @!attribute [rw] players
13
+ # @return [Array]
14
+ attribute :players, Array, default: []
15
+
16
+ # @!attribute [rw] table
17
+ # @return [CardNine::Table]
18
+ attribute :table, CardNine::Table, default: :initialize_table
19
+
20
+ attribute :stages, Hash, default: {}
21
+
22
+ # create a new hand, yield to a setup block if given
23
+ def self.start(args = nil)
24
+ hand = self.new(args)
25
+ yield hand if block_given?
26
+ hand
27
+ end
28
+
29
+ # pass deal commands to table
30
+ # @yieldparam [Table] table for current hand
31
+ def deal(count = 1, from: :shoe, to:)
32
+ table.move_card(count, from: from, to: to)
33
+ end
34
+
35
+ def deal_players(count = 1, from: :shoe)
36
+ count.times do
37
+ players.each do |p|
38
+ deal(1, from: from, to: p)
39
+ end
40
+ end
41
+ end
42
+
43
+ def discard(count = 1, from: :shoe)
44
+ deal(count, from: from, to: :discards)
45
+ end
46
+
47
+ def deal_stage(stage_name = nil, &blk)
48
+ stages[stage_name].call(self) if stage_name && stages[stage_name]
49
+ blk.call(self) if blk
50
+ self
51
+ end
52
+
53
+ # @return Array<Card> cards at +loc+ location on table
54
+ def at(loc)
55
+ table.at(loc)
56
+ end
57
+
58
+ private
59
+ def initialize_table
60
+ CardNine::Table.new(players: players, deck: deck)
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,38 @@
1
+ require 'virtus'
2
+ module CardNine
3
+ # a CardNine::Table is the shoe, discard pile, and player hands
4
+ class Table
5
+ include Virtus.model
6
+
7
+ # @!attribute [rw] deck
8
+ # @return [CardNine::Deck, #shuffle]
9
+ attribute :deck
10
+
11
+ # @!attribute [rw] players
12
+ # @return [Array<Object>] all players at this table
13
+ attribute :players, Array, default: []
14
+
15
+ # locations as key for array of cards
16
+ def layout
17
+ @layout ||= init_layout
18
+ end
19
+
20
+ # deal move +count+ card(s) +from+ the top of one @layout location +to+ top of another
21
+ def move_card(count = 1, from: :shoe, to:)
22
+ layout[to].unshift(*(layout[from].shift(count)))
23
+ end
24
+
25
+ # return all cards at +loc+ in layout
26
+ def at(loc)
27
+ layout[loc]
28
+ end
29
+
30
+ private
31
+ def init_layout
32
+ l = Hash.new { |h, k| h[k] = [] }
33
+ l[:shoe] = self.deck.shuffle
34
+ return l
35
+ end
36
+
37
+ end
38
+ end
data/lib/card_nine.rb ADDED
@@ -0,0 +1,13 @@
1
+ # CardNine is a programmers toolkit providing abstractions for cards, decks, dealers, and
2
+ # hands. It also provides a pair of sample games that use the system.
3
+ # A Card is the base unit and can be as simple as a name, slightly more complicated like
4
+ # a playing card with ranks, suits and sorting. Attributes and keyword lists will make even
5
+ # the most complicated
6
+ module CardNine
7
+ require 'card_nine/card'
8
+ require 'card_nine/deck'
9
+ require 'card_nine/dealer'
10
+ require 'card_nine/table'
11
+ require 'card_nine/hand'
12
+
13
+ end
@@ -0,0 +1,18 @@
1
+ require 'rspec'
2
+ require 'card_nine/card'
3
+
4
+ describe CardNine::Card do
5
+ before(:all) do
6
+ class CardKlass
7
+ include CardNine::Card
8
+ end
9
+ end
10
+ let(:name) { 'Batman' }
11
+ let(:card_id) { :batman }
12
+
13
+ subject { CardKlass.new(id: card_id, name: name) }
14
+ it { is_expected.to be_a described_class }
15
+ it { expect(subject.id).to eq :batman }
16
+ it { expect(subject.name).to eq 'Batman' }
17
+
18
+ end
@@ -0,0 +1,56 @@
1
+ require 'rspec'
2
+ require 'card_nine/cards/playing_card'
3
+
4
+ describe CardNine::Cards::PlayingCard do
5
+ let(:name) { '7 of Diamonds' }
6
+ let(:suit) { 'Diamonds' }
7
+ let(:rank) { '7' }
8
+ let(:id) { '7d' }
9
+ let(:args) { { id: id, name: name, suit: suit, rank: rank } }
10
+ subject { described_class.new(args) }
11
+ it { is_expected.to be_a described_class }
12
+ it { expect(subject.id).to eq id }
13
+ it { expect(subject.name).to eq name }
14
+ it { expect(subject.suit).to eq suit }
15
+ it { expect(subject.rank).to eq rank }
16
+
17
+ describe 'sorting' do
18
+ let(:name_h) { 'King of Spades' }
19
+ let(:suit_h) { 'Spades' }
20
+ let(:rank_h) { 'King' }
21
+ let(:id_h) { 'KS' }
22
+ let(:args_h) { { id: id_h, name: name_h, suit: suit_h, rank: rank_h } }
23
+ let(:higher) { described_class.new(args_h) }
24
+
25
+ it { is_expected.to respond_to :<, :> }
26
+
27
+ it { expect(subject < higher).to be_truthy }
28
+ it { expect(subject > higher).to be_falsey }
29
+ it { expect(subject == higher).to be_falsey }
30
+
31
+ let(:name_l) { '2 of Clubs' }
32
+ let(:suit_l) { 'Clubs' }
33
+ let(:rank_l) { '2' }
34
+ let(:id_l) { '2C' }
35
+ let(:args_l) { { id: id_l, name: name_l, suit: suit_l, rank: rank_l } }
36
+ let(:lower) { described_class.new(args_l) }
37
+
38
+ it { expect(subject < lower).to be_falsey }
39
+ it { expect(subject > lower).to be_truthy }
40
+ it { expect(subject == lower).to be_falsey }
41
+
42
+ let(:same) { described_class.new(args) }
43
+
44
+ it { expect(subject < same).to be_falsey }
45
+ it { expect(subject > same).to be_falsey }
46
+ it { expect(subject == same).to be_truthy }
47
+ end
48
+
49
+ describe '#deck' do
50
+ subject { described_class.deck() }
51
+ it { is_expected.to be_a CardNine::Deck }
52
+ it { expect(subject.cards.length).to eq 52 }
53
+ it { expect(subject.cards).to all(be_a CardNine::Card) }
54
+ it { expect(subject.cards.map(&:id).uniq.length).to eq 52 }
55
+ end
56
+ end
@@ -0,0 +1,11 @@
1
+ require 'rspec'
2
+ require 'card_nine/cards/simple_card'
3
+
4
+ describe CardNine::Cards::SimpleCard do
5
+ let(:name) { 'Batman' }
6
+ let(:card_id) { :batman }
7
+ subject { described_class.new(id: card_id, name: name) }
8
+ it { is_expected.to be_a described_class }
9
+ it { expect(subject.id).to eq :batman }
10
+ it { expect(subject.name).to eq 'Batman' }
11
+ end
@@ -0,0 +1,6 @@
1
+ require 'rspec'
2
+ require 'card_nine/dealer'
3
+
4
+ describe CardNine::Dealer do
5
+
6
+ end
@@ -0,0 +1,89 @@
1
+ require 'rspec'
2
+ require 'card_nine/dealers/texas_holdem'
3
+
4
+ describe CardNine::Dealers::TexasHoldem do
5
+ let(:players) { %w|Barbera Stephanie Cassandra| }
6
+
7
+ subject { described_class.new(players: players) }
8
+
9
+ it { is_expected.to be_a described_class }
10
+ it { is_expected.to respond_to :new_hand }
11
+
12
+ describe '.new_hand' do
13
+ subject { described_class.new(players: players).new_hand }
14
+ it { is_expected.to be_a CardNine::Hand }
15
+ end
16
+
17
+ describe 'STAGES' do
18
+ context ':hole_cards' do
19
+ subject do
20
+ h = described_class.new(players: players).new_hand
21
+ h.deal_stage(:deal_hole_cards)
22
+ h
23
+ end
24
+ it { is_expected.to be_a CardNine::Hand }
25
+ it { expect(subject.at('Barbera').length).to eq 2 }
26
+ it { expect(subject.at('Stephanie').length).to eq 2 }
27
+ it { expect(subject.at('Cassandra').length).to eq 2 }
28
+ it { expect(subject.at(:discards)).to be_empty }
29
+ it { expect(subject.at(:shoe).length).to eq 46 }
30
+ end
31
+
32
+ context ':flop' do
33
+ subject do
34
+ h = described_class.new(players: players).new_hand
35
+ h.deal_stage(:flop)
36
+ h
37
+ end
38
+ it { is_expected.to be_a CardNine::Hand }
39
+ it { expect(subject.at(:community).length).to eq 3 }
40
+ it { expect(subject.at(:discards).length).to eq 1 }
41
+ it { expect(subject.at(:shoe).length).to eq 48 }
42
+ end
43
+
44
+ context ':turn' do
45
+ subject do
46
+ h = described_class.new(players: players).new_hand
47
+ h.deal_stage(:turn)
48
+ h
49
+ end
50
+ it { is_expected.to be_a CardNine::Hand }
51
+ it { expect(subject.at(:community).length).to eq 1 }
52
+ it { expect(subject.at(:discards).length).to eq 1 }
53
+ it { expect(subject.at(:shoe).length).to eq 50 }
54
+ end
55
+
56
+ context ':river' do
57
+ subject do
58
+ h = described_class.new(players: players).new_hand
59
+ h.deal_stage(:river)
60
+ h
61
+ end
62
+ it { is_expected.to be_a CardNine::Hand }
63
+ it { expect(subject.at(:community).length).to eq 1 }
64
+ it { expect(subject.at(:discards).length).to eq 1 }
65
+ it { expect(subject.at(:shoe).length).to eq 50 }
66
+ end
67
+
68
+ context 'all in order' do
69
+ subject do
70
+ h = described_class.new(players: players).new_hand
71
+ h.deal_stage(:deal_hole_cards)
72
+ h.deal_stage(:flop)
73
+ h.deal_stage(:turn)
74
+ h.deal_stage(:river)
75
+ h
76
+ end
77
+ it { is_expected.to be_a CardNine::Hand }
78
+ it { expect(subject.at('Barbera').length).to eq 2 }
79
+ it { expect(subject.at('Stephanie').length).to eq 2 }
80
+ it { expect(subject.at('Cassandra').length).to eq 2 }
81
+ it { expect(subject.at(:community).length).to eq 5 }
82
+ it { expect(subject.at(:discards).length).to eq 3 }
83
+ it { expect(subject.at(:shoe).length).to eq 38 }
84
+
85
+
86
+ end
87
+ end
88
+
89
+ end
@@ -0,0 +1,27 @@
1
+ require 'rspec'
2
+
3
+ require 'card_nine/deck'
4
+
5
+ describe CardNine::Deck do
6
+ let(:cards) { %w|Batman Batgirl Robin Nightwing| }
7
+ let(:rng) { Random.new }
8
+ subject { described_class.new(cards: cards) }
9
+ it { is_expected.to have_attributes(cards: cards) }
10
+ it { expect(subject.rng).to respond_to :rand }
11
+ it { is_expected.to respond_to :shuffle }
12
+ it 'should call shuffle on cards list' do
13
+ cards = %w|Batman Batgirl Robin Nightwing|.map { |n| CardNine::Cards::SimpleCard.new(name: n) }
14
+ rng = Random.new(1234)
15
+ deck = described_class.new(rng: rng, cards: cards)
16
+ expect(deck.cards).to receive(:shuffle)
17
+ deck.shuffle
18
+ end
19
+
20
+ describe 'defaults to' do
21
+ subject { described_class.new }
22
+ it { is_expected.to be_a described_class }
23
+ it { expect(subject.cards).to eq [] }
24
+ it { expect(subject.rng).to be_a Random }
25
+ end
26
+
27
+ end
@@ -0,0 +1,68 @@
1
+ require 'rspec'
2
+ require 'card_nine/hand'
3
+
4
+ describe CardNine::Hand do
5
+ let(:players) { %w|Batman Batgirl Robin| }
6
+ let(:deck) { CardNine::Cards::PlayingCard.deck }
7
+ let(:table) { CardNine::Table.new(players: players, deck: deck) }
8
+ let(:stages) { { deal_five: ->(h) { h.deal_players(5) } } }
9
+ let(:args) { { players: players, deck: deck } }
10
+ subject { described_class.new(args) }
11
+ it { is_expected.to be_a described_class }
12
+
13
+ it { expect(subject.deck).to eq deck }
14
+ it { expect(subject.players).to eq players }
15
+ it { expect(subject.table).to be_a CardNine::Table }
16
+ it { expect(subject.stages).to be_a Hash }
17
+
18
+ describe '#start(args = nil, &blk)' do
19
+ it { expect(described_class.start(args)).to be_a described_class }
20
+ it 'executes block with hand as argument' do
21
+ hand = described_class.start(args) { |h| h.players << 'Nightwing' }
22
+ expect(hand.players).to include 'Nightwing'
23
+ end
24
+ end
25
+
26
+ describe '.at(loc)' do
27
+ subject { described_class.start(args) }
28
+ it { is_expected.to be_a described_class }
29
+ it { expect(subject.at(:shoe).length).to eq 52 }
30
+ it { expect(subject.at(:discards)).to eq [] }
31
+ end
32
+
33
+ describe '.deal_stage(stage_name = nil, &blk)' do
34
+ context 'with only block' do
35
+ subject do
36
+ h = described_class.start(players: players, deck: deck, table: table, stages: stages)
37
+ h.deal_stage do |h|
38
+ h.deal(3, to: :discards)
39
+ end
40
+ h
41
+ end
42
+ it { expect(subject.at(:discards).length).to eq 3 }
43
+ end
44
+
45
+ context 'with only stage' do
46
+ subject do
47
+ h = described_class.start(players: players, deck: deck, table: table, stages: stages)
48
+ h.deal_stage(:deal_five)
49
+ h
50
+ end
51
+ it { expect(subject.at('Batman').length).to eq 5 }
52
+ it { expect(subject.at('Batgirl').length).to eq 5 }
53
+ it { expect(subject.at('Robin').length).to eq 5 }
54
+ end
55
+ context 'with both stages and block' do
56
+ subject do
57
+ h = described_class.start(players: players, deck: deck, table: table, stages: stages)
58
+ h.deal_stage(:deal_five) { |h| h.deal(6, to: :discards) }
59
+ h
60
+ end
61
+ it { expect(subject.at('Batman').length).to eq 5 }
62
+ it { expect(subject.at('Batgirl').length).to eq 5 }
63
+ it { expect(subject.at('Robin').length).to eq 5 }
64
+ it { expect(subject.at(:discards).length).to eq 6 }
65
+ it { expect(subject.at(:shoe).length).to eq 31 }
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,74 @@
1
+ require 'rspec'
2
+ require 'card_nine/table'
3
+
4
+ describe CardNine::Table do
5
+ let(:cards) do
6
+ %w|Batman Batgirl Robin Nightwing|.
7
+ map { |n| CardNine::Cards::SimpleCard.new(name: n) }
8
+ end
9
+ let(:deck) { CardNine::Deck.new(cards: cards) }
10
+ subject { described_class.new(deck: deck) }
11
+ it { is_expected.to be_a described_class }
12
+ it { expect(subject.deck).to eq deck }
13
+ it { expect(subject.players).to eq [] }
14
+ it { expect(subject.layout).to be_a Hash }
15
+ it { expect(subject.layout[:shoe].length).to eq 4 }
16
+ it { expect(subject.layout[:discards]).to eq [] }
17
+ describe '.move_card(from: old_pile, to: new_pile)' do
18
+ context 'using default count and :from' do
19
+ subject do
20
+ table = described_class.new(deck: deck, players: %w|Jason Tim|)
21
+ table.move_card(to: 'Tim')
22
+ table.move_card(to: 'Jason')
23
+ table.move_card(to: :discards)
24
+ table
25
+ end
26
+
27
+ it { is_expected.to be_a CardNine::Table }
28
+
29
+ it 'moves each card to the right spot' do
30
+ expect(subject.at('Tim').length).to eq 1
31
+ expect(subject.at('Jason').length).to eq 1
32
+ expect(subject.at(:shoe).length).to eq 1
33
+ expect(subject.at(:discards).length).to eq 1
34
+
35
+ end
36
+
37
+ end
38
+ context 'with count' do
39
+ subject do
40
+ table = described_class.new(deck: deck, players: %w|Jason Tim|)
41
+ table.move_card(2, to: 'Tim')
42
+ table.move_card(2, to: 'Jason')
43
+ table
44
+ end
45
+
46
+ it { is_expected.to be_a CardNine::Table }
47
+
48
+ it 'moves each card to the right spot' do
49
+ expect(subject.at('Tim').length).to eq 2
50
+ expect(subject.at('Jason').length).to eq 2
51
+ expect(subject.at(:shoe).length).to eq 0
52
+ expect(subject.at(:discards).length).to eq 0
53
+ end
54
+ end
55
+ context 'with count' do
56
+ subject do
57
+ table = described_class.new(deck: deck, players: %w|Jason Tim|)
58
+ table.move_card(4, to: 'Tim')
59
+ table.move_card(2, to: 'Jason', from: 'Tim')
60
+ table
61
+ end
62
+
63
+ it { is_expected.to be_a CardNine::Table }
64
+
65
+ it 'moves each card to the right spot' do
66
+ expect(subject.at('Tim').length).to eq 2
67
+ expect(subject.at('Jason').length).to eq 2
68
+ expect(subject.at(:shoe).length).to eq 0
69
+ expect(subject.at(:discards).length).to eq 0
70
+ end
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'card_nine'
3
+
4
+ describe CardNine do
5
+
6
+ subject { described_class.constants }
7
+ it { is_expected.to include :Card, :Deck, :Dealer, :Hand }
8
+
9
+
10
+ end
@@ -0,0 +1,29 @@
1
+ require 'pry'
2
+ RSpec.configure do |config|
3
+ # rspec-expectations config goes here. You can use an alternate
4
+ # assertion/expectation library such as wrong or the stdlib/minitest
5
+ # assertions if you prefer.
6
+ config.expect_with :rspec do |expectations|
7
+ # This option will default to `true` in RSpec 4. It makes the `description`
8
+ # and `failure_message` of custom matchers include text for helper methods
9
+ # defined using `chain`, e.g.:
10
+ # be_bigger_than(2).and_smaller_than(4).description
11
+ # # => "be bigger than 2 and smaller than 4"
12
+ # ...rather than:
13
+ # # => "be bigger than 2"
14
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
15
+ end
16
+
17
+ config.filter_run :focus
18
+ config.run_all_when_everything_filtered = true
19
+ config.filter_run_excluding :rewrite => true
20
+
21
+ # rspec-mocks config goes here. You can use an alternate test double
22
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
23
+ config.mock_with :rspec do |mocks|
24
+ # Prevents you from mocking or stubbing a method that does not exist on
25
+ # a real object. This is generally recommended, and will default to
26
+ # `true` in RSpec 4.
27
+ mocks.verify_partial_doubles = true
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,252 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: card_nine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.1
5
+ platform: ruby
6
+ authors:
7
+ - Scott M Parrish
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: virtus
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: facets
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.9.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.9.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: hashie
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.3.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.3.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.7.6
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.7.6
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 10.3.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 10.3.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: thor
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.19.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.19.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 3.1.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 3.1.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: guard-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 4.3.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 4.3.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: guard-bundler
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 2.0.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 2.0.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: version
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 1.0.0
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 1.0.0
153
+ - !ruby/object:Gem::Dependency
154
+ name: fuubar
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 2.0.0
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: 2.0.0
167
+ - !ruby/object:Gem::Dependency
168
+ name: pry
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ description: A Toolbox to help me build a board game.
182
+ email:
183
+ - anithri@gmail.com
184
+ executables: []
185
+ extensions: []
186
+ extra_rdoc_files: []
187
+ files:
188
+ - ".gitignore"
189
+ - ".rspec"
190
+ - ".travis.yml"
191
+ - Gemfile
192
+ - Guardfile
193
+ - LICENSE.txt
194
+ - README.md
195
+ - Rakefile
196
+ - Thorfile
197
+ - VERSION
198
+ - card_nine.gemspec
199
+ - lib/card_nine.rb
200
+ - lib/card_nine/card.rb
201
+ - lib/card_nine/cards/playing_card.rb
202
+ - lib/card_nine/cards/simple_card.rb
203
+ - lib/card_nine/dealer.rb
204
+ - lib/card_nine/dealers/texas_holdem.rb
205
+ - lib/card_nine/deck.rb
206
+ - lib/card_nine/hand.rb
207
+ - lib/card_nine/table.rb
208
+ - spec/card_nine/card_spec.rb
209
+ - spec/card_nine/cards/playing_card_spec.rb
210
+ - spec/card_nine/cards/simple_card_spec.rb
211
+ - spec/card_nine/dealer_spec.rb
212
+ - spec/card_nine/dealers/texas_holdem_spec.rb
213
+ - spec/card_nine/deck_spec.rb
214
+ - spec/card_nine/hand_spec.rb
215
+ - spec/card_nine/table_spec.rb
216
+ - spec/card_nine_spec.rb
217
+ - spec/spec_helper.rb
218
+ homepage: ''
219
+ licenses:
220
+ - MIT
221
+ metadata: {}
222
+ post_install_message:
223
+ rdoc_options: []
224
+ require_paths:
225
+ - lib
226
+ required_ruby_version: !ruby/object:Gem::Requirement
227
+ requirements:
228
+ - - ">="
229
+ - !ruby/object:Gem::Version
230
+ version: '0'
231
+ required_rubygems_version: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - ">="
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ requirements: []
237
+ rubyforge_project:
238
+ rubygems_version: 2.4.2
239
+ signing_key:
240
+ specification_version: 4
241
+ summary: Game Dev Toolbox. Cards
242
+ test_files:
243
+ - spec/card_nine/card_spec.rb
244
+ - spec/card_nine/cards/playing_card_spec.rb
245
+ - spec/card_nine/cards/simple_card_spec.rb
246
+ - spec/card_nine/dealer_spec.rb
247
+ - spec/card_nine/dealers/texas_holdem_spec.rb
248
+ - spec/card_nine/deck_spec.rb
249
+ - spec/card_nine/hand_spec.rb
250
+ - spec/card_nine/table_spec.rb
251
+ - spec/card_nine_spec.rb
252
+ - spec/spec_helper.rb