ifrb 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +74 -0
- data/Rakefile +7 -0
- data/bin/ifrb +29 -0
- data/examples/basil.rb +305 -0
- data/lib/ifrb.rb +66 -0
- data/lib/ifrb/version.rb +9 -0
- metadata +52 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f165e1c66438091ed255557f44eed72ca9eaf219
|
4
|
+
data.tar.gz: 6f433a81afa77053b2b054b85bc166f42e8496b8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8d727149c338ec392fb376fba3fdef7ad32202df0506b30852e15e654b27e90cb73146423a0c314ecf0a22e59e2c7feb05d04850e46ed29b82a0a5a4550aba49
|
7
|
+
data.tar.gz: 9941d5b139b9c3e09a4927518de2251b6bbf41459d310cbda65293d8b86797894703beb8bd59ce096995085158256eb46e6e1a70b73778d78a79b726fc292323
|
data/README.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# ifrb
|
2
|
+
|
3
|
+
Interactive fiction (IF), for interactive Ruby (IRB). Play interactive fiction games from within the cozy familiarity of irb! Write stories that incorporate actual, executable Ruby code in the dialog!
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
RubyGems is your friend:
|
8
|
+
|
9
|
+
$ gem install ifrb
|
10
|
+
|
11
|
+
## Usage
|
12
|
+
|
13
|
+
Try it with one of the examples:
|
14
|
+
|
15
|
+
$ ifrb basil
|
16
|
+
|
17
|
+
Or, if you want to do it from within IRB directly:
|
18
|
+
|
19
|
+
$ irb
|
20
|
+
irb> require 'ifrb'
|
21
|
+
irb> ifrb "basil"
|
22
|
+
|
23
|
+
## Writing Your Own Adventures
|
24
|
+
|
25
|
+
Just create a new ruby file. You need at least one method, called `start`, which will be called when your adventure loads.
|
26
|
+
|
27
|
+
def start
|
28
|
+
# ...
|
29
|
+
end
|
30
|
+
|
31
|
+
Define methods inside that method to add actions that are available for players. At the very least, you should add a method called `look`, which will be called when the room loads. The `look` method should describe the room:
|
32
|
+
|
33
|
+
def start
|
34
|
+
def look
|
35
|
+
_format <<-DESC
|
36
|
+
You see a big room. Not much else in here.
|
37
|
+
DESC
|
38
|
+
end
|
39
|
+
|
40
|
+
# ...
|
41
|
+
end
|
42
|
+
|
43
|
+
Other rooms are defined as top-level methods:
|
44
|
+
|
45
|
+
def start
|
46
|
+
#...
|
47
|
+
end
|
48
|
+
|
49
|
+
def monster
|
50
|
+
def look
|
51
|
+
_format "Yuck! A monster!"
|
52
|
+
end
|
53
|
+
# ...
|
54
|
+
end
|
55
|
+
|
56
|
+
Transition to rooms using the `_load_room` method:
|
57
|
+
|
58
|
+
def start
|
59
|
+
def north
|
60
|
+
_load_room :monster
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def monster
|
65
|
+
# ...
|
66
|
+
end
|
67
|
+
|
68
|
+
See the examples for more information about writing your own adventures. Good luck!
|
69
|
+
|
70
|
+
## License
|
71
|
+
|
72
|
+
Creative Commons Attribution 4.0 International License -- (c) Jamis Buck <jamis@jamisbuck.org>
|
73
|
+
|
74
|
+
<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" property="dct:title">IFRB</span> by <a xmlns:cc="http://creativecommons.org/ns#" href="http://github.com/jamis/ifrb" property="cc:attributionName" rel="cc:attributionURL">Jamis Buck</a> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="http://github.com/jamis/ifrb" rel="dct:source">http://github.com/jamis/ifrb</a>.
|
data/Rakefile
ADDED
data/bin/ifrb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/bin/sh ruby
|
2
|
+
|
3
|
+
require "irb"
|
4
|
+
|
5
|
+
game = ARGV.pop or abort "please specify the game you'd like to play"
|
6
|
+
game = game.gsub(/\.rb$/, "")
|
7
|
+
|
8
|
+
if !File.exists?("#{game}.rb")
|
9
|
+
ex_path = File.join(File.dirname(__FILE__), "..", "examples", game)
|
10
|
+
if File.exists?("#{ex_path}.rb")
|
11
|
+
game = ex_path
|
12
|
+
else
|
13
|
+
abort "no such game `#{game}'"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
old_setup = IRB.method(:setup)
|
18
|
+
IRB.singleton_class.send(:define_method, :setup) do |*args|
|
19
|
+
old_setup.call(*args)
|
20
|
+
old_rc = IRB.conf[:IRB_RC]
|
21
|
+
IRB.conf[:IRB_RC] = ->(context) do
|
22
|
+
old_rc[context] if old_rc
|
23
|
+
command = "ifrb #{game.inspect}\n"
|
24
|
+
command.reverse.chars.each { |c| context.irb.scanner.ungetc(c) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
ARGV.push "-rifrb"
|
29
|
+
IRB.start(__FILE__)
|
data/examples/basil.rb
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
WORDS = %w(wonky insipid squeak babushka cantilever intrepid flipper
|
2
|
+
periwinkle ewok munch gorgonzola ogle)
|
3
|
+
|
4
|
+
def start
|
5
|
+
_format <<-DESC
|
6
|
+
"Confound that blasted..."
|
7
|
+
|
8
|
+
The dust swirles and settles to the gentle swearing of your master, Basil Smockwhitener (wizard and gentleman). Coughing, you push your way through to him, and find him trapped beneath a large fallen beam.
|
9
|
+
|
10
|
+
Try as you might, thought, it's too much for you to lift. Basil appears to be injured, but he shoos you away.
|
11
|
+
|
12
|
+
"Stop, Fabian," he says. "Just--stop. It's too heavy. Go on ahead and find the Magic Doohickie. We can use it to get this beam off me. It's the only way, now. No arguing! Just go!"
|
13
|
+
|
14
|
+
You shrug, recognizing that tone of voice, and resigned as usual. "Yes, sir. I'll see what I can find."
|
15
|
+
|
16
|
+
DESC
|
17
|
+
|
18
|
+
armor = Class.new { def ticklish?; false; end }
|
19
|
+
|
20
|
+
doohickie = Class.new do
|
21
|
+
attr_reader :magic_a, :magic_b, :magic_c
|
22
|
+
|
23
|
+
def initialize(a, b, c)
|
24
|
+
@magic_a = a
|
25
|
+
@magic_b = b
|
26
|
+
@magic_c = c
|
27
|
+
end
|
28
|
+
|
29
|
+
def ==(h)
|
30
|
+
magic_a == h.magic_a &&
|
31
|
+
magic_b == h.magic_b &&
|
32
|
+
magic_c == h.magic_c
|
33
|
+
end
|
34
|
+
|
35
|
+
def dup
|
36
|
+
puts "Yeah, you kinda wish it were that easy, eh?"
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
alias clone dup
|
41
|
+
end
|
42
|
+
|
43
|
+
@__basil_freed = false
|
44
|
+
@__locked = true
|
45
|
+
@__armor = armor.new
|
46
|
+
@__armory_blocked = true
|
47
|
+
@__looted = false
|
48
|
+
@__doohickie = doohickie.new(rand(100), rand(100), rand(100))
|
49
|
+
@__setting_goal = rand(100)+1
|
50
|
+
|
51
|
+
undef start
|
52
|
+
basil
|
53
|
+
end
|
54
|
+
|
55
|
+
def basil
|
56
|
+
def look
|
57
|
+
if @__basil_freed
|
58
|
+
_format <<-DESC
|
59
|
+
Basil is free! You've done it! He's limping a bit, but he insists that it's nothing that a few cookies and a good night's rest won't cure. He gestures anxious to the south. "Let's go, Fabian!"
|
60
|
+
DESC
|
61
|
+
elsif @__looted
|
62
|
+
_format <<-DESC
|
63
|
+
You show Basil the Magic Doohickie and he breathes a sigh of relief. "You've done it, Fabian! Jolly good, old man! Now, just [adjust] the thing to the correct setting and get this beam off me. What? How should I know what the correct setting is? Just experiment. It's something between 1 and 100."
|
64
|
+
DESC
|
65
|
+
else
|
66
|
+
_format <<-DESC
|
67
|
+
What was formerly the ceiling now lies mostly on the floor, much of it unfortunately on your master, Basil. He gestures angrily at you to get moving. "Find the Doohickie!"
|
68
|
+
|
69
|
+
The passage goes south (to the exit), and north (towards the treasure chamber). Presumably, Basil wants you to go north.
|
70
|
+
DESC
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def adjust(setting=0)
|
75
|
+
if !@__basil_freed && @__looted
|
76
|
+
if setting < @__setting_goal
|
77
|
+
_format "The doohickie grows cooler momentarily."
|
78
|
+
elsif setting > @__setting_goal
|
79
|
+
_format "The doohickie grows warmer momentarily."
|
80
|
+
else
|
81
|
+
@__basil_freed = true
|
82
|
+
_format <<-DESC
|
83
|
+
With a satisfying *thunk*, the beam that had trapped Basil disappears! He stands up, dusts himself off, and shakes your hand a bit more vigorously than you think the situation calls for. "Well done, man! You did it! Now, let's get out of here. To the south!"
|
84
|
+
DESC
|
85
|
+
end
|
86
|
+
else
|
87
|
+
_format "Adjust what? You're funny."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def south
|
92
|
+
if @__basil_freed
|
93
|
+
_load_room :escape
|
94
|
+
else
|
95
|
+
_format <<-DESC
|
96
|
+
Basil shouts angrily at you. "Not that way, you oaf! North! North! Get the Doohickie!" His mustaches are practically bristling.
|
97
|
+
DESC
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def north
|
102
|
+
if @__basil_freed
|
103
|
+
_format <<-DESC
|
104
|
+
"What are you, a glutton for punishment?" Basil shakes his head in disbelief. "Come along, Fabian. South, man! Let's get out of here."
|
105
|
+
DESC
|
106
|
+
else
|
107
|
+
_load_room :lock
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def lock
|
113
|
+
def look
|
114
|
+
if @__locked
|
115
|
+
_format <<-DESC
|
116
|
+
Not that you have much experience with looting abandoned treasure chambers or anything, but the pattern on the far wall looks a lot like a magical lock. Your hunch is borne out by a large sign above it that reads:
|
117
|
+
|
118
|
+
"This is a magical lock. You'll never figure it out. Only a real magician, one able to [invoke] a spell that takes a string and reverses it, will ever manage to unlock it."
|
119
|
+
|
120
|
+
Better get busy. The alternative is to go south again and tell Basil you failed. (Whew. That gives you chills just thinking about it.)
|
121
|
+
DESC
|
122
|
+
else
|
123
|
+
_format <<-DESC
|
124
|
+
There is a passage going north. This is because you successfully invoked the spell that unlocked it. Good for you! Basil would be so proud. Assuming he noticed.
|
125
|
+
|
126
|
+
Oh, speaking of that. You can also go south, back to Basil.
|
127
|
+
DESC
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def south
|
132
|
+
_load_room :basil
|
133
|
+
end
|
134
|
+
|
135
|
+
def north
|
136
|
+
if @__locked
|
137
|
+
_format <<-DESC
|
138
|
+
What, through a magically locked door? You might try opening it first. Although, you'll need to unlock it before you can open it. Have you tried [invoke] yet?
|
139
|
+
DESC
|
140
|
+
else
|
141
|
+
_load_room :armory
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def invoke(spell=nil, &block)
|
146
|
+
if spell.nil? && !block
|
147
|
+
_format <<-DESC
|
148
|
+
Nothing happens, and it does so in a surprisingly uninspiring way. (Maybe you should provide the spell you want to cast? Perhaps as a lambda, or a block? But I'm just the narrator. What would I know about magic?)
|
149
|
+
DESC
|
150
|
+
elsif spell && !spell.respond_to?(:call)
|
151
|
+
_format "Um. I'm no expert, mind, but that doesn't look like a spell."
|
152
|
+
else
|
153
|
+
spell ||= block
|
154
|
+
words = WORDS.shuffle[0,5]
|
155
|
+
|
156
|
+
_format "Right. Let's see if this cantrip works. I'll just plug in a few words here..."
|
157
|
+
success = words.all? do |word|
|
158
|
+
result = spell[word]
|
159
|
+
puts " - `#{word}' becomes `#{result}'..."
|
160
|
+
word.reverse == result
|
161
|
+
end
|
162
|
+
|
163
|
+
if success
|
164
|
+
@__locked = false
|
165
|
+
_format "What the..?! You did it! A passage opens to the north!"
|
166
|
+
else
|
167
|
+
_format "Hmm. That's not quite right. Maybe you should have another go?"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def armory
|
174
|
+
def look
|
175
|
+
if @__armory_blocked
|
176
|
+
_format <<-DESC
|
177
|
+
The walls of this room are covered with exotic (and ancient-looking) weapons. Suits of armor are arranged haphazardly on stands, with one particularly imposing specimen standing--eerily life-like--right in front a door to the north. On its tabard is written the words:
|
178
|
+
|
179
|
+
"Tickle me. I dare you."
|
180
|
+
|
181
|
+
The only other exit is to the south.
|
182
|
+
DESC
|
183
|
+
else
|
184
|
+
_format <<-DESC
|
185
|
+
Aside from all the weapons and armor arranged around the walls, a large suit of armor lies prone on the floor.
|
186
|
+
|
187
|
+
One passage lies open to the north, and another to the south.
|
188
|
+
DESC
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def south
|
193
|
+
_load_room :lock
|
194
|
+
end
|
195
|
+
|
196
|
+
def north
|
197
|
+
if @__armory_blocked
|
198
|
+
_format <<-DESC
|
199
|
+
You think so, do you? Even with that big suit of armor daring you to tickle it?
|
200
|
+
DESC
|
201
|
+
else
|
202
|
+
_load_room :treasury
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def tickle(what=:armor)
|
207
|
+
if what == :armor
|
208
|
+
if @__armor.ticklish?
|
209
|
+
@__armory_blocked = false
|
210
|
+
|
211
|
+
def tickle(what=:armor)
|
212
|
+
_format "No need for more tickling. The armor is defunct!"
|
213
|
+
end
|
214
|
+
|
215
|
+
_format <<-DESC
|
216
|
+
You boldly start scratching the suit along its sides, viciously making baby noises while watching the suit's arms. Hollowly, from deep within the armor, a tinny-sounding giggling begins. It grows in volume like the Doppler effect with poor AM reception until the suit's arms start flailing helplessly and the armor falls to the floor.
|
217
|
+
|
218
|
+
As you back away, the giggling slowly fades, leaving nothing but rather unsettling echoes.
|
219
|
+
|
220
|
+
The passage to the north is unblocked!
|
221
|
+
DESC
|
222
|
+
else
|
223
|
+
_format <<-DESC
|
224
|
+
You reach out hesitantly and poke the suit of armor about where its belly button ought to be. Feeling faintly ridiculous, you add, "goochie goochie goo."
|
225
|
+
|
226
|
+
One of the suit's arms suddenly holds up a sign that reads, "Sorry. #ticklish? == false," before the other blindsides you and knocks you to the floor. By the time you stand up again, the armor has reset.
|
227
|
+
|
228
|
+
Hmm. Maybe you ought to try to [enhance] the armor with a module that makes it [ticklish?]
|
229
|
+
DESC
|
230
|
+
end
|
231
|
+
else
|
232
|
+
_format "That's a rather odd thing to tickle."
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def enhance(mod)
|
237
|
+
if @__armory_blocked
|
238
|
+
@__armor.extend(mod)
|
239
|
+
_format "Your enhancement settles experimentally onto the armor. Maybe try tickling it now?"
|
240
|
+
else
|
241
|
+
_format "The armor is nonfunctional, now. Enhancing it won't do anything."
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def treasury
|
247
|
+
def look
|
248
|
+
if @__looted
|
249
|
+
_format <<-DESC
|
250
|
+
The fake Magic Doohickie looks pretty convincing there on its pedestal. Perhaps you should go rescue Basil now that yo uhave the real one. Go south!
|
251
|
+
DESC
|
252
|
+
else
|
253
|
+
_format <<-DESC
|
254
|
+
This is it! The treasury, containing the ancient and mysterious Magic Doohickie of Hank Doolickie! Its rumored powers are many, and its rumored guardians are...well...many, also. Somehow, you need to [swap] it with an identical [doohickie], so that the guards won't realize it's been taken.
|
255
|
+
|
256
|
+
Or, you can give up and go south. Quitter.
|
257
|
+
DESC
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
def doohickie
|
262
|
+
@__doohickie
|
263
|
+
end
|
264
|
+
|
265
|
+
def south
|
266
|
+
_load_room :armory
|
267
|
+
end
|
268
|
+
|
269
|
+
def swap(a, b)
|
270
|
+
if @__looted
|
271
|
+
_format "Wait, don't do that! You've already pulled off the heist!"
|
272
|
+
elsif a.equal?(b)
|
273
|
+
_format "What are you trying to pull? You can't swap a thing with itself!"
|
274
|
+
else
|
275
|
+
a, b = b, a if b == @__doohickie
|
276
|
+
if a == @__doohickie
|
277
|
+
if a == b
|
278
|
+
@__looted = true
|
279
|
+
@__my_doohickie, @__doohickie = a, b
|
280
|
+
_format <<-DESC
|
281
|
+
Whoa! That was tricky! You totally swapped your fake for the real deal! This means...wait. This means you can go free Basil, now! Quickly, head south!
|
282
|
+
DESC
|
283
|
+
else
|
284
|
+
_format <<-DESC
|
285
|
+
Hmm...those don't quite look equivalent. I suspect something really, really, really, really, really, really, really bad would happen if you actually tried swapping them. Can you make your fake one look anything more like the real [doohickie]?
|
286
|
+
DESC
|
287
|
+
end
|
288
|
+
else
|
289
|
+
_format "That's...odd. Try that again, this time with the [doohickie]."
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def escape
|
296
|
+
def look
|
297
|
+
_format <<-DESC
|
298
|
+
You've done it! You recovered the Magic Doohickie, rescued Basil, and capped it all of with a daring escape. Well, maybe not *daring*. But an escape, nonetheless.
|
299
|
+
|
300
|
+
Well done!
|
301
|
+
DESC
|
302
|
+
|
303
|
+
quit
|
304
|
+
end
|
305
|
+
end
|
data/lib/ifrb.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
if !defined? IRB
|
2
|
+
abort "ifrb will only work within an IRB session"
|
3
|
+
end
|
4
|
+
|
5
|
+
IRB.conf[:PROMPT][:IFRB] = {
|
6
|
+
:PROMPT_I => "%N> ", # "initial" prompt
|
7
|
+
:PROMPT_C => "..", # continued command
|
8
|
+
:PROMPT_S => "..", # continued string
|
9
|
+
:PROMPT_N => "..", # nested command
|
10
|
+
:RETURN => "" # formatting for return values
|
11
|
+
}
|
12
|
+
|
13
|
+
def ifrb(game)
|
14
|
+
context.prompt_mode = :IFRB
|
15
|
+
|
16
|
+
class <<self
|
17
|
+
def method_missing(sym, *args)
|
18
|
+
if args.empty?
|
19
|
+
sym
|
20
|
+
else
|
21
|
+
super
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def _load_room(name)
|
27
|
+
context.irb_name = name
|
28
|
+
|
29
|
+
(methods - @_baseline).each do |method|
|
30
|
+
eval "undef #{method}"
|
31
|
+
end
|
32
|
+
|
33
|
+
send(name)
|
34
|
+
|
35
|
+
look if respond_to?(:look)
|
36
|
+
end
|
37
|
+
|
38
|
+
def _format(text, length:60, indent:2)
|
39
|
+
indent = " " * indent
|
40
|
+
|
41
|
+
text.each_line do |line|
|
42
|
+
line.strip!
|
43
|
+
|
44
|
+
if line.empty?
|
45
|
+
puts
|
46
|
+
else
|
47
|
+
while line.length > length
|
48
|
+
break_at = length
|
49
|
+
break_at -= 1 while break_at > 0 && line[break_at] != " "
|
50
|
+
break_at = length if break_at == 0
|
51
|
+
puts indent + line[0, break_at]
|
52
|
+
line = line[break_at+1..-1]
|
53
|
+
end
|
54
|
+
|
55
|
+
puts indent + line if line.length > 0
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
load "#{game}.rb"
|
63
|
+
@_baseline = methods
|
64
|
+
|
65
|
+
_load_room :start
|
66
|
+
end
|
data/lib/ifrb/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ifrb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jamis Buck
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-17 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: We spend much of our professional lives in IRB. Why not make a game of
|
14
|
+
it?
|
15
|
+
email:
|
16
|
+
- jamis@jamisbuck.org
|
17
|
+
executables:
|
18
|
+
- ifrb
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- README.md
|
23
|
+
- Rakefile
|
24
|
+
- bin/ifrb
|
25
|
+
- examples/basil.rb
|
26
|
+
- lib/ifrb.rb
|
27
|
+
- lib/ifrb/version.rb
|
28
|
+
homepage: http://github.com/jamis/ifrb
|
29
|
+
licenses:
|
30
|
+
- CC4.0
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubyforge_project:
|
48
|
+
rubygems_version: 2.4.5
|
49
|
+
signing_key:
|
50
|
+
specification_version: 4
|
51
|
+
summary: A system for running interactive fiction games within IRB.
|
52
|
+
test_files: []
|