patience 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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