gamefic 0.2.0 → 0.6.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.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gamefic/action.rb +87 -56
  3. data/lib/gamefic/ansi.rb +55 -0
  4. data/lib/gamefic/character.rb +130 -76
  5. data/lib/gamefic/command.rb +19 -0
  6. data/lib/gamefic/core_ext/array.rb +51 -40
  7. data/lib/gamefic/core_ext/string.rb +4 -0
  8. data/lib/gamefic/describable.rb +108 -46
  9. data/lib/gamefic/direction.rb +46 -0
  10. data/lib/gamefic/director/delegate.rb +91 -0
  11. data/lib/gamefic/director/order.rb +10 -0
  12. data/lib/gamefic/director/parser.rb +119 -0
  13. data/lib/gamefic/director.rb +16 -197
  14. data/lib/gamefic/engine/cgi.rb +221 -0
  15. data/lib/gamefic/engine/tty.rb +237 -0
  16. data/lib/gamefic/engine.rb +88 -67
  17. data/lib/gamefic/entity.rb +96 -69
  18. data/lib/gamefic/grammar/conjugator.rb +20 -0
  19. data/lib/gamefic/grammar/gender.rb +11 -0
  20. data/lib/gamefic/grammar/person.rb +10 -0
  21. data/lib/gamefic/grammar/plural.rb +13 -0
  22. data/lib/gamefic/grammar/pronouns.rb +60 -0
  23. data/lib/gamefic/grammar/tense.rb +6 -0
  24. data/lib/gamefic/grammar/verb_set.rb +43 -0
  25. data/lib/gamefic/grammar/verbs.rb +25 -0
  26. data/lib/gamefic/grammar/word_adapter.rb +36 -0
  27. data/lib/gamefic/grammar.rb +13 -0
  28. data/lib/gamefic/html.rb +53 -0
  29. data/lib/gamefic/keywords.rb +51 -33
  30. data/lib/gamefic/node.rb +65 -58
  31. data/lib/gamefic/plot/article_mount.rb +22 -0
  32. data/lib/gamefic/plot/command_mount.rb +88 -0
  33. data/lib/gamefic/plot/entity_mount.rb +45 -0
  34. data/lib/gamefic/plot/query_mount.rb +9 -0
  35. data/lib/gamefic/plot/scene_mount.rb +181 -0
  36. data/lib/gamefic/plot/you_mount.rb +22 -0
  37. data/lib/gamefic/plot.rb +296 -247
  38. data/lib/gamefic/query/ambiguous_children.rb +5 -0
  39. data/lib/gamefic/query/base.rb +265 -0
  40. data/lib/gamefic/query/children.rb +10 -0
  41. data/lib/gamefic/query/expression.rb +47 -0
  42. data/lib/gamefic/query/family.rb +10 -0
  43. data/lib/gamefic/query/many_children.rb +7 -0
  44. data/lib/gamefic/query/matches.rb +11 -0
  45. data/lib/gamefic/query/parent.rb +10 -0
  46. data/lib/gamefic/query/plural_children.rb +14 -0
  47. data/lib/gamefic/query/self.rb +10 -0
  48. data/lib/gamefic/query/siblings.rb +10 -0
  49. data/lib/gamefic/query/text.rb +43 -0
  50. data/lib/gamefic/query.rb +19 -203
  51. data/lib/gamefic/rule.rb +18 -0
  52. data/lib/gamefic/scene/active.rb +25 -0
  53. data/lib/gamefic/scene/concluded.rb +22 -0
  54. data/lib/gamefic/scene/multiplechoice.rb +74 -0
  55. data/lib/gamefic/scene/paused.rb +26 -0
  56. data/lib/gamefic/scene/yesorno.rb +43 -0
  57. data/lib/gamefic/scene.rb +125 -0
  58. data/lib/gamefic/script/base.rb +33 -0
  59. data/lib/gamefic/script/file.rb +14 -0
  60. data/lib/gamefic/script/text.rb +14 -0
  61. data/lib/gamefic/script.rb +9 -0
  62. data/lib/gamefic/serialized.rb +24 -0
  63. data/lib/gamefic/shell.rb +9 -247
  64. data/lib/gamefic/snapshots.rb +134 -0
  65. data/lib/gamefic/source/base.rb +12 -0
  66. data/lib/gamefic/source/file.rb +23 -0
  67. data/lib/gamefic/source/text.rb +16 -0
  68. data/lib/gamefic/source.rb +9 -0
  69. data/lib/gamefic/stage.rb +75 -0
  70. data/lib/gamefic/syntax.rb +106 -124
  71. data/lib/gamefic/tester.rb +20 -0
  72. data/lib/gamefic/version.rb +3 -0
  73. data/lib/gamefic.rb +18 -12
  74. metadata +102 -70
  75. data/lib/gamefic/base.rb +0 -10
  76. data/lib/gamefic/before.rb +0 -12
  77. data/lib/gamefic/import/basics/actions/close.rb +0 -16
  78. data/lib/gamefic/import/basics/actions/commands.rb +0 -3
  79. data/lib/gamefic/import/basics/actions/drop-in.rb +0 -17
  80. data/lib/gamefic/import/basics/actions/drop-on.rb +0 -16
  81. data/lib/gamefic/import/basics/actions/drop.rb +0 -30
  82. data/lib/gamefic/import/basics/actions/enter.rb +0 -16
  83. data/lib/gamefic/import/basics/actions/go.rb +0 -35
  84. data/lib/gamefic/import/basics/actions/inventory.rb +0 -8
  85. data/lib/gamefic/import/basics/actions/leave.rb +0 -29
  86. data/lib/gamefic/import/basics/actions/look-in-at.rb +0 -27
  87. data/lib/gamefic/import/basics/actions/look-under.rb +0 -3
  88. data/lib/gamefic/import/basics/actions/look.rb +0 -71
  89. data/lib/gamefic/import/basics/actions/nil.rb +0 -25
  90. data/lib/gamefic/import/basics/actions/open.rb +0 -23
  91. data/lib/gamefic/import/basics/actions/quit.rb +0 -3
  92. data/lib/gamefic/import/basics/actions/take.rb +0 -107
  93. data/lib/gamefic/import/basics/entities/container.rb +0 -8
  94. data/lib/gamefic/import/basics/entities/entity.rb +0 -11
  95. data/lib/gamefic/import/basics/entities/fixture.rb +0 -5
  96. data/lib/gamefic/import/basics/entities/item.rb +0 -5
  97. data/lib/gamefic/import/basics/entities/portal.rb +0 -40
  98. data/lib/gamefic/import/basics/entities/room.rb +0 -30
  99. data/lib/gamefic/import/basics/entities/scenery.rb +0 -5
  100. data/lib/gamefic/import/basics/entities/supporter.rb +0 -6
  101. data/lib/gamefic/import/basics/entities/thing.rb +0 -16
  102. data/lib/gamefic/import/basics/queries/reachable.rb +0 -38
  103. data/lib/gamefic/import/basics/queries/room.rb +0 -8
  104. data/lib/gamefic/import/basics/queries/visible.rb +0 -32
  105. data/lib/gamefic/import/basics/rules/has-enough-light.rb +0 -14
  106. data/lib/gamefic/import/basics.old/actions/container.rb +0 -112
  107. data/lib/gamefic/import/basics.old/actions/inventory.rb +0 -50
  108. data/lib/gamefic/import/basics.old/actions/look.rb +0 -53
  109. data/lib/gamefic/import/basics.old/actions/meta.rb +0 -6
  110. data/lib/gamefic/import/basics.old/actions/traversal.rb +0 -35
  111. data/lib/gamefic/import/basics.old/actions.rb +0 -1
  112. data/lib/gamefic/import/basics.old/entities/container.rb +0 -3
  113. data/lib/gamefic/import/basics.old/entities/fixture.rb +0 -3
  114. data/lib/gamefic/import/basics.old/entities/item.rb +0 -3
  115. data/lib/gamefic/import/basics.old/entities/portal.rb +0 -43
  116. data/lib/gamefic/import/basics.old/entities/room.rb +0 -27
  117. data/lib/gamefic/import/basics.old/entities/scenery.rb +0 -3
  118. data/lib/gamefic/import/basics.old/entities/supporter.rb +0 -3
  119. data/lib/gamefic/import/basics.old/entities.rb +0 -1
  120. data/lib/gamefic/import/basics.old/room_modes.rb +0 -48
  121. data/lib/gamefic/import/basics.rb +0 -6
  122. data/lib/gamefic/import/room_modes.rb +0 -48
  123. data/lib/gamefic/import/standard.rb +0 -1
  124. data/lib/gamefic/meta.rb +0 -12
  125. data/lib/gamefic/optionset.rb +0 -114
  126. data/lib/gamefic/requirement.rb +0 -14
  127. data/lib/gamefic/story.rb +0 -14
  128. data/lib/gamefic/thing.rb +0 -7
