inform-runtime 1.0.4 → 1.2.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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -12
  3. data/Rakefile +26 -16
  4. data/lib/{runtime → story_teller}/articles.rb +14 -10
  5. data/lib/{runtime → story_teller}/builtins.rb +50 -22
  6. data/lib/{runtime → story_teller}/color.rb +8 -8
  7. data/lib/{runtime → story_teller}/command.rb +26 -28
  8. data/lib/{runtime → story_teller}/context.rb +23 -24
  9. data/lib/story_teller/core.rb +38 -0
  10. data/lib/{runtime → story_teller}/daemon.rb +35 -36
  11. data/lib/story_teller/engine.rb +151 -0
  12. data/lib/story_teller/ephemeral_adapter.rb +42 -0
  13. data/lib/{runtime → story_teller}/events.rb +8 -9
  14. data/lib/{runtime → story_teller}/experimental/handler_dsl.rb +7 -18
  15. data/lib/story_teller/experimental/reverse_engineer_class.rb +37 -0
  16. data/lib/{runtime → story_teller}/grammar_parser.rb +24 -40
  17. data/lib/{runtime → story_teller}/helpers.rb +21 -7
  18. data/lib/{runtime → story_teller}/history.rb +5 -5
  19. data/lib/{runtime → story_teller}/inflector.rb +4 -5
  20. data/lib/story_teller/inform/base.rb +160 -0
  21. data/lib/{runtime → story_teller/inform/ephemeral}/link.rb +27 -45
  22. data/lib/{runtime → story_teller/inform/ephemeral}/module.rb +17 -58
  23. data/lib/story_teller/inform/ephemeral/object.rb +329 -0
  24. data/lib/{runtime → story_teller/inform/ephemeral}/tag.rb +54 -81
  25. data/lib/story_teller/inform/models.rb +25 -0
  26. data/lib/{runtime → story_teller}/io.rb +10 -10
  27. data/lib/{runtime → story_teller}/kernel.rb +21 -31
  28. data/lib/story_teller/library/bootstrap.rb +66 -0
  29. data/lib/story_teller/library/declarations.rb +53 -0
  30. data/lib/story_teller/library/directives.rb +91 -0
  31. data/lib/story_teller/library/loader.rb +104 -0
  32. data/lib/story_teller/library/location.rb +73 -0
  33. data/lib/{runtime → story_teller}/library.rb +27 -12
  34. data/lib/{runtime → story_teller}/logging.rb +47 -24
  35. data/lib/{runtime → story_teller}/mixins.rb +6 -6
  36. data/lib/story_teller/model_adapter.rb +132 -0
  37. data/lib/{runtime → story_teller}/plurals.rb +11 -11
  38. data/lib/{runtime → story_teller}/prototype.rb +11 -10
  39. data/lib/{runtime → story_teller}/publication.rb +9 -9
  40. data/lib/{runtime → story_teller}/session.rb +6 -8
  41. data/lib/{runtime → story_teller}/stdlib.rb +13 -11
  42. data/lib/{runtime → story_teller}/subscription.rb +8 -8
  43. data/lib/{runtime → story_teller}/tree.rb +6 -6
  44. data/lib/{runtime → story_teller}/version.rb +16 -6
  45. data/lib/story_teller/world_tree.rb +54 -0
  46. data/lib/story_teller.rb +26 -0
  47. metadata +59 -99
  48. data/config/database.yml +0 -37
  49. data/exe/inform.rb +0 -6
  50. data/game/config.yml +0 -5
  51. data/game/example.inf +0 -76
  52. data/game/example.rb +0 -90
  53. data/game/forms/example_form.rb +0 -2
  54. data/game/grammar/game_grammar.inf.rb +0 -11
  55. data/game/languages/english.rb +0 -2
  56. data/game/models/example_model.rb +0 -2
  57. data/game/modules/example_module.rb +0 -9
  58. data/game/rules/example_state.rb +0 -2
  59. data/game/scripts/example_script.rb +0 -2
  60. data/game/topics/example_topic.rb +0 -2
  61. data/game/verbs/game_verbs.rb +0 -15
  62. data/game/verbs/metaverbs.rb +0 -2028
  63. data/lib/runtime/config.rb +0 -48
  64. data/lib/runtime/database.rb +0 -500
  65. data/lib/runtime/game.rb +0 -74
  66. data/lib/runtime/game_loader.rb +0 -132
  67. data/lib/runtime/library_loader.rb +0 -135
  68. data/lib/runtime/object.rb +0 -761
  69. data/lib/runtime/options.rb +0 -104
  70. data/lib/runtime/persistence.rb +0 -292
  71. data/lib/runtime/runtime.rb +0 -321
  72. data/lib/runtime/world_tree.rb +0 -69
  73. data/lib/runtime.rb +0 -35
