mastermind-nowsiany 1.0.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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/Guardfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +15 -0
- data/Rakefile +2 -0
- data/bin/mastermind +7 -0
- data/lib/mastermind/cli.rb +51 -0
- data/lib/mastermind/game_round.rb +180 -0
- data/lib/mastermind/interact.rb +235 -0
- data/lib/mastermind/play_game.rb +74 -0
- data/lib/mastermind/player.rb +17 -0
- data/lib/mastermind/processor.rb +48 -0
- data/lib/mastermind/version.rb +3 -0
- data/lib/mastermind.rb +28 -0
- data/mastermind.gemspec +27 -0
- data/spec/cli_spec.rb +46 -0
- data/spec/game_round_spec.rb +268 -0
- data/spec/interact_spec.rb +37 -0
- data/spec/play_game_spec.rb +90 -0
- data/spec/processor_spec.rb +63 -0
- data/spec/spec_helper.rb +5 -0
- metadata +143 -0
data/lib/mastermind.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "mastermind/version"
|
2
|
+
|
3
|
+
module Mastermind
|
4
|
+
COLORS = ["R", "Y", "G", "B", "P", "M"]
|
5
|
+
|
6
|
+
COLOR_NAMES = {
|
7
|
+
"R" => "(r)ed",
|
8
|
+
"Y" => "(y)ellow",
|
9
|
+
"G" => "(g)reen",
|
10
|
+
"B" => "(b)lue",
|
11
|
+
"P" => "(p)ink",
|
12
|
+
"M" => "(m)agenta"
|
13
|
+
}
|
14
|
+
|
15
|
+
COLOR_CODES = {
|
16
|
+
"R" => :red,
|
17
|
+
"Y" => :yellow,
|
18
|
+
"G" => :green,
|
19
|
+
"B" => :blue,
|
20
|
+
"P" => :magenta,
|
21
|
+
"M" => :light_magenta
|
22
|
+
}
|
23
|
+
|
24
|
+
def self.color_option_string(num_colors)
|
25
|
+
COLOR_NAMES.values.first(num_colors).join(" | ")
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/mastermind.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mastermind/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mastermind-nowsiany"
|
8
|
+
spec.version = Mastermind::VERSION
|
9
|
+
spec.authors = ["Nathan Owsiany"]
|
10
|
+
spec.email = ["nowsiany@gmail.com"]
|
11
|
+
spec.summary = %q{Command Line Mastermind}
|
12
|
+
spec.description = %q{Play Mastermind through your command line... with multiplayer support.}
|
13
|
+
spec.homepage = "https://github.com/ndwhtlssthr/mastermind"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "colorize", "~> 0.7"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "guard", "~> 2.8"
|
26
|
+
spec.add_development_dependency "guard-rspec", "~> 4.3"
|
27
|
+
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'mastermind/cli'
|
2
|
+
require 'mastermind/play_game'
|
3
|
+
require 'mastermind/interact'
|
4
|
+
require 'spec_helper'
|
5
|
+
require 'stringio'
|
6
|
+
|
7
|
+
RSpec.describe Mastermind::CLI do
|
8
|
+
it "should be able to quit" do
|
9
|
+
stdin = StringIO.new("Q")
|
10
|
+
cli = Mastermind::CLI.new(stdin, StringIO.new)
|
11
|
+
expect(cli.quit?).to be_falsey
|
12
|
+
|
13
|
+
cli.get_command
|
14
|
+
expect(cli.quit?).to be_truthy
|
15
|
+
|
16
|
+
stdin.string = "q"
|
17
|
+
cli.get_command
|
18
|
+
expect(cli.quit?).to be_truthy
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should print intro title and content" do
|
22
|
+
stdin = StringIO.new("\nq")
|
23
|
+
stdout = StringIO.new()
|
24
|
+
cli = Mastermind::CLI.new(stdin, stdout)
|
25
|
+
cli.run
|
26
|
+
expect(stdout.string).to include("0;32;49m")
|
27
|
+
expect(stdout.string).to include("MA1N")
|
28
|
+
expect(stdout.string).to include("_/")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should print instructions when prompted" do
|
32
|
+
stdin = StringIO.new("i\nq")
|
33
|
+
stdout = StringIO.new()
|
34
|
+
cli = Mastermind::CLI.new(stdin, stdout)
|
35
|
+
cli.run
|
36
|
+
expect(stdout.string).to include("(i)")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should play the game when prompted" do
|
40
|
+
stdin = StringIO.new("p\nq\nq\n")
|
41
|
+
stdout = StringIO.new()
|
42
|
+
cli = Mastermind::CLI.new(stdin, stdout)
|
43
|
+
cli.run
|
44
|
+
expect(Mastermind::PlayGame.new(stdin, stdout, Mastermind::Interact.new)).to respond_to(:run)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,268 @@
|
|
1
|
+
require 'mastermind/player'
|
2
|
+
require 'mastermind/game_round'
|
3
|
+
require 'mastermind/interact'
|
4
|
+
require 'mastermind/processor'
|
5
|
+
require 'spec_helper'
|
6
|
+
require 'stringio'
|
7
|
+
|
8
|
+
RSpec.describe Mastermind::GameRound do
|
9
|
+
attr_accessor :stdin, :stdout, :interact
|
10
|
+
before do
|
11
|
+
self.stdin = StringIO.new("\nSimon\nAlvin\n")
|
12
|
+
self.stdout = StringIO.new
|
13
|
+
self.interact = Mastermind::Interact.new
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should generate a random secret when there is one player" do
|
17
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
18
|
+
players = game.player_gen(1)
|
19
|
+
round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
20
|
+
expect(round.players[0].secret).to eql(["X", "X", "X", "X"])
|
21
|
+
thread = Thread.new do
|
22
|
+
round.play
|
23
|
+
binding.pry
|
24
|
+
end
|
25
|
+
sleep(0.1)
|
26
|
+
player = round.players[0]
|
27
|
+
colors = Mastermind::Processor.colors(6)
|
28
|
+
expect(player.secret).to_not eql(["X", "X", "X", "X"])
|
29
|
+
expect(Mastermind::Processor.validate(player.secret.join, player.secret, colors)).to be_truthy
|
30
|
+
thread.kill
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when generating a single player secret" do
|
34
|
+
before do
|
35
|
+
@game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
36
|
+
@players = @game.player_gen(1)
|
37
|
+
@round = Mastermind::GameRound.new(stdin, stdout, interact, @players)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "knows the initial state of the secret is invalid" do
|
41
|
+
expect(@round.players[0].secret).to eql(["X", "X", "X", "X"])
|
42
|
+
end
|
43
|
+
|
44
|
+
it "changes the secret from its initial state" do
|
45
|
+
thread = Thread.new do
|
46
|
+
@round.play
|
47
|
+
end
|
48
|
+
sleep(0.1)
|
49
|
+
player = @round.players[0]
|
50
|
+
expect(player.secret).to_not eql(["X", "X", "X", "X"])
|
51
|
+
thread.kill
|
52
|
+
end
|
53
|
+
|
54
|
+
it "generates a valid secret" do
|
55
|
+
thread = Thread.new do
|
56
|
+
@round.play
|
57
|
+
end
|
58
|
+
sleep(0.1)
|
59
|
+
player = @round.players[0]
|
60
|
+
colors = Mastermind::Processor.colors(6)
|
61
|
+
expect(Mastermind::Processor.validate(player.secret.join, player.secret, colors)).to be_truthy
|
62
|
+
thread.kill
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when generating multi player secrets" do
|
67
|
+
before do
|
68
|
+
stdin.string = "m\nSimon\nTheodore\nrrrr\nrrrr\n"
|
69
|
+
@game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
70
|
+
@players = @game.player_gen(2)
|
71
|
+
@round = Mastermind::GameRound.new(stdin, stdout, interact, @players)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "knows the initial state of each players secret is invalid" do
|
75
|
+
expect(@round.players[0].secret).to eql(["X", "X", "X", "X"])
|
76
|
+
expect(@round.players[1].secret).to eql(["X", "X", "X", "X"])
|
77
|
+
end
|
78
|
+
|
79
|
+
it "changes the secret from its initial state" do
|
80
|
+
thread = Thread.new do
|
81
|
+
@round.play
|
82
|
+
end
|
83
|
+
sleep(0.1)
|
84
|
+
player = @round.players[0]
|
85
|
+
expect(player.secret).to_not eql(["X", "X", "X", "X"])
|
86
|
+
expect(player.secret).to eql(["R", "R", "R", "R"])
|
87
|
+
thread.kill
|
88
|
+
end
|
89
|
+
|
90
|
+
it "generates a valid secret" do
|
91
|
+
thread = Thread.new do
|
92
|
+
@round.play
|
93
|
+
end
|
94
|
+
sleep(0.1)
|
95
|
+
player = @round.players[0]
|
96
|
+
colors = Mastermind::Processor.colors(6)
|
97
|
+
expect(Mastermind::Processor.validate(player.secret.join, player.secret, colors)).to be_truthy
|
98
|
+
thread.kill
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "loads a list of valid colors" do
|
103
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
104
|
+
players = game.player_gen(1)
|
105
|
+
round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
106
|
+
expect(round.valid_colors).to eql(["R", "Y", "G", "B", "P", "M"])
|
107
|
+
end
|
108
|
+
|
109
|
+
it "sets max guesses to 12 for single difficulty model" do
|
110
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
111
|
+
players = game.player_gen(1)
|
112
|
+
round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
113
|
+
expect(round.max_guesses).to eql(12)
|
114
|
+
end
|
115
|
+
|
116
|
+
context "when resetting a Players' round info before the round" do
|
117
|
+
before do
|
118
|
+
@game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
119
|
+
@players = @game.player_gen(2)
|
120
|
+
@round = Mastermind::GameRound.new(stdin, stdout, interact, @players)
|
121
|
+
end
|
122
|
+
|
123
|
+
# NOTE: alternating b/w player 1 and 2 to verify it works for each player
|
124
|
+
|
125
|
+
it "resets the players password to XXXX" do
|
126
|
+
@round.players[0].secret = ["Z", "Z", "Z", "Z"]
|
127
|
+
expect(@round.players[0].secret).to_not eql(["X", "X", "X", "X"])
|
128
|
+
@round.player_reset
|
129
|
+
expect(@round.players[0].secret).to eql(["X", "X", "X", "X"])
|
130
|
+
end
|
131
|
+
|
132
|
+
it "sets the players round_over status to false" do
|
133
|
+
@round.players[1].round_over = true
|
134
|
+
expect(@round.players[1].round_over).to be_truthy
|
135
|
+
@round.player_reset
|
136
|
+
expect(@round.players[1].round_over).to be_falsey
|
137
|
+
end
|
138
|
+
|
139
|
+
it "clears the players guess log" do
|
140
|
+
@round.players[0].guesses = ["gggg", "gggg"]
|
141
|
+
expect(@round.players[0].guesses).to_not be_empty
|
142
|
+
@round.player_reset
|
143
|
+
expect(@round.players[0].guesses).to be_empty
|
144
|
+
end
|
145
|
+
|
146
|
+
it "it resets the time counter" do
|
147
|
+
test_time = Time.now
|
148
|
+
@round.player_reset
|
149
|
+
expect(@round.players[1].start_time).to be_within(1).of(test_time)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "it resets the completion time to nil" do
|
153
|
+
@round.players[0].completion_time = Time.new - 500
|
154
|
+
expect(@round.players[0].completion_time).to_not be_nil
|
155
|
+
@round.player_reset
|
156
|
+
expect(@round.players[0].completion_time).to be_nil
|
157
|
+
end
|
158
|
+
|
159
|
+
it "resets a players turn position" do
|
160
|
+
@round.players[1].turn_pos = 1
|
161
|
+
expect(@round.players[1].turn_pos).to_not be_nil
|
162
|
+
@round.player_reset
|
163
|
+
expect(@round.players[1].turn_pos).to be_nil
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
168
|
+
it "it has a blank global string command to start with" do
|
169
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
170
|
+
players = game.player_gen(1)
|
171
|
+
round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
172
|
+
expect(round.command).to eql("")
|
173
|
+
end
|
174
|
+
|
175
|
+
it "is not round over by default" do
|
176
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
177
|
+
players = game.player_gen(1)
|
178
|
+
round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
179
|
+
expect(round.round_over).to be_falsey
|
180
|
+
end
|
181
|
+
|
182
|
+
it "can identify a winning guess" do
|
183
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
184
|
+
players = game.player_gen(1)
|
185
|
+
round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
186
|
+
round.players[0].secret = ["R", "R", "R", "R"]
|
187
|
+
round.players[0].command = "RRRR"
|
188
|
+
expect(round.correct_guess?(round.players[0])).to be_truthy
|
189
|
+
end
|
190
|
+
|
191
|
+
it "knows how many guesses have been taken" do
|
192
|
+
stdin = StringIO.new("m\nsimon\ntheo\nrrrr\nrrrr\ngggg\nyyyy\nbbbb\n")
|
193
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
194
|
+
players = game.player_gen(2)
|
195
|
+
round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
196
|
+
thread = Thread.new do
|
197
|
+
round.play
|
198
|
+
end
|
199
|
+
sleep(0.1)
|
200
|
+
expect(round.num_guesses(players[0])).to eql(2)
|
201
|
+
expect(round.num_guesses(players[1])).to eql(1)
|
202
|
+
thread.kill
|
203
|
+
end
|
204
|
+
|
205
|
+
context "when one player guesses correct" do
|
206
|
+
before do
|
207
|
+
stdin = StringIO.new("m\nsimon\ntheo\nrrrr\nrrrr\nrrrr\nyyyy\nbbbb\n")
|
208
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
209
|
+
players = game.player_gen(2)
|
210
|
+
@round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
211
|
+
end
|
212
|
+
|
213
|
+
it "knows that player1's round is over" do
|
214
|
+
thread = Thread.new do
|
215
|
+
@round.play
|
216
|
+
end
|
217
|
+
sleep(0.1)
|
218
|
+
expect(@round.players[0].round_over).to be_truthy
|
219
|
+
thread.kill
|
220
|
+
end
|
221
|
+
|
222
|
+
it "knows that the game round is not over after one player wins" do
|
223
|
+
thread = Thread.new do
|
224
|
+
@round.play
|
225
|
+
end
|
226
|
+
sleep(0.1)
|
227
|
+
expect(@round.round_over).to be_falsey
|
228
|
+
thread.kill
|
229
|
+
end
|
230
|
+
|
231
|
+
it "continues prompting for guesses for the other player" do
|
232
|
+
thread = Thread.new do
|
233
|
+
@round.play
|
234
|
+
end
|
235
|
+
sleep(0.1)
|
236
|
+
expect(@round.num_guesses(@round.players[1])).to eql(2)
|
237
|
+
thread.kill
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "when both players guess correctly" do
|
242
|
+
before do
|
243
|
+
stdin = StringIO.new("m\nsimon\ntheo\nrrrr\nrrrr\nrrrr\nyyyy\nbbbb\nrrrr\n")
|
244
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
245
|
+
players = game.player_gen(2)
|
246
|
+
@round = Mastermind::GameRound.new(stdin, stdout, interact, players)
|
247
|
+
end
|
248
|
+
|
249
|
+
it "knows that each players' round is over" do
|
250
|
+
thread = Thread.new do
|
251
|
+
@round.play
|
252
|
+
end
|
253
|
+
sleep(0.1)
|
254
|
+
expect(@round.players[0].round_over).to be_truthy
|
255
|
+
expect(@round.players[1].round_over).to be_truthy
|
256
|
+
thread.kill
|
257
|
+
end
|
258
|
+
|
259
|
+
it "knows that the game round is over" do
|
260
|
+
thread = Thread.new do
|
261
|
+
@round.play
|
262
|
+
end
|
263
|
+
sleep(0.1)
|
264
|
+
expect(@round.round_over).to be_truthy
|
265
|
+
thread.kill
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'mastermind/interact'
|
2
|
+
|
3
|
+
RSpec.describe Mastermind::Interact do
|
4
|
+
before do
|
5
|
+
@interact = Mastermind::Interact.new
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'can return a colored string given a string input' do
|
9
|
+
colored = @interact.color_guess("R")
|
10
|
+
expect(colored).to eql("\e[0;31;49mR\e[0m")
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'prints an intro title' do
|
14
|
+
expect(@interact.print_title).to include("0;32;49m")
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'prints the main menu' do
|
18
|
+
expect(@interact.print_intro).to include("(i)")
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'prints an invalid command message' do
|
22
|
+
invalid_cmd = "XXXX"
|
23
|
+
expect(@interact.print_invalid(invalid_cmd)).to include("not a valid")
|
24
|
+
expect(@interact.print_invalid(invalid_cmd)).to include(invalid_cmd)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'prints a round over message' do
|
28
|
+
expect(@interact.print_round_over).to include("Round over")
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'prints an invalid guess message' do
|
32
|
+
invalid_cmd = "XXXX"
|
33
|
+
expect(@interact.print_invalid_guess(invalid_cmd)).to include("not a valid")
|
34
|
+
expect(@interact.print_invalid_guess(invalid_cmd)).to include(invalid_cmd)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'mastermind/play_game'
|
2
|
+
require 'mastermind/interact'
|
3
|
+
require 'mastermind/game_round'
|
4
|
+
require 'spec_helper'
|
5
|
+
require 'stringio'
|
6
|
+
require 'io/console'
|
7
|
+
|
8
|
+
RSpec.describe Mastermind::PlayGame do
|
9
|
+
it "should be able to quit" do
|
10
|
+
stdin = StringIO.new("Q")
|
11
|
+
stdout = StringIO.new
|
12
|
+
interact = Mastermind::Interact.new
|
13
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
14
|
+
expect(game.quit?).to be_falsey
|
15
|
+
|
16
|
+
game.get_command
|
17
|
+
expect(game.quit?).to be_truthy
|
18
|
+
|
19
|
+
stdin.string = "q"
|
20
|
+
game.get_command
|
21
|
+
expect(game.quit?).to be_truthy
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should print intro title and content" do
|
25
|
+
stdin = StringIO.new("q")
|
26
|
+
stdout = StringIO.new
|
27
|
+
interact = Mastermind::Interact.new
|
28
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
29
|
+
game.run
|
30
|
+
expect(stdout.string).to include("(s)1nG1e")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should generate the specified number of players" do
|
34
|
+
stdin = StringIO.new("\nSimon\nAlvin\n")
|
35
|
+
stdout = StringIO.new
|
36
|
+
interact = Mastermind::Interact.new
|
37
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
38
|
+
players = game.player_gen(2)
|
39
|
+
expect(players.length).to eql(2)
|
40
|
+
expect(players[0]).to be_a Mastermind::Player
|
41
|
+
end
|
42
|
+
|
43
|
+
it "gets a valid name" do
|
44
|
+
stdin = StringIO.new("\nANameThatIsTooLong\nAlvin\n")
|
45
|
+
stdout = StringIO.new
|
46
|
+
interact = Mastermind::Interact.new
|
47
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
48
|
+
name = game.get_name(1)
|
49
|
+
expect(stdout.string).to include("Name")
|
50
|
+
expect(name).to eql("Alvin")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "can validate a name" do
|
54
|
+
stdin = StringIO.new("\nANameThatIsTooLong\nAlvin\n")
|
55
|
+
stdout = StringIO.new
|
56
|
+
interact = Mastermind::Interact.new
|
57
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
58
|
+
expect(game.valid_name?("ANameThatIsTooLong")).to be_falsey
|
59
|
+
expect(game.valid_name?("")).to be_falsey
|
60
|
+
expect(game.valid_name?("Theodore")).to be_truthy
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should play a single player game when prompted" do
|
64
|
+
stdin = StringIO.new("s\nTheodore\n")
|
65
|
+
stdout = StringIO.new()
|
66
|
+
interact = Mastermind::Interact.new
|
67
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
68
|
+
thread = Thread.new do
|
69
|
+
game.run
|
70
|
+
end
|
71
|
+
players = []
|
72
|
+
expect(Mastermind::GameRound.new(stdin, stdout, Mastermind::Interact.new, players)).to respond_to(:play)
|
73
|
+
thread.kill
|
74
|
+
end
|
75
|
+
|
76
|
+
# note: undefined method 'noecho' for stringio... not sure how to test this...
|
77
|
+
it "should play a multiplayer game when prompted" do
|
78
|
+
stdin = StringIO.new("m\nTheodore\nAlvin\n")
|
79
|
+
stdout = StringIO.new()
|
80
|
+
interact = Mastermind::Interact.new
|
81
|
+
players = []
|
82
|
+
game = Mastermind::PlayGame.new(stdin, stdout, interact)
|
83
|
+
thread = Thread.new do
|
84
|
+
game.run
|
85
|
+
end
|
86
|
+
expect(Mastermind::GameRound.new(stdin, stdout, Mastermind::Interact.new, players)).to respond_to(:play)
|
87
|
+
thread.kill
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'mastermind/processor'
|
2
|
+
|
3
|
+
RSpec.describe Mastermind::Processor do
|
4
|
+
it "generates a random 4 char secret code" do
|
5
|
+
secret = Mastermind::Processor.secret(4, 6)
|
6
|
+
expect(secret.length).to eql(4)
|
7
|
+
expect(Mastermind::Processor.valid_colors?(secret.join(""), Mastermind::Processor.colors(6))).to be_truthy
|
8
|
+
end
|
9
|
+
|
10
|
+
it "can pull the first x numbers" do
|
11
|
+
expect(Mastermind::Processor.colors(3)).to eql(["R", "Y", "G"])
|
12
|
+
end
|
13
|
+
|
14
|
+
context "when validating a guess" do
|
15
|
+
it "validates that a correct length guess is valid" do
|
16
|
+
valid_length = Mastermind::Processor.valid_length?("RBBY", ["R", "G", "R", "R"])
|
17
|
+
expect(valid_length).to be_truthy
|
18
|
+
end
|
19
|
+
|
20
|
+
it "says that an input containing only valid colors is valid" do
|
21
|
+
valid_color = Mastermind::Processor.valid_colors?("MRRB", ["R", "G", "B", "Y", "P", "M"])
|
22
|
+
expect(valid_color).to be_truthy
|
23
|
+
end
|
24
|
+
|
25
|
+
it "says that an input with the correct length and colors is valid" do
|
26
|
+
valid = Mastermind::Processor.validate("RGMY", ["R", "G", "B", "Y"], ["R", "G", "B", "Y", "P", "M"])
|
27
|
+
expect(valid).to be_truthy
|
28
|
+
end
|
29
|
+
|
30
|
+
it "says that an input that is too long is invalid" do
|
31
|
+
invalid = Mastermind::Processor.validate("RG", ["R", "G", "B", "Y"], ["R", "G", "B", "Y", "P", "M"])
|
32
|
+
expect(invalid).to be_falsey
|
33
|
+
end
|
34
|
+
|
35
|
+
it "says that an input that is too short is invalid" do
|
36
|
+
invalid = Mastermind::Processor.validate("XRESRG", ["R", "G", "B", "Y"], ["R", "G", "B", "Y", "P", "M"])
|
37
|
+
expect(invalid).to be_falsey
|
38
|
+
end
|
39
|
+
|
40
|
+
it "says that an input with invalid letters is invalid" do
|
41
|
+
invalid = Mastermind::Processor.validate("RRRX", ["R", "G", "B", "Y"], ["R", "G", "B", "Y", "P", "M"])
|
42
|
+
expect(invalid).to be_falsey
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when checking a valid guess" do
|
47
|
+
it "checks how many colors are correct but not in the correct position once" do
|
48
|
+
colors = Mastermind::Processor.num_correct_colors("YBBB", ["B", "P", "P", "Y"])
|
49
|
+
expect(colors).to eql(2)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "checks correct_colors again..." do
|
53
|
+
colors = Mastermind::Processor.num_correct_colors("RRBB", ["R", "R", "R", "R"])
|
54
|
+
expect(colors).to eql(0)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "checks how many colors are in the correct position" do
|
58
|
+
positions = Mastermind::Processor.num_correct_pos("RGYM", ["R", "M", "G", "M"])
|
59
|
+
expect(positions).to eql(2)
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|