data/lib/gamefic/shell.rb CHANGED
@@ -1,23 +1,8 @@
1
- require 'rubygems'
2
- require 'rubygems/package'
3
- require 'zlib'
1
+ require 'zip'
4
2
  require 'tmpdir'
5
3
  require 'getoptlong'
6
4
  require 'gamefic/engine/tty'
7
5
 
8
- # Crazy hack to set file mtimes in tar file
9
- class Gem::Package::TarHeader
10
- @@mtime = Time.now
11
- def self.set_mtime(time)
12
- @@mtime = time
13
- end
14
- alias :initialize_orig :initialize
15
- def initialize(vals)
16
- initialize_orig(vals)
17
- @mtime = @@mtime
18
- end
19
- end
20
-
21
6
  module Gamefic
22
7
 
23
8
  class Shell
@@ -33,14 +18,6 @@ module Gamefic
33
18
  case cmd
34
19
  when 'play'
35
20
  play ARGV.shift
36
- when 'test'
37
- test ARGV.shift
38
- when 'init'
39
- init ARGV.shift
40
- when 'build'
41
- build ARGV.shift
42
- when 'fetch'
43
- fetch ARGV.shift
44
21
  when 'help'
45
22
  help ARGV.shift
46
23
  else
@@ -59,177 +36,20 @@ module Gamefic
59
36
  end
