Module: Inform

Includes:
Articles, Color, Plurals
Included in:
Object, System::Object
Defined in:
lib/runtime/io.rb,
lib/runtime/tag.rb,
lib/runtime/tag.rb,
lib/runtime/tag.rb,
lib/runtime/tag.rb,
lib/runtime/tag.rb,
lib/runtime/tag.rb,
lib/runtime/game.rb,
lib/runtime/link.rb,
lib/runtime/link.rb,
lib/runtime/tree.rb,
lib/runtime/color.rb,
lib/runtime/config.rb,
lib/runtime/daemon.rb,
lib/runtime/events.rb,
lib/runtime/events.rb,
lib/runtime/events.rb,
lib/runtime/module.rb,
lib/runtime/module.rb,
lib/runtime/module.rb,
lib/runtime/object.rb,
lib/runtime/object.rb,
lib/runtime/stdlib.rb,
lib/runtime/command.rb,
lib/runtime/command.rb,
lib/runtime/context.rb,
lib/runtime/helpers.rb,
lib/runtime/helpers.rb,
lib/runtime/helpers.rb,
lib/runtime/helpers.rb,
lib/runtime/history.rb,
lib/runtime/library.rb,
lib/runtime/options.rb,
lib/runtime/plurals.rb,
lib/runtime/runtime.rb,
lib/runtime/session.rb,
lib/runtime/version.rb,
lib/runtime/articles.rb,
lib/runtime/builtins.rb,
lib/runtime/database.rb,
lib/runtime/database.rb,
lib/runtime/inflector.rb,
lib/runtime/prototype.rb,
lib/runtime/world_tree.rb,
lib/runtime/game_loader.rb,
lib/runtime/persistence.rb,
lib/runtime/persistence.rb,
lib/runtime/persistence.rb,
lib/runtime/persistence.rb,
lib/runtime/publication.rb,
lib/runtime/subscription.rb,
lib/runtime/grammar_parser.rb,
lib/runtime/grammar_parser.rb,
lib/runtime/grammar_parser.rb,
lib/runtime/library_loader.rb,
lib/runtime/experimental/handler_dsl.rb

Overview

The Inform module

Defined Under Namespace

Modules: App, Articles, Behavior, BuilderInstanceMethods, Color, Commands, Context, Daemons, Databases, Events, Game, Genealogical, Grammar, History, IO, ImplicitMigration, Inflector, InheritanceListener, Library, Linkable, Matchers, Modular, NilClassObjectHelpers, NilClassSetHelpers, ObjectHelpers, Options, Parser, Plurals, Privileges, Prototypical, Publisher, RuntimeClassMethods, RuntimeConstants, RuntimeInstanceMethods, RuntimeLibrary, SetHelpers, StdLib, Subscribers, System, TagHelpers, Taggable, Verbs Classes: BehaviorError, Command, CommandCauseRecordNotFoundError, Config, Database, DuplicateVerb, Event, EventCauseRecordNotFoundError, Link, Modularized, Module, Object, Persistence, Runtime, Tag, TagRegistry, Tagged, UnexpectedToken, Verb

Constant Summary collapse

RUNTIME_DIR_PATH =
File.expand_path(__dir__)
LIB_DIR_PATH =
File.expand_path(File.dirname(RUNTIME_DIR_PATH))
INFORM_DIR_PATH =
'inform'.freeze
PROJECT_DIR_PATH =
File.expand_path(File.dirname(LIB_DIR_PATH))
SystemObjects =
if defined?(Java)
  java.util.concurrent.ConcurrentHashMap.new
else
  {}
end
VERSION =
'1.0.4'.freeze
VN_1610 =
'1610'.freeze
MethodDefinitionPattern =

rubocop: enable Metrics/AbcSize rubocop: enable Metrics/CyclomaticComplexity rubocop: enable Metrics/MethodLength rubocop: enable Metrics/PerceivedComplexity

/\s*def\s+/.freeze
MethodTerminationPattern =
/\s*end$/.freeze
VERB =
1
PLURAL =
4
PREPOSITION =
8
NOUN =
128
Dictionary =
Set.new

Constants included from Color

Color::BackgroundColorCodes, Color::ColorCodes, Color::NearestColor, Color::StyleCodes

Constants included from Articles

Articles::LowercaseASpaceString, Articles::LowercaseSomeSpaceString, Articles::LowercaseTheSpaceString

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Plurals

