mastermind-oscar 0.1.3
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 +15 -0
- data/.travis.yml +3 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +42 -0
- data/Rakefile +9 -0
- data/bin/mastermind_oscar +4 -0
- data/bin/setup +7 -0
- data/circle.yml +3 -0
- data/lib/mastermind/oscar.rb +16 -0
- data/lib/mastermind/oscar/codemaker.rb +208 -0
- data/lib/mastermind/oscar/game_manager.rb +123 -0
- data/lib/mastermind/oscar/printer.rb +180 -0
- data/lib/mastermind/oscar/record_manager.rb +185 -0
- data/lib/mastermind/oscar/time_manager.rb +45 -0
- data/lib/mastermind/oscar/version.rb +5 -0
- data/mastermind-oscar-0.1.1.gem +0 -0
- data/mastermind-oscar-0.1.2.gem +0 -0
- data/mastermind-oscar.gemspec +35 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f3032d53bfa63eb3052ad5ee7968cfc56e579729
|
4
|
+
data.tar.gz: 25805dcf3f4cc27e7d1e275bbe2a667f71090e41
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 12eb3f4b3d3a8d8974819d00ce8d45c7400a2df4a8d9f35cae54b13f0295121ba5c280a76fc2d995eed77cbb5b5c3b5f4129cc47e1623b989208ce458b112cc7
|
7
|
+
data.tar.gz: d13e7176e148ff319baf4b9137bc3ad6c0eca6cc0cbb842954426114d38aa2163808802ff3acc912a349b3fcd9471c0a1cdef46ecfe10dce5bcc03b68dc89b72
|
data/.gitignore
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
/files/expert_record.txt
|
11
|
+
/files/beginner_record.txt
|
12
|
+
/files/intermediate_record.txt
|
13
|
+
/files/top_ten_beginner.yaml
|
14
|
+
/files/top_ten_expert.yaml
|
15
|
+
/files/top_ten_intermediate.yaml
|
data/.travis.yml
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Oscar
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# Mastermind::Oscar
|
2
|
+
|
3
|
+
Mastermind_Oscar is a Ruby implementation of the classic board game of same name. The game is a code breaking game between two players; in this implementation, it is between a player and the computer.
|
4
|
+
|
5
|
+
The computer selects a random sequence of color characters whose length depends on the game level (beginner, intermediate and expert). The player tries to guess the sequence generated by the computer using the feedback from the computer at every attempt as a guide.
|
6
|
+
The game is over either when the player correctly guess the sequence or the player runs out of guesses; player has 12 guesses.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'mastermind-oscar'
|
14
|
+
```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install mastermind-oscar
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
To play the game, open your terminal and run mastermind_oscar. You can also run the game with a desired level as an optional argument e.g mastermind_oscar intermediate
|
27
|
+
|
28
|
+
## Development
|
29
|
+
|
30
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/mastermind_oscar` for an interactive prompt that will allow you to experiment.
|
31
|
+
|
32
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
33
|
+
|
34
|
+
## Contributing
|
35
|
+
|
36
|
+
1. Fork it ( https://github.com/andela-ooranagwa/mastermind-oscar/fork)
|
37
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
38
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
39
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
40
|
+
5. Create a new Pull Request
|
41
|
+
|
42
|
+
[](https://coveralls.io/github/andela-ooranagwa/mastermind-oscar?branch=master)
|
data/Rakefile
ADDED
data/bin/setup
ADDED
data/circle.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "mastermind/oscar/version"
|
2
|
+
require "mastermind/oscar/game_manager"
|
3
|
+
|
4
|
+
module Mastermind
|
5
|
+
module Oscar
|
6
|
+
extend self
|
7
|
+
def mastermind
|
8
|
+
$*.empty? ? arg = nil : arg = Mastermind::Oscar.game_level($*.first[0])
|
9
|
+
game = Mastermind::Oscar::GameManager.new(arg)
|
10
|
+
game.start_game
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
Mastermind::Oscar.mastermind
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require_relative "time_manager"
|
2
|
+
|
3
|
+
module Mastermind
|
4
|
+
module Oscar
|
5
|
+
class Codemaker
|
6
|
+
attr_reader :code, :timer, :difficulty, :recorder, :guess
|
7
|
+
def initialize(difficulty, recorder)
|
8
|
+
@difficulty = difficulty
|
9
|
+
@recorder = recorder
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
generate_code
|
14
|
+
@timer = TimeManager.new
|
15
|
+
@recorder.open_save_file(difficulty)
|
16
|
+
@recorder.print_to_file("Sequence: \t\t<#{code.join}>")
|
17
|
+
@timer.start_timer
|
18
|
+
init_message
|
19
|
+
|
20
|
+
return game_play
|
21
|
+
end
|
22
|
+
|
23
|
+
def game_play
|
24
|
+
max_guess = 12
|
25
|
+
@guess = 0
|
26
|
+
|
27
|
+
while !out_of_guess?(guess, max_guess)
|
28
|
+
input = get_input
|
29
|
+
|
30
|
+
if quit?(input)
|
31
|
+
return :quit
|
32
|
+
elsif cheat?(input)
|
33
|
+
cheat
|
34
|
+
return
|
35
|
+
elsif is_valid_input?(input)
|
36
|
+
@guess += 1
|
37
|
+
status = analyze_input(input)
|
38
|
+
return congratulations if status
|
39
|
+
end
|
40
|
+
Printer.output("\t\t\nYou've taken #{guess} out of #{max_guess} guesses.\n")
|
41
|
+
guess_again
|
42
|
+
end
|
43
|
+
|
44
|
+
#Some one that is out of guesses
|
45
|
+
return game_over
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_input(stream = STDIN)
|
49
|
+
input = stream.gets.chomp
|
50
|
+
input = input.nil? ? " " : input.upcase.strip
|
51
|
+
|
52
|
+
input
|
53
|
+
end
|
54
|
+
|
55
|
+
def analyze_input(input)
|
56
|
+
@recorder.print_to_file("Guess #{guess}:\t\t#{input}")
|
57
|
+
|
58
|
+
input = input.split("")
|
59
|
+
return true if input == code
|
60
|
+
|
61
|
+
exact = exact_match(code, input)
|
62
|
+
partial = partial_match(code, input, exact)
|
63
|
+
exact = exact.size
|
64
|
+
|
65
|
+
give_guess_feedback(input, exact, partial)
|
66
|
+
|
67
|
+
false
|
68
|
+
end
|
69
|
+
|
70
|
+
def exact_match(game_code, input)
|
71
|
+
exact = []
|
72
|
+
input.each_index do |index|
|
73
|
+
exact << index if game_code[index] == input[index]
|
74
|
+
end
|
75
|
+
exact
|
76
|
+
end
|
77
|
+
|
78
|
+
def partial_match(game_code, input,exact)
|
79
|
+
partials = [] + game_code
|
80
|
+
exact.each{|elt| partials[elt] = nil}
|
81
|
+
partial = 0
|
82
|
+
|
83
|
+
input.each_with_index do |item, index|
|
84
|
+
pIndex = partials.index(item)
|
85
|
+
|
86
|
+
if(pIndex && !exact.include?(index))
|
87
|
+
partial += 1
|
88
|
+
partials[pIndex] = nil
|
89
|
+
end
|
90
|
+
end
|
91
|
+
partial
|
92
|
+
end
|
93
|
+
|
94
|
+
def give_guess_feedback(input, exact, partial)
|
95
|
+
feedback = "Hmmm! Your guess, " + Printer.colour_letters(input) + ", has #{exact + partial} of the correct elements with #{exact} in the correct positions."
|
96
|
+
|
97
|
+
Printer.output(feedback)
|
98
|
+
end
|
99
|
+
|
100
|
+
def out_of_guess?(guess, max_guess)
|
101
|
+
guess.eql? max_guess
|
102
|
+
end
|
103
|
+
|
104
|
+
def quit?(input)
|
105
|
+
input[0].upcase == 'Q' if !input.empty?
|
106
|
+
end
|
107
|
+
|
108
|
+
def cheat?(input)
|
109
|
+
input.upcase == 'C' && input.length == 1
|
110
|
+
end
|
111
|
+
|
112
|
+
def cheat
|
113
|
+
Printer.show_cheat(color_code)
|
114
|
+
end
|
115
|
+
|
116
|
+
def generate_code
|
117
|
+
@code = []
|
118
|
+
specs = difficulties(difficulty)
|
119
|
+
@possible_colours = specs[1]
|
120
|
+
characters = specs[0]
|
121
|
+
|
122
|
+
characters.times do
|
123
|
+
index = rand(0...@possible_colours)
|
124
|
+
@code << colors[index]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def difficulties(key)
|
129
|
+
#key => [characters, colors]
|
130
|
+
specs = {
|
131
|
+
:beginner => [4, 4],
|
132
|
+
:intermediate => [6, 5],
|
133
|
+
:expert => [8, 6]
|
134
|
+
}
|
135
|
+
specs[key]
|
136
|
+
end
|
137
|
+
|
138
|
+
def colors
|
139
|
+
Printer.colors.keys
|
140
|
+
end
|
141
|
+
|
142
|
+
def init_message
|
143
|
+
a = (difficulty == :beginner) ? 'a' : 'an'
|
144
|
+
Printer.greet_user(@recorder.user, a, difficulty, code.size, create_color_string)
|
145
|
+
end
|
146
|
+
|
147
|
+
def create_color_string
|
148
|
+
count = 0
|
149
|
+
string = []
|
150
|
+
Printer.colors.each do |key, colo|
|
151
|
+
break if count == @possible_colours
|
152
|
+
text = colo.to_s
|
153
|
+
text.gsub!(text[0],"(#{text[0]})")
|
154
|
+
string << Printer.colour_text(text, colo)
|
155
|
+
count += 1
|
156
|
+
end
|
157
|
+
string[0...-1].join(", ") + ", and " + string.last
|
158
|
+
end
|
159
|
+
|
160
|
+
def is_valid_input?(input)
|
161
|
+
length = code.size
|
162
|
+
return true if input.length == length
|
163
|
+
|
164
|
+
puts "\t" + Printer.colour_background(" !!!::: Oops! Your input is too short :::!!!", :red) if input.length < length
|
165
|
+
puts "\t" + Printer.colour_background(" !!!::: Oops! Your input is too long :::!!!", :red) if input.length > length
|
166
|
+
|
167
|
+
false
|
168
|
+
end
|
169
|
+
|
170
|
+
def congratulations
|
171
|
+
@timer.stop_timer
|
172
|
+
play_time = @timer.get_time
|
173
|
+
congratulation_msg(play_time)
|
174
|
+
save_game(play_time)
|
175
|
+
|
176
|
+
:won
|
177
|
+
end
|
178
|
+
|
179
|
+
def congratulation_msg(play_time)
|
180
|
+
Printer.congratulations(@recorder.user,color_code, guess, play_time)
|
181
|
+
end
|
182
|
+
|
183
|
+
def save_game(play_time)
|
184
|
+
@recorder.print_to_file("Guessed the sequence in: #{play_time}")
|
185
|
+
@recorder.check_for_top_ten(code.join, guess, @timer.get_seconds, difficulty.to_s)
|
186
|
+
@recorder.close
|
187
|
+
end
|
188
|
+
|
189
|
+
def game_over
|
190
|
+
@timer.stop_timer
|
191
|
+
Printer.game_over(@recorder.user, color_code)
|
192
|
+
@recorder.print_to_file("Game over! #{@timer.get_time}")
|
193
|
+
@recorder.close
|
194
|
+
|
195
|
+
:end
|
196
|
+
end
|
197
|
+
|
198
|
+
def color_code
|
199
|
+
Printer.colour_letters(code.join)
|
200
|
+
end
|
201
|
+
|
202
|
+
def guess_again
|
203
|
+
Printer.output "\t\t\tGuess again"
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require_relative "printer"
|
2
|
+
require_relative "codemaker"
|
3
|
+
require_relative "record_manager"
|
4
|
+
require_relative "time_manager"
|
5
|
+
|
6
|
+
module Mastermind
|
7
|
+
module Oscar
|
8
|
+
class GameManager
|
9
|
+
attr_reader :difficulty, :user
|
10
|
+
|
11
|
+
def initialize(diff = nil)
|
12
|
+
@difficulty = diff
|
13
|
+
set_read_stream
|
14
|
+
|
15
|
+
RecordManager.create_save_files
|
16
|
+
end
|
17
|
+
|
18
|
+
# useful for testing inputs
|
19
|
+
def set_read_stream (stream = STDIN)
|
20
|
+
@stream = stream
|
21
|
+
end
|
22
|
+
|
23
|
+
def alert_invalid_input
|
24
|
+
Printer.output "\tHmmm! You entry seems incorrect. Try again."
|
25
|
+
end
|
26
|
+
|
27
|
+
def start_game(stub_for_test=false)
|
28
|
+
Printer.welcome_msg
|
29
|
+
status = true
|
30
|
+
|
31
|
+
while status
|
32
|
+
Printer.format_input_query
|
33
|
+
|
34
|
+
input = get_first_char
|
35
|
+
if input == 'q'
|
36
|
+
break
|
37
|
+
elsif input == 't'
|
38
|
+
show_top_10
|
39
|
+
status = !stub_for_test
|
40
|
+
elsif input == 'i'
|
41
|
+
show_instructions
|
42
|
+
status = !stub_for_test
|
43
|
+
elsif input == "r"
|
44
|
+
show_records
|
45
|
+
status = !stub_for_test
|
46
|
+
elsif input == 'p'
|
47
|
+
# play game
|
48
|
+
status = game_on? play
|
49
|
+
@difficulty = nil
|
50
|
+
else
|
51
|
+
alert_invalid_input
|
52
|
+
status = !stub_for_test
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@user ||= ''
|
56
|
+
Printer.quit_msg(user)
|
57
|
+
end
|
58
|
+
|
59
|
+
def play(allowed = true)
|
60
|
+
return :quit unless set_difficulty
|
61
|
+
@recorder= RecordManager.new(user)
|
62
|
+
@user = @recorder.user unless user
|
63
|
+
|
64
|
+
codemaker = Codemaker.new(difficulty, @recorder)
|
65
|
+
return codemaker.start if allowed
|
66
|
+
end
|
67
|
+
|
68
|
+
def get_first_char
|
69
|
+
return (@stream.gets + " ").chomp[0].downcase.strip
|
70
|
+
end
|
71
|
+
|
72
|
+
def set_difficulty
|
73
|
+
return true if difficulty
|
74
|
+
Printer.level_select_msg
|
75
|
+
input = get_first_char
|
76
|
+
|
77
|
+
return false if input.eql? 'q'
|
78
|
+
|
79
|
+
@difficulty = Mastermind::Oscar.game_level(input)
|
80
|
+
end
|
81
|
+
|
82
|
+
def game_on? (arg)
|
83
|
+
return false if arg == :quit
|
84
|
+
|
85
|
+
show_top_10(@difficulty) if arg == :won
|
86
|
+
return true
|
87
|
+
end
|
88
|
+
|
89
|
+
def show_records
|
90
|
+
Printer.output_file(RecordManager.get_records)
|
91
|
+
end
|
92
|
+
|
93
|
+
def show_instructions
|
94
|
+
Printer.output(RecordManager.get_instructions)
|
95
|
+
end
|
96
|
+
|
97
|
+
def show_top_10 (level = nil)
|
98
|
+
list = level.nil? ? Mastermind::Oscar.game_level.values : [level]
|
99
|
+
|
100
|
+
t_obj = TimeManager.new
|
101
|
+
|
102
|
+
list.each do |lvl|
|
103
|
+
lvl = lvl.to_s
|
104
|
+
rec = RecordManager.get_top_ten(lvl)
|
105
|
+
Printer.output_top_ten(lvl,rec,t_obj)
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.game_level(input = nil)
|
113
|
+
levels = Hash.new(:beginner)
|
114
|
+
levels['a'] = :expert
|
115
|
+
levels['i'] = :intermediate
|
116
|
+
levels['b'] = :beginner
|
117
|
+
|
118
|
+
return levels if input.nil?
|
119
|
+
|
120
|
+
levels[input]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require "colorize"
|
2
|
+
|
3
|
+
module Mastermind
|
4
|
+
module Oscar
|
5
|
+
class Printer
|
6
|
+
@@stream = STDOUT
|
7
|
+
def self.initialize
|
8
|
+
set_output_stream
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.output (content)
|
12
|
+
@@stream.puts content
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.stream
|
16
|
+
@@stream
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.colors
|
20
|
+
{
|
21
|
+
"R" => :red,
|
22
|
+
"G" => :green,
|
23
|
+
"B" => :blue,
|
24
|
+
"Y" => :yellow,
|
25
|
+
"C" => :cyan,
|
26
|
+
"M" => :magenta
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.colour_letters(word)
|
31
|
+
word = word.split("") unless word.is_a?(Array)
|
32
|
+
|
33
|
+
word = word.map!{ |letter| colour_text(letter,colors[letter]) }
|
34
|
+
word.join
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.colour_text (content, colour)
|
38
|
+
content.colorize(:color => colour)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.colour_background (content, colour)
|
42
|
+
content.colorize(:background => colour)
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.colour_background_text (content, colour, b_colour)
|
46
|
+
content.colorize(:background => b_colour).colorize(:color => colour)
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.set_output_stream (stream = STDOUT)
|
50
|
+
@@stream = stream
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.format_input_query
|
54
|
+
output game_message
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.output_file(file)
|
58
|
+
file.each do |f|
|
59
|
+
f.each_line do |line|
|
60
|
+
fColor = line.split("\t\t")
|
61
|
+
if fColor.size == 2
|
62
|
+
fColor[-1] = colour_letters(fColor.last);
|
63
|
+
line = fColor.join("\t\t")
|
64
|
+
end
|
65
|
+
print line
|
66
|
+
end
|
67
|
+
f.close
|
68
|
+
puts "\n\n"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.output_top_ten(level, array,time_obj)
|
73
|
+
puts "\t\t*****#{level.upcase} Leaderboard*****"
|
74
|
+
count = 1
|
75
|
+
array.each do |entry|
|
76
|
+
name = entry[:name]
|
77
|
+
code = colour_letters(entry[:code])
|
78
|
+
guess = entry[:guess]
|
79
|
+
time = time_obj.get_time(entry[:time])
|
80
|
+
output(top_score_display_text(count,name,code,guess,time))
|
81
|
+
count += 1
|
82
|
+
end
|
83
|
+
puts ""
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.top_score_display_text(count,name,code,guess,time)
|
87
|
+
"#{count}. #{name} solved '#{code}' in #{guess} guesses over #{time}"
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.game_message
|
91
|
+
mess = <<-EOS
|
92
|
+
\t* Enter p to play
|
93
|
+
\t* Enter i for instructions
|
94
|
+
\t* Enter t for top scores
|
95
|
+
\t* Enter r for records
|
96
|
+
\t* Enter q to quit
|
97
|
+
\n
|
98
|
+
EOS
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.welcome_msg
|
102
|
+
output <<-EOS
|
103
|
+
|
104
|
+
( ` ) (
|
105
|
+
)\))( ) ( /( ( ( ) ( )\ )
|
106
|
+
((_)()\ ( /( ( )\()) ))\ )( ( )\ ( (()/(
|
107
|
+
(_()((_) )(_)) )\ (_))/ /((_)(()\ )\ '((_) )\ ) ((_))
|
108
|
+
| \/ |((_)_ ((_)| |_ (_)) ((_) _((_)) (_) _(_/( _| |
|
109
|
+
| |\/| |/ _` |(_-<| _|/ -_) | '_|| ' \() | || ' \))/ _` |
|
110
|
+
|_| |_|\__,_|/__/ \__|\___| |_| |_|_|_| |_||_||_| \__,_| "
|
111
|
+
|
112
|
+
\n\t\t.::::::::::::::. WELCOME .:::::::::::::::.\n\n
|
113
|
+
EOS
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.level_select_msg
|
117
|
+
output <<-EOS
|
118
|
+
******* SET GAME DIFFICULTY *******
|
119
|
+
* Enter b for beginner
|
120
|
+
* Enter i for intermediate
|
121
|
+
* Enter a for expert
|
122
|
+
[invalid entry will default to beginner]
|
123
|
+
\n
|
124
|
+
EOS
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.quit_msg(user)
|
128
|
+
output <<-EOS
|
129
|
+
\n\t\t.:::::::::. Thank you for playing, #{user} .::::::::::.
|
130
|
+
\t
|
131
|
+
\t\t+-+-+-+-+-+-+-+
|
132
|
+
\t\t|C|I|A|O|!|!|!|
|
133
|
+
\t\t+-+-+-+-+-+-+-+
|
134
|
+
EOS
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.greet_user(user, a, diff, csize, colors)
|
138
|
+
output <<-EOS
|
139
|
+
\n\t\t.:: Nice to meet you, #{user} ::.
|
140
|
+
|
141
|
+
Ok, I have generated a #{diff} sequence with #{csize} elements made of :
|
142
|
+
\t#{colors}
|
143
|
+
\tEnter (q)uit at any time to exit the game\n\n
|
144
|
+
\t CAN YOU GUESS THE SEQUENCE?
|
145
|
+
EOS
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.show_cheat(code)
|
149
|
+
output <<-EOS
|
150
|
+
\n\t\t\tThe sequence is
|
151
|
+
\t\t\t ========
|
152
|
+
\t\t\t ||#{code}||
|
153
|
+
\t\t\t ========\n\n
|
154
|
+
EOS
|
155
|
+
line
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.line
|
159
|
+
puts "-"*80 + "\n\n"
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.game_over(user, color)
|
163
|
+
output <<-EOS
|
164
|
+
\t ____ ______ ______ _______ __________
|
165
|
+
\t (( __||=||| \/ ||== (( ))\ //|==||_//
|
166
|
+
\t \\_||| ||| ||___ \\_// \V/||__|| \\
|
167
|
+
\t\tYou have used up all your guesses.
|
168
|
+
EOS
|
169
|
+
show_cheat(color)
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.congratulations(user,color,guess, time)
|
173
|
+
output <<-EOS
|
174
|
+
\tCongratulations!!! #{user}
|
175
|
+
You guessed the sequence #{color} in #{guess} guesses over #{time}\n
|
176
|
+
EOS
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,185 @@
|
|
1
|
+
require "yaml"
|
2
|
+
module Mastermind
|
3
|
+
module Oscar
|
4
|
+
class RecordManager
|
5
|
+
attr_reader :user
|
6
|
+
|
7
|
+
def initialize(name = nil, stream = STDIN)
|
8
|
+
set_read_stream(stream)
|
9
|
+
name.nil? ? set_user : @user = name
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.create_save_files
|
13
|
+
Dir.mkdir(file_path) unless Dir.exist?(file_path)
|
14
|
+
level = Mastermind::Oscar.game_level.values
|
15
|
+
level.each do |lvl|
|
16
|
+
File.open("#{file_path}top_ten_#{lvl}.yaml","w+")
|
17
|
+
File.open("#{file_path}#{lvl}_record.txt", "w+")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def file_path
|
22
|
+
RecordManager.file_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.file_path
|
26
|
+
# File.join(File.dirname(File.expand_path(__FILE__)), '../../../files/')
|
27
|
+
"files/"
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_user
|
31
|
+
print <<-EOS
|
32
|
+
\tAwesome!, you want to play. Let's begin!
|
33
|
+
\tMy name is Mastermind; what's is yours?
|
34
|
+
EOS
|
35
|
+
@user = @stream.gets.chomp.capitalize
|
36
|
+
@user = "Anonymous" if @user.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def open_save_file(difficulty)
|
40
|
+
@input_file = File.open(file_path+difficulty.to_s+"_record.txt", "a+")
|
41
|
+
initalize_file
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_read_stream (stream = STDIN)
|
45
|
+
@stream = stream
|
46
|
+
end
|
47
|
+
|
48
|
+
def print_to_file (content)
|
49
|
+
@input_file.puts content
|
50
|
+
end
|
51
|
+
|
52
|
+
def initalize_file
|
53
|
+
text = "\nName:\t#{@user}\n"
|
54
|
+
text += Time.now.strftime("%l:%M%P %b %d, %Y")
|
55
|
+
print_to_file(text)
|
56
|
+
end
|
57
|
+
|
58
|
+
def close
|
59
|
+
@input_file.close if @input_file
|
60
|
+
end
|
61
|
+
|
62
|
+
def check_for_top_ten(code, guess, time, difficulty)
|
63
|
+
top_ten = self.class.get_top_ten(difficulty)
|
64
|
+
position = is_hero?(top_ten, guess, time)
|
65
|
+
|
66
|
+
position = top_ten.size if(!position && top_ten.size < 10)
|
67
|
+
|
68
|
+
if position
|
69
|
+
top_ten = insert_in_top_ten(prep_hash(code, guess, time), position, top_ten)
|
70
|
+
|
71
|
+
save_top_ten(top_ten, difficulty)
|
72
|
+
return position
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def save_top_ten(array,difficulty)
|
77
|
+
file = self.class.get_heros_file(difficulty)
|
78
|
+
serial = YAML::dump(array)
|
79
|
+
File.open(file, "w+") {|f| f.puts serial}
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.get_heros_file(difficulty)
|
83
|
+
"#{file_path}top_ten_#{difficulty}.yaml"
|
84
|
+
end
|
85
|
+
|
86
|
+
def insert_in_top_ten(hero, position, array)
|
87
|
+
new_arr = []
|
88
|
+
i = 0
|
89
|
+
shift = false
|
90
|
+
limit = array.size
|
91
|
+
limit = (limit >= 10) ? limit : limit + 1
|
92
|
+
|
93
|
+
limit.times do
|
94
|
+
if i == position
|
95
|
+
new_arr << hero
|
96
|
+
shift = true
|
97
|
+
else
|
98
|
+
index = shift ? i - 1 : i
|
99
|
+
new_arr << array[index]
|
100
|
+
end
|
101
|
+
i += 1
|
102
|
+
end
|
103
|
+
|
104
|
+
new_arr
|
105
|
+
end
|
106
|
+
|
107
|
+
def prep_hash(code, guess, time)
|
108
|
+
{
|
109
|
+
name: user,
|
110
|
+
code: code,
|
111
|
+
guess: guess,
|
112
|
+
time: time
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.get_records
|
117
|
+
#levels = []
|
118
|
+
#if difficulty
|
119
|
+
# levels << difficulty
|
120
|
+
#else
|
121
|
+
levels = Mastermind::Oscar.game_level
|
122
|
+
levels = levels.values
|
123
|
+
#end
|
124
|
+
|
125
|
+
files = []
|
126
|
+
levels.each do |level|
|
127
|
+
files << File.open("files/"+level.to_s+"_record.txt", "r+")
|
128
|
+
end
|
129
|
+
files
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.get_instructions
|
133
|
+
msg = <<-EOS
|
134
|
+
Playing Mastermind is pretty easy.
|
135
|
+
|
136
|
+
##Rules
|
137
|
+
|
138
|
+
* Once the game starts, you have the option to either play, view instructions, view top ten scores or view score records
|
139
|
+
* To play the game, enter p
|
140
|
+
* To view instructions, enter i
|
141
|
+
* To view top ten scores, enter t
|
142
|
+
* To view score records, enter s
|
143
|
+
* Once you enter p to play, your are given the option to select a difficulty level; beginner, intermediate or expert. The level default to beginner for invalid choice.
|
144
|
+
* You will be required to enter you name to aid in recording your score
|
145
|
+
* Computer will generate a set of random characters made of colours. The lenght of the characters generated and the colours used depends on the game level.
|
146
|
+
* For beginners, 4 characters consisting of red, blue, green and/or yellow. e.g. rbgy
|
147
|
+
* For intermediate, 6 characters consisting of red, blue, green, yellow and/or cyan e.g. rrbyc
|
148
|
+
* For expert, 8 characters consisting of red, blue, green, yellow, cyan and magenta e.g. bgrrgm
|
149
|
+
* Note that colours can be repeated in the sequence
|
150
|
+
* You are to guess the sequence by inputing the combination.
|
151
|
+
* You will be given helpful feedback on each guess you make. Study the feedback to know the colours you were able to guess and their right position in the sequence.
|
152
|
+
* After 12 unsuccessful attempts, the game is over and you lost
|
153
|
+
* You can stop the game at any time by inputing q
|
154
|
+
|
155
|
+
Have fun
|
156
|
+
EOS
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.get_top_ten (difficulty)
|
160
|
+
file = get_heros_file(difficulty)
|
161
|
+
content = []
|
162
|
+
File.open(file, "r+") do |val|
|
163
|
+
content = YAML::load(val)
|
164
|
+
end
|
165
|
+
content = [] if !content
|
166
|
+
content
|
167
|
+
end
|
168
|
+
|
169
|
+
def is_hero?(heros, guess, time)
|
170
|
+
return unless heros.is_a?(Array)
|
171
|
+
guess = guess.to_i
|
172
|
+
heros.each_with_index do |hero, index|
|
173
|
+
hero[:guess] = hero[:guess].to_i
|
174
|
+
if hero[:guess].to_i > guess
|
175
|
+
return index
|
176
|
+
elsif hero[:guess] == guess
|
177
|
+
return index if hero[:time] >time
|
178
|
+
end
|
179
|
+
end
|
180
|
+
nil
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Mastermind
|
2
|
+
module Oscar
|
3
|
+
class TimeManager
|
4
|
+
attr_reader :start, :stop
|
5
|
+
def start_timer
|
6
|
+
@start = Time.now
|
7
|
+
end
|
8
|
+
|
9
|
+
def stop_timer
|
10
|
+
@stop = Time.now
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_time(secs = get_seconds)
|
14
|
+
secs = secs.to_i
|
15
|
+
days, secs = evaluate(secs, 86400)
|
16
|
+
hour, secs = evaluate(secs, 3600)
|
17
|
+
min, secs = evaluate(secs, 60)
|
18
|
+
|
19
|
+
string = []
|
20
|
+
string << to_string(days, 'day')
|
21
|
+
string << to_string(hour, 'hour')
|
22
|
+
string << to_string(min, 'minute')
|
23
|
+
string << to_string(secs, 'second')
|
24
|
+
|
25
|
+
string.select!{|x| !x.nil?}
|
26
|
+
string.join(", ")
|
27
|
+
end
|
28
|
+
|
29
|
+
def evaluate(x,y)
|
30
|
+
[x / y, x % y]
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_seconds
|
34
|
+
stop - start
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_string(time, unit)
|
38
|
+
return if time == 0
|
39
|
+
|
40
|
+
time > 1 ? s = 's' : s = ''
|
41
|
+
"#{time} #{unit}#{s}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mastermind/oscar/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "mastermind-oscar"
|
8
|
+
spec.version = Mastermind::Oscar::VERSION
|
9
|
+
spec.authors = ["Oscar"]
|
10
|
+
spec.email = ["oskarromero3@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Implements the popular classic game: MASTERMIND}
|
13
|
+
spec.description = %q{Mastermind_Oscar is a Ruby implementation of the classic board game of same name. The game is a code breaking game between two players; in this implementation, it is between a player and the computer.}
|
14
|
+
spec.homepage = "https://github.com/andela-ooranagwa/mastermind-oscar.git"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
18
|
+
# delete this section to allow pushing this gem to any host.
|
19
|
+
if spec.respond_to?(:metadata)
|
20
|
+
spec.metadata['allowed_push_host'] = "https://rubygems.org"
|
21
|
+
else
|
22
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
23
|
+
end
|
24
|
+
|
25
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
|
+
spec.bindir = "bin"
|
27
|
+
spec.executables = ['mastermind_oscar']
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
spec.add_development_dependency 'pry', "~> 0.10", ">= 0.10.1"
|
30
|
+
spec.add_development_dependency "bundler", "~> 1.9"
|
31
|
+
spec.add_development_dependency "minitest-reporters", "~> 1.1", ">= 1.1.0"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_runtime_dependency "colorize", "~> 0.7", ">= 0.7.7"
|
34
|
+
spec.add_development_dependency 'simplecov', "~> 0.10", ">= 0.10.0" #, require: false
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mastermind-oscar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Oscar
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.10'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 0.10.1
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.10'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.10.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.9'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.9'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: minitest-reporters
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.1'
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.1.0
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.1'
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.1.0
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rake
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '10.0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '10.0'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: colorize
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0.7'
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 0.7.7
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0.7'
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 0.7.7
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: simplecov
|
103
|
+
requirement: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - "~>"
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0.10'
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.10.0
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.10'
|
118
|
+
- - ">="
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: 0.10.0
|
121
|
+
description: Mastermind_Oscar is a Ruby implementation of the classic board game of
|
122
|
+
same name. The game is a code breaking game between two players; in this implementation,
|
123
|
+
it is between a player and the computer.
|
124
|
+
email:
|
125
|
+
- oskarromero3@gmail.com
|
126
|
+
executables:
|
127
|
+
- mastermind_oscar
|
128
|
+
extensions: []
|
129
|
+
extra_rdoc_files: []
|
130
|
+
files:
|
131
|
+
- ".gitignore"
|
132
|
+
- ".travis.yml"
|
133
|
+
- CODE_OF_CONDUCT.md
|
134
|
+
- Gemfile
|
135
|
+
- LICENSE.txt
|
136
|
+
- README.md
|
137
|
+
- Rakefile
|
138
|
+
- bin/mastermind_oscar
|
139
|
+
- bin/setup
|
140
|
+
- circle.yml
|
141
|
+
- lib/mastermind/oscar.rb
|
142
|
+
- lib/mastermind/oscar/codemaker.rb
|
143
|
+
- lib/mastermind/oscar/game_manager.rb
|
144
|
+
- lib/mastermind/oscar/printer.rb
|
145
|
+
- lib/mastermind/oscar/record_manager.rb
|
146
|
+
- lib/mastermind/oscar/time_manager.rb
|
147
|
+
- lib/mastermind/oscar/version.rb
|
148
|
+
- mastermind-oscar-0.1.1.gem
|
149
|
+
- mastermind-oscar-0.1.2.gem
|
150
|
+
- mastermind-oscar.gemspec
|
151
|
+
homepage: https://github.com/andela-ooranagwa/mastermind-oscar.git
|
152
|
+
licenses:
|
153
|
+
- MIT
|
154
|
+
metadata:
|
155
|
+
allowed_push_host: https://rubygems.org
|
156
|
+
post_install_message:
|
157
|
+
rdoc_options: []
|
158
|
+
require_paths:
|
159
|
+
- lib
|
160
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
166
|
+
requirements:
|
167
|
+
- - ">="
|
168
|
+
- !ruby/object:Gem::Version
|
169
|
+
version: '0'
|
170
|
+
requirements: []
|
171
|
+
rubyforge_project:
|
172
|
+
rubygems_version: 2.2.2
|
173
|
+
signing_key:
|
174
|
+
specification_version: 4
|
175
|
+
summary: 'Implements the popular classic game: MASTERMIND'
|
176
|
+
test_files: []
|
177
|
+
has_rdoc:
|