lib/gamefic/active.rb in gamefic-3.0.0 vs lib/gamefic/active.rb in gamefic-3.1.0
- old
+ new
@@ -19,10 +19,13 @@
# turn.
#
# @return [Active::Cue, nil]
attr_reader :next_cue
+ # @return [String, nil]
+ attr_reader :last_input
+
# @return [Symbol, nil]
def next_scene
next_cue&.scene
end
@@ -46,32 +49,41 @@
# @return [Array<String>]
def queue
@queue ||= []
end
- # A hash of 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.
+ # 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.
#
- # @return [Hash]
+ # 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]
def output
- @output ||= {}
+ @output ||= Props::Output.new.freeze
end
+ # The output from the previous turn.
+ #
+ # @return [Props::Output]
+ def last_output
+ @last_output ||= output
+ end
+
# 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 [void]
+ # @return [Action, nil]
def perform(command)
dispatchers.push Dispatcher.dispatch(self, command)
- dispatchers.last.execute
- dispatchers.pop
+ dispatchers.last.execute.tap { dispatchers.pop }
end
# 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.
@@ -93,15 +105,14 @@
# @example
# character.execute :take, @key
#
# @param verb [Symbol]
# @param params [Array]
- # @return [Gamefic::Action]
+ # @return [Action, nil]
def execute(verb, *params)
dispatchers.push Dispatcher.dispatch_from_params(self, verb, params)
- dispatchers.last.execute
- dispatchers.pop
+ dispatchers.last.execute.tap { dispatchers.pop }
end
# 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.
@@ -123,13 +134,13 @@
# else
# actor.proceed # Execute the previous implementation
# end
# end
#
- # @return [void]
+ # @return [Action, nil]
def proceed
- dispatchers.last&.proceed&.execute
+ dispatchers.last&.proceed
end
# Cue a scene to start in the next turn.
#
# @raise [ArgumentError] if the scene is not valid
@@ -144,21 +155,26 @@
@next_cue = Cue.new(scene, **context)
end
alias prepare cue
+ # @return [void]
def start_take
ensure_cue
@last_cue = @next_cue
cue :default_scene
@props = Take.start(self, @last_cue)
+ @last_output = self.output
+ @output = @props.output.dup.freeze
end
+ # @return [void]
def finish_take
return unless @last_cue
Take.finish(self, @last_cue, @props)
+ @last_input = @props.input
end
# Restart the scene from the most recent cue.
#
# @return [Cue, nil]
@@ -173,10 +189,11 @@
#
# @raise [ArgumentError] if the requested scene is not a conclusion
#
# @param new_scene [Symbol]
# @oaram context [Hash] Additional scene data
+ # @return [Cue]
def conclude scene, **context
cue scene, **context
available = epic.select_scene(scene)
raise ArgumentError, "`#{scene}` is not a conclusion" unless available.conclusion?
@@ -184,10 +201,10 @@
end
# True if the actor is ready to leave the game.
#
def concluding?
- epic.empty? || (@last_cue && epic.conclusion?(@last_cue.scene))
+ epic.empty? || @props&.scene&.type == 'Conclusion'
end
def accessible?
false
end