#apply_inflections, #plural?, #pluralize, #singular?, #singularize

Methods included from Color

#background_color, #color, #nearest_color, #style, #un_background_color, #un_color, #un_style

Methods included from Articles

#A, #Cthatorthose, #Ctheyreorthats, #The, #a, #cthatorthose, #ctheyreorthats, #defart, #indefart, #isorare, #itorthem, #thatorthose, #the

Class Method Details

.attributesObject



142
143
144
# File 'lib/runtime/tag.rb', line 142

def self.attributes
  TagRegistry::SINGLETON.memo ||= TagRegistry.new
end

.contextObject



27
28
29
# File 'lib/runtime/context.rb', line 27

def self.context
  context_class.new
end

.context_classObject



23
24
25
# File 'lib/runtime/context.rb', line 23

def self.context_class
  Inform::Context.definition || Inform::Context.set(Inform::Runtime.invocation_context)
end

.Grammar(src) ⇒ Object



34
35
36
37
38
39
40
# File 'lib/runtime/grammar_parser.rb', line 34

def Grammar(src)
  source_location = caller_locations(1, 1).first
  mod_name = File.basename(source_location.path, '.*').gsub(/\W+/, '_').to_sym
  Inform::Grammar::Parser.new.parse_grammar(mod_name, src.each_line,
    origin_path: source_location.path, origin_line: source_location.lineno)
  self
end

.initialize_persistence_layerObject



35
36
37
38
# File 'lib/runtime/persistence.rb', line 35

def self.initialize_persistence_layer
  log.debug "Inform.initialize_persistence_layer"
  Inform::Persistence.init
end

.load_grammar(module_name) ⇒ Object



255
256
257
# File 'lib/runtime/grammar_parser.rb', line 255

def self.load_grammar(module_name)
  Inform::Grammar.load_by_name(module_name)
end

.load_grammar_by_path(module_path) ⇒ Object



259
260
261
# File 'lib/runtime/grammar_parser.rb', line 259

def self.load_grammar_by_path(module_path)
  Inform::Grammar.load_by_path(module_path)
end

.prime_dictionaryObject



268
269
270
271
272
# File 'lib/runtime/grammar_parser.rb', line 268

def self.prime_dictionary
  Inform::Object.select_map(:name).compact.each do |n|
    Inform::Dictionary.merge(n.split(/[,\s]+/).grep_v(/[^a-z]/i).map(&:downcase).map(&:to_sym))
  end
end

.unload_grammars!Object



263
264
265
266
# File 'lib/runtime/grammar_parser.rb', line 263

def self.unload_grammars!
  log.debug "Unloading all grammars"
  Inform::Grammar::Verbs.clear
end

Instance Method Details

#apply_instance_behavior!Object



108
109
110
111
112
113
114
115
# File 'lib/runtime/builtins.rb', line 108

def apply_instance_behavior!
  source = self.properties[:instance_behavior]
  return if source.nil? || source.empty?
  return unless source.include?('def ')
  self.instance_eval(source, "(instance_behavior for #{self.identity})", 1)
rescue NameError => e
  log.warn "[InstanceBehavior] #{e.class}: #{e.message}"
end

#builder(target, behavior, context) ⇒ Object



166
167
168
169
170
171
172
173
# File 'lib/runtime/experimental/handler_dsl.rb', line 166

def builder(target, behavior, context)
  Class.new do
    def initialize(target, behavior, context)
      @target, @behavior, @context = target, behavior, context
      self.extend(BuilderInstanceMethods)
    end
  end.new(target, behavior, context)
end

#classificationObject



305
306
307
308
309
310
# File 'lib/runtime/builtins.rb', line 305

def classification
  type = object_type.to_s
  clazz = self.class.to_s
  return type if type == clazz
  "#{type} < #{clazz}"
end

#compassObject



42
43
44
# File 'lib/runtime/builtins.rb', line 42

def compass
  InformLibrary::Compass
end

#contentObject Also known as: contents



50
# File 'lib/runtime/builtins.rb', line 50

def content; respond_to?(:descendants) ? self.descendants : Array::Empty; end

#context_proxy(target, context, proxy = Object.new) ⇒ Object

rubocop: disable Metrics/MethodLength



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/runtime/experimental/handler_dsl.rb', line 96

