gamefic 0.2.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gamefic/action.rb +87 -56
  3. data/lib/gamefic/ansi.rb +55 -0
  4. data/lib/gamefic/character.rb +130 -76
  5. data/lib/gamefic/command.rb +19 -0
  6. data/lib/gamefic/core_ext/array.rb +51 -40
  7. data/lib/gamefic/core_ext/string.rb +4 -0
  8. data/lib/gamefic/describable.rb +108 -46
  9. data/lib/gamefic/direction.rb +46 -0
  10. data/lib/gamefic/director/delegate.rb +91 -0
  11. data/lib/gamefic/director/order.rb +10 -0
  12. data/lib/gamefic/director/parser.rb +119 -0
  13. data/lib/gamefic/director.rb +16 -197
  14. data/lib/gamefic/engine/cgi.rb +221 -0
  15. data/lib/gamefic/engine/tty.rb +237 -0
  16. data/lib/gamefic/engine.rb +88 -67
  17. data/lib/gamefic/entity.rb +96 -69
  18. data/lib/gamefic/grammar/conjugator.rb +20 -0
  19. data/lib/gamefic/grammar/gender.rb +11 -0
  20. data/lib/gamefic/grammar/person.rb +10 -0
  21. data/lib/gamefic/grammar/plural.rb +13 -0
  22. data/lib/gamefic/grammar/pronouns.rb +60 -0
  23. data/lib/gamefic/grammar/tense.rb +6 -0
  24. data/lib/gamefic/grammar/verb_set.rb +43 -0
  25. data/lib/gamefic/grammar/verbs.rb +25 -0
  26. data/lib/gamefic/grammar/word_adapter.rb +36 -0
  27. data/lib/gamefic/grammar.rb +13 -0
  28. data/lib/gamefic/html.rb +53 -0
  29. data/lib/gamefic/keywords.rb +51 -33
  30. data/lib/gamefic/node.rb +65 -58
  31. data/lib/gamefic/plot/article_mount.rb +22 -0
  32. data/lib/gamefic/plot/command_mount.rb +88 -0
  33. data/lib/gamefic/plot/entity_mount.rb +45 -0
  34. data/lib/gamefic/plot/query_mount.rb +9 -0
  35. data/lib/gamefic/plot/scene_mount.rb +181 -0
  36. data/lib/gamefic/plot/you_mount.rb +22 -0
  37. data/lib/gamefic/plot.rb +296 -247
  38. data/lib/gamefic/query/ambiguous_children.rb +5 -0
  39. data/lib/gamefic/query/base.rb +265 -0
  40. data/lib/gamefic/query/children.rb +10 -0
  41. data/lib/gamefic/query/expression.rb +47 -0
  42. data/lib/gamefic/query/family.rb +10 -0
  43. data/lib/gamefic/query/many_children.rb +7 -0
  44. data/lib/gamefic/query/matches.rb +11 -0
  45. data/lib/gamefic/query/parent.rb +10 -0
  46. data/lib/gamefic/query/plural_children.rb +14 -0
  47. data/lib/gamefic/query/self.rb +10 -0
  48. data/lib/gamefic/query/siblings.rb +10 -0
  49. data/lib/gamefic/query/text.rb +43 -0
  50. data/lib/gamefic/query.rb +19 -203
  51. data/lib/gamefic/rule.rb +18 -0
  52. data/lib/gamefic/scene/active.rb +25 -0
  53. data/lib/gamefic/scene/concluded.rb +22 -0
  54. data/lib/gamefic/scene/multiplechoice.rb +74 -0
  55. data/lib/gamefic/scene/paused.rb +26 -0
  56. data/lib/gamefic/scene/yesorno.rb +43 -0
  57. data/lib/gamefic/scene.rb +125 -0
  58. data/lib/gamefic/script/base.rb +33 -0
  59. data/lib/gamefic/script/file.rb +14 -0
  60. data/lib/gamefic/script/text.rb +14 -0
  61. data/lib/gamefic/script.rb +9 -0
  62. data/lib/gamefic/serialized.rb +24 -0
  63. data/lib/gamefic/shell.rb +9 -247
  64. data/lib/gamefic/snapshots.rb +134 -0
  65. data/lib/gamefic/source/base.rb +12 -0
  66. data/lib/gamefic/source/file.rb +23 -0
  67. data/lib/gamefic/source/text.rb +16 -0
  68. data/lib/gamefic/source.rb +9 -0
  69. data/lib/gamefic/stage.rb +75 -0
  70. data/lib/gamefic/syntax.rb +106 -124
  71. data/lib/gamefic/tester.rb +20 -0
  72. data/lib/gamefic/version.rb +3 -0
  73. data/lib/gamefic.rb +18 -12
  74. metadata +102 -70
  75. data/lib/gamefic/base.rb +0 -10
  76. data/lib/gamefic/before.rb +0 -12
  77. data/lib/gamefic/import/basics/actions/close.rb +0 -16
  78. data/lib/gamefic/import/basics/actions/commands.rb +0 -3
  79. data/lib/gamefic/import/basics/actions/drop-in.rb +0 -17
  80. data/lib/gamefic/import/basics/actions/drop-on.rb +0 -16
  81. data/lib/gamefic/import/basics/actions/drop.rb +0 -30
  82. data/lib/gamefic/import/basics/actions/enter.rb +0 -16
  83. data/lib/gamefic/import/basics/actions/go.rb +0 -35
  84. data/lib/gamefic/import/basics/actions/inventory.rb +0 -8
  85. data/lib/gamefic/import/basics/actions/leave.rb +0 -29
  86. data/lib/gamefic/import/basics/actions/look-in-at.rb +0 -27
  87. data/lib/gamefic/import/basics/actions/look-under.rb +0 -3
  88. data/lib/gamefic/import/basics/actions/look.rb +0 -71
  89. data/lib/gamefic/import/basics/actions/nil.rb +0 -25
  90. data/lib/gamefic/import/basics/actions/open.rb +0 -23
  91. data/lib/gamefic/import/basics/actions/quit.rb +0 -3
  92. data/lib/gamefic/import/basics/actions/take.rb +0 -107
  93. data/lib/gamefic/import/basics/entities/container.rb +0 -8
  94. data/lib/gamefic/import/basics/entities/entity.rb +0 -11
  95. data/lib/gamefic/import/basics/entities/fixture.rb +0 -5
  96. data/lib/gamefic/import/basics/entities/item.rb +0 -5
  97. data/lib/gamefic/import/basics/entities/portal.rb +0 -40
  98. data/lib/gamefic/import/basics/entities/room.rb +0 -30
  99. data/lib/gamefic/import/basics/entities/scenery.rb +0 -5
  100. data/lib/gamefic/import/basics/entities/supporter.rb +0 -6
  101. data/lib/gamefic/import/basics/entities/thing.rb +0 -16
  102. data/lib/gamefic/import/basics/queries/reachable.rb +0 -38
  103. data/lib/gamefic/import/basics/queries/room.rb +0 -8
  104. data/lib/gamefic/import/basics/queries/visible.rb +0 -32
  105. data/lib/gamefic/import/basics/rules/has-enough-light.rb +0 -14
  106. data/lib/gamefic/import/basics.old/actions/container.rb +0 -112
  107. data/lib/gamefic/import/basics.old/actions/inventory.rb +0 -50
  108. data/lib/gamefic/import/basics.old/actions/look.rb +0 -53
  109. data/lib/gamefic/import/basics.old/actions/meta.rb +0 -6
  110. data/lib/gamefic/import/basics.old/actions/traversal.rb +0 -35
  111. data/lib/gamefic/import/basics.old/actions.rb +0 -1
  112. data/lib/gamefic/import/basics.old/entities/container.rb +0 -3
  113. data/lib/gamefic/import/basics.old/entities/fixture.rb +0 -3
  114. data/lib/gamefic/import/basics.old/entities/item.rb +0 -3
  115. data/lib/gamefic/import/basics.old/entities/portal.rb +0 -43
  116. data/lib/gamefic/import/basics.old/entities/room.rb +0 -27
  117. data/lib/gamefic/import/basics.old/entities/scenery.rb +0 -3
  118. data/lib/gamefic/import/basics.old/entities/supporter.rb +0 -3
  119. data/lib/gamefic/import/basics.old/entities.rb +0 -1
  120. data/lib/gamefic/import/basics.old/room_modes.rb +0 -48
  121. data/lib/gamefic/import/basics.rb +0 -6
  122. data/lib/gamefic/import/room_modes.rb +0 -48
  123. data/lib/gamefic/import/standard.rb +0 -1
  124. data/lib/gamefic/meta.rb +0 -12
  125. data/lib/gamefic/optionset.rb +0 -114
  126. data/lib/gamefic/requirement.rb +0 -14
  127. data/lib/gamefic/story.rb +0 -14
  128. data/lib/gamefic/thing.rb +0 -7
