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
@@ -1,233 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
|
-
module Gamefic
|
4
|
-
module World
|
5
|
-
# A collection of rules for performing commands.
|
6
|
-
#
|
7
|
-
class Playbook
|
8
|
-
ActionHook = Struct.new(:verb, :block)
|
9
|
-
|
10
|
-
# An array of available syntaxes.
|
11
|
-
#
|
12
|
-
# @return [Array<Gamefic::Syntax>]
|
13
|
-
attr_reader :syntaxes
|
14
|
-
|
15
|
-
# An array of blocks to execute before actions.
|
16
|
-
#
|
17
|
-
# @return [Array<Proc>]
|
18
|
-
attr_reader :before_actions
|
19
|
-
|
20
|
-
# An array of blocks to execute after actions.
|
21
|
-
#
|
22
|
-
# @return [Array<Proc>]
|
23
|
-
attr_reader :after_actions
|
24
|
-
|
25
|
-
# @param commands [Hash]
|
26
|
-
# @param syntaxes [Array<Syntax>, Set<Syntax>]
|
27
|
-
# @param before_actions [Array]
|
28
|
-
# @param after_actions [Array]
|
29
|
-
def initialize commands: {}, syntaxes: [], before_actions: [], after_actions: []
|
30
|
-
@commands = commands
|
31
|
-
@syntax_set = syntaxes.to_set
|
32
|
-
sort_syntaxes
|
33
|
-
@before_actions = before_actions
|
34
|
-
@after_actions = after_actions
|
35
|
-
end
|
36
|
-
|
37
|
-
# An array of available actions.
|
38
|
-
#
|
39
|
-
# @return [Array<Gamefic::Action>]
|
40
|
-
def actions
|
41
|
-
@commands.values.flatten
|
42
|
-
end
|
43
|
-
|
44
|
-
# An array of recognized verbs.
|
45
|
-
#
|
46
|
-
# @return [Array<Symbol>]
|
47
|
-
def verbs
|
48
|
-
@commands.keys
|
49
|
-
end
|
50
|
-
|
51
|
-
# Add a proc to be evaluated before a character executes an action.
|
52
|
-
# When a verb is specified, the proc will only be evaluated if the
|
53
|
-
# action's verb matches it.
|
54
|
-
#
|
55
|
-
# @param verb [Symbol, nil]
|
56
|
-
# @yieldparam [Gamefic::Action]
|
57
|
-
def before_action verb = nil, &block
|
58
|
-
@before_actions.push ActionHook.new(verb, block)
|
59
|
-
end
|
60
|
-
alias validate before_action
|
61
|
-
|
62
|
-
# Add a proc to be evaluated after a character executes an action.
|
63
|
-
# When a verb is specified, the proc will only be evaluated if the
|
64
|
-
# action's verb matches it.
|
65
|
-
#
|
66
|
-
# @param verb [Symbol, nil]
|
67
|
-
# @yieldparam [Gamefic::Action]
|
68
|
-
def after_action verb = nil, &block
|
69
|
-
@after_actions.push ActionHook.new(verb, block)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Get an Array of all Actions associated with the specified verb.
|
73
|
-
#
|
74
|
-
# @param verb [Symbol] The Symbol for the verb (e.g., :go or :look)
|
75
|
-
# @return [Array<Class<Action>>] The verb's associated Actions
|
76
|
-
def actions_for verb
|
77
|
-
@commands[verb] || []
|
78
|
-
end
|
79
|
-
|
80
|
-
# Create an Action that responds to a command.
|
81
|
-
# An Action uses the command argument to identify the imperative verb that
|
82
|
-
# triggers the action.
|
83
|
-
# It can also accept queries to tokenize the remainder of the input and
|
84
|
-
# filter for particular entities or properties.
|
85
|
-
# The block argument contains the code to be executed when the input
|
86
|
-
# matches all of the Action's criteria (i.e., verb and queries).
|
87
|
-
#
|
88
|
-
# @example A simple Action.
|
89
|
-
# respond :salute do |actor|
|
90
|
-
# actor.tell "Hello, sir!"
|
91
|
-
# end
|
92
|
-
# # The command "salute" will respond "Hello, sir!"
|
93
|
-
#
|
94
|
-
# @example An Action that accepts a Character
|
95
|
-
# respond :salute, Use.visible(Character) do |actor, character|
|
96
|
-
# actor.tell "#{The character} returns your salute."
|
97
|
-
# end
|
98
|
-
#
|
99
|
-
# @param verb [Symbol] An imperative verb for the command
|
100
|
-
# @param queries [Array<Query::Base>] Filters for the command's tokens
|
101
|
-
# @yieldparam [Gamefic::Actor]
|
102
|
-
# @return [Class<Gamefic::Action>]
|
103
|
-
def respond(verb, *queries, &proc)
|
104
|
-
act = Action.subclass verb, *queries, &proc
|
105
|
-
add_action act
|
106
|
-
act
|
107
|
-
end
|
108
|
-
|
109
|
-
# Create a Meta Action that responds to a command.
|
110
|
-
# Meta Actions are very similar to standard Actions, except the Plot
|
111
|
-
# understands them to be commands that operate above and/or outside of the
|
112
|
-
# actual game world. Examples of Meta Actions are commands that report the
|
113
|
-
# player's current score, save and restore saved games, or list the game's
|
114
|
-
# credits.
|
115
|
-
#
|
116
|
-
# @example A simple Meta Action
|
117
|
-
# meta :credits do |actor|
|
118
|
-
# actor.tell "This game was written by John Smith."
|
119
|
-
# end
|
120
|
-
#
|
121
|
-
# @param verb [Symbol] An imperative verb for the command
|
122
|
-
# @param queries [Array<Query::Base>] Filters for the command's tokens
|
123
|
-
# @yieldparam [Gamefic::Actor]
|
124
|
-
# @return [Class<Gamefic::Action>]
|
125
|
-
def meta(verb, *queries, &proc)
|
126
|
-
act = Action.subclass verb, *queries, meta: true, &proc
|
127
|
-
add_action act
|
128
|
-
act
|
129
|
-
end
|
130
|
-
|
131
|
-
# Create an alternate Syntax for an Action.
|
132
|
-
# The command and its translation can be parameterized.
|
133
|
-
#
|
134
|
-
# @example Create a synonym for the Inventory Action.
|
135
|
-
# interpret "catalogue", "inventory"
|
136
|
-
# # The command "catalogue" will be translated to "inventory"
|
137
|
-
#
|
138
|
-
# @example Create a parameterized synonym for the Look Action.
|
139
|
-
# interpret "scrutinize :entity", "look :entity"
|
140
|
-
# # The command "scrutinize chair" will be translated to "look chair"
|
141
|
-
#
|
142
|
-
# @param input [String] The format of the original command
|
143
|
-
# @param translation [String] The format of the translated command
|
144
|
-
# @return [Syntax] the Syntax object
|
145
|
-
def interpret(input, translation)
|
146
|
-
syn = Syntax.new(input, translation)
|
147
|
-
add_syntax syn
|
148
|
-
syn
|
149
|
-
end
|
150
|
-
|
151
|
-
# Get a Dispatcher to select actions that can potentially be executed
|
152
|
-
# from the specified command string.
|
153
|
-
#
|
154
|
-
# @param actor [Actor]
|
155
|
-
# @param text [String]
|
156
|
-
# @return [Dispatcher]
|
157
|
-
def dispatch(actor, text)
|
158
|
-
commands = Syntax.tokenize(text, actor.syntaxes)
|
159
|
-
actions = commands.flat_map { |cmd| actions_for(cmd.verb).reject(&:hidden?) }
|
160
|
-
Dispatcher.new(actor, commands, sort_and_reduce_actions(actions))
|
161
|
-
end
|
162
|
-
|
163
|
-
# Get an array of actions, derived from the specified verb and params,
|
164
|
-
# that the actor can potentially execute.
|
165
|
-
#
|
166
|
-
# @return [Array<Gamefic::Action>]
|
167
|
-
def dispatch_from_params actor, verb, params
|
168
|
-
available = actions_for(verb)
|
169
|
-
Dispatcher.new(actor, [Command.new(verb, params)], sort_and_reduce_actions(available))
|
170
|
-
end
|
171
|
-
|
172
|
-
# Duplicate the playbook.
|
173
|
-
# This method will duplicate the commands hash and the syntax array so
|
174
|
-
# the new playbook can be modified without affecting the original.
|
175
|
-
#
|
176
|
-
# @return [Playbook]
|
177
|
-
def dup
|
178
|
-
Playbook.new commands: @commands.dup, syntaxes: @syntaxes.dup
|
179
|
-
end
|
180
|
-
|
181
|
-
def freeze
|
182
|
-
@commands.freeze
|
183
|
-
@syntaxes.freeze
|
184
|
-
end
|
185
|
-
|
186
|
-
private
|
187
|
-
|
188
|
-
def add_action(action)
|
189
|
-
@commands[action.verb] ||= []
|
190
|
-
@commands[action.verb].push action
|
191
|
-
generate_default_syntax action
|
192
|
-
end
|
193
|
-
|
194
|
-
def generate_default_syntax action
|
195
|
-
user_friendly = action.verb.to_s.gsub(/_/, ' ')
|
196
|
-
args = []
|
197
|
-
used_names = []
|
198
|
-
action.queries.each do |_c|
|
199
|
-
num = 1
|
200
|
-
new_name = ":var"
|
201
|
-
while used_names.include? new_name
|
202
|
-
num += 1
|
203
|
-
new_name = ":var#{num}"
|
204
|
-
end
|
205
|
-
used_names.push new_name
|
206
|
-
user_friendly += " #{new_name}"
|
207
|
-
args.push new_name
|
208
|
-
end
|
209
|
-
add_syntax Syntax.new(user_friendly.strip, "#{action.verb} #{args.join(' ')}") unless action.verb.to_s.start_with?('_')
|
210
|
-
end
|
211
|
-
|
212
|
-
def add_syntax syntax
|
213
|
-
raise "No actions exist for \"#{syntax.verb}\"" if @commands[syntax.verb].nil?
|
214
|
-
sort_syntaxes if @syntax_set.add?(syntax)
|
215
|
-
end
|
216
|
-
|
217
|
-
def sort_and_reduce_actions arr
|
218
|
-
arr.sort_by.with_index { |a, i| [a.rank, i] }.reverse.uniq
|
219
|
-
end
|
220
|
-
|
221
|
-
def sort_syntaxes
|
222
|
-
@syntaxes = @syntax_set.sort do |a, b|
|
223
|
-
if a.token_count == b.token_count
|
224
|
-
# For syntaxes of the same length, sort first word
|
225
|
-
b.first_word <=> a.first_word
|
226
|
-
else
|
227
|
-
b.token_count <=> a.token_count
|
228
|
-
end
|
229
|
-
end
|
230
|
-
end
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
module Gamefic
|
2
|
-
module World
|
3
|
-
module Players
|
4
|
-
include Gamefic::World::Entities
|
5
|
-
include Gamefic::World::Commands
|
6
|
-
|
7
|
-
# An array of entities that are currently connected to users.
|
8
|
-
#
|
9
|
-
# @return [Array<Gamefic::Actor>]
|
10
|
-
def players
|
11
|
-
@players ||= []
|
12
|
-
end
|
13
|
-
|
14
|
-
def player_class cls = nil
|
15
|
-
STDERR.puts "Modifying player_class this way is deprecated. Use set_player_class instead" unless cls.nil?
|
16
|
-
@player_class = cls unless cls.nil?
|
17
|
-
@player_class ||= Gamefic::Actor
|
18
|
-
end
|
19
|
-
|
20
|
-
# @param cls [Class]
|
21
|
-
def set_player_class cls
|
22
|
-
unless cls < Gamefic::Active && cls <= Gamefic::Entity
|
23
|
-
raise ArgumentError, "Player class must be an active entity"
|
24
|
-
end
|
25
|
-
@player_class = cls
|
26
|
-
end
|
27
|
-
|
28
|
-
# Make a character that a player will control on introduction.
|
29
|
-
#
|
30
|
-
# @return [Gamefic::Actor]
|
31
|
-
def make_player_character
|
32
|
-
cast player_class, name: 'yourself', synonyms: 'self myself you me', proper_named: true
|
33
|
-
end
|
34
|
-
alias get_player_character make_player_character
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/gamefic/world/scenes.rb
DELETED
@@ -1,228 +0,0 @@
|
|
1
|
-
module Gamefic
|
2
|
-
module World
|
3
|
-
module Scenes
|
4
|
-
include Commands
|
5
|
-
include Players
|
6
|
-
|
7
|
-
# @return [Class<Gamefic::Scene::Activity>]
|
8
|
-
def default_scene
|
9
|
-
@default_scene ||= Scene::Activity
|
10
|
-
end
|
11
|
-
|
12
|
-
# @return [Class<Gamefic::Scene::Conclusion>]
|
13
|
-
def default_conclusion
|
14
|
-
@default_conclusion ||= Scene::Conclusion
|
15
|
-
end
|
16
|
-
|
17
|
-
# Add a block to be executed when a player is added to the game.
|
18
|
-
# Each Plot can only have one introduction. Subsequent calls will
|
19
|
-
# overwrite the existing one.
|
20
|
-
#
|
21
|
-
# @example Welcome the player to the game
|
22
|
-
# introduction do |actor|
|
23
|
-
# actor.tell "Welcome to the game!"
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# @yieldparam [Gamefic::Actor]
|
27
|
-
def introduction(&proc)
|
28
|
-
@introduction = proc
|
29
|
-
end
|
30
|
-
|
31
|
-
# Introduce a player to the game.
|
32
|
-
# This method is typically called by the Engine that manages game execution.
|
33
|
-
#
|
34
|
-
# @param [Gamefic::Actor]
|
35
|
-
# @return [void]
|
36
|
-
def introduce(player)
|
37
|
-
player.playbooks.push playbook unless player.playbooks.include?(playbook)
|
38
|
-
player.cue default_scene
|
39
|
-
players.push player
|
40
|
-
@introduction&.call(player)
|
41
|
-
end
|
42
|
-
|
43
|
-
# Create a multiple-choice scene.
|
44
|
-
# The user will be required to make a valid choice to continue.
|
45
|
-
#
|
46
|
-
# @example
|
47
|
-
# @scene = multiple_choice 'Go to work', 'Go to school' do |actor, scene|
|
48
|
-
# # Assuming user selected the first choice:
|
49
|
-
# scene.selection #=> 'Go to work'
|
50
|
-
# scene.index #=> 0
|
51
|
-
# scene.number #=> 1
|
52
|
-
# end
|
53
|
-
#
|
54
|
-
# @yieldparam [Gamefic::Actor]
|
55
|
-
# @yieldparam [Gamefic::Scene::MultipleChoice]
|
56
|
-
# @return [Class<Gamefic::Scene::MultipleChoice>]
|
57
|
-
def multiple_choice *choices, &block
|
58
|
-
s = Scene::MultipleChoice.subclass do |_actor, scene|
|
59
|
-
scene.options.concat choices
|
60
|
-
scene.on_finish &block
|
61
|
-
end
|
62
|
-
scene_classes.push s
|
63
|
-
s
|
64
|
-
end
|
65
|
-
|
66
|
-
# Create a yes-or-no scene.
|
67
|
-
# The user will be required to answer Yes or No to continue.
|
68
|
-
#
|
69
|
-
# @example
|
70
|
-
# @scene = yes_or_no 'What is your answer?' do |actor, scene|
|
71
|
-
# if scene.yes?
|
72
|
-
# actor.tell "You said yes."
|
73
|
-
# else
|
74
|
-
# actor.tell "You said no."
|
75
|
-
# end
|
76
|
-
# end
|
77
|
-
#
|
78
|
-
# @param prompt [String, nil]
|
79
|
-
# @yieldparam [Gamefic::Actor]
|
80
|
-
# @yieldparam [Gamefic::Scene::YesOrNo]
|
81
|
-
# @return [Class<Gamefic::Scene::YesOrNo>]
|
82
|
-
def yes_or_no prompt = nil, &block
|
83
|
-
s = Scene::YesOrNo.subclass do |_actor, scene|
|
84
|
-
scene.prompt = prompt
|
85
|
-
scene.on_finish &block
|
86
|
-
end
|
87
|
-
scene_classes.push s
|
88
|
-
s
|
89
|
-
end
|
90
|
-
|
91
|
-
# Create a scene with custom processing on user input.
|
92
|
-
#
|
93
|
-
# @example Echo the user's response
|
94
|
-
# @scene = question 'What do you say?' do |actor, scene|
|
95
|
-
# actor.tell "You said #{scene.input}"
|
96
|
-
# end
|
97
|
-
#
|
98
|
-
# @param prompt [String]
|
99
|
-
# @yieldparam [Gamefic::Actor]
|
100
|
-
# @yieldparam [Gamefic::Scene::Base]
|
101
|
-
# @return [Class<Gamefic::Scene::Base>]
|
102
|
-
def question prompt = 'What is your answer?', &block
|
103
|
-
s = Scene::Base.subclass do |_actor, scene|
|
104
|
-
scene.prompt = prompt
|
105
|
-
scene.on_finish &block
|
106
|
-
end
|
107
|
-
scene_classes.push s
|
108
|
-
s
|
109
|
-
end
|
110
|
-
|
111
|
-
# Create a scene that pauses the game.
|
112
|
-
# This scene will execute the specified block and wait for input from the
|
113
|
-
# the user (e.g., pressing Enter) to continue.
|
114
|
-
#
|
115
|
-
# @example
|
116
|
-
# @scene = pause 'Continue' do |actor|
|
117
|
-
# actor.tell "After you continue, you will be prompted for a command."
|
118
|
-
# actor.prepare default_scene
|
119
|
-
# end
|
120
|
-
#
|
121
|
-
# @param prompt [String, nil] The text to display when prompting the user to continue
|
122
|
-
# @yieldparam [Gamefic::Actor]
|
123
|
-
# @return [Class<Gamefic::Scene::Pause>]
|
124
|
-
def pause prompt = nil, &block
|
125
|
-
s = Scene::Pause.subclass do |actor, scene|
|
126
|
-
scene.prompt = prompt unless prompt.nil?
|
127
|
-
block&.call(actor, scene)
|
128
|
-
end
|
129
|
-
scene_classes.push s
|
130
|
-
s
|
131
|
-
end
|
132
|
-
|
133
|
-
# Create a conclusion.
|
134
|
-
# The game (or the character's participation in it) will end after this
|
135
|
-
# scene is complete.
|
136
|
-
#
|
137
|
-
# @example
|
138
|
-
# @scene = conclusion do |actor|
|
139
|
-
# actor.tell 'Game over'
|
140
|
-
# end
|
141
|
-
#
|
142
|
-
# @yieldparam [Gamefic::Actor]
|
143
|
-
# @return [Class<Gamefic::Scene::Conclusion>]
|
144
|
-
def conclusion &block
|
145
|
-
s = Scene::Conclusion.subclass &block
|
146
|
-
scene_classes.push s
|
147
|
-
s
|
148
|
-
end
|
149
|
-
|
150
|
-
# Create a custom scene.
|
151
|
-
#
|
152
|
-
# Custom scenes should always specify the next scene to be cued or
|
153
|
-
# prepared. If not, the scene will get repeated on the next turn.
|
154
|
-
#
|
155
|
-
# This method creates a Scene::Base by default. You can customize other
|
156
|
-
# scene types by specifying the class to create.
|
157
|
-
#
|
158
|
-
# @example Ask the user for a name
|
159
|
-
# @scene = custom do |actor, scene|
|
160
|
-
# scene.prompt = "What's your name?"
|
161
|
-
# scene.on_finish do
|
162
|
-
# actor.name = scene.input
|
163
|
-
# actor.tell "Hello, #{actor.name}!"
|
164
|
-
# actor.cue default_scene
|
165
|
-
# end
|
166
|
-
# end
|
167
|
-
#
|
168
|
-
# @param cls [Class<Scene::Base>] The class of scene to be instantiated.
|
169
|
-
# @yieldparam [Gamefic::Actor]
|
170
|
-
# @return [Class<Gamefic::Scene::Base>]
|
171
|
-
def custom cls = Scene::Base, &block
|
172
|
-
s = cls.subclass &block
|
173
|
-
scene_classes.push s
|
174
|
-
s
|
175
|
-
end
|
176
|
-
|
177
|
-
# Choose a new scene based on a list of options.
|
178
|
-
# This is a specialized type of multiple-choice scene that determines
|
179
|
-
# which scene to cue based on a Hash of choices and scene keys.
|
180
|
-
#
|
181
|
-
# @example Select a scene
|
182
|
-
# scene_one = pause do |actor|
|
183
|
-
# actor.tell "You went to scene one"
|
184
|
-
# end
|
185
|
-
#
|
186
|
-
# scene_two = pause do |actor|
|
187
|
-
# actor.tell "You went to scene two"
|
188
|
-
# end
|
189
|
-
#
|
190
|
-
# select_one_or_two = multiple_scene "One" => scene_one, "Two" => scene_two
|
191
|
-
#
|
192
|
-
# introduction do |actor|
|
193
|
-
# actor.cue select_one_or_two # The actor will be prompted to select "one" or "two" and get sent to the corresponding scene
|
194
|
-
# end
|
195
|
-
#
|
196
|
-
# @example Customize options
|
197
|
-
# scene_one = pause # do...
|
198
|
-
# scene_two = pause # do...
|
199
|
-
#
|
200
|
-
# # Some event in the game sets actor[:can_go_to_scene_two] to true
|
201
|
-
#
|
202
|
-
# select_one_or_two = multiple_scene do |actor, scene|
|
203
|
-
# scene.map "Go to scene one", scene_one
|
204
|
-
# scene.map "Go to scene two", scene_two if actor[:can_go_to_scene_two]
|
205
|
-
# end
|
206
|
-
#
|
207
|
-
# @param map [Hash] A Hash of options and associated scenes.
|
208
|
-
# @yieldparam [Gamefic::Actor]
|
209
|
-
# @yieldparam [Gamefic::Scene::MultipleScene]
|
210
|
-
# @return [Class<Gamefic::Scene::MultipleScene>]
|
211
|
-
def multiple_scene map = {}, &block
|
212
|
-
s = Scene::MultipleScene.subclass do |actor, scene|
|
213
|
-
map.each_pair do |k, v|
|
214
|
-
scene.map k, v
|
215
|
-
end
|
216
|
-
block&.call actor, scene
|
217
|
-
end
|
218
|
-
scene_classes.push s
|
219
|
-
s
|
220
|
-
end
|
221
|
-
|
222
|
-
# @return [Array<Class<Gamefic::Scene::Base>>]
|
223
|
-
def scene_classes
|
224
|
-
@scene_classes ||= []
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|
228
|
-
end
|
data/lib/gamefic/world.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
module Gamefic
|
2
|
-
# A collection of classes and modules related to generating a world model.
|
3
|
-
#
|
4
|
-
module World
|
5
|
-
autoload :Playbook, 'gamefic/world/playbook'
|
6
|
-
autoload :Entities, 'gamefic/world/entities'
|
7
|
-
autoload :Commands, 'gamefic/world/commands'
|
8
|
-
autoload :Callbacks, 'gamefic/world/callbacks'
|
9
|
-
autoload :Scenes, 'gamefic/world/scenes'
|
10
|
-
autoload :Players, 'gamefic/world/players'
|
11
|
-
|
12
|
-
include Entities
|
13
|
-
include Commands
|
14
|
-
include Callbacks
|
15
|
-
include Scenes
|
16
|
-
include Players
|
17
|
-
end
|
18
|
-
end
|