gamefic-standard 3.3.0 → 4.0.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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/Rakefile +6 -3
  4. data/gamefic-standard.gemspec +4 -4
  5. data/lib/{gamefic-standard → gamefic/standard}/actions/drop.rb +2 -2
  6. data/lib/{gamefic-standard → gamefic/standard}/actions/enter.rb +0 -8
  7. data/lib/gamefic/standard/actions/give.rb +38 -0
  8. data/lib/{gamefic-standard → gamefic/standard}/actions/lock.rb +15 -3
  9. data/lib/gamefic/standard/actions/look.rb +149 -0
  10. data/lib/gamefic/standard/actions/mount.rb +29 -0
  11. data/lib/gamefic/standard/actions/nil.rb +37 -0
  12. data/lib/{gamefic-standard → gamefic/standard}/actions/place.rb +2 -2
  13. data/lib/{gamefic-standard → gamefic/standard}/actions/pronouns.rb +5 -7
  14. data/lib/gamefic/standard/actions/quit.rb +24 -0
  15. data/lib/gamefic/standard/actions/repeat.rb +28 -0
  16. data/lib/{gamefic-standard → gamefic/standard}/actions/search.rb +9 -9
  17. data/lib/{gamefic-standard → gamefic/standard}/actions/take.rb +2 -1
  18. data/lib/{gamefic-standard → gamefic/standard}/actions/talk.rb +2 -2
  19. data/lib/{gamefic-standard → gamefic/standard}/actions/unlock.rb +6 -2
  20. data/lib/gamefic/standard/actions.rb +57 -0
  21. data/lib/{gamefic-standard → gamefic/standard}/articles.rb +2 -0
  22. data/lib/gamefic/standard/entities/character.rb +14 -0
  23. data/lib/gamefic/standard/entities/container.rb +16 -0
  24. data/lib/gamefic/standard/entities/door.rb +46 -0
  25. data/lib/gamefic/standard/entities/fixture.rb +8 -0
  26. data/lib/gamefic/standard/entities/item.rb +11 -0
  27. data/lib/gamefic/standard/entities/portal.rb +50 -0
  28. data/lib/gamefic/standard/entities/receptacle.rb +9 -0
  29. data/lib/gamefic/standard/entities/room.rb +61 -0
  30. data/lib/gamefic/standard/entities/rubble.rb +16 -0
  31. data/lib/gamefic/standard/entities/scenery.rb +13 -0
  32. data/lib/gamefic/standard/entities/supporter.rb +9 -0
  33. data/lib/gamefic/standard/entities/thing.rb +9 -0
  34. data/lib/gamefic/standard/entities.rb +18 -0
  35. data/lib/{gamefic-standard → gamefic/standard}/lockable.rb +8 -0
  36. data/lib/{gamefic-standard → gamefic/standard}/openable.rb +2 -2
  37. data/lib/gamefic/standard/queries.rb +24 -0
  38. data/lib/{gamefic-standard → gamefic/standard}/version.rb +1 -1
  39. data/lib/gamefic/standard.rb +32 -0
  40. data/lib/gamefic-standard.rb +1 -34
  41. metadata +59 -57
  42. data/lib/gamefic-standard/actions/give.rb +0 -41
  43. data/lib/gamefic-standard/actions/look.rb +0 -152
  44. data/lib/gamefic-standard/actions/nil.rb +0 -70
  45. data/lib/gamefic-standard/actions/quit.rb +0 -20
  46. data/lib/gamefic-standard/actions/repeat.rb +0 -22
  47. data/lib/gamefic-standard/actions.rb +0 -56
  48. data/lib/gamefic-standard/entities/character.rb +0 -5
  49. data/lib/gamefic-standard/entities/container.rb +0 -8
  50. data/lib/gamefic-standard/entities/door.rb +0 -42
  51. data/lib/gamefic-standard/entities/fixture.rb +0 -4
  52. data/lib/gamefic-standard/entities/item.rb +0 -7
  53. data/lib/gamefic-standard/entities/portal.rb +0 -46
  54. data/lib/gamefic-standard/entities/receptacle.rb +0 -5
  55. data/lib/gamefic-standard/entities/room.rb +0 -61
  56. data/lib/gamefic-standard/entities/rubble.rb +0 -12
  57. data/lib/gamefic-standard/entities/scenery.rb +0 -9
  58. data/lib/gamefic-standard/entities/supporter.rb +0 -5
  59. data/lib/gamefic-standard/entities/thing.rb +0 -5
  60. data/lib/gamefic-standard/entities.rb +0 -12
  61. data/lib/gamefic-standard/queries.rb +0 -12
  62. /data/lib/{gamefic-standard → gamefic/standard}/actions/attack.rb +0 -0
  63. /data/lib/{gamefic-standard → gamefic/standard}/actions/close.rb +0 -0
  64. /data/lib/{gamefic-standard → gamefic/standard}/actions/go.rb +0 -0
  65. /data/lib/{gamefic-standard → gamefic/standard}/actions/insert.rb +0 -0
  66. /data/lib/{gamefic-standard → gamefic/standard}/actions/inventory.rb +0 -0
  67. /data/lib/{gamefic-standard → gamefic/standard}/actions/leave.rb +0 -0
  68. /data/lib/{gamefic-standard → gamefic/standard}/actions/move.rb +0 -0
  69. /data/lib/{gamefic-standard → gamefic/standard}/actions/open.rb +0 -0
  70. /data/lib/{gamefic-standard → gamefic/standard}/actions/save-restore-undo.rb +0 -0
  71. /data/lib/{gamefic-standard → gamefic/standard}/actions/wait.rb +0 -0
  72. /data/lib/{gamefic-standard → gamefic/standard}/direction.rb +0 -0
  73. /data/lib/{gamefic-standard → gamefic/standard}/enterable.rb +0 -0
  74. /data/lib/{gamefic-standard → gamefic/standard}/introduction.rb +0 -0
  75. /data/lib/{gamefic-standard → gamefic/standard}/pathfinder.rb +0 -0
  76. /data/lib/{gamefic-standard → gamefic/standard}/standardized.rb +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 83db9094673ea86b25db1d51bf9c06c62be6fadc7ed938f39c71b9c16cba9566
