gamefic 2.0.0 → 2.1.1

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.
@@ -4,22 +4,30 @@ module Gamefic
4
4
  class Subplot #< Container
5
5
  include World
6
6
  include Scriptable
7
+ include Gamefic::Serialize
7
8
  # @!parse extend Scriptable::ClassMethods
8
9
 
9
10
  # @return [Gamefic::Plot]
10
11
  attr_reader :plot
11
12
 
12
13
  # @param plot [Gamefic::Plot]
13
- # @param introduce [Gamefic::Actor]
14
- # @param next_cue [Class<Gamefic::Scene::Base>]
14
+ # @param introduce [Gamefic::Actor, nil]
15
+ # @param next_cue [Class<Gamefic::Scene::Base>, nil]
16
+ # @param more [Hash]
15
17
  def initialize plot, introduce: nil, next_cue: nil, **more
16
18
  @plot = plot
17
19
  @next_cue = next_cue
18
20
  @concluded = false
21
+ @more = more
19
22
  configure more
20
23
  run_scripts
21
24
  playbook.freeze
22
25
  self.introduce introduce unless introduce.nil?
26
+ @static = [self] + scene_classes + entities
27
+ end
28
+
29
+ def static
30
+ plot.static
23
31
  end
24
32
 
25
33
  def players
@@ -63,6 +71,7 @@ module Gamefic
63
71
  # @todo I'm not sure why rejecting nils is necessary here. It's only an
64
72
  # issue in Opal.
65
73
  entities.reject(&:nil?).each { |e| destroy e }
74
+ # plot.static.remove(scene_classes + entities)
66
75
  end
67
76
 
68
77
  def concluded?
@@ -86,6 +86,7 @@ module Gamefic
86
86
  end
87
87
 
88
88
  def ==(other)
89
+ return false unless other.is_a?(Syntax)
89
90
  signature == other.signature
90
91
  end
91
92
 
@@ -1,3 +1,3 @@
1
1
  module Gamefic
2
- VERSION = '2.0.0'
2
+ VERSION = '2.1.1'
3
3
  end
data/lib/gamefic/world.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  module Gamefic
2
+ # A collection of classes and modules related to generating a world model.
3
+ #
2
4
  module World
3
5
  autoload :Playbook, 'gamefic/world/playbook'
4
6
  autoload :Entities, 'gamefic/world/entities'
@@ -96,7 +96,7 @@ module Gamefic
96
96
  end
97
97
 
98
98
  # Declare a dismabiguation response for actions.
99
- # The disambigurator is executed when an action expects an argument to
99
+ # The disambiguator is executed when an action expects an argument to
100
100
  # reference a specific entity but its query matched more than one. For
101
101
  # example, "red" might refer to either a red key or a red book.
102
102
  #
@@ -144,7 +144,7 @@ module Gamefic
144
144
  #
145
145
  # @return [Array<String>]
146
146
  def verbs
147
- playbook.verbs.map { |v| v.to_s }.reject{ |v| v.start_with?('_') }
147
+ playbook.verbs.map(&:to_s).reject { |v| v.start_with?('_') }
148
148
  end
149
149
 
150
150
  # Get an Array of all Actions defined in the Plot.
@@ -164,20 +164,20 @@ module Gamefic
164
164
 
165
165
  private
166
166
 
167
+ # @param queries [Array]
168
+ # @return [Array<Query::Base>]
167
169
  def map_response_args queries
168
- result = []
169
- queries.each do |q|
170
+ queries.map do |q|
170
171
  if q.is_a?(Regexp)
171
- result.push Gamefic::Query::Text.new(q)
172
+ Gamefic::Query::Text.new(q)
172
173
  elsif q.is_a?(Gamefic::Query::Base)
173
- result.push q
174
+ q
174
175
  elsif q.is_a?(Gamefic::Element) || (q.is_a?(Class) && q <= Gamefic::Element)
175
- result.push get_default_query.new(q)
176
+ get_default_query.new(q)
176
177
  else
177
178
  raise ArgumentError.new("Invalid argument for response: #{q}")
178
179
  end
179
180
  end
180
- result
181
181
  end
182
182
  end
183
183
  end
@@ -43,11 +43,18 @@ module Gamefic
43
43
  # @param [Gamefic::Entity] The entity to remove
44
44
  def destroy entity
45
45
  entity.parent = nil