60
37
  Dir.mktmpdir 'gamefic_' do |dir|
61
38
  puts "Loading..."
62
- story = Story.new
39
+ story = Plot.new(Source.new(dir + '/scripts'))
63
40
  begin
64
41
  decompress file, dir
65
42
  rescue Exception => e
66
43
  puts "'#{file}' does not appear to be a valid Gamefic file."
67
- puts "#{e}"
44
+ puts e.backtrace
68
45
  exit 1
69
46
  end
70
- story.load dir + '/main.rb'
47
+ story.load dir + '/main'
71
48
  engine = Tty::Engine.new story
72
49
  puts "\n"
73
50
  engine.run
74
51
  end
75
52
  end
76
- def test path
77
- puts "Loading..."
78
- story = Story.new
79
- #begin
80
- if File.directory?(path)
81
- if !File.file?(path + '/main.rb')
82
- raise "#{path}/main.rb does not exist"
83
- end
84
- story.load path + '/main.rb', true
85
- else
86
- story.load path
87
- end
88
- #rescue Exception => e
89
- # puts "An error occurred in #{path}:"
90
- # puts "#{e.inspect}"
91
- # exit 1
92
- #end
93
- engine = Tty::Engine.new story
94
- puts "\n"
95
- engine.run
96
- end
97
- def init directory
98
- if directory.to_s == ''
99
- puts "No directory specified."
100
- exit 1
101
- elsif File.exist?(directory)
102
- if !File.directory?(directory)
103
- files = Dir[directory + '/*']
104
- if files.length > 0
105
- puts "'#{directory}' is not an empty directory."
106
- exit 1
107
- end
108
- else
109
- puts "'#{directory}' is not an empty directory."
110
- exit 1
111
- end
112
- else
113
- Dir.mkdir(directory)
114
- end
115
- Dir.mkdir(directory + '/import')
116
- main_rb = File.new(directory + '/main.rb', 'w')
117
- main_rb.write <<EOS
118
- import 'standard'
119
-
120
- room = make Room, :name => 'room'
121
-
122
- introduction do |player|
123
- player.parent = room
124
- player.perform "look"
125
- end
126
- EOS
127
- main_rb.close
128
- #fetch directory
129
- puts "Game directory '#{directory}' initialized."
130
- end
131
- def fetch directory
132
- if directory.to_s == ''
133
- puts "No source directory was specified."
134
- exit 1
135
- end
136
- if !File.directory?(directory)
137
- puts "#{directory} is not a directory."
138
- exit 1
139
- end
140
- puts "Loading game data..."
141
- story = Story.new
142
- begin
143
- story.load directory + '/main.rb', true
144
- rescue Exception => e
145
- puts "'#{directory}' has errors or is not a valid source directory."
146
- puts "#{e}"
147
- exit 1
148
- end
149
- puts "Checking for external script references..."
150
- fetched = 0
151
- story.imported_scripts.each { |script|
152
- if !script.filename.start_with?(directory)
153
- base = script.filename[(script.filename.rindex('import/') + 7)..-1]
154
- puts "Fetching #{base}"
155
- FileUtils.mkdir_p directory + '/import/' + File.dirname(base)
156
- FileUtils.copy script.filename, directory + '/import/' + base
157
- fetched += 1
158
- end
159
- }
160
- if fetched == 0
161
- puts "Nothing to fetch."
162
- else
163
- puts "Done."
164
- end
165
- end
166
- def build directory
167
- if directory.to_s == ''
168
- puts "No source directory was specified."
169
- exit 1
170
- end
171
- if !File.directory?(directory)
172
- puts "#{directory} is not a directory."
173
- exit 1
174
- end
175
- filename = File.basename(directory) + '.gfic'
176
- opts = GetoptLong.new(
177
- [ '-o', '--output', GetoptLong::REQUIRED_ARGUMENT ]
178
- )
179
- opts.quiet = true
180
- begin
181
- opts.each { |opt, arg|
182
- case opt
183
- when '-o'
184
- filename = arg
185
- end
186
- }
187
- rescue Exception => e
188
- puts "#{e}"
189
- exit 1
190
- end
191
- if File.exist?(filename)
192
- puts "The file #{filename} already exists."
193
- exit 1
194
- end
195
- story = Story.new
196
- puts "Loading game data..."
197
- begin
198
- story.load directory + '/main.rb', true
199
- rescue Exception => e
200
- puts "'#{directory}' has errors or is not a valid source directory."
201
- puts "#{e}"
202
- exit 1
203
- end
204
- puts "Building file..."
205
- stream = StringIO.new("")
206
- Gem::Package::TarWriter.new(stream) do |tar|
207
- Gem::Package::TarHeader.set_mtime Time.now
208
- tar.add_file('main.rb', 0600) do |io|
209
- File.open(directory + '/main.rb', "rb") { |f| io.write f.read }
210
- end
211
- if story.imported_scripts.length > 0
212
- Gem::Package::TarHeader.set_mtime Time.now
213
- tar.mkdir('import', 0700)
214
- story.imported_scripts.each { |script|
215
- base = script.filename[script.filename.rindex('import/') + 7..-1]
216
- Gem::Package::TarHeader.set_mtime Time.now
217
- tar.add_file('import/' + base, 0700) do |io|
218
- io.write script.code
219
- end
220
- }
221
- end
222
- end
223
- gz = StringIO.new("")
224
- z = Zlib::GzipWriter.new(gz)
225
- z.mtime = Time.now
226
- z.write stream.string
227
- z.close
228
- file = File.new(filename, "w")
229
- file.write gz.string
230
- file.close
231
- puts "Gamefic file '#{filename}' complete."
232
- end
233
53
  def help command