@@ -0,0 +1,38 @@
1
+ # lib/story_teller/core.rb
2
+ # encoding: utf-8
3
+ # frozen_string_literal: false
4
+
5
+ # Copyright Nels Nelson 2008-2025 but freely usable (see license)
6
+ #
7
+ # This file is part of the StoryTeller.
8
+ #
9
+ # The StoryTeller is free software: you can redistribute it and/or
10
+ # modify it under the terms of the GNU General Public License as published
11
+ # by the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # The StoryTeller is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
21
+
22
+ require_relative 'builtins'
23
+ require_relative 'stdlib'
24
+ require_relative 'logging'
25
+ require_relative 'prototype'
26
+ require_relative 'command'
27
+ require_relative 'history'
28
+ require_relative 'events'
29
+ require_relative 'grammar_parser'
30
+ require_relative 'kernel'
31
+ require_relative 'mixins'
32
+ require_relative 'helpers'
33
+ require_relative 'io'
34
+ require_relative 'publication'
35
+ require_relative 'context'
36
+ require_relative 'world_tree'
37
+ require_relative 'library'
38
+ require_relative 'engine'
@@ -1,24 +1,23 @@
1
+ # src/lib/daemon.rb
1
2
  # encoding: utf-8
2
3
  # frozen_string_literal: false
3
4
 
4
- # Copyright Nels Nelson 2008-2023 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
6
  #
6
- # This file is part of the Inform Runtime.
7
+ # This file is part of the StoryTeller.
7
8
  #
8
- # The Inform Runtime is free software: you can redistribute it and/or
9
+ # The StoryTeller is free software: you can redistribute it and/or
9
10
  # modify it under the terms of the GNU General Public License as published
10
11
  # by the Free Software Foundation, either version 3 of the License, or
11
12
  # (at your option) any later version.
12
13
  #
13
- # The Inform Runtime is distributed in the hope that it will be useful,
14
+ # The StoryTeller is distributed in the hope that it will be useful,
14
15
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
16
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
17
  # GNU General Public License for more details.
17
18
  #
18
19
  # You should have received a copy of the GNU General Public License
19
- # along with the Inform Runtime. If not, see <http://www.gnu.org/licenses/>.
20
-
21
- require 'set'
20
+ # along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
22
21
 
23
22
  # In order to support atmospheric messages and NPC automation
24
23
  # based on timers, I'm trying to come up with an approach for
@@ -75,14 +74,14 @@ require 'set'
75
74
  # has switchable ~on;
76
75
  #
77
76
 
78
- # The Inform module
79
- module Inform
77
+ # The StoryTeller module
78
+ module StoryTeller
80
79
  def run_daemons
81
80
  return if defined?(TURN_BASED)
82
- Inform::Daemons.start
81
+ StoryTeller::Daemons.start
83
82
  end
84
83
 
85
- # The Inform::Daemons module
84
+ # The StoryTeller::Daemons module
86
85
  module Daemons
87
86
  def spawn
88
87
  @spawn ||= defined?(Java) ? java.util.concurrent.ConcurrentSkipListSet.new : Set.new
@@ -98,10 +97,10 @@ module Inform
98
97
  java.util.concurrent.Executors.newSingleThreadScheduledExecutor()
99
98
  end
100
99
 
101
- # The Inform::Daemons::Entheogen class encapsulates a heartbeat which
100
+ # The StoryTeller::Daemons::Entheogen class encapsulates a heartbeat which
102
101
  # is a ScheduledFuture created by the Heart executor and instantiated
103
- # when Inform::Daemons.start is executed.
104
- class Entheogen < Inform::System::Object
102
+ # when StoryTeller::Daemons.start is executed.
103
+ class Entheogen < Inform::Ephemeral::Object
105
104
  attr_accessor :heartbeat
106
105
  end
107
106
 
@@ -114,13 +113,13 @@ module Inform
114
113
  end
115
114
 
116
115
  def on?
117
- return false if Inform::Daemons.ghost.heartbeat.nil?
118
- Inform::Daemons.ghost.heartbeat.isCancelled() == false
116
+ return false if StoryTeller::Daemons.ghost.heartbeat.nil?
117
+ StoryTeller::Daemons.ghost.heartbeat.isCancelled() == false
119
118
  end
