patience 0.1.0

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.
Files changed (56) hide show
  1. data/CHANGELOG.md +6 -0
  2. data/Gemfile +5 -0
  3. data/Gemfile.lock +17 -0
  4. data/LICENSE +19 -0
  5. data/README.md +111 -0
  6. data/Rakefile +11 -0
  7. data/bin/patience +5 -0
  8. data/lib/patience.rb +13 -0
  9. data/lib/patience/area.rb +62 -0
  10. data/lib/patience/card.rb +107 -0
  11. data/lib/patience/core_ext/class.rb +17 -0
  12. data/lib/patience/core_ext/core_ext.rb +1 -0
  13. data/lib/patience/core_ext/object.rb +37 -0
  14. data/lib/patience/core_ext/string.rb +33 -0
  15. data/lib/patience/cursor.rb +66 -0
  16. data/lib/patience/deck.rb +21 -0
  17. data/lib/patience/event_handlers/click.rb +99 -0
  18. data/lib/patience/event_handlers/drag.rb +36 -0
  19. data/lib/patience/event_handlers/drop.rb +147 -0
  20. data/lib/patience/foundation.rb +30 -0
  21. data/lib/patience/game.rb +10 -0
  22. data/lib/patience/pile.rb +78 -0
  23. data/lib/patience/processable.rb +87 -0
  24. data/lib/patience/rank.rb +56 -0
  25. data/lib/patience/scenes/game_scene.rb +66 -0
  26. data/lib/patience/sprites/card_deck.png +0 -0
  27. data/lib/patience/sprites/empty_stock.png +0 -0
  28. data/lib/patience/sprites/pile_background.png +0 -0
  29. data/lib/patience/stock.rb +20 -0
  30. data/lib/patience/suit.rb +73 -0
  31. data/lib/patience/tableau.rb +42 -0
  32. data/lib/patience/version.rb +3 -0
  33. data/lib/patience/waste.rb +18 -0
  34. data/test/patience/core_ext/test_class.rb +28 -0
  35. data/test/patience/core_ext/test_object.rb +15 -0
  36. data/test/patience/core_ext/test_string.rb +35 -0
  37. data/test/patience/event_handlers/test_click.rb +142 -0
  38. data/test/patience/event_handlers/test_drag.rb +45 -0
  39. data/test/patience/event_handlers/test_drop.rb +175 -0
  40. data/test/patience/helper.rb +8 -0
  41. data/test/patience/scenes/test_game_scene.rb +14 -0
  42. data/test/patience/test_area.rb +74 -0
  43. data/test/patience/test_card.rb +165 -0
  44. data/test/patience/test_cursor.rb +77 -0
  45. data/test/patience/test_deck.rb +53 -0
  46. data/test/patience/test_foundation.rb +38 -0
  47. data/test/patience/test_game.rb +29 -0
  48. data/test/patience/test_pile.rb +83 -0
  49. data/test/patience/test_processable.rb +159 -0
  50. data/test/patience/test_rank.rb +88 -0
  51. data/test/patience/test_stock.rb +43 -0
  52. data/test/patience/test_suit.rb +87 -0
  53. data/test/patience/test_tableau.rb +57 -0
  54. data/test/patience/test_version.rb +11 -0
  55. data/test/patience/test_waste.rb +35 -0
  56. metadata +135 -0
