cardlike 0.0.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.
@@ -0,0 +1,47 @@
1
+ module Cardlike
2
+ #
3
+ # Increment the score for a target (usually a string or symbol).
4
+ #
5
+ # Cardlike.score "player 1" # => sets the score to 1
6
+ #
7
+ def self.score(target)
8
+ @scores ||= {}
9
+ @scores[target] ||= 0
10
+ @scores[target] += 1
11
+ end
12
+
13
+ #
14
+ # Clear all scores.
15
+ #
16
+ def self.clear_scores
17
+ @scores = {}
18
+ end
19
+
20
+ #
21
+ # Return the hash of the form <tt>{target: score}</tt>.
22
+ #
23
+ def self.scores
24
+ @scores ||= {}
25
+ @scores
26
+ end
27
+
28
+ #
29
+ # Retrieve the score for a target (usually a string or symbol).
30
+ #
31
+ # Cardlike.score "player 1" # => sets the score to 1
32
+ # Cardlike.score "player 1" # => sets the score to 2
33
+ # Cardlike.the_score "player 1" # => 2
34
+ #
35
+ def self.the_score(target)
36
+ @scores ||= {}
37
+ @scores[target]
38
+ end
39
+
40
+ #
41
+ # Set the score for a target to a particular value.
42
+ #
43
+ def self.set_score(target, value)
44
+ @scores ||= {}
45
+ @scores[target] = value
46
+ end
47
+ end
@@ -0,0 +1,27 @@
1
+ module Cardlike
2
+ #
3
+ # Define a turn block that can be run with Cardlike.begin_new_turn.
4
+ #
5
+ # Cardlike.define_turn do |current_player|
6
+ # puts "#{current_player}'s turn"
7
+ # end
8
+ #
9
+ def self.define_turn(&block)
10
+ @turn = block
11
+ end
12
+
13
+ #
14
+ # Return the turn block set by Cardlike.define_turn.
15
+ #
16
+ def self.the_turn
17
+ @turn
18
+ end
19
+
20
+ #
21
+ # Call the block defined by Cardlike.define_turn. You can pass arguments to
22
+ # the block as well.
23
+ #
24
+ def self.begin_new_turn(*args)
25
+ @turn.call(*args)
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Cardlike
2
+ VERSION = "0.0.1"
3
+ end
data/lib/cardlike.rb ADDED
@@ -0,0 +1,154 @@
1
+ require "cardlike/version"
2
+ require "cardlike/deck"
3
+ require "cardlike/card"
4
+ require "cardlike/hand"
5
+ require "cardlike/score"
6
+ require "cardlike/turn"
7
+ require "active_support/inflector"
8
+
9
+ module Cardlike
10
+ def self.version
11
+ "#{self} version #{VERSION}"
12
+ end
13
+
14
+ #
15
+ # Optionally use this to wrap Cardlike DSL methods to avoid having to prefix
16
+ # them with +Cardlike+. This is mainly useful for large blocks.
17
+ #
18
+ # Cardlike.game do
19
+ # type_of_card :playing_card { has :suit }
20
+ # end
21
+ #
22
+ # is the same as
23
+ #
24
+ # Cardlike.type_of_card :playing_card { has :suit }
25
+ #
26
+ def self.game(&block)
27
+ self.class_eval(&block)
28
+ end
29
+
30
+ #
31
+ # Set up a new Deck with the given name. Returns the created Deck which can
32
+ # also be accessed with +the_deck+. Within the block you may use the Deck DSL.
33
+ #
34
+ # Cardlike.deck "Poker Deck" do
35
+ # include_card "King of Diamonds"
36
+ # include_card "Three of Clubs"
37
+ # end
38
+ #
39
+ def self.deck(name, &block)
40
+ @decks ||= {}
41
+ d = Deck.new(name: name)
42
+ d.instance_eval(&block) if block_given?
43
+ @decks[name] = d
44
+ d
45
+ end
46
+
47
+ #
48
+ # Set up a new Hand with the given name. Returns the created Hand which can
49
+ # also be accessed with +the_deck+. Within the block you may use the Hand DSL.
50
+ #
51
+ # Cardlike.hand "Poker Hand" do
52
+ # include_card "King of Diamonds"
53
+ # include_card "Three of Clubs"
54
+ # end
55
+ #
56
+ def self.hand(name, &block)
57
+ @hands ||= {}
58
+ d = Hand.new(name: name)
59
+ d.instance_eval(&block) if block_given?
60
+ @hands[name] = d
61
+ d
62
+ end
63
+
64
+ #
65
+ # Return a Deck created by the +deck+ method by +name+.
66
+ #
67
+ # Cardlike.the_deck("Blackjack Deck").size # => 52
68
+ #
69
+ def self.the_deck(name)
70
+ @decks ||= {}
71
+ @decks[name]
72
+ end
73
+
74
+ #
75
+ # Return a Hand created by the +hand+ method by +name+.
76
+ #
77
+ # Cardlike.the_hand("Poker Hand").size # => 5
78
+ #
79
+ def self.the_hand(name)
80
+ @hands ||= {}
81
+ @hands[name]
82
+ end
83
+
84
+ #
85
+ # Return a Card created by the +card+ method. Also will return cards created
86
+ # by the custom +new_+ card methods (see +type_of_card+).
87
+ #
88
+ # Cardlike.the_card("Six of Diamonds").name # => "Six of Diamonds"
89
+ #
90
+ def self.the_card(name)
91
+ @cards ||= {}
92
+ @cards[name]
93
+ end
94
+
95
+ #
96
+ # Create a new Card with the given name and block evaluated in the context of
97
+ # the Card. Returns the Card (that can also be accessed with +the_card+). You
98
+ # may use the Card DSL in the block.
99
+ #
100
+ # Cardlike.card "Fire Monster" do
101
+ # text "A red-hot monster."
102
+ # end
103
+ #
104
+ def self.card(name, &block)
105
+ c = Card.create(name, &block)
106
+ @cards ||= {}
107
+ @cards[name] = c
108
+ c
109
+ end
110
+
111
+ #
112
+ # Create a new subclass of Card with its own properties as defined in the
113
+ # block. You may use the Card class DSL in the block. Automatically defines a
114
+ # method for creating new objects of that class, prefixed by +new_+. For
115
+ # example, a <tt>type_of_card :fun_card</tt> defines the method +new_fun_card+
116
+ # (which operates like the +card+ method) that can be used in either a +deck+
117
+ # block or directly.
118
+ #
119
+ # Cardlike.type_of_card :playing_card do
120
+ # has :value
121
+ # has :suit
122
+ # end
123
+ #
124
+ # You can then access the card with:
125
+ #
126
+ # Cardlike.new_playing_card "Six of Spades" do
127
+ # value 6
128
+ # suit 'spades'
129
+ # end
130
+ #
131
+ # or:
132
+ #
133
+ # Cardlike.deck "Poker Deck" do
134
+ # new_playing_card "Six of Spades" do
135
+ # value 6
136
+ # suit 'spades'
137
+ # end
138
+ # end
139
+ #
140
+ def self.type_of_card(name, &block)
141
+ klass = Class.new(Card)
142
+ klass_name = name.to_s.camelize
143
+ name_underscored = name.to_s.downcase.underscore
144
+ Object.const_set(klass_name, klass) if not Object.const_defined?(klass_name)
145
+ c = Object.const_get(klass_name)
146
+ c.class_eval(&block) if block_given?
147
+
148
+ Deck.send(:define_method, "new_#{name_underscored}", lambda { |arg, &blk| card = c.create(arg, &blk); self << card; card })
149
+ self.class.send(:define_method, "new_#{name_underscored}", lambda { |arg, &blk| card = c.create(arg, &blk); @cards ||= {}; @cards[arg] = card; card })
150
+
151
+ c
152
+ end
153
+
154
+ end
@@ -0,0 +1,105 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Defining a card' do
4
+ context "using the basic card DSL" do
5
+
6
+ context "for a basic card" do
7
+ before do
8
+ @card = Cardlike.card "Fire Monster" do
9
+ text "A red-hot monster."
10
+ end
11
+ end
12
+
13
+ it "creates a Card object" do
14
+ @card.should be_a_kind_of Cardlike::Card
15
+ end
16
+
17
+ it "properly sets the card name" do
18
+ @card.name.should eq "Fire Monster"
19
+ end
20
+
21
+ it "properly sets the card text" do
22
+ @card.text.should eq "A red-hot monster."
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ context "using the custom card DSL" do
29
+ before do
30
+ @playing_card = Cardlike.type_of_card :playing_card do
31
+ has :value
32
+ has :suit
33
+ end
34
+ end
35
+
36
+ it "creates a new Class" do
37
+ @playing_card.should be_a_kind_of Class
38
+ end
39
+
40
+ it "creates a subclass of Card" do
41
+ @playing_card.should < Cardlike::Card
42
+ end
43
+
44
+ it "creates a dynamic custom Class" do
45
+ @playing_card.name.should eq "PlayingCard"
46
+ end
47
+
48
+ it "creates an accessor for the custom field" do
49
+ @playing_card.new.should respond_to :suit
50
+ end
51
+
52
+ context "when instantiated with the 'new_' factory" do
53
+ before do
54
+ deck = Cardlike.deck "Test" do
55
+ new_playing_card "Six of Spades" do
56
+ value 6
57
+ suit 'Spades'
58
+ end
59
+ end
60
+ @card = deck.first
61
+ end
62
+
63
+ it "creates a custom Card object" do
64
+ @card.should be_a_kind_of Cardlike::Card
65
+ end
66
+
67
+ it "creates an accessor for the custom field" do
68
+ @card.should respond_to :suit
69
+ end
70
+ end
71
+
72
+ context "when instantiated" do
73
+ before do
74
+ @card = @playing_card.create "Six of Spades" do
75
+ value 6
76
+ suit 'Spades'
77
+ end
78
+ end
79
+
80
+ it "creates a custom Card object" do
81
+ @card.should be_a_kind_of Cardlike::Card
82
+ end
83
+
84
+ it "creates an accessor for the custom field" do
85
+ @card.should respond_to :suit
86
+ end
87
+
88
+ it "does not affect other Card instances" do
89
+ @card2 = Cardlike.card "Castle"
90
+ @card2.should_not respond_to :suit
91
+ end
92
+
93
+ it "sets the field properly" do
94
+ @card[:suit].should eq 'Spades'
95
+ end
96
+
97
+ it "does not allow fields to be set again" do
98
+ lambda { @card.suit 'Clubs' }.should raise_error(StandardError)
99
+ end
100
+
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'A deck of cards' do
4
+ before do
5
+ @cards = []
6
+ @cards << Cardlike::Card.new(name: 'Leonardo', text: 'Has two swords.')
7
+ @cards << Cardlike::Card.new(name: 'Donatello', text: 'Has a Bo staff.')
8
+ @cards << Cardlike::Card.new(name: 'Michaelangelo', text: 'Has Nunchuku.')
9
+ @cards << Cardlike::Card.new(name: 'Raphael', text: 'Has Sai.')
10
+
11
+ @deck = Cardlike::Deck.new(name: 'Turtles', cards: @cards)
12
+ end
13
+
14
+ context 'when a card is drawn' do
15
+ before do
16
+ @drawn = @deck.draw
17
+ end
18
+
19
+ it 'is one of the cards from the deck' do
20
+ @cards.should include @drawn
21
+ end
22
+
23
+ it 'is no longer in the deck' do
24
+ @deck.should_not include @drawn
25
+ end
26
+ end
27
+
28
+ context "when a card is drawn into a Hand" do
29
+ before do
30
+ @hand = Cardlike::Hand.new(name: 'Player 1')
31
+ @drawn = @deck.draw_into @hand
32
+ end
33
+
34
+ it "inserts the card into the Hand" do
35
+ @hand.should include @drawn
36
+ end
37
+
38
+ it "removes the card from the Deck" do
39
+ @deck.should_not include @drawn
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,143 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Building a deck" do
4
+ context "with a simple card" do
5
+ before do
6
+ Cardlike.game do
7
+ deck "Simple Deck" do
8
+ card "Boring Card"
9
+ end
10
+ end
11
+ end
12
+
13
+ it "has 1 card" do
14
+ Cardlike.the_deck("Simple Deck").size.should eq 1
15
+ end
16
+
17
+ it "contains the first card" do
18
+ Cardlike.the_deck("Simple Deck").first.name.should eq "Boring Card"
19
+ end
20
+ end
21
+
22
+ context "with a bunch of cards defined in the block" do
23
+ before do
24
+ Cardlike.game do
25
+ type_of_card :playing_card do
26
+ has :value
27
+ has :suit
28
+ end
29
+
30
+ deck "Poker Deck" do
31
+ new_playing_card "Ace of Spades" do
32
+ value 11
33
+ suit 'Spades'
34
+ end
35
+
36
+ new_playing_card "Ace of Diamonds" do
37
+ value 11
38
+ suit 'Diamonds'
39
+ end
40
+
41
+ new_playing_card "Five of Clubs" do
42
+ value 5
43
+ suit 'Clubs'
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ it "contains the right number of cards" do
51
+ Cardlike.the_deck("Poker Deck").size.should eq 3
52
+ end
53
+
54
+ it "contains a card created in the block" do
55
+ Cardlike.the_deck("Poker Deck").first.name.should eq "Ace of Spades"
56
+ end
57
+
58
+ context "and another deck exists" do
59
+ before do
60
+ Cardlike.deck "Go Fish Deck" do
61
+ new_playing_card "Seven of Spades" do
62
+ value 7
63
+ suit :spades
64
+ end
65
+ end
66
+ end
67
+
68
+ it "the first deck contains the right number of cards" do
69
+ Cardlike.the_deck("Poker Deck").size.should eq 3
70
+ end
71
+
72
+ it "the new deck contains the right number of cards" do
73
+ Cardlike.the_deck("Go Fish Deck").size.should eq 1
74
+ end
75
+
76
+ end
77
+ end
78
+
79
+ context "with a bunch of cards pre-defined" do
80
+ before do
81
+ Cardlike.type_of_card :playing_card do
82
+ has :value
83
+ has :suit
84
+ end
85
+
86
+ Cardlike.new_playing_card "King of Diamonds" do
87
+ value 10
88
+ suit :diamonds
89
+ end
90
+
91
+ Cardlike.new_playing_card "Three of Clubs" do
92
+ value 3
93
+ suit :clubs
94
+ end
95
+
96
+ Cardlike.deck "Blackjack Deck" do
97
+ include_card "King of Diamonds"
98
+ include_card "Three of Clubs"
99
+ end
100
+ end
101
+
102
+ it "contains the right number of cards" do
103
+ Cardlike.the_deck("Blackjack Deck").size.should eq 2
104
+ end
105
+
106
+ it "contains a card created in the block" do
107
+ Cardlike.the_deck("Blackjack Deck").first.name.should eq "King of Diamonds"
108
+ end
109
+
110
+ end
111
+
112
+ context "with multiple copies of a card" do
113
+ before do
114
+ Cardlike.type_of_card :playing_card do
115
+ has :value
116
+ has :suit
117
+ end
118
+
119
+ Cardlike.new_playing_card "Queen of Diamonds" do
120
+ value 10
121
+ suit :diamonds
122
+ end
123
+
124
+ Cardlike.deck "Copy Deck" do
125
+ 6.times { copy_card "Queen of Diamonds" }
126
+ end
127
+ end
128
+
129
+ it "contains the right number of cards" do
130
+ Cardlike.the_deck("Copy Deck").size.should eq 6
131
+ end
132
+
133
+ it "contains a card created in the block" do
134
+ Cardlike.the_deck("Copy Deck").first.name.should eq "Queen of Diamonds"
135
+ end
136
+
137
+ it "contains another card created in the block" do
138
+ Cardlike.the_deck("Copy Deck")[2].name.should eq "Queen of Diamonds"
139
+ end
140
+
141
+ end
142
+
143
+ end
@@ -0,0 +1,4 @@
1
+ require 'cardlike'
2
+
3
+ RSpec.configure do |config|
4
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cardlike do
4
+ describe '.version' do
5
+ it 'returns correct version' do
6
+ Cardlike.version.should eq "Cardlike version #{Cardlike::VERSION}"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cardlike::Deck do
4
+ let (:deck) { Cardlike::Deck.new(cards: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']) }
5
+
6
+ describe "#shuffle" do
7
+ before do
8
+ @orig_deck = deck.dup
9
+ @shuffled = deck.shuffle
10
+ end
11
+
12
+ it "returns a Deck" do
13
+ @shuffled.should be_a_kind_of Cardlike::Deck
14
+ end
15
+
16
+ it "returns a differently-ordered deck" do
17
+ @shuffled.should_not eq @orig_deck
18
+ end
19
+
20
+ it "retains the order of the deck" do
21
+ deck.should eq @orig_deck
22
+ end
23
+ end
24
+
25
+ describe "#shuffle!" do
26
+ before do
27
+ @orig_deck = deck.dup
28
+ @shuffled = deck.shuffle!
29
+ end
30
+
31
+ it "the deck remains a Deck" do
32
+ @shuffled.should be_a_kind_of Cardlike::Deck
33
+ end
34
+
35
+ it "returns a differently-ordered deck" do
36
+ deck.should_not eq @orig_deck
37
+ end
38
+
39
+ it "changes the order of the deck" do
40
+ deck.should_not eq @orig_deck
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe "A hand of cards" do
4
+ context "with 4 cards added" do
5
+ before do
6
+ Cardlike.hand "Player 1" do
7
+ card "Boring Card One"
8
+ card "Boring Card Two"
9
+ card "Boring Card Three"
10
+ card "Boring Card Four"
11
+ end
12
+ end
13
+
14
+ it "has 4 cards" do
15
+ Cardlike.the_hand("Player 1").size.should eq 4
16
+ end
17
+
18
+ it "contains the first card" do
19
+ Cardlike.the_hand("Player 1").first.name.should eq "Boring Card One"
20
+ end
21
+
22
+ context "when removing a specific card" do
23
+ before do
24
+ @card1 = Cardlike.the_hand("Player 1").remove_card "Boring Card One"
25
+ end
26
+
27
+ it "can remove a specific card" do
28
+ @card1.name.should eq "Boring Card One"
29
+ end
30
+
31
+ it "removes the card from the Hand" do
32
+ Cardlike.the_hand("Player 1").size.should eq 3
33
+ end
34
+ end
35
+
36
+ context "when removing a card with remove_card_if" do
37
+ before do
38
+ @card1 = Cardlike.the_hand("Player 1").remove_card_if { |c| c.name =~ /Three/ }.first
39
+ end
40
+
41
+ it "removes and returns the correct card" do
42
+ @card1.name.should eq "Boring Card Three"
43
+ end
44
+
45
+ it "removes the card from the Hand" do
46
+ Cardlike.the_hand("Player 1").size.should eq 3
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cardlike do
4
+ describe ".score" do
5
+ context "with a new target" do
6
+ before do
7
+ Cardlike.clear_scores
8
+ Cardlike.score :foobar
9
+ end
10
+
11
+ it "sets a new target with the score" do
12
+ Cardlike.the_score(:foobar).should eq 1
13
+ end
14
+ end
15
+
16
+ context "with an existing target" do
17
+ before do
18
+ Cardlike.game do
19
+ 3.times { score :foobaz }
20
+ end
21
+ end
22
+
23
+ it "increments the score for the target" do
24
+ Cardlike.the_score(:foobaz).should eq 3
25
+ end
26
+ end
27
+ end
28
+
29
+ describe ".clear_scores" do
30
+ before do
31
+ Cardlike.score :barfoo
32
+ Cardlike.clear_scores
33
+ end
34
+
35
+ it "removes all scores" do
36
+ Cardlike.scores.should be_empty
37
+ end
38
+ end
39
+
40
+ describe ".scores" do
41
+ before do
42
+ Cardlike.clear_scores
43
+ Cardlike.game do
44
+ 2.times { score :foo }
45
+ 3.times { score :bar }
46
+ 1.times { score :baz }
47
+ end
48
+ end
49
+
50
+ it "returns a hash of target => score" do
51
+ hash = {:foo => 2, :bar => 3, :baz => 1}
52
+ Cardlike.scores.should eq hash
53
+ end
54
+ end
55
+
56
+ describe ".set_score" do
57
+ before do
58
+ Cardlike.clear_scores
59
+ Cardlike.game do
60
+ score :foo
61
+ score :foo
62
+ score :bar
63
+
64
+ set_score :foo, 5
65
+ end
66
+ end
67
+
68
+ it "sets a score to particular value" do
69
+ Cardlike.the_score(:foo).should eq 5
70
+ end
71
+ end
72
+ end
73
+