234
54
  shell_script = File.basename($0)
235
55
  case command
@@ -237,40 +57,10 @@ EOS
237
57
  puts <<EOS
238
58
  #{shell_script} play [file]
239
59
  Play a Gamefic file on the command line.
240
- EOS
241
- when "test"
242
- puts <<EOS
243
- #{shell_script} test [path]
244
- Test a Gamefic source directory or script.
245
- EOS
246
- when "init"
247
- puts <<EOS
248
- #{shell_script} init [directory]
249
- Initialize a Gamefic source directory. The resulting directory will contain
250
- source files ready to build into a Gamefic file.
251
- EOS
252
- when "fetch"
253
- puts <<EOS
254
- #{shell_script} fetch [directory]
255
- Copy shared scripts to the source directory.
256
- If the specified game directory imnports external scripts, such as the ones
257
- that are distributed with the Gamefic gem, this command will copy them into
258
- the game's import directory. Fetching can be useful if you want to customize
259
- common features.
260
- EOS
261
- when "build"
262
- puts <<EOS
263
- #{shell_script} build [directory] [-o | --output filename]
264
- Build a distributable Gamefic file from the source directory. The default
265
- filename is [directory].gfic. You can change the filename with the -o option.
266
60
  EOS
267
61
  when nil, "help"
