module Gamefic::Scriptable

A class module that enables scripting.

Narratives extend Scriptable to enable definition of scripts and seeds. Modules can also be extended with Scriptable to make them includable to other Scriptables.

@example Include a scriptable module in a plot

module MyScript
  extend Gamefic::Scriptable

  respond :myscript do |actor|
    actor.tell "This command was added by MyScript"
  end
end

class MyPlot < Gamefic::Plot
  include MyScript
end

Public Instance Methods

_attr(key)
Alias for: lazy_attr
_ivar(key)
Alias for: lazy_ivar
_pick(*args)
Alias for: pick
_pick!(*args)
Alias for: pick
attr_seed(name, klass, **opts) click to toggle source

Seed an entity with an attribute method.

@example

class Plot < Gamefic::Plot
  attr_seed :thing, Gamefic::Entity, name: 'thing'
end

plot = Plot.new
plot.thing #=> #<Gamefic::Entity a thing>

@param name [Symbol] The attribute name @param klass [Class<Gamefic::Entity>] @return [Proxy]

# File lib/gamefic/scriptable.rb, line 124
def attr_seed name, klass, **opts
  ivname = "@#{name}"
  define_method(name) do
    return instance_variable_get(ivname) if instance_variable_defined?(ivname)

    instance_variable_set(ivname, make(klass, **opts))
  end
  seed { send name }
  Proxy.new(:attr, name)
end
blocks() click to toggle source

@return [Array<Block>]

# File lib/gamefic/scriptable.rb, line 41
def blocks
  @blocks ||= []
end
Also aliased as: scripts
included_blocks() click to toggle source

@return [Array<Block>]

# File lib/gamefic/scriptable.rb, line 90
def included_blocks
  included_modules.that_are(Scriptable)
                  .uniq
                  .reverse
                  .flat_map(&:blocks)
                  .concat(blocks)
end
lazy_attr(key) click to toggle source

Lazy reference an entity by its attribute or method.

@example

lazy_attr(:method)

@param key [Symbol] @return [Proxy]

# File lib/gamefic/scriptable.rb, line 166
def lazy_attr key
  Gamefic.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`lazy_attr` is deprecated. Use `pick` or `pick!` instead."
  Proxy.new(:attr, key)
end
Also aliased as: _attr
lazy_ivar(key) click to toggle source

Lazy reference an entity by its instance variable.

@example

lazy_ivar(:@variable)

@param key [Symbol] @return [Proxy]

# File lib/gamefic/scriptable.rb, line 153
def lazy_ivar key
  Gamefic.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`lazy_ivar` is deprecated. Use `pick` or `pick!` instead."
  Proxy.new(:ivar, key)
end
Also aliased as: _ivar
lazy_pick(*args)
Alias for: pick
lazy_pick!(*args)
Alias for: pick
make(klass, **opts)
Alias for: make_seed
make_seed(klass, **opts) click to toggle source

Seed an entity.

@example

make_seed Gamefic::Entity, name: 'thing'

@param klass [Class<Gamefic::Entity>] @return [Proxy]

# File lib/gamefic/scriptable.rb, line 105
def make_seed klass, **opts
  seed { make(klass, **opts) }
  Proxy::Pick.new(klass, opts[:name], raise: true)
end
Also aliased as: make
method_missing(method, *args, &block) click to toggle source

:nocov:

Calls superclass method
# File lib/gamefic/scriptable.rb, line 195
def method_missing method, *args, &block
  return super unless respond_to_missing?(method)

  script { send(method, *args, &block) }
end
no_scripts() click to toggle source

Create an anonymous module that includes the features of a Scriptable module but does not include its scripts.

This can be useful when you need access to the Scriptable’s constants and instance methods, but you don’t want to duplicate its rules.

@deprecated Removing script blocks is no longer necessary. This method

will simply return self until it's removed.

@return [Module<self>]

# File lib/gamefic/scriptable.rb, line 224
def no_scripts
  Logging.logger.warn "#{caller.first ? "#{caller.first}: " : ''}Calling `no_scripts` on Scriptable modules is no longer necessary."
  self
end
pick(*args) click to toggle source

Lazy pick an entity.

@example

pick('the red box')

@param args [Array] @return [Proxy]

# File lib/gamefic/scriptable.rb, line 179
def pick *args
  Proxy::Pick.new(*args)
end
Also aliased as: lazy_pick, _pick, lazy_pick!, _pick!
pick!(*args) click to toggle source

Lazy pick an entity or raise

# File lib/gamefic/scriptable.rb, line 187
def pick! *args
  Proxy::Pick.new(*args)
end
proxy(symbol) click to toggle source

@param symbol [Symbol] @return [Proxy]

# File lib/gamefic/scriptable.rb, line 137
def proxy symbol
  Logging.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`proxy` is deprecated. Use `pick` or `pick!` instead."
  if symbol.to_s.start_with?('@')
    Proxy.new(:ivar, symbol)
  else
    Proxy.new(:attr, symbol)
  end
end
respond_to_missing?(method, _with_private = false) click to toggle source
# File lib/gamefic/scriptable.rb, line 209
def respond_to_missing?(method, _with_private = false)
  [Scriptable::Actions, Scriptable::Events, Scriptable::Scenes].flat_map(&:public_instance_methods)
                                                               .include?(method)
end
script(&block) click to toggle source

Add a block of code to be executed during initialization.

These blocks are primarily used to define actions, scenes, and hooks in the narrative’s rulebook. Entities and game data should be initialized with ‘seed`.

@example

class MyPlot < Gamefic::Plot
  script do
    introduction do |actor|
      actor.tell 'Hello, world!'
    end

    respond :wait do |actor|
      actor.tell 'Time passes.'
    end
  end
end
# File lib/gamefic/scriptable.rb, line 65
def script &block
  blocks.push Block.new(:script, block)
end
scripts()
Alias for: blocks
seed(&block) click to toggle source

Add a block of code to generate content after initialization.

Seeds run after the initial scripts have been executed. Their primary use is to add entities and other data components, especially randomized or procedurally generated content that can vary between instances.

@note Seeds do not get executed when a narrative is restored from a

snapshot.

@example

class MyPlot < Gamefic::Plot
  seed do
    @thing = make Gamefic::Entity, name: 'a thing'
  end
end
# File lib/gamefic/scriptable.rb, line 85
def seed &block
  blocks.push Block.new(:seed, block)
end