data/lib/gamefic/plot.rb CHANGED
@@ -1,238 +1,297 @@
1
+ # TODO: JSON support is currently experimental.
2
+ #require 'gamefic/entityloader'
3
+ require 'gamefic/stage'
4
+ require 'gamefic/tester'
5
+ require 'gamefic/source'
6
+ require 'gamefic/script'
7
+ require 'gamefic/query'
8
+ require 'gamefic/plot/article_mount'
9
+ require 'gamefic/plot/you_mount'
10
+
1
11
  module Gamefic
2
12
 
3
- def self.bind(plot)
4
- mod = Module.new do
5
- def self.bind(plot)
6
- @@plot = plot
7
- end
8
- def self.get_binding
9
- binding
10
- end
11
- def self.method_missing(name, *args, &block)
12
- if @@plot.respond_to?(name)
13
- @@plot.send name, *args, &block
14
- elsif Gamefic.respond_to?(name)
15
- Gamefic.send name, *args, &block
16
- end
17
- end
13
+ class Plot
14
+ autoload :SceneMount, 'gamefic/plot/scene_mount'
15
+ autoload :CommandMount, 'gamefic/plot/command_mount'
16
+ autoload :EntityMount, 'gamefic/plot/entity_mount'
17
+ autoload :QueryMount, 'gamefic/plot/query_mount'
18
+ #autoload :ArticleMount, 'gamefic/plot/article_mount'
19
+ #autoload :YouMount, 'gamefic/plot/you_mount'
20
+ attr_reader :commands, :imported_scripts, :rules, :asserts, :source
21
+ attr_accessor :default_scene
22
+ include Stage
23
+ # TODO This include is only here to make the module's methods visible in the IDE.
24
+ # Gamefic Studio has a PlotStageMetaMapper that handles it, but it doesn't run if
25
+ # 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
29
+
30
+ # @param [Source::Base]
31
+ def initialize(source = nil)
32
+ @source = source || Source::Text.new({})
33
+ @commands = Hash.new
34
+ @syntaxes = Array.new
35
+ @ready_procs = Array.new
36
+ @update_procs = Array.new
37
+ @player_ready = Array.new
38
+ @player_procs = Array.new
39
+ @working_scripts = Array.new
40
+ @imported_scripts = Array.new
41
+ @entities = Array.new
42
+ @players = Array.new
43
+ @asserts = Hash.new
44
+ @default_scene = :active
45
+ post_initialize
18
46
  end
