module Gamefic::Active

The Active module gives entities the ability to perform actions and participate in scenes. The Actor class, for example, is an Entity subclass that includes this module.

Attributes

last_input[R]

@return [String, nil]

next_cue[R]

The cue that will be used to create a scene at the beginning of the next turn.

@return [Active::Cue, nil]

Public Instance Methods

accessible?() click to toggle source
# File lib/gamefic/active.rb, line 211
def accessible?
  false
end
acting?() click to toggle source
# File lib/gamefic/active.rb, line 215
def acting?
  !epic.empty?
end
conclude(scene, **context) click to toggle source

Cue a conclusion. This method works like cue, except it will raise an error if the scene is not a conclusion.

@raise [ArgumentError] if the requested scene is not a conclusion

@param new_scene [Symbol] @oaram context [Hash] Additional scene data @return [Cue]

# File lib/gamefic/active.rb, line 197
def conclude scene, **context
  cue scene, **context
  available = epic.select_scene(scene)
  raise ArgumentError, "`#{scene}` is not a conclusion" unless available.conclusion?

  @next_cue
end
concluding?() click to toggle source

True if the actor is ready to leave the game.

# File lib/gamefic/active.rb, line 207
def concluding?
  epic.empty? || @props&.scene&.fetch(:type) == 'Conclusion'
end
cue(scene, **context) click to toggle source

Cue a scene to start in the next turn.

@raise [ArgumentError] if the scene is not valid

@param scene [Symbol] @param context [Hash] Extra data to pass to the scene’s props @return [Cue]

# File lib/gamefic/active.rb, line 151
def cue scene, **context
  return @next_cue if @next_cue&.scene == scene && @next_cue&.context == context

  logger.debug "Overwriting existing cue `#{@next_cue.scene}` with `#{scene}`" if @next_cue

  @next_cue = Cue.new(scene, **context)
end
Also aliased as: prepare
epic() click to toggle source

The narratives in which the entity is participating.

@return [Epic]

# File lib/gamefic/active.rb, line 43
def epic
  @epic ||= Epic.new
end
execute(verb, *params) click to toggle source

Perform an action. This is functionally identical to the ‘perform` method, except the action must be declared as a verb with a list of arguments. Use `perform` if you need to parse a string as a command.

The command will be executed immediately, regardless of the entity’s state.

@example

character.execute :take, @key

@param verb [Symbol] @param params [Array] @return [Action, nil]

# File lib/gamefic/active.rb, line 111
def execute(verb, *params)
  dispatchers.push Dispatcher.dispatch_from_params(self, verb, params)
  dispatchers.last.execute.tap { dispatchers.pop }
end
finish_take() click to toggle source

@return [void]

# File lib/gamefic/active.rb, line 173
def finish_take
  return unless @last_cue

  Take.finish(self, @last_cue, @props)
  @last_input = @props.input
end
last_output() click to toggle source

The output from the previous turn.

@return [Props::Output]

# File lib/gamefic/active.rb, line 68
def last_output
  @last_output ||= output
end
next_scene() click to toggle source

@return [Symbol, nil]

# File lib/gamefic/active.rb, line 28
def next_scene
  next_cue&.scene
end
output() click to toggle source

Data that will be sent to the user. The output is typically sent after a scene has started and before the user is prompted for input.

The output object attached to the actor is always frozen. Authors should use on_player_output blocks to modify output to be sent to the user.

@return [Props::Output]

# File lib/gamefic/active.rb, line 61
def output
  @output ||= Props::Output.new.freeze
end
perform(command) click to toggle source

Perform a command.

The command’s action will be executed immediately, regardless of the entity’s state.

@example Send a command as a string

character.perform "take the key"

@param command [String] @return [Action, nil]

# File lib/gamefic/active.rb, line 82
def perform(command)
  dispatchers.push Dispatcher.dispatch(self, command)
  dispatchers.last.execute.tap { dispatchers.pop }
end
prepare(scene, **context)
Alias for: cue
proceed() click to toggle source

Proceed to the next Action in the current stack. This method is typically used in Action blocks to cascade through multiple implementations of the same verb.

@example Proceed through two implementations of a verb

introduction do |actor|
  actor[:has_eaten] = false # Initial value
end

respond :eat do |actor|
  actor.tell "You eat something."
  actor[:has_eaten] = true
end

respond :eat do |actor|
  # This version will be executed first because it was implemented last
  if actor[:has_eaten]
    actor.tell "You already ate."
  else
    actor.proceed # Execute the previous implementation
  end
end

@return [Action, nil]

# File lib/gamefic/active.rb, line 140
def proceed
  dispatchers.last&.proceed
end
queue() click to toggle source

An array of commands waiting to be executed.

@return [Array<String>]

# File lib/gamefic/active.rb, line 50
def queue
  @queue ||= []
end
quietly(command) click to toggle source

Quietly perform a command. This method executes the command exactly as perform does, except it buffers the resulting output instead of sending it to messages.

@param command [String] @return [String] The output that resulted from performing the command.

# File lib/gamefic/active.rb, line 93
def quietly(command)
  messenger.buffer { perform command }
end
recue() click to toggle source

Restart the scene from the most recent cue.

@return [Cue, nil]

# File lib/gamefic/active.rb, line 183
def recue
  logger.warn "No scene to recue" unless @last_cue

  @next_cue = @last_cue
end
start_take() click to toggle source

@return [void]

# File lib/gamefic/active.rb, line 161
def start_take
  ensure_cue
  @last_cue = @next_cue
  cue :default_scene
  @props = Take.start(self, @last_cue)
  @last_output = self.output
  @props.output[:last_prompt] = @last_output.prompt
  @props.output[:last_input] = @last_input
  @output = @props.output.dup.freeze
end

Private Instance Methods

dispatchers() click to toggle source

@return [Array<Dispatcher>]

# File lib/gamefic/active.rb, line 222
def dispatchers
  @dispatchers ||= []
end
ensure_cue() click to toggle source
# File lib/gamefic/active.rb, line 226
def ensure_cue
  return if next_cue

  logger.debug "Using default scene for actor without cue"
  cue :default_scene
end