def context_proxy(target, context, proxy = Object.new)
  return target if context.nil?

  proxy.define_singleton_method(:method_missing) do |method_name, *args, &block|
    if context.local_variable_defined?(method_name)
      context.local_variable_get(method_name)
    elsif target.respond_to?(method_name)
      target.public_send(method_name, *args, &block)
    else
      super(method_name, *args, &block)
    end
  end

  proxy.define_singleton_method(:respond_to_missing?) do |method_name, include_private = false|
    context.local_variable_defined?(method_name) || target.respond_to?(method_name, include_private)
  end

  proxy
end

#current_wordObject



226
227
228
# File 'lib/runtime/builtins.rb', line 226

def current_word
  @words[@wn] || ''
end

#deadflagObject



185
# File 'lib/runtime/builtins.rb', line 185

def deadflag; @deadflag; end

#deadflag=(flag) ⇒ Object



187
# File 'lib/runtime/builtins.rb', line 187

def deadflag=(flag); @deadflag = flag; end

#dict_par1(w, par = 0) ⇒ Object



329
330
331
332
333
334
335
336
# File 'lib/runtime/builtins.rb', line 329

def dict_par1(w, par = 0)
  # +128 if given a noun, +8 if a preposition, +4 if plural, +1 if a verb
  par += NOUN if Inform::Dictionary.include?(w.to_sym)
  par += PREPOSITION if Inform::English::Prepositions.include?(w)
  par += PLURAL if plural?(w)
  par += VERB unless Inform::Grammar::Verbs.lookup(w).nil?
  par
end

#dictionaryObject



38
39
40
# File 'lib/runtime/builtins.rb', line 38

def dictionary
  Inform::Dictionary
end

#disrobe(obj) ⇒ Object



274
275
276
# File 'lib/runtime/builtins.rb', line 274

def disrobe(obj)
  invoke :Disrobe, obj
end

#drop(obj) ⇒ Object



266
267
268
# File 'lib/runtime/builtins.rb', line 266

def drop(obj)
  invoke :Drop, obj
end

#emote(*s) ⇒ Object



261
262
263
264
# File 'lib/runtime/builtins.rb', line 261

def emote(*s)
  return consult_words if s.empty?
  invoke :Emote, s.flatten.sample
end

#ensure_behavior_module!(key, behavior) ⇒ Object

Raises:



123
124
125
# File 'lib/runtime/experimental/handler_dsl.rb', line 123

def ensure_behavior_module!(key, behavior)
  raise BehaviorError.new(key, behavior) unless behavior.is_a?(::Module)
end

#extend_and_persist(behavior) ⇒ Object

rubocop: enable Metrics/MethodLength



117
118
119
120
121
# File 'lib/runtime/experimental/handler_dsl.rb', line 117

def extend_and_persist(behavior)
  self.extend(behavior)
  self.save_changes if self.respond_to?(:save_changes)
  self
end

#findobject(*args, &block) ⇒ Object



180
181
182
183
# File 'lib/runtime/builtins.rb', line 180

def findobject(*args, &block)
  return Inform::Object.dataset.order(:name, :id).grep(:name, *args).to_a if args.first.is_a?(Regexp)
  Inform::Object.dataset.grep(&block).to_a
end

#getobject(id) ⇒ Object



173
174
175
176
177
178
# File 'lib/runtime/builtins.rb', line 173

def getobject(id)
  o = Inform::Object[id]
  o.refresh
rescue StandardError
  raise NoSuchObject
end

#go(obj) ⇒ Object



253
254
255
# File 'lib/runtime/builtins.rb', line 253

def go(obj)
  invoke :Go, obj
end

#initialObject



121
122
123
# File 'lib/runtime/builtins.rb', line 121

def initial
  # TODO: What is this supposed to return?
end

#language_descriptorsObject



240
241
242
243
244
# File 'lib/runtime/builtins.rb', line 240

def language_descriptors
  # TODO: Cleanup upon disconnect
  key = self.respond_to?(:inflib) ? self.inflib : self.identity
  LanguageDescriptors[key] ||= Marshal.load(Marshal.dump(LanguageDescriptors[:default]))
end

#language_pronounsObject



234
235
236
237
238
# File 'lib/runtime/builtins.rb', line 234

def language_pronouns
  # TODO: Cleanup upon disconnect
  key = self.respond_to?(:inflib) ? self.inflib : self.identity
  LanguagePronouns[key] ||= Marshal.load(Marshal.dump(LanguagePronouns[:default]))
