gamefic 0.6.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/gamefic +3 -0
- data/lib/gamefic/character.rb +42 -6
- data/lib/gamefic/director/parser.rb +25 -25
- data/lib/gamefic/engine/tty.rb +14 -2
- data/lib/gamefic/engine.rb +8 -7
- data/lib/gamefic/grammar/gender.rb +1 -1
- data/lib/gamefic/grammar/pronouns.rb +53 -8
- data/lib/gamefic/grammar/verbs.rb +1 -0
- data/lib/gamefic/grammar/word_adapter.rb +31 -18
- data/lib/gamefic/html.rb +27 -13
- data/lib/gamefic/plot/article_mount.rb +1 -1
- data/lib/gamefic/plot/scene_mount.rb +27 -110
- data/lib/gamefic/{snapshots.rb → plot/snapshot.rb} +60 -29
- data/lib/gamefic/plot/you_mount.rb +1 -1
- data/lib/gamefic/plot.rb +56 -29
- data/lib/gamefic/query/base.rb +3 -1
- data/lib/gamefic/scene/active.rb +11 -18
- data/lib/gamefic/scene/base.rb +21 -0
- data/lib/gamefic/scene/conclusion.rb +11 -0
- data/lib/gamefic/scene/custom.rb +21 -0
- data/lib/gamefic/scene/multiple_choice/input.rb +11 -0
- data/lib/gamefic/scene/multiple_choice.rb +73 -0
- data/lib/gamefic/scene/passive.rb +17 -0
- data/lib/gamefic/scene/pause.rb +24 -0
- data/lib/gamefic/scene/question.rb +21 -0
- data/lib/gamefic/scene/yes_or_no.rb +30 -0
- data/lib/gamefic/scene.rb +10 -120
- data/lib/gamefic/script/base.rb +7 -2
- data/lib/gamefic/script.rb +4 -0
- data/lib/gamefic/shell/command/base.rb +38 -0
- data/lib/gamefic/shell/command/play.rb +51 -0
- data/lib/gamefic/shell/command.rb +4 -0
- data/lib/gamefic/shell/registry.rb +13 -0
- data/lib/gamefic/shell.rb +14 -71
- data/lib/gamefic/source/file.rb +1 -1
- data/lib/gamefic/source.rb +5 -0
- data/lib/gamefic/tester.rb +0 -1
- data/lib/gamefic/version.rb +1 -1
- data/lib/gamefic.rb +1 -6
- metadata +69 -61
- data/lib/gamefic/scene/concluded.rb +0 -22
- data/lib/gamefic/scene/multiplechoice.rb +0 -74
- data/lib/gamefic/scene/paused.rb +0 -26
- data/lib/gamefic/scene/yesorno.rb +0 -43
@@ -4,50 +4,25 @@ end
|
|
4
4
|
module Gamefic
|
5
5
|
|
6
6
|
module Plot::SceneMount
|
7
|
-
# Get a Hash of SceneManager objects.
|
8
|
-
#
|
9
|
-
# @return [Hash<Symbol, SceneManager>]
|
10
|
-
def scene_managers
|
11
|
-
if @scene_managers.nil?
|
12
|
-
@scene_managers ||= {}
|
13
|
-
@scene_managers[:active] = ActiveSceneManager.new
|
14
|
-
@scene_managers[:concluded] = ConcludedSceneManager.new
|
15
|
-
end
|
16
|
-
@scene_managers
|
17
|
-
end
|
18
|
-
|
19
7
|
# Create a multiple-choice scene.
|
20
8
|
# The user will be required to make a valid choice to continue
|
21
9
|
#
|
22
10
|
# @yieldparam [Character]
|
23
|
-
# @yieldparam [
|
24
|
-
def multiple_choice key,
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
config.finish(&block)
|
30
|
-
end
|
11
|
+
# @yieldparam [String]
|
12
|
+
def multiple_choice key, options, &block
|
13
|
+
scenes[key] = Scene::MultipleChoice.new(
|
14
|
+
options: options,
|
15
|
+
finish: block
|
16
|
+
)
|
31
17
|
end
|
32
18
|
|
33
19
|
# Create a yes-or-no scene.
|
34
20
|
# The user will be required to answer Yes or No to continue.
|
35
21
|
#
|
36
22
|
# @yieldparam [Character]
|
37
|
-
# @yieldparam [
|
23
|
+
# @yieldparam [String] "yes" or "no"
|
38
24
|
def yes_or_no key, prompt = nil, &block
|
39
|
-
|
40
|
-
config.prompt = prompt
|
41
|
-
config.finish do |actor, data|
|
42
|
-
if data.answer.nil?
|
43
|
-
actor.tell "Please answer Yes or No."
|
44
|
-
else
|
45
|
-
data.next_cue ||= :active
|
46
|
-
block.call(actor, data)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
scene_managers[key] = manager
|
25
|
+
scenes[key] = Scene::YesOrNo.new(prompt, &block)
|
51
26
|
end
|
52
27
|
|
53
28
|
# Create a scene with a prompt.
|
@@ -55,18 +30,11 @@ module Gamefic
|
|
55
30
|
# from the user.
|
56
31
|
#
|
57
32
|
# @param key [Symbol] A unique name for the scene.
|
58
|
-
# @param prompt [String] The prompt
|
33
|
+
# @param prompt [String] The input prompt to display to the user.
|
59
34
|
# @yieldparam [Character]
|
60
|
-
# @yieldparam [
|
61
|
-
def
|
62
|
-
|
63
|
-
config.prompt = prompt
|
64
|
-
config.finish do |actor, data|
|
65
|
-
data.next_cue ||= :active
|
66
|
-
block.call actor, data
|
67
|
-
end
|
68
|
-
end
|
69
|
-
scene_managers[key].state = "Prompted"
|
35
|
+
# @yieldparam [String]
|
36
|
+
def question key, prompt, &block
|
37
|
+
scenes[key] = Scene::Question.new prompt, &block
|
70
38
|
end
|
71
39
|
|
72
40
|
# Create a scene that pauses the game.
|
@@ -75,15 +43,8 @@ module Gamefic
|
|
75
43
|
#
|
76
44
|
# @param key [Symbol] A unique name for the scene.
|
77
45
|
# @yieldparam [Character]
|
78
|
-
# @yieldparam [SceneData]
|
79
46
|
def pause key, &block
|
80
|
-
|
81
|
-
config.start do |actor, data|
|
82
|
-
data.next_cue = :active
|
83
|
-
block.call actor, data
|
84
|
-
end
|
85
|
-
end
|
86
|
-
scene_managers[key] = manager
|
47
|
+
scenes[key] = Scene::Pause.new &block
|
87
48
|
end
|
88
49
|
|
89
50
|
# Create a conclusion.
|
@@ -91,32 +52,18 @@ module Gamefic
|
|
91
52
|
#
|
92
53
|
# @param key [Symbol] A unique name for the scene.
|
93
54
|
# @yieldparam [Character]
|
94
|
-
# @yieldparam [SceneData]
|
95
55
|
def conclusion key, &block
|
96
|
-
|
97
|
-
config.start(&block)
|
98
|
-
end
|
99
|
-
scene_managers[key] = manager
|
56
|
+
scenes[key] = Scene::Conclusion.new &block
|
100
57
|
end
|
101
58
|
|
102
59
|
# Create a generic scene.
|
103
|
-
# After the scene is complete, it will automatically start the next
|
60
|
+
# After the scene is complete, it will automatically start the next
|
61
|
+
# prepared scene, or the :active scene if none is prepared.
|
104
62
|
#
|
105
63
|
# @param [Symbol] A unique name for the scene.
|
106
64
|
# @yieldparam [Character]
|
107
|
-
# @yieldparam [SceneData]
|
108
65
|
def scene key, &block
|
109
|
-
|
110
|
-
manager.start do |actor, data|
|
111
|
-
data.next_cue = :active
|
112
|
-
block.call(actor, data) if !block.nil?
|
113
|
-
cue actor, data.next_cue
|
114
|
-
actor.scene.start actor
|
115
|
-
end
|
116
|
-
# Since generic scenes always cue a new scene, there's no reason to
|
117
|
-
# define a finish block.
|
118
|
-
end
|
119
|
-
scene_managers[key] = scene
|
66
|
+
scenes[key] = Scene::Passive.new &block
|
120
67
|
end
|
121
68
|
|
122
69
|
# Branch to a new scene based on a list of options.
|
@@ -132,50 +79,20 @@ module Gamefic
|
|
132
79
|
# actor.tell "You went to scene two"
|
133
80
|
# end
|
134
81
|
# introduction do |actor|
|
135
|
-
# cue
|
82
|
+
# actor.cue, :select_one_or_two # The actor will be prompted to select "one" or "two" and get sent to the corresponding scene
|
136
83
|
# end
|
137
84
|
#
|
138
85
|
# @param key [Symbol] A unique name for the scene.
|
139
|
-
# @param
|
140
|
-
def branch key,
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
#
|
148
|
-
# @param actor [Character] The character being cued
|
149
|
-
# @param key [Symbol] The name of the scene
|
150
|
-
def cue actor, key
|
151
|
-
if !actor.scene.nil? and actor.scene.state == "Concluded"
|
152
|
-
return
|
153
|
-
end
|
154
|
-
if key.nil?
|
155
|
-
raise "Cueing scene with nil key"
|
156
|
-
end
|
157
|
-
manager = scene_managers[key]
|
158
|
-
if manager.nil?
|
159
|
-
raise "No '#{key}' scene found"
|
160
|
-
else
|
161
|
-
actor.scene = manager.prepare key
|
162
|
-
end
|
163
|
-
@scene
|
164
|
-
end
|
165
|
-
|
166
|
-
# This is functionally identical to #cue, but it also raises an
|
167
|
-
# exception if the selected scene is not a Concluded state.
|
168
|
-
#
|
169
|
-
# @param actor [Character] The character being cued
|
170
|
-
# @param key [Symbol] The name of the scene
|
171
|
-
def conclude actor, key
|
172
|
-
key = :concluded if key.nil?
|
173
|
-
manager = scene_managers[key]
|
174
|
-
if manager.state != "Concluded"
|
175
|
-
raise NotConclusionError("Cued scene '#{key}' is not a conclusion")
|
176
|
-
end
|
177
|
-
cue actor, key
|
86
|
+
# @param map [Hash] A Hash of options and associated scene keys.
|
87
|
+
def branch key, map
|
88
|
+
scenes[key] = Scene::MultipleChoice.new(
|
89
|
+
options: map.keys,
|
90
|
+
finish: proc { |actor, input|
|
91
|
+
actor.cue map[input.choice]
|
92
|
+
}
|
93
|
+
)
|
178
94
|
end
|
95
|
+
|
179
96
|
end
|
180
97
|
|
181
98
|
end
|
@@ -1,13 +1,8 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
3
|
module Gamefic
|
4
|
-
|
5
|
-
|
6
|
-
def initialize entities
|
7
|
-
@history = []
|
8
|
-
@entities = entities
|
9
|
-
end
|
10
|
-
def save entities
|
4
|
+
module Plot::Snapshot
|
5
|
+
def save
|
11
6
|
store = []
|
12
7
|
index = 0
|
13
8
|
entities.each { |e|
|
@@ -19,11 +14,11 @@ module Gamefic
|
|
19
14
|
end
|
20
15
|
if e.respond_to?(m) == true
|
21
16
|
begin
|
22
|
-
|
23
|
-
if
|
17
|
+
val = e.send(m)
|
18
|
+
if val == false
|
24
19
|
hash[con] = false
|
25
|
-
elsif
|
26
|
-
hash[con] = serialize_obj(
|
20
|
+
elsif val
|
21
|
+
hash[con] = serialize_obj(val)
|
27
22
|
else
|
28
23
|
hash[con] = nil
|
29
24
|
end
|
@@ -32,6 +27,7 @@ module Gamefic
|
|
32
27
|
end
|
33
28
|
end
|
34
29
|
}
|
30
|
+
hash[:class] = e.class.to_s
|
35
31
|
hash[:session] = {}
|
36
32
|
e.session.each_pair { |k, v|
|
37
33
|
hash[:session][k] = serialize_obj(v)
|
@@ -39,29 +35,68 @@ module Gamefic
|
|
39
35
|
store.push hash
|
40
36
|
index += 1
|
41
37
|
}
|
42
|
-
if @
|
43
|
-
@
|
38
|
+
if @initial_state.nil?
|
39
|
+
@initial_state = store
|
40
|
+
store = []
|
41
|
+
@initial_state.length.times do
|
42
|
+
store.push {}
|
43
|
+
end
|
44
|
+
else
|
45
|
+
store = reduce(store)
|
44
46
|
end
|
45
|
-
|
46
|
-
#puts json
|
47
|
-
json
|
47
|
+
store
|
48
48
|
end
|
49
49
|
def restore snapshot
|
50
|
-
|
50
|
+
internal_restore snapshot, true
|
51
|
+
end
|
52
|
+
private
|
53
|
+
def internal_restore snapshot, with_restore = true
|
54
|
+
if with_restore
|
55
|
+
@entities[@initial_state.length..-1].each { |e|
|
56
|
+
e.parent = nil
|
57
|
+
}
|
58
|
+
@entities.slice! @initial_state.length..-1
|
59
|
+
internal_restore @initial_state, false
|
60
|
+
end
|
51
61
|
index = 0
|
52
|
-
|
62
|
+
snapshot.each { |hash|
|
63
|
+
if entities[index].nil?
|
64
|
+
if with_restore
|
65
|
+
cls = Kernel.const_get(hash[:class])
|
66
|
+
entities[index] = make cls
|
67
|
+
else
|
68
|
+
break
|
69
|
+
end
|
70
|
+
end
|
53
71
|
hash.each_pair { |k, v|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
72
|
+
if k == :scene
|
73
|
+
entities[index].cue v.to_sym
|
74
|
+
else
|
75
|
+
entities[index].send("#{k}=", unserialize(v)) if k != :session and k != :class
|
76
|
+
end
|
59
77
|
}
|
78
|
+
unless hash[:session].nil?
|
79
|
+
hash[:session].each_pair { |k, v|
|
80
|
+
entities[index].session[k.to_sym] = unserialize(v)
|
81
|
+
}
|
82
|
+
end
|
60
83
|
index += 1
|
61
84
|
}
|
62
85
|
end
|
63
|
-
def
|
64
|
-
|
86
|
+
def reduce entities
|
87
|
+
reduced = []
|
88
|
+
index = 0
|
89
|
+
entities.each { |e|
|
90
|
+
r = {}
|
91
|
+
e.each_pair { |k, v|
|
92
|
+
if index >= @initial_state.length or @initial_state[index][k] != v
|
93
|
+
r[k] = v
|
94
|
+
end
|
95
|
+
}
|
96
|
+
reduced.push r
|
97
|
+
index += 1
|
98
|
+
}
|
99
|
+
reduced
|
65
100
|
end
|
66
101
|
private
|
67
102
|
def can_serialize? obj
|
@@ -98,8 +133,6 @@ module Gamefic
|
|
98
133
|
return "#<EIN_#{@entities.index(obj)}>"
|
99
134
|
elsif obj.kind_of?(Direction)
|
100
135
|
return "#<DIR_#{obj.name}>"
|
101
|
-
#elsif obj.kind_of?(Symbol)
|
102
|
-
# return "#<SYM_#{obj.to_s}>"
|
103
136
|
end
|
104
137
|
end
|
105
138
|
return obj
|
@@ -123,8 +156,6 @@ module Gamefic
|
|
123
156
|
@entities[i]
|
124
157
|
elsif obj.to_s.match(/^#<DIR_[a-z]+>$/)
|
125
158
|
Direction.find(obj[6..-2])
|
126
|
-
#elsif obj.to_s.match(/^#<SYM_[a-z]+>$/)
|
127
|
-
# Direction.find(obj[6..-2].to_sym)
|
128
159
|
else
|
129
160
|
obj
|
130
161
|
end
|
data/lib/gamefic/plot.rb
CHANGED
@@ -5,8 +5,6 @@ require 'gamefic/tester'
|
|
5
5
|
require 'gamefic/source'
|
6
6
|
require 'gamefic/script'
|
7
7
|
require 'gamefic/query'
|
8
|
-
require 'gamefic/plot/article_mount'
|
9
|
-
require 'gamefic/plot/you_mount'
|
10
8
|
|
11
9
|
module Gamefic
|
12
10
|
|
@@ -15,35 +13,52 @@ module Gamefic
|
|
15
13
|
autoload :CommandMount, 'gamefic/plot/command_mount'
|
16
14
|
autoload :EntityMount, 'gamefic/plot/entity_mount'
|
17
15
|
autoload :QueryMount, 'gamefic/plot/query_mount'
|
18
|
-
|
19
|
-
|
16
|
+
autoload :ArticleMount, 'gamefic/plot/article_mount'
|
17
|
+
autoload :YouMount, 'gamefic/plot/you_mount'
|
18
|
+
autoload :Snapshot, 'gamefic/plot/snapshot'
|
19
|
+
|
20
20
|
attr_reader :commands, :imported_scripts, :rules, :asserts, :source
|
21
|
-
|
21
|
+
# TODO Metadata could use better protection
|
22
|
+
attr_accessor :default_scene, :metadata
|
22
23
|
include Stage
|
23
24
|
# TODO This include is only here to make the module's methods visible in the IDE.
|
24
25
|
# Gamefic Studio has a PlotStageMetaMapper that handles it, but it doesn't run if
|
25
26
|
# the plugin isn't activated.
|
26
|
-
include Gamefic, Tester, SceneMount, CommandMount, EntityMount, QueryMount, ArticleMount, YouMount
|
27
|
-
mount Gamefic, Tester, SceneMount, CommandMount, EntityMount, QueryMount, ArticleMount, YouMount
|
28
|
-
expose :script, :introduction, :assert_action, :on_update, :on_player_update, :entities, :on_ready, :on_player_ready, :players
|
27
|
+
#include Gamefic, Tester, SceneMount, CommandMount, EntityMount, QueryMount, ArticleMount, YouMount, Snapshot
|
28
|
+
mount Gamefic, Tester, SceneMount, CommandMount, EntityMount, QueryMount, ArticleMount, YouMount, Snapshot
|
29
|
+
expose :script, :introduction, :assert_action, :before_player_update, :on_update, :on_player_update, :entities, :on_ready, :on_player_ready, :players, :scenes, :metadata
|
29
30
|
|
30
31
|
# @param [Source::Base]
|
31
32
|
def initialize(source = nil)
|
32
33
|
@source = source || Source::Text.new({})
|
33
|
-
@commands =
|
34
|
-
@syntaxes =
|
35
|
-
@ready_procs =
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@
|
40
|
-
@
|
41
|
-
@
|
42
|
-
@
|
43
|
-
@
|
34
|
+
@commands = {}
|
35
|
+
@syntaxes = []
|
36
|
+
@ready_procs = []
|
37
|
+
@before_player_update_procs = []
|
38
|
+
@update_procs = []
|
39
|
+
@player_ready = []
|
40
|
+
@player_procs = []
|
41
|
+
@working_scripts = []
|
42
|
+
@imported_scripts = []
|
43
|
+
@entities = []
|
44
|
+
@players = []
|
45
|
+
@asserts = {}
|
44
46
|
@default_scene = :active
|
45
47
|
post_initialize
|
46
48
|
end
|
49
|
+
|
50
|
+
def scenes
|
51
|
+
if @scenes.nil?
|
52
|
+
@scenes = {}
|
53
|
+
@scenes[:active] = Scene::Active.new
|
54
|
+
@scenes[:concluded] = Scene::Conclusion.new
|
55
|
+
end
|
56
|
+
@scenes
|
57
|
+
end
|
58
|
+
|
59
|
+
def concluded?(actor)
|
60
|
+
scenes[actor.scene].kind_of?(Scene::Conclusion)
|
61
|
+
end
|
47
62
|
|
48
63
|
# Get an Array of all Actions defined in the Plot.
|
49
64
|
#
|
@@ -158,7 +173,7 @@ module Gamefic
|
|
158
173
|
# by the plot, which would be :active by default. We could
|
159
174
|
# get it like player.cue nil.
|
160
175
|
if player.scene.nil?
|
161
|
-
cue
|
176
|
+
player.cue :active
|
162
177
|
ready
|
163
178
|
update
|
164
179
|
end
|
@@ -175,7 +190,6 @@ module Gamefic
|
|
175
190
|
@player_ready.each { |block|
|
176
191
|
block.call player
|
177
192
|
}
|
178
|
-
player.scene.start player
|
179
193
|
}
|
180
194
|
end
|
181
195
|
|
@@ -184,14 +198,24 @@ module Gamefic
|
|
184
198
|
def update
|
185
199
|
# Update the plot.
|
186
200
|
@players.each { |player|
|
187
|
-
|
201
|
+
# TODO: This really doesn't belong here. We need a before_update in the plot.
|
202
|
+
@before_player_update_procs.each { |p|
|
203
|
+
p.call player
|
204
|
+
}
|
205
|
+
this_scene = player.next_scene || player.scene
|
206
|
+
player.prepare nil
|
207
|
+
if this_scene != player.scene
|
208
|
+
player.cue this_scene
|
209
|
+
player.queue.shift
|
210
|
+
else
|
211
|
+
process_input player
|
212
|
+
end
|
188
213
|
}
|
189
214
|
@entities.each { |e|
|
190
215
|
e.update
|
191
216
|
}
|
192
217
|
@players.each { |player|
|
193
218
|
update_player player
|
194
|
-
cue player, player.scene.data.next_cue if !player.scene.data.next_cue.nil?
|
195
219
|
}
|
196
220
|
@update_procs.each { |p|
|
197
221
|
p.call
|
@@ -242,22 +266,25 @@ module Gamefic
|
|
242
266
|
@player_procs.push block
|
243
267
|
end
|
244
268
|
|
269
|
+
# Add a block to be executed for each player before the turn's update is
|
270
|
+
# performed.
|
271
|
+
#
|
272
|
+
# @yieldparam [Character]
|
273
|
+
def before_player_update &block
|
274
|
+
@before_player_update_procs.push block
|
275
|
+
end
|
276
|
+
|
245
277
|
private
|
246
278
|
def process_input player
|
247
279
|
line = player.queue.shift
|
248
280
|
if !line.nil?
|
249
|
-
player.scene.finish player, line
|
250
|
-
#cue player, player.scene.data.next_cue if !player.scene.data.next_cue.nil?
|
281
|
+
scenes[player.scene].finish player, line
|
251
282
|
end
|
252
283
|
end
|
253
284
|
def update_player player
|
254
285
|
@player_procs.each { |proc|
|
255
286
|
proc.call player
|
256
287
|
}
|
257
|
-
# HACK Exception for running tests
|
258
|
-
if player[:testing] == true
|
259
|
-
cue player, :test
|
260
|
-
end
|
261
288
|
end
|
262
289
|
def rem_entity(entity)
|
263
290
|
@entities.delete(entity)
|
data/lib/gamefic/query/base.rb
CHANGED
@@ -16,6 +16,8 @@ module Gamefic::Query
|
|
16
16
|
@arguments = arguments
|
17
17
|
@match_hash = Hash.new
|
18
18
|
end
|
19
|
+
# Check whether the query allows ambiguous matches.
|
20
|
+
# If allowed, this query's
|
19
21
|
def allow_ambiguous?
|
20
22
|
false
|
21
23
|
end
|
@@ -110,7 +112,7 @@ module Gamefic::Query
|
|
110
112
|
arguments.each { |a|
|
111
113
|
if a.kind_of?(Class) or a.kind_of?(Module)
|
112
114
|
my_classes.push a
|
113
|
-
elsif a.kind_of?(Entity)
|
115
|
+
elsif a.kind_of?(Gamefic::Entity)
|
114
116
|
my_objects.push a
|
115
117
|
elsif a.kind_of?(Symbol)
|
116
118
|
if my_classes.length == 0 and my_objects.length == 0
|
data/lib/gamefic/scene/active.rb
CHANGED
@@ -1,25 +1,18 @@
|
|
1
1
|
module Gamefic
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
# Active Scenes handle the default command prompt, where input is parsed
|
4
|
+
# into an Action performed by the Character. This is the default scene in
|
5
|
+
# a Plot.
|
6
|
+
#
|
7
|
+
class Scene::Active < Scene::Base
|
8
|
+
def start actor
|
9
|
+
# TODO Anything necessary here?
|
6
10
|
end
|
7
|
-
def state
|
8
|
-
@state ||= "Active"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class ActiveScene < Scene
|
13
11
|
def finish actor, input
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
# HACK Set the last_order here so inline performs don't set it
|
18
|
-
actor.send(:last_order=, last_order)
|
19
|
-
else
|
20
|
-
@finish.call actor, data
|
21
|
-
end
|
12
|
+
last_order = actor.perform input
|
13
|
+
# HACK Set the last_order here so inline performs don't set it
|
14
|
+
actor.send(:last_order=, last_order)
|
22
15
|
end
|
23
16
|
end
|
24
|
-
|
17
|
+
|
25
18
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gamefic::Scene
|
2
|
+
|
3
|
+
# The Base Scene is not intended for instantiation. Other Scene classes
|
4
|
+
# should inherit from it.
|
5
|
+
#
|
6
|
+
class Base
|
7
|
+
def prompt
|
8
|
+
@prompt ||= '>'
|
9
|
+
end
|
10
|
+
def start actor
|
11
|
+
|
12
|
+
end
|
13
|
+
def finish actor, input
|
14
|
+
|
15
|
+
end
|
16
|
+
def state
|
17
|
+
self.class.to_s.split('::').last
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Gamefic
|
2
|
+
|
3
|
+
# A Custom Scene is a generic scene that allows for complete configuration
|
4
|
+
# of its behavior upon instantiation. It is suitable for direct instantion
|
5
|
+
# or extension by other Scene classes.
|
6
|
+
#
|
7
|
+
class Scene::Custom < Scene::Base
|
8
|
+
def initialize config = {}
|
9
|
+
@start = config[:start]
|
10
|
+
@finish = config[:finish]
|
11
|
+
@prompt = config[:prompt]
|
12
|
+
end
|
13
|
+
def start actor
|
14
|
+
@start.call(actor) unless @start.nil?
|
15
|
+
end
|
16
|
+
def finish actor, input
|
17
|
+
@finish.call(actor, input) unless @finish.nil?
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|