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
@@ -1,132 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: false
3
-
4
- # Copyright Nels Nelson 2008-2023 but freely usable (see license)
5
- #
6
- # This file is part of the Inform Runtime.
7
- #
8
- # The Inform Runtime is free software: you can redistribute it and/or
9
- # modify it under the terms of the GNU General Public License as published
10
- # by the Free Software Foundation, either version 3 of the License, or
11
- # (at your option) any later version.
12
- #
13
- # The Inform Runtime is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # 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
- # The Inform module
22
- module Inform
23
- # The Game module
24
- module Game
25
- class GameLoadError < StandardError; end
26
-
27
- # The Game::Loader module loads a game from a given directory.
28
- module Loader
29
- def load_game(game_dir_path = Inform::Game.config[:game_path])
30
- self.load_path = game_dir_path
31
- require_relative 'world_tree'
32
- load_game_subcomponents
33
- load_game_files
34
- load_grammars
35
- reset_constants
36
- load_library
37
- rescue StandardError => e
38
- handle_load_failure(e)
39
- end
40
-
41
- def first_orphan_object_with_description_that_has_light
42
- Inform::Object.all.find { |o| !o.description.nil? && o.has?(:light) }&.name
43
- end
44
-
45
- def load_path=(path)
46
- @game_dir_path = path
47
- $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
48
- end
49
-
50
- def load_game_subcomponents
51
- game_components.each { |component| load_game_sub(component) }
52
- end
53
-
54
- def reset_constants
55
- reset_constant(:HDR_GAMESERIAL, defined?(Serial) ? Serial : File.mtime(@game_dir_path).strftime('%y%m%d'))
56
- reset_constant(:HDR_GAMERELEASE, defined?(Release) ? Release : 0)
57
- end
58
-
59
- def load_game_sub(component, start = Time.now)
60
- game_component_path = File.join(@game_dir_path, component.to_s)
61
- Dir.glob(File.join(game_component_path, '*')).sort.each do |file|
62
- next unless File.file?(file)
63
- log.debug "Loading file: #{file}"
64
- require file
65
- end
66
- ensure
67
- elapsed = (Time.now - start) * 1000
68
- log.debug format("Loaded #{component} in %0.2f milliseconds", elapsed)
69
- end
70
-
71
- def load_game_files(game_path = @game_dir_path)
72
- log.info "Loading game: #{game_path}"
73
- Dir.glob(File.join(game_path, '*.rb')).sort.each do |file|
74
- next unless File.file?(file)
75
- log.debug "Loading file: #{file}"
76
- require file
77
- end
78
- end
79
-
80
- def handle_load_failure(e)
81
- case e.message
82
- when /PG::UndefinedTable/
83
- log.error "Fatal: Database initialization is required"
84
- abort
85
- else
86
- log.error "Error loading game: #{e.class.name}: #{e.message}"
87
- e.backtrace.each { |t| log.error t }
88
- end
89
- end
90
-
91
- # Move to the front of the list any element matching the given condition
92
- def prioritize_if(list, &condition)
93
- element = list.find(&condition)
94
- return list if element.nil?
95
- list.unshift(list.delete(element))
96
- end
97
-
98
- EnsureFirst = [/emotes.inf/, /grammar.inf/].freeze
99
-
100
- def grammar_files
101
- files = Dir.glob(File.join(grammar_module_path, '*'))
102
- EnsureFirst.each do |pattern|
103
- prioritize_if(files) { |file_path| file_path.match?(pattern) }
104
- end
105
- files
106
- end
107
-
108
- GrammarParsedInfoMessage = 'Parsed grammar %<file>s in %0.2<elapsed>f milliseconds'.freeze
109
-
110
- def load_grammars
111
- grammar_files.each do |file_path|
112
- start = Time.now
113
- Inform.load_grammar_by_path(file_path)
114
- elapsed = (Time.now - start) * 1000
115
- log.debug format(GrammarParsedInfoMessage, file: File.basename(file_path), elapsed: elapsed)
116
- end
117
- end
118
-
119
- def load_game_states
120
- states = Inform::Game.config.fetch(:additional_promiscuous_states, []).map(&:to_sym)
121
- Session.add_promiscuous_states(states)
122
- end
123
-
124
- def reload_game
125
- load_game
126
- end
127
- end
128
- # module Loader
129
- end
130
- # module Game
131
- end
132
- # module Inform
@@ -1,135 +0,0 @@
1
- # encoding: utf-8
2
- # frozen_string_literal: false
3
-
4
- # Copyright Nels Nelson 2008-2023 but freely usable (see license)
5
- #
6
- # This file is part of the Inform Runtime.
7
- #
8
- # The Inform Runtime is free software: you can redistribute it and/or
9
- # modify it under the terms of the GNU General Public License as published
10
- # by the Free Software Foundation, either version 3 of the License, or
11
- # (at your option) any later version.
12
- #
13
- # The Inform Runtime is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # 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'
22
-
23
- # The Inform module
24
- module Inform
25
- # The Inform::Library module
26
- module Library
27
- GEM_NAME = 'inform6lib'.freeze
28
- GEM_PATH = Gem.loaded_specs[GEM_NAME]&.full_gem_path or raise "The #{GEM_NAME} gem is required"
29
-
30
- DeclaredProperties = Struct.new(:memo).new({})
31
- DeclaredAttributes = Struct.new(:memo).new(Set.new)
32
- DeclaredGlobals = Struct.new(:memo).new([])
33
- class LibraryLoadError < StandardError; end
34
-
35
- def self.inform_gem_lib_path
36
- @inform_gem_lib_path ||= File.expand_path(File.join(Inform::Library::GEM_PATH, 'lib'))
37
- end
38
-
39
- # The Library::Loader module provides methods for loading Library files.
40
- module Loader
41
- def load_library
42
- overrides
43
- end
44
-
45
- def overrides
46
- InformLibrary.extend(Inform::RuntimeLibrary)
47
- manage_inform_library
48
- end
49
- end
50
-
51
- # The Inform::Library::ClassMethods module
52
- module ClassMethods
53
- def Link(link)
54
- # TODO: Implement
55
- # Not a priority, because in the original Inform6 links were
56
- # effectively just pointers to objects loaded in memory, and
57
- # weren't persisted using a database relation.
58
- end
59
-
60
- InclusionGrammarGuessTemplate = '%<inclusion>s.h.inf.rb'.freeze
61
- InclusionGuessesTemplate = '%<inclusion>s.h'.freeze
62
-
63
- def Include(inclusion)
64
- inclusion = Inform::Runtime.language_name if /^language__$/.match(inclusion)
65
- grammar_guess = format(InclusionGrammarGuessTemplate, inclusion: inclusion)
66
- guess = File.expand_path(
67
- File.join(
68
- Inform::Library.inform_gem_lib_path,
69
- Inform::Runtime.inform_dir_path,
70
- grammar_guess))
71
- return Inform.load_grammar_by_path(guess) if File.exist?(guess)
72
- require_first_existing(format(InclusionGuessesTemplate, inclusion: inclusion).split)
73
- end
74
-
75
- # rubocop: disable Metrics/AbcSize
76
- # rubocop: disable Metrics/MethodLength
77
- def require_first_existing(guesses)
78
- guessed_file_path = File.join(Inform::Runtime.inform_dir_path, guesses.shift)
79
- guessed_local_file_path = File.expand_path(guessed_file_path)
80
- if File.exist?(guessed_local_file_path)
81
- log.debug "Loading local library file: #{guessed_local_file_path}"
82
- require_relative guessed_local_file_path
83
- else
84
- log.debug "Loading library: #{guessed_local_file_path}"
85
- require guessed_file_path
86
- end
87
- rescue LoadError, StandardError => e
88
- log.warn e.message
89
- e.backtrace.each { |t| log.warn t } if defined?(Logging)
90
- retry unless guesses.empty?
91
- end
92
- # rubocop: enable Metrics/AbcSize
93
- # rubocop: enable Metrics/MethodLength
94
-
95
- def Attribute(attribute)
96
- DeclaredAttributes.memo << attribute
97
- end
98
-
99
- def declare_property(property, value, _modifier = nil)
100
- DeclaredProperties.memo[property] ||= []
101
- DeclaredProperties.memo[property] << value
102
- end
103
-
104
- PropertyModifiers = %i[additive].freeze
105
- def Property(*args)
106
- if PropertyModifiers.include?(modifier_or_property = args.shift)
107
- declare_property(args.shift, args.shift, modifier_or_property)
108
- else
109
- declare_property(modifier_or_property, args.shift)
110
- end
111
- end
112
-
113
- def Default(property, value)
114
- Constant(property, value)
115
- end
116
-
117
- def Constant(constant, value, target = ::Object)
118
- return if constant.nil?
119
- silence_warnings do
120
- target.instance_eval { const_set(constant.to_sym, value) }
121
- end
122
- rescue StandardError => e
123
- log.error "Unexpected error resetting constant #{constant}", e
124
- nil
125
- end
126
-
127
- def import_global(symbol)
128
- DeclaredGlobals.memo << symbol
129
- end
130
- end
131
- # module ClassMethods
132
- end
133
- # module Library
134
- end
135
- # module Inform