4
- data.tar.gz: 579a371ef1c031b2b7bb2bf9d66831e7ce92ad04d3f7ec450dd183b1265e4f80
3
+ metadata.gz: ca3a0186e345a9afcd439decd174e1e0d25af882a3c12a4fae8c93ce7dc148a9
4
+ data.tar.gz: 983d0edf810abcade4ccca1ebcdb45d9052968cea7e614f4dd478d79d4fdc94b
5
5
  SHA512:
6
- metadata.gz: beffd2638efbb5a61fe6f0605a59e7807045aa67705c1cf5a042c28cd279e8efe8b9146690a9e742a9ebc369db035b4ecefcf0b2ea2cdca288b9a68426f253d9
7
- data.tar.gz: 324c51c2f6eeec341ee26d81449949521f0cb51063f739fa319faf072abd090b18b31c92ed16e2855934cffadb088f98e6ba3a8a4f05b13e66fbc90b43601b15
6
+ metadata.gz: 10f9e483b14180248220dec5dfb2d99a331ef54f06f3e2cedd869a2577fdd6bc968457e0675bbc6af16f48f79a4585b5c0215d247053ee089f742a3d5ebe3dc7
7
+ data.tar.gz: 5afbf188e3dde7b5850aedc9e7f45bc5dc9b0c46f0cd913a16f60142e8d2d2ddcf184507b4f7c2cb68b72671d2ec1df1307a1171f421428bf68d387961d84c2d
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 4.0.1 - May 26, 2025
2
+ - Fix lock/unlock actions
3
+
4
+ ## 4.0.0 - January 25, 2025
5
+ - Updates for Gamefic 4.0
6
+
1
7
  ## 3.3.0 - October 5, 2024