19
- mod.bind plot
20
- mod.get_binding
21
- end
22
-
23
- def self.safe_level
24
- @@safe_level ||= (RUBY_VERSION.split('.')[0].to_i < 2 ? 2 : 3)
25
- end
26
-
27
- class Plot
28
- attr_reader :scenes, :commands, :conclusions, :imported_scripts, :rules
29
- attr_accessor :story
30
- include OptionMap
31
- def commandwords
32
- words = Array.new
33
- @syntaxes.each { |s|
34
- word = s.template[0]
35
- words.push(word) if !word.kind_of?(Symbol)
36
- }
37
- words.uniq
38
- end
39
- def initialize
40
- @scenes = Hash.new
41
- @commands = Hash.new
42
- @syntaxes = Array.new
43
- @conclusions = Hash.new
44
- @update_procs = Array.new
45
- @available_scripts = Hash.new
46
- @imported_scripts = Array.new
47
- @entities = Array.new
48
- @rules = Hash.new
49
- post_initialize
50
- end
51
- def assert name, &block
52
- @rules[name] = Requirement.new self, name, &block
47
+
48
+ # Get an Array of all Actions defined in the Plot.
49
+ #
50
+ # @return Array[Action]
51
+ def actions
52
+ @commands.values.flatten
53
53
  end
