mastermind-orion 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 13cae8fa270e213595e02d183851ded101cf90ad
4
+ data.tar.gz: 82f5a407bc19aa1014c263a29750e753921d82e4
5
+ SHA512:
6
+ metadata.gz: fb6e1b5cf3f29199383c3f3d23e7a1e10f4d73f0fd49c5df46dd38eff0e8d00b14930310d4a5565097c444a26f4f3cc3d7a7a78439f78cfb5a81811abce3ff54
7
+ data.tar.gz: 4a3d74d7c45a4e45e16dfb48fad043c5bbe2ebfeabf7ed1323327e3a09b1961e161f4212a70f95b98d36e33be2bda799edb8f4c8043a079b618642e782c31c7c
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ lib_dir = File.expand_path('../lib/*.rb', __dir__)
4
+ $LOAD_PATH.unshift(lib_dir)
5
+ require 'game_interface'
6
+
7
+ GameInterface.new($stdin, $stdout).start
data/lib/display.rb ADDED
@@ -0,0 +1,90 @@
1
+ require 'colorize'
2
+
3
+ class Display
4
+ COLORS = {
5
+ "r" => "(#{"r".colorize(:red)})ed",
6
+ "g" => "(#{"g".colorize(:green)})reen",
7
+ "b" => "(#{"b".colorize(:blue)})lue",
8
+ "y" => "(#{"y".colorize(:yellow)})ellow",
9
+ "w" => "(#{"w".colorize(:white)})hite",
10
+ "c" => "(#{"c".colorize(:cyan)})yan",
11
+ "m" => "(#{"m".colorize(:magenta)})agenta"
12
+ }
13
+
14
+ GUESS_COLORS = {
15
+ "r" => "#{"R".colorize(:red)}",
16
+ "g" => "#{"G".colorize(:green)}",
17
+ "b" => "#{"B".colorize(:blue)}",
18
+ "y" => "#{"Y".colorize(:yellow)}",
19
+ "w" => "#{"W".colorize(:white)}",
20
+ "c" => "#{"C".colorize(:cyan)}",
21
+ "m" => "#{"M".colorize(:magenta)}"
22
+ }
23
+
24
+ attr_reader :welcome,
25
+ :initial_message,
26
+ :invalid_input,
27
+ :instructions,
28
+ :guess_too_short,
29
+ :guess_too_long,
30
+ :play_message,
31
+ :invalid_guess,
32
+ :guess_question,
33
+ :win_question,
34
+ :level
35
+
36
+ def initialize
37
+ @welcome = "\nWelcome to...\n" +
38
+ "
39
+
40
+ _/ _/ _/_/ _/_/_/ _/_/_/_/_/ _/_/_/_/ _/_/_/ _/ _/ _/_/_/ _/ _/ _/_/_/
41
+ _/_/ _/_/ _/ _/ _/ _/ _/ _/ _/ _/_/ _/_/ _/ _/_/ _/ _/ _/
42
+ _/ _/ _/ _/_/_/_/ _/_/ _/ _/_/_/ _/_/_/ _/ _/ _/ _/ _/ _/ _/ _/ _/
43
+ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/ _/_/ _/ _/
44
+ _/ _/ _/ _/ _/_/_/ _/ _/_/_/_/ _/ _/ _/ _/ _/_/_/ _/ _/ _/_/_/
45
+
46
+
47
+ ".colorize(:blue)
48
+
49
+ @initial_message = "Would you like to (p)lay, read the (i)nstructions, or (q)uit?"
50
+ @invalid_input = "Invalid input! Please type (p) for play, (i) for instructions, or (q) for quit."
51
+ @instructions =
52
+
53
+ "\nThe computer will select a set of four, five, or seven colors at random,
54
+ depending upon the difficulty level selected. Duplicates may be possible.
55
+ Your task will be to guess the colors and order in which they are placed.
56
+ You will be prompted to enter your guess using the first letter of the color,
57
+ for example [rbgy]. After each guess the correct number of colors guessed,
58
+ regardless of position, will be displayed. The number of correctly placed
59
+ colors will also be displayed. Using that information and multiple guesses
60
+ you will be able to discover the answer and win!\n"
61
+
62
+ @guess_too_short = "Your guess was too short."
63
+ @guess_too_long = "Your guess was too long."
64
+ @guess_question = "\nWhat's your guess?\n"
65
+ @invalid_guess = "Invalid guess."
66
+ @win_question = "\nDo you want to (p)lay again or (q)uit?"
67
+ @level = "\nWould you like to play (e)asy, (i)ntermediate, or (h)ard?"
68
+ end
69
+
70
+ def determine_play_message(colors)
71
+ possible_colors_message = ""
72
+ colors.chars.each do |color|
73
+ possible_colors_message += COLORS[color] + "\n"
74
+ end
75
+ difficulty_level = {
76
+ 'rgby' => 'beginner',
77
+ 'rgbyw' => 'intermediate',
78
+ 'rgbywcm' => 'expert'
79
+ }
80
+ @play_message = "\nI have generated a#{'n' if difficulty_level[colors] == 'intermediate' || difficulty_level[colors] == 'expert'} #{difficulty_level[colors]} sequence with #{colors.length} elements made up of:\n\n#{possible_colors_message}\nUse (q)uit at any time to end the game.\n"
81
+ end
82
+
83
+ def guess_stats(player_guess, number_of_correct_colors, number_of_correct_positions, guess_count)
84
+ "'#{player_guess.chars.map { |color| GUESS_COLORS[color]}.join}' has #{number_of_correct_colors} of the correct elements with #{number_of_correct_positions} in the correct positions.\nYou have taken #{ guess_count } guess#{ "es" if guess_count > 1 }"
85
+ end
86
+
87
+ def win_message(player_guess, guess_count, minutes, seconds)
88
+ @win_message = "Congratulations! You guessed the sequence '#{player_guess}' in #{guess_count} guesses over #{minutes} #{minutes == 1 ? 'minute' : 'minutes'},\n#{seconds} seconds."
89
+ end
90
+ end
data/lib/game.rb ADDED
@@ -0,0 +1,93 @@
1
+ require_relative 'sequence'
2
+ require_relative 'guess'
3
+ require_relative 'display'
4
+ require_relative 'guess_stats'
5
+ require_relative 'trash_talking'
6
+
7
+ class Game
8
+ include GuessStats
9
+ include TrashTalking
10
+
11
+ attr_reader :in_stream,
12
+ :out_stream,
13
+ :sequence,
14
+ :display,
15
+ :beginning_time,
16
+ :ending_time,
17
+ :guess_count,
18
+ :guess,
19
+ :colors
20
+
21
+ def initialize(in_stream, out_stream, display, colors='rgby')
22
+ @in_stream = in_stream
23
+ @out_stream = out_stream
24
+ @display = display
25
+ @colors = colors
26
+ @sequence = Sequence.new(colors)
27
+ @guess = Guess.new('', colors)
28
+ @guess_count = 0
29
+ end
30
+
31
+ def play
32
+ @beginning_time = Time.now
33
+ out_stream.puts display.determine_play_message(colors)
34
+ out_stream.puts display.guess_question
35
+ until win? || exit?
36
+ @guess = Guess.new(in_stream.gets.strip, colors)
37
+ exit! if exit?
38
+ @guess_count += 1
39
+ process_game_turn
40
+ end
41
+ if win?
42
+ @ending_time = Time.now
43
+ compute_game_stats
44
+ end
45
+ end
46
+
47
+ def process_game_turn
48
+ case
49
+ when guess.invalid?
50
+ out_stream.puts display.invalid_guess
51
+ when guess.too_short?
52
+ out_stream.puts display.guess_too_short
53
+ trash_talk_too_short
54
+ when guess.too_long?
55
+ out_stream.puts display.guess_too_long
56
+ when win?
57
+ trash_talk_congratulations
58
+ when exit?
59
+ exit!
60
+ else
61
+ compute_guess_stats
62
+ trash_talk_quip if guess_count % 3 == 0
63
+ end
64
+ out_stream.puts display.guess_question if (!win? || !exit?)
65
+ end
66
+
67
+ def win?
68
+ guess.player_guess == sequence.solution
69
+ end
70
+
71
+ def exit?
72
+ trash_talk_quit if guess.player_guess == 'q' || guess.player_guess == 'quit'
73
+ guess.player_guess == 'q' || guess.player_guess == 'quit'
74
+ end
75
+
76
+ def compute_guess_stats
77
+ number_of_correct_colors = compute_correct_colors(sequence.solution, guess.player_guess)
78
+ number_of_correct_positions = compute_correct_positions(sequence.solution, guess.player_guess)
79
+ out_stream.puts display.guess_stats(guess.player_guess, number_of_correct_colors, number_of_correct_positions, guess_count)
80
+ end
81
+
82
+ def compute_game_stats
83
+ beginning_seconds = convert_to_seconds(beginning_time)
84
+ ending_seconds = convert_to_seconds(ending_time)
85
+ minutes = (ending_seconds - beginning_seconds) / 60
86
+ seconds = (ending_seconds - beginning_seconds) % 60
87
+ out_stream.puts display.win_message(guess.player_guess, guess_count, minutes, seconds)
88
+ end
89
+
90
+ def convert_to_seconds(time)
91
+ time.hour * 60 * 60 + time.min * 60 + time.sec
92
+ end
93
+ end
@@ -0,0 +1,83 @@
1
+ require_relative 'display'
2
+ require_relative 'game'
3
+
4
+ class GameInterface
5
+ attr_reader :command,
6
+ :display,
7
+ :in_stream,
8
+ :out_stream
9
+
10
+ def initialize(in_stream, out_stream)
11
+ @command = ''
12
+ @display = Display.new
13
+ @in_stream = in_stream
14
+ @out_stream = out_stream
15
+ end
16
+
17
+ def start
18
+ out_stream.puts display.welcome
19
+ out_stream.puts display.initial_message
20
+ until finished?
21
+ @command = in_stream.gets.strip
22
+ process_initial_command
23
+ end
24
+ end
25
+
26
+ def process_initial_command
27
+ case
28
+ when play?
29
+ play_game
30
+ when instructions?
31
+ display_instructions
32
+ when finished?
33
+ else
34
+ display_invalid_input_message
35
+ end
36
+ end
37
+
38
+ def play_game
39
+ out_stream.puts display.level
40
+ @command = in_stream.gets.strip
41
+ Game.new(in_stream, out_stream, display, selected_level).play
42
+ out_stream.puts display.win_question
43
+ end
44
+
45
+ def display_instructions
46
+ out_stream.puts display.instructions
47
+ out_stream.puts display.win_question
48
+ end
49
+
50
+ def display_invalid_input_message
51
+ out_stream.puts display.invalid_input
52
+ end
53
+
54
+ def play?
55
+ command == 'p'
56
+ end
57
+
58
+ def instructions?
59
+ command == 'i'
60
+ end
61
+
62
+ def finished?
63
+ command == 'q' || command == 'quit'
64
+ end
65
+
66
+ private
67
+
68
+ def selected_level
69
+ levels[@command] || default_level
70
+ end
71
+
72
+ def levels
73
+ @levels ||= {
74
+ 'e' => 'rgby',
75
+ 'i' => 'rgbyw',
76
+ 'h' => 'rgbywcm'
77
+ }
78
+ end
79
+
80
+ def default_level
81
+ 'rgby'
82
+ end
83
+ end
data/lib/guess.rb ADDED
@@ -0,0 +1,24 @@
1
+ class Guess
2
+ attr_reader :player_guess,
3
+ :possible_colors,
4
+ :solution_length
5
+
6
+ def initialize(player_guess, colors='rgby')
7
+ @player_guess = player_guess
8
+ @possible_colors = colors
9
+ @solution_length = colors.length
10
+ end
11
+
12
+ def invalid?
13
+ valid_colors = /[^#{possible_colors}]+/
14
+ player_guess.match(valid_colors)
15
+ end
16
+
17
+ def too_short?
18
+ player_guess.length < solution_length
19
+ end
20
+
21
+ def too_long?
22
+ player_guess.length > solution_length
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ module GuessStats
2
+ def compute_correct_colors(solution, player_guess)
3
+ solution = solution.chars
4
+ player_guess = player_guess.chars
5
+ correct_color_count = 0
6
+ solution.each do |color|
7
+ if player_guess.include?(color)
8
+ player_guess.delete_at(player_guess.index(color))
9
+ correct_color_count += 1
10
+ end
11
+ end
12
+ correct_color_count
13
+ end
14
+
15
+ def compute_correct_positions(solution, player_guess)
16
+ solution = solution.chars
17
+ player_guess = player_guess.chars
18
+ solution.zip(player_guess).select do |item|
19
+ item[0] == item[1]
20
+ end.length
21
+ end
22
+ end
data/lib/sequence.rb ADDED
@@ -0,0 +1,15 @@
1
+ class Sequence
2
+ attr_reader :colors,
3
+ :solution
4
+
5
+ def initialize(colors='rgby')
6
+ @colors = colors
7
+ @solution = randomizer
8
+ end
9
+
10
+ def randomizer
11
+ colors.chars.map do
12
+ colors.chars.sample
13
+ end.join
14
+ end
15
+ end
@@ -0,0 +1,27 @@
1
+ module TrashTalking
2
+ def trash_talk_too_short
3
+ system("say 'Your guess was too small, like your brain.'")
4
+ end
5
+
6
+ def trash_talk_congratulations
7
+ system("say 'Congratulations. We are all a little bit dumber for having watched you play.'")
8
+ end
9
+
10
+ def trash_talk_quit
11
+ system("say 'Your parents were right, you are a quitter.'")
12
+ end
13
+
14
+ def trash_talk_quip
15
+ system("say #{generate_quip}")
16
+ end
17
+
18
+ def generate_quip
19
+ possible_quips = [
20
+ 'You are a good example of why some animals eat their young.',
21
+ 'Are you even trying?',
22
+ 'Why dont you slip into something more comfortable? Like a coma.',
23
+ 'I could say nice things about you, but I would rather tell the truth.'
24
+ ]
25
+ possible_quips.sample
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'mastermind-orion'
3
+ s.version = '0.0.1'
4
+ s.date = '2014-11-13'
5
+ s.summary = "Try to guess the secret code."
6
+ s.description = "The Mastermind Game"
7
+ s.authors = ["Orion Osborn"]
8
+ s.email = 'orion.osborn@gmail.com'
9
+ s.files = %w[mastermind-orion.gemspec
10
+ mastermind.rb
11
+ lib/display.rb
12
+ lib/game_interface.rb
13
+ lib/game.rb
14
+ lib/guess_stats.rb
15
+ lib/guess.rb
16
+ lib/sequence.rb
17
+ lib/trash_talking.rb ]
18
+ s.homepage = 'http://rubygems.org/gems/mastermind-orion'
19
+ s.license = 'OLO'
20
+ s.executables << 'mastermind-orion'
21
+
22
+ s.add_runtime_dependency 'colorize', '>= 0.7.3'
23
+ end
data/mastermind.rb ADDED
@@ -0,0 +1,5 @@
1
+ lib_dir = File.expand_path('lib', __dir__)
2
+ $LOAD_PATH.unshift(lib_dir)
3
+ require 'game_interface'
4
+
5
+ GameInterface.new($stdin, $stdout).start
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mastermind-orion
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Orion Osborn
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: colorize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.7.3
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.7.3
27
+ description: The Mastermind Game
28
+ email: orion.osborn@gmail.com
29
+ executables:
30
+ - mastermind-orion
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - bin/mastermind-orion
35
+ - lib/display.rb
36
+ - lib/game.rb
37
+ - lib/game_interface.rb
38
+ - lib/guess.rb
39
+ - lib/guess_stats.rb
40
+ - lib/sequence.rb
41
+ - lib/trash_talking.rb
42
+ - mastermind-orion.gemspec
43
+ - mastermind.rb
44
+ homepage: http://rubygems.org/gems/mastermind-orion
45
+ licenses:
46
+ - OLO
47
+ metadata: {}
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 2.4.2
65
+ signing_key:
66
+ specification_version: 4
67
+ summary: Try to guess the secret code.
68
+ test_files: []