Module: Gamefic::Active

Included in:
Actor
Defined in:
lib/gamefic/active.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.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#last_actionGamefic::Action (readonly)

The last action executed by the entity, as reported by the Active#performed method.

Returns:



13
14
15
# File 'lib/gamefic/active.rb', line 13

def last_action
  @last_action
end

#last_inputString

The input for the previous scene.

Returns:



36
37
38
# File 'lib/gamefic/active.rb', line 36

def last_input
  @last_input
end

#last_promptString

The prompt for the previous scene.

Returns:



31
32
33
# File 'lib/gamefic/active.rb', line 31

def last_prompt
  @last_prompt
end

#next_optionsObject (readonly)

Returns the value of attribute next_options.



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

def next_options
  @next_options
end

#next_sceneClass<Gamefic::Scene::Base> (readonly)

The scene class that will be cued for this entity on the next turn. Usually set with the #prepare method.

Returns:



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

def next_scene
  @next_scene
end

#sceneGamefic::Scene::Base (readonly)

The scene in which the entity is currently participating.



18
19
20
# File 'lib/gamefic/active.rb', line 18

def scene
  @scene
end

Instance Method Details

#accessible?Boolean

Returns:

  • (Boolean)


242
243
244
# File 'lib/gamefic/active.rb', line 242

def accessible?
  false
end

#conclude(scene) ⇒ Object

Cue a conclusion. This method works like #cue, except it will raise a NotConclusionError if the scene is not a Scene::Conclusion.

Raises:



222
223
224
225
# File 'lib/gamefic/active.rb', line 222

def conclude scene
  raise NotConclusionError unless scene <= Scene::Conclusion
  cue scene
end

#concluded?Boolean

True if the character is in a conclusion.

Returns:

  • (Boolean)


230
231
232
# File 'lib/gamefic/active.rb', line 230

def concluded?
  !scene.nil? && scene.kind_of?(Scene::Conclusion)
end

#cue(new_scene, **options) ⇒ Object

Immediately start a new scene for the character. Use #prepare if you want to declare a scene to be started at the beginning of the next turn.

Parameters:

  • new_scene (Class)


191
192
193
194
195
196
197
198
199
# File 'lib/gamefic/active.rb', line 191

def cue new_scene, **options
  @next_scene = nil
  if new_scene.nil?
    @scene = nil
  else
    @scene = new_scene.new(self, **options)
    @scene.start
  end
end

#entered(scene) ⇒ Object

Track the entity’s performance of a scene.



252
253
254
255
# File 'lib/gamefic/active.rb', line 252

def entered scene
  klass = (scene.kind_of?(Gamefic::Scene::Base) ? scene.class : scene)
  entered_scenes.push klass unless entered_scenes.include?(klass)
end

#entered?(scene) ⇒ Boolean

Determine whether the entity has performed the specified scene.

Returns:

  • (Boolean)


260
261
262
263
# File 'lib/gamefic/active.rb', line 260

def entered? scene
  klass = (scene.kind_of?(Gamefic::Scene::Base) ? scene.class : scene)
  entered_scenes.include?(klass)
end

#execute(verb, *params, quietly: false) ⇒ Gamefic::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 parameters. 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

Returns:



141
142
143
144
145
# File 'lib/gamefic/active.rb', line 141

def execute(verb, *params, quietly: false)
  actions = []
  playbooks.reverse.each { |p| actions.concat p.dispatch_from_params(self, verb, params) }
  execute_stack actions, quietly: quietly
end

#inspectObject



246
247
248
# File 'lib/gamefic/active.rb', line 246

def inspect
  to_s
end

#outputObject



63
64
65
# File 'lib/gamefic/active.rb', line 63

def output
  @output ||= {}
end

#perform(*command) ⇒ Gamefic::Action

Perform a command. The command can be specified as a String or a verb with a list of parameters. Either form should yield the same result, but the verb/parameter form can yield better performance since it bypasses the parser.

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

Examples:

Send a command as a string

character.perform "take the key"

Send a command as a verb with parameters

character.perform :take, @key

Returns:



108
109
110
111
112
# File 'lib/gamefic/active.rb', line 108

def perform(*command)
  actions = []
  playbooks.reverse.each { |p| actions.concat p.dispatch(self, *command) }
  execute_stack actions
end

#performed(action) ⇒ Object

Record the last action the entity executed. This method is typically called when the entity performs an action in response to user input.



237
238
239
240
# File 'lib/gamefic/active.rb', line 237

def performed action
  action.freeze
  @last_action = action
end

#playbooksArray<Gamefic::World::Playbook>

The playbooks that will be used to perform commands.



41
42
43
# File 'lib/gamefic/active.rb', line 41

def playbooks
  @playbooks ||= []
end

#prepare(new_scene, **options) ⇒ Object

Prepare a scene to be started for this character at the beginning of the next turn. As opposed to #cue, a prepared scene will not start until the current scene finishes.

Parameters:

  • new_scene (Class)


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

def prepare new_scene, **options
  @next_scene = new_scene
  @next_options = options
end

#proceed(quietly: false) ⇒ Object

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


168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/gamefic/active.rb', line 168

def proceed quietly: false
  return if performance_stack.empty?
  a = performance_stack.last.shift
  unless a.nil?
    if quietly
      if buffer_stack == 0
        @buffer = ""
      end
      set_buffer_stack(buffer_stack + 1)
    end
    a.execute
    if quietly
      set_buffer_stack(buffer_stack - 1)
      @buffer
    end
  end
end

#queueArray<String>

An array of actions waiting to be performed.

Returns:



52
53
54
# File 'lib/gamefic/active.rb', line 52

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 the user.

Returns:

  • (String)

    The output that resulted from performing the command.



119
120
121
122
123
124
125
126
127
# File 'lib/gamefic/active.rb', line 119

def quietly(*command)
  if buffer_stack == 0
    clear_buffer
  end
  set_buffer_stack buffer_stack + 1
  self.perform *command
  set_buffer_stack buffer_stack - 1
  buffer
end

#stateHash{Symbol => Object}

A hash of values representing the state of a performing entity.

Returns:



59
60
61
# File 'lib/gamefic/active.rb', line 59

def state
  @state ||= {}
end

#stream(message) ⇒ Object

Send a message to the Character as raw text. Unlike #tell, this method will not wrap the message in HTML paragraphs.

Parameters:



84
85
86
87
88
89
90
# File 'lib/gamefic/active.rb', line 84

def stream(message)
  if buffer_stack > 0
    append_buffer message
  else
    super
  end
end

#syntaxesObject



45
46
47
# File 'lib/gamefic/active.rb', line 45

def syntaxes
  playbooks.map(&:syntaxes).flatten
end

#tell(message) ⇒ Object

Send a message to the entity. This method will automatically wrap the message in HTML paragraphs. To send a message without paragraph formatting, use #stream instead.

Parameters:



72
73
74
75
76
77
78
# File 'lib/gamefic/active.rb', line 72

def tell(message)
  if buffer_stack > 0
    append_buffer format(message)
  else
    super
  end
end

#will_cue?(scene) ⇒ Boolean

Return true if the character is expected to be in the specified scene on the next turn.

Returns:

  • (Boolean)


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

def will_cue? scene
  (@scene.class == scene and @next_scene.nil?) || @next_scene == scene
end