2
8
  - Include Pronoun and Give in Standard
3
9
  - Add gamefic-what
data/Rakefile CHANGED
@@ -1,10 +1,13 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'bundler/gem_tasks'
5
+ require 'rspec/core/rake_task'
3
6
  require 'opal/rspec/rake_task'
4
7
 
5
8
  RSpec::Core::RakeTask.new(:spec)
6
9
 
7
- task :default => :spec
10
+ task default: :spec
8
11
 
9
12
  Opal::RSpec::RakeTask.new(:opal) do |_, config|
10
13
  Opal.append_path File.join(__dir__, 'lib')
@@ -1,6 +1,6 @@
1
1
  lib = File.expand_path('lib', __dir__)
2
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
- require 'gamefic-standard/version'
3
+ require 'gamefic/standard/version'
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'gamefic-standard'
@@ -37,9 +37,9 @@ Gem::Specification.new do |spec|
37
37
 
38
38
  spec.required_ruby_version = '>= 2.7.0'
39
39
 
40
- spec.add_dependency 'gamefic', '~> 3.3'
41
- spec.add_dependency 'gamefic-grammar', '~> 1.0'
42
- spec.add_dependency 'gamefic-what', '~> 1.0'
40
+ spec.add_dependency 'gamefic', '~> 4.0'
41
+ spec.add_dependency 'gamefic-grammar', '~> 1.1'
42
+ spec.add_dependency 'gamefic-what', '~> 2.0'
43
43
 
44
44
  spec.add_development_dependency 'opal', '~> 1.7'
45
45
  spec.add_development_dependency 'opal-rspec', '~> 1.0'
@@ -10,7 +10,7 @@ module Gamefic
10
10
  actor.tell "You're not carrying #{the thing}."
11
11
  end
12
12
 
13
- respond :drop, children do |actor, thing|
13
+ respond :drop, descendants do |actor, thing|
14
14
  actor.execute :take, thing
15
15
  next unless thing.parent == actor
16
16
 
@@ -18,7 +18,7 @@ module Gamefic
18
18
  actor.tell "You drop #{the thing}."
19
19
  end
20
20
 
21
- respond :drop, children do |actor, thing|
21
+ respond :drop, descendants do |actor, thing|
22
22
  thing.parent = actor.parent
23
23
  actor.tell "You drop #{the thing}."
24
24
  end
@@ -19,22 +19,14 @@ module Gamefic
19
19
  actor.tell "You're already in #{the container}."
20
20
  end
21
21
 
22
- respond :enter, parent(Supporter) do |actor, supporter|
23
- actor.tell "You're inside #{the supporter} already."
24
- end
25
-
26
22
  respond :enter, siblings(Container, proc(&:enterable?), proc(&:closed?)) do |actor, container|
27
23
  actor.tell "#{The container} is closed."
28
24
  end
29
25
 
30
- interpret 'get on :thing', 'enter :thing'
31
26
  interpret 'get in :thing', 'enter :thing'
32
27
  interpret 'get inside :thing', 'enter :thing'
33
- interpret 'sit on :thing', 'enter :thing'
34
28
  interpret 'sit in :thing', 'enter :thing'
35
- interpret 'lie on :thing', 'enter :thing'
36
29
  interpret 'lie in :thing', 'enter :thing'
37
- interpret 'stand on :thing', 'enter :thing'
38
30
  interpret 'stand in :thing', 'enter :thing'
39
31
  end
