fortune_teller 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.txt +28 -4
- data/bin/fortune_teller +1 -1
- data/lib/fortune_teller.rb +1 -60
- data/lib/fortune_teller/chooser.rb +29 -20
- data/lib/fortune_teller/cli_ui.rb +51 -0
- data/lib/fortune_teller/game.rb +101 -0
- data/lib/fortune_teller/nil_panel.rb +6 -2
- data/lib/fortune_teller/panel.rb +6 -17
- data/lib/fortune_teller/reveal.rb +1 -2
- data/lib/fortune_teller/version.rb +1 -1
- metadata +6 -4
data/README.txt
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
What?
|
2
|
+
A total hack
|
3
|
+
A Ruby-based commandline version of an origami fortune-teller:
|
4
|
+
http://en.wikipedia.org/wiki/Paper_fortune_teller
|
5
|
+
|
6
|
+
Why?
|
7
|
+
Cuz my kids were making paper fortune-tellers and I thought I'd
|
8
|
+
inspire them with a little computer-science
|
9
|
+
(so far they just like that I can change my fortune-teller faster than
|
10
|
+
they can)
|
3
11
|
|
4
12
|
To use it simply...
|
5
13
|
install it:
|
@@ -27,6 +35,22 @@ At which point, you type your selection, followed by pressing the
|
|
27
35
|
enter-key
|
28
36
|
...it's that easy.
|
29
37
|
|
38
|
+
To integrate with your own code...
|
39
|
+
require 'fortune_teller'
|
40
|
+
|
41
|
+
And have fun (see FortuneTeller::Game.run):
|
42
|
+
|
43
|
+
# array of array of strings
|
44
|
+
selection_groups = FortuneTeller::Game::DEFAULT_SELECTION_GROUPS.map(&:call)
|
45
|
+
|
46
|
+
# array of strings
|
47
|
+
fortunes = FortuneTeller::Game::DEFAULT_FORTUNES
|
48
|
+
|
49
|
+
# options include the :ui to use, default is CliUi
|
50
|
+
|
51
|
+
game = FortuneTeller::Game.new( selection_groups, fortunes, options )
|
52
|
+
|
53
|
+
game.run
|
54
|
+
|
30
55
|
TODO:
|
31
|
-
|
32
|
-
graphics
|
56
|
+
confirm (i.e. create proof-of-concept) that modularized & injected dependencies (i.e. :ui) work w/ Commandline, Ruby, Rubygame, etc...
|
data/bin/fortune_teller
CHANGED
data/lib/fortune_teller.rb
CHANGED
@@ -1,62 +1,3 @@
|
|
1
|
-
require_relative "fortune_teller/
|
1
|
+
require_relative "fortune_teller/game"
|
2
2
|
module FortuneTeller
|
3
|
-
class Game
|
4
|
-
def jail_reveal
|
5
|
-
Reveal.new( "Oops, you're in Jail!" )
|
6
|
-
end
|
7
|
-
|
8
|
-
def mud_reveal
|
9
|
-
Reveal.new( "Oops, you're in the mud!" )
|
10
|
-
end
|
11
|
-
|
12
|
-
def cookie_reveal
|
13
|
-
Reveal.new( "Wow, you get a cookie!" )
|
14
|
-
end
|
15
|
-
|
16
|
-
def final_choices
|
17
|
-
@final_choices ||= [
|
18
|
-
Panel.new( "blue", choice([jail_reveal, mud_reveal, cookie_reveal]) ),
|
19
|
-
Panel.new( "green", choice([jail_reveal, mud_reveal, cookie_reveal]) ),
|
20
|
-
Panel.new( "pink", choice([jail_reveal, mud_reveal, cookie_reveal]) ),
|
21
|
-
]
|
22
|
-
end
|
23
|
-
|
24
|
-
def final_choice_1
|
25
|
-
@final_choice_1 ||= choice(final_choices)
|
26
|
-
end
|
27
|
-
|
28
|
-
def final_choice_2
|
29
|
-
@final_choice_2 ||= choice(final_choices - [ final_choice_1 ])
|
30
|
-
end
|
31
|
-
|
32
|
-
def choice(choices)
|
33
|
-
choices[rand(choices.size)]
|
34
|
-
end
|
35
|
-
|
36
|
-
def level_three_chooser
|
37
|
-
Chooser.new( final_choice_1, final_choice_2 )
|
38
|
-
end
|
39
|
-
|
40
|
-
def level_two_chooser
|
41
|
-
Chooser.new(
|
42
|
-
Panel.new( "9", level_three_chooser ),
|
43
|
-
Panel.new( "7", level_three_chooser ),
|
44
|
-
Panel.new( "3", level_three_chooser ),
|
45
|
-
Panel.new( "5", level_three_chooser ),
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
def level_one_chooser
|
50
|
-
Chooser.new(
|
51
|
-
Panel.new( "bird", level_two_chooser ),
|
52
|
-
Panel.new( "dog", level_two_chooser ),
|
53
|
-
Panel.new( "chicken", level_two_chooser ),
|
54
|
-
Panel.new( "mouse", level_two_chooser )
|
55
|
-
)
|
56
|
-
end
|
57
|
-
|
58
|
-
def run
|
59
|
-
level_one_chooser.choose
|
60
|
-
end
|
61
|
-
end
|
62
3
|
end
|
@@ -3,16 +3,34 @@ require_relative "logger"
|
|
3
3
|
module FortuneTeller
|
4
4
|
class Chooser
|
5
5
|
LOCATIONS = [ :tl, :tr, :bl, :br ]
|
6
|
+
|
7
|
+
def self.subset(list, num=list.size)
|
8
|
+
Logger.log("got list: #{list.inspect}, num: #{num.inspect}")
|
9
|
+
choices = list.dup
|
10
|
+
num.times.collect {|num|
|
11
|
+
reduce_choices!(choices)
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.reduce_choices!( choices, by=random_choice(choices) )
|
16
|
+
choices.delete(by)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.random_choice(choices)
|
20
|
+
choices[rand(choices.size)]
|
21
|
+
end
|
22
|
+
|
6
23
|
attr_reader :tl_panel, :tr_panel, :bl_panel, :br_panel
|
7
|
-
attr_reader :list_renderer
|
8
|
-
def initialize(_tl_panel, _tr_panel,
|
24
|
+
attr_reader :list_renderer, :ui
|
25
|
+
def initialize(_tl_panel, _tr_panel, options = {})
|
26
|
+
@ui = options[:ui]
|
9
27
|
@tl_panel = _tl_panel
|
10
28
|
Logger.log "tl_panel: #{@tl_panel}"
|
11
29
|
@tr_panel = _tr_panel
|
12
30
|
Logger.log "tr_panel: #{@tr_panel}"
|
13
|
-
@bl_panel =
|
31
|
+
@bl_panel = options[:bl_panel] || NilPanel.new(@ui)
|
14
32
|
Logger.log "bl_panel: #{@bl_panel}"
|
15
|
-
@br_panel =
|
33
|
+
@br_panel = options[:br_panel] || NilPanel.new(@ui)
|
16
34
|
Logger.log "br_panel: #{@br_panel}"
|
17
35
|
@list_renderer = options[:list_renderer] || ListRenderer.new
|
18
36
|
define_selection_aliases
|
@@ -52,32 +70,23 @@ module FortuneTeller
|
|
52
70
|
def choose
|
53
71
|
choice = nil
|
54
72
|
begin
|
55
|
-
|
56
|
-
choice =
|
73
|
+
ui.clear_screen
|
74
|
+
choice = ui.prompt( list_renderer.render( selections | [:exit] ) )
|
57
75
|
Logger.log("got: #{choice.inspect}")
|
58
76
|
end until( valid?( choice ) )
|
59
77
|
Logger.log("trying it...")
|
60
|
-
|
78
|
+
ui.clear_screen(1)
|
79
|
+
# need to unalias methods...
|
61
80
|
send( choice )
|
62
81
|
end
|
63
82
|
|
64
|
-
def self.clear_screen( after = 0 )
|
65
|
-
sleep( after )
|
66
|
-
puts "\e[H\e[2J"
|
67
|
-
end
|
68
|
-
|
69
83
|
LOCATIONS.each do |location|
|
70
84
|
define_method(location) {
|
71
|
-
send( "#{location}_panel" ).
|
85
|
+
send( "#{location}_panel" ).tap do |panel|
|
86
|
+
panel.pick
|
87
|
+
end
|
72
88
|
}
|
73
89
|
end
|
74
|
-
|
75
|
-
def self.prompt(text)
|
76
|
-
print text
|
77
|
-
gets.chomp.tap do |result|
|
78
|
-
puts
|
79
|
-
end
|
80
|
-
end
|
81
90
|
end
|
82
91
|
end
|
83
92
|
require_relative "panel"
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module FortuneTeller
|
2
|
+
class CliUi
|
3
|
+
DEFAULT_SOUND_FILE = 'flick_flick.ogg'.freeze
|
4
|
+
attr_reader :game, :sound_file
|
5
|
+
def initialize( options = {} )
|
6
|
+
@game = options[ :game ]
|
7
|
+
@sound_file = options[ :sound_file ] || DEFAULT_SOUND_FILE
|
8
|
+
end
|
9
|
+
|
10
|
+
def prompt(text)
|
11
|
+
print text
|
12
|
+
gets.chomp.tap do |result|
|
13
|
+
display
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def exit( message = nil )
|
18
|
+
display( message )
|
19
|
+
Kernel.exit
|
20
|
+
end
|
21
|
+
|
22
|
+
def display( text = nil )
|
23
|
+
puts text
|
24
|
+
end
|
25
|
+
|
26
|
+
def interstitial( text )
|
27
|
+
display text
|
28
|
+
play
|
29
|
+
sleep(1.2)
|
30
|
+
end
|
31
|
+
|
32
|
+
def clear_screen( after = 0 )
|
33
|
+
sleep( after )
|
34
|
+
display "\e[H\e[2J"
|
35
|
+
end
|
36
|
+
|
37
|
+
def play
|
38
|
+
sound.play
|
39
|
+
end
|
40
|
+
|
41
|
+
def sound
|
42
|
+
@sound ||= begin
|
43
|
+
require "rubygame"
|
44
|
+
if defined?(Rubygame::Sound)
|
45
|
+
Rubygame::Sound.load(sound_file)
|
46
|
+
end
|
47
|
+
rescue
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require_relative "chooser"
|
2
|
+
require_relative "cli_ui"
|
3
|
+
module FortuneTeller
|
4
|
+
class Game
|
5
|
+
DEFAULT_SELECTION_GROUPS = [
|
6
|
+
lambda { Chooser.subset([ "dog", "chicken", "mouse", "cat", "dragon", "turtle", "tiger", "snake", "monkey" ], 4) },
|
7
|
+
lambda { Chooser.subset([ "3", "9", "5", "7", "10", "27", "100" ], 4) },
|
8
|
+
lambda { Chooser.subset([ "pink", "green", "blue", "yellow" ], 2) },
|
9
|
+
].freeze
|
10
|
+
|
11
|
+
DEFAULT_FORTUNES = [
|
12
|
+
"Oops, you're in Jail!",
|
13
|
+
"Yuck, you're in the mud!",
|
14
|
+
"Wow, you get a cookie!",
|
15
|
+
"Ouch, you got bit!",
|
16
|
+
"Hey, you get a hug!",
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
def self.run( options = {} )
|
20
|
+
options[:selection_groups] ||= DEFAULT_SELECTION_GROUPS.map(&:call)
|
21
|
+
options[:fortunes] ||= DEFAULT_FORTUNES
|
22
|
+
new( options.delete(:selection_groups), options.delete(:fortunes), options ).run
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :selection_groups, :fortunes
|
26
|
+
attr_reader :chooser_class, :reveal_class, :panel_class
|
27
|
+
attr_reader :chooser_options
|
28
|
+
attr_reader :ui
|
29
|
+
def initialize( selection_groups, fortunes, options = {} )
|
30
|
+
@original_selection_groups = selection_groups
|
31
|
+
@original_fortunes = fortunes
|
32
|
+
|
33
|
+
@ui = options[:ui] || CliUi.new(:game => self)
|
34
|
+
|
35
|
+
@chooser_class = options[:choose_class] || Chooser
|
36
|
+
@reveal_class = options[:reveal_class] || Reveal
|
37
|
+
@panel_class = options[:panel_class] || Panel
|
38
|
+
@chooser_options = options[:chooser_options] || {}
|
39
|
+
@chooser_options[:ui] ||= ui
|
40
|
+
|
41
|
+
reset
|
42
|
+
end
|
43
|
+
|
44
|
+
def restart
|
45
|
+
reset
|
46
|
+
run
|
47
|
+
end
|
48
|
+
|
49
|
+
def reset
|
50
|
+
@fortunes = @original_fortunes.dup
|
51
|
+
@selection_groups = @original_selection_groups.dup
|
52
|
+
end
|
53
|
+
|
54
|
+
def run
|
55
|
+
chooser_tree.choose
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def fortune_reveals
|
62
|
+
@fortune_reveals ||= fortunes.map { |fortune|
|
63
|
+
reveal_class.new( fortune, :ui => ui )
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
def final_choices
|
68
|
+
@final_choices ||= selection_groups.pop.map { |selection|
|
69
|
+
Logger.log("fc-selection: #{selection.inspect}")
|
70
|
+
panel_class.new( selection, :reveal => chooser_class.reduce_choices!(fortune_reveals), :ui => ui )
|
71
|
+
}
|
72
|
+
end
|
73
|
+
|
74
|
+
def final_chooser
|
75
|
+
@final_chooser ||= chooser_class.new( chooser_class.reduce_choices!(final_choices), chooser_class.reduce_choices!(final_choices), chooser_options )
|
76
|
+
end
|
77
|
+
|
78
|
+
def chooser_tree
|
79
|
+
@chooser_tree ||= generate_choosers
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
def generate_choosers
|
84
|
+
choosers = [ final_chooser ]
|
85
|
+
begin
|
86
|
+
panels = []
|
87
|
+
if selection_group = selection_groups.pop
|
88
|
+
selection_group.each do |selection|
|
89
|
+
panels << panel_class.new( selection, :reveal => choosers.first, :ui => ui )
|
90
|
+
end
|
91
|
+
end
|
92
|
+
chooser_params = panels.pop, panels.pop
|
93
|
+
chooser_options[:bl_panel] = panels.pop if panels.first
|
94
|
+
chooser_options[:br_panel] = panels.pop if panels.first
|
95
|
+
chooser_params << chooser_options
|
96
|
+
choosers.unshift chooser_class.new( *chooser_params )
|
97
|
+
end until [] == selection_groups
|
98
|
+
return choosers.first
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module FortuneTeller
|
2
2
|
class NilPanel
|
3
|
+
attr_reader :ui
|
4
|
+
def initialize(ui)
|
5
|
+
@ui = ui
|
6
|
+
end
|
3
7
|
def to_s
|
4
8
|
""
|
5
9
|
end
|
@@ -9,11 +13,11 @@ module FortuneTeller
|
|
9
13
|
end
|
10
14
|
|
11
15
|
def pick
|
12
|
-
|
16
|
+
ui.exit
|
13
17
|
end
|
14
18
|
|
15
19
|
def choose
|
16
|
-
|
20
|
+
ui.exit
|
17
21
|
end
|
18
22
|
end
|
19
23
|
end
|
data/lib/fortune_teller/panel.rb
CHANGED
@@ -3,9 +3,11 @@ module FortuneTeller
|
|
3
3
|
class Panel
|
4
4
|
attr_reader :label
|
5
5
|
attr_accessor :reveal
|
6
|
-
|
7
|
-
|
8
|
-
@
|
6
|
+
attr_accessor :ui
|
7
|
+
def initialize(label, options = {} )
|
8
|
+
@label = label
|
9
|
+
@ui = options[:ui]
|
10
|
+
@reveal = options[:reveal] || NilPanel.new(@ui)
|
9
11
|
end
|
10
12
|
alias_method :to_s, :label
|
11
13
|
|
@@ -14,23 +16,10 @@ module FortuneTeller
|
|
14
16
|
end
|
15
17
|
|
16
18
|
def pick
|
17
|
-
|
18
|
-
sound.play
|
19
|
-
sleep(1.2)
|
19
|
+
ui.interstitial( "Flick, flick, flick, flick..." )
|
20
20
|
reveal.choose
|
21
21
|
end
|
22
22
|
|
23
|
-
private
|
24
|
-
|
25
|
-
def sound
|
26
|
-
@sound ||= begin
|
27
|
-
require "rubygame"
|
28
|
-
if defined?(Rubygame::Sound)
|
29
|
-
Rubygame::Sound.load('flick_flick.ogg')
|
30
|
-
end
|
31
|
-
rescue
|
32
|
-
end
|
33
|
-
end
|
34
23
|
end
|
35
24
|
end
|
36
25
|
require_relative "reveal"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fortune_teller
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-08-
|
12
|
+
date: 2012-08-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubygame
|
@@ -61,6 +61,8 @@ files:
|
|
61
61
|
- fortune_teller.gemspec
|
62
62
|
- lib/fortune_teller.rb
|
63
63
|
- lib/fortune_teller/chooser.rb
|
64
|
+
- lib/fortune_teller/cli_ui.rb
|
65
|
+
- lib/fortune_teller/game.rb
|
64
66
|
- lib/fortune_teller/list_renderer.rb
|
65
67
|
- lib/fortune_teller/logger.rb
|
66
68
|
- lib/fortune_teller/nil_panel.rb
|
@@ -82,7 +84,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
82
84
|
version: '0'
|
83
85
|
segments:
|
84
86
|
- 0
|
85
|
-
hash:
|
87
|
+
hash: 3561951047884625826
|
86
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
89
|
none: false
|
88
90
|
requirements:
|
@@ -91,7 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
93
|
version: '0'
|
92
94
|
segments:
|
93
95
|
- 0
|
94
|
-
hash:
|
96
|
+
hash: 3561951047884625826
|
95
97
|
requirements: []
|
96
98
|
rubyforge_project: fortune_teller
|
97
99
|
rubygems_version: 1.8.24
|