268
62
  puts <<EOS
269
63
  #{shell_script} play [file] - play a Gamefic file
270
- #{shell_script} init [dir] - initialize a Gamefic source directory
271
- #{shell_script} test [path] - test a Gamefic source directory or script
272
- #{shell_script} fetch [directory] - copy shared scripts into directory
273
- #{shell_script} build [directory] - build a Gamefic file
274
64
  #{shell_script} help - display this message
275
65
  #{shell_script} help [command] - display info about command
276
66
  EOS
@@ -279,39 +69,11 @@ EOS
279
69
  exit 1
280
70
  end
281
71
  end
282
- def decompress(tarfile, destination)
283
- tar_longlink = '././@LongLink'
284
- Gem::Package::TarReader.new( Zlib::GzipReader.open tarfile ) do |tar|
285
- dest = nil
286
- tar.each do |entry|
287
- if entry.full_name == tar_longlink
288
- dest = File.join destination, entry.read.strip
289
- next
290
- end
291
- dest ||= File.join destination, entry.full_name
292
- if entry.directory?
293
- FileUtils.rm_rf dest unless File.directory? dest
294
- FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false
295
- elsif entry.file?
296
- cur_stack = dest.split('/')
297
- cur_stack.pop
298
- cur_dir = ''
299
- while cur_stack.length > 0
300
- cur_dir += '/' + cur_stack.shift
301
- if !File.exist?(destination + cur_dir)
302
- FileUtils.mkdir_p dest, :mode => 0700, :verbose => false
303
- end
304
- end
305
- FileUtils.mkdir_p dest, :mode => entry.header.mode, :verbose => false
306
- FileUtils.rm_rf dest unless File.file? dest
307
- File.open dest, "wb" do |f|
308
- f.print entry.read
309
- end
310
- FileUtils.chmod entry.header.mode, dest, :verbose => false
311
- elsif entry.header.typeflag == '2' #Symlink!
312
- File.symlink entry.header.linkname, dest
313
- end
314
- dest = nil
72
+ def decompress(zipfile, destination)
73
+ Zip::File.open(zipfile) do |z|
74
+ z.each do |entry|
75
+ FileUtils.mkdir_p "#{destination}/#{File.dirname(entry.name)}"
76
+ entry.extract "#{destination}/#{entry.name}"
315
77
  end
316
78
  end
317
79
  end
