leonardo-bridge 0.4.3 → 0.6.5
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 +5 -13
- data/LICENSE.txt +1 -1
- data/README.md +10 -7
- data/bin/leo-console +1 -0
- data/bin/leo-play +23 -4
- data/bridge.gemspec +2 -6
- data/lib/bridge.rb +2 -1
- data/lib/bridge/auction.rb +0 -1
- data/lib/bridge/board.rb +0 -1
- data/lib/bridge/call.rb +0 -1
- data/lib/bridge/contract.rb +0 -3
- data/lib/bridge/deal.rb +9 -6
- data/lib/bridge/deck.rb +13 -2
- data/lib/bridge/game.rb +55 -7
- data/lib/bridge/hand.rb +1 -1
- data/lib/bridge/player.rb +1 -3
- data/lib/bridge/result.rb +5 -5
- data/lib/bridge/trick_play.rb +0 -1
- data/lib/bridge/version.rb +1 -1
- data/spec/auction_spec.rb +23 -23
- data/spec/board_spec.rb +8 -8
- data/spec/bridge_spec.rb +16 -16
- data/spec/call_spec.rb +19 -19
- data/spec/card_spec.rb +21 -21
- data/spec/deck_spec.rb +2 -2
- data/spec/enum_spec.rb +7 -7
- data/spec/game_spec.rb +169 -85
- data/spec/hand_spec.rb +3 -3
- data/spec/player_spec.rb +3 -3
- data/spec/result_spec.rb +5 -5
- data/spec/spec_helper.rb +0 -7
- data/spec/support/auction_helper.rb +3 -3
- data/spec/trick_play_spec.rb +44 -45
- data/spec/trick_spec.rb +4 -4
- metadata +18 -83
- data/lib/bridge/db.rb +0 -27
- data/lib/redis_model.rb +0 -137
- data/lib/uuid.rb +0 -280
- data/spec/db_spec.rb +0 -19
- data/spec/redis_model_spec.rb +0 -50
- data/spec/support/test_model.rb +0 -3
data/spec/board_spec.rb
CHANGED
@@ -3,17 +3,17 @@ require 'spec_helper'
|
|
3
3
|
describe Board do
|
4
4
|
subject { Board.first }
|
5
5
|
|
6
|
-
it { subject.number.
|
7
|
-
it { subject.vulnerability.
|
8
|
-
it { subject.dealer.
|
9
|
-
it { subject.deal.hands.size.
|
10
|
-
it { subject.deal.hands.each { |h| h.size.
|
6
|
+
it { expect(subject.number).to eq(1) }
|
7
|
+
it { expect(subject.vulnerability).to eq(0) }
|
8
|
+
it { expect(subject.dealer).to eq(0) }
|
9
|
+
it { expect(subject.deal.hands.size).to eq(4) }
|
10
|
+
it { subject.deal.hands.each { |h| expect(h.size).to eq(13) } }
|
11
11
|
|
12
12
|
describe '#next' do
|
13
13
|
let(:next_board) { subject.next }
|
14
14
|
|
15
|
-
it { next_board.number.
|
16
|
-
it { next_board.vulnerability.
|
17
|
-
it { next_board.dealer.
|
15
|
+
it { expect(next_board.number).to eq(2) }
|
16
|
+
it { expect(next_board.vulnerability).to eq(1) }
|
17
|
+
it { expect(next_board.dealer).to eq(1) }
|
18
18
|
end
|
19
19
|
end
|
data/spec/bridge_spec.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Direction do
|
4
|
-
it { Direction.north.
|
5
|
-
it { Direction.east.
|
6
|
-
it { Direction.south.
|
7
|
-
it { Direction.west.
|
4
|
+
it { expect(Direction.north).to eq(0) }
|
5
|
+
it { expect(Direction.east).to eq(1) }
|
6
|
+
it { expect(Direction.south).to eq(2) }
|
7
|
+
it { expect(Direction.west).to eq(3) }
|
8
8
|
|
9
|
-
it { Direction.next(Direction.north).
|
10
|
-
it { Direction.next(Direction.east).
|
11
|
-
it { Direction.next(Direction.south).
|
12
|
-
it { Direction.next(Direction.west).
|
9
|
+
it { expect(Direction.next(Direction.north)).to eq(Direction.east) }
|
10
|
+
it { expect(Direction.next(Direction.east)).to eq(Direction.south) }
|
11
|
+
it { expect(Direction.next(Direction.south)).to eq(Direction.west) }
|
12
|
+
it { expect(Direction.next(Direction.west)).to eq(Direction.north) }
|
13
13
|
end
|
14
14
|
|
15
15
|
describe Vulnerability do
|
16
|
-
it { Vulnerability.none.
|
17
|
-
it { Vulnerability.north_south.
|
18
|
-
it { Vulnerability.east_west.
|
19
|
-
it { Vulnerability.all.
|
16
|
+
it { expect(Vulnerability.none).to eq(0) }
|
17
|
+
it { expect(Vulnerability.north_south).to eq(1) }
|
18
|
+
it { expect(Vulnerability.east_west).to eq(2) }
|
19
|
+
it { expect(Vulnerability.all).to eq(3) }
|
20
20
|
|
21
|
-
it { Vulnerability.next(Vulnerability.none).
|
22
|
-
it { Vulnerability.next(Vulnerability.north_south).
|
23
|
-
it { Vulnerability.next(Vulnerability.east_west).
|
24
|
-
it { Vulnerability.next(Vulnerability.all).
|
21
|
+
it { expect(Vulnerability.next(Vulnerability.none)).to eq(Vulnerability.north_south) }
|
22
|
+
it { expect(Vulnerability.next(Vulnerability.north_south)).to eq(Vulnerability.east_west) }
|
23
|
+
it { expect(Vulnerability.next(Vulnerability.east_west)).to eq(Vulnerability.all) }
|
24
|
+
it { expect(Vulnerability.next(Vulnerability.all)).to eq(Vulnerability.none) }
|
25
25
|
end
|
data/spec/call_spec.rb
CHANGED
@@ -2,43 +2,43 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Call do
|
4
4
|
it 'can create a pass from a string' do
|
5
|
-
Call.from_string('pass').
|
6
|
-
Call.from_string('p').
|
7
|
-
Call.from_string('Pass').
|
8
|
-
Call.from_string('P').
|
5
|
+
expect(Call.from_string('pass')).to be_a(Pass)
|
6
|
+
expect(Call.from_string('p')).to be_a(Pass)
|
7
|
+
expect(Call.from_string('Pass')).to be_a(Pass)
|
8
|
+
expect(Call.from_string('P')).to be_a(Pass)
|
9
9
|
end
|
10
10
|
|
11
11
|
it 'can create a double from a string' do
|
12
|
-
Call.from_string('double').
|
13
|
-
Call.from_string('d').
|
12
|
+
expect(Call.from_string('double')).to be_a(Double)
|
13
|
+
expect(Call.from_string('d')).to be_a(Double)
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'can create a redouble from a string' do
|
17
|
-
Call.from_string('redouble').
|
18
|
-
Call.from_string('r').
|
17
|
+
expect(Call.from_string('redouble')).to be_a(Redouble)
|
18
|
+
expect(Call.from_string('r')).to be_a(Redouble)
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'can create a bid from a string' do
|
22
22
|
c = Call.from_string('bid one heart')
|
23
|
-
c.
|
24
|
-
c.strain.
|
25
|
-
c.level.
|
23
|
+
expect(c).to be_a(Bid)
|
24
|
+
expect(c.strain).to eq(Strain.heart)
|
25
|
+
expect(c.level).to eq(Level.one)
|
26
26
|
|
27
27
|
c = Call.from_string('b one heart')
|
28
|
-
c.strain.
|
29
|
-
c.level.
|
28
|
+
expect(c.strain).to eq(Strain.heart)
|
29
|
+
expect(c.level).to eq(Level.one)
|
30
30
|
|
31
31
|
c = Call.from_string('b one no trump')
|
32
|
-
c.strain.
|
33
|
-
c.level.
|
32
|
+
expect(c.strain).to eq(Strain.no_trump)
|
33
|
+
expect(c.level).to eq(Level.one)
|
34
34
|
|
35
35
|
c = Call.from_string('b one no_trump')
|
36
|
-
c.strain.
|
37
|
-
c.level.
|
36
|
+
expect(c.strain).to eq(Strain.no_trump)
|
37
|
+
expect(c.level).to eq(Level.one)
|
38
38
|
end
|
39
39
|
|
40
40
|
it 'returns all available calls' do
|
41
|
-
Call.all.
|
42
|
-
Call.all.size.
|
41
|
+
expect(Call.all).to be_a(Array)
|
42
|
+
expect(Call.all.size).to eq(38)
|
43
43
|
end
|
44
44
|
end
|
data/spec/card_spec.rb
CHANGED
@@ -5,38 +5,38 @@ describe Card do
|
|
5
5
|
let(:card){ Card.new('2', 'C') }
|
6
6
|
|
7
7
|
it "sets rank on initialize" do
|
8
|
-
card.rank.
|
8
|
+
expect(card.rank).to eq('2')
|
9
9
|
end
|
10
10
|
|
11
11
|
it "sets suit on initialize" do
|
12
|
-
card.suit.
|
12
|
+
expect(card.suit).to eq('C')
|
13
13
|
end
|
14
14
|
|
15
15
|
it "returns a string with rank and suit" do
|
16
|
-
card.to_s.
|
16
|
+
expect(card.to_s).to eq('2C')
|
17
17
|
end
|
18
18
|
|
19
|
-
it { card.suit_i.
|
19
|
+
it { expect(card.suit_i).to eq(Suit.club) }
|
20
20
|
|
21
21
|
describe "honour" do
|
22
22
|
it "has an honour of 4 when rank is A" do
|
23
|
-
Card.new('A','H').honour.
|
23
|
+
expect(Card.new('A','H').honour).to eq(4)
|
24
24
|
end
|
25
25
|
|
26
26
|
it "has an honour of 3 when rank is K" do
|
27
|
-
Card.new('K','H').honour.
|
27
|
+
expect(Card.new('K','H').honour).to eq(3)
|
28
28
|
end
|
29
29
|
|
30
30
|
it "has an honour of 2 when rank is Q" do
|
31
|
-
Card.new('Q','H').honour.
|
31
|
+
expect(Card.new('Q','H').honour).to eq(2)
|
32
32
|
end
|
33
33
|
|
34
34
|
it "has an honour of 1 when rank is J" do
|
35
|
-
Card.new('J','H').honour.
|
35
|
+
expect(Card.new('J','H').honour).to eq(1)
|
36
36
|
end
|
37
37
|
|
38
38
|
it "has an honour of 0 when rank is a number" do
|
39
|
-
Card.new('5','H').honour.
|
39
|
+
expect(Card.new('5','H').honour).to eq(0)
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -46,10 +46,10 @@ describe Card do
|
|
46
46
|
it { expect { Card.from_string('GT') }.to raise_error(CardError) }
|
47
47
|
it { expect { Card.from_string('GC') }.to raise_error(CardError) }
|
48
48
|
it { expect { Card.from_string('2F') }.to raise_error(CardError) }
|
49
|
-
it { Card.from_string('10C').
|
50
|
-
it { Card.from_string('2C').
|
51
|
-
it { Card.from_string('2C').rank.
|
52
|
-
it { Card.from_string('2C').suit.
|
49
|
+
it { expect(Card.from_string('10C')).to eq(Card.new('10','C')) }
|
50
|
+
it { expect(Card.from_string('2C')).to eq(card) }
|
51
|
+
it { expect(Card.from_string('2C').rank).to eq('2') }
|
52
|
+
it { expect(Card.from_string('2C').suit).to eq('C') }
|
53
53
|
end
|
54
54
|
|
55
55
|
describe "<=>" do
|
@@ -76,20 +76,20 @@ describe Card do
|
|
76
76
|
end
|
77
77
|
|
78
78
|
it "compares to other cards" do
|
79
|
-
(Card.new('2','C') < Card.new('2','D')).
|
80
|
-
(Card.new('2','C') > Card.new('2','D')).
|
81
|
-
(Card.new('2','C') == Card.new('2','D')).
|
79
|
+
expect(Card.new('2','C') < Card.new('2','D')).to eq(true)
|
80
|
+
expect(Card.new('2','C') > Card.new('2','D')).to eq(false)
|
81
|
+
expect(Card.new('2','C') == Card.new('2','D')).to eq(false)
|
82
82
|
end
|
83
83
|
|
84
84
|
it "compares to other cards of same suit" do
|
85
|
-
(Card.new('2','C') < Card.new('J','C')).
|
86
|
-
(Card.new('2','C') > Card.new('J','C')).
|
87
|
-
(Card.new('2','C') == Card.new('J','C')).
|
85
|
+
expect(Card.new('2','C') < Card.new('J','C')).to eq(true)
|
86
|
+
expect(Card.new('2','C') > Card.new('J','C')).to eq(false)
|
87
|
+
expect(Card.new('2','C') == Card.new('J','C')).to eq(false)
|
88
88
|
end
|
89
89
|
|
90
90
|
it "compares as equal to same card" do
|
91
|
-
cards.each { |c| c.
|
92
|
-
cards.each_index { |i| cards[i].
|
91
|
+
cards.each { |c| expect(c).to eq(c) } # same card
|
92
|
+
cards.each_index { |i| expect(cards[i]).to eq(other_cards[i]) } # same card, different object
|
93
93
|
end
|
94
94
|
end
|
95
95
|
end
|
data/spec/deck_spec.rb
CHANGED
@@ -4,11 +4,11 @@ describe Deck do
|
|
4
4
|
|
5
5
|
subject { Deck.new }
|
6
6
|
|
7
|
-
it { subject.size.
|
7
|
+
it { expect(subject.size).to eq(52) }
|
8
8
|
|
9
9
|
it "should be shuffleable" do
|
10
10
|
old_deck = subject.clone
|
11
11
|
subject.shuffle!
|
12
|
-
subject.
|
12
|
+
expect(subject).to_not eq(old_deck)
|
13
13
|
end
|
14
14
|
end
|
data/spec/enum_spec.rb
CHANGED
@@ -4,11 +4,11 @@ describe Enum do
|
|
4
4
|
|
5
5
|
subject { TestEnum }
|
6
6
|
|
7
|
-
it { subject.size.
|
8
|
-
it { subject.first.
|
9
|
-
it { subject.next(0).
|
10
|
-
it { subject[0].
|
11
|
-
it { subject.oh.
|
12
|
-
it { subject.name(0).
|
13
|
-
it { subject.each.
|
7
|
+
it { expect(subject.size).to eq(4) }
|
8
|
+
it { expect(subject.first).to eq(0) }
|
9
|
+
it { expect(subject.next(0)).to eq(1) }
|
10
|
+
it { expect(subject[0]).to eq(0) }
|
11
|
+
it { expect(subject.oh).to eq(0) }
|
12
|
+
it { expect(subject.name(0)).to eq('oh') }
|
13
|
+
it { expect(subject.each).to be_a(Enumerator) }
|
14
14
|
end
|
data/spec/game_spec.rb
CHANGED
@@ -11,18 +11,18 @@ describe Game do
|
|
11
11
|
)
|
12
12
|
}
|
13
13
|
|
14
|
-
it { subject.in_progress
|
15
|
-
it { subject.state.
|
14
|
+
it { expect(subject.in_progress?).to eq(false) }
|
15
|
+
it { expect(subject.state).to eq(:new) }
|
16
16
|
it { expect { subject.get_turn }.to raise_error(GameError) }
|
17
17
|
|
18
18
|
describe 'in #rubber_mode' do
|
19
19
|
subject { Game.new(:rubber_mode => true) }
|
20
20
|
|
21
21
|
it 'sets rubber mode' do
|
22
|
-
subject.rubbers.
|
22
|
+
expect(subject.rubbers).to eq([])
|
23
23
|
end
|
24
24
|
|
25
|
-
it "
|
25
|
+
it ").to set vulnerability" do
|
26
26
|
subject.start!(board)
|
27
27
|
subject.board.vulnerability = Vulnerability.none
|
28
28
|
end
|
@@ -30,28 +30,28 @@ describe Game do
|
|
30
30
|
|
31
31
|
it 'should start with the first board by default' do
|
32
32
|
subject.start!
|
33
|
-
subject.board.number.
|
33
|
+
expect(subject.board.number).to eq(1)
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'should increment boards' do
|
37
37
|
g = Game.new(:board => Board.first)
|
38
38
|
g.start!
|
39
|
-
g.board.number.
|
39
|
+
expect(g.board.number).to eq(2)
|
40
40
|
end
|
41
41
|
|
42
42
|
describe '#start!' do
|
43
43
|
before { subject.start! }
|
44
44
|
|
45
|
-
it { subject.state.
|
46
|
-
it { subject.in_progress
|
47
|
-
it { subject.get_turn.
|
45
|
+
it { expect(subject.state).to eq(:auction) }
|
46
|
+
it { expect(subject.in_progress?).to eq(true) }
|
47
|
+
it { expect(subject.get_turn).to eq(subject.board.dealer) }
|
48
48
|
end
|
49
49
|
|
50
50
|
describe '#start with board' do
|
51
51
|
before { subject.start!(board) }
|
52
52
|
|
53
|
-
it { subject.board.
|
54
|
-
it { subject.get_turn.
|
53
|
+
it { expect(subject.board).to eq(board) }
|
54
|
+
it { expect(subject.get_turn).to eq(board.dealer) }
|
55
55
|
end
|
56
56
|
|
57
57
|
describe 'player methods' do
|
@@ -61,15 +61,15 @@ describe Game do
|
|
61
61
|
players[position] = subject.add_player(position)
|
62
62
|
end
|
63
63
|
}
|
64
|
-
it { subject.players.size.
|
65
|
-
it { expect { subject.add_player(Direction.north) }.to raise_error }
|
64
|
+
it { expect(subject.players.size).to eq(4) }
|
65
|
+
it { expect { subject.add_player(Direction.north) }.to raise_error(GameError) }
|
66
66
|
|
67
67
|
it 'should be able to remove all players' do
|
68
68
|
Direction.each do |position|
|
69
69
|
expect { subject.remove_player(position) }.to_not raise_error
|
70
70
|
end
|
71
71
|
|
72
|
-
expect { subject.remove_player(Direction.north) }.to raise_error
|
72
|
+
expect { subject.remove_player(Direction.north) }.to raise_error(GameError)
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
@@ -97,15 +97,15 @@ describe Game do
|
|
97
97
|
subject.start!(board)
|
98
98
|
}
|
99
99
|
|
100
|
-
it '
|
101
|
-
subject.get_state[:calls].size.
|
102
|
-
subject.get_state[:available_calls].size.
|
100
|
+
it 'to return all available calls at start' do
|
101
|
+
expect(subject.get_state[:calls].size).to eq(38)
|
102
|
+
expect(subject.get_state[:available_calls].size).to eq(36)
|
103
103
|
end
|
104
104
|
|
105
105
|
it 'should return available calls' do
|
106
106
|
@players[subject.get_turn].make_call(Call.from_string('b two heart'))
|
107
|
-
subject.get_state[:calls].size.
|
108
|
-
subject.get_state[:available_calls].size.
|
107
|
+
expect(subject.get_state[:calls].size).to eq(38)
|
108
|
+
expect(subject.get_state[:available_calls].size).to eq(29)
|
109
109
|
end
|
110
110
|
end
|
111
111
|
|
@@ -121,12 +121,98 @@ describe Game do
|
|
121
121
|
|
122
122
|
it 'should return game state' do
|
123
123
|
state = subject.get_state
|
124
|
-
state.
|
125
|
-
state[:state].
|
126
|
-
state[:available_calls].
|
127
|
-
state[:auction].size.
|
128
|
-
state[:turn].
|
129
|
-
state[:play].
|
124
|
+
expect(state).to be_a(Hash)
|
125
|
+
expect(state[:state]).to eq(:finished)
|
126
|
+
expect(state[:available_calls]).to eq([])
|
127
|
+
expect(state[:auction].size).to eq(4)
|
128
|
+
expect(state[:turn]).to eq(nil)
|
129
|
+
expect(state[:play]).to eq(nil)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context '#undo' do
|
134
|
+
before { subject.start!(board) }
|
135
|
+
|
136
|
+
it 'should work during auction' do
|
137
|
+
turn = board.dealer
|
138
|
+
calls.first(3).each do |c|
|
139
|
+
players[turn].make_call(c) # Each player passes.
|
140
|
+
turn = Direction[(turn+1) % Direction.size]
|
141
|
+
end
|
142
|
+
call_size = subject.auction.calls.size
|
143
|
+
|
144
|
+
expect(subject.undo!).to eq(true)
|
145
|
+
expect(subject.auction.calls.size).to eq(call_size-1)
|
146
|
+
expect(subject.get_turn).to eq(turn-1)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should not work with a completed auction and no cards' do
|
150
|
+
turn = board.dealer
|
151
|
+
calls.each do |c|
|
152
|
+
players[turn].make_call(c) # Each player passes.
|
153
|
+
turn = Direction[(turn+1) % Direction.size]
|
154
|
+
end
|
155
|
+
call_size = subject.auction.calls.size
|
156
|
+
turn = subject.get_turn
|
157
|
+
expect(subject.undo!).to eq(false)
|
158
|
+
expect(subject.auction.calls.size).to eq(call_size)
|
159
|
+
expect(subject.get_turn).to eq(turn)
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'with complete auction' do
|
163
|
+
before {
|
164
|
+
turn = board.dealer
|
165
|
+
calls.each do |c|
|
166
|
+
players[turn].make_call(c) # Each player passes.
|
167
|
+
turn = Direction[(turn+1) % Direction.size]
|
168
|
+
end
|
169
|
+
}
|
170
|
+
|
171
|
+
it 'should work while in play' do
|
172
|
+
5.times do # play 3 cards
|
173
|
+
turn = subject.get_turn
|
174
|
+
# Find a valid card.
|
175
|
+
board.deal[turn].each do |card|
|
176
|
+
if subject.play.valid_play?(card, turn, board.deal[turn])
|
177
|
+
if turn == subject.play.dummy
|
178
|
+
self.players[subject.play.declarer].play_card(card)
|
179
|
+
else
|
180
|
+
self.players[turn].play_card(card)
|
181
|
+
end
|
182
|
+
break
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
turn = subject.get_turn
|
188
|
+
|
189
|
+
# We can undo all the way to the bank baby
|
190
|
+
expect(subject.undo!).to eq(true)
|
191
|
+
expect(subject.play.get_current_trick.cards.compact.size).to eq(4)
|
192
|
+
expect(subject.get_turn).to eq(turn-1 % 4)
|
193
|
+
|
194
|
+
p1 = subject.play.whose_turn
|
195
|
+
expect(subject.undo!).to eq(true)
|
196
|
+
p2 = subject.play.whose_turn
|
197
|
+
|
198
|
+
expect(p1).to_not eq(p2)
|
199
|
+
count = subject.board.deal.hands[p2].size
|
200
|
+
|
201
|
+
expect(subject.play.get_current_trick.cards.compact.size).to eq(3)
|
202
|
+
expect(subject.board.deal.hands[p2].size).to eq(count+1)
|
203
|
+
|
204
|
+
expect(subject.undo!).to eq(true)
|
205
|
+
expect(subject.play.get_current_trick.cards.compact.size).to eq(2)
|
206
|
+
|
207
|
+
expect(subject.undo!).to eq(true)
|
208
|
+
expect(subject.play.get_current_trick.cards.compact.size).to eq(1)
|
209
|
+
|
210
|
+
expect(subject.undo!).to eq(true)
|
211
|
+
expect(subject.play.get_current_trick.cards.compact.size).to eq(0)
|
212
|
+
|
213
|
+
expect(subject.undo!).to eq(false)
|
214
|
+
expect(subject.play.get_current_trick.cards.compact.size).to eq(0)
|
215
|
+
end
|
130
216
|
end
|
131
217
|
end
|
132
218
|
|
@@ -142,27 +228,27 @@ describe Game do
|
|
142
228
|
|
143
229
|
it 'should return game state' do
|
144
230
|
state = subject.get_state
|
145
|
-
state.
|
146
|
-
state[:auction].size.
|
147
|
-
state[:available_calls].
|
148
|
-
state[:play].
|
149
|
-
state[:state].
|
150
|
-
state[:turn].
|
151
|
-
Strain.name(state[:play][:trumps]).
|
152
|
-
state[:contract][:bid].to_s.
|
153
|
-
Direction.name(state[:play][:declarer]).
|
154
|
-
Direction.name(state[:play][:dummy]).
|
155
|
-
state[:play][:declarer_trick_count].
|
156
|
-
state[:play][:defender_trick_count].
|
157
|
-
state[:play][:tricks].
|
158
|
-
state[:play][:tricks].size.
|
231
|
+
expect(state).to be_a(Hash)
|
232
|
+
expect(state[:auction].size).to eq(13)
|
233
|
+
expect(state[:available_calls]).to eq([])
|
234
|
+
expect(state[:play]).to be_a(Hash)
|
235
|
+
expect(state[:state]).to eq(:playing)
|
236
|
+
expect(state[:turn]).to eq(2) # this is now game turn
|
237
|
+
expect(Strain.name(state[:play][:trumps])).to eq('heart')
|
238
|
+
expect(state[:contract][:bid].to_s).to eq('two heart')
|
239
|
+
expect(Direction.name(state[:play][:declarer])).to eq('east')
|
240
|
+
expect(Direction.name(state[:play][:dummy])).to eq('west')
|
241
|
+
expect(state[:play][:declarer_trick_count]).to eq(0)
|
242
|
+
expect(state[:play][:defender_trick_count]).to eq(0)
|
243
|
+
expect(state[:play][:tricks]).to be_a(Array)
|
244
|
+
expect(state[:play][:tricks].size).to eq(0)
|
159
245
|
end
|
160
246
|
|
161
247
|
it 'should return well-formed json state' do
|
162
248
|
state = JSON.parse(subject.get_state.to_json)
|
163
|
-
state['state'].
|
164
|
-
state['auction'].size.
|
165
|
-
state['auction'].first.
|
249
|
+
expect(state['state']).to eq('playing')
|
250
|
+
expect(state['auction'].size).to eq(13)
|
251
|
+
expect(state['auction'].first).to eq('pass')
|
166
252
|
end
|
167
253
|
|
168
254
|
context 'in play' do
|
@@ -178,61 +264,59 @@ describe Game do
|
|
178
264
|
# go to json and test that for sanity
|
179
265
|
state = JSON.parse(state.to_json)
|
180
266
|
dummy = state['play']['dummy']
|
181
|
-
dummy.
|
182
|
-
state['play']['played'][@turn.to_s].first.
|
183
|
-
state['board']['deal'][dummy.to_s].
|
267
|
+
expect(dummy).to eq(3)
|
268
|
+
expect(state['play']['played'][@turn.to_s].first).to eq(@card.to_s)
|
269
|
+
expect(state['board']['deal'][dummy.to_s]).to eq(subject.get_hand(dummy).map { |c| c.to_s })
|
184
270
|
end
|
185
271
|
|
186
272
|
it 'can perform a claim issued by a defender' do
|
187
273
|
subject.claim(Direction.north, 9)
|
188
|
-
subject.results.size.
|
189
|
-
subject.state.
|
274
|
+
expect(subject.results.size).to eq(1)
|
275
|
+
expect(subject.state).to eq(:finished)
|
190
276
|
result = subject.results.first
|
191
|
-
result.claimed_by.
|
192
|
-
result.claimed.
|
193
|
-
result.tricks_made.
|
194
|
-
result.score.
|
277
|
+
expect(result.claimed_by).to eq(Direction.north)
|
278
|
+
expect(result.claimed).to eq(9)
|
279
|
+
expect(result.tricks_made).to eq(4)
|
280
|
+
expect(result.score).to eq(-400)
|
195
281
|
end
|
196
282
|
|
197
283
|
it 'can perform a zero claim issued by a defender' do
|
198
284
|
subject.claim(Direction.north, 0)
|
199
|
-
subject.results.size.
|
200
|
-
subject.state.
|
285
|
+
expect(subject.results.size).to eq(1)
|
286
|
+
expect(subject.state).to eq(:finished)
|
201
287
|
result = subject.results.first
|
202
|
-
result.claimed_by.
|
203
|
-
result.claimed.
|
204
|
-
result.tricks_made.
|
205
|
-
result.score.
|
288
|
+
expect(result.claimed_by).to eq(Direction.north)
|
289
|
+
expect(result.claimed).to eq(0)
|
290
|
+
expect(result.tricks_made).to eq(13)
|
291
|
+
expect(result.score).to eq(260)
|
206
292
|
end
|
207
293
|
|
208
294
|
it 'can perform a claim issued by a declarer' do
|
209
295
|
subject.claim(Direction.east, 9)
|
210
|
-
subject.results.size.
|
211
|
-
subject.state.
|
212
|
-
state = subject.get_state
|
296
|
+
expect(subject.results.size).to eq(1)
|
297
|
+
expect(subject.state).to eq(:finished)
|
213
298
|
result = subject.results.first
|
214
|
-
result.claimed_by.
|
215
|
-
result.claimed.
|
216
|
-
result.tricks_made.
|
217
|
-
result.score.
|
299
|
+
expect(result.claimed_by).to eq(Direction.east)
|
300
|
+
expect(result.claimed).to eq(9)
|
301
|
+
expect(result.tricks_made).to eq(9)
|
302
|
+
expect(result.score).to eq(140)
|
218
303
|
end
|
219
304
|
|
220
305
|
it 'can perform a zero claim issued by a declarer' do
|
221
306
|
subject.claim(Direction.east, 0)
|
222
|
-
subject.results.size.
|
223
|
-
subject.state.
|
224
|
-
state = subject.get_state
|
307
|
+
expect(subject.results.size).to eq(1)
|
308
|
+
expect(subject.state).to eq(:finished)
|
225
309
|
result = subject.results.first
|
226
|
-
result.claimed_by.
|
227
|
-
result.claimed.
|
228
|
-
result.tricks_made.
|
229
|
-
result.score.
|
310
|
+
expect(result.claimed_by).to eq(Direction.east)
|
311
|
+
expect(result.claimed).to eq(0)
|
312
|
+
expect(result.tricks_made).to eq(0)
|
313
|
+
expect(result.score).to eq(-800)
|
230
314
|
end
|
231
315
|
end
|
232
316
|
end
|
233
317
|
end
|
234
318
|
|
235
|
-
# All players pass, game
|
319
|
+
# All players pass, game ).to finish without reaching play
|
236
320
|
it 'should finish without reaching play if passed out' do
|
237
321
|
subject.start!(board)
|
238
322
|
turn = board.dealer # Avoid calling getTurn.
|
@@ -240,13 +324,13 @@ describe Game do
|
|
240
324
|
players[i].make_call(Pass.new) # Each player passes.
|
241
325
|
turn = Direction[(turn+1) % Direction.size]
|
242
326
|
end
|
243
|
-
turn.
|
327
|
+
expect(turn).to eq(board.dealer) # Sanity check.
|
244
328
|
|
245
329
|
# Bidding is passed out - game is over.
|
246
|
-
subject.in_progress
|
247
|
-
subject.state.
|
248
|
-
expect { players[turn].make_call(Bid.new(Level.one, Strain.club)) }.to raise_error
|
249
|
-
expect { players[turn].play_card(board.deal.hands[turn].first) }.to raise_error
|
330
|
+
expect(subject.in_progress?).to eq(false)
|
331
|
+
expect(subject.state).to eq(:finished)
|
332
|
+
expect { players[turn].make_call(Bid.new(Level.one, Strain.club)) }.to raise_error(Bridge::GameError)
|
333
|
+
expect { players[turn].play_card(board.deal.hands[turn].first) }.to raise_error(Bridge::GameError)
|
250
334
|
end
|
251
335
|
|
252
336
|
# Play through a sample game.
|
@@ -265,27 +349,27 @@ describe Game do
|
|
265
349
|
players[turn].make_call(call)
|
266
350
|
end
|
267
351
|
|
268
|
-
subject.state.
|
269
|
-
subject.auction.complete
|
270
|
-
subject.play.
|
352
|
+
expect(subject.state).to eq(:playing)
|
353
|
+
expect(subject.auction.complete?).to eq(true)
|
354
|
+
expect(subject.play).to_not eq(nil)
|
271
355
|
|
272
356
|
while not subject.play.complete?
|
273
|
-
subject.state.
|
357
|
+
expect(subject.state).to eq(:playing)
|
274
358
|
turn = subject.get_turn
|
275
359
|
# Find a valid card.
|
276
360
|
board.deal[turn].each do |card|
|
277
361
|
if subject.play.valid_play?(card, turn, board.deal[turn])
|
278
362
|
if turn == subject.play.dummy
|
279
|
-
self.players[subject.play.declarer].play_card(card).
|
363
|
+
expect(self.players[subject.play.declarer].play_card(card)).to eq(true)
|
280
364
|
else
|
281
|
-
self.players[turn].play_card(card).
|
365
|
+
expect(self.players[turn].play_card(card)).to eq(true)
|
282
366
|
end
|
283
367
|
break
|
284
368
|
end
|
285
369
|
end
|
286
370
|
end
|
287
|
-
subject.state.
|
288
|
-
subject.in_progress
|
371
|
+
expect(subject.state).to eq(:finished)
|
372
|
+
expect(subject.in_progress?).to eq(false) # Game complete.
|
289
373
|
end
|
290
374
|
end
|
291
375
|
end
|