40
32
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Standard
5
+ module Actions
6
+ module Give
7
+ extend Gamefic::Scriptable
8
+ include Gamefic::What
9
+
10
+ respond :give, available, children do |actor, _character, _gift|
11
+ actor.tell 'Nothing happens.'
12
+ end
13
+
14
+ respond :give, available(Character), available do |actor, character, gift|
15
+ actor.tell "#{The character} has no use for #{the gift}."
16
+ end
17
+
18
+ respond :give, available(Character), available do |actor, _character, gift|
19
+ actor.execute :take, gift if gift.parent != actor
20
+
21
+ actor.proceed if gift.parent == actor
22
+ end
23
+
24
+ respond :give, Thing do |actor, thing|
25
+ actor.tell "Who do you want to give #{the thing} to?"
26
+ actor.cue AskForWhat, template: "give #{the thing} to __what__"
27
+ end
28
+
29
+ respond :give, Character do |actor, character|
30
+ actor.tell "What do you want to give to #{the character}?"
31
+ actor.cue AskForWhat, template: "give __what__ to #{the character}"
32
+ end
33
+
34
+ interpret 'give :gift to :character', 'give :character :gift'
35
+ end
36
+ end
37
+ end
38
+ end
@@ -10,10 +10,22 @@ module Gamefic
10
10
  actor.tell "You can't lock #{the thing}."
11
11
  end
12
12
 
13
+ respond :lock, available(Lockable) do |actor, thing|
14
+ if thing.has_lock_key? && actor.children.include?(thing.lock_key)
15
+ actor.execute :lock, thing, thing.lock_key
16
+ else
17
+ actor.tell "You can't lock #{the thing}."
18
+ end
19
+ end
20
+
13
21
  respond :lock, available(Lockable, proc(&:has_lock_key?)), children do |actor, thing, key|
14
22
  if thing.lock_key == key
15
- thing.locked = true
16
- actor.tell "You lock ##{the thing} with #{the key}."
23
+ if thing.locked?
24
+ actor.tell "It's already locked."
25
+ else
26
+ thing.locked = true
27
+ actor.tell "You lock #{the thing} with #{the key}."
28
+ end
17
29
  else
18
30
  actor.tell "You can't lock #{the thing} with #{the key}."
19
31
  end
@@ -24,7 +36,7 @@ module Gamefic
24
36
  actor.proceed if key.parent == actor
25
37
  end
26
38
 
27
- interpret "lock :container with :key", "lock :container :key"
39
+ interpret "lock :container with :key", "lock :container :key"
28
40
  end
29
41
  end
30
42
  end
