gamefic 3.6.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +0 -3
- data/CHANGELOG.md +19 -0
- data/Rakefile +1 -0
- data/gamefic.gemspec +1 -1
- data/lib/gamefic/action.rb +68 -54
- data/lib/gamefic/active/cue.rb +84 -6
- data/lib/gamefic/active/messaging.rb +8 -0
- data/lib/gamefic/active/narratives.rb +101 -0
- data/lib/gamefic/active.rb +80 -92
- data/lib/gamefic/binding.rb +44 -0
- data/lib/gamefic/chapter.rb +30 -46
- data/lib/gamefic/command.rb +22 -40
- data/lib/gamefic/core_ext/array.rb +7 -7
- data/lib/gamefic/core_ext/string.rb +2 -2
- data/lib/gamefic/describable.rb +13 -0
- data/lib/gamefic/dispatcher.rb +35 -55
- data/lib/gamefic/entity.rb +6 -5
- data/lib/gamefic/expression.rb +1 -11
- data/lib/gamefic/logging.rb +3 -10
- data/lib/gamefic/match.rb +23 -0
- data/lib/gamefic/messenger.rb +1 -1
- data/lib/gamefic/narrative.rb +38 -74
- data/lib/gamefic/narrator.rb +77 -0
- data/lib/gamefic/node.rb +40 -8
- data/lib/gamefic/order.rb +53 -0
- data/lib/gamefic/plot.rb +41 -59
- data/lib/gamefic/props/default.rb +5 -17
- data/lib/gamefic/props/multiple_choice.rb +5 -2
- data/lib/gamefic/props/multiple_partial.rb +16 -0
- data/lib/gamefic/props/output.rb +7 -5
- data/lib/gamefic/props/yes_or_no.rb +2 -2
- data/lib/gamefic/props.rb +1 -0
- data/lib/gamefic/proxy/attr.rb +11 -0
- data/lib/gamefic/proxy/base.rb +3 -15
- data/lib/gamefic/proxy/config.rb +2 -2
- data/lib/gamefic/proxy/pick.rb +3 -3
- data/lib/gamefic/proxy/pick_ex.rb +11 -0
- data/lib/gamefic/proxy.rb +3 -71
- data/lib/gamefic/query/ascendants.rb +16 -0
- data/lib/gamefic/query/base.rb +47 -73
- data/lib/gamefic/query/children.rb +15 -0
- data/lib/gamefic/query/descendants.rb +17 -0
- data/lib/gamefic/query/extended.rb +20 -0
- data/lib/gamefic/query/family.rb +27 -0
- data/lib/gamefic/query/global.rb +22 -0
- data/lib/gamefic/query/integer.rb +32 -0
- data/lib/gamefic/query/myself.rb +13 -0
- data/lib/gamefic/query/parent.rb +13 -0
- data/lib/gamefic/query/result.rb +1 -1
- data/lib/gamefic/query/siblings.rb +12 -0
- data/lib/gamefic/query/subqueries.rb +17 -0
- data/lib/gamefic/query/text.rb +8 -9
- data/lib/gamefic/query.rb +11 -3
- data/lib/gamefic/request.rb +60 -0
- data/lib/gamefic/response.rb +46 -72
- data/lib/gamefic/scanner/nesting.rb +6 -6
- data/lib/gamefic/scanner/result.rb +3 -0
- data/lib/gamefic/scanner/strict.rb +14 -4
- data/lib/gamefic/scanner.rb +11 -6
- data/lib/gamefic/scene/active_choice.rb +75 -0
- data/lib/gamefic/scene/activity.rb +7 -3
- data/lib/gamefic/scene/base.rb +123 -0
- data/lib/gamefic/scene/conclusion.rb +4 -1
- data/lib/gamefic/scene/multiple_choice.rb +14 -11
- data/lib/gamefic/scene/pause.rb +5 -1
- data/lib/gamefic/scene/yes_or_no.rb +9 -0
- data/lib/gamefic/scene.rb +2 -1
- data/lib/gamefic/scriptable/hooks.rb +161 -0
- data/lib/gamefic/scriptable/queries.rb +38 -29
- data/lib/gamefic/scriptable/responses.rb +70 -0
- data/lib/gamefic/scriptable/scenes.rb +88 -115
- data/lib/gamefic/scriptable/seeds.rb +69 -0
- data/lib/gamefic/scriptable/syntaxes.rb +29 -0
- data/lib/gamefic/scriptable.rb +14 -199
- data/lib/gamefic/{scriptable → scripting}/entities.rb +22 -22
- data/lib/gamefic/scripting/hooks.rb +45 -0
- data/lib/gamefic/{scriptable → scripting}/proxies.rb +5 -3
- data/lib/gamefic/scripting/responses.rb +21 -0
- data/lib/gamefic/scripting/scenes.rb +57 -0
- data/lib/gamefic/scripting/seeds.rb +10 -0
- data/lib/gamefic/scripting/syntaxes.rb +13 -0
- data/lib/gamefic/scripting.rb +43 -0
- data/lib/gamefic/subplot.rb +11 -22
- data/lib/gamefic/syntax.rb +39 -24
- data/lib/gamefic/version.rb +1 -1
- data/lib/gamefic.rb +6 -7
- metadata +38 -41
- data/lib/gamefic/active/epic.rb +0 -74
- data/lib/gamefic/active/take.rb +0 -67
- data/lib/gamefic/block.rb +0 -28
- data/lib/gamefic/callback.rb +0 -16
- data/lib/gamefic/proxy/plot_pick.rb +0 -11
- data/lib/gamefic/query/abstract.rb +0 -12
- data/lib/gamefic/query/general.rb +0 -41
- data/lib/gamefic/query/scoped.rb +0 -27
- data/lib/gamefic/rulebook/calls.rb +0 -86
- data/lib/gamefic/rulebook/events.rb +0 -65
- data/lib/gamefic/rulebook/hooks.rb +0 -57
- data/lib/gamefic/rulebook/scenes.rb +0 -68
- data/lib/gamefic/rulebook.rb +0 -125
- data/lib/gamefic/scene/default.rb +0 -88
- data/lib/gamefic/scope/base.rb +0 -44
- data/lib/gamefic/scope/children.rb +0 -16
- data/lib/gamefic/scope/descendants.rb +0 -16
- data/lib/gamefic/scope/family.rb +0 -43
- data/lib/gamefic/scope/myself.rb +0 -13
- data/lib/gamefic/scope/parent.rb +0 -13
- data/lib/gamefic/scope/siblings.rb +0 -14
- data/lib/gamefic/scope.rb +0 -9
- data/lib/gamefic/scriptable/actions.rb +0 -137
- data/lib/gamefic/scriptable/events.rb +0 -71
- data/lib/gamefic/scriptable/plot_proxies.rb +0 -29
- data/lib/gamefic/snapshot.rb +0 -44
- data/lib/gamefic/stage.rb +0 -51
- data/lib/gamefic/syntax/template.rb +0 -67
- data/lib/gamefic/vault.rb +0 -52
data/lib/gamefic/active/epic.rb
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
module Active
|
|
5
|
-
# A collection of narratives.
|
|
6
|
-
#
|
|
7
|
-
class Epic
|
|
8
|
-
include Logging
|
|
9
|
-
|
|
10
|
-
# @return [Set<Narrative>]
|
|
11
|
-
attr_reader :narratives
|
|
12
|
-
|
|
13
|
-
def initialize
|
|
14
|
-
@narratives = Set.new
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# @param narrative [Narrative]
|
|
18
|
-
def add narrative
|
|
19
|
-
narratives.add narrative
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# @param narrative [Narrative]
|
|
23
|
-
def delete narrative
|
|
24
|
-
narratives.delete narrative
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# @return [Array<Rulebook>]
|
|
28
|
-
def rulebooks
|
|
29
|
-
narratives.map(&:rulebook)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# @return [Array<Symbol>]
|
|
33
|
-
def verbs
|
|
34
|
-
rulebooks.flat_map(&:verbs).uniq
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# @return [Array<Symbol>]
|
|
38
|
-
def synonyms
|
|
39
|
-
rulebooks.flat_map(&:synonyms).uniq
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def empty?
|
|
43
|
-
narratives.empty?
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def one?
|
|
47
|
-
narratives.one?
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def syntaxes
|
|
51
|
-
rulebooks.flat_map(&:syntaxes)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# @return [Array<Response>]
|
|
55
|
-
def responses_for(*verbs)
|
|
56
|
-
rulebooks.to_a
|
|
57
|
-
.reverse
|
|
58
|
-
.flat_map { |rb| rb.responses_for(*verbs) }
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# @param name [Symbol]
|
|
62
|
-
# @return [Scene]
|
|
63
|
-
def select_scene name
|
|
64
|
-
scenes = rulebooks.map { |rlbk| rlbk.scenes[name] }
|
|
65
|
-
.compact
|
|
66
|
-
raise ArgumentError, "Scene named `#{name}` does not exist" if scenes.empty?
|
|
67
|
-
|
|
68
|
-
logger.warn "Found #{scenes.length} scenes named `#{name}`" unless scenes.one?
|
|
69
|
-
|
|
70
|
-
scenes.last
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
data/lib/gamefic/active/take.rb
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
module Active
|
|
5
|
-
# The combination of an actor and a scene to be performed in a plot turn.
|
|
6
|
-
#
|
|
7
|
-
class Take
|
|
8
|
-
# @return [Active]
|
|
9
|
-
attr_reader :actor
|
|
10
|
-
|
|
11
|
-
# @return [Active::Cue]
|
|
12
|
-
attr_reader :cue
|
|
13
|
-
|
|
14
|
-
# @return [Scene::Default]
|
|
15
|
-
attr_reader :scene
|
|
16
|
-
|
|
17
|
-
# @param actor [Active]
|
|
18
|
-
# @param cue [Active::Cue]
|
|
19
|
-
# @param props [Props::Default, nil]
|
|
20
|
-
def initialize actor, cue, props = nil
|
|
21
|
-
@actor = actor
|
|
22
|
-
@cue = cue
|
|
23
|
-
@scene = actor.epic.select_scene(cue.scene)
|
|
24
|
-
@props = props
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# @return [Props::Default]
|
|
28
|
-
def props
|
|
29
|
-
@props ||= @scene.new_props(**cue.context)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# @return [Props::Default]
|
|
33
|
-
def start
|
|
34
|
-
scene.run_start_blocks actor, props
|
|
35
|
-
scene.start actor, props
|
|
36
|
-
# @todo See if this can be handled better
|
|
37
|
-
actor.epic.rulebooks.each { |rlbk| rlbk.run_player_output_blocks actor, props.output }
|
|
38
|
-
props.output.merge!({
|
|
39
|
-
messages: actor.messages,
|
|
40
|
-
queue: actor.queue
|
|
41
|
-
})
|
|
42
|
-
props
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# @return [void]
|
|
46
|
-
def finish
|
|
47
|
-
actor.flush
|
|
48
|
-
scene.finish(actor, props)
|
|
49
|
-
scene.run_finish_blocks actor, props
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# @param actor [Active]
|
|
53
|
-
# @param cue [Active::Cue]
|
|
54
|
-
# @return [Props::Default]
|
|
55
|
-
def self.start actor, cue
|
|
56
|
-
Take.new(actor, cue).start
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
# @param actor [Active]
|
|
60
|
-
# @param cue [Active::Cue]
|
|
61
|
-
# @return [void]
|
|
62
|
-
def self.finish actor, cue, props
|
|
63
|
-
Take.new(actor, cue, props).finish
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
data/lib/gamefic/block.rb
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
# A code container for seeds and scripts.
|
|
5
|
-
#
|
|
6
|
-
class Block
|
|
7
|
-
# @return [Symbol]
|
|
8
|
-
attr_reader :type
|
|
9
|
-
|
|
10
|
-
# @return [Proc]
|
|
11
|
-
attr_reader :code
|
|
12
|
-
|
|
13
|
-
# @param type [Symbol]
|
|
14
|
-
# @param code [Proc]
|
|
15
|
-
def initialize type, code
|
|
16
|
-
@type = type
|
|
17
|
-
@code = code
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def script?
|
|
21
|
-
type == :script
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def seed?
|
|
25
|
-
type == :seed
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
data/lib/gamefic/callback.rb
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
class Callback
|
|
5
|
-
# @param narrative [Narrative]
|
|
6
|
-
# @param code [Proc]
|
|
7
|
-
def initialize narrative, code
|
|
8
|
-
@narrative = narrative
|
|
9
|
-
@code = code
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def run *args
|
|
13
|
-
Stage.run @narrative, *args, &@code
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
module Query
|
|
5
|
-
# A General query accepts an array of entities to filter. Unlike Scoped
|
|
6
|
-
# queries, the resulting entities will not necessarily be in the actor's
|
|
7
|
-
# immediate vicinity.
|
|
8
|
-
#
|
|
9
|
-
# General queries can also be passed a Proc that returns an array of
|
|
10
|
-
# entities. If the Proc accepts an argument, it will be given the subject
|
|
11
|
-
# of the query.
|
|
12
|
-
#
|
|
13
|
-
class General < Base
|
|
14
|
-
# @param entities [Array, Proc]
|
|
15
|
-
# @param arguments [Array<Object>]
|
|
16
|
-
# @param ambiguous [Boolean]
|
|
17
|
-
def initialize entities, *arguments, ambiguous: false, name: nil
|
|
18
|
-
super(*arguments, ambiguous: ambiguous, name: name)
|
|
19
|
-
@entities = entities
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def span subject
|
|
23
|
-
available_entities(subject)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
def available_entities(subject)
|
|
29
|
-
if @entities.is_a?(Proc)
|
|
30
|
-
if @entities.arity.zero?
|
|
31
|
-
Stage.run narrative, &@entities
|
|
32
|
-
else
|
|
33
|
-
Stage.run narrative, subject, &@entities
|
|
34
|
-
end
|
|
35
|
-
else
|
|
36
|
-
@entities
|
|
37
|
-
end
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
data/lib/gamefic/query/scoped.rb
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
module Query
|
|
5
|
-
# A Scoped query uses a Scope to select entities to filter based on their
|
|
6
|
-
# relationship to the entity performing the query. For example,
|
|
7
|
-
# Scope::Children would filter from an array of the entity's descendants.
|
|
8
|
-
#
|
|
9
|
-
class Scoped < Base
|
|
10
|
-
attr_reader :scope
|
|
11
|
-
|
|
12
|
-
# @param scope [Class<Gamefic::Scope::Base>]
|
|
13
|
-
def initialize scope, *arguments, ambiguous: false, name: nil
|
|
14
|
-
super(*arguments, ambiguous: ambiguous, name: name)
|
|
15
|
-
@scope = scope
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def span(subject)
|
|
19
|
-
@scope.matches(subject)
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def precision
|
|
23
|
-
@precision ||= @scope.precision + calculate_precision
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
class Rulebook
|
|
5
|
-
# A collection of responses and syntaxes that constitute the actions
|
|
6
|
-
# available to actors.
|
|
7
|
-
#
|
|
8
|
-
class Calls
|
|
9
|
-
def initialize
|
|
10
|
-
@verb_response_map = Hash.new { |hash, key| hash[key] = [] }
|
|
11
|
-
@synonym_syntax_map = Hash.new { |hash, key| hash[key] = [] }
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def freeze
|
|
15
|
-
super
|
|
16
|
-
@verb_response_map.freeze
|
|
17
|
-
@verb_response_map.values.map(&:freeze)
|
|
18
|
-
@synonym_syntax_map.freeze
|
|
19
|
-
@synonym_syntax_map.values.map(&:freeze)
|
|
20
|
-
self
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def syntaxes
|
|
24
|
-
synonym_syntax_map.values.flatten
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def synonyms
|
|
28
|
-
synonym_syntax_map.keys.compact.sort
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def responses
|
|
32
|
-
verb_response_map.values.flatten
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def verbs
|
|
36
|
-
verb_response_map.keys.compact.sort
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def responses_for *verbs
|
|
40
|
-
verbs.flat_map { |verb| verb_response_map.fetch(verb, []) }
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def syntaxes_for *synonyms
|
|
44
|
-
synonyms.flat_map { |syn| synonym_syntax_map.fetch(syn, []) }
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def add_response response
|
|
48
|
-
verb_response_map[response.verb].unshift response
|
|
49
|
-
sort_responses_for response.verb
|
|
50
|
-
add_syntax response.syntax unless response.verb.to_s.start_with?('_')
|
|
51
|
-
response
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# @param syntax [Syntax]
|
|
55
|
-
# @return [Syntax]
|
|
56
|
-
def add_syntax syntax
|
|
57
|
-
raise "No responses exist for \"#{syntax.verb}\"" unless verb_response_map.key?(syntax.verb)
|
|
58
|
-
|
|
59
|
-
return if synonym_syntax_map[syntax.synonym].include?(syntax)
|
|
60
|
-
|
|
61
|
-
synonym_syntax_map[syntax.synonym].unshift syntax
|
|
62
|
-
sort_syntaxes_for syntax.synonym
|
|
63
|
-
syntax
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def empty?
|
|
67
|
-
verb_response_map.empty? && synonym_syntax_map.empty?
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
private
|
|
71
|
-
|
|
72
|
-
attr_reader :verb_response_map
|
|
73
|
-
|
|
74
|
-
attr_reader :synonym_syntax_map
|
|
75
|
-
|
|
76
|
-
# @param responses [Array<Response>]
|
|
77
|
-
def sort_responses_for verb
|
|
78
|
-
verb_response_map[verb].sort_by!.with_index { |a, i| [a.precision, -i] }.reverse!
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def sort_syntaxes_for synonym
|
|
82
|
-
synonym_syntax_map[synonym].sort! { |a, b| a.compare b }
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
end
|
|
86
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
class Rulebook
|
|
5
|
-
# Blocks of code to be executed for various narrative events, such as
|
|
6
|
-
# on_ready and on_update.
|
|
7
|
-
#
|
|
8
|
-
class Events
|
|
9
|
-
attr_reader :player_output_blocks
|
|
10
|
-
|
|
11
|
-
attr_reader :player_conclude_blocks
|
|
12
|
-
|
|
13
|
-
attr_reader :ready_blocks
|
|
14
|
-
|
|
15
|
-
attr_reader :update_blocks
|
|
16
|
-
|
|
17
|
-
attr_reader :conclude_blocks
|
|
18
|
-
|
|
19
|
-
def initialize
|
|
20
|
-
@ready_blocks = []
|
|
21
|
-
@update_blocks = []
|
|
22
|
-
@conclude_blocks = []
|
|
23
|
-
@player_conclude_blocks = []
|
|
24
|
-
@player_output_blocks = []
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def empty?
|
|
28
|
-
[player_output_blocks, player_conclude_blocks, ready_blocks, update_blocks, conclude_blocks].all?(&:empty?)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def freeze
|
|
32
|
-
super
|
|
33
|
-
instance_variables.each { |k| instance_variable_get(k).freeze }
|
|
34
|
-
self
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# @return [void]
|
|
38
|
-
def on_ready callback
|
|
39
|
-
@ready_blocks.push callback
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def on_update callback
|
|
43
|
-
@update_blocks.push callback
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# @return [void]
|
|
47
|
-
def on_conclude callback
|
|
48
|
-
@conclude_blocks.push callback
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# @yieldparam [Actor]
|
|
52
|
-
# @return [void]
|
|
53
|
-
def on_player_conclude callback
|
|
54
|
-
@player_conclude_blocks.push callback
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# @yieldparam [Actor]
|
|
58
|
-
# @yieldparam [Hash]
|
|
59
|
-
# @return [void]
|
|
60
|
-
def on_player_output callback
|
|
61
|
-
@player_output_blocks.push callback
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
class Rulebook
|
|
5
|
-
# A collection of hooks that can be executed before and after an action.
|
|
6
|
-
#
|
|
7
|
-
class Hooks
|
|
8
|
-
attr_reader :before_actions
|
|
9
|
-
|
|
10
|
-
attr_reader :after_actions
|
|
11
|
-
|
|
12
|
-
def initialize
|
|
13
|
-
@before_actions = []
|
|
14
|
-
@after_actions = []
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def freeze
|
|
18
|
-
super
|
|
19
|
-
@before_actions.freeze
|
|
20
|
-
@after_actions.freeze
|
|
21
|
-
self
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def before_action narrative, *verbs, &block
|
|
25
|
-
before_actions.push Action::Hook.new(verbs, Callback.new(narrative, block))
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def after_action narrative, *verbs, &block
|
|
29
|
-
after_actions.push Action::Hook.new(verbs, Callback.new(narrative, block))
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def empty?
|
|
33
|
-
before_actions.empty? && after_actions.empty?
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def run_before action
|
|
37
|
-
run_action_hooks action, before_actions
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def run_after action
|
|
41
|
-
run_action_hooks action, after_actions
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
private
|
|
45
|
-
|
|
46
|
-
def run_action_hooks action, hooks
|
|
47
|
-
hooks.each do |hook|
|
|
48
|
-
break if action.cancelled?
|
|
49
|
-
|
|
50
|
-
next unless hook.match?(action.verb)
|
|
51
|
-
|
|
52
|
-
hook.callback.run action
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
end
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Gamefic
|
|
4
|
-
class Rulebook
|
|
5
|
-
# The scene manager for rulebooks.
|
|
6
|
-
#
|
|
7
|
-
class Scenes
|
|
8
|
-
attr_reader :introductions
|
|
9
|
-
|
|
10
|
-
def initialize
|
|
11
|
-
@scene_map = {}
|
|
12
|
-
@introductions = []
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def freeze
|
|
16
|
-
super
|
|
17
|
-
@scene_map.freeze
|
|
18
|
-
@introductions.freeze
|
|
19
|
-
self
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Add a scene to the scenebook.
|
|
23
|
-
#
|
|
24
|
-
# @param [Scene]
|
|
25
|
-
def add scene
|
|
26
|
-
raise ArgumentError, "A scene named `#{scene.name} already exists" if @scene_map.key?(scene.name)
|
|
27
|
-
|
|
28
|
-
@scene_map[scene.name] = scene
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def scene? name
|
|
32
|
-
@scene_map.key? name
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# @return [Scene, nil]
|
|
36
|
-
def [](name)
|
|
37
|
-
@scene_map[name]
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# @return [Array<Symbol>]
|
|
41
|
-
def names
|
|
42
|
-
@scene_map.keys
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# @return [Array<Scene>]
|
|
46
|
-
def all
|
|
47
|
-
@scene_map.values
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def introduction scene
|
|
51
|
-
introductions.push scene
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def with_defaults narrative
|
|
55
|
-
maybe_add :default_scene, Scene::Activity, narrative
|
|
56
|
-
maybe_add :default_conclusion, Scene::Conclusion, narrative
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def maybe_add name, klass, narrative
|
|
60
|
-
add klass.new(name, narrative) unless names.include?(name)
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def empty?
|
|
64
|
-
@scene_map.empty? && introductions.empty?
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|
data/lib/gamefic/rulebook.rb
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'gamefic/rulebook/calls'
|
|
4
|
-
require 'gamefic/rulebook/events'
|
|
5
|
-
require 'gamefic/rulebook/hooks'
|
|
6
|
-
require 'gamefic/rulebook/scenes'
|
|
7
|
-
|
|
8
|
-
module Gamefic
|
|
9
|
-
# A collection of rules that define the behavior of a narrative.
|
|
10
|
-
#
|
|
11
|
-
# Rulebooks provide a way to separate narrative data from code. This
|
|
12
|
-
# separation is necessary to ensure that the game state can be serialized in
|
|
13
|
-
# snapshots.
|
|
14
|
-
#
|
|
15
|
-
class Rulebook
|
|
16
|
-
# @return [Calls]
|
|
17
|
-
attr_reader :calls
|
|
18
|
-
|
|
19
|
-
# @return [Events]
|
|
20
|
-
attr_reader :events
|
|
21
|
-
|
|
22
|
-
# @return [Hooks]
|
|
23
|
-
attr_reader :hooks
|
|
24
|
-
|
|
25
|
-
# @return [Scenes]
|
|
26
|
-
attr_reader :scenes
|
|
27
|
-
|
|
28
|
-
def initialize
|
|
29
|
-
@calls = Calls.new
|
|
30
|
-
@events = Events.new
|
|
31
|
-
@hooks = Hooks.new
|
|
32
|
-
@scenes = Scenes.new
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def freeze
|
|
36
|
-
super
|
|
37
|
-
[@calls, @events, @hooks, @scenes].each(&:freeze)
|
|
38
|
-
self
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
# @return [Array<Response>]
|
|
42
|
-
def responses
|
|
43
|
-
@calls.responses
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# @return [Array<Syntax>]
|
|
47
|
-
def syntaxes
|
|
48
|
-
@calls.syntaxes
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# An array of all the verbs available in the rulebook. This list only
|
|
52
|
-
# includes verbs that are explicitly defined in reponses. It excludes
|
|
53
|
-
# synonyms that might be defined in syntaxes (see #synonyms).
|
|
54
|
-
#
|
|
55
|
-
# @example
|
|
56
|
-
# rulebook.respond :verb { |_| nil }
|
|
57
|
-
# rulebook.interpret 'synonym', 'verb'
|
|
58
|
-
# rulebook.verbs #=> [:verb]
|
|
59
|
-
#
|
|
60
|
-
# @return [Array<Symbol>]
|
|
61
|
-
def verbs
|
|
62
|
-
@calls.verbs
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# An array of all the verbs defined in responses and any synonyms defined
|
|
66
|
-
# in syntaxes.
|
|
67
|
-
#
|
|
68
|
-
# @example
|
|
69
|
-
# rulebook.respond :verb { |_| nil }
|
|
70
|
-
# rulebook.interpret 'synonym', 'verb'
|
|
71
|
-
# rulebook.synonyms #=> [:synonym, :verb]
|
|
72
|
-
#
|
|
73
|
-
def synonyms
|
|
74
|
-
@calls.synonyms
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
# Get an array of all the responses that match a list of verbs.
|
|
78
|
-
#
|
|
79
|
-
# @param verbs [Array<Symbol>]
|
|
80
|
-
# @return [Array<Response>]
|
|
81
|
-
def responses_for *verbs
|
|
82
|
-
@calls.responses_for *verbs
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Get an array of all the syntaxes that match a lit of verbs.
|
|
86
|
-
#
|
|
87
|
-
# @param words [Array<Symbol>]
|
|
88
|
-
# @return [Array<Syntax>]
|
|
89
|
-
def syntaxes_for *synonyms
|
|
90
|
-
@calls.syntaxes_for *synonyms
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def run_ready_blocks
|
|
94
|
-
events.ready_blocks.each(&:run)
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
def run_update_blocks
|
|
98
|
-
events.update_blocks.each(&:run)
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def run_before_actions action
|
|
102
|
-
hooks.run_before action
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def run_after_actions action
|
|
106
|
-
hooks.run_after action
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def run_conclude_blocks
|
|
110
|
-
events.conclude_blocks.each(&:run)
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def run_player_conclude_blocks player
|
|
114
|
-
events.player_conclude_blocks.each { |blk| blk.run(player) }
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def run_player_output_blocks player, output
|
|
118
|
-
events.player_output_blocks.each { |blk| blk.run(player, output) }
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
def empty?
|
|
122
|
-
calls.empty? && hooks.empty? && scenes.empty? && events.empty?
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|