end

#library_method?(method) ⇒ Boolean

Returns:

  • (Boolean)


321
322
323
# File 'lib/runtime/builtins.rb', line 321

def library_method?(method)
  Inform::Library.methods_index.include?(method) && respond_to?(method)
end

#life?(action_routine = action) ⇒ Boolean

Returns:

  • (Boolean)


156
157
158
159
160
161
162
163
# File 'lib/runtime/builtins.rb', line 156

def life?(action_routine = action)
  return false if action_routine.nil?
  self.apply_modules if self.respond_to?(:apply_modules)
  self.provides?('life_' + action_routine)
rescue StandardError => e
  log.error "Error checking for life reaction: #{e.message}", e
  false
end

#light_adjusted(obj = @player) ⇒ Object



246
247
248
249
250
251
# File 'lib/runtime/builtins.rb', line 246

def light_adjusted(obj = @player)
  # TODO: Consider performing the following in another thread or an event
  obj.root.descendants.each do |o|
    o.inflib.send(:AdjustLight, true) if o.has?(:creature) && !o.inflib.nil?
  end
end

#method_source(method_name) ⇒ Object



102
103
104
105
106
# File 'lib/runtime/builtins.rb', line 102

def method_source(method_name)
  self.singleton_class.instance_method(method_name).source
rescue StandardError => _e
  nil
end

#nothingObject



46
47
48
# File 'lib/runtime/builtins.rb', line 46

def nothing
  nil
end

#num_wordsObject



222
223
224
# File 'lib/runtime/builtins.rb', line 222

def num_words
  @words.nil? || @words.empty? ? 0 : @words.length
end

#number(x = nil) ⇒ Object



212
213
214
215
216
# File 'lib/runtime/builtins.rb', line 212

def number(x = nil)
  return special_number1 if x.nil?
  LanguageNumber(x)
  ''
end

#objectloop(*_args, &block) ⇒ Object



165
166
167
168
169
170
171
# File 'lib/runtime/builtins.rb', line 165

def objectloop(*_args, &block)
  if self.is_a?(InformLibrary)
    Inform::Object.all.each { |o| block.call(o) }
  elsif self.respond_to?(:descendants)
    self.descendants.each { |o| block.call(o) }
  end
end

#ofclass(klass) ⇒ Object Also known as: ofclass?



125
126
127
# File 'lib/runtime/builtins.rb', line 125

def ofclass(klass)
  self.is_a?(klass)
end

#pause(n) ⇒ Object



316
317
318
319
# File 'lib/runtime/builtins.rb', line 316

def pause(n)
  sleep(n)
  :inform
end

#provides?(prop) ⇒ Boolean

Returns:

  • (Boolean)


130
131
132
133
134
135
136
# File 'lib/runtime/builtins.rb', line 130

def provides?(prop)
  symbolized_prop = prop.to_sym
  return symbolized_prop if self.respond_to?(symbolized_prop)
  downcased_prop = symbolized_prop.downcase
  return downcased_prop if self.respond_to?(downcased_prop)
  false
end

#quitObject



278
279
280
281
# File 'lib/runtime/builtins.rb', line 278

def quit
  Inform::Runtime.instance.quit
  publish :disconnect
end

#randomly(n = 3) ⇒ Object



312
313
314
# File 'lib/runtime/builtins.rb', line 312

def randomly(n = 3)
  rand * n
end

#react_after?(action_routine = action) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
141
142
143
144
145
# File 'lib/runtime/builtins.rb', line 138

def react_after?(action_routine = action)
  return false if action_routine.nil?
  self.apply_modules if self.respond_to?(:apply_modules)
  self.provides?('react_after_' + action_routine)
rescue StandardError => e
  log.error "Error checking for after reaction: #{e.message}", e
  false
end

#react_before?(action_routine = action) ⇒ Boolean

Returns:

  • (Boolean)


147
148
149
150
151
152
153
154
# File 'lib/runtime/builtins.rb', line 147

def react_before?(action_routine = action)
  return false if action_routine.nil?
  self.apply_modules if self.respond_to?(:apply_modules)
  self.provides?('react_before_' + action_routine)
rescue StandardError => e
  log.error "Error checking for before reaction: #{e.message}", e
  false
end

#remaining_wordsObject