@@ -0,0 +1,149 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Standard
5
+ module Actions
6
+ module Look
7
+ RELATION_PHRASES = {
8
+ in: 'inside',
9
+ on: 'on top of'
10
+ }.freeze
11
+
12
+ extend Gamefic::Scriptable
13
+
14
+ def itemize_room(actor)
15
+ return unless (room = actor.room)
16
+
17
+ siblings = room.children.select(&:itemized?).that_are_not(actor)
18
+
19
+ siblings.that_are(Character)
20
+ .reject(&:locale_description)
21
+ .tap do |list|
22
+ list.empty? or actor.tell "#{list.join_and.cap_first} #{list.one? ? 'is' : 'are'} here."
23
+ end
24
+
25
+ siblings.that_are_not(Character, Portal)
26
+ .reject(&:locale_description)
27
+ .tap do |list|
28
+ list.empty? or actor.tell "You see #{list.join_and}."
29
+ end
30
+
31
+ siblings.select(&:locale_description)
32
+ .each { |thing| actor.tell thing.locale_description }
33
+
34
+ itemize_explicit_portals(actor)
35
+ itemize_parent(actor) unless actor.parent == actor.room
36
+ end
37
+
38
+ def itemize_explicit_portals(actor)
39
+ return unless actor.room&.explicit_exits?
40
+
41
+ siblings = actor.room.children.select(&:itemized?).that_are_not(actor)
42
+ earlier = siblings.select(&:locale_description).that_are(Portal).any?
43
+ siblings.that_are(Portal)
44
+ .reject(&:locale_description)
45
+ .tap do |portals|
46
+ next if portals.empty?
47
+
48
+ if portals.one?
49
+ actor.tell "There is#{earlier ? ' also ' : ' '}an exit #{portals.first.instruction}."
50
+ else
51
+ order = %w[north northeast east southeast south southwest west northwest up down]
52
+ dirs = portals.map(&:instruction)
53
+ .map(&:to_s)
54
+ .sort { |a, b| order.index(a) || 0 <=> order.index(b) || 1 }
55
+ actor.tell "There are#{earlier ? ' also ' : ' '}exits #{dirs.join_and}."
56
+ end
57
+ end
58
+ end
59
+
60
+ def itemize_parent(actor)
61
+ return unless (parent = actor.parent)
62
+
63
+ siblings = parent.children.that_are_not(actor)
64
+ if siblings.empty?
65
+ actor.tell "You're #{RELATION_PHRASES[actor.relation]} #{the parent}."
66
+ else
67
+ actor.tell "You're #{RELATION_PHRASES[actor.relation]} #{the parent}, along with #{siblings.join_and}."
68
+ end
69
+ end
70
+
71
+ respond :look do |actor|
72
+ if actor.room
73
+ actor.execute :look, actor.room
74
+ else
75
+ actor.tell "You're in a featureless void."
76
+ end
77
+ end
78
+
79
+ respond :look, myself do |actor, _|
80
+ actor.tell actor.description
81
+ actor.execute :inventory
82
+ end
83
+
84
+ respond :look, available(Thing) do |actor, thing|
85
+ actor.tell thing.description
86
+ thing.children.that_are(proc(&:attached?)).that_are(proc(&:itemized?)).each do |item|
87
+ actor.tell "#{An item} is attached to #{the thing}."
88
+ end
89
+ end
90
+
91
+ respond :look, available(Supporter) do |actor, thing|
92
+ itemized = thing.children.that_are_not(proc(&:attached?)).that_are(proc(&:itemized?))
93
+ # If the supporter does not have a description but it does contain
94
+ # itemized things, avoid saying there's nothing special about it.
95
+ actor.proceed if thing.has_description? || itemized.empty?
96
+ actor.tell "You see #{itemized.join_and} on #{the thing}." unless itemized.empty?
97
+ end
98
+
99
+ respond :look, available(Receptacle) do |actor, thing|
100
+ actor.proceed
101
+ actor.tell "You're currently in #{the thing}." if actor.parent == thing
102
+ next unless actor.parent == thing
103
+
104
+ itemized = thing.accessible.that_are_not(actor, proc(&:attached?)).that_are(proc(&:itemized?))
105
+ next if itemized.empty?
106
+
107
+ if actor.parent == thing
108
+ actor.tell "You see #{itemized.join_and} here." unless itemized.empty?
109
+ else
110
+ actor.tell "You see #{itemized.join_and} in #{the thing}." unless itemized.empty?
111
+ end
112
+ end
113
+
114
+ respond :look, parent(Supporter, proc(&:enterable?)) do |actor, supporter|
115
+ actor.proceed
116
+ actor.tell "You are currently on #{the supporter}."
117
+ end
118
+
119
+ respond :look, available(Thing, Openable) do |actor, thing|
120
+ actor.tell thing.description if thing.has_description?
121
+ actor.tell "#{The thing} is #{thing.open? ? 'open' : 'closed'}."
122
+ next if thing.closed? || thing.children.empty?
123
+
124
+ actor.tell "You see #{thing.children.join_and}."
125
+ end
126
+
127
+ respond :look, room do |actor, room|
128
+ actor.tell "<strong>#{room.name.cap_first}</strong>"
129
+ actor.tell room.description if room.described?
130
+ itemize_room(actor)
131
+ end
132
+
133
+ interpret 'look around', 'look'
134
+ interpret 'look here', 'look'
135
+ interpret 'l', 'look'
136
+
137
+ interpret 'look at :thing', 'look :thing'
138
+ interpret 'look on :thing', 'look :thing'
139
+ interpret 'look under :thing', 'look :thing'
140
+ interpret 'look beneath :thing', 'look :thing'
141
+ interpret 'look around :thing', 'look :thing'
142
+ interpret 'l :thing', 'look :thing'
143
+ interpret 'examine :thing', 'look :thing'
144
+ interpret 'x :thing', 'look :thing'
145
+ interpret 'inspect :thing', 'look :thing'
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Standard
5
+ module Actions
6
+ module Mount
7
+ extend Gamefic::Scriptable
8
+
9
+ respond :mount, siblings do |actor, thing|
10
+ actor.tell "#{The thing} can't accommodate you."
11
+ end
12
+
13
+ respond :mount, siblings(Supporter, proc(&:enterable?)) do |actor, supporter|
14
+ actor.put supporter, :on
15
+ actor.tell "You get on #{the supporter}."
16
+ end
17
+
18
+ respond :mount, parent(Supporter) do |actor, supporter|
19
+ actor.tell "You're already on #{the supporter}."
20
+ end
21
+
22
+ interpret 'get on :thing', 'mount :thing'
23
+ interpret 'sit on :thing', 'mount :thing'
24
+ interpret 'lie on :thing', 'mount :thing'
25
+ interpret 'stand on :thing', 'mount :thing'
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Standard
5
+ module Actions
6
+ module Nil
7
+ extend Gamefic::Scriptable
8
+
9
+ meta nil, plaintext do |actor, string|
10
+ next if string.strip.empty?
11
+
12
+ words = string.keywords
13
+ if actor.can?(words[0])
14
+ if words.length > 1
15
+ possible = [actor] + available.span(actor)
16
+ result = Scanner.scan(possible, words[1..-1].join(' '))
17
+ if result.matched.empty?
18
+ actor.tell %(I recognize "#{words[0]}" as a verb but don't know what you mean by "#{words[1..-1].join(' ')}.")
19
+ elsif result.remainder != ''
20
+ actor.tell %(I recognize "#{string.sub(/#{result.remainder}$/,
21
+ '').strip}" as a command but was confused by "#{result.remainder}.")
22
+ elsif result.matched.one?
23
+ actor.tell %(I recognize "#{words[0]}" and "#{result.matched.first.name}" but could not understand them together.)
24
+ else
25
+ actor.tell %(I recognize "#{words[0]}" but I'm not sure if "#{words[1..-1].join(' ')}" means #{result.matched.map(&:definitely).join_or}.)
26
+ end
27
+ else
28
+ actor.tell %(I recognize "#{words[0]}" as a verb but could not understand it in this context.)
29
+ end
30
+ else
31
+ actor.tell %(I don't recognize "#{words[0]}" as a verb.)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -14,12 +14,12 @@ module Gamefic
14
14
  actor.execute :take, thing unless thing.parent == actor
15
15
  next unless thing.parent == actor
16
16
 
17
- thing.parent = supporter
17
+ thing.put supporter, :on
18
18
  actor.tell "You put #{the thing} on #{the supporter}."
19
19
  end
20
20
 
21
21
  respond :place, children, available(Supporter) do |actor, thing, supporter|
22
- thing.parent = supporter
22
+ thing.put supporter, :on
23
23
  actor.tell "You put #{the thing} on #{the supporter}."
24
24
  end
25
25
 
@@ -10,16 +10,15 @@ module Gamefic
10
10
  actor[:standard_pronoun_targets] = []
11
11
  end
12
12
 
13
- after_action do |action|
14
- next unless action.verb
13
+ after_command do |actor, command|
14
+ next unless command.verb
15
15
 
16
- action.actor[:standard_pronoun_targets].replace action.arguments.that_are(Thing)
16
+ actor[:standard_pronoun_targets].replace command.arguments.that_are(Thing)
17
17
  end
18
18
 
19
19
  meta nil, plaintext do |actor, string|
20
20
  keywords = string.keywords
21
- list = actor.epic.synonyms
22
- next actor.proceed unless list.include?(keywords.first&.to_sym)
21
+ next actor.proceed unless actor.can?(keywords.first)
23
22
 
24
23
  xlation = keywords[1..].map do |word|
25
24
  next word unless %w[him her it them].include?(word)
@@ -27,8 +26,7 @@ module Gamefic
27
26
  actor[:standard_pronoun_targets].find { |obj| obj.objective == word }
28
27
  end
29
28
  next actor.proceed if xlation.any?(&:nil?) || xlation.that_are(Thing).empty?
30
-
31
- actor.perform "#{keywords[0].to_sym} #{xlation.join(' ')}"
29
+ actor.perform "#{keywords[0]} #{xlation.join(' ')}"
32
30
  end
33
31
  end
34
32
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Standard
5
+ module Actions
6
+ module Quit
7
+ extend Gamefic::Scriptable
8
+
9
+ ConfirmQuit = yes_or_no do
10
+ on_start do |actor|
11
+ actor.tell 'Are you sure you want to quit?'
12
+ end
13
+ on_finish do |actor, props|
14
+ actor.cue default_conclusion if props.yes?
15
+ end
16
+ end
17
+
18
+ meta :quit do |actor|
19
+ actor.cue ConfirmQuit
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Standard
5
+ module Actions
6
+ module Repeat
7
+ extend Gamefic::Scriptable
8
+
9
+ after_command do |actor, command|
10
+ next if command.verb == :repeat || command.input.nil?
11
+
12
+ actor[:standard_repeatable_command] = command.input
13
+ end
14
+
15
+ meta :repeat do |actor|
16
+ if actor[:standard_repeatable_command]
17
+ actor.tell "Repeating <kbd>\"#{actor[:standard_repeatable_command]}\"</kbd>..."
18
+ actor.perform actor[:standard_repeatable_command]
19
+ else
20
+ actor.tell "You don't have a previous command to repeat right now."
21
+ end
22
+ end
23
+
24
+ interpret 'again', 'repeat'
25
+ end
26
+ end
27
+ end
28
+ end
@@ -11,21 +11,21 @@ module Gamefic
11
11
  end
12
12
 
13
13
  respond :search, available(Receptacle) do |actor, thing|
14
- if thing.accessible?
15
- itemized = thing.children.that_are_not(proc(&:attached?)).that_are(proc(&:itemized?))
16
- if itemized.empty?
17
- actor.tell "There's nothing inside #{the thing}."
18
- else
19
- actor.tell "You see #{itemized.join_and} in #{the thing}." unless itemized.empty?
20
- end
14
+ itemized = thing.accessible.that_are_not(proc(&:attached?)).that_are(proc(&:itemized?))
15
+ if itemized.empty?
16
+ actor.tell "There's nothing inside #{the thing}."
21
17
  else
22
- actor.tell "You can't see inside #{the thing}."
18
+ actor.tell "You see #{itemized.join_and} in #{the thing}." unless itemized.empty?
23
19
  end
24
20
  end
25
21
 
26
22
  respond :search, available(Container, proc(&:closed?)) do |actor, container|
27
23
  actor.execute :open, container
28
- actor.proceed if container.open?
24
+ if container.open?
25
+ actor.proceed
26
+ else
27
+ actor.tell "You can't see inside #{the container}."
28
+ end
29
29
  end
30
30
 
31
31
  interpret 'look inside :thing', 'search :thing'
@@ -30,7 +30,8 @@ module Gamefic
30
30
  end
31
31
 
32
32
  respond :take, plaintext(/^(all|everything)$/) do |actor, _all|
33
- items = Gamefic::Scope::Family.matches(actor)
33
+ items = Gamefic::Query::Family.new
34
+ .span(actor)
34
35
  .select(&:portable?)
35
36
  .reject { |item| actor.flatten.include?(item) }
36
37
  if items.empty?
@@ -7,11 +7,11 @@ module Gamefic
7
7
  extend Gamefic::Scriptable
8
8
 
9
9
  respond :talk do |actor|
10
- actor.tell 'You talk to yourself.'
10
+ actor.execute :talk, actor
11
11
  end
12
12
 
13
13
  respond :talk, myself do |actor, _yourself|
14
- actor.execute :talk
14
+ actor.tell 'You talk to yourself.'
15
15
  end
16
16
 
17
17
  respond :talk, available do |actor, _thing|
@@ -16,8 +16,12 @@ module Gamefic
16
16
 
17
17
  respond :unlock, available(Lockable, proc(&:has_lock_key?)), children do |actor, thing, key|
18
18
  if thing.lock_key == key
19
- thing.locked = false
20
- actor.tell "You unlock #{the thing} with #{the key}."
19
+ if thing.locked?
20
+ thing.locked = false
21
+ actor.tell "You unlock #{the thing} with #{the key}."
22
+ else
23
+ actor.tell "It's already unlocked."
24
+ end
21
25
  else
22
26
  actor.tell "You can't unlock #{the thing} with #{the key}."
23
27
  end
@@ -0,0 +1,57 @@
1
+ require 'gamefic/standard/actions/nil'
2
+ require 'gamefic/standard/actions/attack'
3
+ require 'gamefic/standard/actions/drop'
4
+ require 'gamefic/standard/actions/enter'
5
+ require 'gamefic/standard/actions/mount'
6
+ require 'gamefic/standard/actions/open'
7
+ require 'gamefic/standard/actions/close'
8
+ require 'gamefic/standard/actions/lock'
9
+ require 'gamefic/standard/actions/unlock'
10
+ require 'gamefic/standard/actions/go'
11
+ require 'gamefic/standard/actions/insert'
12
+ require 'gamefic/standard/actions/inventory'
13
+ require 'gamefic/standard/actions/leave'
14
+ require 'gamefic/standard/actions/look'
15
+ require 'gamefic/standard/actions/search'
16
+ require 'gamefic/standard/actions/place'
17
+ require 'gamefic/standard/actions/quit'
18
+ require 'gamefic/standard/actions/take'
19
+ require 'gamefic/standard/actions/move'
20
+ require 'gamefic/standard/actions/talk'
21
+ require 'gamefic/standard/actions/wait'
22
+ require 'gamefic/standard/actions/give'
23
+ require 'gamefic/standard/actions/repeat'
24
+ require 'gamefic/standard/actions/save-restore-undo'
25
+ require 'gamefic/standard/actions/pronouns'
26
+
27
+ module Gamefic
28
+ module Standard
29
+ module Actions
30
+ include Nil
31
+ include Attack
32
+ include Drop
33
+ include Enter
34
+ include Open
35
+ include Close
36
+ include Lock
37
+ include Unlock
38
+ include Go
39
+ include Insert
40
+ include Inventory
41
+ include Leave
42
+ include Look
43
+ include Search
44
+ include Place
45
+ include Quit
46
+ include Take
47
+ include Move
48
+ include Talk
49
+ include Wait
50
+ include Give
51
+ include Repeat
52
+ include SaveRestoreUndo
53
+ include Pronouns
54
+ include Gamefic::What
55
+ end
56
+ end
57
+ end
@@ -5,6 +5,8 @@ module Gamefic
5
5
  # Methods for adding definite and indefinite articles to entity names.
6
6
  #
7
7
  module Articles
8
+ extend Gamefic::Scriptable
9
+
8
10
  # Get a name for the entity with an indefinite article (unless the entity
9
11
  # has a proper name).
10
12
  #
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gamefic
4
+ module Standard
5
+ Character = Gamefic::Actor
6
+ Character.set_default gender: :other
7
+
8
+ class Character
9
+ def accessible
10
+ children.select { |child| child.is_a?(Scenery) }
11
+ end
12
+ end
13
+ end
14
+ end