fortune_teller 0.0.5 → 0.0.6
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.
- 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
|