gamefic 2.4.0 → 3.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/.github/workflows/rspec.yml +41 -40
- data/.rspec-opal +2 -0
- data/.solargraph.yml +20 -3
- data/CHANGELOG.md +9 -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 +52 -183
- data/lib/gamefic/active/cue.rb +25 -0
- data/lib/gamefic/active/epic.rb +68 -0
- data/lib/gamefic/active/messaging.rb +43 -0
- data/lib/gamefic/active/take.rb +69 -0
- data/lib/gamefic/active.rb +95 -192
- data/lib/gamefic/actor.rb +2 -0
- data/lib/gamefic/block.rb +28 -0
- data/lib/gamefic/command.rb +16 -6
- 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 +63 -32
- data/lib/gamefic/entity.rb +44 -19
- 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 +41 -0
- data/lib/gamefic/props/multiple_choice.rb +65 -0
- data/lib/gamefic/props/pause.rb +11 -0
- data/lib/gamefic/props/yes_or_no.rb +21 -0
- data/lib/gamefic/props.rb +10 -0
- data/lib/gamefic/query/base.rb +45 -126
- data/lib/gamefic/query/general.rb +46 -0
- data/lib/gamefic/query/result.rb +20 -0
- data/lib/gamefic/query/scoped.rb +41 -0
- data/lib/gamefic/query/text.rb +30 -31
- data/lib/gamefic/query.rb +7 -15
- data/lib/gamefic/response.rb +118 -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 +103 -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 +76 -0
- data/lib/gamefic/scriptable/events.rb +65 -0
- data/lib/gamefic/scriptable/proxy.rb +55 -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 +36 -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 +26 -15
- data/spec-opal/spec_helper.rb +24 -0
- metadata +91 -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
data/lib/gamefic/syntax.rb
CHANGED
@@ -1,72 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'gamefic/syntax/template'
|
4
|
+
|
1
5
|
module Gamefic
|
6
|
+
# Syntaxes provide rules for matching input patterns to existing responses.
|
7
|
+
# Common uses are to provide synonyms for response verbs and allow for
|
8
|
+
# variations in sentence structure.
|
9
|
+
#
|
10
|
+
# The template and command patterns use words beginning with a colon (e.g.,
|
11
|
+
# `:thing`) to identify phrases that should be tokenized into arguments.
|
12
|
+
#
|
13
|
+
# @example All of these syntaxes will translate input into a command of the
|
14
|
+
# form "look thing container"
|
15
|
+
#
|
16
|
+
# Syntax.new('examine :thing in :container', 'look :thing :container')
|
17
|
+
# Syntax.new('look at :thing inside :container', 'look :thing :container')
|
18
|
+
# Syntax.new('search :container for :thing', 'look :thing :container')
|
19
|
+
#
|
2
20
|
class Syntax
|
3
|
-
|
21
|
+
# The pattern that matching input is expected to follow.
|
22
|
+
#
|
23
|
+
# @return [Template]
|
24
|
+
attr_reader :template
|
25
|
+
|
26
|
+
# The pattern that will be used to tokenize the input into a command.
|
27
|
+
#
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :command
|
30
|
+
|
31
|
+
# The response verb to which the command will be translated.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# syntax = Syntax.new('examine :thing', 'look :thing')
|
35
|
+
# syntax.verb #=> :look
|
36
|
+
#
|
37
|
+
# @return [Symbol]
|
38
|
+
attr_reader :verb
|
4
39
|
|
40
|
+
# @param template [Template, String]
|
41
|
+
# @param command [String]
|
5
42
|
def initialize template, command
|
6
|
-
|
7
|
-
@
|
8
|
-
|
9
|
-
@
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
words.each { |w|
|
23
|
-
if w.match(/^:[a-z0-9_]+$/i)
|
24
|
-
variable_tokens.push w
|
25
|
-
if last_token_is_reg
|
26
|
-
next
|
27
|
-
else
|
28
|
-
tokens.push '([\w\W\s\S]*?)'
|
29
|
-
last_token_is_reg = true
|
30
|
-
end
|
31
|
-
else
|
32
|
-
tokens.push w
|
33
|
-
last_token_is_reg = false
|
34
|
-
end
|
35
|
-
}
|
36
|
-
subs = []
|
37
|
-
index = 0
|
38
|
-
command_words.each { |t|
|
39
|
-
if t[0] == ':'
|
40
|
-
index = variable_tokens.index(t) + 1
|
41
|
-
subs.push "{$#{index}}"
|
42
|
-
else
|
43
|
-
subs.push t
|
44
|
-
end
|
45
|
-
}
|
46
|
-
@replace = subs.join(' ')
|
47
|
-
@regexp = Regexp.new("^#{tokens.join(' ')}$", Regexp::IGNORECASE)
|
43
|
+
@template = Template.to_template(template)
|
44
|
+
@command = command.normalize
|
45
|
+
@verb = Syntax.literal_or_nil(@command.keywords[0])
|
46
|
+
@replace = parse_replace
|
47
|
+
end
|
48
|
+
|
49
|
+
# A symbol for the first word in the template. Used by rulebooks to
|
50
|
+
# classify groups of related syntaxes.
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
# syntax = Syntax.new('examine :thing', 'look :thing')
|
54
|
+
# syntax.synonym #=> :examine
|
55
|
+
#
|
56
|
+
# @return [Symbol]
|
57
|
+
def synonym
|
58
|
+
template.verb
|
48
59
|
end
|
49
60
|
|
50
61
|
# Convert a String into a Command.
|
51
62
|
#
|
52
63
|
# @param text [String]
|
53
|
-
# @return [
|
64
|
+
# @return [Command, nil]
|
54
65
|
def tokenize text
|
55
|
-
|
56
|
-
return nil
|
57
|
-
|
58
|
-
|
59
|
-
xverb = @verb
|
60
|
-
@replace.to_s.split_words[b..-1].each { |r|
|
61
|
-
if r.match(/^\{\$[0-9]+\}$/)
|
62
|
-
arguments.push m[r[2..-2].to_i]
|
63
|
-
elsif arguments.empty? && xverb.nil?
|
64
|
-
xverb = r.to_sym
|
65
|
-
else
|
66
|
-
arguments.push r
|
67
|
-
end
|
68
|
-
}
|
69
|
-
Command.new xverb, arguments
|
66
|
+
match = text&.match(template.regexp)
|
67
|
+
return nil unless match
|
68
|
+
|
69
|
+
Command.new(verb, match_to_args(match))
|
70
70
|
end
|
71
71
|
|
72
72
|
# Determine if the specified text matches the syntax's expected pattern.
|
@@ -74,47 +74,66 @@ module Gamefic
|
|
74
74
|
# @param text [String]
|
75
75
|
# @return [Boolean]
|
76
76
|
def accept? text
|
77
|
-
|
77
|
+
!!text.match(template.regexp)
|
78
78
|
end
|
79
79
|
|
80
80
|
# Get a signature that identifies the form of the Syntax.
|
81
81
|
# Signatures are used to compare Syntaxes to each other.
|
82
82
|
#
|
83
83
|
def signature
|
84
|
-
[
|
84
|
+
[template.regexp, replace]
|
85
85
|
end
|
86
86
|
|
87
87
|
def ==(other)
|
88
|
-
|
89
|
-
signature == other.signature
|
90
|
-
end
|
91
|
-
|
92
|
-
def eql?(other)
|
93
|
-
self == other
|
88
|
+
signature == other&.signature
|
94
89
|
end
|
95
90
|
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
# Tokenize an Array of Commands from the specified text. The resulting
|
101
|
-
# array is in descending order of specificity, i.e., most to least matched
|
91
|
+
# Tokenize an array of commands from the specified text. The resulting
|
92
|
+
# array is in descending order of precision, i.e., most to least matched
|
102
93
|
# tokens.
|
103
94
|
#
|
104
95
|
# @param text [String] The text to tokenize.
|
105
|
-
# @param syntaxes [Array<
|
106
|
-
# @return [Array<
|
96
|
+
# @param syntaxes [Array<Syntax>] The syntaxes to use.
|
97
|
+
# @return [Array<Command>] The tokenized commands.
|
107
98
|
def self.tokenize text, syntaxes
|
108
99
|
syntaxes
|
109
100
|
.map { |syn| syn.tokenize(text) }
|
110
|
-
.
|
111
|
-
.sort
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
101
|
+
.compact
|
102
|
+
.sort { |syn, other_syn| syn.compare other_syn }
|
103
|
+
end
|
104
|
+
|
105
|
+
# Compare two syntaxes for the purpose of ordering them in rulebooks.
|
106
|
+
#
|
107
|
+
def compare other
|
108
|
+
template.compare other.template
|
109
|
+
end
|
110
|
+
|
111
|
+
# @param string [String]
|
112
|
+
# @return [String, nil]
|
113
|
+
def self.literal_or_nil string
|
114
|
+
string.start_with?(':') ? nil : string.to_sym
|
115
|
+
end
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
# @return [String]
|
120
|
+
attr_reader :replace
|
121
|
+
|
122
|
+
def parse_replace
|
123
|
+
command.keywords.map do |word|
|
124
|
+
next word unless word.start_with?(':')
|
125
|
+
|
126
|
+
index = template.params.index(word) ||
|
127
|
+
raise(ArgumentError, "syntax command references undefined parameter `#{word}`")
|
128
|
+
"{$#{index + 1}}"
|
129
|
+
end.join(' ')
|
130
|
+
end
|
131
|
+
|
132
|
+
def match_to_args match
|
133
|
+
start = replace.start_with?('{') ? 0 : 1
|
134
|
+
replace.keywords[start..].map do |str|
|
135
|
+
str.match?(/^\{\$[0-9]+\}$/) ? match[str[2..-2].to_i] : str
|
136
|
+
end
|
118
137
|
end
|
119
138
|
end
|
120
139
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Gamefic
|
2
|
+
# An array wrapper that exposes a protected interface. The array is always
|
3
|
+
# returned frozen. It can only be modified through #add and #delete. The
|
4
|
+
# vault can be "locked" to prevent existing elements from being deleted.
|
5
|
+
#
|
6
|
+
class Vault
|
7
|
+
def initialize
|
8
|
+
@set = Set.new
|
9
|
+
@array = []
|
10
|
+
@lock_index = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Array]
|
14
|
+
def array
|
15
|
+
@array.freeze
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param object [Object]
|
19
|
+
def add object
|
20
|
+
@array = @set.add(object).to_a
|
21
|
+
object
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param object [Object]
|
25
|
+
# @return [Boolean] True if object was deleted
|
26
|
+
def delete object
|
27
|
+
return false unless deletable?(object) && @set.delete?(object)
|
28
|
+
|
29
|
+
@array = @set.to_a.freeze
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Lock the current elements in the vault.
|
34
|
+
#
|
35
|
+
# After the vault is locked, calling #delete on a locked element will leave
|
36
|
+
# the element in the array and return false. Elements added after the lock
|
37
|
+
# can be deleted.
|
38
|
+
#
|
39
|
+
def lock
|
40
|
+
return @lock_index if @lock_index
|
41
|
+
|
42
|
+
@lock_index = @array.length
|
43
|
+
end
|
44
|
+
|
45
|
+
# @return [Boolean] True if the object is deletable (i.e., not locked).
|
46
|
+
def deletable? object
|
47
|
+
@lock_index.to_i <= @array.find_index(object).to_i
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/gamefic/version.rb
CHANGED
data/lib/gamefic.rb
CHANGED
@@ -1,22 +1,33 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'json'
|
4
|
+
require 'gamefic/version'
|
5
|
+
require 'gamefic/logging'
|
4
6
|
require 'gamefic/core_ext/array'
|
5
7
|
require 'gamefic/core_ext/string'
|
6
|
-
|
8
|
+
require 'gamefic/syntax'
|
9
|
+
require 'gamefic/response'
|
10
|
+
require 'gamefic/rulebook'
|
11
|
+
require 'gamefic/query'
|
12
|
+
require 'gamefic/scanner'
|
13
|
+
require 'gamefic/scope'
|
14
|
+
require 'gamefic/command'
|
15
|
+
require 'gamefic/action'
|
16
|
+
require 'gamefic/props'
|
17
|
+
require 'gamefic/scene'
|
18
|
+
require 'gamefic/scriptable'
|
19
|
+
require 'gamefic/block'
|
20
|
+
require 'gamefic/stage'
|
21
|
+
require 'gamefic/vault'
|
22
|
+
require 'gamefic/narrative'
|
23
|
+
require 'gamefic/plot'
|
24
|
+
require 'gamefic/subplot'
|
25
|
+
require 'gamefic/snapshot'
|
26
|
+
require 'gamefic/node'
|
7
27
|
require 'gamefic/describable'
|
8
|
-
require 'gamefic/
|
9
|
-
require 'gamefic/element'
|
28
|
+
require 'gamefic/messenger'
|
10
29
|
require 'gamefic/entity'
|
30
|
+
require 'gamefic/dispatcher'
|
11
31
|
require 'gamefic/active'
|
32
|
+
require 'gamefic/active/cue'
|
12
33
|
require 'gamefic/actor'
|
13
|
-
require "gamefic/scene"
|
14
|
-
require "gamefic/query"
|
15
|
-
require "gamefic/action"
|
16
|
-
require "gamefic/syntax"
|
17
|
-
require "gamefic/command"
|
18
|
-
require "gamefic/dispatcher"
|
19
|
-
require 'gamefic/world'
|
20
|
-
require 'gamefic/scriptable'
|
21
|
-
require 'gamefic/plot'
|
22
|
-
require 'gamefic/subplot'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'gamefic'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
# Run specs in random order to surface order dependencies. If you find an
|
8
|
+
# order dependency and want to debug it, you can fix the order by providing
|
9
|
+
# the seed, which is printed after each run.
|
10
|
+
# --seed 1234
|
11
|
+
# config.order = :random
|
12
|
+
|
13
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
14
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
15
|
+
# test failures related to randomization by passing the same `--seed` value
|
16
|
+
# as the one that triggered the failure.
|
17
|
+
# Kernel.srand config.seed
|
18
|
+
|
19
|
+
config.after :each do
|
20
|
+
Gamefic::Narrative.blocks.clear
|
21
|
+
Gamefic::Plot.blocks.clear
|
22
|
+
Gamefic::Subplot.blocks.clear
|
23
|
+
end
|
24
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,57 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gamefic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.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:
|
11
|
+
date: 2024-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: opal
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.7'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: opal-rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: opal-sprockets
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.0'
|
13
55
|
- !ruby/object:Gem::Dependency
|
14
56
|
name: rake
|
15
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -73,6 +115,7 @@ files:
|
|
73
115
|
- ".github/workflows/rspec.yml"
|
74
116
|
- ".gitignore"
|
75
117
|
- ".rspec"
|
118
|
+
- ".rspec-opal"
|
76
119
|
- ".rubocop.yml"
|
77
120
|
- ".solargraph.yml"
|
78
121
|
- CHANGELOG.md
|
@@ -80,58 +123,77 @@ files:
|
|
80
123
|
- LICENSE
|
81
124
|
- README.md
|
82
125
|
- Rakefile
|
126
|
+
- bin/console
|
127
|
+
- bin/setup
|
83
128
|
- gamefic.gemspec
|
84
129
|
- lib/gamefic.rb
|
85
130
|
- lib/gamefic/action.rb
|
86
131
|
- lib/gamefic/active.rb
|
132
|
+
- lib/gamefic/active/cue.rb
|
133
|
+
- lib/gamefic/active/epic.rb
|
134
|
+
- lib/gamefic/active/messaging.rb
|
135
|
+
- lib/gamefic/active/take.rb
|
87
136
|
- lib/gamefic/actor.rb
|
137
|
+
- lib/gamefic/block.rb
|
88
138
|
- lib/gamefic/command.rb
|
89
139
|
- lib/gamefic/core_ext/array.rb
|
90
140
|
- lib/gamefic/core_ext/string.rb
|
91
141
|
- lib/gamefic/describable.rb
|
92
142
|
- lib/gamefic/dispatcher.rb
|
93
|
-
- lib/gamefic/element.rb
|
94
143
|
- lib/gamefic/entity.rb
|
95
|
-
- lib/gamefic/
|
96
|
-
- lib/gamefic/
|
144
|
+
- lib/gamefic/logging.rb
|
145
|
+
- lib/gamefic/messenger.rb
|
146
|
+
- lib/gamefic/narrative.rb
|
97
147
|
- lib/gamefic/node.rb
|
98
148
|
- lib/gamefic/plot.rb
|
99
|
-
- lib/gamefic/
|
100
|
-
- lib/gamefic/
|
101
|
-
- lib/gamefic/
|
149
|
+
- lib/gamefic/props.rb
|
150
|
+
- lib/gamefic/props/default.rb
|
151
|
+
- lib/gamefic/props/multiple_choice.rb
|
152
|
+
- lib/gamefic/props/pause.rb
|
153
|
+
- lib/gamefic/props/yes_or_no.rb
|
102
154
|
- lib/gamefic/query.rb
|
103
155
|
- lib/gamefic/query/base.rb
|
104
|
-
- lib/gamefic/query/
|
105
|
-
- lib/gamefic/query/
|
106
|
-
- lib/gamefic/query/
|
107
|
-
- lib/gamefic/query/family.rb
|
108
|
-
- lib/gamefic/query/itself.rb
|
109
|
-
- lib/gamefic/query/matches.rb
|
110
|
-
- lib/gamefic/query/parent.rb
|
111
|
-
- lib/gamefic/query/siblings.rb
|
156
|
+
- lib/gamefic/query/general.rb
|
157
|
+
- lib/gamefic/query/result.rb
|
158
|
+
- lib/gamefic/query/scoped.rb
|
112
159
|
- lib/gamefic/query/text.rb
|
113
|
-
- lib/gamefic/
|
160
|
+
- lib/gamefic/response.rb
|
161
|
+
- lib/gamefic/rulebook.rb
|
162
|
+
- lib/gamefic/rulebook/calls.rb
|
163
|
+
- lib/gamefic/rulebook/events.rb
|
164
|
+
- lib/gamefic/rulebook/hooks.rb
|
165
|
+
- lib/gamefic/rulebook/scenes.rb
|
166
|
+
- lib/gamefic/scanner.rb
|
114
167
|
- lib/gamefic/scene.rb
|
115
168
|
- lib/gamefic/scene/activity.rb
|
116
|
-
- lib/gamefic/scene/base.rb
|
117
169
|
- lib/gamefic/scene/conclusion.rb
|
170
|
+
- lib/gamefic/scene/default.rb
|
118
171
|
- lib/gamefic/scene/multiple_choice.rb
|
119
|
-
- lib/gamefic/scene/multiple_scene.rb
|
120
172
|
- lib/gamefic/scene/pause.rb
|
121
173
|
- lib/gamefic/scene/yes_or_no.rb
|
174
|
+
- lib/gamefic/scope.rb
|
175
|
+
- lib/gamefic/scope/base.rb
|
176
|
+
- lib/gamefic/scope/children.rb
|
177
|
+
- lib/gamefic/scope/family.rb
|
178
|
+
- lib/gamefic/scope/myself.rb
|
179
|
+
- lib/gamefic/scope/parent.rb
|
180
|
+
- lib/gamefic/scope/siblings.rb
|
122
181
|
- lib/gamefic/scriptable.rb
|
123
|
-
- lib/gamefic/
|
182
|
+
- lib/gamefic/scriptable/actions.rb
|
183
|
+
- lib/gamefic/scriptable/entities.rb
|
184
|
+
- lib/gamefic/scriptable/events.rb
|
185
|
+
- lib/gamefic/scriptable/proxy.rb
|
186
|
+
- lib/gamefic/scriptable/queries.rb
|
187
|
+
- lib/gamefic/scriptable/scenes.rb
|
188
|
+
- lib/gamefic/snapshot.rb
|
189
|
+
- lib/gamefic/stage.rb
|
124
190
|
- lib/gamefic/subplot.rb
|
125
191
|
- lib/gamefic/syntax.rb
|
192
|
+
- lib/gamefic/syntax/template.rb
|
193
|
+
- lib/gamefic/vault.rb
|
126
194
|
- lib/gamefic/version.rb
|
127
|
-
-
|
128
|
-
|
129
|
-
- lib/gamefic/world/commands.rb
|
130
|
-
- lib/gamefic/world/entities.rb
|
131
|
-
- lib/gamefic/world/playbook.rb
|
132
|
-
- lib/gamefic/world/players.rb
|
133
|
-
- lib/gamefic/world/scenes.rb
|
134
|
-
homepage: http://gamefic.com
|
195
|
+
- spec-opal/spec_helper.rb
|
196
|
+
homepage: https://gamefic.com
|
135
197
|
licenses:
|
136
198
|
- MIT
|
137
199
|
metadata: {}
|
@@ -143,7 +205,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
143
205
|
requirements:
|
144
206
|
- - ">="
|
145
207
|
- !ruby/object:Gem::Version
|
146
|
-
version: 2.
|
208
|
+
version: 2.7.0
|
147
209
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
210
|
requirements:
|
149
211
|
- - ">="
|
data/lib/gamefic/element.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module Gamefic
|
2
|
-
# The simplest class that can compose an object for use in a plot.
|
3
|
-
# Most game objects, especially tangible items in the game, should derive
|
4
|
-
# from the Entity class. Elements, on the other hand, can be used for
|
5
|
-
# abstractions and ideas that don't have a physical presence but still might
|
6
|
-
# need to be referenced in a command.
|
7
|
-
#
|
8
|
-
class Element
|
9
|
-
include Gamefic::Describable
|
10
|
-
include Gamefic::Serialize
|
11
|
-
|
12
|
-
def initialize(args = {})
|
13
|
-
klass = self.class
|
14
|
-
defaults = {}
|
15
|
-
while klass <= Element
|
16
|
-
defaults = klass.default_attributes.merge(defaults)
|
17
|
-
klass = klass.superclass
|
18
|
-
end
|
19
|
-
defaults.merge(args).each_pair do |k, v|
|
20
|
-
public_send "#{k}=", v
|
21
|
-
end
|
22
|
-
post_initialize
|
23
|
-
yield self if block_given?
|
24
|
-
end
|
25
|
-
|
26
|
-
def post_initialize
|
27
|
-
# raise NotImplementedError, "#{self.class} must implement post_initialize"
|
28
|
-
end
|
29
|
-
|
30
|
-
class << self
|
31
|
-
# Set or update the default values for new instances.
|
32
|
-
#
|
33
|
-
# @param attrs [Hash] The attributes to be merged into the defaults.
|
34
|
-
def set_default attrs = {}
|
35
|
-
default_attributes.merge! attrs
|
36
|
-
end
|
37
|
-
|
38
|
-
# A hash of default values for attributes when creating an instance.
|
39
|
-
#
|
40
|
-
# @return [Hash]
|
41
|
-
def default_attributes
|
42
|
-
@default_attributes ||= {}
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
data/lib/gamefic/keywords.rb
DELETED
@@ -1,52 +0,0 @@
|
|
1
|
-
module Gamefic
|
2
|
-
module Keywords
|
3
|
-
SPLIT_REGEXP = /[\s]+/
|
4
|
-
|
5
|
-
# Get an array of keywords associated with this object.
|
6
|
-
# The default implementation splits the value of self.to_s into an array.
|
7
|
-
#
|
8
|
-
# @return [Array<String>]
|
9
|
-
def keywords
|
10
|
-
self.to_s.downcase.split(SPLIT_REGEXP).uniq
|
11
|
-
end
|
12
|
-
|
13
|
-
# Determine if this object matches the provided description.
|
14
|
-
# In a regular match, every word in the description must be a keyword.
|
15
|
-
# Fuzzy matches accept words if a keyword starts with it, e.g., "red"
|
16
|
-
# would be a fuzzy match for "reddish."
|
17
|
-
#
|
18
|
-
# @example
|
19
|
-
# dog = "big red dog"
|
20
|
-
# dog.extend Gamefic::Matchable
|
21
|
-
#
|
22
|
-
# dog.specified?("red dog") #=> true
|
23
|
-
# dog.specified?("gray dog") #=> false
|
24
|
-
# dog.specified?("red do") #=> false
|
25
|
-
#
|
26
|
-
# dog.specified?("re do", fuzzy: true) #=> true
|
27
|
-
# dog.specified?("red og", fuzzy: true) #=> false
|
28
|
-
#
|
29
|
-
# @param description [String] The description to be compared
|
30
|
-
# @param fuzzy [Boolean] Use fuzzy matching (default is false)
|
31
|
-
# @return [Boolean]
|
32
|
-
def specified? description, fuzzy: false
|
33
|
-
words = description.split(SPLIT_REGEXP)
|
34
|
-
return false if words.empty?
|
35
|
-
matches = 0
|
36
|
-
available = keywords
|
37
|
-
words.each { |w|
|
38
|
-
if fuzzy
|
39
|
-
available.each { |k|
|
40
|
-
if k.gsub(/[^a-z0-9]/, '').start_with?(w.downcase.gsub(/[^a-z0-9]/, ''))
|
41
|
-
matches +=1
|
42
|
-
break
|
43
|
-
end
|
44
|
-
}
|
45
|
-
else
|
46
|
-
matches +=1 if available.include?(w.downcase)
|
47
|
-
end
|
48
|
-
}
|
49
|
-
matches == words.length
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
data/lib/gamefic/messaging.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
module Gamefic
|
2
|
-
module Messaging
|
3
|
-
# Send a message to the entity.
|
4
|
-
# This method will automatically wrap the message in HTML paragraphs.
|
5
|
-
# To send a message without paragraph formatting, use #stream instead.
|
6
|
-
#
|
7
|
-
# @param message [String]
|
8
|
-
def tell(message)
|
9
|
-
@messages = @messages.to_s + format(message)
|
10
|
-
end
|
11
|
-
|
12
|
-
# Send a message to the Character as raw text.
|
13
|
-
# Unlike #tell, this method will not wrap the message in HTML paragraphs.
|
14
|
-
#
|
15
|
-
# @param message [String]
|
16
|
-
def stream(message)
|
17
|
-
@messages = @messages.to_s + message
|
18
|
-
end
|
19
|
-
|
20
|
-
# Get all the currently buffered messages consolidated in a single string.
|
21
|
-
#
|
22
|
-
# @return [String]
|
23
|
-
def messages
|
24
|
-
@messages ||= ''
|
25
|
-
end
|
26
|
-
|
27
|
-
# Clear the buffered messages.
|
28
|
-
#
|
29
|
-
def flush
|
30
|
-
@messages = ''
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def format message
|
36
|
-
"<p>#{message.strip}</p>"
|
37
|
-
.gsub(/[ \t\r]*\n[ \t\r]*\n[ \t\r]*/, "</p><p>")
|
38
|
-
.gsub(/[ \t]*\n[ \t]*/, ' ')
|
39
|
-
.gsub(/<p>[\s]*<p>/, '<p>')
|
40
|
-
.gsub(/<\/p>[\s]*<\/p>/, '</p>')
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|