chadet 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/bin/chadet +272 -0
- data/chadet.gemspec +21 -0
- data/lib/chadet/version.rb +3 -0
- data/lib/chadet.rb +296 -0
- metadata +57 -0
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
data/Gemfile
ADDED
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
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
|
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: []
|