46
- index = entities.index(entity)
47
- return if index.nil? || index < static_entity_length - 1
48
- entities.delete_at index
46
+ # index = entities.index(entity)
47
+ # return if index.nil? || index < static_entity_length - 1
48
+ # entities.delete_at index
49
+ # players.delete entity
50
+ # entity.destroy
51
+
52
+ # @todo It might make sense to destroy the entity completely now. It
53
+ # will still have a reference in the index, but that shouldn't impact
54
+ # the current state of the plot.
55
+ return if static.include?(entity)
56
+ entities.delete entity
49
57
  players.delete entity
50
- entity.destroy
51
58
  end
52
59
 
53
60
  # Pick an entity based on its description.
@@ -86,16 +93,6 @@ module Gamefic
86
93
  def players
87
94
  @players ||= []
88
95
  end
89
-
90
- private
91
-
92
- def mark_static_entities
93
- @static_entity_length ||= entities.length
94
- end
95
-
96
- def static_entity_length
97
- @static_entity_length || 0
98
- end
99
96
  end
100
97
  end
101
98
  end
@@ -3,6 +3,16 @@ module Gamefic
3
3
  # A collection of rules for performing commands.
4
4
  #
5
5
  class Playbook
6
+ # An array of available syntaxes.
7
+ #
8
+ # @return [Array<Gamefic::Syntax>]
9
+ attr_reader :syntaxes
10
+
11
+ # An array of defined validators.
12
+ #
13
+ # @return [Array<Proc>]
14
+ attr_reader :validators
15
+
6
16
  def initialize commands: {}, syntaxes: [], validators: [], disambiguator: nil
7
17
  @commands = commands
8
18
  @syntaxes = syntaxes
@@ -10,13 +20,6 @@ module Gamefic
10
20
  @disambiguator = disambiguator
11
21
  end
12
22
 
13
- # An array of available syntaxes.
14
- #
15
- # @return [Array<Gamefic::Syntax>]
16
- def syntaxes
17
- @syntaxes
18
- end
19
-
20
23
  # An array of available actions.
21
24
  #
22
25
  # @return [Array<Gamefic::Action>]
@@ -31,21 +34,14 @@ module Gamefic
31
34
  @commands.keys
32
35
  end
33
36
 
34
- # An array of defined validators.
35
- #
36
- # @return [Array<Proc>]
37
- def validators
38
- @validators
39
- end
40
-
41
37
  # Get the action for handling ambiguous entity references.
42
38
  #
43
39
  def disambiguator
44
40
  @disambiguator ||= Action.subclass(nil, Query::Base.new) do |actor, entities|
45
41
  definites = []
46
- entities.each { |entity|
42
+ entities.each do |entity|
47
43
  definites.push entity.definitely
48
- }
44
+ end
49
45
  actor.tell "I don't know which you mean: #{definites.join_or}."
50
46
  end
51
47
  end
@@ -66,7 +62,7 @@ module Gamefic
66
62
  # Get an Array of all Actions associated with the specified verb.
67
63
  #
68
64
  # @param verb [Symbol] The Symbol for the verb (e.g., :go or :look)
69
- # @return [Array<Action>] The verb's associated Actions
65
+ # @return [Array<Class<Action>>] The verb's associated Actions
70
66
  def actions_for verb
71
67
  @commands[verb] || []
72
68
  end
@@ -150,12 +146,8 @@ module Gamefic
150
146
  # @return [Array<Gamefic::Action>]
151
147
  def dispatch(actor, *command)
152
148
  result = []
153
- if command.length > 1
154
- result.concat dispatch_from_params(actor, command[0], command[1..-1])
155
- end
156
- if result.empty?
157
- result.concat dispatch_from_string(actor, command.join(' '))
158
- end
149
+ result.concat dispatch_from_params(actor, command[0], command[1..-1]) if command.length > 1
150
+ result.concat dispatch_from_string(actor, command.join(' ')) if result.empty?
159
151
  result
160
152
  end
161
153
 
@@ -167,14 +159,13 @@ module Gamefic
167
159
  def dispatch_from_string actor, text
168
160
  result = []
169
161
  commands = Syntax.tokenize(text, actor.syntaxes)
170
- commands.each { |c|
171
- available = actions_for(c.verb)
172
- available.each { |a|
162
+ commands.each do |c|
163
+ actions_for(c.verb).each do |a|
173
164
  next if a.hidden?
174
165
  o = a.attempt(actor, c.arguments)
175
166
  result.unshift o unless o.nil?
176
- }
177
- }
167
+ end
168
+ end
178
169
  sort_and_reduce_actions result
