gamefic 3.5.0 → 3.6.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/CHANGELOG.md +9 -1
- data/lib/gamefic/action.rb +1 -0
- data/lib/gamefic/command.rb +10 -1
- data/lib/gamefic/dispatcher.rb +3 -0
- data/lib/gamefic/expression.rb +3 -0
- data/lib/gamefic/node.rb +3 -5
- data/lib/gamefic/proxy/base.rb +27 -0
- data/lib/gamefic/proxy/config.rb +16 -0
- data/lib/gamefic/proxy/pick.rb +11 -0
- data/lib/gamefic/proxy/plot_pick.rb +11 -0
- data/lib/gamefic/proxy.rb +38 -5
- data/lib/gamefic/query/abstract.rb +12 -0
- data/lib/gamefic/query/base.rb +41 -11
- data/lib/gamefic/query/general.rb +4 -4
- data/lib/gamefic/query/scoped.rb +3 -4
- data/lib/gamefic/query/text.rb +5 -4
- data/lib/gamefic/query.rb +1 -0
- data/lib/gamefic/response.rb +13 -3
- data/lib/gamefic/scanner/nesting.rb +2 -2
- data/lib/gamefic/scanner/result.rb +10 -0
- data/lib/gamefic/scope/descendants.rb +16 -16
- data/lib/gamefic/scriptable/entities.rb +28 -16
- data/lib/gamefic/scriptable/plot_proxies.rb +13 -0
- data/lib/gamefic/scriptable/proxies.rb +1 -1
- data/lib/gamefic/scriptable/queries.rb +18 -7
- data/lib/gamefic/scriptable.rb +24 -14
- data/lib/gamefic/subplot.rb +6 -0
- data/lib/gamefic/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5c61efc096ecbacdd43431dd3f0b755120650258a4a3e5d724692957ee45f53
|
4
|
+
data.tar.gz: 499d740594a35e767c86fae7610a51dafa9ba647658af7b3ab46c61de4335501
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd430f5dfa970cacfe12915ff09284ef286b1116aa701ce5484472fdf880b68a5de91953182189c647e90c527653bde92db26016045ac5ea5304e660082979fe
|
7
|
+
data.tar.gz: 1726fc542b40c55443bc9b452df85d94fe0831fa19bc73e40076cd6768e92bc71e504fd2da7998ef65b913c21f8b3ccb7bd4f04329186b88e71eb9dc675b0b69
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,12 @@
|
|
1
|
-
## 3.
|
1
|
+
## 3.6.0 - October 6, 2024
|
2
|
+
- Normalized arguments accept strings
|
3
|
+
- Smarter picks and proxies
|
4
|
+
- Commands prefer strictness over precision
|
5
|
+
- Queries scan for ambiguity before filtering through arguments
|
6
|
+
- Abstract queries
|
7
|
+
- Command logging
|
8
|
+
|
9
|
+
## 3.5.0 - October 5, 2024
|
2
10
|
- Configurable scanners
|
3
11
|
- Refactored scanners and queries
|
4
12
|
- Allow assignment to nil instance variables in stage
|
data/lib/gamefic/action.rb
CHANGED
data/lib/gamefic/command.rb
CHANGED
@@ -30,6 +30,14 @@ module Gamefic
|
|
30
30
|
@precision = precision
|
31
31
|
end
|
32
32
|
|
33
|
+
def substantiality
|
34
|
+
@substantiality ||= arguments.that_are(Entity).length + (verb ? 1 : 0)
|
35
|
+
end
|
36
|
+
|
37
|
+
def inspect
|
38
|
+
"#<#{self.class} #{([verb] + arguments).map(&:inspect).join(', ')}>"
|
39
|
+
end
|
40
|
+
|
33
41
|
class << self
|
34
42
|
# Compose a command from input.
|
35
43
|
#
|
@@ -48,11 +56,12 @@ module Gamefic
|
|
48
56
|
# @param expression [Expression]
|
49
57
|
# @return [Array<Command>]
|
50
58
|
def expression_to_commands actor, expression
|
59
|
+
Gamefic.logger.info "Evaluating #{expression.inspect}"
|
51
60
|
actor.epic
|
52
61
|
.responses_for(expression.verb)
|
53
62
|
.map { |response| response.to_command(actor, expression) }
|
54
63
|
.compact
|
55
|
-
.sort_by.with_index { |result, idx| [-result.
|
64
|
+
.sort_by.with_index { |result, idx| [-result.substantiality, -result.strictness, -result.precision, idx] }
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|
data/lib/gamefic/dispatcher.rb
CHANGED
@@ -4,12 +4,15 @@ module Gamefic
|
|
4
4
|
# The action executor for character commands.
|
5
5
|
#
|
6
6
|
class Dispatcher
|
7
|
+
include Logging
|
8
|
+
|
7
9
|
# @param actor [Actor]
|
8
10
|
# @param command [Command]
|
9
11
|
def initialize actor, command
|
10
12
|
@actor = actor
|
11
13
|
@command = command
|
12
14
|
@executed = false
|
15
|
+
Gamefic.logger.info "Dispatching #{command.inspect}"
|
13
16
|
end
|
14
17
|
|
15
18
|
# Run the dispatcher.
|
data/lib/gamefic/expression.rb
CHANGED
data/lib/gamefic/node.rb
CHANGED
@@ -88,11 +88,9 @@ module Gamefic
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def validate_parent(node)
|
91
|
-
raise NodeError,
|
92
|
-
|
93
|
-
raise NodeError, "
|
94
|
-
|
95
|
-
raise NodeError, 'Node cannot be a child of a descendant' if flatten.include?(node)
|
91
|
+
raise NodeError, "Parent of #{inspect} must be a Node, received #{node.inspect}" unless node.is_a?(Node) || node.nil?
|
92
|
+
raise NodeError, "#{inspect} cannot be its own parent" if node == self
|
93
|
+
raise NodeError, "#{inspect} cannot be a child of descendant #{node.inspect}" if flatten.include?(node)
|
96
94
|
end
|
97
95
|
end
|
98
96
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gamefic
|
4
|
+
class Proxy
|
5
|
+
class Base
|
6
|
+
attr_reader :args
|
7
|
+
|
8
|
+
def initialize *args, raise: false
|
9
|
+
@args = args
|
10
|
+
@raise = raise
|
11
|
+
end
|
12
|
+
|
13
|
+
def raise?
|
14
|
+
@raise
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch narrative
|
18
|
+
result = select(narrative)
|
19
|
+
return result if result
|
20
|
+
raise "#{self.class} failed for #{args.inspect}" if raise?
|
21
|
+
end
|
22
|
+
|
23
|
+
def select narrative
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/gamefic/proxy.rb
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Gamefic
|
4
|
+
# @todo Turn this into a module after the old proxies are completely deprecated
|
5
|
+
#
|
4
6
|
class Proxy
|
7
|
+
require 'gamefic/proxy/base'
|
8
|
+
require 'gamefic/proxy/config'
|
9
|
+
require 'gamefic/proxy/pick'
|
10
|
+
require 'gamefic/proxy/plot_pick'
|
11
|
+
|
12
|
+
TYPES = %i[attr ivar pick pick! plot_pick plot_pick! config].freeze
|
13
|
+
|
5
14
|
# @return [Symbol]
|
6
15
|
attr_reader :type
|
7
16
|
|
@@ -9,11 +18,12 @@ module Gamefic
|
|
9
18
|
attr_reader :key
|
10
19
|
|
11
20
|
# @param type [Symbol]
|
12
|
-
# @param key [Symbol, String]
|
21
|
+
# @param key [Symbol, String, Array]
|
13
22
|
def initialize type, key
|
23
|
+
Gamefic.logger.debug "Using deprecated #{type} proxy"
|
14
24
|
@type = type
|
15
|
-
@key = key
|
16
25
|
validate_type
|
26
|
+
@key = type == :config ? [key].compact : key
|
17
27
|
end
|
18
28
|
|
19
29
|
def fetch narrative
|
@@ -21,6 +31,13 @@ module Gamefic
|
|
21
31
|
raise(ArgumentError, "Unable to fetch entity from proxy agent symbol `#{key}`")
|
22
32
|
end
|
23
33
|
|
34
|
+
def [](key)
|
35
|
+
raise ArgumentError, 'Invalid []' unless type == :config
|
36
|
+
|
37
|
+
@key.push key
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
24
41
|
private
|
25
42
|
|
26
43
|
def attr narrative
|
@@ -34,13 +51,29 @@ module Gamefic
|
|
34
51
|
end
|
35
52
|
|
36
53
|
def pick narrative
|
37
|
-
narrative.pick
|
54
|
+
narrative.pick *key
|
55
|
+
end
|
56
|
+
|
57
|
+
def pick! narrative
|
58
|
+
narrative.pick! *key
|
59
|
+
end
|
60
|
+
|
61
|
+
def plot_pick narrative
|
62
|
+
narrative.plot.pick *key
|
63
|
+
end
|
64
|
+
|
65
|
+
def plot_pick! narrative
|
66
|
+
narrative.plot.pick! *key
|
67
|
+
end
|
68
|
+
|
69
|
+
def config narrative
|
70
|
+
key.inject(narrative.config) { |hash, key| hash[key] }
|
38
71
|
end
|
39
72
|
|
40
73
|
def validate_type
|
41
|
-
return if
|
74
|
+
return if TYPES.include?(type)
|
42
75
|
|
43
|
-
raise ArgumentError, "Invalid proxy type `#{type}` (must be
|
76
|
+
raise ArgumentError, "Invalid proxy type `#{type}` (must be #{TYPES.join_or})"
|
44
77
|
end
|
45
78
|
end
|
46
79
|
end
|
data/lib/gamefic/query/base.rb
CHANGED
@@ -19,11 +19,13 @@ module Gamefic
|
|
19
19
|
#
|
20
20
|
# @param arguments [Array<Object>]
|
21
21
|
# @param ambiguous [Boolean]
|
22
|
-
|
22
|
+
# @param name [String]
|
23
|
+
def initialize *arguments, ambiguous: false, name: self.class.to_s
|
23
24
|
raise ArgumentError, "nil argument in query" if arguments.any?(&:nil?)
|
24
25
|
|
25
26
|
@arguments = arguments
|
26
27
|
@ambiguous = ambiguous
|
28
|
+
@name = name
|
27
29
|
end
|
28
30
|
|
29
31
|
# Get a query result for a given subject and token.
|
@@ -38,19 +40,35 @@ module Gamefic
|
|
38
40
|
# @param token [String]
|
39
41
|
# @return [Result]
|
40
42
|
def query(subject, token)
|
41
|
-
|
42
|
-
ambiguous?
|
43
|
+
first_pass = Scanner.scan(span(subject), token)
|
44
|
+
if ambiguous?
|
45
|
+
ambiguous_result(first_pass.filter(*normalized_arguments))
|
46
|
+
elsif first_pass.match.one?
|
47
|
+
unambiguous_result(first_pass.filter(*normalized_arguments))
|
48
|
+
else
|
49
|
+
unambiguous_result(first_pass)
|
50
|
+
end
|
43
51
|
end
|
44
52
|
alias filter query
|
45
53
|
|
46
|
-
# Get an array of entities that match the
|
47
|
-
# subject.
|
54
|
+
# Get an array of entities that match the arguments from the context of
|
55
|
+
# the subject.
|
56
|
+
#
|
57
|
+
# @param subject [Entity]
|
58
|
+
# @return [Array<Entity>]
|
59
|
+
def select subject
|
60
|
+
span(subject).that_are(*normalized_arguments)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Get an array of entities that are candidates for selection from the
|
64
|
+
# context of the subject. These are the entities that #select will
|
65
|
+
# filter through query's arguments.
|
48
66
|
#
|
49
67
|
# Subclasses should override this method.
|
50
68
|
#
|
51
69
|
# @param subject [Entity]
|
52
70
|
# @return [Array<Entity>]
|
53
|
-
def
|
71
|
+
def span _subject
|
54
72
|
[]
|
55
73
|
end
|
56
74
|
|
@@ -77,12 +95,20 @@ module Gamefic
|
|
77
95
|
@ambiguous
|
78
96
|
end
|
79
97
|
|
98
|
+
def name
|
99
|
+
@name || self.class.to_s
|
100
|
+
end
|
101
|
+
|
102
|
+
def inspect
|
103
|
+
"##{ambiguous? ? '*' : ''}#{name}(#{normalized_arguments.map(&:inspect).join(', ')})"
|
104
|
+
end
|
105
|
+
|
80
106
|
private
|
81
107
|
|
82
108
|
def calculate_precision
|
83
|
-
|
109
|
+
normalized_arguments.sum(@ambiguous ? -1000 : 0) do |arg|
|
84
110
|
case arg
|
85
|
-
when Entity, Proxy
|
111
|
+
when Entity, Proxy, Proxy::Base
|
86
112
|
1000
|
87
113
|
when Class, Module
|
88
114
|
class_depth(arg) * 100
|
@@ -115,11 +141,15 @@ module Gamefic
|
|
115
141
|
Result.new(scan.matched.first, scan.remainder, scan.strictness)
|
116
142
|
end
|
117
143
|
|
118
|
-
def
|
119
|
-
@
|
144
|
+
def normalized_arguments
|
145
|
+
@normalized_arguments ||= arguments.map do |arg|
|
120
146
|
case arg
|
121
|
-
when Proxy
|
147
|
+
when Proxy, Proxy::Base
|
122
148
|
arg.fetch(narrative)
|
149
|
+
when String
|
150
|
+
proc do |entity|
|
151
|
+
arg.keywords.all? { |word| entity.keywords.include?(word) }
|
152
|
+
end
|
123
153
|
else
|
124
154
|
arg
|
125
155
|
end
|
@@ -14,13 +14,13 @@ module Gamefic
|
|
14
14
|
# @param entities [Array, Proc]
|
15
15
|
# @param arguments [Array<Object>]
|
16
16
|
# @param ambiguous [Boolean]
|
17
|
-
def initialize entities, *arguments, ambiguous: false
|
18
|
-
super(*arguments, ambiguous: ambiguous)
|
17
|
+
def initialize entities, *arguments, ambiguous: false, name: nil
|
18
|
+
super(*arguments, ambiguous: ambiguous, name: name)
|
19
19
|
@entities = entities
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
available_entities(subject)
|
22
|
+
def span subject
|
23
|
+
available_entities(subject)
|
24
24
|
end
|
25
25
|
|
26
26
|
private
|
data/lib/gamefic/query/scoped.rb
CHANGED
@@ -10,14 +10,13 @@ module Gamefic
|
|
10
10
|
attr_reader :scope
|
11
11
|
|
12
12
|
# @param scope [Class<Gamefic::Scope::Base>]
|
13
|
-
def initialize scope, *arguments, ambiguous: false
|
14
|
-
super(*arguments, ambiguous: ambiguous)
|
13
|
+
def initialize scope, *arguments, ambiguous: false, name: nil
|
14
|
+
super(*arguments, ambiguous: ambiguous, name: name)
|
15
15
|
@scope = scope
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def span(subject)
|
19
19
|
@scope.matches(subject)
|
20
|
-
.that_are(*unproxied_arguments)
|
21
20
|
end
|
22
21
|
|
23
22
|
def precision
|
data/lib/gamefic/query/text.rb
CHANGED
@@ -6,9 +6,10 @@ module Gamefic
|
|
6
6
|
#
|
7
7
|
class Text < Base
|
8
8
|
# @param argument [String, Regexp]
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
# @param name [String, nil]
|
10
|
+
def initialize argument = /.*/, name: self.class.name
|
11
|
+
super(argument, name: name)
|
12
|
+
validate_argument
|
12
13
|
end
|
13
14
|
|
14
15
|
def argument
|
@@ -50,7 +51,7 @@ module Gamefic
|
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
|
-
def
|
54
|
+
def validate_argument
|
54
55
|
return if argument.is_a?(String) || argument.is_a?(Regexp)
|
55
56
|
|
56
57
|
raise ArgumentError, 'Invalid text query argument'
|
data/lib/gamefic/query.rb
CHANGED
data/lib/gamefic/response.rb
CHANGED
@@ -77,11 +77,12 @@ module Gamefic
|
|
77
77
|
# @param expression [Expression]
|
78
78
|
# @return [Command, nil]
|
79
79
|
def to_command actor, expression
|
80
|
-
return
|
80
|
+
return log_and_discard unless expression.verb == verb && expression.tokens.length <= queries.length
|
81
81
|
|
82
82
|
results = filter(actor, expression)
|
83
|
-
return
|
83
|
+
return log_and_discard unless results
|
84
84
|
|
85
|
+
Gamefic.logger.info "Accepted #{inspect}"
|
85
86
|
Command.new(
|
86
87
|
verb,
|
87
88
|
results.map(&:match),
|
@@ -90,8 +91,17 @@ module Gamefic
|
|
90
91
|
)
|
91
92
|
end
|
92
93
|
|
94
|
+
def inspect
|
95
|
+
"#<#{self.class} #{([verb] + queries).map(&:inspect).join(', ')}>"
|
96
|
+
end
|
97
|
+
|
93
98
|
private
|
94
99
|
|
100
|
+
def log_and_discard
|
101
|
+
Gamefic.logger.info "Discarded #{inspect}"
|
102
|
+
nil
|
103
|
+
end
|
104
|
+
|
95
105
|
def filter actor, expression
|
96
106
|
remainder = ''
|
97
107
|
result = queries.zip(expression.tokens)
|
@@ -126,7 +136,7 @@ module Gamefic
|
|
126
136
|
|
127
137
|
def select_query arg, narrative
|
128
138
|
case arg
|
129
|
-
when Entity, Class, Module, Proc, Proxy
|
139
|
+
when Entity, Class, Module, Proc, Proxy, Proxy::Base
|
130
140
|
narrative.available(arg)
|
131
141
|
when String, Regexp
|
132
142
|
narrative.plaintext(arg)
|
@@ -12,7 +12,7 @@ module Gamefic
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def scan
|
15
|
-
return
|
15
|
+
return unmatched_result unless token =~ NEST_REGEXP
|
16
16
|
|
17
17
|
denest selection, token
|
18
18
|
end
|
@@ -27,7 +27,7 @@ module Gamefic
|
|
27
27
|
current = parts.pop
|
28
28
|
last_result = subprocessor.scan(near, current)
|
29
29
|
last_result = subprocessor.scan(far, current) if last_result.matched.empty? && near != far
|
30
|
-
return
|
30
|
+
return unmatched_result if last_result.matched.empty? || last_result.matched.length > 1
|
31
31
|
|
32
32
|
near = last_result.matched.first.children & objects
|
33
33
|
far = last_result.matched.first.flatten & objects
|
@@ -42,6 +42,16 @@ module Gamefic
|
|
42
42
|
@strictness ||= Scanner.strictness(processor)
|
43
43
|
end
|
44
44
|
|
45
|
+
def filter *args
|
46
|
+
Scanner::Result.new(
|
47
|
+
scanned,
|
48
|
+
token,
|
49
|
+
match.that_are(*args),
|
50
|
+
remainder,
|
51
|
+
processor
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
45
55
|
def self.unmatched scanned, token, processor
|
46
56
|
new(scanned, token, [], token, processor)
|
47
57
|
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Gamefic
|
4
|
-
module Scope
|
5
|
-
# The Descendants scope returns an entity's children and accessible
|
6
|
-
# descendants.
|
7
|
-
#
|
8
|
-
class Descendants < Base
|
9
|
-
def matches
|
10
|
-
context.children.flat_map do |child|
|
11
|
-
[child] + subquery_accessible(child)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gamefic
|
4
|
+
module Scope
|
5
|
+
# The Descendants scope returns an entity's children and accessible
|
6
|
+
# descendants.
|
7
|
+
#
|
8
|
+
class Descendants < Base
|
9
|
+
def matches
|
10
|
+
context.children.flat_map do |child|
|
11
|
+
[child] + subquery_accessible(child)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -49,16 +49,30 @@ module Gamefic
|
|
49
49
|
entity_vault.delete entity
|
50
50
|
end
|
51
51
|
|
52
|
-
|
53
|
-
|
52
|
+
def find *args
|
53
|
+
args.inject(entities) do |entities, arg|
|
54
|
+
case arg
|
55
|
+
when String
|
56
|
+
result = Scanner.scan(entities, arg)
|
57
|
+
result.remainder.empty? ? result.match : []
|
58
|
+
else
|
59
|
+
entities.that_are(arg)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Pick a unique entity based on the given arguments. String arguments are
|
65
|
+
# used to scan the entities for matching names and synonyms. Return nil
|
66
|
+
# if an entity could not be found or there is more than one possible
|
67
|
+
# match.
|
54
68
|
#
|
55
|
-
# @param description [
|
69
|
+
# @param description [Array]
|
56
70
|
# @return [Gamefic::Entity, nil]
|
57
|
-
def pick
|
58
|
-
|
59
|
-
return nil unless
|
71
|
+
def pick *args
|
72
|
+
matches = find(*args)
|
73
|
+
return nil unless matches.one?
|
60
74
|
|
61
|
-
|
75
|
+
matches.first
|
62
76
|
end
|
63
77
|
|
64
78
|
# Same as #pick, but raise an error if a unique match could not be found.
|
@@ -66,16 +80,14 @@ module Gamefic
|
|
66
80
|
#
|
67
81
|
# @raise [RuntimeError] if a unique match was not found.
|
68
82
|
#
|
69
|
-
# @param
|
70
|
-
# @return [Gamefic::Entity
|
71
|
-
def pick!
|
72
|
-
|
73
|
-
|
74
|
-
raise "
|
75
|
-
|
76
|
-
raise "multiple entities matching '#{description}': #{result.matched.join_and}" unless result.matched.one?
|
83
|
+
# @param args [Array]
|
84
|
+
# @return [Gamefic::Entity]
|
85
|
+
def pick! *args
|
86
|
+
matches = find(*args)
|
87
|
+
raise "no entity matching '#{args.inspect}'" if matches.empty?
|
88
|
+
raise "multiple entities matching '#{args.inspect}': #{matches.join_and}" unless matches.one?
|
77
89
|
|
78
|
-
|
90
|
+
matches.first
|
79
91
|
end
|
80
92
|
end
|
81
93
|
end
|
@@ -4,6 +4,7 @@ module Gamefic
|
|
4
4
|
module Scriptable
|
5
5
|
module PlotProxies
|
6
6
|
def lazy_plot key
|
7
|
+
Logging.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`lazy_plot` is deprecated. Use `plot_pick`, `plot_pick!, or pass the entity from the plot in a `config` option instead."
|
7
8
|
Proxy.new(:attr, [:plot, key])
|
8
9
|
end
|
9
10
|
alias _plot lazy_plot
|
@@ -11,6 +12,18 @@ module Gamefic
|
|
11
12
|
def attr_plot attr
|
12
13
|
define_method(attr) { plot.send(attr) }
|
13
14
|
end
|
15
|
+
|
16
|
+
def plot_pick *args
|
17
|
+
Proxy::PlotPick.new(*args)
|
18
|
+
end
|
19
|
+
alias lazy_plot_pick plot_pick
|
20
|
+
alias _plot_pick plot_pick
|
21
|
+
|
22
|
+
def plot_pick! *args
|
23
|
+
Proxy::PlotPick.new(*args)
|
24
|
+
end
|
25
|
+
alias lazy_plot_pick! plot_pick!
|
26
|
+
alias _plot_pick! plot_pick!
|
14
27
|
end
|
15
28
|
end
|
16
29
|
end
|
@@ -12,7 +12,18 @@ module Gamefic
|
|
12
12
|
# @param args [Array<Object>] Query arguments
|
13
13
|
# @return [Query::General]
|
14
14
|
def anywhere *args, ambiguous: false
|
15
|
-
Query::General.new -> { entities }, *args, ambiguous: ambiguous
|
15
|
+
Query::General.new -> { entities }, *args, ambiguous: ambiguous, name: 'anywhere'
|
16
|
+
end
|
17
|
+
|
18
|
+
# Define a query that searches for abstract entities.
|
19
|
+
#
|
20
|
+
# An abstract entity is a pseudo-entity that is describable but does
|
21
|
+
# not have a parent or children.
|
22
|
+
#
|
23
|
+
# @param args [Array<Object>] Query arguments
|
24
|
+
# @return [Query::Abstract]
|
25
|
+
def abstract *args, ambiguous: false
|
26
|
+
Query::Abstract.new -> { entities }, *args, ambiguous: ambiguous
|
16
27
|
end
|
17
28
|
|
18
29
|
# Define a query that searches an actor's family of entities. The
|
@@ -22,7 +33,7 @@ module Gamefic
|
|
22
33
|
# @param args [Array<Object>] Query arguments
|
23
34
|
# @return [Query::Scoped]
|
24
35
|
def available *args, ambiguous: false
|
25
|
-
Query::Scoped.new Scope::Family, *args, ambiguous: ambiguous
|
36
|
+
Query::Scoped.new Scope::Family, *args, ambiguous: ambiguous, name: 'available'
|
26
37
|
end
|
27
38
|
alias family available
|
28
39
|
|
@@ -31,7 +42,7 @@ module Gamefic
|
|
31
42
|
# @param args [Array<Object>] Query arguments
|
32
43
|
# @return [Query::Scoped]
|
33
44
|
def parent *args, ambiguous: false
|
34
|
-
Query::Scoped.new Scope::Parent, *args, ambiguous: ambiguous
|
45
|
+
Query::Scoped.new Scope::Parent, *args, ambiguous: ambiguous, name: 'parent'
|
35
46
|
end
|
36
47
|
|
37
48
|
# Define a query that searches an actor's children.
|
@@ -39,7 +50,7 @@ module Gamefic
|
|
39
50
|
# @param args [Array<Object>] Query arguments
|
40
51
|
# @return [Query::Scoped]
|
41
52
|
def children *args, ambiguous: false
|
42
|
-
Query::Scoped.new Scope::Children, *args, ambiguous: ambiguous
|
53
|
+
Query::Scoped.new Scope::Children, *args, ambiguous: ambiguous, name: 'children'
|
43
54
|
end
|
44
55
|
|
45
56
|
# Define a query that searches an actor's descendants.
|
@@ -55,7 +66,7 @@ module Gamefic
|
|
55
66
|
# @param args [Array<Object>] Query arguments
|
56
67
|
# @return [Query::Scoped]
|
57
68
|
def siblings *args, ambiguous: false
|
58
|
-
Query::Scoped.new Scope::Siblings, *args, ambiguous: ambiguous
|
69
|
+
Query::Scoped.new Scope::Siblings, *args, ambiguous: ambiguous, name: 'siblings'
|
59
70
|
end
|
60
71
|
|
61
72
|
# Define a query that returns the actor itself.
|
@@ -63,7 +74,7 @@ module Gamefic
|
|
63
74
|
# @param args [Array<Object>] Query arguments
|
64
75
|
# @return [Query::Scoped]
|
65
76
|
def myself *args, ambiguous: false
|
66
|
-
Query::Scoped.new Scope::Myself, *args, ambiguous: ambiguous
|
77
|
+
Query::Scoped.new Scope::Myself, *args, ambiguous: ambiguous, name: 'myself'
|
67
78
|
end
|
68
79
|
|
69
80
|
# Define a query that performs a plaintext search. It can take a String
|
@@ -74,7 +85,7 @@ module Gamefic
|
|
74
85
|
# @param arg [String, Regexp] The string or regular expression to match
|
75
86
|
# @return [Query::Text]
|
76
87
|
def plaintext arg = /.*/
|
77
|
-
Query::Text.new arg
|
88
|
+
Query::Text.new arg, name: 'plaintext'
|
78
89
|
end
|
79
90
|
end
|
80
91
|
end
|
data/lib/gamefic/scriptable.rb
CHANGED
@@ -101,11 +101,12 @@ module Gamefic
|
|
101
101
|
# make_seed Gamefic::Entity, name: 'thing'
|
102
102
|
#
|
103
103
|
# @param klass [Class<Gamefic::Entity>]
|
104
|
-
# @return [
|
104
|
+
# @return [Proxy]
|
105
105
|
def make_seed klass, **opts
|
106
106
|
seed { make(klass, **opts) }
|
107
|
-
|
107
|
+
Proxy::Pick.new(klass, opts[:name], raise: true)
|
108
108
|
end
|
109
|
+
alias make make_seed
|
109
110
|
|
110
111
|
# Seed an entity with an attribute method.
|
111
112
|
#
|
@@ -134,11 +135,11 @@ module Gamefic
|
|
134
135
|
# @param symbol [Symbol]
|
135
136
|
# @return [Proxy]
|
136
137
|
def proxy symbol
|
137
|
-
Logging.logger.warn "#proxy is deprecated. Use
|
138
|
+
Logging.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`proxy` is deprecated. Use `pick` or `pick!` instead."
|
138
139
|
if symbol.to_s.start_with?('@')
|
139
|
-
|
140
|
+
Proxy.new(:ivar, symbol)
|
140
141
|
else
|
141
|
-
|
142
|
+
Proxy.new(:attr, symbol)
|
142
143
|
end
|
143
144
|
end
|
144
145
|
|
@@ -150,6 +151,7 @@ module Gamefic
|
|
150
151
|
# @param key [Symbol]
|
151
152
|
# @return [Proxy]
|
152
153
|
def lazy_ivar key
|
154
|
+
Gamefic.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`lazy_ivar` is deprecated. Use `pick` or `pick!` instead."
|
153
155
|
Proxy.new(:ivar, key)
|
154
156
|
end
|
155
157
|
alias _ivar lazy_ivar
|
@@ -162,23 +164,31 @@ module Gamefic
|
|
162
164
|
# @param key [Symbol]
|
163
165
|
# @return [Proxy]
|
164
166
|
def lazy_attr key
|
167
|
+
Gamefic.logger.warn "#{caller.first ? "#{caller.first}: " : ''}`lazy_attr` is deprecated. Use `pick` or `pick!` instead."
|
165
168
|
Proxy.new(:attr, key)
|
166
169
|
end
|
167
170
|
alias _attr lazy_attr
|
168
171
|
|
169
|
-
# Lazy
|
172
|
+
# Lazy pick an entity.
|
170
173
|
#
|
171
174
|
# @example
|
172
|
-
#
|
173
|
-
#
|
174
|
-
# @raise [RuntimeError] if a unique match could not be found.
|
175
|
+
# pick('the red box')
|
175
176
|
#
|
176
|
-
# @param
|
177
|
+
# @param args [Array]
|
177
178
|
# @return [Proxy]
|
178
|
-
def
|
179
|
-
Proxy.new(
|
179
|
+
def pick *args
|
180
|
+
Proxy::Pick.new(*args)
|
181
|
+
end
|
182
|
+
alias lazy_pick pick
|
183
|
+
alias _pick pick
|
184
|
+
|
185
|
+
# Lazy pick an entity or raise
|
186
|
+
#
|
187
|
+
def pick! *args
|
188
|
+
Proxy::Pick.new(*args)
|
180
189
|
end
|
181
|
-
alias
|
190
|
+
alias lazy_pick! pick
|
191
|
+
alias _pick! pick
|
182
192
|
|
183
193
|
if RUBY_ENGINE == 'opal'
|
184
194
|
# :nocov:
|
@@ -212,7 +222,7 @@ module Gamefic
|
|
212
222
|
#
|
213
223
|
# @return [Module<self>]
|
214
224
|
def no_scripts
|
215
|
-
Logging.logger.warn 'Calling `no_scripts` on Scriptable modules is no longer necessary.
|
225
|
+
Logging.logger.warn "#{caller.first ? "#{caller.first}: " : ''}Calling `no_scripts` on Scriptable modules is no longer necessary."
|
216
226
|
self
|
217
227
|
end
|
218
228
|
end
|
data/lib/gamefic/subplot.rb
CHANGED
data/lib/gamefic/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gamefic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Fred Snyder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-10-
|
11
|
+
date: 2024-10-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -156,7 +156,12 @@ files:
|
|
156
156
|
- lib/gamefic/props/pause.rb
|
157
157
|
- lib/gamefic/props/yes_or_no.rb
|
158
158
|
- lib/gamefic/proxy.rb
|
159
|
+
- lib/gamefic/proxy/base.rb
|
160
|
+
- lib/gamefic/proxy/config.rb
|
161
|
+
- lib/gamefic/proxy/pick.rb
|
162
|
+
- lib/gamefic/proxy/plot_pick.rb
|
159
163
|
- lib/gamefic/query.rb
|
164
|
+
- lib/gamefic/query/abstract.rb
|
160
165
|
- lib/gamefic/query/base.rb
|
161
166
|
- lib/gamefic/query/general.rb
|
162
167
|
- lib/gamefic/query/result.rb
|