230
231
232
# File 'lib/runtime/builtins.rb', line 230

def remaining_words
  @words[@wn..]
end

#resembles_method?(source) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/runtime/builtins.rb', line 98

def resembles_method?(source)
  MethodDefinitionPattern.match?(source) && MethodTerminationPattern.match?(source)
end

#run_daemonsObject



80
81
82
83
# File 'lib/runtime/daemon.rb', line 80

def run_daemons
  return if defined?(TURN_BASED)
  Inform::Daemons.start
end

#say(*s) ⇒ Object



257
258
259
# File 'lib/runtime/builtins.rb', line 257

def say(*s)
  invoke :Say, s.flatten.sample
end

#scoreObject



193
# File 'lib/runtime/builtins.rb', line 193

def score; @score.nil? ? 0 : @score; end

#score=(score) ⇒ Object



195
# File 'lib/runtime/builtins.rb', line 195

def score=(score); @score = score; end

#search(obj) ⇒ Object



270
271
272
# File 'lib/runtime/builtins.rb', line 270

def search(obj)
  invoke :Search, obj
end

#specialObject



218
219
220
# File 'lib/runtime/builtins.rb', line 218

def special
  @special_word
end

#the_timeObject



189
# File 'lib/runtime/builtins.rb', line 189

def the_time; @the_time.nil? ? 0 : @the_time; end

#the_time=(the_time) ⇒ Object



191
# File 'lib/runtime/builtins.rb', line 191

def the_time=(the_time); @the_time = the_time; end

#things_scoreObject



197
# File 'lib/runtime/builtins.rb', line 197

def things_score; @things_score.nil? ? 0 : @things_score; end

#things_score=(things_score) ⇒ Object



199
# File 'lib/runtime/builtins.rb', line 199

def things_score=(things_score); @things_score = things_score; end

#to_sObject Also known as: to_str


(From the Inform Designer's Manual)
§26 Describing objects and rooms

To print the name of such an object, Inform does the following:

(1) If the short_name is a string, it's printed and that's all.
(2) If it is a routine, then it is called. If it returns true, that's all.
(3) The text given in the header of the object definition is printed.



293
294
295
296
297
298
299
300
301
302
# File 'lib/runtime/builtins.rb', line 293

def to_s
  textual_name = self.short_name if self.respond_to?(:short_name)
  return textual_name if textual_name.is_a?(String)  # (1)
  return if textual_name == true                     # (2)
  if self.respond_to?(:name)
    return self.name.join(' ') if self.name.respond_to?(:join)
    return self.name.to_s                            # (3)
  end
  self.identity
end

#topicObject Also known as: text



207
208
209
# File 'lib/runtime/builtins.rb', line 207

def topic
  consult_words
end

#visibility_ceiling=(visibility_ceiling) ⇒ Object



201
202
203
204
205
# File 'lib/runtime/builtins.rb', line 201

def visibility_ceiling=(visibility_ceiling)
  e = Thread.current[:event]
  @visibility_ceiling = visibility_ceiling
  e.visibility_ceiling = visibility_ceiling if e
end

#with(context = nil, key = Inform::Behavior.key_for(self), &block) ⇒ Object

rubocop: disable Metrics/AbcSize rubocop: disable Metrics/MethodLength



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/runtime/builtins.rb', line 57

def with(context = nil, &block)
  return self if block.nil?
  existing_methods = self.singleton_methods(false)

  if context.nil?
    self.instance_eval(&block)
  else
    self.instance_exec(context, &block)
  end

  # Only persist methods being defined just now on *this* instance
  added = self.singleton_methods(false) - existing_methods
  added.select! do |m|
    self.singleton_class.instance_method(m).owner == self.singleton_class
  end

  if added.any?
    persisted = self.properties.fetch(:instance_behavior, '')
    added.each do |method_name|
      source = method_source(method_name)
      next if source.nil?
      # Only support def ... end blocks
      next unless resembles_method?(source)
      persisted << source unless persisted.include?(source)
    end
    unless persisted.empty?
      self.will_change_column(:properties) if self.respond_to?(:will_change_column)
      self.properties[:instance_behavior] = persisted
    end
  end
  self.save_changes if self.respond_to?(:save_changes)
  self
end

#workflagsObject



117
118
119
# File 'lib/runtime/builtins.rb', line 117

def workflags
  Thread.current[:workflags] ||= Set.new
end