@@ -0,0 +1,134 @@
1
+ require 'json'
2
+
3
+ module Gamefic
4
+ class Snapshots
5
+ attr_accessor :history
6
+ def initialize entities
7
+ @history = []
8
+ @entities = entities
9
+ end
10
+ def save entities
11
+ store = []
12
+ index = 0
13
+ entities.each { |e|
14
+ hash = {}
15
+ e.serialized_attributes.each {|m|
16
+ con = m.to_s
17
+ if con.end_with?("?")
18
+ con = con[0..-2]
19
+ end
20
+ if e.respond_to?(m) == true
21
+ begin
22
+ xxx = e.send(m)
23
+ if xxx == false
24
+ hash[con] = false
25
+ elsif xxx
26
+ hash[con] = serialize_obj(xxx)
27
+ else
28
+ hash[con] = nil
29
+ end
30
+ rescue Exception => error
31
+ hash[con] = nil
32
+ end
33
+ end
34
+ }
35
+ hash[:session] = {}
36
+ e.session.each_pair { |k, v|
37
+ hash[:session][k] = serialize_obj(v)
38
+ }
39
+ store.push hash
40
+ index += 1
41
+ }
42
+ if @history.length > 10
43
+ @history.shift
44
+ end
45
+ json = JSON.generate(store)
46
+ #puts json
47
+ json
48
+ end
49
+ def restore snapshot
50
+ data = JSON.parse(snapshot)
51
+ index = 0
52
+ data.each { |hash|
53
+ hash.each_pair { |k, v|
54
+ @entities[index].send("#{k}=", unserialize(v)) if k.to_s != "session"
55
+ }
56
+ #unser = unserialize(hash["session"])
57
+ hash["session"].each_pair { |k, v|
58
+ @entities[index].session[k.to_sym] = unserialize(v)
59
+ }
60
+ index += 1
61
+ }
62
+ end
63
+ def blacklist
64
+ [:children, :session, :scene, :object_of_pronoun, :test_queue, :test_queue_scene, :test_queue_length, :testing]
65
+ end
66
+ private
67
+ def can_serialize? obj
68
+ return true if (obj == true or obj == false or obj.nil?)
69
+ allowed = [String, Fixnum, Float, Numeric, Entity, Direction, Hash, Array, Symbol]
70
+ allowed.each { |a|
71
+ return true if obj.kind_of?(a)
72
+ }
73
+ false
74
+ end
75
+ def serialize_obj obj
76
+ return nil if obj.nil?
77
+ return false if obj == false
78
+ if obj.kind_of?(Hash)
79
+ hash = {}
80
+ obj.each_pair { |k, v|
81
+ if can_serialize?(k) and can_serialize?(v)
82
+ hash[serialize_obj(k)] = serialize_obj(v)
83
+ end
84
+ }
85
+ return hash
86
+ elsif obj.kind_of?(Array)
87
+ arr = []
88
+ obj.each_index { |i|
89
+ if can_serialize?(obj[i])
90
+ arr[i] = serialize_obj(obj[i])
91
+ else
92
+ raise "Bad array in snapshot"
93
+ end
94
+ }
95
+ return arr
96
+ else
97
+ if obj.kind_of?(Entity)
98
+ return "#<EIN_#{@entities.index(obj)}>"
99
+ elsif obj.kind_of?(Direction)
100
+ return "#<DIR_#{obj.name}>"
101
+ #elsif obj.kind_of?(Symbol)
102
+ # return "#<SYM_#{obj.to_s}>"
103
+ end
104
+ end
105
+ return obj
106
+ end
107
+ def unserialize obj
108
+ if obj.kind_of?(Hash)
109
+ hash = {}
110
+ obj.each_pair { |k, v|
111
+ hash[unserialize(k)] = unserialize(v)
112
+ }
113
+ hash
114
+ elsif obj.kind_of?(Array)
115
+ arr = []
116
+ obj.each_index { |i|
117
+ arr[i] = unserialize(obj[i])
118
+ }
119
+ arr
120
+ else
121
+ if obj.to_s.match(/^#<EIN_[0-9]+>$/)
122
+ i = obj[6..-2].to_i
123
+ @entities[i]
124
+ elsif obj.to_s.match(/^#<DIR_[a-z]+>$/)
125
+ Direction.find(obj[6..-2])
126
+ #elsif obj.to_s.match(/^#<SYM_[a-z]+>$/)
127
+ # Direction.find(obj[6..-2].to_sym)
128
+ else
129
+ obj
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,12 @@
1
+ module Gamefic
2
+
3
+ class Source::Base
4
+ def initialize
5
+ raise "#initialize must be defined in subclasses"
6
+ end
7
+ def export path
8
+ raise "#export must be defined in subclasses"
9
+ end
10
+ end
11
+
12
+ end
@@ -0,0 +1,23 @@
1
+ module Gamefic
2
+
3
+ class Source::File < Source::Base
4
+ @@extensions = ['.plot.rb', '.plot', '.rb']
5
+ attr_reader :directories
6
+ attr_accessor :main_dir
7
+ def initialize(*directories)
8
+ @directories = directories || []
9
+ end
10
+ def export path
11
+ @directories.each { |directory|
12
+ @@extensions.each { |ext|
13
+ abs_file = directory + '/' + path + ext
14
+ if File.file?(abs_file)
15
+ return Script::File.new(abs_file, path)
16
+ end
17
+ }
18
+ }
19
+ raise "Script #{path} not found"
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,16 @@
1
+ module Gamefic
2
+
3
+ class Source::Text < Source::Base
4
+ def initialize scripts = {}
5
+ @scripts = scripts
6
+ end
7
+ def export path
8
+ if @scripts.has_key?(path)
9
+ Script::Text.new(path, @scripts[path])
10
+ else
11
+ raise "Script #{path} not found"
12
+ end
13
+ end
14
+ end
15
+
16
+ end
@@ -0,0 +1,9 @@
1
+ module Gamefic
2
+
3
+ module Source
4
+ autoload :Base, 'gamefic/source/base'
5
+ autoload :File, 'gamefic/source/file'
6
+ autoload :Text, 'gamefic/source/text'
7
+ end
8
+
9
+ end
@@ -0,0 +1,75 @@
1
+ module Gamefic
2
+
3
+ module Stage
4
+ def stage *args, &block
5
+ s = generate_stage
6
+
7
+ if block.nil?
8
+ s.module_eval(*args)
9
+ else
10
+ s.module_exec(*args, &block)
11
+ end
12
+ end
13
+ private
14
+ def generate_stage
15
+ return @stage if !@stage.nil?
16
+
17
+ exposed = self.class.exposed_methods.keys
18
+ mounted = self.class.mounted_modules.keys
19
+ instance = self
20
+
21
+ @stage = Module.new do
22
+ define_singleton_method(:__instance__) do
23
+ unless caller.length == 0 or caller[0].include?(__FILE__)
24
+ raise NoMethodError.new("Method __instance__ is not available from the stage.")
25
+ end
26
+ instance
27
+ end
28
+ exposed.each do |exposed_method|
29
+ define_singleton_method(exposed_method) do |*args, &block|
30
+ __instance__.public_send(exposed_method, *args, &block)
31
+ end
32
+ end
33
+ mounted.each { |dsl|
34
+ dsl.public_instance_methods.each { |method|
35
+ define_singleton_method(method) do |*args, &block|
36
+ #puts "Calling a mounted method"
37
+ result = __instance__.public_send(method, *args, &block)
38
+ #puts "Done"
39
+ result
40
+ end
41
+ }
42
+ }
43
+ end
44
+
45
+ return @stage
46
+ end
47
+ module ClassMethods
48
+ def mount *args
49
+ args.each { |a|
50
+ include a
51
+ mounted_modules[a] = nil
52
+ }
53
+ end
54
+ def expose *args
55
+ args.each { |a|
56
+ exposed_methods[a] = nil
57
+ }
58
+ end
59
+ def exposed_methods
60
+ @@exposed_methods ||= from_superclass(:exposed_methods, {}).dup
61
+ end
62
+ def mounted_modules
63
+ @@mounted_modules ||= from_superclass(:mounted_modules, {}).dup
64
+ end
65
+ private
66
+ def from_superclass(m, default = nil)
67
+ superclass.respond_to?(m) ? superclass.send(m) : default
68
+ end
69
+ end
70
+ def self.included(base)
71
+ base.extend(ClassMethods)
72
+ end
73
+ end
74
+
75
+ end