gamefic 2.4.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rspec.yml +41 -40
- data/.rspec-opal +2 -0
- data/.solargraph.yml +20 -3
- data/CHANGELOG.md +18 -0
- data/Rakefile +11 -1
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/gamefic.gemspec +5 -2
- data/lib/gamefic/action.rb +58 -181
- data/lib/gamefic/active/cue.rb +25 -0
- data/lib/gamefic/active/epic.rb +73 -0
- data/lib/gamefic/active/messaging.rb +43 -0
- data/lib/gamefic/active/take.rb +69 -0
- data/lib/gamefic/active.rb +111 -191
- data/lib/gamefic/actor.rb +2 -0
- data/lib/gamefic/block.rb +28 -0
- data/lib/gamefic/command.rb +6 -7
- data/lib/gamefic/composer.rb +68 -0
- data/lib/gamefic/core_ext/array.rb +4 -4
- data/lib/gamefic/core_ext/string.rb +10 -5
- data/lib/gamefic/describable.rb +39 -65
- data/lib/gamefic/dispatcher.rb +79 -41
- data/lib/gamefic/entity.rb +42 -19
- data/lib/gamefic/expression.rb +31 -0
- data/lib/gamefic/logging.rb +32 -0
- data/lib/gamefic/messenger.rb +66 -0
- data/lib/gamefic/narrative.rb +104 -0
- data/lib/gamefic/node.rb +44 -53
- data/lib/gamefic/plot.rb +60 -93
- data/lib/gamefic/props/default.rb +49 -0
- data/lib/gamefic/props/multiple_choice.rb +65 -0
- data/lib/gamefic/props/output.rb +82 -0
- data/lib/gamefic/props/pause.rb +11 -0
- data/lib/gamefic/props/yes_or_no.rb +21 -0
- data/lib/gamefic/props.rb +11 -0
- data/lib/gamefic/query/base.rb +64 -121
- data/lib/gamefic/query/general.rb +50 -0
- data/lib/gamefic/query/result.rb +20 -0
- data/lib/gamefic/query/scoped.rb +46 -0
- data/lib/gamefic/query/text.rb +43 -33
- data/lib/gamefic/query.rb +7 -15
- data/lib/gamefic/response.rb +112 -0
- data/lib/gamefic/rulebook/calls.rb +90 -0
- data/lib/gamefic/rulebook/events.rb +79 -0
- data/lib/gamefic/rulebook/hooks.rb +57 -0
- data/lib/gamefic/rulebook/scenes.rb +68 -0
- data/lib/gamefic/rulebook.rb +139 -0
- data/lib/gamefic/scanner.rb +130 -0
- data/lib/gamefic/scene/activity.rb +9 -17
- data/lib/gamefic/scene/conclusion.rb +6 -5
- data/lib/gamefic/scene/default.rb +88 -0
- data/lib/gamefic/scene/multiple_choice.rb +14 -69
- data/lib/gamefic/scene/pause.rb +9 -13
- data/lib/gamefic/scene/yes_or_no.rb +6 -46
- data/lib/gamefic/scene.rb +11 -7
- data/lib/gamefic/scope/base.rb +44 -0
- data/lib/gamefic/scope/children.rb +16 -0
- data/lib/gamefic/scope/family.rb +20 -0
- data/lib/gamefic/scope/myself.rb +13 -0
- data/lib/gamefic/scope/parent.rb +13 -0
- data/lib/gamefic/scope/siblings.rb +14 -0
- data/lib/gamefic/scope.rb +8 -0
- data/lib/gamefic/scriptable/actions.rb +156 -0
- data/lib/gamefic/scriptable/entities.rb +79 -0
- data/lib/gamefic/scriptable/events.rb +65 -0
- data/lib/gamefic/scriptable/proxy.rb +66 -0
- data/lib/gamefic/scriptable/queries.rb +73 -0
- data/lib/gamefic/scriptable/scenes.rb +162 -0
- data/lib/gamefic/scriptable.rb +167 -73
- data/lib/gamefic/snapshot.rb +44 -0
- data/lib/gamefic/stage.rb +51 -0
- data/lib/gamefic/subplot.rb +51 -79
- data/lib/gamefic/syntax/template.rb +67 -0
- data/lib/gamefic/syntax.rb +102 -83
- data/lib/gamefic/vault.rb +50 -0
- data/lib/gamefic/version.rb +1 -1
- data/lib/gamefic.rb +28 -15
- data/spec-opal/spec_helper.rb +24 -0
- metadata +94 -29
- data/lib/gamefic/element.rb +0 -46
- data/lib/gamefic/keywords.rb +0 -52
- data/lib/gamefic/messaging.rb +0 -43
- data/lib/gamefic/plot/darkroom.rb +0 -120
- data/lib/gamefic/plot/host.rb +0 -42
- data/lib/gamefic/plot/snapshot.rb +0 -27
- data/lib/gamefic/query/children.rb +0 -9
- data/lib/gamefic/query/descendants.rb +0 -15
- data/lib/gamefic/query/external.rb +0 -39
- data/lib/gamefic/query/family.rb +0 -18
- data/lib/gamefic/query/itself.rb +0 -13
- data/lib/gamefic/query/matches.rb +0 -75
- data/lib/gamefic/query/parent.rb +0 -9
- data/lib/gamefic/query/siblings.rb +0 -13
- data/lib/gamefic/query/tree.rb +0 -17
- data/lib/gamefic/scene/base.rb +0 -142
- data/lib/gamefic/scene/multiple_scene.rb +0 -29
- data/lib/gamefic/serialize.rb +0 -196
- data/lib/gamefic/world/callbacks.rb +0 -135
- data/lib/gamefic/world/commands.rb +0 -181
- data/lib/gamefic/world/entities.rb +0 -98
- data/lib/gamefic/world/playbook.rb +0 -233
- data/lib/gamefic/world/players.rb +0 -37
- data/lib/gamefic/world/scenes.rb +0 -228
- data/lib/gamefic/world.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3900923aaef12a43321ce6f9cc5957953b12bba7d939e0a1666d8c6c75703855
|
4
|
+
data.tar.gz: 6023310c5e26e9632ed4c053a9bea619e1455dbb66966d82fc9e772044d19d3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aea9a57211541f056c730707227020f2c35376d59cc4e69c3c7463e8a8bafa7b6fcd4585a99bf2ce235fdc4c583393f53e060554e06f6e5912358959305627eb
|
7
|
+
data.tar.gz: 5351ea7cc8b3ff4e01e064eb12a594dc2d928641b19e8593243da00b672780acff0d808d73eca1a80cf2e2139fd657b870fa7a5a5315e0a2a3998bc306db0c05
|
data/.github/workflows/rspec.yml
CHANGED
@@ -1,40 +1,41 @@
|
|
1
|
-
# This workflow uses actions that are not certified by GitHub.
|
2
|
-
# They are provided by a third-party and are governed by
|
3
|
-
# separate terms of service, privacy policy, and support
|
4
|
-
# documentation.
|
5
|
-
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with rspec.
|
6
|
-
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
-
|
8
|
-
name: RSpec
|
9
|
-
|
10
|
-
on:
|
11
|
-
push:
|
12
|
-
branches: [ master ]
|
13
|
-
pull_request:
|
14
|
-
branches: [ master ]
|
15
|
-
|
16
|
-
permissions:
|
17
|
-
contents: read
|
18
|
-
|
19
|
-
jobs:
|
20
|
-
test:
|
21
|
-
|
22
|
-
runs-on: ubuntu-latest
|
23
|
-
strategy:
|
24
|
-
matrix:
|
25
|
-
ruby-version: ['2.
|
26
|
-
|
27
|
-
steps:
|
28
|
-
- uses: actions/checkout@v3
|
29
|
-
- name: Set up Ruby
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
2
|
+
# They are provided by a third-party and are governed by
|
3
|
+
# separate terms of service, privacy policy, and support
|
4
|
+
# documentation.
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with rspec.
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
7
|
+
|
8
|
+
name: RSpec
|
9
|
+
|
10
|
+
on:
|
11
|
+
push:
|
12
|
+
branches: [ master ]
|
13
|
+
pull_request:
|
14
|
+
branches: [ master ]
|
15
|
+
|
16
|
+
permissions:
|
17
|
+
contents: read
|
18
|
+
|
19
|
+
jobs:
|
20
|
+
test:
|
21
|
+
|
22
|
+
runs-on: ubuntu-latest
|
23
|
+
strategy:
|
24
|
+
matrix:
|
25
|
+
ruby-version: ['2.7', '3.0', '3.1']
|
26
|
+
|
27
|
+
steps:
|
28
|
+
- uses: actions/checkout@v3
|
29
|
+
- name: Set up Ruby
|
30
|
+
uses: ruby/setup-ruby@v1
|
31
|
+
with:
|
32
|
+
ruby-version: ${{ matrix.ruby-version }}
|
33
|
+
bundler-cache: false
|
34
|
+
- name: Set up Node
|
35
|
+
uses: actions/setup-node@v3
|
36
|
+
- name: Install dependencies
|
37
|
+
run: bundle install
|
38
|
+
- name: Run Ruby tests
|
39
|
+
run: bundle exec rspec
|
40
|
+
- name: Run Opal tests
|
41
|
+
run: bundle exec rake opal
|
data/.rspec-opal
ADDED
data/.solargraph.yml
CHANGED
@@ -1,5 +1,22 @@
|
|
1
|
+
---
|
1
2
|
include:
|
2
|
-
|
3
|
+
- "**/*.rb"
|
3
4
|
exclude:
|
4
|
-
|
5
|
-
|
5
|
+
- spec/**/*
|
6
|
+
- test/**/*
|
7
|
+
- vendor/**/*
|
8
|
+
- ".bundle/**/*"
|
9
|
+
require: []
|
10
|
+
domains: []
|
11
|
+
reporters:
|
12
|
+
- rubocop
|
13
|
+
- require_not_found
|
14
|
+
formatter:
|
15
|
+
rubocop:
|
16
|
+
cops: safe
|
17
|
+
except: []
|
18
|
+
only: []
|
19
|
+
extra_args: []
|
20
|
+
require_paths: []
|
21
|
+
plugins: []
|
22
|
+
max_files: 5000
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
## 3.1.0 - April 8, 2024
|
2
|
+
- Dispatcher prioritizes strict token matches
|
3
|
+
- Scanner builds commands
|
4
|
+
- Tokenize expressions and execute commands
|
5
|
+
- Delete concluded subplots last in Plot#ready
|
6
|
+
- Fix plot conclusion check after subplots conclude
|
7
|
+
- Correct contexts for conclude and output blocks
|
8
|
+
- Reinstate Active#last_input
|
9
|
+
|
10
|
+
## 3.0.0 - January 27, 2024
|
11
|
+
- Instantiate subplots from snapshots
|
12
|
+
- Split Action into Response and Action
|
13
|
+
- Logging
|
14
|
+
- Remove deprecated Active#perform behavior
|
15
|
+
- Snapshots use single static index
|
16
|
+
- Hydration improvements
|
17
|
+
- Snapshot metadata validation
|
18
|
+
|
1
19
|
## 2.4.0 - February 11, 2023
|
2
20
|
- Fix arity of delegated methods in scripts
|
3
21
|
- Action hooks accept verb filters
|
data/Rakefile
CHANGED
@@ -1,5 +1,9 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
2
5
|
require 'rspec/core/rake_task'
|
6
|
+
require 'opal/rspec/rake_task'
|
3
7
|
|
4
8
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
5
9
|
t.pattern = Dir.glob('spec/**/*_spec.rb')
|
@@ -8,3 +12,9 @@ RSpec::Core::RakeTask.new(:spec) do |t|
|
|
8
12
|
#t.rcov = true
|
9
13
|
end
|
10
14
|
task :default => :spec
|
15
|
+
|
16
|
+
Opal::RSpec::RakeTask.new(:opal) do |_, config|
|
17
|
+
Opal.append_path File.expand_path('../lib', __FILE__)
|
18
|
+
config.pattern = 'spec/**/*_spec.rb'
|
19
|
+
config.requires = ['spec_helper']
|
20
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "gamefic-sdk"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/gamefic.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.description = "An adventure game and interactive fiction framework"
|
12
12
|
s.authors = ["Fred Snyder"]
|
13
13
|
s.email = 'fsnyder@gamefic.com'
|
14
|
-
s.homepage = '
|
14
|
+
s.homepage = 'https://gamefic.com'
|
15
15
|
s.license = 'MIT'
|
16
16
|
|
17
17
|
s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
@@ -19,8 +19,11 @@ Gem::Specification.new do |s|
|
|
19
19
|
end
|
20
20
|
s.require_paths = ['lib']
|
21
21
|
|
22
|
-
s.required_ruby_version = '>= 2.
|
22
|
+
s.required_ruby_version = '>= 2.7.0'
|
23
23
|
|
24
|
+
s.add_development_dependency 'opal', '~> 1.7'
|
25
|
+
s.add_development_dependency 'opal-rspec', '~> 1.0'
|
26
|
+
s.add_development_dependency 'opal-sprockets', '~> 1.0'
|
24
27
|
s.add_development_dependency 'rake', '~> 12.3', '>= 12.3'
|
25
28
|
s.add_development_dependency 'rspec', '~> 3.5', '>= 3.5.0'
|
26
29
|
s.add_development_dependency 'simplecov', '~> 0.14'
|
data/lib/gamefic/action.rb
CHANGED
@@ -1,213 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gamefic
|
4
|
+
# The handler for executing responses for a provided actor and array of
|
5
|
+
# arguments. It's also responsible for executing before_action and
|
6
|
+
# after_action hooks if necessary.
|
7
|
+
#
|
2
8
|
class Action
|
3
|
-
|
4
|
-
attr_reader :actor
|
9
|
+
include Logging
|
5
10
|
|
6
|
-
#
|
7
|
-
#
|
11
|
+
# Hooks are blocks of code that get executed before or after an actor
|
12
|
+
# performs an action. A before action hook is capable of cancelling the
|
13
|
+
# action's performance.
|
8
14
|
#
|
9
|
-
|
15
|
+
class Hook
|
16
|
+
# @param [Array<Symbol>]
|
17
|
+
attr_reader :verbs
|
18
|
+
|
19
|
+
# @param [Proc]
|
20
|
+
attr_reader :block
|
21
|
+
|
22
|
+
def initialize *verbs, &block
|
23
|
+
@verbs = verbs
|
24
|
+
@block = block
|
25
|
+
end
|
26
|
+
|
27
|
+
def match?(input)
|
28
|
+
verbs.empty? || verbs.include?(input)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# @return [Active]
|
33
|
+
attr_reader :actor
|
34
|
+
|
35
|
+
# @return [Array]
|
10
36
|
attr_reader :arguments
|
11
|
-
alias parameters arguments
|
12
37
|
|
13
|
-
# @
|
14
|
-
|
15
|
-
|
38
|
+
# @return [Response]
|
39
|
+
attr_reader :response
|
40
|
+
|
41
|
+
# @param actor [Active]
|
42
|
+
# @param arguments [Array]
|
43
|
+
# @param response [Response]
|
44
|
+
def initialize actor, arguments, response
|
16
45
|
@actor = actor
|
17
46
|
@arguments = arguments
|
18
|
-
@
|
19
|
-
@with_callbacks = with_callbacks
|
47
|
+
@response = response
|
20
48
|
end
|
21
49
|
|
22
|
-
#
|
23
|
-
#
|
50
|
+
# @return [self]
|
24
51
|
def execute
|
25
|
-
return if
|
26
|
-
|
27
|
-
return if @cancelled
|
28
|
-
self.class.executor.call(@actor, *arguments) unless self.class.executor.nil?
|
52
|
+
return self if cancelled? || executed?
|
53
|
+
|
29
54
|
@executed = true
|
30
|
-
|
55
|
+
response.execute actor, *arguments
|
56
|
+
self
|
31
57
|
end
|
32
58
|
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
59
|
+
# True if the response has been executed. False typically means that the
|
60
|
+
# #execute method has not been called or the action was cancelled in a
|
61
|
+
# before_action hook.
|
36
62
|
#
|
37
|
-
def
|
38
|
-
|
39
|
-
# executed
|
40
|
-
@cancelled = true
|
63
|
+
def executed?
|
64
|
+
@executed ||= false
|
41
65
|
end
|
42
66
|
|
43
|
-
#
|
67
|
+
# Cancel an action. This method can be called in an action hook to
|
68
|
+
# prevent subsequent hooks and/or the action itself from being executed.
|
44
69
|
#
|
45
|
-
|
46
|
-
|
47
|
-
@executed
|
70
|
+
def cancel
|
71
|
+
@cancelled = true
|
48
72
|
end
|
49
73
|
|
50
74
|
def cancelled?
|
51
|
-
|
75
|
+
@cancelled ||= false
|
52
76
|
end
|
53
77
|
|
54
|
-
# The verb associated with this action.
|
55
|
-
#
|
56
|
-
# @return [Symbol] The symbol representing the verb
|
57
78
|
def verb
|
58
|
-
|
79
|
+
response.verb
|
59
80
|
end
|
60
81
|
|
61
|
-
def
|
62
|
-
|
82
|
+
def narrative
|
83
|
+
response.narrative
|
63
84
|
end
|
64
85
|
|
65
|
-
def rank
|
66
|
-
self.class.rank
|
67
|
-
end
|
68
|
-
|
69
|
-
# True if the action is flagged as meta.
|
70
|
-
#
|
71
|
-
# @return [Boolean]
|
72
86
|
def meta?
|
73
|
-
|
74
|
-
end
|
75
|
-
|
76
|
-
# @param verb [Symbol]
|
77
|
-
# @param queries [Array<Gamefic::Query::Base>]
|
78
|
-
# @param meta [Boolean]
|
79
|
-
# @return [Class<Action>]
|
80
|
-
def self.subclass verb, *queries, meta: false, &block
|
81
|
-
act = Class.new(self) do
|
82
|
-
self.verb = verb
|
83
|
-
self.meta = meta
|
84
|
-
queries.each do |q|
|
85
|
-
add_query q
|
86
|
-
end
|
87
|
-
on_execute &block
|
88
|
-
end
|
89
|
-
if !block.nil? && act.queries.length + 1 != block.arity && block.arity > 0
|
90
|
-
raise ArgumentError.new("Number of parameters is not compatible with proc arguments")
|
91
|
-
end
|
92
|
-
act
|
93
|
-
end
|
94
|
-
|
95
|
-
private
|
96
|
-
|
97
|
-
def run_before_actions
|
98
|
-
return unless @with_callbacks
|
99
|
-
@actor.playbooks
|
100
|
-
.flat_map(&:before_actions)
|
101
|
-
.each do |hook|
|
102
|
-
next unless hook.verb.nil? || hook.verb == verb
|
103
|
-
hook.block.call(self)
|
104
|
-
break if @cancelled
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def run_after_actions
|
109
|
-
return unless @with_callbacks
|
110
|
-
@actor.playbooks
|
111
|
-
.flat_map(&:after_actions)
|
112
|
-
.each do |hook|
|
113
|
-
next unless hook.verb.nil? || hook.verb == verb
|
114
|
-
hook.block.call(self)
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
class << self
|
119
|
-
attr_reader :verb
|
120
|
-
|
121
|
-
# The proc to call when the action is executed
|
122
|
-
#
|
123
|
-
# @return [Proc]
|
124
|
-
attr_reader :executor
|
125
|
-
|
126
|
-
def meta?
|
127
|
-
@meta ||= false
|
128
|
-
end
|
129
|
-
|
130
|
-
def add_query q
|
131
|
-
@specificity = nil
|
132
|
-
queries.push q
|
133
|
-
end
|
134
|
-
|
135
|
-
def queries
|
136
|
-
@queries ||= []
|
137
|
-
end
|
138
|
-
|
139
|
-
def on_execute &block
|
140
|
-
@executor = block
|
141
|
-
end
|
142
|
-
|
143
|
-
def signature
|
144
|
-
# @todo This is clearly unfinished
|
145
|
-
"#{verb} #{queries.map {|m| m.signature}.join(', ')}"
|
146
|
-
end
|
147
|
-
|
148
|
-
# True if this action is not intended to be performed directly by a
|
149
|
-
# character.
|
150
|
-
# If the action is hidden, users should not be able to perform it with a
|
151
|
-
# direct command. By default, any action whose verb starts with an
|
152
|
-
# underscore is hidden.
|
153
|
-
#
|
154
|
-
# @return [Boolean]
|
155
|
-
def hidden?
|
156
|
-
verb.to_s.start_with?('_')
|
157
|
-
end
|
158
|
-
|
159
|
-
# @return [Integer]
|
160
|
-
def rank
|
161
|
-
if @rank.nil?
|
162
|
-
@rank = 0
|
163
|
-
queries.each do |q|
|
164
|
-
@rank += (q.rank + 1)
|
165
|
-
end
|
166
|
-
@rank -= 1000 if verb.nil?
|
167
|
-
end
|
168
|
-
@rank
|
169
|
-
end
|
170
|
-
|
171
|
-
def valid? actor, objects
|
172
|
-
return false if objects.length != queries.length
|
173
|
-
queries.each_with_index do |p, i|
|
174
|
-
return false unless p.include?(actor, objects[i])
|
175
|
-
end
|
176
|
-
true
|
177
|
-
end
|
178
|
-
|
179
|
-
# Return an instance of this Action if the actor can execute it with the
|
180
|
-
# provided tokens, or nil if the tokens are invalid.
|
181
|
-
#
|
182
|
-
# @param action [Gamefic::Entity]
|
183
|
-
# @param command [Command]
|
184
|
-
# @return [self, nil]
|
185
|
-
def attempt actor, command, with_callbacks = false
|
186
|
-
return nil if command.verb != verb
|
187
|
-
tokens = command.arguments
|
188
|
-
result = []
|
189
|
-
matches = Gamefic::Query::Matches.new([], '', '')
|
190
|
-
queries.each_with_index do |p, i|
|
191
|
-
return nil if tokens[i].nil? && matches.remaining == ''
|
192
|
-
matches = p.resolve(actor, "#{matches.remaining} #{tokens[i]}".strip, continued: (i < queries.length - 1))
|
193
|
-
return nil if matches.objects.empty?
|
194
|
-
accepted = matches.objects.select { |o| p.accept?(o) }
|
195
|
-
return nil if accepted.empty?
|
196
|
-
if p.ambiguous?
|
197
|
-
result.push accepted
|
198
|
-
else
|
199
|
-
return nil if accepted.length != 1
|
200
|
-
result.push accepted.first
|
201
|
-
end
|
202
|
-
end
|
203
|
-
new(actor, result, with_callbacks)
|
204
|
-
end
|
205
|
-
|
206
|
-
protected
|
207
|
-
|
208
|
-
attr_writer :verb
|
209
|
-
|
210
|
-
attr_writer :meta
|
87
|
+
response.meta?
|
211
88
|
end
|
212
89
|
end
|
213
90
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gamefic
|
4
|
+
module Active
|
5
|
+
# The data that actors use to configure a Take.
|
6
|
+
#
|
7
|
+
class Cue
|
8
|
+
# @return [Symbol]
|
9
|
+
attr_reader :scene
|
10
|
+
|
11
|
+
# @return [Hash]
|
12
|
+
attr_reader :context
|
13
|
+
|
14
|
+
# @param scene [Symbol]
|
15
|
+
def initialize scene, **context
|
16
|
+
@scene = scene
|
17
|
+
@context = context
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
scene.to_s
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,73 @@
|
|
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
|
+
def responses_for(*verbs)
|
55
|
+
rulebooks.to_a
|
56
|
+
.reverse
|
57
|
+
.flat_map { |rb| rb.responses_for(*verbs) }
|
58
|
+
end
|
59
|
+
|
60
|
+
# @param name [Symbol]
|
61
|
+
# @return [Scene]
|
62
|
+
def select_scene name
|
63
|
+
scenes = rulebooks.map { |rlbk| rlbk.scenes[name] }
|
64
|
+
.compact
|
65
|
+
raise ArgumentError, "Scene named `#{name}` does not exist" if scenes.empty?
|
66
|
+
|
67
|
+
logger.warn "Found #{scenes.length} scenes named `#{name}`" unless scenes.one?
|
68
|
+
|
69
|
+
scenes.last
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Gamefic
|
2
|
+
module Active
|
3
|
+
# A module for active entities that provides a default Messenger with
|
4
|
+
# a few shortcuts.
|
5
|
+
#
|
6
|
+
module Messaging
|
7
|
+
def messenger
|
8
|
+
@messenger ||= Messenger.new
|
9
|
+
end
|
10
|
+
|
11
|
+
# Send a message to the entity.
|
12
|
+
#
|
13
|
+
# This method will automatically wrap the message in HTML paragraphs.
|
14
|
+
# To send a message without paragraph formatting, use #stream instead.
|
15
|
+
#
|
16
|
+
# @param message [String]
|
17
|
+
def tell(message)
|
18
|
+
messenger.tell message
|
19
|
+
end
|
20
|
+
|
21
|
+
# Send a message to the entity as raw text.
|
22
|
+
#
|
23
|
+
# Unlike #tell, this method will not wrap the message in HTML paragraphs.
|
24
|
+
#
|
25
|
+
# @param message [String]
|
26
|
+
def stream(message)
|
27
|
+
messenger.stream message
|
28
|
+
end
|
29
|
+
|
30
|
+
def messages
|
31
|
+
messenger.messages
|
32
|
+
end
|
33
|
+
|
34
|
+
def buffer &block
|
35
|
+
messenger.buffer(&block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def flush
|
39
|
+
messenger.flush
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|