gamefic 3.1.0 → 3.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3900923aaef12a43321ce6f9cc5957953b12bba7d939e0a1666d8c6c75703855
4
- data.tar.gz: 6023310c5e26e9632ed4c053a9bea619e1455dbb66966d82fc9e772044d19d3a
3
+ metadata.gz: ea395014528ad74c93bfc7e33809a6b6ea24c0c8e2d37a2f6e0d7067eef564d1
4
+ data.tar.gz: ec2fcf7c80c501cf93c036bf2416f3f583755460d38aca464a5844eb2705151f
5
5
  SHA512:
6
- metadata.gz: aea9a57211541f056c730707227020f2c35376d59cc4e69c3c7463e8a8bafa7b6fcd4585a99bf2ce235fdc4c583393f53e060554e06f6e5912358959305627eb
7
- data.tar.gz: 5351ea7cc8b3ff4e01e064eb12a594dc2d928641b19e8593243da00b672780acff0d808d73eca1a80cf2e2139fd657b870fa7a5a5315e0a2a3998bc306db0c05
6
+ metadata.gz: 7875f99a1d9d327f0251fdbeae15ddf31820091fd0cbdc43a1e5cbe7cabd8697057fe6333b84400d5e545fc31e3720c82ecc366dc2cc0066b71f3e2794b6e196
7
+ data.tar.gz: 91353478d4a994758c6fcc0a843335819cdb9086be9a29fdd429b333abdf58c4e2179e147b685a2f4720fb9e160ecd83ef5f4e5b4ab41a0ad582f583845f2843
data/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 3.2.1 - July 1, 2024
2
+ - MultipleChoice accepts shortened text
3
+ - Return Proxy::Agent from attr_seed and make_seed
4
+ - MultipleChoice skips finish blocks for invalid input
5
+
6
+ ## 3.2.0 - April 9, 2024
7
+ - Bug fix for marshal of structs in Opal
8
+ - Add last_input and last_prompt at start of take
9
+
1
10
  ## 3.1.0 - April 8, 2024
2
11
  - Dispatcher prioritizes strict token matches
3
12
  - Scanner builds commands
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gamefic
2
4
  module Active
3
5
  # A module for active entities that provides a default Messenger with
@@ -31,7 +31,6 @@ module Gamefic
31
31
 
32
32
  # @return [Props::Default]
33
33
  def start
34
- props.output[:scene] = scene.to_hash
35
34
  scene.run_start_blocks actor, props
36
35
  scene.start actor, props
37
36
  # @todo See if this can be handled better
@@ -47,7 +46,6 @@ module Gamefic
47
46
  def finish
48
47
  actor.flush
49
48
  scene.finish(actor, props)
50
- props.output.replace(last_prompt: props.prompt, last_input: props.input)
51
49
  scene.run_finish_blocks actor, props
52
50
  end
53
51
 
@@ -164,6 +164,8 @@ module Gamefic
164
164
  cue :default_scene
165
165
  @props = Take.start(self, @last_cue)
166
166
  @last_output = self.output
167
+ @props.output[:last_prompt] = @last_output.prompt
168
+ @props.output[:last_input] = @last_input
167
169
  @output = @props.output.dup.freeze
168
170
  end
169
171
 
@@ -203,7 +205,7 @@ module Gamefic
203
205
  # True if the actor is ready to leave the game.
204
206
  #
205
207
  def concluding?
206
- epic.empty? || @props&.scene&.type == 'Conclusion'
208
+ epic.empty? || @props&.scene&.fetch(:type) == 'Conclusion'
207
209
  end
208
210
 
209
211
  def accessible?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gamefic
2
4
  # A function module for creating commands from expressions.
3
5
  #
@@ -2,8 +2,6 @@
2
2
 
3
3
  module Gamefic
4
4
  module Props
5
- SceneData = Struct.new(:name, :type)
6
-
7
5
  # A collection of data related to a scene. Scenes define which Props class
8
6
  # they use. Props can be accessed in a scene's on_start and on_finish
9
7
  # callbacks.
@@ -27,13 +25,13 @@ module Gamefic
27
25
  attr_reader :context
28
26
  alias data context
29
27
 
30
- # @return [SceneData]
28
+ # @return [Hash]
31
29
  attr_reader :scene
32
30
 
33
31
  # @param scene [Scene]
34
32
  # @param context [Hash]
35
33
  def initialize scene, **context
36
- @scene = SceneData.new(scene.name, scene.type)
34
+ @scene = { name: scene.name, type: scene.type }
37
35
  @context = context
38
36
  end
39
37
 
@@ -58,7 +58,8 @@ module Gamefic
58
58
  end
59
59
 
60
60
  def index_by_text
61
- options.find_index { |text| input.downcase == text.downcase }
61
+ matches = options.map.with_index { |text, idx| next idx if text.downcase.start_with?(input.downcase) }.compact
62
+ matches.first if matches.one?
62
63
  end
63
64
  end
64
65
  end
@@ -6,11 +6,10 @@ module Gamefic
6
6
  # data.
7
7
  #
8
8
  class Output
9
- # @return [String, nil]
10
- attr_reader :last_input
9
+ READER_METHODS = %i[messages options queue scene prompt last_prompt last_input].freeze
10
+ WRITER_METHODS = %i[messages= prompt= last_prompt= last_input=].freeze
11
11
 