120
119
 
121
120
  def rescan
122
- Inform::Daemons.spawn.clear
123
- Inform::Daemons.scan_objects
121
+ StoryTeller::Daemons.spawn.clear
122
+ StoryTeller::Daemons.scan_objects
124
123
  end
125
124
 
126
125
  DaemonScanElapsedMessage = "Scanned %<daemons>s daemons in %<elapsed>0.2f milliseconds".freeze
@@ -138,32 +137,32 @@ module Inform
138
137
 
139
138
  # rubocop: disable Metrics/AbcSize
140
139
  def self.start
141
- initial_delay = Inform::Game.config[:daemon_initial_delay]
142
- period = Inform::Game.config[:daemons_period]
140
+ initial_delay = StoryTeller::Game.config[:daemon_initial_delay]
141
+ period = StoryTeller::Game.config[:daemons_period]
143
142
  unit = defined?(Java) ? java.util.concurrent.TimeUnit::MILLISECONDS : 'milliseconds'
144
143
  Thread.new do
145
- Inform::Daemons.rescan
144
+ StoryTeller::Daemons.rescan
146
145
  log.debug "Starting daemons..."
147
- daemons = Inform::Daemons.method(:daemons).to_proc
148
- Inform::Daemons.ghost.heartbeat = Inform::Daemons.heart.scheduleAtFixedRate(
146
+ daemons = StoryTeller::Daemons.method(:daemons).to_proc
147
+ StoryTeller::Daemons.ghost.heartbeat = StoryTeller::Daemons.heart.scheduleAtFixedRate(
149
148
  daemons, initial_delay, period, unit)
150
149
  end
151
150
  end
152
151
  # rubocop: enable Metrics/AbcSize
153
152
 
154
153
  def self.stop
155
- Inform::Daemons.ghost.heartbeat.cancel(false)
156
- Inform::Daemons.spawn.clear
154
+ StoryTeller::Daemons.ghost.heartbeat.cancel(false)
155
+ StoryTeller::Daemons.spawn.clear
157
156
  end
158
157
 
159
158
  DaemonExecutionElapsedMessage = "\e[1m\e[33mExecuted daemons in %<elapsed>0.2f milliseconds\e[39m\e[22m".freeze
160
159
 
161
160
  def self.daemons
162
161
  start = Time.ms
163
- Inform::Daemons.spawn.each do |daemon|
162
+ StoryTeller::Daemons.spawn.each do |daemon|
164
163
  # In realtime games, each_turn is a synonym for daemon
165
164
  next unless daemon.respond_to?(:daemon) || daemon.respond_to?(:each_turn)
166
- Inform::Daemons.execute daemon
165
+ StoryTeller::Daemons.execute daemon
167
166
  end
168
167
  ensure
169
168
  finish = Time.ms
@@ -185,7 +184,7 @@ module Inform
185
184
  # TODO: Use a pool of InformLibraries until
186
185
  # comprehensive event contexts can be implemented
187
186
  log.warn "Using singleton Ghost InformLibrary for #{obj} daemon"
188
- obj.inflib = Inform::Runtime.libraries[Inform::Daemons.ghost]
187
+ obj.inflib = StoryTeller::Engine.libraries[StoryTeller::Daemons.ghost]
189
188
  end
190
189
 
191
190
  # TODO: Potentially go ahead and print any string results
@@ -216,14 +215,14 @@ module Inform
216
215
  end
217
216
 
218
217
  def StartDaemon(obj)
219
- Inform::Daemons.spawn.add obj if obj.respond_to?(:daemon) || obj.respond_to?(:each_turn)
218
+ StoryTeller::Daemons.spawn.add obj if obj.respond_to?(:daemon) || obj.respond_to?(:each_turn)
220
219
  end
221
220
 
222
221
  def StopDaemon(obj)
223
222
  return if obj.nil?
224
223
  log.warn "Stopping daemon: #{obj}"
225
224
  obj.undef_method(:daemon) # TODO: Maybe don't do this
226
- Inform::Daemons.spawn.remove obj
225
+ StoryTeller::Daemons.spawn.remove obj
227
226
  end
228
227
 
229
228
  def StartTimer(obj, interval)
@@ -235,11 +234,11 @@ module Inform
235
234
  end
236
235
 
237
236
  def daemonize(event)
238
- Inform::Daemons.schedules[self] = event
237
+ StoryTeller::Daemons.schedules[self] = event
239
238
  end
240
239
 
241
240
  def daemonic?
242
- Inform::Daemons.schedules.include? self
241
+ StoryTeller::Daemons.schedules.include? self
243
242
  end
244
243
 
245
244
  def before_destroy
@@ -250,17 +249,17 @@ module Inform
250
249
 
251
250
  # rubocop: disable Metrics/AbcSize
252
251
  def occasionally(time = nil, &block)
253
- time = Inform::Game.config[:daemons_frequency_default] if time.nil?
252
+ time = StoryTeller::Game.config[:daemons_frequency_default] if time.nil?
254
253
  return if active? || daemonic?
255
254
  frequency = ((self.&:frequency) || time).to_i
256
255
  occasion = rand(frequency) + 1
257
256
  log.trace "Scheduling occasional daemonic event for #{self} in #{occasion} seconds"
258
- (Inform::Daemons.schedules[self] = delay(occasion, &block)).finally do
259
- Inform::Daemons.schedules.delete self
257
+ (StoryTeller::Daemons.schedules[self] = delay(occasion, &block)).finally do
258
+ StoryTeller::Daemons.schedules.delete self
260
259
  end
261
260
  end
262
261
  end
263
262
  # rubocop: enable Metrics/AbcSize
264
263
  # module Daemons
265
264
  end
266
- # module Inform
265
+ # module StoryTeller
@@ -0,0 +1,151 @@
1
+ # lib/story_teller/engine.rb
2
+ # encoding: utf-8
3
+ # frozen_string_literal: false
4
+
5
+ # Copyright Nels Nelson 2008-2025 but freely usable (see license)
6
+ #
7
+ # This file is part of the StoryTeller.
8
+ #
9
+ # The StoryTeller is free software: you can redistribute it and/or
10
+ # modify it under the terms of the GNU General Public License as published
11
+ # by the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # The StoryTeller is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
21
+
22
+ require_relative 'session'
23
+ require_relative 'io'
24
+ require_relative 'context'
25
+ require_relative 'library'
26
+ require_relative 'publication'
27
+
28
+ # The StoryTeller module
29
+ module StoryTeller
30
+ # The Engine module
31
+ module Engine
32
+ # The Library module
33
+ module Library
34
+ def play
35
+ log.debug "Using engine-managed InformLibrary play method override"
36
+ inform_library = StoryTeller::Engine.libraries[StoryTeller::Engine]
37
+ inform_library.play
38
+ inform_library
39
+ end
40
+ end
41
+
42
+ # The Config class
43
+ module Config
44
+ DEFAULTS = {
45
+ environment: 'default',
46
+ inform6lib_gem_code_prefix: 'inform',
47
+ language: 'English',
48
+ properties: 'player actor action action_to_be ' \
49
+ 'results parameters pattern ' \
50
+ 'noun second inp1 inp2 ' \
51
+ 'special_word special_number special_number1 special_number2 ' \
52
+ 'consult_words match_from wn verb_wordnum words ' \
53
+ 'parser_action parser_one parser_two scope_reason',
54
+ log_level: Logger::INFO
55
+ }.freeze
56
+ end
57
+
58
+ module_function
59
+
60
+ def libraries
61
+ @libraries ||= {}
62
+ end
63
+
64
+ def main_object=(obj)
65
+ @main_object = obj
66
+ end
67
+
68
+ def main_object
69
+ @main_object
70
+ end
71
+
72
+ def default_config
73
+ @default_config ||= StoryTeller::Engine::Config::DEFAULTS
74
+ end
75
+
76
+ def inform_code_prefix
77
+ StoryTeller::Engine.default_config[:inform6lib_gem_code_prefix]
78
+ end
79
+
80
+ def project_dir_path
81
+ @project_dir_path ||= begin
82
+ story_dir_path = File.expand_path(__dir__)
83
+ lib_dir_path = File.expand_path(File.dirname(story_dir_path))
84
+ File.expand_path(File.dirname(lib_dir_path))
85
+ end
86
+ end
87
+
88
+ def executable=(executable)
89
+ @executable = executable
90
+ end
91
+
92
+ def executable
93
+ @executable
94
+ end
95
+
96
+ def default_environment
97
+ StoryTeller::Engine.default_config[:environment]
98
+ end
99
+
100
+ def default_invocation_properties
101
+ StoryTeller::Engine.default_config.fetch(:properties, '').split.map(&:to_sym).freeze
102
+ end
103
+
104
+ def invocation_properties
105
+ @invocation_properties ||= default_invocation_properties
106
+ end
107
+
108
+ def invocation_properties=(properties)
109
+ @invocation_properties = properties
110
+ @invocation_context = nil
111
+ end
112
+
113
+ def invocation_context
114
+ @invocation_context ||= Struct.new(*invocation_properties)
115
+ end
116
+
117
+ def language_name
118
+ StoryTeller::Engine.default_config[:language]
119
+ end
120
+
121
+ def player?(obj)
122
+ return false unless defined?(StoryTeller::IO::Session) && StoryTeller::IO::Session.respond_to?(:players)
123
+ StoryTeller::IO::Session.players.include?(obj)
124
+ end
125
+
126
+ def prime_dictionary
127
+ Inform::Object.select_map(:name).compact.each do |n|
128
+ StoryTeller::Dictionary.merge(n.split(/[,\s]+/).grep_v(/[^a-z]/i).map(&:downcase).map(&:to_sym))
129
+ end
130
+ end
131
+ end
132
+ # module Engine
133
+
134
+ # The StoryTeller::Privileges module to implement privilege
135
+ module Privileges
136
+ def admin?
137
+ self.has?(:admin)
138
+ end
139
+
140
+ def builder?
141
+ admin? || self.has?(:builder)
142
+ end
143
+ end
144
+ end
145
+ # module StoryTeller
146
+
147
+ if defined?(ZCODE_ONLY)
148
+ # Simulate compiling with Z-code only compiler
149
+ WORDSIZE = (2**((0.size * 8) - 2) - 1)
150
+ end
151
+ # defined?(ZCODE_ONLY)
@@ -0,0 +1,42 @@
1
+ # lib/story_teller/ephemeral_adapter.rb
2
+ # encoding: utf-8
3
+ # frozen_string_literal: false
4
+
5
+ # Copyright Nels Nelson 2008-2025 but freely usable (see license)
6
+ #
7
+ # This file is part of StoryTeller.
8
+ #
9
+ # StoryTeller is free software: you can redistribute it and/or
10
+ # modify it under the terms of the GNU General Public License as published
11
+ # by the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # StoryTeller is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
21
+
22
+ # module StoryTeller
23
+ module StoryTeller
24
+ # module EphemeralAdapter
25
+ module EphemeralAdapter
26
+ Adapter = {
27
+ name: :ephemeral,
28
+ object_class: Inform::Ephemeral::Object,
29
+ tag_class: Inform::Ephemeral::Tag,
30
+ link_class: Inform::Ephemeral::Link,
31
+ module_class: Inform::Ephemeral::Module
32
+ }.freeze
33
+
34
+ module_function
35
+
36
+ def register!
37
+ StoryTeller::ModelAdapter.register!(Adapter)
38
+ end
39
+ end
40
+ end
41
+
42
+ StoryTeller::EphemeralAdapter.register!
@@ -1,22 +1,23 @@
1
+ # lib/story_teller/events.rb
1
2
  # encoding: utf-8
2
3
  # frozen_string_literal: false
3
4
 
4
- # Copyright Nels Nelson 2008-2023 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
6
  #
6
- # This file is part of the Inform Runtime.
7
+ # This file is part of StoryTeller.
7
8
  #
8
- # The Inform Runtime is free software: you can redistribute it and/or
9
+ # StoryTeller is free software: you can redistribute it and/or
9
10
  # modify it under the terms of the GNU General Public License as published
10
11
  # by the Free Software Foundation, either version 3 of the License, or
11
12
  # (at your option) any later version.
12
13
  #
13
- # The Inform Runtime is distributed in the hope that it will be useful,
14
+ # StoryTeller is distributed in the hope that it will be useful,
14
15
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
16
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
17
  # GNU General Public License for more details.
17
18
  #
18
19
  # You should have received a copy of the GNU General Public License
19
- # along with the Inform Runtime. If not, see <http://www.gnu.org/licenses/>.
20
+ # along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
20
21
 
21
22
  # The Time class
22
23
  class Time
@@ -480,13 +481,13 @@ module EventInitializationMethods
480
481
  def generate_identity
481
482
  s = format(EventCauseIdentityTemplate, identity: @cause.identity, name: @cause.name)
482
483
  if !@callstack.empty?
483
- trace = @callstack.first.gsub(Inform::Runtime.project_dir_path, '')
484
+ trace = @callstack.first.gsub(StoryTeller::Engine.project_dir_path, '')
484
485
  location, line_number, method_name = CallerPattern.match(trace)&.captures
485
486
  s << format(EventSourceFullTemplate,
486
487
  method_name: method_name, source_location: location, source_line_number: line_number)
487
488
  elsif @activity.respond_to?(:source_location) || @activity.is_a?(Proc)
488
489
  activity_source_location_enumerator = @activity.source_location.each
489
- source_location = activity_source_location_enumerator.next.gsub(Inform::Runtime.project_dir_path, '')
490
+ source_location = activity_source_location_enumerator.next.gsub(StoryTeller::Engine.project_dir_path, '')
490
491
  source_line_number = activity_source_location_enumerator.next
491
492
  s << format(
492
493
  EventSourceTemplate, source_location: source_location, source_line_number: source_line_number)
@@ -536,8 +537,6 @@ module Inform
536
537
  invoke(self)
537
538
  end
538
539
 
539
- private
540
-
541
540
  include EventInitializationMethods
542
541
  end
543
542
 
@@ -1,22 +1,23 @@
1
+ # lib/story_teller/experimental/handler_dsl.rb
1
2
  # encoding: utf-8
2
3
  # frozen_string_literal: false
3
4
 
4
- # Copyright Nels Nelson 2008-2023 but freely usable (see license)
5
+ # Copyright Nels Nelson 2008-2025 but freely usable (see license)
5
6
  #
6
- # This file is part of the Inform Runtime.
7
+ # This file is part of the StoryTeller.
7
8
  #
8
- # The Inform Runtime is free software: you can redistribute it and/or
9
+ # The StoryTeller is free software: you can redistribute it and/or
9
10
  # modify it under the terms of the GNU General Public License as published
10
11
  # by the Free Software Foundation, either version 3 of the License, or
11
12
  # (at your option) any later version.
12
13
  #
13
- # The Inform Runtime is distributed in the hope that it will be useful,
14
+ # The StoryTeller is distributed in the hope that it will be useful,
14
15
  # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
16
  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
17
  # GNU General Public License for more details.
17
18
  #
18
19
  # You should have received a copy of the GNU General Public License
19
- # along with the Inform Runtime. If not, see <http://www.gnu.org/licenses/>.
20
+ # along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
20
21
 
21
22
  # The Inform module
22
23
  module Inform
@@ -37,7 +38,7 @@ module Inform
37
38
 
38
39
  # The Inform::Behavior module
39
40
  module Behavior
40
- Registry = Class.new(Hash)
41
+ class Registry < Hash; end
41
42
  REGISTRY = Registry.new
42
43
 
43
44
  def self.key_for(obj)
@@ -126,18 +127,6 @@ module Inform
126
127
 
127
128
  # The BuilderInstanceMethods module
128
129
  module BuilderInstanceMethods
129
- # Unknown method with a block => define it on behavior.
130
- # def method_missing(method_name, *args, &block)
131
- # return @target.public_send(method_name, *args) if block.nil?
132
- # local_context = @context
133
- # @behavior.send(:define_method, method_name) do |*call_args, &_block|
134
- # instance_exec(local_context, *call_args, &block)
135
- # end
136
- # method_name
137
- # rescue NoMethodError
138
- # super
139
- # end
140
-
141
130
  def method_missing(method_name, *args, &block)
142
131
  # 1) Try the real receiver first (even when a block is present)
143
132
  log.debug "@target: #{@target.inspect}"
@@ -0,0 +1,37 @@
1
+ # lib/story_teller/experimental/reverse_engineer_class.rb
2
+ # encoding: utf-8
3
+ # frozen_string_literal: false
4
+
5
+ # Copyright Nels Nelson 2008-2025 but freely usable (see license)
6
+ #
7
+ # This file is part of StoryTeller.
8
+ #
9
+ # StoryTeller is free software: you can redistribute it and/or
10
+ # modify it under the terms of the GNU General Public License as published
11
+ # by the Free Software Foundation, either version 3 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # StoryTeller is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU General Public License
20
+ # along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
21
+
22
+ # The ReverseEngineerClass module
23
+ module ReverseEngineerClass
24
+ def singleton_object_to_class(object, superclass = Object)
25
+ source = object.singleton_class
26
+
27
+ Class.new(superclass) do
28
+ source.instance_methods(false).each do |method_name|
29
+ define_method(method_name, source.instance_method(method_name))
30
+ end
31
+ end
32
+ end
33
+
34
+ old_library = InformLibrary
35
+ Object.send(:remove_const, :InformLibrary)
36
+ InformLibrary = singleton_object_to_class(old_library, Inform::Ephemeral::Object)
37
+ end