gamefic 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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