dopairb 0.1.0 → 0.4.0
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 +4 -4
- data/README.md +63 -10
- data/lib/dopairb/canvas.rb +39 -16
- data/lib/dopairb/cli.rb +5 -7
- data/lib/dopairb/config.rb +11 -5
- data/lib/dopairb/demo.rb +22 -4
- data/lib/dopairb/director.rb +75 -12
- data/lib/dopairb/fx.rb +23 -0
- data/lib/dopairb/gallery/impressionism.rb +818 -0
- data/lib/dopairb/gallery/japan.rb +693 -0
- data/lib/dopairb/gallery/modern_ancient.rb +774 -0
- data/lib/dopairb/gallery/renaissance.rb +829 -0
- data/lib/dopairb/gallery/romantic.rb +703 -0
- data/lib/dopairb/gallery.rb +349 -0
- data/lib/dopairb/game.rb +90 -9
- data/lib/dopairb/input_fx.rb +78 -10
- data/lib/dopairb/irb_adapter.rb +8 -0
- data/lib/dopairb/output_tap.rb +10 -0
- data/lib/dopairb/profile.rb +106 -0
- data/lib/dopairb/reline_adapter.rb +1 -0
- data/lib/dopairb/scene.rb +12 -0
- data/lib/dopairb/scenes/bonus.rb +279 -0
- data/lib/dopairb/scenes/failure.rb +7 -0
- data/lib/dopairb/scenes/finale.rb +326 -0
- data/lib/dopairb/scenes/session.rb +115 -3
- data/lib/dopairb/scenes/success.rb +22 -4
- data/lib/dopairb/session.rb +57 -6
- data/lib/dopairb/sound.rb +420 -0
- data/lib/dopairb/term.rb +3 -1
- data/lib/dopairb/tour.rb +89 -0
- data/lib/dopairb/version.rb +1 -1
- data/lib/dopairb.rb +73 -3
- data/spec.md +3 -3
- metadata +12 -1
data/lib/dopairb.rb
CHANGED
|
@@ -19,18 +19,24 @@ require_relative "dopairb/fx"
|
|
|
19
19
|
require_relative "dopairb/stage"
|
|
20
20
|
require_relative "dopairb/game"
|
|
21
21
|
require_relative "dopairb/probe"
|
|
22
|
+
require_relative "dopairb/profile"
|
|
23
|
+
require_relative "dopairb/gallery"
|
|
22
24
|
require_relative "dopairb/scene"
|
|
23
25
|
require_relative "dopairb/scenes/success"
|
|
24
26
|
require_relative "dopairb/scenes/failure"
|
|
25
27
|
require_relative "dopairb/scenes/session"
|
|
28
|
+
require_relative "dopairb/scenes/finale"
|
|
29
|
+
require_relative "dopairb/scenes/bonus"
|
|
26
30
|
require_relative "dopairb/director"
|
|
27
31
|
require_relative "dopairb/output_tap"
|
|
28
32
|
require_relative "dopairb/charge_line"
|
|
33
|
+
require_relative "dopairb/sound"
|
|
29
34
|
require_relative "dopairb/input_fx"
|
|
30
35
|
require_relative "dopairb/reline_adapter"
|
|
31
36
|
require_relative "dopairb/irb_adapter"
|
|
32
37
|
require_relative "dopairb/session"
|
|
33
38
|
require_relative "dopairb/demo"
|
|
39
|
+
require_relative "dopairb/tour"
|
|
34
40
|
|
|
35
41
|
# dopairb: IRB where every keystroke, result and exception gets a show.
|
|
36
42
|
#
|
|
@@ -42,7 +48,10 @@ module Dopairb
|
|
|
42
48
|
def config
|
|
43
49
|
@config ||= begin
|
|
44
50
|
c = Config.new
|
|
45
|
-
|
|
51
|
+
if ENV["DOPAIRB"]
|
|
52
|
+
c.apply_string(ENV["DOPAIRB"])
|
|
53
|
+
overrides << [:string, ENV["DOPAIRB"]]
|
|
54
|
+
end
|
|
46
55
|
c
|
|
47
56
|
rescue ArgumentError => e
|
|
48
57
|
warn "dopairb: ignoring DOPAIRB=#{ENV['DOPAIRB'].inspect}: #{e.message}"
|
|
@@ -50,14 +59,29 @@ module Dopairb
|
|
|
50
59
|
end
|
|
51
60
|
end
|
|
52
61
|
|
|
62
|
+
# Settings for this run only ($DOPAIRB, dopairb options). They win over
|
|
63
|
+
# Dopairb.enable(...) in .irbrc, which IRB loads after they are applied.
|
|
64
|
+
def overrides = (@overrides ||= [])
|
|
65
|
+
|
|
66
|
+
def override(name, value)
|
|
67
|
+
name == :string ? config.apply_string(value) : config.set(name, value)
|
|
68
|
+
overrides << [name, value]
|
|
69
|
+
end
|
|
70
|
+
|
|
53
71
|
# Hook into IRB. Safe to call more than once; options are config settings.
|
|
54
72
|
def enable(intro: nil, **settings)
|
|
55
73
|
settings.each { |k, v| config.set(k, v) }
|
|
56
74
|
config.set(:intro, intro) unless intro.nil?
|
|
75
|
+
overrides.each { |k, v| k == :string ? config.apply_string(v) : config.set(k, v) }
|
|
57
76
|
@session ||= Session.new(config)
|
|
58
77
|
if IrbAdapter.install
|
|
59
78
|
RelineAdapter.install(@session.fx)
|
|
60
79
|
OutputTap.install
|
|
80
|
+
if active?
|
|
81
|
+
# decided before warming up: the first run shows the loading screen
|
|
82
|
+
@session.cold_start = Sound.available? && !Sound.ready?(:intro, config.duration)
|
|
83
|
+
Sound.warm_up(config.duration)
|
|
84
|
+
end
|
|
61
85
|
else
|
|
62
86
|
warn "dopairb: IRB #{defined?(IRB::VERSION) ? IRB::VERSION : '?'} is not supported; running plain IRB"
|
|
63
87
|
end
|
|
@@ -81,33 +105,78 @@ module Dopairb
|
|
|
81
105
|
"normal" => { intensity: :normal },
|
|
82
106
|
"max" => { intensity: :max },
|
|
83
107
|
"calm" => { intensity: :low, flash: :off, duration: 0.7 },
|
|
84
|
-
"party" => { intensity: :max, flash: :full, sound:
|
|
108
|
+
"party" => { intensity: :max, flash: :full, sound: :sfx, duration: 1.0 },
|
|
85
109
|
}.freeze
|
|
86
110
|
|
|
87
111
|
HELP = <<~TXT
|
|
88
112
|
dopa show settings and session stats
|
|
89
113
|
dopa off|low|normal|max
|
|
90
114
|
dopa calm low intensity, no flash, shorter
|
|
91
|
-
dopa party max intensity, full-screen flash,
|
|
115
|
+
dopa party max intensity, full-screen flash, sound effects
|
|
92
116
|
dopa demo play every effect once
|
|
117
|
+
dopa loading show the loading screen
|
|
118
|
+
dopa gallery the bonus art you have collected (dopa gallery NAME shows one)
|
|
119
|
+
dopa gallery tour a slideshow of all 100 (uncollected ones as silhouettes)
|
|
93
120
|
dopa KEY=VALUE ... change one setting, e.g. `dopa flash=off duration=0.5`
|
|
94
121
|
|
|
95
122
|
settings:
|
|
96
123
|
TXT
|
|
97
124
|
|
|
125
|
+
def gallery(name)
|
|
126
|
+
owned = ((@session&.profile&.gallery || []) + (@session&.collected || [])).uniq
|
|
127
|
+
if name == "tour"
|
|
128
|
+
return puts("dopairb: the tour needs a terminal") unless Term.interactive?
|
|
129
|
+
return Tour.run(config, owned)
|
|
130
|
+
end
|
|
131
|
+
if name.nil?
|
|
132
|
+
puts "dopairb gallery: #{owned.size}/#{Gallery::PIECES.size} (level-ups, jackpots and lucky ART DROPs bring more)"
|
|
133
|
+
Gallery::PIECES.each do |p|
|
|
134
|
+
puts format(" %-32s %s -- %s, %s", p.id, p.title, p.artist, p.year) if owned.include?(p.id)
|
|
135
|
+
end
|
|
136
|
+
rest = Gallery::PIECES.size - owned.size
|
|
137
|
+
puts " ... #{rest} more to discover" if rest > 0
|
|
138
|
+
puts " `dopa gallery NAME` shows one; `dopa gallery tour` walks through all #{Gallery::PIECES.size}"
|
|
139
|
+
return
|
|
140
|
+
end
|
|
141
|
+
piece = Gallery.find(name.to_sym) if Gallery.ids.include?(name.to_sym)
|
|
142
|
+
return puts("dopairb: no such piece #{name.inspect}") unless piece
|
|
143
|
+
return puts("dopairb: not unlocked yet -- keep playing!") unless owned.include?(piece.id)
|
|
144
|
+
cols = [Term.cols - 1, 100].min
|
|
145
|
+
w, h = Gallery.fit(piece, cols, [Term.rows - 4, 30].min)
|
|
146
|
+
c = Canvas.new(w, h / 2)
|
|
147
|
+
Gallery.draw(c, piece, 0, 0, w, h, depth: Term.depth(config))
|
|
148
|
+
puts c.render(Term.depth(config))
|
|
149
|
+
puts "\"#{piece.title}\" #{piece.artist}, #{piece.year}"
|
|
150
|
+
end
|
|
151
|
+
|
|
98
152
|
def command(arg)
|
|
99
153
|
words = arg.split
|
|
100
154
|
if words.empty? || words == ["status"]
|
|
101
155
|
s = @session&.game
|
|
102
156
|
puts "dopairb #{VERSION} (#{active? ? 'active' : 'inactive: not a terminal or intensity=off'})"
|
|
103
157
|
puts config.describe
|
|
158
|
+
puts " sound player: #{Sound.backend ? Sound.backend[1].first : '(none; bell only)'} cache: #{Sound.dir}"
|
|
104
159
|
puts " session: #{s.evals} evals, #{s.successes} hits, #{s.failures} errors, max combo #{s.max_combo}, score #{Fx.number_with_commas(s.score)}" if s
|
|
160
|
+
prof = @session&.profile
|
|
161
|
+
if prof&.persistent?
|
|
162
|
+
lv = s.leveling? ? s.level : prof.level
|
|
163
|
+
xp = s.leveling? ? s.xp : prof.xp
|
|
164
|
+
puts " career: LV #{lv} (#{Fx.number_with_commas(xp)} / #{Fx.number_with_commas(Game.xp_for(lv + 1))} XP), " \
|
|
165
|
+
"best score #{Fx.number_with_commas(prof.best_score)}, best combo #{prof.best_combo}, day streak #{prof.streak}, " \
|
|
166
|
+
"gallery #{prof.gallery.size}/#{Gallery::PIECES.size} (#{prof.path})"
|
|
167
|
+
end
|
|
105
168
|
elsif words == ["help"]
|
|
106
169
|
puts HELP + config.describe
|
|
107
170
|
elsif words == ["demo"]
|
|
108
171
|
Demo.run(self)
|
|
172
|
+
elsif words[0] == "gallery"
|
|
173
|
+
gallery(words[1])
|
|
174
|
+
elsif words == ["loading"]
|
|
175
|
+
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
176
|
+
@session&.director&.loading { Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0 > 2.5 } if active?
|
|
109
177
|
elsif words.size == 1 && PRESETS.key?(words[0])
|
|
110
178
|
PRESETS[words[0]].each { |k, v| config.set(k, v) }
|
|
179
|
+
Sound.warm_up(config.duration) if active?
|
|
111
180
|
puts "dopairb: #{words[0]}"
|
|
112
181
|
else
|
|
113
182
|
words.each do |w|
|
|
@@ -115,6 +184,7 @@ module Dopairb
|
|
|
115
184
|
raise ArgumentError, "expected KEY=VALUE, got #{w.inspect}" unless v
|
|
116
185
|
config.set(k, v)
|
|
117
186
|
end
|
|
187
|
+
Sound.warm_up(config.duration) if active?
|
|
118
188
|
puts "dopairb: " + words.join(" ")
|
|
119
189
|
end
|
|
120
190
|
nil
|
data/spec.md
CHANGED
|
@@ -127,10 +127,10 @@
|
|
|
127
127
|
|
|
128
128
|
| 設定 | 内容 |
|
|
129
129
|
| --- | --- |
|
|
130
|
-
| `intensity` | `off` / `low` / `normal` / `max`。初期値 `normal` |
|
|
130
|
+
| `intensity` | `off` / `low` / `normal` / `max`。初期値 `max`(v0.4.0 で `normal` から変更) |
|
|
131
131
|
| `motion` | アニメーションの有無と長さ |
|
|
132
132
|
| `flash` | 全画面フラッシュの有無。初期値は控えめ |
|
|
133
|
-
| `sound` |
|
|
133
|
+
| `sound` | `off` / `bell` / `sfx`。初期値 `sfx`(v0.4.0 で `off` から変更。プレイヤーがなければベル) |
|
|
134
134
|
| `hud` | COMBO・CHARGE・SCORE の表示 |
|
|
135
135
|
| `duration` | 各演出時間の倍率 |
|
|
136
136
|
| `color` | 色数と配色。モノクロでも意味が分かる表示 |
|
|
@@ -196,7 +196,7 @@ stateDiagram-v2
|
|
|
196
196
|
|
|
197
197
|
- 常時 HUD を画面上部に固定するか、プロンプト周辺の一時表示にするか。
|
|
198
198
|
- `puts` などの評価途中の出力をどの範囲まで捕捉・装飾するか。
|
|
199
|
-
-
|
|
199
|
+
- ~~スコアをセッション内だけにするか、記録を保存するか。~~ → 生涯 XP・レベル・ベスト記録・連続日数・ボーナス絵を `~/.local/state/dopairb/profile.json` に保存する(`DOPAIRB_PROFILE=off` で無効)。
|
|
200
200
|
- 演出素材を Unicode 文字中心にするか、端末によって別の表現を選ぶか。
|
|
201
201
|
- gem の起動コマンドと、通常の `irb` や `.irbrc` から有効化する方法。
|
|
202
202
|
- IRB/Reline の対象バージョンと、毎キー描画に必要な拡張点。
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dopairb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Koichi Sasada
|
|
@@ -72,19 +72,30 @@ files:
|
|
|
72
72
|
- lib/dopairb/director.rb
|
|
73
73
|
- lib/dopairb/font.rb
|
|
74
74
|
- lib/dopairb/fx.rb
|
|
75
|
+
- lib/dopairb/gallery.rb
|
|
76
|
+
- lib/dopairb/gallery/impressionism.rb
|
|
77
|
+
- lib/dopairb/gallery/japan.rb
|
|
78
|
+
- lib/dopairb/gallery/modern_ancient.rb
|
|
79
|
+
- lib/dopairb/gallery/renaissance.rb
|
|
80
|
+
- lib/dopairb/gallery/romantic.rb
|
|
75
81
|
- lib/dopairb/game.rb
|
|
76
82
|
- lib/dopairb/input_fx.rb
|
|
77
83
|
- lib/dopairb/irb_adapter.rb
|
|
78
84
|
- lib/dopairb/output_tap.rb
|
|
79
85
|
- lib/dopairb/probe.rb
|
|
86
|
+
- lib/dopairb/profile.rb
|
|
80
87
|
- lib/dopairb/reline_adapter.rb
|
|
81
88
|
- lib/dopairb/scene.rb
|
|
89
|
+
- lib/dopairb/scenes/bonus.rb
|
|
82
90
|
- lib/dopairb/scenes/failure.rb
|
|
91
|
+
- lib/dopairb/scenes/finale.rb
|
|
83
92
|
- lib/dopairb/scenes/session.rb
|
|
84
93
|
- lib/dopairb/scenes/success.rb
|
|
85
94
|
- lib/dopairb/session.rb
|
|
95
|
+
- lib/dopairb/sound.rb
|
|
86
96
|
- lib/dopairb/stage.rb
|
|
87
97
|
- lib/dopairb/term.rb
|
|
98
|
+
- lib/dopairb/tour.rb
|
|
88
99
|
- lib/dopairb/version.rb
|
|
89
100
|
- spec.md
|
|
90
101
|
homepage: https://github.com/ko1/dopairb
|