179
170
  end
180
171
 
@@ -185,9 +176,9 @@ module Gamefic
185
176
  def dispatch_from_params actor, verb, params
186
177
  result = []
187
178
  available = actions_for(verb)
188
- available.each { |a|
179
+ available.each do |a|
189
180
  result.unshift a.new(actor, params) if a.valid?(actor, params)
190
- }
181
+ end
191
182
  sort_and_reduce_actions result
192
183
  end
193
184
 
@@ -217,38 +208,37 @@ module Gamefic
217
208
  user_friendly = action.verb.to_s.gsub(/_/, ' ')
218
209
  args = []
219
210
  used_names = []
220
- action.queries.each { |c|
211
+ action.queries.each do |_c|
221
212
  num = 1
222
213
  new_name = ":var"
223
214
  while used_names.include? new_name
224
- num = num + 1
215
+ num += 1
225
216
  new_name = ":var#{num}"
226
217
  end
227
218
  used_names.push new_name
228
219
  user_friendly += " #{new_name}"
229
220
  args.push new_name
230
- }
221
+ end
231
222
  add_syntax Syntax.new(user_friendly.strip, "#{action.verb} #{args.join(' ')}") unless action.verb.to_s.start_with?('_')
232
223
  end
233
224
 
234
225
  def add_syntax syntax
235
- if @commands[syntax.verb] == nil
236
- raise "No actions exist for \"#{syntax.verb}\""
237
- end
226
+ raise "No actions exist for \"#{syntax.verb}\"" if @commands[syntax.verb].nil?
227
+
238
228
  @syntaxes.unshift syntax
239
- @syntaxes.uniq! &:signature
240
- @syntaxes.sort! { |a, b|
229
+ @syntaxes.uniq!(&:signature)
230
+ @syntaxes.sort! do |a, b|
241
231
  if a.token_count == b.token_count
242
232
  # For syntaxes of the same length, length of action takes precedence
243
233
  b.first_word <=> a.first_word
244
234
  else
245
235
  b.token_count <=> a.token_count
246
236
  end
247
- }
237
+ end
248
238
  end
249
239
 
250
240
  def sort_and_reduce_actions arr
251
- arr.sort_by.with_index{|a, i| [a.rank, -i]}.reverse.uniq(&:class)
241
+ arr.sort_by.with_index { |a, i| [a.rank, -i]}.reverse.uniq(&:class)
252
242
  end
253
243
  end
254
244
  end
@@ -2,6 +2,7 @@ module Gamefic
2
2
  module World
3
3
  module Players
4
4
  include Gamefic::World::Entities
5
+ include Gamefic::World::Commands
5
6
 
6
7
  # An array of entities that are currently connected to users.
7
8
  #
@@ -10,12 +11,27 @@ module Gamefic
10
11
  @players ||= []
11
12
  end
12
13
 
13
- # Get the character that the player will control on introduction.
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.
14
29
  #
15
30
  # @return [Gamefic::Actor]
16
- def get_player_character
31
+ def make_player_character
17
32
  cast player_class, name: 'yourself', synonyms: 'self myself you me', proper_named: true
18
33
  end
34
+ alias get_player_character make_player_character
19
35
  end
20
36
  end
21
37
  end
@@ -35,7 +35,7 @@ module Gamefic
35
35
  players.push player
36
36
  @introduction.call(player) unless @introduction.nil?
37
37
  # @todo Find a better way to persist player characters
38
- Gamefic::Index.stick
38
+ # Gamefic::Index.stick
39
39
  end
40
40
 
41
41
  # Create a multiple-choice scene.
@@ -95,10 +95,10 @@ module Gamefic
95
95
  #
96
96
  # @param prompt [String]
97
97
  # @yieldparam [Gamefic::Actor]
98
- # @yieldparam [Gamefic::Scene::Custom]
99
- # @return [Class<Gamefic::Scene::Custom>]
98
+ # @yieldparam [Gamefic::Scene::Base]
99
+ # @return [Class<Gamefic::Scene::Base>]
100
100
  def question prompt = 'What is your answer?', &block
101
- s = Scene::Custom.subclass do |actor, scene|
101
+ s = Scene::Base.subclass do |actor, scene|
102
102
  scene.prompt = prompt
103
103
  scene.on_finish &block
104
104
  end
@@ -144,29 +144,29 @@ module Gamefic
144
144
  scene_classes.push s
145
145
  s
146
146
  end
