gamefic 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/gamefic/action.rb +11 -12
- data/lib/gamefic/director/delegate.rb +61 -48
- data/lib/gamefic/director/parser.rb +1 -1
- data/lib/gamefic/engine/tty.rb +2 -5
- data/lib/gamefic/plot.rb +9 -3
- data/lib/gamefic/plot/command_mount.rb +5 -2
- data/lib/gamefic/plot/snapshot.rb +121 -55
- data/lib/gamefic/subplot.rb +81 -0
- data/lib/gamefic/syntax.rb +1 -4
- data/lib/gamefic/version.rb +1 -1
- metadata +26 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b365a88c85293650a4450cb905443a222aa1fa23
|
4
|
+
data.tar.gz: 2e299521b31b1c357651c52b7d2978c69988f306
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5839d40d6211f3327e7f0d79667e591456e44a72da1f622f87af99127dcc97a207b6cefe06f6beb5edb75e135d85b1517a8731504b032fa706062f86d4c69e0b
|
7
|
+
data.tar.gz: 6ad1537348f09477915daab0a77b1709cea1380145323ab4d803565898f9ab693bd0fd065dd33eef57d94d09d104355d64e7119978e2f57fba359c58a599fde5
|
data/lib/gamefic/action.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
module Gamefic
|
2
2
|
|
3
|
+
# Exception raised when the Action's proc arity is not compatible with the
|
4
|
+
# number of queries
|
5
|
+
class ActionArgumentError < ArgumentError
|
6
|
+
end
|
7
|
+
|
3
8
|
# Actions manage the execution of commands that Characters can perform.
|
4
9
|
#
|
5
10
|
class Action
|
@@ -7,28 +12,24 @@ module Gamefic
|
|
7
12
|
attr_writer :meta
|
8
13
|
@@order_key_seed = 0
|
9
14
|
|
10
|
-
def initialize(
|
15
|
+
def initialize(verb, *queries, &proc)
|
11
16
|
if !verb.kind_of?(Symbol)
|
12
17
|
verb = verb.to_s
|
13
18
|
verb = nil if verb == ''
|
14
19
|
end
|
15
|
-
@plot = plot
|
16
20
|
@order_key = @@order_key_seed
|
17
21
|
@@order_key_seed += 1
|
18
22
|
@proc = proc
|
19
23
|
if (verb.kind_of?(Symbol) == false and !verb.nil?)
|
20
|
-
raise "Action verbs must be symbols"
|
24
|
+
raise "Action verbs must be symbols #{verb}"
|
21
25
|
end
|
22
26
|
if !@proc.nil?
|
23
|
-
if (queries.length + 1 != @proc.arity) and (
|
24
|
-
raise "Number of queries is not compatible with proc arguments"
|
27
|
+
if (queries.length + 1 != @proc.arity) and (@proc.arity > 0)
|
28
|
+
raise ActionArgumentError.new("Number of queries is not compatible with proc arguments")
|
25
29
|
end
|
26
30
|
end
|
27
31
|
@verb = verb
|
28
32
|
@queries = queries
|
29
|
-
if !plot.nil?
|
30
|
-
plot.send :add_action, self
|
31
|
-
end
|
32
33
|
end
|
33
34
|
|
34
35
|
# Get the specificity of the Action.
|
@@ -44,14 +45,12 @@ module Gamefic
|
|
44
45
|
if verb.nil?
|
45
46
|
spec = -100
|
46
47
|
end
|
47
|
-
magnitude = 1
|
48
48
|
@queries.each { |q|
|
49
49
|
if q.kind_of?(Query::Base)
|
50
|
-
spec +=
|
50
|
+
spec += q.specificity
|
51
51
|
else
|
52
|
-
spec +=
|
52
|
+
spec += 1
|
53
53
|
end
|
54
|
-
#magnitude = magnitude * 10
|
55
54
|
}
|
56
55
|
return spec
|
57
56
|
end
|
@@ -4,7 +4,7 @@ module Gamefic
|
|
4
4
|
# If we use Query::Base.new in the @disambiguator declaration, Opal
|
5
5
|
# passes the block to the query instead of the action.
|
6
6
|
base = Query::Base.new
|
7
|
-
@@disambiguator = Action.new nil,
|
7
|
+
@@disambiguator = Action.new nil, base do |actor, entities|
|
8
8
|
definites = []
|
9
9
|
entities.each { |entity|
|
10
10
|
definites.push entity.definitely
|
@@ -23,53 +23,7 @@ module Gamefic
|
|
23
23
|
while !executed
|
24
24
|
order = @orders.shift
|
25
25
|
break if order.nil?
|
26
|
-
|
27
|
-
final_arguments = []
|
28
|
-
order.arguments.each { |argument|
|
29
|
-
if argument.length > 1 and !order.action.queries[arg_i].allow_many?
|
30
|
-
if argument[0].kind_of?(Array)
|
31
|
-
# This thing refers to multiple items. Just keep going.
|
32
|
-
final_arguments = nil
|
33
|
-
break
|
34
|
-
else
|
35
|
-
ambiguous = argument
|
36
|
-
end
|
37
|
-
order = Order.new(@actor, @@disambiguator, [])
|
38
|
-
final_arguments = [ambiguous]
|
39
|
-
break
|
40
|
-
end
|
41
|
-
valid = []
|
42
|
-
if order.action.queries[arg_i].allow_ambiguous?
|
43
|
-
valid = argument.flatten
|
44
|
-
else
|
45
|
-
argument.each { |m|
|
46
|
-
if order.action.queries[arg_i].validate(@actor, m)
|
47
|
-
valid.push m
|
48
|
-
else
|
49
|
-
final_arguments = nil
|
50
|
-
break
|
51
|
-
end
|
52
|
-
}
|
53
|
-
end
|
54
|
-
if order.action == @@disambiguator or final_arguments.nil?
|
55
|
-
break
|
56
|
-
end
|
57
|
-
if order.action.queries[arg_i].allow_many?
|
58
|
-
final_arguments.push valid.flatten
|
59
|
-
elsif valid.length == 1
|
60
|
-
final_arguments.push valid[0]
|
61
|
-
else
|
62
|
-
final_arguments = nil
|
63
|
-
break
|
64
|
-
end
|
65
|
-
arg_i += 1
|
66
|
-
}
|
67
|
-
if !final_arguments.nil?
|
68
|
-
# The actor is always the first argument to an Action proc
|
69
|
-
final_arguments.unshift @actor
|
70
|
-
order.action.execute(*final_arguments)
|
71
|
-
executed = true
|
72
|
-
end
|
26
|
+
executed = try(order)
|
73
27
|
end
|
74
28
|
@actor.send(:delegate_stack).pop
|
75
29
|
end
|
@@ -86,6 +40,65 @@ module Gamefic
|
|
86
40
|
proceed
|
87
41
|
end
|
88
42
|
private
|
43
|
+
def try order
|
44
|
+
executed = false
|
45
|
+
arg_i = 0
|
46
|
+
final_arguments = []
|
47
|
+
order.arguments.each { |argument|
|
48
|
+
if argument.length > 1 and !order.action.queries[arg_i].allow_many?
|
49
|
+
if argument[0].kind_of?(Array)
|
50
|
+
# This thing refers to multiple items. Just keep going.
|
51
|
+
final_arguments = nil
|
52
|
+
break
|
53
|
+
else
|
54
|
+
ambiguous = argument
|
55
|
+
end
|
56
|
+
order = Order.new(@actor, @@disambiguator, [])
|
57
|
+
final_arguments = [ambiguous]
|
58
|
+
break
|
59
|
+
end
|
60
|
+
if order.action.queries[arg_i].allow_ambiguous?
|
61
|
+
valid = argument.flatten
|
62
|
+
else
|
63
|
+
valid = validate(argument, arg_i, order)
|
64
|
+
if valid.nil?
|
65
|
+
final_arguments = nil
|
66
|
+
break
|
67
|
+
end
|
68
|
+
end
|
69
|
+
if order.action == @@disambiguator or final_arguments.nil?
|
70
|
+
break
|
71
|
+
end
|
72
|
+
if order.action.queries[arg_i].allow_many?
|
73
|
+
final_arguments.push valid.flatten
|
74
|
+
elsif valid.length == 1
|
75
|
+
final_arguments.push valid[0]
|
76
|
+
else
|
77
|
+
final_arguments = nil
|
78
|
+
break
|
79
|
+
end
|
80
|
+
arg_i += 1
|
81
|
+
}
|
82
|
+
if !final_arguments.nil?
|
83
|
+
# The actor is always the first argument to an Action proc
|
84
|
+
final_arguments.unshift @actor
|
85
|
+
order.action.execute(*final_arguments)
|
86
|
+
executed = true
|
87
|
+
end
|
88
|
+
executed
|
89
|
+
end
|
90
|
+
def validate argument, arg_i, order
|
91
|
+
valid = []
|
92
|
+
argument.each { |m|
|
93
|
+
if order.action.queries[arg_i].validate(@actor, m)
|
94
|
+
valid.push m
|
95
|
+
else
|
96
|
+
valid = nil
|
97
|
+
break
|
98
|
+
end
|
99
|
+
}
|
100
|
+
valid
|
101
|
+
end
|
89
102
|
end
|
90
103
|
end
|
91
104
|
end
|
@@ -102,7 +102,7 @@ module Gamefic
|
|
102
102
|
objects.push Order.new(actor, action, prepared)
|
103
103
|
else
|
104
104
|
if !action.queries.last.allow_many? or action.queries.last.allow_ambiguous?
|
105
|
-
misunderstood = Action.new nil,
|
105
|
+
misunderstood = Action.new nil, Query::Text.new do |actor, text|
|
106
106
|
actor.tell "I understand the first part of your command but not \"#{text}.\""
|
107
107
|
end
|
108
108
|
misunderstood.meta = true
|
data/lib/gamefic/engine/tty.rb
CHANGED
@@ -33,10 +33,7 @@ module Gamefic
|
|
33
33
|
@stream.ansi
|
34
34
|
end
|
35
35
|
def save filename, snapshot
|
36
|
-
data =
|
37
|
-
:metadata => @character.plot.metadata,
|
38
|
-
:entities => snapshot
|
39
|
-
}
|
36
|
+
data = snapshot.merge(:metadata => @character.plot.metadata)
|
40
37
|
json = JSON.generate data
|
41
38
|
if json.nil?
|
42
39
|
@character.tell "Nothing to save."
|
@@ -63,7 +60,7 @@ module Gamefic
|
|
63
60
|
if (data[:metadata] != @character.plot.metadata)
|
64
61
|
@character.tell "The save file is not compatible with this version of the game."
|
65
62
|
else
|
66
|
-
return data
|
63
|
+
return data
|
67
64
|
end
|
68
65
|
else
|
69
66
|
@character.tell "File \"#{filename}\" not found."
|
data/lib/gamefic/plot.rb
CHANGED
@@ -5,6 +5,7 @@ require 'gamefic/tester'
|
|
5
5
|
require 'gamefic/source'
|
6
6
|
require 'gamefic/script'
|
7
7
|
require 'gamefic/query'
|
8
|
+
require 'gamefic/subplot'
|
8
9
|
|
9
10
|
module Gamefic
|
10
11
|
|
@@ -25,8 +26,11 @@ module Gamefic
|
|
25
26
|
# Gamefic Studio has a PlotStageMetaMapper that handles it, but it doesn't run if
|
26
27
|
# the plugin isn't activated.
|
27
28
|
#include Gamefic, Tester, SceneMount, CommandMount, EntityMount, QueryMount, ArticleMount, YouMount, Snapshot
|
28
|
-
mount Gamefic, Tester, SceneMount, CommandMount, EntityMount, QueryMount,
|
29
|
-
|
29
|
+
mount Gamefic, Tester, SceneMount, CommandMount, EntityMount, QueryMount,
|
30
|
+
ArticleMount, YouMount, Snapshot, Subplot::Host
|
31
|
+
expose :script, :introduction, :assert_action, :before_player_update,
|
32
|
+
:on_update, :on_player_update, :entities, :on_ready, :on_player_ready,
|
33
|
+
:players, :scenes, :metadata
|
30
34
|
|
31
35
|
# @param [Source::Base]
|
32
36
|
def initialize(source = nil)
|
@@ -44,6 +48,7 @@ module Gamefic
|
|
44
48
|
@players = []
|
45
49
|
@asserts = {}
|
46
50
|
@default_scene = :active
|
51
|
+
@subplots = []
|
47
52
|
post_initialize
|
48
53
|
end
|
49
54
|
|
@@ -165,6 +170,7 @@ module Gamefic
|
|
165
170
|
# Introduce a player to the game.
|
166
171
|
# This method is typically called by the Engine that manages game execution.
|
167
172
|
def introduce(player)
|
173
|
+
player.extend Subplot::Feature
|
168
174
|
@players.push player
|
169
175
|
if @introduction != nil
|
170
176
|
@introduction.call(player)
|
@@ -341,7 +347,7 @@ module Gamefic
|
|
341
347
|
user_friendly += " #{new_name}"
|
342
348
|
args.push new_name
|
343
349
|
}
|
344
|
-
Syntax.new
|
350
|
+
add_syntax Syntax.new(user_friendly.strip, "#{action.verb} #{args.join(' ')}")
|
345
351
|
end
|
346
352
|
def rem_action(action)
|
347
353
|
@commands[action.verb].delete(action)
|
@@ -24,7 +24,9 @@ module Gamefic
|
|
24
24
|
act
|
25
25
|
end
|
26
26
|
def action(command, *queries, &proc)
|
27
|
-
Action.new(
|
27
|
+
act = Action.new(command, *queries, &proc)
|
28
|
+
add_action act
|
29
|
+
act
|
28
30
|
end
|
29
31
|
# Create an Action that responds to a command.
|
30
32
|
# An Action uses the command argument to identify the imperative verb that
|
@@ -72,7 +74,8 @@ module Gamefic
|
|
72
74
|
xlate(*args)
|
73
75
|
end
|
74
76
|
def xlate(*args)
|
75
|
-
syn = Syntax.new(
|
77
|
+
syn = Syntax.new(*args)
|
78
|
+
add_syntax syn
|
76
79
|
syn
|
77
80
|
end
|
78
81
|
def commandwords
|
@@ -2,6 +2,10 @@ require 'json'
|
|
2
2
|
|
3
3
|
module Gamefic
|
4
4
|
module Plot::Snapshot
|
5
|
+
|
6
|
+
# Take a snapshot of the plot's current state.
|
7
|
+
#
|
8
|
+
# @return [Hash]
|
5
9
|
def save
|
6
10
|
store = []
|
7
11
|
index = 0
|
@@ -44,44 +48,59 @@ module Gamefic
|
|
44
48
|
else
|
45
49
|
store = reduce(store)
|
46
50
|
end
|
47
|
-
|
51
|
+
return {
|
52
|
+
entities: store,
|
53
|
+
subplots: save_subplots
|
54
|
+
}
|
48
55
|
end
|
56
|
+
|
57
|
+
# Restore the plot to the state of the provided snapshot.
|
58
|
+
#
|
59
|
+
# @param [Hash]
|
49
60
|
def restore snapshot
|
50
|
-
|
61
|
+
restore_initial_state
|
62
|
+
internal_restore snapshot[:entities]
|
63
|
+
restore_subplots snapshot[:subplots]
|
51
64
|
end
|
65
|
+
|
52
66
|
private
|
53
|
-
|
54
|
-
|
67
|
+
|
68
|
+
# Restore the plot to the state of its first snapshot.
|
69
|
+
#
|
70
|
+
def restore_initial_state
|
55
71
|
@entities[@initial_state.length..-1].each { |e|
|
56
72
|
e.parent = nil
|
57
73
|
}
|
58
74
|
@entities.slice! @initial_state.length..-1
|
59
|
-
internal_restore @initial_state
|
60
|
-
|
75
|
+
internal_restore @initial_state
|
76
|
+
end
|
77
|
+
|
78
|
+
def internal_restore snapshot
|
61
79
|
index = 0
|
62
80
|
snapshot.each { |hash|
|
63
81
|
if entities[index].nil?
|
64
|
-
|
65
|
-
|
66
|
-
entities[index] = make cls
|
67
|
-
else
|
68
|
-
break
|
69
|
-
end
|
82
|
+
cls = Kernel.const_get(hash[:class])
|
83
|
+
@entities[index] = make cls
|
70
84
|
end
|
71
|
-
hash
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
85
|
+
internal_restore_hash hash, index
|
86
|
+
index += 1
|
87
|
+
}
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
def internal_restore_hash hash, index
|
91
|
+
hash.each { |k, v|
|
92
|
+
if k == :scene
|
93
|
+
entities[index].cue v.to_sym
|
94
|
+
elsif (k != :session and k != :class)
|
95
|
+
entities[index].send("#{k}=", unserialize(v))
|
96
|
+
end
|
78
97
|
unless hash[:session].nil?
|
79
98
|
hash[:session].each_pair { |k, v|
|
80
99
|
entities[index].session[k.to_sym] = unserialize(v)
|
81
100
|
}
|
82
101
|
end
|
83
|
-
index += 1
|
84
102
|
}
|
103
|
+
nil
|
85
104
|
end
|
86
105
|
def reduce entities
|
87
106
|
reduced = []
|
@@ -98,7 +117,6 @@ module Gamefic
|
|
98
117
|
}
|
99
118
|
reduced
|
100
119
|
end
|
101
|
-
private
|
102
120
|
def can_serialize? obj
|
103
121
|
return true if (obj == true or obj == false or obj.nil?)
|
104
122
|
allowed = [String, Fixnum, Float, Numeric, Entity, Direction, Hash, Array, Symbol]
|
@@ -111,23 +129,9 @@ module Gamefic
|
|
111
129
|
return nil if obj.nil?
|
112
130
|
return false if obj == false
|
113
131
|
if obj.kind_of?(Hash)
|
114
|
-
|
115
|
-
obj.each_pair { |k, v|
|
116
|
-
if can_serialize?(k) and can_serialize?(v)
|
117
|
-
hash[serialize_obj(k)] = serialize_obj(v)
|
118
|
-
end
|
119
|
-
}
|
120
|
-
return hash
|
132
|
+
return serialize_hash obj
|
121
133
|
elsif obj.kind_of?(Array)
|
122
|
-
|
123
|
-
obj.each_index { |i|
|
124
|
-
if can_serialize?(obj[i])
|
125
|
-
arr[i] = serialize_obj(obj[i])
|
126
|
-
else
|
127
|
-
raise "Bad array in snapshot"
|
128
|
-
end
|
129
|
-
}
|
130
|
-
return arr
|
134
|
+
return serialize_array obj
|
131
135
|
else
|
132
136
|
if obj.kind_of?(Entity)
|
133
137
|
return "#<EIN_#{@entities.index(obj)}>"
|
@@ -137,29 +141,91 @@ module Gamefic
|
|
137
141
|
end
|
138
142
|
return obj
|
139
143
|
end
|
144
|
+
def serialize_hash obj
|
145
|
+
hash = {}
|
146
|
+
obj.each_pair { |k, v|
|
147
|
+
if can_serialize?(k) and can_serialize?(v)
|
148
|
+
hash[serialize_obj(k)] = serialize_obj(v)
|
149
|
+
end
|
150
|
+
}
|
151
|
+
return hash
|
152
|
+
end
|
153
|
+
def serialize_array obj
|
154
|
+
arr = []
|
155
|
+
obj.each_index { |i|
|
156
|
+
if can_serialize?(obj[i])
|
157
|
+
arr[i] = serialize_obj(obj[i])
|
158
|
+
else
|
159
|
+
raise "Bad array in snapshot"
|
160
|
+
end
|
161
|
+
}
|
162
|
+
return arr
|
163
|
+
end
|
140
164
|
def unserialize obj
|
141
165
|
if obj.kind_of?(Hash)
|
142
|
-
|
143
|
-
obj.each_pair { |k, v|
|
144
|
-
hash[unserialize(k)] = unserialize(v)
|
145
|
-
}
|
146
|
-
hash
|
166
|
+
unserialize_hash obj
|
147
167
|
elsif obj.kind_of?(Array)
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
168
|
+
unserialize_array obj
|
169
|
+
elsif obj.to_s.match(/^#<EIN_[0-9]+>$/)
|
170
|
+
i = obj[6..-2].to_i
|
171
|
+
@entities[i]
|
172
|
+
elsif obj.to_s.match(/^#<DIR_[a-z]+>$/)
|
173
|
+
Direction.find(obj[6..-2])
|
153
174
|
else
|
154
|
-
|
155
|
-
i = obj[6..-2].to_i
|
156
|
-
@entities[i]
|
157
|
-
elsif obj.to_s.match(/^#<DIR_[a-z]+>$/)
|
158
|
-
Direction.find(obj[6..-2])
|
159
|
-
else
|
160
|
-
obj
|
161
|
-
end
|
175
|
+
obj
|
162
176
|
end
|
163
177
|
end
|
178
|
+
def unserialize_hash obj
|
179
|
+
hash = {}
|
180
|
+
obj.each_pair { |k, v|
|
181
|
+
hash[unserialize(k)] = unserialize(v)
|
182
|
+
}
|
183
|
+
hash
|
184
|
+
end
|
185
|
+
def unserialize_array obj
|
186
|
+
arr = []
|
187
|
+
obj.each_index { |i|
|
188
|
+
arr[i] = unserialize(obj[i])
|
189
|
+
}
|
190
|
+
arr
|
191
|
+
end
|
192
|
+
def save_subplots
|
193
|
+
arr = []
|
194
|
+
subplots.each { |s|
|
195
|
+
hash = {}
|
196
|
+
hash[:class] = s.class.to_s
|
197
|
+
s.instance_variables.each { |k|
|
198
|
+
v = s.instance_variable_get(k)
|
199
|
+
if can_serialize?(v)
|
200
|
+
hash[k] = serialize_obj(v)
|
201
|
+
end
|
202
|
+
}
|
203
|
+
arr.push hash
|
204
|
+
}
|
205
|
+
arr
|
206
|
+
end
|
207
|
+
def restore_subplots arr
|
208
|
+
players.each { |p|
|
209
|
+
p.send(:p_subplots).clear
|
210
|
+
}
|
211
|
+
p_subplots.clear
|
212
|
+
arr.each { |hash|
|
213
|
+
cls = Kernel.const_get(hash[:class])
|
214
|
+
subplot = cls.new self
|
215
|
+
hash.each { |k, v|
|
216
|
+
if k != :class
|
217
|
+
subplot.instance_variable_set(k, unserialize(v))
|
218
|
+
end
|
219
|
+
}
|
220
|
+
subplot.players.each { |p|
|
221
|
+
p.send(:p_subplots).push subplot
|
222
|
+
}
|
223
|
+
subplot.entities.each { |e|
|
224
|
+
e.extend Subplot::Element
|
225
|
+
e.instance_variable_set(:@subplot, subplot)
|
226
|
+
}
|
227
|
+
p_subplots.push subplot
|
228
|
+
}
|
229
|
+
end
|
164
230
|
end
|
165
231
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Gamefic
|
2
|
+
|
3
|
+
class Subplot
|
4
|
+
module Element
|
5
|
+
attr_reader :subplot
|
6
|
+
end
|
7
|
+
module Feature
|
8
|
+
def subplots
|
9
|
+
p_subplots.clone
|
10
|
+
end
|
11
|
+
private
|
12
|
+
def p_subplots
|
13
|
+
@p_subplots ||= []
|
14
|
+
end
|
15
|
+
end
|
16
|
+
module Host
|
17
|
+
# Get an array of all the current subplots.
|
18
|
+
#
|
19
|
+
# @return [Array<Subplot>]
|
20
|
+
def subplots
|
21
|
+
p_subplots.clone
|
22
|
+
end
|
23
|
+
|
24
|
+
# Start a new subplot based on the provided class.
|
25
|
+
#
|
26
|
+
# @param [Class] The class of the subplot to be created (Subplot by default)
|
27
|
+
# @return [Subplot]
|
28
|
+
def branch subplot_class = Subplot, &block
|
29
|
+
subplot = subplot_class.new(self, &block)
|
30
|
+
p_subplots.push subplot
|
31
|
+
subplot
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def p_subplots
|
36
|
+
@p_subplots ||= []
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :plot, :entities, :players
|
41
|
+
|
42
|
+
def initialize plot
|
43
|
+
@plot = plot
|
44
|
+
@entities = []
|
45
|
+
@players = []
|
46
|
+
@concluded = false
|
47
|
+
post_initialize
|
48
|
+
yield(self) if block_given?
|
49
|
+
end
|
50
|
+
def post_initialize
|
51
|
+
end
|
52
|
+
def make *args
|
53
|
+
e = plot.make(*args)
|
54
|
+
e.extend Gamefic::Subplot::Element
|
55
|
+
e.instance_variable_set(:@subplot, self)
|
56
|
+
entities.push e
|
57
|
+
e
|
58
|
+
end
|
59
|
+
def introduce player
|
60
|
+
player.send(:p_subplots).push self
|
61
|
+
players.push player
|
62
|
+
end
|
63
|
+
def exeunt player
|
64
|
+
player.send(:p_subplots).delete self
|
65
|
+
players.delete player
|
66
|
+
end
|
67
|
+
def conclude
|
68
|
+
concluded = true
|
69
|
+
entities.each { |e|
|
70
|
+
e.destroy
|
71
|
+
}
|
72
|
+
players.each { |p|
|
73
|
+
exeunt p
|
74
|
+
}
|
75
|
+
end
|
76
|
+
def concluded?
|
77
|
+
@concluded
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
data/lib/gamefic/syntax.rb
CHANGED
@@ -6,7 +6,7 @@ module Gamefic
|
|
6
6
|
attr_reader :token_count, :first_word, :verb, :template, :command
|
7
7
|
@@phrase = '([\w\W\s\S]*?)'
|
8
8
|
|
9
|
-
def initialize
|
9
|
+
def initialize template, *command
|
10
10
|
command = command.join(' ')
|
11
11
|
words = template.split_words
|
12
12
|
@token_count = words.length
|
@@ -50,9 +50,6 @@ module Gamefic
|
|
50
50
|
}
|
51
51
|
@replace = subs.join(' ')
|
52
52
|
@regexp = Regexp.new("^#{tokens.join(' ')}$", Regexp::IGNORECASE)
|
53
|
-
if !plot.nil?
|
54
|
-
plot.send :add_syntax, self
|
55
|
-
end
|
56
53
|
end
|
57
54
|
|
58
55
|
# Convert a String into a Command.
|
data/lib/gamefic/version.rb
CHANGED
metadata
CHANGED
@@ -1,41 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gamefic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.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: 2016-
|
11
|
+
date: 2016-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: slop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: rubyzip
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
|
-
- -
|
31
|
+
- - '>='
|
18
32
|
- !ruby/object:Gem::Version
|
19
33
|
version: '0'
|
20
34
|
type: :runtime
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
|
-
- -
|
38
|
+
- - '>='
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rspec
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- -
|
45
|
+
- - '>='
|
32
46
|
- !ruby/object:Gem::Version
|
33
47
|
version: '0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- -
|
52
|
+
- - '>='
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
description: An adventure game and interactive fiction framework
|
@@ -124,6 +138,7 @@ files:
|
|
124
138
|
- lib/gamefic/source/file.rb
|
125
139
|
- lib/gamefic/source/text.rb
|
126
140
|
- lib/gamefic/stage.rb
|
141
|
+
- lib/gamefic/subplot.rb
|
127
142
|
- lib/gamefic/syntax.rb
|
128
143
|
- lib/gamefic/tester.rb
|
129
144
|
- lib/gamefic/version.rb
|
@@ -137,18 +152,19 @@ require_paths:
|
|
137
152
|
- lib
|
138
153
|
required_ruby_version: !ruby/object:Gem::Requirement
|
139
154
|
requirements:
|
140
|
-
- -
|
155
|
+
- - '>='
|
141
156
|
- !ruby/object:Gem::Version
|
142
|
-
version:
|
157
|
+
version: 2.0.0
|
143
158
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
159
|
requirements:
|
145
|
-
- -
|
160
|
+
- - '>='
|
146
161
|
- !ruby/object:Gem::Version
|
147
162
|
version: '0'
|
148
163
|
requirements: []
|
149
164
|
rubyforge_project:
|
150
|
-
rubygems_version: 2.
|
165
|
+
rubygems_version: 2.6.8
|
151
166
|
signing_key:
|
152
167
|
specification_version: 4
|
153
168
|
summary: Gamefic
|
154
169
|
test_files: []
|
170
|
+
has_rdoc:
|