inform-runtime 1.2.3 → 1.3.1
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.
- checksums.yaml +4 -4
- data/README.md +33 -41
- data/lib/story_teller/articles.rb +2 -1
- data/lib/story_teller/builtins.rb +63 -10
- data/lib/story_teller/color.rb +2 -1
- data/lib/story_teller/command.rb +2 -1
- data/lib/story_teller/context.rb +23 -27
- data/lib/story_teller/daemon.rb +2 -2
- data/lib/story_teller/engine.rb +45 -10
- data/lib/story_teller/events.rb +1 -1
- data/lib/story_teller/experimental/handler_dsl.rb +1 -16
- data/lib/story_teller/experimental/reverse_engineer_class.rb +1 -1
- data/lib/story_teller/grammar_parser.rb +60 -13
- data/lib/story_teller/helpers.rb +8 -4
- data/lib/story_teller/history.rb +1 -1
- data/lib/story_teller/inflector.rb +4 -2
- data/lib/story_teller/inform/ephemeral/link.rb +63 -31
- data/lib/story_teller/inform/ephemeral/module.rb +6 -5
- data/lib/story_teller/inform/ephemeral/object.rb +223 -236
- data/lib/story_teller/inform/ephemeral/tag.rb +27 -14
- data/lib/story_teller/io.rb +99 -49
- data/lib/story_teller/kernel.rb +2 -2
- data/lib/story_teller/library/bootstrap.rb +2 -2
- data/lib/story_teller/library/declarations.rb +1 -1
- data/lib/story_teller/library/directives.rb +1 -1
- data/lib/story_teller/library/loader.rb +3 -20
- data/lib/story_teller/library/location.rb +9 -3
- data/lib/story_teller/library.rb +1 -1
- data/lib/story_teller/logging.rb +1 -1
- data/lib/story_teller/mixins.rb +11 -4
- data/lib/story_teller/plurals.rb +2 -1
- data/lib/story_teller/privileges.rb +89 -6
- data/lib/story_teller/prototype.rb +150 -32
- data/lib/story_teller/publication.rb +2 -1
- data/lib/story_teller/session.rb +115 -25
- data/lib/story_teller/stdlib.rb +231 -1
- data/lib/story_teller/subscription.rb +2 -1
- data/lib/story_teller/tree.rb +2 -1
- data/lib/story_teller/version.rb +2 -2
- data/lib/story_teller/world_tree.rb +21 -23
- data/lib/story_teller.rb +18 -5
- metadata +6 -10
- data/lib/story_teller/core.rb +0 -39
- data/lib/story_teller/ephemeral_adapter.rb +0 -40
- data/lib/story_teller/inform/base.rb +0 -160
- data/lib/story_teller/model_adapter.rb +0 -132
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1a9737a28a03ce80dd3698d1fc2824b22cb3090d4f0db6c3b52c84134e17a04c
|
|
4
|
+
data.tar.gz: 30ea465986dd84a628280ffa63c83228e04689db657d26c1bf449a15a779165a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f0f82b48842ed1cb74515abf3e26d2aeadc1c29004177a556e819ff814c3ce7ee63cf8b4225f5a53a3bfa8102c6bfa2ad0a21ad4b2654518269535c9fc3eca0f
|
|
7
|
+
data.tar.gz: e6122d69fc1a5fbbe2640709f567889a7d70d303740796883bec8ffb3001abd243b91597c02f12a7d31e9aac61de7e08b288cd648c9f784140e935279a2fb085
|
data/README.md
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
# StoryTeller
|
|
1
|
+
# StoryTeller Engine
|
|
2
2
|
|
|
3
3
|
[](license-gpl)
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
**StoryTeller** is a runtime layer for use by software programs used to
|
|
5
|
+
**StoryTeller Engine** is a runtime layer for use by software programs used to
|
|
8
6
|
play interactive-fiction games which are built for the [Inform 6 Ruby Port].
|
|
9
7
|
|
|
10
|
-
StoryTeller is intended to simply provide the barest minimum
|
|
11
|
-
required by the Inform 6 Library Ruby Port software to function
|
|
12
|
-
context of a game play specified by a game directory or file. It
|
|
13
|
-
attempt to replicate a byte code interpreter runtime like frotz.
|
|
8
|
+
The StoryTeller Engine is intended to simply provide the barest minimum
|
|
9
|
+
facilities required by the Inform 6 Library Ruby Port software to function
|
|
10
|
+
in the context of a game play specified by a game directory or file. It
|
|
11
|
+
does not attempt to replicate a byte code interpreter runtime like frotz.
|
|
14
12
|
|
|
15
13
|
|
|
16
14
|
## Install mise-en-place
|
|
@@ -97,81 +95,75 @@ bundle exec rake test
|
|
|
97
95
|
Here is a bird's-eye view of the project layout.
|
|
98
96
|
|
|
99
97
|
```sh
|
|
100
|
-
# date && tree -A -I "game|logs|vendor|tmp|Gemfile.lock"
|
|
101
|
-
|
|
98
|
+
# $ date && tree -A -I "coverage|game|logs|vendor|tmp|Gemfile.lock"
|
|
99
|
+
Sun May 10 09:36:13 CDT 2026
|
|
102
100
|
.
|
|
103
|
-
├── config
|
|
104
|
-
│ └── database.yml
|
|
105
101
|
├── CONTRIBUTING.md
|
|
106
|
-
├── exe
|
|
107
|
-
│ └── inform.rb
|
|
108
102
|
├── Gemfile
|
|
103
|
+
├── inform-runtime-1.2.3.gem
|
|
109
104
|
├── inform-runtime.gemspec
|
|
110
105
|
├── lib
|
|
111
|
-
│ ├──
|
|
106
|
+
│ ├── story_teller
|
|
112
107
|
│ │ ├── articles.rb
|
|
113
108
|
│ │ ├── builtins.rb
|
|
114
109
|
│ │ ├── color.rb
|
|
115
110
|
│ │ ├── command.rb
|
|
116
|
-
│ │ ├── config.rb
|
|
117
111
|
│ │ ├── context.rb
|
|
118
112
|
│ │ ├── daemon.rb
|
|
119
|
-
│ │ ├──
|
|
113
|
+
│ │ ├── engine.rb
|
|
120
114
|
│ │ ├── events.rb
|
|
121
115
|
│ │ ├── experimental
|
|
122
|
-
│ │ │
|
|
123
|
-
│ │
|
|
124
|
-
│ │ ├── game.rb
|
|
116
|
+
│ │ │ ├── handler_dsl.rb
|
|
117
|
+
│ │ │ └── reverse_engineer_class.rb
|
|
125
118
|
│ │ ├── grammar_parser.rb
|
|
126
119
|
│ │ ├── helpers.rb
|
|
127
120
|
│ │ ├── history.rb
|
|
128
121
|
│ │ ├── inflector.rb
|
|
122
|
+
│ │ ├── inform
|
|
123
|
+
│ │ │ ├── ephemeral
|
|
124
|
+
│ │ │ │ ├── link.rb
|
|
125
|
+
│ │ │ │ ├── module.rb
|
|
126
|
+
│ │ │ │ ├── object.rb
|
|
127
|
+
│ │ │ │ └── tag.rb
|
|
128
|
+
│ │ │ └── models.rb
|
|
129
129
|
│ │ ├── io.rb
|
|
130
130
|
│ │ ├── kernel.rb
|
|
131
|
-
│ │ ├──
|
|
131
|
+
│ │ ├── library
|
|
132
|
+
│ │ │ ├── bootstrap.rb
|
|
133
|
+
│ │ │ ├── declarations.rb
|
|
134
|
+
│ │ │ ├── directives.rb
|
|
135
|
+
│ │ │ ├── loader.rb
|
|
136
|
+
│ │ │ └── location.rb
|
|
132
137
|
│ │ ├── library.rb
|
|
133
|
-
│ │ ├── link.rb
|
|
134
138
|
│ │ ├── logging.rb
|
|
135
139
|
│ │ ├── mixins.rb
|
|
136
|
-
│ │ ├── module.rb
|
|
137
|
-
│ │ ├── object.rb
|
|
138
|
-
│ │ ├── options.rb
|
|
139
|
-
│ │ ├── persistence.rb
|
|
140
140
|
│ │ ├── plurals.rb
|
|
141
|
+
│ │ ├── privileges.rb
|
|
141
142
|
│ │ ├── prototype.rb
|
|
142
143
|
│ │ ├── publication.rb
|
|
143
|
-
│ │ ├── runtime.rb
|
|
144
144
|
│ │ ├── session.rb
|
|
145
|
-
│ │ ├── snapshots.rb
|
|
146
145
|
│ │ ├── stdlib.rb
|
|
147
146
|
│ │ ├── subscription.rb
|
|
148
|
-
│ │ ├── tag.rb
|
|
149
147
|
│ │ ├── tree.rb
|
|
150
148
|
│ │ ├── version.rb
|
|
151
149
|
│ │ └── world_tree.rb
|
|
152
|
-
│ └──
|
|
150
|
+
│ └── story_teller.rb
|
|
153
151
|
├── LICENSE
|
|
154
152
|
├── Rakefile
|
|
155
153
|
├── README.md
|
|
156
154
|
├── roller2.jpg
|
|
157
|
-
├── scripts
|
|
158
|
-
│ ├── backup.rb
|
|
159
|
-
│ ├── clone.rb
|
|
160
|
-
│ ├── delete.rb
|
|
161
|
-
│ ├── init.rb
|
|
162
|
-
│ ├── rebuild.rb
|
|
163
|
-
│ └── restore.rb
|
|
164
155
|
└── spec
|
|
165
|
-
├──
|
|
156
|
+
├── engine_spec.rb
|
|
157
|
+
├── inform_ephemeral_spec.rb
|
|
166
158
|
├── inform_spec.rb
|
|
167
|
-
├── inform_system_spec.rb
|
|
168
|
-
├── object_spec.rb
|
|
169
159
|
├── parser_spec.rb
|
|
160
|
+
├── prototype_spec.rb
|
|
170
161
|
├── spec_helper.rb
|
|
162
|
+
├── stdlib_spec.rb
|
|
171
163
|
├── verblib_spec.rb
|
|
172
164
|
└── verify_gem_spec.rb
|
|
173
165
|
|
|
174
|
-
|
|
166
|
+
8 directories, 57 files
|
|
175
167
|
```
|
|
176
168
|
|
|
177
169
|
Thanks!
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# lib/story_teller/articles.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
5
6
|
#
|
|
6
7
|
# This file is part of the StoryTeller.
|
|
7
8
|
#
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
# frozen_string_literal: false
|
|
4
4
|
|
|
5
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
6
6
|
#
|
|
7
7
|
# This file is part of the StoryTeller.
|
|
8
8
|
#
|
|
@@ -165,25 +165,78 @@ module Builtins
|
|
|
165
165
|
|
|
166
166
|
def objectloop(*_args, &block)
|
|
167
167
|
if self.is_a?(InformLibrary)
|
|
168
|
-
|
|
169
|
-
object_class&.all&.each { |o| block.call(o) }
|
|
168
|
+
inform_object_collection.each { |object| block.call(object) }
|
|
170
169
|
elsif self.respond_to?(:descendants)
|
|
171
|
-
self.descendants.each { |
|
|
170
|
+
self.descendants.each { |object| block.call(object) }
|
|
172
171
|
end
|
|
173
172
|
end
|
|
174
173
|
|
|
175
174
|
def getobject(id)
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
175
|
+
object = inform_object_fetch(id)
|
|
176
|
+
object.refresh if object.respond_to?(:refresh)
|
|
177
|
+
object
|
|
179
178
|
rescue StandardError
|
|
180
179
|
raise NoSuchObject
|
|
181
180
|
end
|
|
182
181
|
|
|
182
|
+
# rubocop: disable Metrics/AbcSize
|
|
183
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
|
184
|
+
# rubocop: disable Metrics/MethodLength
|
|
183
185
|
def findobject(*args, &block)
|
|
184
|
-
object_class =
|
|
185
|
-
|
|
186
|
-
object_class
|
|
186
|
+
object_class = inform_object_class
|
|
187
|
+
|
|
188
|
+
if sequel_model?(object_class)
|
|
189
|
+
return object_class.dataset.order(:name, :id).grep(:name, *args).to_a if args.first.is_a?(Regexp)
|
|
190
|
+
|
|
191
|
+
return object_class.dataset.grep(&block).to_a
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
objects = inform_object_collection
|
|
195
|
+
if args.first.is_a?(Regexp)
|
|
196
|
+
return objects.select do |object|
|
|
197
|
+
object_name_matches?(object, args.first)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
block.nil? ? objects : objects.select(&block)
|
|
202
|
+
end
|
|
203
|
+
# rubocop: enable Metrics/AbcSize
|
|
204
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
|
205
|
+
# rubocop: enable Metrics/MethodLength
|
|
206
|
+
|
|
207
|
+
def inform_object_class
|
|
208
|
+
if defined?(Inform::Object) && sequel_model?(Inform::Object)
|
|
209
|
+
Inform::Object
|
|
210
|
+
elsif defined?(Inform::Ephemeral::Object)
|
|
211
|
+
Inform::Ephemeral::Object
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def sequel_model?(object_class)
|
|
216
|
+
!object_class.nil? && object_class.respond_to?(:dataset)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def inform_object_collection
|
|
220
|
+
object_class = inform_object_class
|
|
221
|
+
return Array::Empty if object_class.nil?
|
|
222
|
+
return object_class.all if object_class.respond_to?(:all)
|
|
223
|
+
|
|
224
|
+
Array::Empty
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def inform_object_fetch(id)
|
|
228
|
+
object_class = inform_object_class
|
|
229
|
+
raise NoSuchObject if object_class.nil?
|
|
230
|
+
|
|
231
|
+
object = object_class[id] if object_class.respond_to?(:[])
|
|
232
|
+
raise NoSuchObject if object.nil?
|
|
233
|
+
|
|
234
|
+
object
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def object_name_matches?(object, pattern)
|
|
238
|
+
name = object.name if object.respond_to?(:name)
|
|
239
|
+
Array(name).any? { |part| part.to_s.match?(pattern) } || name.to_s.match?(pattern)
|
|
187
240
|
end
|
|
188
241
|
|
|
189
242
|
def deadflag; @deadflag; end
|
data/lib/story_teller/color.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# lib/story_teller/color.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
5
6
|
#
|
|
6
7
|
# This file is part of the StoryTeller.
|
|
7
8
|
#
|
data/lib/story_teller/command.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# lib/story_teller/command.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
5
6
|
#
|
|
6
7
|
# This file is part of the StoryTeller.
|
|
7
8
|
#
|
data/lib/story_teller/context.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
# frozen_string_literal: false
|
|
4
4
|
|
|
5
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
6
6
|
#
|
|
7
7
|
# This file is part of the StoryTeller.
|
|
8
8
|
#
|
|
@@ -34,42 +34,38 @@ end
|
|
|
34
34
|
module Inform
|
|
35
35
|
# Define Context module
|
|
36
36
|
module Context
|
|
37
|
-
module_function
|
|
38
|
-
|
|
39
37
|
@definition = nil
|
|
40
38
|
|
|
41
|
-
def definition
|
|
42
|
-
@definition
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
alias get definition
|
|
46
|
-
|
|
47
39
|
AttributeFieldReferenceTemplate = '@%<attribute>s'.freeze
|
|
40
|
+
AttributeSetterMethodTemplate = '%<attribute>s='.freeze
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
end
|
|
42
|
+
class << self
|
|
43
|
+
attr_reader :definition
|
|
44
|
+
alias get definition
|
|
53
45
|
|
|
54
|
-
|
|
46
|
+
def get_value(from, attribute)
|
|
47
|
+
return from.send(attribute) if from.respond_to?(attribute)
|
|
48
|
+
from.instance_variable_get(format(AttributeFieldReferenceTemplate, attribute: attribute).to_sym)
|
|
49
|
+
end
|
|
55
50
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
51
|
+
def setter_method(attribute)
|
|
52
|
+
format(AttributeSetterMethodTemplate, attribute: attribute).to_sym
|
|
53
|
+
end
|
|
59
54
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
def each_attribute(obj)
|
|
56
|
+
@definition&.members&.each do |attribute|
|
|
57
|
+
yield(attribute, get_value(obj, attribute))
|
|
58
|
+
end
|
|
63
59
|
end
|
|
64
|
-
end
|
|
65
60
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
def set(definition)
|
|
62
|
+
@definition = definition
|
|
63
|
+
@definition&.members&.each do |attribute|
|
|
64
|
+
StoryTeller::Command.send(:attr_accessor, attribute) unless StoryTeller::Command.respond_to? attribute
|
|
65
|
+
Inform::Event.send(:attr_accessor, attribute) unless Inform::Event.respond_to? attribute
|
|
66
|
+
end
|
|
67
|
+
@definition
|
|
71
68
|
end
|
|
72
|
-
@definition
|
|
73
69
|
end
|
|
74
70
|
end
|
|
75
71
|
# module Context
|
data/lib/story_teller/daemon.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# lib/story_teller/daemon.rb
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
# frozen_string_literal: false
|
|
4
4
|
|
|
5
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
6
6
|
#
|
|
7
7
|
# This file is part of the StoryTeller.
|
|
8
8
|
#
|
data/lib/story_teller/engine.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
# frozen_string_literal: false
|
|
4
4
|
|
|
5
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
6
6
|
#
|
|
7
7
|
# This file is part of the StoryTeller.
|
|
8
8
|
#
|
|
@@ -33,9 +33,7 @@ module StoryTeller
|
|
|
33
33
|
module Library
|
|
34
34
|
def play
|
|
35
35
|
log.debug "Using engine-managed InformLibrary play method override"
|
|
36
|
-
|
|
37
|
-
inform_library.play
|
|
38
|
-
inform_library
|
|
36
|
+
StoryTeller::Engine.library.tap(&:play)
|
|
39
37
|
end
|
|
40
38
|
end
|
|
41
39
|
|
|
@@ -45,6 +43,7 @@ module StoryTeller
|
|
|
45
43
|
environment: 'default',
|
|
46
44
|
inform6lib_gem_code_prefix: 'inform',
|
|
47
45
|
language: 'English',
|
|
46
|
+
persist_player_location: false,
|
|
48
47
|
properties: 'player actor action action_to_be ' \
|
|
49
48
|
'results parameters pattern ' \
|
|
50
49
|
'noun second inp1 inp2 ' \
|
|
@@ -61,11 +60,42 @@ module StoryTeller
|
|
|
61
60
|
@libraries ||= {}
|
|
62
61
|
end
|
|
63
62
|
|
|
64
|
-
def
|
|
65
|
-
|
|
63
|
+
def persist_player_location?
|
|
64
|
+
return @persist_player_location unless @persist_player_location.nil?
|
|
65
|
+
|
|
66
|
+
default_config.fetch(:persist_player_location, false)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def persist_player_location=(value)
|
|
70
|
+
@persist_player_location = value
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def player_object
|
|
74
|
+
@player_object || parser_selfobj
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def player_object=(object)
|
|
78
|
+
raise ManagedLibraryError, "player object is nil" if object.nil?
|
|
79
|
+
|
|
80
|
+
@player_object = object
|
|
81
|
+
replace_parser_selfobj(object)
|
|
82
|
+
libraries.clear
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def library(selfobj = player_object)
|
|
66
86
|
return libraries[selfobj] if !selfobj.nil? && libraries.key?(selfobj)
|
|
67
87
|
|
|
68
|
-
|
|
88
|
+
inflib = InformLibrary.new.tap { |inflib| inflib.selfobj = selfobj }
|
|
89
|
+
bind_managed_library(inflib)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def replace_parser_selfobj(object)
|
|
93
|
+
return object unless defined?(Inform::Parser)
|
|
94
|
+
|
|
95
|
+
Inform::Parser.send(:remove_const, :SelfObj) if Inform::Parser.const_defined?(:SelfObj, false)
|
|
96
|
+
Inform::Parser.const_set(:SelfObj, object)
|
|
97
|
+
|
|
98
|
+
object
|
|
69
99
|
end
|
|
70
100
|
|
|
71
101
|
def bind_managed_library(inform_library)
|
|
@@ -77,12 +107,14 @@ module StoryTeller
|
|
|
77
107
|
libraries[selfobj] = inform_library
|
|
78
108
|
selfobj.inflib = inform_library if selfobj.respond_to?(:inflib=)
|
|
79
109
|
|
|
80
|
-
|
|
110
|
+
ensure_player_location(inform_library) if persist_player_location?
|
|
81
111
|
|
|
82
112
|
inform_library
|
|
83
113
|
end
|
|
84
114
|
|
|
85
|
-
|
|
115
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
|
116
|
+
def ensure_player_location(inflib)
|
|
117
|
+
return unless persist_player_location?
|
|
86
118
|
return if inflib.nil?
|
|
87
119
|
|
|
88
120
|
existing_location = inflib.instance_variable_get(:@location)
|
|
@@ -94,6 +126,7 @@ module StoryTeller
|
|
|
94
126
|
|
|
95
127
|
inflib.instance_variable_set(:@location, location) unless location.nil?
|
|
96
128
|
end
|
|
129
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
|
97
130
|
|
|
98
131
|
def parser_selfobj
|
|
99
132
|
return nil unless defined?(Inform::Parser::SelfObj)
|
|
@@ -165,7 +198,9 @@ module StoryTeller
|
|
|
165
198
|
|
|
166
199
|
def prime_dictionary
|
|
167
200
|
Inform::Object.select_map(:name).compact.each do |n|
|
|
168
|
-
|
|
201
|
+
Array(n).join(' ').split(/[,\s]+/).grep_v(/[^a-z]/i).map(&:downcase).map(&:to_sym).each do |word|
|
|
202
|
+
StoryTeller::Dictionary.merge([word])
|
|
203
|
+
end
|
|
169
204
|
end
|
|
170
205
|
end
|
|
171
206
|
end
|
data/lib/story_teller/events.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
# frozen_string_literal: false
|
|
4
4
|
|
|
5
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
6
6
|
#
|
|
7
7
|
# This file is part of the StoryTeller.
|
|
8
8
|
#
|
|
@@ -21,21 +21,6 @@
|
|
|
21
21
|
|
|
22
22
|
# The Inform module
|
|
23
23
|
module Inform
|
|
24
|
-
# TODO: Testme
|
|
25
|
-
# class Object
|
|
26
|
-
# def after_initialize
|
|
27
|
-
# super
|
|
28
|
-
# return if new?
|
|
29
|
-
# Inform::Behavior.attach(self)
|
|
30
|
-
# apply_instance_behavior!
|
|
31
|
-
# end
|
|
32
|
-
|
|
33
|
-
# def after_refresh
|
|
34
|
-
# super
|
|
35
|
-
# apply_instance_behavior!
|
|
36
|
-
# end
|
|
37
|
-
# end
|
|
38
|
-
|
|
39
24
|
# The Inform::Behavior module
|
|
40
25
|
module Behavior
|
|
41
26
|
class Registry < Hash; end
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# lib/story_teller/grammar_parser.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2026 but freely usable (see license)
|
|
5
6
|
#
|
|
6
7
|
# This file is part of StoryTeller.
|
|
7
8
|
#
|
|
@@ -90,7 +91,12 @@ module Inform
|
|
|
90
91
|
EmoteString = 'emote'.freeze
|
|
91
92
|
Newline = "\n".freeze
|
|
92
93
|
|
|
94
|
+
# rubocop: disable Metrics/AbcSize
|
|
95
|
+
# rubocop: disable Metrics/MethodLength
|
|
93
96
|
def to_s
|
|
97
|
+
grammar_lines = grammars.map(&:to_s)
|
|
98
|
+
grammar_lines[-1] = "#{grammar_lines[-1]};" if grammar_lines.any?
|
|
99
|
+
|
|
94
100
|
VerbString + SpaceString +
|
|
95
101
|
if meta?
|
|
96
102
|
MetaString + SpaceString
|
|
@@ -100,8 +106,10 @@ module Inform
|
|
|
100
106
|
''
|
|
101
107
|
end +
|
|
102
108
|
map { |verb| "'#{verb}'" }.join(SpaceString) + Newline +
|
|
103
|
-
|
|
109
|
+
grammar_lines.join(Newline)
|
|
104
110
|
end
|
|
111
|
+
# rubocop: enable Metrics/AbcSize
|
|
112
|
+
# rubocop: enable Metrics/MethodLength
|
|
105
113
|
alias to_str to_s
|
|
106
114
|
|
|
107
115
|
def hash
|
|
@@ -115,15 +123,22 @@ module Inform
|
|
|
115
123
|
CustomScopePattern = %r{^(.*)=(.*)$}.freeze
|
|
116
124
|
attr_reader :source, :action, :expected_tokens
|
|
117
125
|
|
|
126
|
+
# rubocop: disable Metrics/MethodLength
|
|
118
127
|
def initialize(grammar, source, action, reverse = nil)
|
|
119
128
|
super()
|
|
120
|
-
|
|
129
|
+
unless grammar.empty?
|
|
130
|
+
symbolized_grammar = symbolize_grammar(grammar)
|
|
131
|
+
concat(symbolized_grammar) unless symbolized_grammar.empty?
|
|
132
|
+
end
|
|
121
133
|
push(:end)
|
|
122
134
|
@action = action
|
|
123
|
-
@expected_tokens =
|
|
135
|
+
@expected_tokens = symbolized_grammar&.map do |a|
|
|
136
|
+
CustomScopePattern.match?(a) ? a.to_s.split('=').first.to_sym : a
|
|
137
|
+
end
|
|
124
138
|
@reverse = reverse.nil? ? false : reverse
|
|
125
139
|
@source = source
|
|
126
140
|
end
|
|
141
|
+
# rubocop: enable Metrics/MethodLength
|
|
127
142
|
|
|
128
143
|
def empty?
|
|
129
144
|
length == (include?(:end) ? 1 : 0)
|
|
@@ -261,35 +276,64 @@ module Inform
|
|
|
261
276
|
BuilderPattern = %r{builder}.freeze
|
|
262
277
|
Profanity = %w[shit damn fuck sod].freeze
|
|
263
278
|
ValidModes = %i[admin builder player].freeze
|
|
264
|
-
ModePatterns = ValidModes.each_with_object({})
|
|
279
|
+
ModePatterns = ValidModes.each_with_object({}) do |key, memo|
|
|
280
|
+
memo[key] = Regexp.new(key.to_s)
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# TODO: Remove (2026-04-30) after confirming replacement below
|
|
284
|
+
# works better.
|
|
285
|
+
# def lookup(key, actor = nil, grammar_index = self)
|
|
286
|
+
# return nil if key.nil? || !grammar_index.include?(key)
|
|
287
|
+
# verb = grammar_index[key].dup
|
|
288
|
+
# return verb if actor.nil?
|
|
289
|
+
# return nil if guarded?(verb, actor)
|
|
290
|
+
# filter_by_permission(verb, actor)
|
|
291
|
+
# verb
|
|
292
|
+
# end
|
|
265
293
|
|
|
266
294
|
def lookup(key, actor = nil, grammar_index = self)
|
|
267
295
|
return nil if key.nil? || !grammar_index.include?(key)
|
|
296
|
+
|
|
268
297
|
verb = grammar_index[key].dup
|
|
269
298
|
return verb if actor.nil?
|
|
270
|
-
|
|
299
|
+
|
|
271
300
|
filter_by_permission(verb, actor)
|
|
301
|
+
return nil if verb.grammars.empty?
|
|
302
|
+
|
|
272
303
|
verb
|
|
273
304
|
end
|
|
274
305
|
|
|
275
306
|
def all(actor = nil, grammar_index = self)
|
|
276
307
|
return grammar_index.map(&:keys).flatten.sort if actor.nil?
|
|
277
308
|
mode = role(actor)
|
|
278
|
-
|
|
309
|
+
unless Inform::Grammar.partitions.include?(mode)
|
|
310
|
+
init_all_verbs_by_mode(mode, grammar_index, actor)
|
|
311
|
+
end
|
|
279
312
|
Inform::Grammar.partitions[mode]
|
|
280
313
|
end
|
|
281
314
|
|
|
282
315
|
def by_mode(mode = nil, grammar_index = self)
|
|
283
316
|
mode = validate(mode)
|
|
284
|
-
|
|
317
|
+
unless Inform::Grammar.selections.include?(mode)
|
|
318
|
+
init_verbs_filtered_by_mode(mode, grammar_index)
|
|
319
|
+
end
|
|
285
320
|
Inform::Grammar.selections[mode]
|
|
286
321
|
end
|
|
287
322
|
|
|
288
323
|
private
|
|
289
324
|
|
|
325
|
+
# TODO: Remove (2026-04-30) after confirming replacement below
|
|
326
|
+
# works better.
|
|
327
|
+
# def init_all_verbs_by_mode(mode, grammar_index, actor, set = verbs_set_instance)
|
|
328
|
+
# verbs = grammar_index.each_with_object(set) do |(key, verb), memo|
|
|
329
|
+
# memo.add(key) unless Profanity.include?(key) || guarded?(verb, actor)
|
|
330
|
+
# end
|
|
331
|
+
# Inform::Grammar.partitions[mode] = verbs.to_a
|
|
332
|
+
# end
|
|
333
|
+
|
|
290
334
|
def init_all_verbs_by_mode(mode, grammar_index, actor, set = verbs_set_instance)
|
|
291
335
|
verbs = grammar_index.each_with_object(set) do |(key, verb), memo|
|
|
292
|
-
memo.add(key) unless Profanity.include?(key) ||
|
|
336
|
+
memo.add(key) unless Profanity.include?(key) || !visible_to?(verb, actor)
|
|
293
337
|
end
|
|
294
338
|
Inform::Grammar.partitions[mode] = verbs.to_a
|
|
295
339
|
end
|
|
@@ -312,13 +356,16 @@ module Inform
|
|
|
312
356
|
end
|
|
313
357
|
|
|
314
358
|
def guarded?(resource, obj)
|
|
315
|
-
(AdminPattern.match?(resource.source) &&
|
|
316
|
-
|
|
359
|
+
(AdminPattern.match?(resource.source) &&
|
|
360
|
+
!StoryTeller::Privileges.privileged?(obj, :admin)) ||
|
|
361
|
+
(BuilderPattern.match?(resource.source) &&
|
|
362
|
+
!StoryTeller::Privileges.privileged?(obj, :builder))
|
|
317
363
|
end
|
|
318
364
|
|
|
319
365
|
def role(obj)
|
|
320
|
-
return :
|
|
321
|
-
return :
|
|
366
|
+
return :admin if StoryTeller::Privileges.privileged?(obj, :admin)
|
|
367
|
+
return :builder if StoryTeller::Privileges.privileged?(obj, :builder)
|
|
368
|
+
|
|
322
369
|
:player
|
|
323
370
|
end
|
|
324
371
|
|