@@ -0,0 +1,159 @@
1
+ require_relative 'helper'
2
+
3
+ module Patience
4
+ class TestProcessable < TestCase
5
+
6
+ class Dummy
7
+ include Processable
8
+ attr_accessor :area, :card, :pile
9
+
10
+ def find_all(areas, mouse_pos)
11
+ @area = find_area_in(areas) { |area| area.hit?(mouse_pos) }
12
+ @pile = find_pile_in(areas) { |pile| pile.hit?(mouse_pos) }
13
+ @card = find_card_in(areas) { |card| card.hit?(mouse_pos) }
14
+ end
15
+ end
16
+
17
+ def setup
18
+ @dummy = Dummy.new
19
+ @mouse_pos_miss = Ray::Vector2[0, 0]
20
+ @mouse_pos_hit = Ray::Vector2[32, 166]
21
+ @deck = Deck.new
22
+ @areas = { :tableau => Tableau.new(@deck.shuffle_off! 28),
23
+ :stock => Stock.new(@deck.shuffle_off! 24),
24
+ :waste => Waste.new,
25
+ :foundation => Foundation.new }
26
+ end
27
+
28
+ test 'Processable can select entity in areas by certain conditions' do
29
+ assert_equal Tableau,
30
+ @dummy.detect_in(@areas, :area) { |area|
31
+ area.hit?(@mouse_pos_hit)
32
+ }.class
33
+ assert_equal NilClass,
34
+ @dummy.detect_in(@areas, :area) { |area|
35
+ area.hit?(@mouse_pos_miss)
36
+ }.class
37
+
38
+ assert_equal Pile,
39
+ @dummy.detect_in(@areas, :pile) { |pile|
40
+ pile.hit?(@mouse_pos_hit)
41
+ }.class
42
+ assert_equal NilClass,
43
+ @dummy.detect_in(@areas, :pile) { |pile|
44
+ pile.hit?(@mouse_pos_miss)
45
+ }.class
46
+
47
+ assert_equal Card,
48
+ @dummy.detect_in(@areas, :card) { |card|
49
+ card.hit?(@mouse_pos_hit)
50
+ }.class
51
+ assert_equal NilClass,
52
+ @dummy.detect_in(@areas, :card) { |card|
53
+ card.hit?(@mouse_pos_miss)
54
+ }.class
55
+
56
+ assert_raises(ArgumentError) do
57
+ @dummy.detect_in(@areas, :cake) { |cake| cake.hit?(@mouse_pos_miss) }
58
+ @dummy.detect_in(@areas, :yadda) { |blah| blah.hit?(@mouse_pos_hit) }
59
+ end
60
+ end
61
+
62
+ test 'Processable can find an area' do
63
+ assert_equal Tableau, @dummy.find_area_in(@areas) { |area|
64
+ area.hit?(@mouse_pos_hit)
65
+ }.class
66
+ mouse_pos_hit_stock = Ray::Vector2[31, 65]
67
+ assert_equal Stock, @dummy.find_area_in(@areas) { |area|
68
+ area.hit?(mouse_pos_hit_stock)
69
+ }.class
70
+ assert_equal NilClass, @dummy.find_area_in(@areas) { |area|
71
+ area.hit?(@mouse_pos_miss)
72
+ }.class
73
+ end
74
+
75
+ test 'Processable can find a pile' do
76
+ assert_equal Pile, @dummy.find_pile_in(@areas) { |pile|
77
+ pile.hit?(@mouse_pos_hit) && @hit_pile = pile
78
+ }.class
79
+ assert @areas[:tableau].piles.include?(@hit_pile)
80
+ assert_equal NilClass, @dummy.find_pile_in(@areas) { |pile|
81
+ pile.hit?(@mouse_pos_miss)
82
+ }.class
83
+ end
84
+
85
+ test 'Processable can find a card' do
86
+ mouse_pos_hit_stock = Ray::Vector2[31, 65]
87
+ assert_equal Card, @dummy.find_card_in(@areas) { |card|
88
+ card.hit?(@mouse_pos_hit)
89
+ }.class
90
+ assert_equal Card, @dummy.find_card_in(@areas) { |card|
91
+ card.hit?(mouse_pos_hit_stock) &&
92
+ @hit_card = card
93
+ }.class
94
+ assert @areas[:stock].cards.include?(@hit_card)
95
+ assert_equal NilClass, @dummy.find_card_in(@areas) { |card|
96
+ card.hit?(@mouse_pos_miss)
97
+ }.class
98
+ end
99
+
100
+ test 'Processable can represent data as array' do
101
+ assert_equal [nil, nil, nil], @dummy.to_a
102
+ @dummy.find_all(@areas, @mouse_pos_hit)
103
+ refute_nil @dummy.to_a.compact
104
+ assert_instance_of Tableau, @dummy.to_a.first
105
+ assert_kind_of Area, @dummy.to_a.first
106
+ assert_instance_of Pile, @dummy.to_a[1]
107
+ assert_instance_of Card, @dummy.to_a.last
108
+ end
109
+
110
+ test 'Processable can represent data as hash' do
111
+ assert_equal({ :area => nil, :pile => nil, :card => nil }, @dummy.to_h)
112
+ @dummy.find_all(@areas, @mouse_pos_hit)
113
+ refute_nil @dummy.to_h
114
+ assert_instance_of Tableau, @dummy.to_h[:area]
115
+ assert_kind_of Area, @dummy.to_h[:area]
116
+ assert_instance_of Pile, @dummy.to_h[:pile]
117
+ assert_instance_of Card, @dummy.to_h[:card]
118
+ end
119
+
120
+ test 'Processable can check for data existence' do
121
+ refute @dummy.something?
122
+ @dummy.find_all(@areas, @mouse_pos_hit)
123
+ assert @dummy.something?
124
+ end
125
+
126
+ test 'Processable can check for data abscence' do
127
+ assert @dummy.nothing?
128
+ @dummy.find_all(@areas, @mouse_pos_hit)
129
+ refute @dummy.nothing?
130
+ end
131
+
132
+ test 'Processable can count an offset' do
133
+ @dummy.find_all(@areas, @mouse_pos_hit)
134
+ assert_equal Ray::Vector2[-1, -1],
135
+ @dummy.pick_up(@areas[:tableau].cards[0], @mouse_pos_hit)
136
+ end
137
+
138
+ test 'Processable can check, if Stock has been hit' do
139
+ @dummy.find_all(@areas, Ray::Vector2[40, 40])
140
+ assert @dummy.stock?
141
+ end
142
+
143
+ test 'Processable can check, if Waste has been hit' do
144
+ @dummy.find_all(@areas, Ray::Vector2[160, 40])
145
+ assert @dummy.waste?
146
+ end
147
+
148
+ test 'Processable can check, if Tableau has been hit' do
149
+ @dummy.find_all(@areas, Ray::Vector2[32, 166])
150
+ assert @dummy.tableau?
151
+ end
152
+
153
+ test 'Processable can check, if Foundation has been hit' do
154
+ @dummy.find_all(@areas, Ray::Vector2[590, 40])
155
+ assert @dummy.foundation?
156
+ end
157
+
158
+ end
159
+ end
@@ -0,0 +1,88 @@
1
+ require_relative 'helper'
2
+
3
+ module Patience
4
+ class TestRank < TestCase
5
+
6
+ def setup
7
+ @ranks = %w[Ace Two Three Four Five Six Seven
8
+ Eight Nine Ten Jack Queen King]
9
+ @rank = Card::Rank::Five.new
10
+ end
11
+
12
+ test 'All ranks do exist' do
13
+ @ranks.each do |rank|
14
+ assert "Patience::Card::Rank::#{rank}".constantize.new
15
+ end
16
+ end
17
+
18
+ test 'Ranks are kind of Rank' do
19
+ @ranks.each do |rank|
20
+ assert_kind_of Patience::Card::Rank,
21
+ "Patience::Card::Rank::#{rank}".constantize.new
22
+ end
23
+ end
24
+
25
+ test "An unreal rank can't be created" do
26
+ assert_raises(NameError) { Patience::Card::Rank::One.new }
27
+ assert_raises(NameError) { Patience::Card::Rank::Eleven.new }
28
+ assert_raises(NameError) { Patience::Card::Rank::Joker.new }
29
+ end
30
+
31
+ test 'A rank can be represented as Fixnum' do
32
+ @ranks.each_with_index do |rank, i|
33
+ assert_equal i+1, "Patience::Card::Rank::#{rank}".constantize.new.to_i
34
+ end
35
+ end
36
+
37
+ test 'A rank can be represented as String' do
38
+ @ranks.each do |rank|
39
+ assert_equal rank, "Patience::Card::Rank::#{rank}".constantize.new.to_s
40
+ end
41
+ end
42
+
43
+ test 'Ranks can be compared to each other' do
44
+ ace = Patience::Card::Rank::Ace.new
45
+ two = Patience::Card::Rank::Two.new
46
+ ten1 = Patience::Card::Rank::Ten.new
47
+ ten2 = Patience::Card::Rank::Ten.new
48
+
49
+ assert ace < two
50
+ refute ace > two
51
+ refute ace == two
52
+ assert ace != two
53
+ assert ten1 == ten2
54
+ refute ten1 > ten2
55
+ refute ten1 < ten2
56
+ end
57
+
58
+ test "A rank can be checked, if it's higher other rank by one" do
59
+ ace = Patience::Card::Rank::Ace.new
60
+ four = Patience::Card::Rank::Four.new
61
+ six = Patience::Card::Rank::Six.new
62
+
63
+ assert @rank.higher_by_one_than?(four)
64
+ refute four.higher_by_one_than?(@rank)
65
+ refute @rank.higher_by_one_than?(ace)
66
+ refute ace.higher_by_one_than?(@rank)
67
+ refute @rank.higher_by_one_than?(six)
68
+ assert six.higher_by_one_than?(@rank)
69
+ end
70
+
71
+ test "A rank can be checked, if it's an ace" do
72
+ ace_rank = Patience::Card::Rank::Ace.new
73
+ king_rank = Patience::Card::Rank::King.new
74
+
75
+ assert ace_rank.ace?
76
+ refute king_rank.ace?
77
+ end
78
+
79
+ test "A rank can be checked, if it's a king" do
80
+ ace_rank = Patience::Card::Rank::Ace.new
81
+ king_rank = Patience::Card::Rank::King.new
82
+
83
+ assert king_rank.king?
84
+ refute ace_rank.king?
85
+ end
86
+
87
+ end
88
+ end
@@ -0,0 +1,43 @@
1
+ require_relative 'helper'
2
+
3
+ module Patience
4
+ class TestStockArea < TestCase
5
+
6
+ def setup
7
+ @deck = Deck.new
8
+ @deck.cards.shuffle!
9
+ @stock = Stock.new(@deck.shuffle_off! 24)
10
+ end
11
+
12
+ test 'Stock is a child of Area' do
13
+ assert_kind_of Area, @stock
14
+ end
15
+
16
+ test 'Initial Stock has 24 cards' do
17
+ assert_equal 24, @stock.piles[0].size
18
+ end
19
+
20
+ test 'Initial Stock has 24 cards, even if there were provided more cards' do
21
+ deck = Deck.new
22
+ stock = Stock.new(deck.shuffle_off! 52)
23
+ assert_equal 24, @stock.piles[0].size
24
+ end
25
+
26
+ test 'Stock consists of one pile' do
27
+ assert_equal 1, @stock.piles.size
28
+ end
29
+
30
+ test 'The overall position of Stock can be gotten' do
31
+ assert_equal Ray::Vector2[31, 23], @stock.pos
32
+ assert_equal Ray::Vector2[31, 23], @stock.piles.first.pos
33
+ end
34
+
35
+ test 'Stock can be disposed in the window' do
36
+ @stock.send(:pos=, [0, 0])
37
+ assert_equal Ray::Vector2[0, 0], @stock.pos
38
+ @stock.send(:pos=, [200, 300])
39
+ assert_equal Ray::Vector2[200, 300], @stock.pos
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,87 @@
1
+ require_relative 'helper'
2
+
3
+ module Patience
4
+ class TestCardSuit < TestCase
5
+
6
+ def setup
7
+ @suits = %w[Heart Diamond Spade Club]
8
+ @suit = Patience::Card::Suit::Diamond.new
9
+ end
10
+
11
+ test 'All suits do exist' do
12
+ @suits.each do |suit|
13
+ assert "Patience::Card::Suit::#{suit}".constantize.new
14
+ end
15
+ end
16
+
17
+ test 'Suits are kind of Suit' do
18
+ @suits.each do |suit|
19
+ assert_kind_of Patience::Card::Suit,
20
+ "Patience::Card::Suit::#{suit}".constantize.new
21
+ end
22
+ end
23
+
24
+ test 'A suit can be represented as Fixnum' do
25
+ @suits.each_with_index do |suit, i|
26
+ assert_equal i+1, "Patience::Card::Suit::#{suit}".constantize.new
27
+ end
28
+ end
29
+
30
+ test 'A suit can be represented as String' do
31
+ @suits.each do |suit|
32
+ assert_equal suit+'s',
33
+ "Patience::Card::Suit::#{suit}".constantize.new.to_s
34
+ end
35
+ end
36
+
37
+ test 'The Heart suit is red' do
38
+ assert Patience::Card::Suit::Heart.new.red?
39
+ refute Patience::Card::Suit::Heart.new.black?
40
+ end
41
+
42
+ test 'The Diamond suit is red' do
43
+ assert Patience::Card::Suit::Diamond.new.red?
44
+ refute Patience::Card::Suit::Diamond.new.black?
45
+ end
46
+
47
+ test 'The Spade suit is black' do
48
+ assert Patience::Card::Suit::Spade.new.black?
49
+ refute Patience::Card::Suit::Spade.new.red?
50
+ end
51
+
52
+ test 'The Club suit is black' do
53
+ assert Patience::Card::Suit::Club.new.black?
54
+ refute Patience::Card::Suit::Club.new.red?
55
+ end
56
+
57
+ test 'Suits can be compared to each other' do
58
+ spades = Patience::Card::Suit::Spade.new
59
+ hearts = Patience::Card::Suit::Heart.new
60
+ diamonds1 = Patience::Card::Suit::Diamond.new
61
+ diamonds2 = Patience::Card::Suit::Diamond.new
62
+
63
+ refute spades == hearts
64
+ assert spades != hearts
65
+ assert diamonds1 == diamonds2
66
+ end
67
+
68
+ test "Suits can be checked, if they're of the same color" do
69
+ red_suit = Patience::Card::Suit::Heart.new
70
+ black_suit = Patience::Card::Suit::Spade.new
71
+ assert @suit.same_color?(red_suit)
72
+ assert red_suit.same_color?(@suit)
73
+ refute @suit.same_color?(black_suit)
74
+ refute black_suit.same_color?(@suit)
75
+ end
76
+
77
+ test "Suits can be checked, if they're of the different colors" do
78
+ red_suit = Patience::Card::Suit::Heart.new
79
+ black_suit = Patience::Card::Suit::Spade.new
80
+ refute @suit.different_color?(red_suit)
81
+ refute red_suit.different_color?(@suit)
82
+ assert @suit.different_color?(black_suit)
83
+ assert black_suit.different_color?(@suit)
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,57 @@
1
+ require_relative 'helper'
2
+
3
+ module Patience
4
+ class TestTableauArea < TestCase
5
+
6
+ def setup
7
+ @deck = Deck.new
8
+ @tableau = Tableau.new(@deck.shuffle_off! 28)
9
+ end
10
+
11
+ test 'Tableau is a child of Area' do
12
+ assert_kind_of Area, @tableau
13
+ end
14
+
15
+ test 'Initial Tableau has 28 cards' do
16
+ cards = @tableau.piles.inject([]) { |cards, pile| cards << pile.cards }
17
+ assert_equal 28, cards.flatten.size
18
+ end
19
+
20
+ # Test, that initial tableau pile contains N+1 cards,
21
+ # where N is an index number of the pile, starting from 0.
22
+ test 'Initial Tableau piles have correct amount of cards' do
23
+ @tableau.piles.each_with_index do |pile, i|
24
+ assert_equal i+1, pile.size
25
+ end
26
+ end
27
+
28
+ test 'The overall position of Tableau can be gotten' do
29
+ assert_equal Ray::Vector2[31, 165], @tableau.pos
30
+ assert_equal Ray::Vector2[31, 165], @tableau.piles.first.pos
31
+ end
32
+
33
+ test 'Particular position of a pile in Tableau can be gotten' do
34
+ assert_equal Ray::Vector2[141, 165], @tableau.piles[1].pos
35
+ assert_equal Ray::Vector2[251, 165], @tableau.piles[2].pos
36
+ assert_equal Ray::Vector2[691, 165], @tableau.piles.last.pos
37
+ end
38
+
39
+ test 'Tableau can be disposed in the window' do
40
+ @tableau.send(:pos=, [0, 0])
41
+ assert_equal Ray::Vector2[0, 0], @tableau.pos
42
+ assert_equal Ray::Vector2[660, 0], @tableau.piles.last.pos
43
+ @tableau.send(:pos=, [200, 300])
44
+ assert_equal Ray::Vector2[200, 300], @tableau.pos
45
+ assert_equal Ray::Vector2[860, 300], @tableau.piles.last.pos
46
+ end
47
+
48
+ test 'Cards in Tableau have a margin along the Y axis' do
49
+ assert_equal Ray::Vector2[31, 165], @tableau.piles[0].cards[0].pos
50
+ assert_equal Ray::Vector2[251, 191], @tableau.piles[2].cards[1].pos
51
+ assert_equal Ray::Vector2[471, 191], @tableau.piles[4].cards[1].pos
52
+ assert_equal Ray::Vector2[581, 217], @tableau.piles[5].cards[2].pos
53
+ assert_equal Ray::Vector2[691, 321], @tableau.piles.last.cards.last.pos
54
+ end
55
+
56
+ end
57
+ end
@@ -0,0 +1,11 @@
1
+ require_relative 'helper'
2
+
3
+ module Patience
4
+ class TestVERSION < TestCase
5
+
6
+ test 'The Patience version is correct' do
7
+ assert_equal "0.1.0", Patience::VERSION
8
+ end
9
+
10
+ end
11
+ end