54
- def post_initialize
54
+
55
+ # Get an Array of all Actions associated with the specified verb.
56
+ #
57
+ # @param verb [Symbol] The Symbol for the verb (e.g., :go or :look)
58
+ # @return Array<Action> The verb's associated Actions
59
+ def actions_with_verb(verb)
60
+ @commands[verb].clone || []
61
+ end
62
+
63
+ # Get an Array of all scripts that have been imported into the Plot.
64
+ #
65
+ # @return [Array<Script>] The imported scripts
66
+ def imported_scripts
67
+ @imported_scripts ||= []
68
+ end
69
+
70
+ # Add a Block to be executed for the given verb.
71
+ # If the block returns false, the Action is cancelled.
72
+ #
73
+ # @example Require the player to have a property enabled before performing the Action.
74
+ # assert_action :authorize do |actor, verb, arguments|
75
+ # if actor[:can_authorize] == true
76
+ # true
77
+ # else
78
+ # actor.tell "You don't have permission to use the authorize command."
79
+ # false
80
+ # end
81
+ # end
82
+ #
83
+ # @yieldparam [Character] The character performing the Action.
84
+ # @yieldparam [Symbol] The verb associated with the Action.
85
+ # @yieldparam [Array] The arguments that will be passed to the Action's #execute method.
86
+ def assert_action name, &block
87
+ @asserts[name] = Assert.new(name, &block)
88
+ end
89
+
90
+ def post_initialize
55
91
  # TODO: Should this method be required by extended classes?
56
- end
57
- def meta(command, *queries, &proc)
58
- act = Meta.new(self, command, *queries, &proc)
59
- end
60
- def action(command, *queries, &proc)
61
- act = Action.new(self, command, *queries, &proc)
62
- end
63
- def respond(command, *queries, &proc)
64
- self.action(command, *queries, &proc)
65
- end
66
- def before(command, *queries, &proc)
67
- bef = Before.new(self, command, *queries, &proc)
68
- end
69
- def make(cls, args = {})
70
- ent = cls.new(self, args)
71
- if ent.kind_of?(Entity) == false
72
- raise "Invalid entity class"
73
- end
74
- ent
75
- end
76
- def syntax(*args)
77
- xlate *args
78
- end
79
- def xlate(*args)
80
- syn = Syntax.new(self, *args)
81
- @syntaxes.push syn
82
- syn
83
- end
84
- def entities
85
- @entities.clone
86
- end
87
- def syntaxes
88
- @syntaxes.clone
89
- end
90
- def on_update(&block)
91
- @update_procs.push block
92
- end
93
- def introduction (&proc)
94
- @introduction = proc
95
- end
96
- def conclusion(key, &proc)
97
- @conclusions[key] = proc
98
- end
99
- def scene(key, &proc)
100
- @scenes[key] = proc
101
- end
102
- def introduce(player)
103
- if @introduction != nil
104
- @introduction.call(player)
105
- end
106
- end
107
- def conclude(player, key = nil)
108
- if key != nil and @conclusions[key]
109
- @conclusions[key].call(player)
110
- player.state = GameOverState.new(player)
111
- end
112
- end
113
- def cue scene
114
- @scenes[scene].call
115
- end
116
- def passthru
117
- Director::Delegate.passthru
118
- end
119
- def pass requirement
120
- Director::Delegate.pass requirement
121
92
  end
