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