gamefic-commodities 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: '08a734e8585509d12f97f384bcd5e7ff9081ee6500ea4f3eaaae6337bbaf0d98'
4
+ data.tar.gz: 7c83ac167edba79d950397f919faeffe7c12ef76c0f0e82e4b4fbe8cda3d288a
5
+ SHA512:
6
+ metadata.gz: ff83060ddb98824b01c98a229697834e5d3448d4ceb8c22f8de11939439c48fae7cdda371c79dd5cc94f2347edc51dc98fca623d1f42ca7a14152e136756f440
7
+ data.tar.gz: ada7030b38061a939c7ee47b010f67dbd039645f8bf2464a9a71658568fd9144a7c4f9072806d3fc377398aaa28e07c36eb4c3a12e9f770cfbafd42024da69ec
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ## 0.1.0 - October 5, 2024
2
+ - First release
data/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # Gamefic::Commodities
2
+
3
+ A groupable Gamefic entity.
4
+
5
+ Commodities are grouped by default. When a commodity gets added to a parent
6
+ that already contains a commodity with the same class and name, they get
7
+ combined, i.e., the existing commodity's quantity is increased by the new
8
+ commodity's quantity, and the other commodity is destroyed.
9
+
10
+ Players can specify quantities in commands, e.g., `take 1 coin`.
11
+
12
+ ## Installation
13
+
14
+ Add the library to your Gamefic project's Gemfile:
15
+
16
+ ```
17
+ gem 'gamefic-commodities'
18
+ ```
19
+
20
+ Run `bundle install`.
21
+
22
+ Add the requirement to your project's code (typically in `main.rb`):
23
+
24
+ ```
25
+ require 'gamefic-commodities'
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ The `Commodity` entity and related actions are automatically imported into `Gamefic::Standard`.
31
+
32
+ Example of adding a commodity:
33
+
34
+ ```ruby
35
+ class Example::Plot < Gamefic::Plot
36
+ include Gamefic::Standard
37
+
38
+ attr_seed :room, Room,
39
+ name: 'room'
40
+
41
+ make_seed Commodity,
42
+ name: 'coin',
43
+ quantity: 2,
44
+ parent: _attr(:room)
45
+
46
+ introduction do |actor|
47
+ actor.parent = room
48
+ end
49
+ end
50
+ ```
51
+
52
+ Example gameplay:
53
+
54
+ > look
55
+ You see 2 coins.
56
+ > take coin
57
+ You take 2 coins.
58
+ > drop 1 coin
59
+ You drop a coin.
60
+ > look
61
+ You see a coin.
62
+ > inventory
63
+ You're carrying a coin.
64
+
65
+ ## Development
66
+
67
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
68
+
69
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
70
+
71
+ ## Contributing
72
+
73
+ Bug reports and pull requests are welcome on GitHub at https://github.com/castwide/gamefic-commodity.
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require 'opal/rspec/rake_task'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task default: :spec
10
+
11
+ Opal::RSpec::RakeTask.new(:opal) do |_, config|
12
+ Opal.append_path File.join(__dir__, 'lib')
13
+ Opal.use_gem 'gamefic'
14
+ Opal.use_gem 'gamefic-standard'
15
+ config.default_path = 'spec'
16
+ config.pattern = 'spec/**/*_spec.rb'
17
+ config.requires = ['opal_helper']
18
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/gamefic/commodities/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'gamefic-commodities'
7
+ spec.version = Gamefic::Commodities::VERSION
8
+ spec.authors = ['Fred Snyder']
9
+ spec.email = ['fsnyder@castwide.com']
10
+
11
+ spec.summary = 'A Commodity entity for Gamefic.'
12
+ # spec.description = "TODO: Write a longer description or delete this line."
13
+ # spec.homepage = "TODO: Put your gem's website or public repo URL here."
14
+ spec.required_ruby_version = '>= 2.7.0'
15
+
16
+ # spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+
18
+ # spec.metadata["homepage_uri"] = spec.homepage
19
+ # spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
20
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(__dir__) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (File.expand_path(f) == __FILE__) ||
27
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
28
+ end
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ # Uncomment to register a new dependency of your gem
35
+ # spec.add_dependency "example-gem", "~> 1.0"
36
+ spec.add_dependency 'gamefic', '~> 3.5'
37
+ spec.add_dependency 'gamefic-standard', '~> 3.0'
38
+
39
+ spec.add_development_dependency 'opal', '~> 1.7'
40
+ spec.add_development_dependency 'opal-rspec', '~> 1.0'
41
+ spec.add_development_dependency 'opal-sprockets', '~> 1.0'
42
+ spec.add_development_dependency 'rspec', '~> 3.0'
43
+ spec.add_development_dependency 'simplecov', '~> 0.14'
44
+
45
+ # For more information and examples about making a new gem, check out our
46
+ # guide at: https://bundler.io/guides/creating_gem.html
47
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Commodities
5
+ module Actions
6
+ extend Gamefic::Scriptable
7
+
8
+ respond :look, ::Commodity do |actor, thing|
9
+ actor.proceed
10
+ next unless thing.plural?
11
+
12
+ if thing.parent == actor
13
+ actor.tell "You have #{thing.quantity} of them."
14
+ else
15
+ actor.tell "There are #{thing.quantity} of them in #{the thing.parent}."
16
+ end
17
+ end
18
+
19
+ respond :take, siblings(::Commodity) do |actor, _|
20
+ actor.proceed
21
+ end
22
+
23
+ respond :place, siblings(::Commodity), available do |actor, _|
24
+ actor.proceed
25
+ end
26
+
27
+ respond :place, children(::Commodity), available do |actor, _|
28
+ actor.proceed
29
+ end
30
+
31
+ respond :insert, siblings(::Commodity), available do |actor, _|
32
+ actor.proceed
33
+ end
34
+
35
+ respond :insert, children(::Commodity), available do |actor, _|
36
+ actor.proceed
37
+ end
38
+
39
+ respond :take, available(::Commodity, ambiguous: true) do |actor, comms|
40
+ comms = comms.reject { |com| com.parent == actor }
41
+ if comms.one?
42
+ actor.execute :take, comms.first
43
+ else
44
+ filtered = comms.reject { |ent| actor.flatten.include?(ent) }
45
+ if filtered.one?
46
+ actor.execute :take, filtered.first
47
+ else
48
+ places = filtered.map { |object| object.parent.definitely }
49
+ actor.tell "Where do you want to take one from, #{places.join_or}?"
50
+ actor.ask_for_what "take #{filtered.first.name} from __what__"
51
+ end
52
+ end
53
+ end
54
+
55
+ respond :collect, available(::Commodity, ambiguous: true) do |actor, comms|
56
+ comms.reject { |com| com.parent == actor }
57
+ .each { |com| actor.perform "take #{com.plural_name} from #{com.parent}" }
58
+ end
59
+ interpret 'collect all', 'take all'
60
+ interpret 'collect :thing', 'take :thing'
61
+ interpret 'collect all :commodity', 'collect :commodity'
62
+ interpret 'collect all of :commodity', 'collect :commodity'
63
+ interpret 'collect every :commodity', 'collect :commodity'
64
+ interpret 'collect each :commodity', 'collect :commodity'
65
+ interpret 'take all :commodity', 'collect :commodity'
66
+ interpret 'take all of :commodity', 'collect :commodity'
67
+ interpret 'take every :commodity', 'collect :commodity'
68
+ interpret 'take each :commodity', 'collect :commodity'
69
+
70
+ meta nil, plaintext do |actor, text|
71
+ words = text.keywords
72
+ verb = words.shift
73
+ next actor.proceed if words.empty? || words.first =~ /[^\d]+/
74
+
75
+ number = words.shift.to_i
76
+ Utils.try_quantity(actor, number, "#{verb} #{words.join(' ')}")
77
+ end
78
+
79
+ on_update do
80
+ entities.that_are(::Commodity)
81
+ .reject(&:parent)
82
+ .each { |entity| destroy entity }
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Commodities
5
+ # A groupable Gamefic entity.
6
+ #
7
+ # Commodities are grouped by default. When a commodity gets added to a parent
8
+ # that already contains a commodity with the same class and name, they get
9
+ # combined, i.e., the existing commodity's quantity is increased by the new
10
+ # commodity's quantity, and the other commodity is destroyed.
11
+ #
12
+ class Commodity < Item
13
+ class CommodityError < ArgumentError; end
14
+
15
+ # @return [Integer]
16
+ attr_writer :quantity
17
+
18
+ # @return [String]
19
+ attr_writer :plural_name
20
+
21
+ def quantity
22
+ @quantity ||= 1
23
+ end
24
+
25
+ def name
26
+ plural? ? plural_name : super
27
+ end
28
+
29
+ def indefinite_article
30
+ plural? ? quantity : super
31
+ end
32
+
33
+ def plural?
34
+ quantity > 1
35
+ end
36
+
37
+ # @return [String]
38
+ def plural_name
39
+ @plural_name ||= "#{@name}s"
40
+ end
41
+
42
+ # @param amount [Integer]
43
+ # @return [Commodity]
44
+ def except(amount)
45
+ validate_split(amount)
46
+ split(quantity - amount)
47
+ end
48
+
49
+ # @param amount [Integer]
50
+ # @return [Commodity]
51
+ def split(amount)
52
+ validate_split(amount)
53
+ return nil if amount.zero?
54
+
55
+ dup.tap do |other|
56
+ self.quantity -= amount
57
+ other.quantity = amount
58
+ other.parent = nil
59
+ end
60
+ end
61
+
62
+ def parent=(other)
63
+ extant = other&.children&.that_are&.find { |ent| same?(ent) }
64
+ if extant
65
+ extant.quantity += quantity
66
+ super(nil)
67
+ else
68
+ super
69
+ end
70
+ end
71
+
72
+ def same?(other)
73
+ other.class == self.class && other.plural_name == plural_name
74
+ end
75
+
76
+ def keywords
77
+ super + plural_name.keywords
78
+ end
79
+
80
+ def counted?
81
+ @counted ||= false
82
+ end
83
+
84
+ def count(number)
85
+ raise CommodityError, "You need to specify 1 or more #{plural_name}" if number.zero?
86
+ return unless block_given?
87
+
88
+ @counted = true
89
+ rest = except(number)
90
+ from = parent
91
+ yield
92
+ rest&.parent = from if rest&.quantity&.positive?
93
+ @counted = false
94
+ end
95
+
96
+ def validate_split(amount)
97
+ raise CommodityError, "There #{maybe_plural('is', 'are')} only #{quantity} #{name}." unless amount <= quantity
98
+
99
+ raise CommodityError, "You can't specify a negative number of #{plural_name}." unless amount >= 0
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ Commodity = Gamefic::Commodities::Commodity
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Commodities
5
+ module Utils
6
+ module_function
7
+
8
+ # @param actor [Gamefic::Actor]
9
+ # @param number [Integer]
10
+ # @param input [String]
11
+ def try_quantity(actor, number, input)
12
+ command = Gamefic::Command.compose(actor, input)
13
+ return actor.proceed unless command.arguments.first.is_a?(Commodity)
14
+
15
+ command.arguments.first.count(number) do
16
+ actor.execute command.verb, *command.arguments
17
+ end
18
+ rescue Commodity::CommodityError => e
19
+ actor.tell e.message
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Commodities
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gamefic'
4
+ require 'gamefic-standard'
5
+
6
+ module Gamefic
7
+ module Commodities
8
+ require 'gamefic/commodities/version'
9
+ require 'gamefic/commodities/commodity'
10
+ require 'gamefic/commodities/utils'
11
+ require 'gamefic/commodities/actions'
12
+ end
13
+ end
14
+
15
+ Gamefic::Standard.include Gamefic::Commodities::Actions
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'gamefic/commodities'
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gamefic-commodities
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Fred Snyder
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-10-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gamefic
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.5'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gamefic-standard
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: opal
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: opal-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: opal-sprockets
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.14'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.14'
111
+ description:
112
+ email:
113
+ - fsnyder@castwide.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".rspec"
119
+ - CHANGELOG.md
120
+ - README.md
121
+ - Rakefile
122
+ - gamefic-commodities.gemspec
123
+ - lib/gamefic-commodities.rb
124
+ - lib/gamefic/commodities.rb
125
+ - lib/gamefic/commodities/actions.rb
126
+ - lib/gamefic/commodities/commodity.rb
127
+ - lib/gamefic/commodities/utils.rb
128
+ - lib/gamefic/commodities/version.rb
129
+ homepage:
130
+ licenses: []
131
+ metadata: {}
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ required_ruby_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: 2.7.0
141
+ required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ requirements: []
147
+ rubygems_version: 3.3.7
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: A Commodity entity for Gamefic.
151
+ test_files: []