122
- def deny requirement
123
- Director::Delegate.deny requirement
93
+
94
+ # Get an Array of the Plot's current Entities.
95
+ #
96
+ # @return [Array<Entity>]
97
+ def entities
98
+ @entities.clone
124
99
  end
125
- def update
126
- @update_procs.each { |p|
127
- p.call
128
- }
129
- @entities.each { |e|
130
- e.update
131
- }
132
- end
133
-
134
- def tell entities, message, refresh = false
135
- entities.each { |entity|
136
- entity.tell message, refresh
137
- }
138
- end
139
-
140
- def load script, with_libs = true
141
- code = File.read(script)
142
- code.untaint
143
- @source_directory = File.dirname(script)
144
- if with_libs == true
145
- $LOAD_PATH.reverse.each { |path|
146
- get_scripts path + '/gamefic/import'
147
- }
100
+
101
+ # Get an Array of the Plot's current Syntaxes.
102
+ #
103
+ # @return [Array<Syntax>]
104
+ def syntaxes
105
+ @syntaxes.clone
106
+ end
107
+
108
+ # Get an Array of current players.
109
+ #
110
+ # @return [Array<Character>] The players.
111
+ def players
112
+ @players.clone
113
+ end
114
+
115
+ # Add a block to be executed on preparation of every turn.
116
+ # Each on_ready block is executed once per turn, as opposed to
117
+ # on_player_ready blocks, which are executed once for each player.
118
+ #
119
+ # @example Increment a turn counter
120
+ # turn = 0
121
+ # on_ready do
122
+ # turn += 1
123
+ # end
124
+ #
125
+ def on_ready(&block)
126
+ @ready_procs.push block
127
+ end
128
+
129
+ # Add a block to be executed after the Plot is finished updating a turn.
130
+ # Each on_update block is executed once per turn, as opposed to
131
+ # on_player_update blocks, which are executed once for each player.
132
+ def on_update(&block)
133
+ @update_procs.push block
134
+ end
135
+
136
+ # Add a block to be executed when a player is added to the game.
137
+ # Each Plot can only have one introduction. Subsequent calls will
138
+ # overwrite the existing one.
139
+ #
140
+ # @example Welcome the player to the game
141
+ # introduction do |actor|
142
+ # actor.tell "Welcome to the game!"
143
+ # end
144
+ #
145
+ # @yieldparam [Character]
146
+ def introduction (&proc)
147
+ @introduction = proc
148
+ end
149
+
150
+ # Introduce a player to the game.
151
+ # This method is typically called by the Engine that manages game execution.
152
+ def introduce(player)
153
+ @players.push player
154
+ if @introduction != nil
155
+ @introduction.call(player)
156
+ end
157
+ # TODO: There should probably be a default state specified
158
+ # by the plot, which would be :active by default. We could
159
+ # get it like player.cue nil.
160
+ if player.scene.nil?
161
+ cue player, default_scene
162
+ ready
163
+ update
148
164
  end
149
- get_scripts @source_directory + '/import'
150
- proc {
151
- $SAFE = Gamefic.safe_level
152
- eval code, ::Gamefic.bind(self), script, 1
153
- }.call
154
165
  end
155
166
 
