elus 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.
- 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
|