lib/gamefic/narrative.rb
# frozen_string_literal: true require 'corelib/marshal' if RUBY_ENGINE == 'opal' # Required in browser module Gamefic # A base class for building and managing the resources that compose a story. # The Plot and Subplot classes inherit from Narrative and provide additional # functionality. # class Narrative include Scripting # @!parse extend Gamefic::Scriptable select_default_scene Scene::Activity select_default_conclusion Scene::Conclusion def initialize seeds.each { |blk| instance_exec(&blk) } end # Introduce an actor to the story. # # @param player [Gamefic::Actor] # @return [Gamefic::Actor] def introduce(player = Gamefic::Actor.new) cast player introductions.each { |blk| blk[player] } player end # A narrative is considered to be concluding when all of its players are in # a conclusion scene. Engines can use this method to determine whether the # game is ready to end. # def concluding? players.empty? || players.all?(&:concluding?) end # Add an active entity to the narrative. # # @param active [Gamefic::Active] # @return [Gamefic::Active] def cast(active) active.narratives.add self player_set.add active entity_set.add active active end # Remove an active entity from the narrative. # # @param active [Gamefic::Active] # @return [Gamefic::Active] def uncast(active) active.narratives.delete self player_set.delete active entity_set.delete active active end # Complete a game turn. # # In the base Narrative class, this method runs all applicable player # conclude blocks and the narrative's own conclude blocks. # # @return [void] def turn players.select(&:concluding?).each { |plyr| player_conclude_blocks.each { |blk| blk[plyr] } } conclude_blocks.each(&:call) if concluding? end # @return [String] def save Marshal.dump(self) end # @param snapshot [String] # @return [self] def self.restore(snapshot) Marshal.load(snapshot) end def self.inherited(klass) super klass.seeds.concat seeds klass.select_default_scene default_scene klass.select_default_conclusion default_conclusion end end end