156
- def import script
157
- if script[-2, 2] == '/*'
158
- directory = script[0..-3]
159
- resolved = directory
160
- @available_scripts.each { |f, c|
161
- if f.start_with?(resolved)
162
- self.import f
163
- end
167
+ # Prepare the Plot for the next turn of gameplay.
168
+ # This method is typically called by the Engine that manages game execution.
169
+ def ready
170
+ @ready_procs.each { |p|
171
+ p.call
172
+ }
173
+ # Prepare player scenes for the update.
174
+ @players.each { |player|
175
+ @player_ready.each { |block|
176
+ block.call player
164
177
  }
178
+ player.scene.start player
179
+ }
180
+ end
181
+
182
+ # Update the Plot's current turn of gameplay.
183
+ # This method is typically called by the Engine that manages game execution.
184
+ def update
185
+ # Update the plot.
186
+ @players.each { |player|
187
+ process_input player
188
+ }
189
+ @entities.each { |e|
190
+ e.update
191
+ }
192
+ @players.each { |player|
193
+ update_player player
194
+ cue player, player.scene.data.next_cue if !player.scene.data.next_cue.nil?
195
+ }
196
+ @update_procs.each { |p|
197
+ p.call
198
+ }
199
+ end
200
+
201
+ def tell entities, message, refresh = false
202
+ entities.each { |entity|
203
+ entity.tell message, refresh
204
+ }
205
+ end
206
+
207
+ # Load a script into the current Plot.
208
+ # This method is similar to Kernel#require, except that the script is
209
+ # evaluated within the Plot's context via #stage.
210
+ #
211
+ # @param path [String] The path to the script being evaluated
212
+ # @return [Boolean] true if the script was loaded by this call or false if it was already loaded.
213
+ def script path
214
+ imported_script = source.export(path)
215
+ if imported_script.nil?
216
+ raise "Script not found: #{path}"
217
+ end
218
+ if !@working_scripts.include?(imported_script) and !imported_scripts.include?(imported_script)
219
+ @working_scripts.push imported_script
220
+ stage imported_script.read, imported_script.absolute_path
221
+ @working_scripts.pop
222
+ imported_scripts.push imported_script
223
+ true
165
224
  else
166
- resolved = script
167
- if !@available_scripts.has_key?(resolved)
168
- if @available_scripts.has_key?(resolved + '.rb')
169
- resolved = resolved + '.rb'
170
- end
171
- end
172
- if @available_scripts.has_key?(resolved)
173
- if @available_scripts[resolved] != nil
174
- script_object = @available_scripts[resolved]
175
- @available_scripts[resolved] = nil
176
- proc {
177
- $SAFE = Gamefic.safe_level
178
- @imported_scripts.push script_object
179
- eval script_object.code, Gamefic.bind(self), script_object.filename, 1
180
- }.call
181
- end
182
- else
183
- raise "Unavailable import: #{resolved}"
184
- end
225
+ false
185
226
  end
186
227
  end
187
228
 
188
- private
189
- def get_scripts(directory)
190
- Dir[directory + '/*'].each { |f|
191
- if File.directory?(f)
192
- get_scripts f
193
- else
194
- relative = f[(f.index('/import/')+8)..-1]
195
- @available_scripts[relative] = Script.new(f)
196
- end
229
+ # Add a block to be executed for each player when the Plot prepares them
230
+ # for the next turn in the game.
231
+ #
232
+ # @yieldparam [Character]
233
+ def on_player_ready &block
234
+ @player_ready.push block
235
+ end
236
+
237
+ # Add a block to be executed for each player after they have completed a
238
+ # turn in the game.
239
+ #
240
+ # @yieldparam [Character]
241
+ def on_player_update &block
242
+ @player_procs.push block
243
+ end
244
+
245
+ private
246
+ def process_input player
247
+ line = player.queue.shift
248
+ if !line.nil?
249
+ player.scene.finish player, line
250
+ #cue player, player.scene.data.next_cue if !player.scene.data.next_cue.nil?
251
+ end
252
+ end
253
+ def update_player player
254
+ @player_procs.each { |proc|
255
+ proc.call player
197
256
  }
257
+ # HACK Exception for running tests
258
+ if player[:testing] == true
259
+ cue player, :test
260
+ end
198
261
  end
199
- def rem_entity(entity)
200
- @entities.delete(entity)
201
- end
202
- def recursive_update(entity)
203
- entity.update
204
- entity.children.each { |e|
205
- recursive_update e
206
- }
207
- end
208
- def add_syntax syntax
209
- if @commands[syntax.command] == nil
210
- raise "Action \"#{syntax.command}\" does not exist"
211
- end
212
- @syntaxes.unshift syntax
213
- @syntaxes.sort! { |a, b|
214
- al = a.template.length
215
- if (a.command.nil?)
216
- al -= 1
217
- end
218
- bl = b.template.length
219
- if (b.command.nil?)
220
- bl -= 1
262
+ def rem_entity(entity)
263
+ @entities.delete(entity)
264
+ end
265
+ def recursive_update(entity)
266
+ entity.update
267
+ entity.children.each { |e|
268
+ recursive_update e
269
+ }
270
+ end
271
+ def add_syntax syntax
272
+ if @commands[syntax.verb] == nil
273
+ raise "Action \"#{syntax.verb}\" does not exist."
274
+ end
275
+ # Delete duplicate syntaxes
276
+ @syntaxes = @syntaxes.delete_if { |existing|
277
+ existing == syntax
278
+ }
279
+ @syntaxes.unshift syntax
280
+ @syntaxes.sort! { |a, b|
281
+ if a.token_count == b.token_count
282
+ # For syntaxes of the same length, length of action takes precedence
283
+ b.first_word <=> a.first_word
284
+ else
285
+ b.token_count <=> a.token_count
221
286
  end
222
- if al == bl
223
- # For syntaxes of the same length, creation order takes precedence
224
- 0
225
- else
226
- bl <=> al
227
- end
228
- }
229
- end
230
- def add_action(action)
231
- if (@commands[action.command] == nil)
232
- @commands[action.command] = Array.new
233
- end
234
- @commands[action.command].unshift action
235
- @commands[action.command].sort! { |a, b|
287
+ }
288
+ end
289
+ def add_action(action)
290
+ if (@commands[action.verb] == nil)
291
+ @commands[action.verb] = Array.new
292
+ end
293
+ @commands[action.verb].unshift action
294
+ @commands[action.verb].sort! { |a, b|
236
295
  if a.specificity == b.specificity
237
296
  # Newer action takes precedence
238
297
  b.order_key <=> a.order_key
@@ -240,41 +299,31 @@ module Gamefic
240
299
  # Higher specificity takes precedence
241
300
  b.specificity <=> a.specificity
242
301
  end
243
- }
244
- #if action.command != nil
245
- user_friendly = action.command.to_s.sub(/_/, ' ')
246
- args = Array.new
247
- used_names = Array.new
248
- action.queries.each { |c|
249
- num = 1
250
- new_name = "var"
251
- while used_names.include? new_name
252
- num = num + 1
253
- new_name = "var#{num}"
254
- end
255
- used_names.push new_name
256
- user_friendly += " :#{new_name}"
257
- args.push new_name.to_sym
258
- }
259
- Syntax.new self, *[user_friendly.strip, action.command] + args
260
- #end
261
- end
302
+ }
303
+ user_friendly = action.verb.to_s.gsub(/_/, ' ')
304
+ args = Array.new
305
+ used_names = Array.new
306
+ action.queries.each { |c|
307
+ num = 1
308
+ new_name = ":var"
309
+ while used_names.include? new_name
310
+ num = num + 1
311
+ new_name = ":var#{num}"
312
+ end
313
+ used_names.push new_name
314
+ user_friendly += " #{new_name}"
315
+ args.push new_name
316
+ }
317
+ Syntax.new self, user_friendly.strip, "#{action.verb} #{args.join(' ')}"
318
+ end
262
319
  def rem_action(action)
263
- @commands[action.command].delete(action)
320
+ @commands[action.verb].delete(action)
264
321
  end
265
322
  def rem_syntax(syntax)
266
323
  @syntaxes.delete syntax
267
324
  end
268
- def add_entity(entity)
269
- @entities.push entity
270
- end
271
- class Script
272
- attr_reader :filename, :code
273
- def initialize filename
274
- @filename = filename
275
- @code = File.read(filename)
276
- @code.untaint
277
- end
325
+ def add_entity(entity)
326
+ @entities.push entity
278
327
  end
279
328
  end
280
329
 
@@ -0,0 +1,5 @@
1
+ class Gamefic::Query::AmbiguousChildren < Gamefic::Query::ManyChildren
2
+ def allow_ambiguous?
3
+ true
4
+ end
5
+ end