chadet 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: 6cfd2236b309e3803cd4a359698031aa14bc4769
4
+ data.tar.gz: 482cfc03d09d4d6521d9b132caa172f24cb44929
5
+ SHA512:
6
+ metadata.gz: 553de67587410c0583ada232854e81061d4da84e22d5f05dfe60d8eeaa5a82da61a6fa647ce09ed862396f5eeb83bc15478ea92f7c354e5d5800a6e5b167adac
7
+ data.tar.gz: 210db35063e06da63b93862978cc84c7302591900bb50a24b2be7a244f0a944b45ed4b7432b687c703b51ccb248deca02f8996c037ecf8038ad4e7ae7bcd0e29
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in chadet.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 astyd
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Chadet
2
+
3
+ Characters Detective. Game of guessing characters intelligently.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'chadet'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install chadet
20
+
21
+ ## Usage
22
+
23
+ Type: 'chadet --help' for options.
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://bitbucket.org/astyd/chadet/ )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/chadet ADDED
@@ -0,0 +1,272 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse' # to parse the command options
4
+ require 'set' # to check character redundancy
5
+ require 'chadet'
6
+
7
+ class String
8
+ # define methods for coloring text
9
+ colors = {:red => 31, :green => 32, :yellow => 33, :blue => 34, :cyan=> 36}
10
+ colors.each do |k, v|
11
+ define_method(k) {return "\e[#{v}m#{self}\e[0m" }
12
+ end
13
+
14
+ def flash seconds = 2
15
+ info = " " + self
16
+ print info
17
+ sleep seconds
18
+ print "\r" + " "*info.gsub(/\e\[\d*m(.*)\e\[0m/, '\1').length
19
+ print "\r"
20
+ end
21
+
22
+ def blink num_of_times = 4
23
+ info = " " + self
24
+ print "\n"
25
+ x = num_of_times
26
+ x.times do
27
+ print info.gsub(/[\w!?\.\'\(\)˚\-。ー\;\/\"\:<>+,★·.·´¯`░]/, " ")
28
+ sleep 0.18*x/4
29
+ print (info.lines.length == 1 ? "\r" : "\r\e[#{info.lines.count-1}A")
30
+ print info.yellow
31
+ sleep 0.1
32
+ print (info.lines.length == 1 ? "\r" : "\r\e[#{info.lines.count-1}A")
33
+ x -= 0.2
34
+ end
35
+ puts info.yellow
36
+ end
37
+
38
+ def flash seconds = 2
39
+ info = " " + self
40
+ print info
41
+ sleep seconds
42
+ print "\r" + " "*info.gsub(/\e\[\d*m(.*)\e\[0m/, '\1').length
43
+ print "\r"
44
+ end
45
+
46
+ def blink num_of_times = 4
47
+ info = " " + self
48
+ print "\n"
49
+ x = num_of_times
50
+ x.times do
51
+ print info.gsub(/[\w!?\.\'\(\)˚\-。ー\;\/\"\:<>+,★·.·´¯`░]/, " ")
52
+ sleep 0.18*x/4
53
+ print (info.lines.length == 1 ? "\r" : "\r\e[#{info.lines.count-1}A")
54
+ print info.yellow
55
+ sleep 0.1
56
+ print (info.lines.length == 1 ? "\r" : "\r\e[#{info.lines.count-1}A")
57
+ x -= 0.2
58
+ end
59
+ puts info.yellow
60
+ end
61
+ end
62
+
63
+ # Specify new Hash to store the options
64
+ options = {}
65
+
66
+ # Create an option parser object to describe the type of options and their description
67
+ optparse = OptionParser.new do |opts|
68
+ opts.banner = "Usage:\n\n" \
69
+ + " chadet " \
70
+ + "[Options] Number... [Options] Characters... [Options]\n\n" \
71
+ + "Description:\n\n" \
72
+ + " Characters Detective.\n" \
73
+ + " Game of guessing characters. The default number of characters is 4 and\n" \
74
+ + " the default set of characters is decimal digits from 0 to 9.\n\n" \
75
+ + "Options:\n\n"
76
+
77
+ opts.on '-r', '--rules', 'How to play this game' do
78
+ rules_of_play = <<rules
79
+ -----------------------------------
80
+ How to play Characters Detective:
81
+ -----------------------------------
82
+ +-------------------------------------------------------------+
83
+ ◙ | As the game begins, computer generates a random set of |
84
+ | characters for you to guess. |
85
+ +-------------------------------------------------------------+
86
+ +-------------------------------------------------------------+
87
+ ◙ | This random set of characters is by default a 4 digit |
88
+ | decimal numbers, or the standard Bulls and Cows game, as |
89
+ | people know it. To change this behaviour, simply specify |
90
+ | the '--number=' (or simply '-n') option to change the |
91
+ | number of characters to guess and/or specify the |
92
+ | '--characters=' (or '-c') option to change the default set |
93
+ | of characters to guess. |
94
+ | |
95
+ | Example: |
96
+ | If you type \e[32mchadet --number=2 --characters=abcdef\e[0m you will |
97
+ | then play the game like this: |
98
+ | ,¸¸,ø¤º°``°º¤ø,¸¸,ø¤°``°º¤ø,¸¸,ø¤º°``°º¤ø,¸¸,ø¤º°``°º¤ø,¸¸ |
99
+ | ------------------ ------------------- |
100
+ | no.| chars cc. cp. |Set of characters| |
101
+ | ------------------ |to guess with: | |
102
+ | 1| \e[33mab\e[0m [\e[32m0\e[0m] [\e[32m0\e[0m] ------------------- |
103
+ | 2| \e[33mcd\e[0m [\e[32m1\e[0m] [\e[32m0\e[0m] |\e[33mabcdef\e[0m | |
104
+ | \e[32mGuess:\e[0m _ ------------------- |
105
+ | |
106
+ | |
107
+ | For more options, type: \e[32mchadet --help\e[0m |
108
+ +-------------------------------------------------------------+
109
+ +-------------------------------------------------------------+
110
+ ◙ | At first, you have to blindly guess the characters. |
111
+ +-------------------------------------------------------------+
112
+ +-------------------------------------------------------------+
113
+ ◙ | After each guess, computer will give you answer on how many |
114
+ | characters you guessed correctly (Correct Characters or |
115
+ | cc.) and how many characters that their positions you |
116
+ | guessed correctly (Correct Positions or cp.). |
117
+ +-------------------------------------------------------------+
118
+ +-------------------------------------------------------------+
119
+ ◙ | By analizing computer answers in the previous guesses, you |
120
+ | can guess inteligently next. |
121
+ +-------------------------------------------------------------+
122
+ +-------------------------------------------------------------+
123
+ ◙ | You can type \e[32msave\e[0m, \e[32mquit\e[0m, \e[32mload\e[0m or \e[32mhint\e[0m during the game. |
124
+ | Their names should imply what they can do. |
125
+ +-------------------------------------------------------------+
126
+ rules
127
+ puts rules_of_play
128
+ exit
129
+ end
130
+
131
+ options[:num_of_chars] = 4
132
+ opts.on '-n', '--number NUMBER', Integer, 'How many characters you want to play' do |num|
133
+ options[:num_of_chars] = num
134
+ end
135
+
136
+ options[:characters] = "0123456789"
137
+ opts.on '-c', '--characters CHARS SET', 'Set of characters you want to play' do |chars|
138
+ options[:characters] = chars
139
+ end
140
+
141
+ options[:test] = false
142
+ opts.on '-t', '--test [TEST MODE]', 'Display the characters to guess' do
143
+ options[:test] = true
144
+ end
145
+
146
+ options[:load] = false
147
+ opts.on '-g', '--load [LOAD GAME]', 'Load previously saved game' do
148
+ options[:load] = true
149
+ end
150
+
151
+ opts.on '-h', '--help', 'Display this message' do
152
+ puts opts
153
+ puts ""
154
+ exit
155
+ end
156
+
157
+ opts.on '-v', '--version', 'Display the version of this game' do
158
+ version = "Chadet v.0.0.1"
159
+ puts version
160
+ exit
161
+ end
162
+ end
163
+
164
+ # Run parse! on the parser object
165
+ optparse.parse!
166
+
167
+ # Set of characters to play with
168
+ chars_set = options[:characters]
169
+ if chars_set.length < 2
170
+ print "Chadet: ".green
171
+ puts "Cannot play with a set of character less than 2 characters.".red
172
+ exit
173
+ end
174
+
175
+ # Set number of characters based on option -d given or the default number of 4
176
+ num_of_chars = options[:num_of_chars]
177
+ if num_of_chars > chars_set.length
178
+ num_of_chars = chars_set.length
179
+ elsif num_of_chars < 1
180
+ print "Chadet: ".green
181
+ puts "Cannot play with less than 1 character to guess.".red
182
+ exit
183
+ end
184
+
185
+ secret_obj = Chadet::SecretCharacters.new(chars_set, num_of_chars)
186
+ chars_to_guess = secret_obj.secret_chars
187
+ num_of_chars = secret_obj.num_of_chars
188
+
189
+ # Set the number to guess
190
+ puts "The secret characters are: #{chars_to_guess}".blue if options[:test] == true
191
+
192
+ system('clear')
193
+ play = Chadet::Play.new(secret_obj)
194
+ play.header
195
+ play.chars_to_use
196
+ play.table_header
197
+
198
+ go = Chadet::Guess.new(chars_set)
199
+
200
+
201
+ # list of commands
202
+ load_commands = %w{load laod}
203
+ save_commands = %w{save svae saev sav sev}
204
+ exit_commands = %w{quit exit solve solv}
205
+ cheat_commands = %w{hint hit cheat clue bonus}
206
+
207
+ # Play the game until cc. & cp. = num_of_chars
208
+ begin
209
+ print "Guess: ".green
210
+ go.guess = gets.chomp
211
+ print "\r\e[1A" + " "*(go.guess.length + 7)
212
+ print "\r"
213
+ # Check for exit commands
214
+ if load_commands.include? go.guess.downcase
215
+ go.guess_num = play.load_game go, secret_obj
216
+ elsif save_commands.include? go.guess.downcase
217
+ go.guess_num = play.do_save go.guess_num
218
+ break if go.guess_num < 0
219
+ elsif exit_commands.include? go.guess.downcase
220
+ go.guess_num = play.do_quit go.guess_num
221
+ break if go.guess_num < 0
222
+ elsif cheat_commands.include? go.guess.downcase
223
+ play.do_hint
224
+ elsif go.guess.length < num_of_chars
225
+ "Not enough input characters!".red.flash 1
226
+ elsif go.wrong_input?
227
+ "Wrong input character!".red.flash 1
228
+ elsif go.is_redundant?
229
+ go.handle_redundancy
230
+ elsif go.guess.length > num_of_chars
231
+ ("We'll take the first#{num_of_chars == 1 ? '' : ' ' + num_of_chars.to_s} "\
232
+ + "character#{num_of_chars == 1 ? '' : 's'}.").green.flash 1.5
233
+ go.guess = go.guess[0...num_of_chars]
234
+ go.guess_num += 1
235
+ puts play.answer go.guess, go.guess_num
236
+ else
237
+ go.guess = go.guess[0...num_of_chars]
238
+ go.guess_num += 1
239
+ puts play.answer go.guess, go.guess_num
240
+ end
241
+ end until go.guess == secret_obj.secret_chars
242
+
243
+ play.end_game if go.guess_num > 0
244
+
245
+ # Congratulate the player for finishing the game
246
+ save = "Your game has been saved."
247
+ quit = "Try it again!"
248
+ lucky = "Wow! (˚o˚) Lucky guess."
249
+ congratulate = "★·.·´¯`·.·★·.·´¯`·.·★\n ░G░O░O░D░ ░J░O░B░!░\n ★·.·´¯`·.·★·.·´¯`·.·★\n" \
250
+ + " You did it in " + go.guess_num.to_s + " steps."
251
+ a_bit_slow = "(-。ー;) Finally..\n But don't beat yourself up. Try it again!\n I know you "\
252
+ + "can do better than " + go.guess_num.to_s + " guesses."
253
+
254
+ # To decide what message to display after the game finished
255
+ case go.guess_num
256
+ when -2
257
+ message = save
258
+ when -1
259
+ message = quit
260
+ when 1
261
+ message = lucky
262
+ when 2..chars_set.length
263
+ message = congratulate
264
+ else
265
+ message = a_bit_slow
266
+ end
267
+
268
+ if message == a_bit_slow
269
+ puts "\n " + message.yellow
270
+ else
271
+ message.blink
272
+ end
data/chadet.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'chadet/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "chadet"
8
+ spec.version = Chadet::VERSION
9
+ spec.authors = ["Adrian Setyadi"]
10
+ spec.email = ["a.styd@yahoo.com"]
11
+ spec.summary = %q{Characters Detective. Game of guessing characters intelligently.}
12
+ spec.description = %q{Computer will generate a random set of characters. The default number of characters is 4 and the default set of characters is decimal digits from 0 to 9. After each guess you make, computer will tell you how many characters you guessed correctly and how many characters that their position you guessed correctly.}
13
+ spec.homepage = "https://bitbucket.org/astyd"
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
+ end
@@ -0,0 +1,3 @@
1
+ module Chadet
2
+ VERSION = "0.0.1"
3
+ end
data/lib/chadet.rb ADDED
@@ -0,0 +1,296 @@
1
+ require "chadet/version"
2
+
3
+ module Chadet
4
+ class Play
5
+ def initialize secret_chars_object
6
+ @chars_set = secret_chars_object.chars_set
7
+ @num_of_chars = secret_chars_object.num_of_chars
8
+ @secret_chars = secret_chars_object.secret_chars
9
+ @loaded = false
10
+ @used_true = ""
11
+ @used_false = ""
12
+ @max_hint = (@chars_set.length/@num_of_chars).to_i
13
+ @hint_used = 0
14
+ @moves = ""
15
+ end
16
+
17
+ def header
18
+ puts "Type: " + "chadet --help".green + " in the terminal to see more options.\n"\
19
+ + "To quit this game at any time, type: " + "quit".green + "\n"
20
+ puts ",¸¸,ø¤º°``°º¤ø,¸¸,ø¤°``°º¤ø,¸¸,ø¤º°``°º¤ø,¸¸,ø¤º°``°º¤ø,¸¸"
21
+ end
22
+
23
+ def chars_to_use
24
+ @chars_set.length >= 17 ? box_width = @chars_set.length + 2 : box_width = 19
25
+ end_pos = 58
26
+ start_pos = end_pos - box_width
27
+ puts " "*start_pos + "+" + "-"*(box_width-2) + "+" + "\n"\
28
+ + " "*start_pos + "|Set of characters" + " "*(box_width - 19) + "|\n" \
29
+ + " "*start_pos + "|to guess with:" + " "*(box_width - 16) + "|\n" \
30
+ + " "*start_pos + "+" + "-"*(box_width-2) + "+" + "\n" \
31
+ + " "*start_pos + "|" + @chars_set.yellow + " "*(box_width - @chars_set.length - 2) + "|\n" \
32
+ + " "*start_pos + "+" + "-"*(box_width-2) + "+"
33
+ print "\r\e[6A"
34
+ end
35
+
36
+ def table_header
37
+ chars_pos = (5 + @num_of_chars - "chars".length)/2
38
+ cc_pos = 10 + @num_of_chars
39
+ cp_pos = 12 + @num_of_chars + 2*@num_of_chars.to_s.length
40
+ table_width = cp_pos + 2
41
+ puts " " + "-"*table_width + "\n"\
42
+ + " no.|" + " "*chars_pos + "chars" + " "*(cc_pos - chars_pos - "chars".length - " no.|".length) \
43
+ + "cc." + " "*(cp_pos - cc_pos - "cc.".length)\
44
+ + "cp." + "\n"\
45
+ + " " + "-"*table_width
46
+ end
47
+
48
+ def end_game
49
+ # table bottom horizontal line
50
+ cp_pos = 12 + @num_of_chars + 2*@num_of_chars.to_s.length
51
+ table_width = cp_pos + 2
52
+ puts " " + "-"*table_width
53
+ end
54
+
55
+ def answer guess, guess_num
56
+ # Display number of correct characters and number of correct positions
57
+ _G_ = guess_num.abs.to_s
58
+ _g_ = _G_.length
59
+ _N_ = @num_of_chars.to_s
60
+ _n_ = _N_.length
61
+ _B_ = checkCC(guess).to_s
62
+ _b_ = _B_.length
63
+ _U_ = checkCO(guess).to_s
64
+ _u_ = _U_.length
65
+ output = (guess_num == -1 ? ' XXX' : " "*(4-_g_) + _G_) + "| #{guess.yellow}" \
66
+ + " [" + ("0"*(_n_-_b_) + _B_).green + "] [" \
67
+ + ("0"*(_n_-_u_) + _U_).green + "]"
68
+ @moves << (output + "\n")
69
+ if _U_ == _N_ && @loaded == true
70
+ filename = ".filename"
71
+ work_dir = File.dirname(__FILE__)
72
+ file = work_dir + "/" + filename + ".4dig"
73
+ File.delete(file) if File.exists?(file)
74
+ end
75
+ return output
76
+ end
77
+
78
+ # Method to check how many digits are correctly guessed
79
+ def checkCC guess
80
+ cc = 0
81
+ guess.each_char do |x|
82
+ if @secret_chars.include? x.to_s
83
+ cc += 1
84
+ end
85
+ end
86
+ return cc
87
+ end
88
+
89
+ # Method to check how many correct digits are presented in correct positions
90
+ def checkCO guess
91
+ co = 0
92
+ for i in 0...@num_of_chars
93
+ if @secret_chars[i] == guess[i]
94
+ co += 1
95
+ end
96
+ end
97
+ return co
98
+ end
99
+
100
+ # Method to display hint
101
+ def hint
102
+ picked_number = 0
103
+ clue = ""
104
+ chance = rand 1..100
105
+ if chance < (@num_of_chars.to_f/@chars_set.length.to_f*100) \
106
+ && chance > (@num_of_chars.to_f/@chars_set.length.to_f*20) #display one correct number
107
+ picked_number = rand 0...(@num_of_chars-@used_true.length) || 0
108
+ true_characters = @secret_chars.tr(@used_true, '')
109
+ picked_true = true_characters[picked_number] || ""
110
+ @used_true += picked_true
111
+ if picked_true == ""
112
+ clue = "You've already known #{@num_of_chars == 1 ? 'the' : 'all'} true "\
113
+ + "character#{'s' unless @num_of_chars == 1}."
114
+ else
115
+ clue = "'#{picked_true}' is#{@num_of_chars == 1 ? '' : ' among'} the true "\
116
+ + "character#{'s' unless @num_of_chars == 1}."
117
+ end
118
+ else
119
+ picked_number = rand 0...(@chars_set.length - @num_of_chars - @used_false.length) || 0
120
+ false_characters = @chars_set.tr(@secret_chars, '').tr(@used_false, '') || ""
121
+ picked_false = false_characters[picked_number] || ""
122
+ @used_false += picked_false
123
+ if picked_false == ""
124
+ clue = "You've already known #{(@chars_set.length - @num_of_chars) == 1 ? 'the' : 'all'} "\
125
+ + "false character#{'s' unless (@chars_set.length - @num_of_chars) == 1}."
126
+ else
127
+ clue = "One can simply omit '#{picked_false}'."
128
+ end
129
+ end
130
+ return clue.yellow
131
+ end
132
+
133
+ def do_hint
134
+ if @hint_used != @max_hint
135
+ hint.flash 1.1
136
+ @hint_used += 1
137
+ else
138
+ ("Sorry, you've used #{@max_hint == 1 ? 'the' : 'up all'} #{@max_hint.to_s + " " unless @max_hint == 1}"\
139
+ + "hint#{'s' unless @max_hint == 1}.").red.flash 1.2
140
+ end
141
+ end
142
+
143
+ def save_game guess_num
144
+ end_game if guess_num > 0
145
+ # generate filename
146
+ time = Time.now
147
+ work_dir = File.dirname(__FILE__)
148
+ filename = ".filename" # "."+time.strftime("%y%m%d%H%M%S").to_i.to_s(36)
149
+ # save file
150
+ File.open(work_dir + "/" + filename + ".4dig", "w+") do |f|
151
+ f.write("[set of chars]\n")
152
+ f.write(@chars_set + "\n"*2)
153
+ f.write("[secret chars]\n")
154
+ f.write(@secret_chars + "\n"*2)
155
+ f.write("[hint used]\n")
156
+ f.write(@hint_used.to_s + "\n"*2)
157
+ f.write("[moves]\n")
158
+ f.write(@moves)
159
+ end
160
+ guess_num = -2
161
+ return guess_num
162
+ end
163
+
164
+ def do_save guess_num
165
+ if guess_num > 0
166
+ guess_num = save_game guess_num
167
+ else
168
+ "No game to save.".red.flash 1
169
+ end
170
+ return guess_num
171
+ end
172
+
173
+ def quit_game guess_num
174
+ print "\r"
175
+ "¯\\(°_o)/¯ I give up.".yellow.flash 1
176
+ guess_num = -1
177
+ puts answer @secret_chars, guess_num
178
+ end_game
179
+ return guess_num
180
+ end
181
+
182
+ def do_quit guess_num
183
+ if guess_num > 0
184
+ yes_commands = %w{yes yse ys ye y save saev seav sav sev s}
185
+ print "\r "
186
+ print "\r " + "Save game? (yes/no): ".yellow
187
+ save = gets.chomp
188
+ print "\r\e[1A" + " "*25
189
+ print "\r"
190
+ if yes_commands.include? save.downcase
191
+ guess_num = do_save guess_num
192
+ else
193
+ guess_num = quit_game guess_num
194
+ end
195
+ else
196
+ guess_num = quit_game guess_num
197
+ end
198
+ return guess_num
199
+ end
200
+
201
+ def load_game guess_object, secret_object
202
+ filename = ".filename"
203
+ work_dir = File.dirname(__FILE__)
204
+ if File.exists?(work_dir + "/" + filename + ".4dig")
205
+ @loaded = true
206
+ table_width = 15 + @num_of_chars + 2*@num_of_chars.to_s.length
207
+ print "\r\e[#{guess_object.guess_num+3}A"
208
+ print (" "*table_width + "\n")*(guess_object.guess_num+3)
209
+ print "\r\e[#{guess_object.guess_num+3}A"
210
+ saved_game = File.read(work_dir + "/" + filename + ".4dig")
211
+ saved_game_arr = saved_game.split("\n")
212
+ @chars_set = saved_game_arr[1]
213
+ @secret_chars = saved_game_arr[4]
214
+ secret_object.secret_chars = @secret_chars
215
+ @num_of_chars = @secret_chars.length
216
+ @hint_used = saved_game_arr[7].to_i
217
+ @max_hint = (@chars_set.length/@num_of_chars).to_i
218
+ @moves = saved_game_arr[10..-1]
219
+ guess_object.guess_num = @moves.length
220
+ chars_to_use
221
+ table_header
222
+ @moves = @moves.inject("") {|result, line| result + line + "\n"}
223
+ puts @moves
224
+ else
225
+ "No saved game found.".yellow.flash 1.5
226
+ end
227
+ return guess_object.guess_num
228
+ end
229
+ end
230
+
231
+ class SecretCharacters
232
+ attr_reader :num_of_chars, :chars_set, :max_hint
233
+ attr_accessor :secret_chars
234
+
235
+ # default chars = "0123456789" and default num = 4, see option parser.
236
+ def initialize chars_set, num_of_chars
237
+ @num_of_chars = num_of_chars
238
+ @chars_set = chars_set
239
+ @secret_chars = do_shuffle
240
+ end
241
+
242
+ # Shuffle a set of number from 0-9
243
+ def do_shuffle
244
+ prep_chars = @chars_set.chars.to_a.shuffle
245
+ secret_chars = prep_chars[0, @num_of_chars].join.to_s
246
+ return secret_chars
247
+ end
248
+ end
249
+
250
+ class Guess
251
+ # check if guess has redundant characters
252
+ attr_accessor :guess, :guess_num, :chars_set
253
+ def initialize chars_set
254
+ @guess = ""
255
+ @guess_num = 0
256
+ @chars_set = chars_set
257
+ end
258
+
259
+ def is_redundant?
260
+ redundant = false
261
+ a = @guess.split("").to_set.length
262
+ b = @guess.length
263
+ redundant = true if a < b
264
+ return redundant
265
+ end
266
+
267
+ def handle_redundancy
268
+ char_freq = {}
269
+ @guess.each_char do |char|
270
+ char_freq[char] ? char_freq[char] += 1 : char_freq[char] = 1
271
+ end
272
+ redundant_char = char_freq.select {|k, v| v > 1}
273
+ sorted_red_char = redundant_char.sort_by {|k, v| v}
274
+ sorted_red_char.reverse! unless sorted_red_char[1].nil? || sorted_red_char[0][1] == sorted_red_char[1][1]
275
+ redundant = sorted_red_char[0][0]
276
+ frequency = sorted_red_char[0][1]
277
+ if frequency == 2
278
+ freq_string = "twice"
279
+ else
280
+ freq_string = "#{frequency} times"
281
+ end
282
+ "Redundant: you mentioned \"#{redundant}\" #{freq_string}.".yellow.flash 1.1
283
+ end
284
+
285
+ # Check if wrong character is input
286
+ def wrong_input?
287
+ wrong_char = false
288
+ error_num = 0
289
+ @guess.each_char do |char|
290
+ error_num += 1 unless chars_set.include? char
291
+ end
292
+ wrong_char = true if error_num > 0
293
+ return wrong_char
294
+ end
295
+ end
296
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chadet
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Adrian Setyadi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-01 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Computer will generate a random set of characters. The default number
14
+ of characters is 4 and the default set of characters is decimal digits from 0 to
15
+ 9. After each guess you make, computer will tell you how many characters you guessed
16
+ correctly and how many characters that their position you guessed correctly.
17
+ email:
18
+ - a.styd@yahoo.com
19
+ executables:
20
+ - chadet
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - ".gitignore"
25
+ - Gemfile
26
+ - LICENSE.txt
27
+ - README.md
28
+ - Rakefile
29
+ - bin/chadet
30
+ - chadet.gemspec
31
+ - lib/chadet.rb
32
+ - lib/chadet/version.rb
33
+ homepage: https://bitbucket.org/astyd
34
+ licenses:
35
+ - MIT
36
+ metadata: {}
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project:
53
+ rubygems_version: 2.2.2
54
+ signing_key:
55
+ specification_version: 4
56
+ summary: Characters Detective. Game of guessing characters intelligently.
57
+ test_files: []