gamefic 3.2.1 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea395014528ad74c93bfc7e33809a6b6ea24c0c8e2d37a2f6e0d7067eef564d1
4
- data.tar.gz: ec2fcf7c80c501cf93c036bf2416f3f583755460d38aca464a5844eb2705151f
3
+ metadata.gz: 85e6fc4d2b5c4a9abfe20cbbe17affdec1f1badb134e8cad88849a5305fb9bf0
4
+ data.tar.gz: 97a29823857d93fafa9e8a3bc4872e27a4a6da480f589535da6abf254eb5aa7a
5
5
  SHA512:
6
- metadata.gz: 7875f99a1d9d327f0251fdbeae15ddf31820091fd0cbdc43a1e5cbe7cabd8697057fe6333b84400d5e545fc31e3720c82ecc366dc2cc0066b71f3e2794b6e196
7
- data.tar.gz: 91353478d4a994758c6fcc0a843335819cdb9086be9a29fdd429b333abdf58c4e2179e147b685a2f4720fb9e160ecd83ef5f4e5b4ab41a0ad582f583845f2843
6
+ metadata.gz: 611c3b366e76a29cd2ffb95f906882a63ac9d73bfb6d1d7aaa505e4470f4526311704c2245285f908247b6248b086914d8a145e1c9b86577e197d8d77c707939
7
+ data.tar.gz: dc19cf51ab4edbc1b9f9708eb543c977527e3165a949d948782349e545d0a32fde42f8532c9071e0ddc86b521cc0d1cb778e8e88b1d7b0dcc575d547c5db1df1
@@ -22,7 +22,7 @@ jobs:
22
22
  runs-on: ubuntu-latest
23
23
  strategy:
24
24
  matrix:
25
- ruby-version: ['2.7', '3.0', '3.1']
25
+ ruby-version: ['2.7', '3.0', '3.1', '3.3']
26
26
 
27
27
  steps:
28
28
  - uses: actions/checkout@v3
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## 3.3.0 - September 1, 2024
2
+ - Node#take
3
+ - Node#include?
4
+ - Reject non-string tokens in Text queries
5
+
6
+ ## 3.2.2 - July 21, 2024
7
+ - Describable#described?
8
+
1
9
  ## 3.2.1 - July 1, 2024
2
10
  - MultipleChoice accepts shortened text
3
11
  - Return Proxy::Agent from attr_seed and make_seed
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "bundler/gem_tasks"
4
- require "rspec/core/rake_task"
3
+ require 'bundler/gem_tasks'
5
4
  require 'rspec/core/rake_task'
6
5
  require 'opal/rspec/rake_task'
7
6
 
@@ -14,7 +13,8 @@ end
14
13
  task :default => :spec
15
14
 
16
15
  Opal::RSpec::RakeTask.new(:opal) do |_, config|
17
- Opal.append_path File.expand_path('../lib', __FILE__)
16
+ Opal.append_path File.join(__dir__, 'lib')
17
+ config.default_path = 'spec'
18
18
  config.pattern = 'spec/**/*_spec.rb'
19
- config.requires = ['spec_helper']
19
+ config.requires = ['opal_helper']
20
20
  end
@@ -6,6 +6,7 @@ module Gamefic
6
6
  # a few shortcuts.
7
7
  #
8
8
  module Messaging
9
+ # @return [Messenger]
9
10
  def messenger
10
11
  @messenger ||= Messenger.new
11
12
  end
@@ -43,7 +43,7 @@ module Gamefic
43
43
  arguments = []
44
44
  response.queries.each_with_index do |query, idx|
45
45
  result = Scanner.send(method, query.select(actor), "#{remainder} #{expression.tokens[idx]}".strip)
46
- break unless validate_result_from_query(result, query)
46
+ break unless valid_result_from_query?(result, query)
47
47
 
48
48
  if query.ambiguous?
49
49
  arguments.push result.matched
@@ -60,7 +60,7 @@ module Gamefic
60
60
 
61
61
  # @param result [Scanner::Result]
62
62
  # @param query [Query::Base]
63
- def validate_result_from_query result, query
63
+ def valid_result_from_query? result, query
64
64
  return false if result.matched.empty?
65
65
 
66
66
  result.matched.length == 1 || query.ambiguous?
@@ -112,10 +112,11 @@ module Gamefic
112
112
  # Does the object have a description?
113
113
  #
114
114
  # @return [Boolean]
115
- def description?
115
+ def described?
116
116
  @description.to_s != ''
117
117
  end
118
- alias has_description? description?
118
+ alias description? described?
119
+ alias has_description? described?
119
120
 
120
121
  # Get the object's description.
121
122
  #
data/lib/gamefic/node.rb CHANGED
@@ -42,6 +42,15 @@ module Gamefic
42
42
  parent&.add_child self
43
43
  end
44
44
 
45
+ # Add children to the node. Return all the node's children.
46
+ #
47
+ # @param children [Array<Node, Array<Node>>]
48
+ # @return [Array<Node>]
49
+ def take *children
50
+ children.flatten.each { |child| child.parent = self }
51
+ children
52
+ end
53
+
45
54
  # Determine if external objects can interact with this object's children.
46
55
  # For example, a game can designate that the contents of a bowl are
47
56
  # accessible, while the contents of a locked safe are not.
@@ -54,10 +63,14 @@ module Gamefic
54
63
  # True if this node is the other's parent.
55
64
  #
56
65
  # @param other [Node]
57
- def has?(other)
66
+ def include?(other)
58
67
  other.parent == self
59
68
  end
60
69
 
70
+ def adjacent?(other)
71
+ other.parent == parent
72
+ end
73
+
61
74
  protected
62
75
 
63
76
  def add_child(node)
