Module: Gamefic::Active

Includes:
Messaging, Logging
Included in:
Actor
Defined in:
lib/gamefic/active.rb,
lib/gamefic/active/cue.rb,
lib/gamefic/active/epic.rb,
lib/gamefic/active/take.rb,
lib/gamefic/active/messaging.rb

Overview

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.

Defined Under Namespace

Modules: Messaging Classes: Cue, Epic, Take

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Messaging

#buffer, #flush, #messages, #messenger, #stream, #tell

Methods included from Logging

logger

Instance Attribute Details

#last_inputString? (readonly)

Returns:



25
26
27
# File 'lib/gamefic/active.rb', line 25

def last_input
  @last_input
end

#next_cueActive::Cue? (readonly)

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

Returns:



22
23
24
# File 'lib/gamefic/active.rb', line 22

def next_cue
  @next_cue
end

Instance Method Details

#accessible?Boolean

Returns:

  • (Boolean)


211
212
213
# File 'lib/gamefic/active.rb', line 211

def accessible?
  false
end

#acting?Boolean

Returns:

  • (Boolean)


215
216
217
# File 'lib/gamefic/active.rb', line 215

def acting?
  !epic.empty?
end

#conclude(scene, **context) ⇒ Cue

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

Parameters:

  • new_scene (Symbol)

Returns:

Raises:

  • (ArgumentError)

    if the requested scene is not a conclusion



197
198
199
200
201
202
203
# 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?Boolean

True if the actor is ready to leave the game.

Returns:

  • (Boolean)


207
208
209
# File 'lib/gamefic/active.rb', line 207

def concluding?
  epic.empty? || @props&.scene&.fetch(:type) == 'Conclusion'
end

#cue(scene, **context) ⇒ Cue Also known as: prepare

Cue a scene to start in the next turn.

Parameters:

  • scene (Symbol)
  • context (Hash)

    Extra data to pass to the scene’s props

Returns:

Raises:

  • (ArgumentError)

    if the scene is not valid



151
152
153
154
155
156
157
# 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

#epicEpic

The narratives in which the entity is participating.

Returns:



43
44
45
# File 'lib/gamefic/active.rb', line 43

def epic
  @epic ||= Epic.new
end

#execute(verb, *params) ⇒ Action?

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.

Examples:

character.execute :take, @key

Parameters:

  • verb (Symbol)
  • params (Array)

Returns:



111
112
113
114
# 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_takevoid

This method returns an undefined value.



173
174
175
176
177
178
# 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_outputProps::Output

The output from the previous turn.

Returns:



68
69
70
# File 'lib/gamefic/active.rb', line 68

def last_output
  @last_output ||= output
end

#next_sceneSymbol?

Returns:

  • (Symbol, nil)


28
29
30
# File 'lib/gamefic/active.rb', line 28

def next_scene
  next_cue&.scene
end

#outputProps::Output

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.

Returns:



61
62
63
# File 'lib/gamefic/active.rb', line 61

def output
  @output ||= Props::Output.new.freeze
end

#perform(command) ⇒ Action?

Perform a command.

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

Examples:

Send a command as a string

character.perform "take the key"

Parameters:

Returns:



82
83
84
85
# File 'lib/gamefic/active.rb', line 82

def perform(command)
  dispatchers.push Dispatcher.dispatch(self, command)
  dispatchers.last.execute.tap { dispatchers.pop }
end

#proceedAction?

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.

Examples:

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

Returns:



140
141
142
# File 'lib/gamefic/active.rb', line 140

def proceed
  dispatchers.last&.proceed
end

#queueArray<String>

An array of commands waiting to be executed.

Returns:



50
51
52
# File 'lib/gamefic/active.rb', line 50

def queue
  @queue ||= []
end

#quietly(command) ⇒ String

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.

Parameters:

Returns:

  • (String)

    The output that resulted from performing the command.



93
94
95
# File 'lib/gamefic/active.rb', line 93

def quietly(command)
  messenger.buffer { perform command }
end

#recueCue?

Restart the scene from the most recent cue.

Returns:



183
184
185
186
187
# File 'lib/gamefic/active.rb', line 183

def recue
  logger.warn "No scene to recue" unless @last_cue

  @next_cue = @last_cue
end

#start_takevoid

This method returns an undefined value.



161
162
163
164
165
166
167
168
169
170
# 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