12
- # @return [String, nil]
13
- attr_reader :last_prompt
12
+ attr_reader :raw_data
14
13
 
15
14
  def initialize **data
16
15
  @raw_data = {
@@ -23,36 +22,49 @@ module Gamefic
23
22
  merge! data
24
23
  end
25
24
 
26
- # @return [String]
27
- def messages
28
- raw_data[:messages]
29
- end
30
-
31
- # @return [Array<String>]
32
- def options
33
- raw_data[:options]
34
- end
35
-
36
- # @return [Array<String>]
37
- def queue
38
- raw_data[:queue]
39
- end
40
-
41
- # @todo Should this be a concrete class?
42
- # @return [Hash]
43
- def scene
44
- raw_data[:scene]
45
- end
46
-
47
- # @return [String]
48
- def prompt
49
- raw_data[:prompt]
50
- end
51
-
25
+ # @!attribute [rw] messages
26
+ # A text message to be displayed at the start of a scene.
27
+ #
28
+ # @return [String]
29
+
30
+ # @!attribute [rw] options
31
+ # An array of options to be presented to the player, e.g., in a
32
+ # MultipleChoice scene.
33
+ #
34
+ # @return [Array<String>]
35
+
36
+ # @!attribute [rw] queue
37
+ # An array of commands waiting to be executed.
38
+ #
39
+ # @return [Array<String>]
40
+
41
+ # @!attribute [rw] scene
42
+ # A hash containing the scene's :name and :type.
43
+ #
44
+ # @return [Hash]
45
+
46
+ # @!attribute [rw] [prompt]
47
+ # The input prompt to be displayed to the player.
48
+ #
49
+ # @return [String]
50
+
51
+ # @!attribute [rw] last_input
52
+ # The input received from the player in the previous scene.
53
+ #
54
+ # @return [String, nil]
55
+
56
+ # @!attribute [rw] last_prompt
57
+ # The input prompt from the previous scene.
58
+ #
59
+ # @return [String, nil]
60
+
61
+ # @param key [Symbol]
52
62
  def [] key
53
63
  raw_data[key]
54
64
  end
55
65
 
66
+ # @param key [Symbol]
67
+ # @param value [Object]
56
68
  def []= key, value
57
69
  raw_data[key] = value
58
70
  end
@@ -74,9 +86,22 @@ module Gamefic
74
86
  raw_data.replace data
75
87
  end
76
88
 
77
- private
89
+ def freeze
90
+ raw_data.freeze
91
+ super
92
+ end
78
93
 
79
- attr_reader :raw_data
94
+ def method_missing method, *args
95
+ return raw_data[method] if READER_METHODS.include?(method)
96
+
97
+ return raw_data[method.to_s[0..-2].to_sym] = args.first if WRITER_METHODS.include?(method)
98
+
99
+ super
100
+ end
101
+
102
+ def respond_to_missing?(method, _with_private = false)
103
+ READER_METHODS.include?(method) || WRITER_METHODS.include?(method)
104
+ end
80
105
  end
81
106
  end
82
107
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gamefic
2
4
  module Props
3
5
  # Props for Pause scenes.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gamefic
2
4
  # A module for matching objects to tokens.
3
5
  #
@@ -53,7 +53,7 @@ module Gamefic
53
53
  # @param props [Props::Default]
54
54
  # @return [void]
55
55
  def finish actor, props
56
- props.input = actor.queue.shift
56
+ props.input = actor.queue.shift&.strip
57
57
  end
58
58
 
59
59
  def run_start_blocks actor, props
@@ -20,6 +20,12 @@ module Gamefic
20
20
  actor.tell format(props.invalid_message, input: props.input)
21
21
  actor.recue
22
22
  end
23
+
24
+ def run_finish_blocks actor, props
25
+ return unless props.index
26
+
27
+ super
28
+ end
23
29
  end
24
30
  end
25
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gamefic
2
4
  module Scriptable
3
5
  # Functions that provide proxies for referencing a narrative's entities
@@ -104,7 +104,7 @@ module Gamefic
104
104
  def make_seed klass, **opts
105
105
  @count ||= 0
106
106
  seed { make(klass, **opts) }
107
- @count.tap { @count += 1 }
107
+ Proxy::Agent.new(@count.tap { @count += 1 })
108
108
  end
109
109
 
110
110
  # Seed an entity with an attribute method.
@@ -124,7 +124,7 @@ module Gamefic
124
124
  instance_variable_set("@#{name}", make(klass, **opts))
125
125
  self.class.define_method(name) { instance_variable_get("@#{name}") }
126
126
  end
127
- @count.tap { @count += 1 }
127
+ Proxy::Agent.new(@count.tap { @count += 1 })
128
128
  end
129
129
 
130
130
  if RUBY_ENGINE == 'opal'
data/lib/gamefic/vault.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Gamefic
2
4
  # An array wrapper that exposes a protected interface. The array is always
3
5
  # returned frozen. It can only be modified through #add and #delete. The
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gamefic
4
- VERSION = '3.1.0'
4
+ VERSION = '3.2.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gamefic
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-04-08 00:00:00.000000000 Z
11
+ date: 2024-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal