elus 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +30 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/bin/elus +8 -0
- data/doc/dev_plan.htm +923 -0
- data/doc/dev_plan_files/colorschememapping.xml +2 -0
- data/doc/dev_plan_files/filelist.xml +6 -0
- data/doc/dev_plan_files/themedata.thmx +0 -0
- data/doc/user_stories.htm +959 -0
- data/doc/user_stories_files/colorschememapping.xml +2 -0
- data/doc/user_stories_files/filelist.xml +6 -0
- data/doc/user_stories_files/themedata.thmx +0 -0
- data/elus.gemspec +91 -0
- data/features/gamer_inputs_state.feature +135 -0
- data/features/gamer_starts_solver.feature +13 -0
- data/features/gamer_updates_state.feature +27 -0
- data/features/solver_shows_hints.feature +36 -0
- data/features/step_definitions/elus_steps.rb +116 -0
- data/features/support/env.rb +5 -0
- data/features/support/stats.rb +32 -0
- data/lib/elus.rb +5 -0
- data/lib/elus/game.rb +74 -0
- data/lib/elus/generator.rb +48 -0
- data/lib/elus/piece.rb +93 -0
- data/lib/elus/rule.rb +36 -0
- data/lib/elus/solver.rb +84 -0
- data/spec/cucumber/stats_spec.rb +13 -0
- data/spec/elus/game_spec.rb +116 -0
- data/spec/elus/generator_spec.rb +124 -0
- data/spec/elus/piece_spec.rb +190 -0
- data/spec/elus/rule_spec.rb +39 -0
- data/spec/elus/solver_spec.rb +203 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +198 -0
- metadata +117 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), ".." ,"spec_helper" )
|
2
|
+
|
3
|
+
module Elus
|
4
|
+
include ElusTest
|
5
|
+
|
6
|
+
shared_examples_for 'all generators' do
|
7
|
+
it 'should generate rules array' do
|
8
|
+
generator = described_class.new
|
9
|
+
rules = generator.generate_rules
|
10
|
+
rules.class.should == Array
|
11
|
+
rules.each {|rule| rule.class.should == Rule} unless rules.empty?
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe Generator do
|
16
|
+
it_should_behave_like 'all generators'
|
17
|
+
end
|
18
|
+
|
19
|
+
describe EmptyGenerator do
|
20
|
+
it_should_behave_like 'all generators'
|
21
|
+
|
22
|
+
it 'should generate empty rules set' do
|
23
|
+
generator = EmptyGenerator.new
|
24
|
+
generator.generate_rules.should == []
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe Turn1Generator do
|
29
|
+
before :each do
|
30
|
+
@generator = Turn1Generator.new
|
31
|
+
@rules = @generator.generate_rules
|
32
|
+
end
|
33
|
+
|
34
|
+
it_should_behave_like 'all generators'
|
35
|
+
|
36
|
+
it 'should generate non-empty rules set' do
|
37
|
+
@rules.should_not be_empty
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should generate rules with Any condition and without "no" branch' do
|
41
|
+
@rules.each do |rule|
|
42
|
+
rule.name.should =~ /If last Piece is Any Piece/
|
43
|
+
rule.name.should_not =~ /otherwise/
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should generate only rules with valid(.X.) Pieces in "yes" branch' do
|
48
|
+
@rules.count.should == 12
|
49
|
+
permutate do |code|
|
50
|
+
piece = Piece.create(code)
|
51
|
+
re = Regexp.new(', ' + piece.name + ' Piece is next')
|
52
|
+
@rules.count {|rule| rule.name =~ re}.should == 1
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe Turn2Generator do
|
58
|
+
before :each do
|
59
|
+
@generator = Turn2Generator.new
|
60
|
+
@rules = @generator.generate_rules
|
61
|
+
end
|
62
|
+
|
63
|
+
it_should_behave_like 'all generators'
|
64
|
+
|
65
|
+
it 'should generate non-empty rules set' do
|
66
|
+
@rules.should_not be_empty
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should generate rules without Any condition and with obligatory "no" branch' do
|
70
|
+
@rules.each do |rule|
|
71
|
+
rule.name.should_not =~ /If last Piece is Any Piece/
|
72
|
+
rule.name.should =~ /otherwise/
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should generate only rules with opposite yes-no branches' do
|
77
|
+
@rules.count.should == 36
|
78
|
+
permutate('1') do |cond_code|
|
79
|
+
cond = Piece.create(cond_code)
|
80
|
+
permutate do |yes_code|
|
81
|
+
yes = Piece.create(yes_code)
|
82
|
+
no = Piece.create(Piece.different(yes_code))
|
83
|
+
re = Regexp.new("If last Piece is #{cond.name} Piece, #{yes.name} Piece is next, otherwise #{no.name} Piece is next")
|
84
|
+
@rules.count {|rule| rule.name =~ re}.should == 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe Turn3Generator do
|
91
|
+
before :each do
|
92
|
+
@generator = Turn3Generator.new
|
93
|
+
@rules = @generator.generate_rules
|
94
|
+
end
|
95
|
+
|
96
|
+
it_should_behave_like 'all generators'
|
97
|
+
|
98
|
+
it 'should generate non-empty rules set' do
|
99
|
+
@rules.should_not be_empty
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should generate rules without Any condition and with obligatory "no" branch' do
|
103
|
+
@rules.each do |rule|
|
104
|
+
rule.name.should_not =~ /If last Piece is Any Piece/
|
105
|
+
rule.name.should =~ /otherwise/
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should generate rules with all possible yes-no branches' do
|
110
|
+
@rules.count.should == 432
|
111
|
+
permutate('1') do |cond_code|
|
112
|
+
cond = Piece.create(cond_code)
|
113
|
+
permutate do |yes_code|
|
114
|
+
yes = Piece.create(yes_code)
|
115
|
+
permutate do |no_code|
|
116
|
+
no = Piece.create(no_code)
|
117
|
+
re = Regexp.new("If last Piece is #{cond.name} Piece, #{yes.name} Piece is next, otherwise #{no.name} Piece is next")
|
118
|
+
@rules.count {|rule| rule.name =~ re}.should == 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), ".." ,"spec_helper" )
|
2
|
+
|
3
|
+
module Elus
|
4
|
+
include ElusTest
|
5
|
+
|
6
|
+
describe Piece do
|
7
|
+
context "creating" do
|
8
|
+
it "should raise error if new method is called" do
|
9
|
+
CODES.each_key do |code|
|
10
|
+
lambda{Piece.new(code)}.should raise_error(NoMethodError)
|
11
|
+
end
|
12
|
+
WRONG_CODES.each do |code|
|
13
|
+
lambda{Piece.new(code)}.should raise_error(NoMethodError)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return nil for a wrong code" do
|
18
|
+
WRONG_CODES.each do |code|
|
19
|
+
Piece.create(code).should == nil
|
20
|
+
end
|
21
|
+
Piece.create(nil).should == nil
|
22
|
+
Piece.create('').should == nil
|
23
|
+
Piece.create(1).should == nil
|
24
|
+
Piece.create(3.14).should == nil
|
25
|
+
Piece.create(:byd).should == nil
|
26
|
+
Piece.create([]).should == nil
|
27
|
+
Piece.create([1,2,3]).should == nil
|
28
|
+
Piece.create({:symb=>'something'}).should == nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should have code and name consistent with an input code" do
|
32
|
+
CODES.each do |code, name|
|
33
|
+
Piece.create(code).name.should == name
|
34
|
+
Piece.create(code).code.should == Piece.convert_code(code)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should drop irrelevant characters from code" do
|
39
|
+
Piece.create('b y d ').name.should == BYD
|
40
|
+
Piece.create('yfdzb').name.should == BYD
|
41
|
+
Piece.create('AEFHIJKLMNOPQTUVWXZaefhijklmnopqtuvwxz byd').name.should == BYD
|
42
|
+
Piece.create('byd23456789~@#$%^&*()_+-?><{}[],|/`').name.should == BYD
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should drop duplicate characters from code" do
|
46
|
+
Piece.create('byyd').name.should == BYD
|
47
|
+
Piece.create('DDyb').name.should == BYD
|
48
|
+
Piece.create('AEFHIJbbbbbbbbbbbbbbbbbbbbyd').name.should == BYD
|
49
|
+
Piece.create('byddd').name.should == BYD
|
50
|
+
Piece.create('byrd').name.should == BYD
|
51
|
+
Piece.create('bydrrdrrrrdr').name.should == BYD
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should sort code letter if they are given in wrong order" do
|
55
|
+
Piece.create('ydb').name.should == BYD
|
56
|
+
Piece.create('ybd').name.should == BYD
|
57
|
+
Piece.create('dBy').name.should == BYD
|
58
|
+
Piece.create('Dby').name.should == BYD
|
59
|
+
Piece.create('dyb').name.should == BYD
|
60
|
+
Piece.create('Bdy').name.should == BYD
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should not sort code letter mixed with numbers or specials but return nil" do
|
64
|
+
Piece.create('1dy').should == nil
|
65
|
+
Piece.create('d1b').should == nil
|
66
|
+
Piece.create('yb0').should == nil
|
67
|
+
Piece.create('!dy').should == nil
|
68
|
+
Piece.create('d=b').should == nil
|
69
|
+
Piece.create('yb.').should == nil
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should create Pieces from codes with special meaning" do
|
73
|
+
SPECIAL_CODES.each do |code, name|
|
74
|
+
Piece.create(code).name.should == name
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'comparing' do
|
80
|
+
it 'should match its code, self and Piece with the same code' do
|
81
|
+
(CODES.merge SPECIAL_CODES).each do |code, name|
|
82
|
+
piece1 = Piece.create(code)
|
83
|
+
piece2 = Piece.create(code)
|
84
|
+
should_be_equal(piece1, code)
|
85
|
+
should_be_equal(piece1, piece1)
|
86
|
+
should_be_equal(piece1, piece2)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should be reciprocal' do
|
91
|
+
all_chars_twice do |code1, code2|
|
92
|
+
piece1 = Piece.create(code1)
|
93
|
+
piece2 = Piece.create(code2)
|
94
|
+
should_be_equal(piece2, piece1) if piece1 == piece2
|
95
|
+
should_be_equal(piece1, piece2) if piece2 == piece1
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should match dots in all positions' do
|
100
|
+
all_chars do |code|
|
101
|
+
c1,c2,c3 = code.split(//)
|
102
|
+
piece = Piece.create(c1+c2+c3)
|
103
|
+
should_be_equal(piece, '.'+c2+c3)
|
104
|
+
should_be_equal(piece, Piece.create('.'+c2+c3))
|
105
|
+
should_be_equal(Piece.create('.'+c2+c3), piece)
|
106
|
+
should_be_equal(piece, c1+'.'+c3)
|
107
|
+
should_be_equal(piece, Piece.create(c1+'.'+c3))
|
108
|
+
should_be_equal(Piece.create(c1+'.'+c3), piece)
|
109
|
+
should_be_equal(piece, c1+c2+'.')
|
110
|
+
should_be_equal(piece, Piece.create(c1+c2+'.'))
|
111
|
+
should_be_equal(Piece.create(c1+c2+'.'), piece)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
it 'should support eql? comparison (based on code)' do
|
115
|
+
all_chars_twice do |code1, code2|
|
116
|
+
piece1 = Piece.create(code1)
|
117
|
+
piece2 = Piece.create(code2)
|
118
|
+
(piece1.eql? piece2).should be_true if piece1.code == piece2.code
|
119
|
+
(piece2.eql? piece1).should be_true if piece1.code == piece2.code
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should be bigger than nil" do
|
124
|
+
all_chars('01=!.') do |code|
|
125
|
+
(Piece.create(code) > nil).should be_true
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'multiplying Piece by mask (finding next Piece)' do
|
131
|
+
it 'should copy mask if the mask contains only numbers OR dots' do
|
132
|
+
all_chars_twice('01.=!', '01.') do |code1, code2|
|
133
|
+
piece = Piece.create(code1)
|
134
|
+
mask = Piece.create(code2)
|
135
|
+
should_be_equal(piece * mask, mask)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should convert mask if mask contains special chars' do
|
140
|
+
all_chars_twice do |orig_code, mask_code|
|
141
|
+
expected = []
|
142
|
+
mask_code.split(//).each_with_index do |char,i|
|
143
|
+
expected[i] = case char
|
144
|
+
when '0' then '0'
|
145
|
+
when '1' then '1'
|
146
|
+
when '.' then '.'
|
147
|
+
when '=' then orig_code[i]
|
148
|
+
when '!' then Piece.different(orig_code[i])
|
149
|
+
end
|
150
|
+
end
|
151
|
+
expected_code = expected.join('')
|
152
|
+
piece = Piece.create(orig_code)
|
153
|
+
mask = Piece.create(mask_code)
|
154
|
+
should_be_equal(piece * mask, expected_code)
|
155
|
+
should_be_equal(piece * mask, Piece.create(expected_code))
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
context 'assorted class methods' do
|
161
|
+
it 'should be able to return universal (Any) Piece' do
|
162
|
+
any = Piece.any
|
163
|
+
any.name.should == 'Any'
|
164
|
+
all_chars do |code|
|
165
|
+
piece = Piece.create(code)
|
166
|
+
should_be_equal(piece, any)
|
167
|
+
(piece * any).name.should == 'Any'
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'should be able to convert code to different (opposite)' do
|
172
|
+
all_chars do |code|
|
173
|
+
expected = []
|
174
|
+
code.split(//).each_with_index do |char,i|
|
175
|
+
expected[i] = case char
|
176
|
+
when '0' then '1'
|
177
|
+
when '1' then '0'
|
178
|
+
when '.' then '.'
|
179
|
+
when '=' then '!'
|
180
|
+
when '!' then '='
|
181
|
+
end
|
182
|
+
end
|
183
|
+
expected_code = expected.join('')
|
184
|
+
Piece.different(code).should == expected_code
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), ".." ,"spec_helper" )
|
2
|
+
|
3
|
+
module Elus
|
4
|
+
include ElusTest
|
5
|
+
|
6
|
+
describe Rule do
|
7
|
+
context 'creating' do
|
8
|
+
it 'should create appropriate Rules given correct arguments' do
|
9
|
+
RULES.each do |args, name|
|
10
|
+
rule = Rule.new(*args)
|
11
|
+
rule.name.should == name
|
12
|
+
end
|
13
|
+
end
|
14
|
+
it 'should fail if given wrong arguments' do
|
15
|
+
WRONG_RULES.each do |args|
|
16
|
+
lambda{Rule.new(*args)}.should raise_error(Invalid)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
context 'applying Rule to Pieces' do
|
21
|
+
it 'should produce expected outcome when applied to any Piece' do
|
22
|
+
all_chars_twice('01.') do |piece, condition|
|
23
|
+
p = Piece.create(piece)
|
24
|
+
c = Piece.create(condition)
|
25
|
+
random_chars_twice 100 do |yes, no|
|
26
|
+
y = Piece.create(yes)
|
27
|
+
n = Piece.create(no)
|
28
|
+
rule = Rule.new(c, y, n)
|
29
|
+
if p == c
|
30
|
+
should_be_equal(rule.apply(p), p * y)
|
31
|
+
else
|
32
|
+
should_be_equal(rule.apply(p), p * n)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), ".." ,"spec_helper" )
|
2
|
+
|
3
|
+
module Elus
|
4
|
+
include ElusTest
|
5
|
+
|
6
|
+
def create_solver(options={})
|
7
|
+
@stdout = options[:stdout] || mock('stdout').as_null_object
|
8
|
+
@stdin = options[:stdin] || mock('stdin')
|
9
|
+
@stdin.stub(:gets).and_return(*options[:input]) if options[:input]
|
10
|
+
@solver = Solver.new(@stdin, @stdout)
|
11
|
+
end
|
12
|
+
|
13
|
+
def start_solver(options={})
|
14
|
+
create_solver(options)
|
15
|
+
@solver.start(options[:generator] || stub('generator', :generate_rules => []))
|
16
|
+
end
|
17
|
+
|
18
|
+
# sets expectation for stdout to receive strictly ordered sequence of exact messages
|
19
|
+
def stdout_should_receive(*messages)
|
20
|
+
messages.each do |message|
|
21
|
+
@stdout.should_receive(:puts).with(message).once.ordered
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# sets expectation for stdout to receive message(s) containing all of the patterns (unordered)
|
26
|
+
def stdout_should_include(*patterns)
|
27
|
+
patterns.each do |pattern|
|
28
|
+
re = Regexp === pattern ? pattern : Regexp.new(Regexp.escape(pattern))
|
29
|
+
@stdout.should_receive(:puts).with(re).at_least(:once)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe Solver do
|
34
|
+
context 'starting up' do
|
35
|
+
it 'should send a welcome message' do
|
36
|
+
create_solver
|
37
|
+
stdout_should_receive("Welcome to Elus Solver!")
|
38
|
+
@solver.start(stub('generator', :generate_rules => []))
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should prompt for Game state' do
|
42
|
+
create_solver
|
43
|
+
stdout_should_receive("Enter Game state:")
|
44
|
+
@solver.start(stub('generator', :generate_rules => []))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'inputing single Piece' do
|
49
|
+
it 'should return corresponding Piece for each correct code entered' do
|
50
|
+
CODES.each do |code, name|
|
51
|
+
start_solver
|
52
|
+
@stdin.stub(:gets).and_return(code)
|
53
|
+
piece = @solver.input_piece
|
54
|
+
piece.name.should == name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
it 'should inform about invalid codes and return nil if interrupted' do
|
58
|
+
WRONG_CODES.each do |code|
|
59
|
+
start_solver
|
60
|
+
@stdin.stub(:gets).and_return(code, "\n")
|
61
|
+
stdout_should_receive("Invalid code: #{code}")
|
62
|
+
@solver.input_piece.should == nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# context 'inputing Game state as a codestring' do
|
68
|
+
# it 'should ignore wrong piece codes' do
|
69
|
+
# WRONG_CODES.each do |code|
|
70
|
+
# start_solver
|
71
|
+
# stdout_should_receive("Free:\n#{BYD}\n#{BYD}\n#{BYD}\nBoard:\n#{BYD}\n#{BYD}\n#{BYD}\n")
|
72
|
+
# @solver.input_state(code+"\n"+"BYD\n"*6)
|
73
|
+
# end
|
74
|
+
# end
|
75
|
+
# it 'should output matching Piece name' do
|
76
|
+
# CODES.each do |code, name|
|
77
|
+
# start_solver
|
78
|
+
# stdout_should_include(name)
|
79
|
+
# @solver.input_state("#{code}\n"+"BYD\n"*5)
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
# it 'should raise exception if not enough Pieces' do
|
83
|
+
# (0..5).each do |n|
|
84
|
+
# start_solver
|
85
|
+
# lambda{@solver.input_state("BYD\n"*n)}.should raise_error(Invalid)
|
86
|
+
# end
|
87
|
+
# end
|
88
|
+
# it 'should output correct Game state' do
|
89
|
+
# CODES.each do |code, name|
|
90
|
+
# start_solver
|
91
|
+
# stdout_should_receive("Free:\n#{name}\n#{BYD}\n#{BYD}\nBoard:\n#{BYD}\n#{BYD}\n#{BYD}\n")
|
92
|
+
# @solver.input_state("#{code}\n#"+"BYD\n"*5)
|
93
|
+
# end
|
94
|
+
# end
|
95
|
+
# end
|
96
|
+
|
97
|
+
context 'inputing Game state from stdin' do
|
98
|
+
it 'should report wrong piece codes' do
|
99
|
+
WRONG_CODES.each do |code|
|
100
|
+
start_solver(:input => ["BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", code+"\n", "\n"])
|
101
|
+
stdout_should_receive("Invalid code: #{code}\n")
|
102
|
+
@solver.input_state
|
103
|
+
end
|
104
|
+
end
|
105
|
+
it 'should output matching Piece name' do
|
106
|
+
CODES.each do |code, name|
|
107
|
+
start_solver(:input => [code+"\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "\n"])
|
108
|
+
stdout_should_include(name)
|
109
|
+
@solver.input_state
|
110
|
+
end
|
111
|
+
end
|
112
|
+
it 'should raise exception if not enough Pieces' do
|
113
|
+
(0..5).each do |n|
|
114
|
+
start_solver(:input => [* Array.new(n,"BYD\n") << "\n"])
|
115
|
+
lambda{@solver.input_state}.should raise_error(Invalid)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
it 'should output prompts, separate piece feedback and then correct Game state' do
|
119
|
+
CODES.each do |code, name|
|
120
|
+
start_solver(:input => [code+"\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "\n"])
|
121
|
+
stdout_should_receive("Enter Free Piece code (1):", "You entered Free Piece (1): #{name}",
|
122
|
+
"Enter Free Piece code (2):", "You entered Free Piece (2): #{BYD}",
|
123
|
+
"Enter Free Piece code (3):", "You entered Free Piece (3): #{BYD}",
|
124
|
+
"Enter Board Piece code (1):", "You entered Board Piece (1): #{BYD}",
|
125
|
+
"Enter Board Piece code (2):", "You entered Board Piece (2): #{BYD}",
|
126
|
+
"Enter Board Piece code (3):", "You entered Board Piece (3): #{BYD}")
|
127
|
+
@solver.input_state
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'showing state/hints' do
|
133
|
+
it 'should correctly output Game state before making move' do
|
134
|
+
CODES.each do |code, name|
|
135
|
+
start_solver(:input => [code+"\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "\n"])
|
136
|
+
@solver.input_state
|
137
|
+
stdout_should_receive("Free:\n#{name}\n#{BYD}\n#{BYD}\nBoard:\n#{BYD}\n#{BYD}\n#{BYD}\n")
|
138
|
+
@solver.make_move
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should output zero Rules when making moves in inconsistent (wrong) Game state' do
|
143
|
+
start_solver(:generator => Turn1Generator.new, :input => ["BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "BYD\n", "\n"])
|
144
|
+
stdout_should_include(/Rules\(0\):\s*Moves\(0\):/)
|
145
|
+
@solver.input_state
|
146
|
+
@solver.make_move
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'should output possible game Rules wheh given correct Game state' do
|
150
|
+
start_solver(:generator => Turn1Generator.new, :input => ["BGC\n", "sgd\n", "syc\n", "BYD\n", "SYD\n", "BGD\n", "\n"])
|
151
|
+
stdout_should_include \
|
152
|
+
"Rules(2):
|
153
|
+
If last Piece is Any Piece, Diamond Piece is next
|
154
|
+
If last Piece is Any Piece, Same shape Piece is next
|
155
|
+
Moves(1):
|
156
|
+
Small Green Diamond(2)"
|
157
|
+
@solver.input_state
|
158
|
+
@solver.make_move
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'making move' do
|
163
|
+
it 'should prompt to make move' do
|
164
|
+
start_solver(:generator => Turn1Generator.new, :input => ["BGC\n", "sgd\n", "syc\n", "BYD\n", "SYD\n", "BGD\n", "\n"])
|
165
|
+
stdout_should_include("Make your move:")
|
166
|
+
@solver.input_state
|
167
|
+
@solver.make_move
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'should output move feedback for incorrect move (invalid code, interrupt)' do
|
171
|
+
start_solver(:generator => Turn1Generator.new, :input => ["BGC\n", "sgd\n", "syc\n", "BYD\n", "SYD\n", "BGD\n", "\n"])
|
172
|
+
@solver.input_state
|
173
|
+
@stdin.stub(:gets).and_return("Saa","\n","SYC","SYD","BYC")
|
174
|
+
stdout_should_include("Make your move:", "Wrong move (no piece given)")
|
175
|
+
@solver.make_move
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should output move feedback for incorrect move (valid code, but not in free set)' do
|
179
|
+
start_solver(:generator => Turn1Generator.new, :input => ["BGC\n", "sgd\n", "syc\n", "BYD\n", "SYD\n", "BGD\n", "\n"])
|
180
|
+
@solver.input_state
|
181
|
+
@stdin.stub(:gets).and_return("BGD","N","SYC","SYD","BYC")
|
182
|
+
stdout_should_include("Make your move:", "Wrong move (not in free set): Big Green Diamond")
|
183
|
+
@solver.make_move
|
184
|
+
end
|
185
|
+
|
186
|
+
it 'should output move feedback for right move' do
|
187
|
+
start_solver(:generator => Turn1Generator.new, :input => ["BGC\n", "sgd\n", "syc\n", "BYD\n", "SYD\n", "BGD\n", "\n"])
|
188
|
+
@solver.input_state
|
189
|
+
@stdin.stub(:gets).and_return("SGD","Y","SYC","SYD","BYC")
|
190
|
+
stdout_should_include("Make your move:", "You moved: Small Green Diamond", "Was the move right(Y/N)?:", "Great, now enter new Free set:")
|
191
|
+
@solver.make_move
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'should output move feedback for wrong move' do
|
195
|
+
start_solver(:generator => Turn1Generator.new, :input => ["BGC\n", "sgd\n", "syc\n", "BYD\n", "SYD\n", "BGD\n", "\n"])
|
196
|
+
@solver.input_state
|
197
|
+
@stdin.stub(:gets).and_return("SYC","N")
|
198
|
+
stdout_should_include("Make your move:", "You moved: Small Yellow Circle", "Was the move right(Y/N)?:", "Too bad")
|
199
|
+
@solver.make_move
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|