data/lib/gamefic/plot.rb CHANGED
@@ -9,6 +9,8 @@ module Gamefic
9
9
  super
10
10
  subplots.each(&:ready)
11
11
  players.each(&:start_take)
12
+ subplots.each(&:conclude) if concluding?
13
+
12
14
  players.select(&:concluding?).each { |plyr| rulebook.run_player_conclude_blocks plyr }
13
15
  subplots.delete_if(&:concluding?)
14
16
  end
@@ -24,16 +24,24 @@ module Gamefic
24
24
  @ambiguous = ambiguous
25
25
  end
26
26
 
27
- # @deprecated Queries should only be used to select entities that are
28
- # eligible to be response arguments. After a text command is tokenized
29
- # into an array of expressions, the composer builds the command that
30
- # the dispatcher uses to execute actions. The #accept? method verifies
31
- # that the command's arguments match the response's queries.
27
+ # Get a query result for a given subject and token.
28
+ #
29
+ # @note This method is retained as a convenience for authors. Narratives
30
+ # should use Composer to build commands, as it provides more precise
31
+ # matching of tokens to valid response arguments. Authors can use
32
+ # #query to find entities that match a token regardless of whether the
33
+ # result matches an available response.
34
+ #
35
+ # @example
36
+ # respond :reds do |actor|
37
+ # reds = available(ambiguous: true).query(actor, 'red').match
38
+ # actor.tell "The red things you can see here are #{reds.join_and}."
39
+ # end
32
40
  #
33
41
  # @param subject [Gamefic::Entity]
34
42
  # @param token [String]
35
43
  # @return [Result]
36
- def query(subject, token)
44
+ def query(_subject, _token)
37
45
  raise "#query not implemented for #{self.class}"
38
46
  end
39
47
 
@@ -42,7 +50,7 @@ module Gamefic
42
50
  #
43
51
  # @param subject [Entity]
44
52
  # @return [Array<Entity>]
45
- def select subject
53
+ def select _subject
46
54
  raise "#select not implemented for #{self.class}"
47
55
  end
48
56
 
@@ -88,12 +96,14 @@ module Gamefic
88
96
  depth
89
97
  end
90
98
 
99
+ # @param scan [Scanner::Result]
91
100
  def ambiguous_result scan
92
101
  return Result.new(nil, scan.token) if scan.matched.empty?
93
102
 
94
103
  Result.new(scan.matched, scan.remainder)
95
104
  end
96
105
 
106
+ # @param scan [Scanner::Result]
97
107
  def unambiguous_result scan
98
108
  return Result.new(nil, scan.token) unless scan.matched.one?
99
109
 
@@ -6,7 +6,6 @@ module Gamefic
6
6
  # relationship to the entity performing the query. For example,
7
7
  # Scope::Children would filter from an array of the entity's descendants.
8
8
  #
9
- # @return [Class<Gamefic::Scope::Base>]
10
9
  class Scoped < Base
11
10
  attr_reader :scope
12
11
 
@@ -39,6 +39,8 @@ module Gamefic
39
39
  private
40
40
 
41
41
  def match? token
42
+ return false unless token.is_a?(String)
43
+
42
44
  case @argument
43
45
  when Regexp
44
46
  token =~ @argument
@@ -45,6 +45,7 @@ module Gamefic
45
45
  # proxy(:@instance_variable_name)
46
46
  #
47
47
  # @param symbol [Symbol]
48
+ # @return [Agent]
48
49
  def proxy symbol
49
50
  Agent.new(symbol)
50
51
  end
@@ -38,6 +38,12 @@ module Gamefic
38
38
  end
39
39
  alias scene block
40
40
 
41
+ def preface name, klass = Scene::Activity, &start
42
+ rulebook.scenes.add klass.new(name, rulebook.narrative, on_start: start)
43
+ name
44
+ end
45
+ alias precursor preface
46
+
41
47
  # Add a block to be executed when a player is added to the game.
42
48
  # Each Plot should only have one introduction.
43
49
  #
@@ -55,7 +61,7 @@ module Gamefic
55
61
  rulebook.scenes
56
62
  .introduction Scene::Default.new nil,
57
63
  rulebook.narrative,
58
- on_start: proc { |actor, _props| instance_exec(actor, &start) }
64
+ on_start: proc { |actor, _props| Stage.run(self, actor, &start) }
59
65
  end
60
66
 
61
67
  # Create a multiple-choice scene.
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gamefic
4
- VERSION = '3.2.1'
4
+ VERSION = '3.3.0'
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.2.1
4
+ version: 3.3.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: 2024-07-01 00:00:00.000000000 Z
11
+ date: 2024-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: opal
@@ -195,7 +195,6 @@ files:
195
195
  - lib/gamefic/syntax/template.rb
196
196
  - lib/gamefic/vault.rb
197
197
  - lib/gamefic/version.rb
198
- - spec-opal/spec_helper.rb
199
198
  homepage: https://gamefic.com
200
199
  licenses:
201
200
  - MIT
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'gamefic'
4
- require 'ostruct'
5
-
6
- RSpec.configure do |config|
7
- # Run specs in random order to surface order dependencies. If you find an
8
- # order dependency and want to debug it, you can fix the order by providing
9
- # the seed, which is printed after each run.
10
- # --seed 1234
11
- # config.order = :random
12
-
13
- # Seed global randomization in this process using the `--seed` CLI option.
14
- # Setting this allows you to use `--seed` to deterministically reproduce
15
- # test failures related to randomization by passing the same `--seed` value
16
- # as the one that triggered the failure.
17
- # Kernel.srand config.seed
18
-
19
- config.after :each do
20
- Gamefic::Narrative.blocks.clear
21
- Gamefic::Plot.blocks.clear
22
- Gamefic::Subplot.blocks.clear
23
- end
24
- end