147
-
147
+
148
148
  # Create a custom scene.
149
149
  #
150
150
  # Custom scenes should always specify the next scene to be cued or
151
151
  # prepared. If not, the scene will get repeated on the next turn.
152
152
  #
153
- # This method creates a Scene::Custom by default. You can customize other
153
+ # This method creates a Scene::Base by default. You can customize other
154
154
  # scene types by specifying the class to create.
155
155
  #
156
156
  # @example Ask the user for a name
157
- # @scene = custom do |scene|
158
- # data.prompt = "What's your name?"
159
- # scene.on_finish do |actor, data|
160
- # actor.name = data.input
157
+ # @scene = custom do |actor, scene|
158
+ # scene.prompt = "What's your name?"
159
+ # scene.on_finish do
160
+ # actor.name = scene.input
161
161
  # actor.tell "Hello, #{actor.name}!"
162
- # actor.cue :active
162
+ # actor.cue default_scene
163
163
  # end
164
164
  # end
165
165
  #
166
166
  # @param cls [Class] The class of scene to be instantiated.
167
167
  # @yieldparam [Gamefic::Actor]
168
- # @return [Class<Gamefic::Scene::Custom>]
169
- def custom cls = Scene::Custom, &block
168
+ # @return [Class<Gamefic::Scene::Base>]
169
+ def custom cls = Scene::Base, &block
170
170
  s = cls.subclass &block
171
171
  scene_classes.push s
172
172
  s
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gamefic
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-24 00:00:00.000000000 Z
11
+ date: 2021-07-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '12.3'
20
- - - "~>"
20
+ - - ">="
21
21
  - !ruby/object:Gem::Version
22
22
  version: '12.3'
23
23
  type: :development
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
- - - ">="
27
+ - - "~>"
28
28
  - !ruby/object:Gem::Version
29
29
  version: '12.3'
30
- - - "~>"
30
+ - - ">="
31
31
  - !ruby/object:Gem::Version
32
32
  version: '12.3'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rspec
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 3.5.0
40
37
  - - "~>"
41
38
  - !ruby/object:Gem::Version
42
39
  version: '3.5'
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 3.5.0
43
43
  type: :development
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 3.5.0
50
47
  - - "~>"
51
48
  - !ruby/object:Gem::Version
52
49
  version: '3.5'
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 3.5.0
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: simplecov
55
55
  requirement: !ruby/object:Gem::Requirement
@@ -74,6 +74,7 @@ files:
74
74
  - ".rspec"
75
75
  - ".rubocop.yml"
76
76
  - ".solargraph.yml"
77
+ - CHANGELOG.md
77
78
  - Gemfile
78
79
  - LICENSE
79
80
  - README.md
@@ -89,7 +90,6 @@ files:
89
90
  - lib/gamefic/describable.rb
90
91
  - lib/gamefic/element.rb
91
92
  - lib/gamefic/entity.rb
92
- - lib/gamefic/index.rb
93
93
  - lib/gamefic/keywords.rb
94
94
  - lib/gamefic/messaging.rb
95
95
  - lib/gamefic/node.rb
@@ -108,11 +108,11 @@ files:
108
108
  - lib/gamefic/query/parent.rb
109
109
  - lib/gamefic/query/siblings.rb
110
110
  - lib/gamefic/query/text.rb
111
+ - lib/gamefic/query/tree.rb
111
112
  - lib/gamefic/scene.rb
112
113
  - lib/gamefic/scene/activity.rb
113
114
  - lib/gamefic/scene/base.rb
114
115
  - lib/gamefic/scene/conclusion.rb
115
- - lib/gamefic/scene/custom.rb
116
116
  - lib/gamefic/scene/multiple_choice.rb
117
117
  - lib/gamefic/scene/multiple_scene.rb
118
118
  - lib/gamefic/scene/pause.rb
@@ -133,7 +133,7 @@ homepage: http://gamefic.com
133
133
  licenses:
134
134
  - MIT
135
135
  metadata: {}
136
- post_install_message:
136
+ post_install_message:
137
137
  rdoc_options: []
138
138
  require_paths:
139
139
  - lib
@@ -148,8 +148,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
148
  - !ruby/object:Gem::Version
149
149
  version: '0'
150
150
  requirements: []
151
- rubygems_version: 3.0.3
152
- signing_key:
151
+ rubygems_version: 3.1.6
152
+ signing_key:
153
153
  specification_version: 4
154
154
  summary: Gamefic
155
155
  test_files: []