gamefic-standard 2.4.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/rspec.yml +41 -40
- data/.rspec-opal +2 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +2 -0
- data/README.md +64 -60
- data/Rakefile +14 -6
- data/gamefic-standard.gemspec +6 -3
- data/lib/gamefic-standard/actions/attack.rb +28 -0
- data/lib/gamefic-standard/actions/close.rb +14 -10
- data/lib/gamefic-standard/actions/drop.rb +20 -16
- data/lib/gamefic-standard/actions/enter.rb +29 -19
- data/lib/gamefic-standard/actions/go.rb +51 -47
- data/lib/gamefic-standard/actions/help.rb +52 -0
- data/lib/gamefic-standard/actions/insert.rb +33 -29
- data/lib/gamefic-standard/actions/inventory.rb +12 -8
- data/lib/gamefic-standard/actions/leave.rb +43 -39
- data/lib/gamefic-standard/actions/lock.rb +21 -17
- data/lib/gamefic-standard/actions/look.rb +117 -96
- data/lib/gamefic-standard/actions/move.rb +24 -0
- data/lib/gamefic-standard/actions/nil.rb +16 -15
- data/lib/gamefic-standard/actions/open.rb +5 -5
- data/lib/gamefic-standard/actions/place.rb +4 -4
- data/lib/gamefic-standard/actions/quit.rb +4 -8
- data/lib/gamefic-standard/actions/repeat.rb +14 -0
- data/lib/gamefic-standard/actions/save-restore-undo.rb +18 -0
- data/lib/gamefic-standard/actions/search.rb +5 -5
- data/lib/gamefic-standard/actions/take.rb +15 -4
- data/lib/gamefic-standard/actions/talk.rb +16 -4
- data/lib/gamefic-standard/actions/unlock.rb +10 -6
- data/lib/gamefic-standard/actions/wait.rb +3 -1
- data/lib/gamefic-standard/actions.rb +5 -0
- data/lib/gamefic-standard/articles.rb +2 -7
- data/lib/gamefic-standard/direction.rb +2 -3
- data/lib/gamefic-standard/entities/container.rb +2 -0
- data/lib/gamefic-standard/entities/door.rb +2 -0
- data/lib/gamefic-standard/entities/fixture.rb +2 -1
- data/lib/gamefic-standard/entities/item.rb +2 -0
- data/lib/gamefic-standard/entities/portal.rb +2 -0
- data/lib/gamefic-standard/entities/receptacle.rb +2 -0
- data/lib/gamefic-standard/entities/room.rb +21 -36
- data/lib/gamefic-standard/entities/rubble.rb +2 -1
- data/lib/gamefic-standard/entities/scenery.rb +2 -0
- data/lib/gamefic-standard/entities/supporter.rb +2 -0
- data/lib/gamefic-standard/entities/thing.rb +2 -0
- data/lib/gamefic-standard/give.rb +15 -14
- data/lib/gamefic-standard/grammar/pronoun.rb +80 -80
- data/lib/gamefic-standard/introduction.rb +8 -0
- data/lib/gamefic-standard/modules/enterable.rb +2 -0
- data/lib/gamefic-standard/modules/lockable.rb +3 -1
- data/lib/gamefic-standard/modules/standardized.rb +10 -12
- data/lib/gamefic-standard/modules.rb +0 -1
- data/lib/gamefic-standard/queries.rb +7 -20
- data/lib/gamefic-standard/version.rb +1 -1
- data/lib/gamefic-standard.rb +26 -8
- data/spec-opal/spec_helper.rb +32 -0
- metadata +33 -13
- data/lib/gamefic-standard/modules/use.rb +0 -45
- data/lib/gamefic-standard/test.rb +0 -34
@@ -1,11 +1,11 @@
|
|
1
|
-
Gamefic.script do
|
2
|
-
respond :search,
|
1
|
+
Gamefic::Standard.script do
|
2
|
+
respond :search, available(Thing) do |actor, thing|
|
3
3
|
actor.execute :look, thing
|
4
4
|
end
|
5
5
|
|
6
|
-
respond :search,
|
6
|
+
respond :search, available(Receptacle) do |actor, thing|
|
7
7
|
if thing.accessible?
|
8
|
-
itemized = thing.children.that_are_not(
|
8
|
+
itemized = thing.children.that_are_not(proc(&:attached?)).that_are(proc(&:itemized?))
|
9
9
|
if itemized.empty?
|
10
10
|
actor.tell "There's nothing inside #{the thing}."
|
11
11
|
else
|
@@ -16,7 +16,7 @@ Gamefic.script do
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
respond :search,
|
19
|
+
respond :search, available(Container, proc(&:closed?)) do |actor, container|
|
20
20
|
actor.execute :open, container
|
21
21
|
actor.proceed if container.open?
|
22
22
|
end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
Gamefic.script do
|
2
|
-
respond :take,
|
1
|
+
Gamefic::Standard.script do
|
2
|
+
respond :take, available do |actor, thing|
|
3
3
|
if thing.parent == actor
|
4
4
|
actor.tell "You're already carrying #{the thing}."
|
5
5
|
elsif thing.portable?
|
@@ -14,14 +14,25 @@ Gamefic.script do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
respond :take,
|
17
|
+
respond :take, available(proc(&:attached?)) do |actor, thing|
|
18
18
|
actor.tell "#{The thing} is attached to #{the thing.parent}."
|
19
19
|
end
|
20
20
|
|
21
|
-
respond :take,
|
21
|
+
respond :take, available(Rubble) do |actor, rubble|
|
22
22
|
actor.tell "You don't have any use for #{the rubble}."
|
23
23
|
end
|
24
24
|
|
25
|
+
respond :take, plaintext(/^(all|everything)$/) do |actor, _all|
|
26
|
+
items = Gamefic::Scope::Family.matches(actor)
|
27
|
+
.select(&:portable?)
|
28
|
+
.reject { |item| actor.flatten.include?(item) }
|
29
|
+
if items.empty?
|
30
|
+
actor.tell "You don't see anything you can carry."
|
31
|
+
else
|
32
|
+
items.each { |item| actor.execute :take, item }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
25
36
|
interpret "get :thing", "take :thing"
|
26
37
|
interpret "pick up :thing", "take :thing"
|
27
38
|
interpret "pick :thing up", "take :thing"
|
@@ -1,20 +1,24 @@
|
|
1
|
-
Gamefic.script do
|
1
|
+
Gamefic::Standard.script do
|
2
2
|
respond :talk do |actor|
|
3
3
|
actor.tell "You talk to yourself."
|
4
4
|
end
|
5
5
|
|
6
|
-
respond :talk,
|
6
|
+
respond :talk, myself do |actor, yourself|
|
7
7
|
actor.execute :talk
|
8
8
|
end
|
9
9
|
|
10
|
-
respond :talk,
|
10
|
+
respond :talk, available do |actor, thing|
|
11
11
|
actor.tell "Nothing happens."
|
12
12
|
end
|
13
13
|
|
14
|
-
respond :talk,
|
14
|
+
respond :talk, Character do |actor, character|
|
15
15
|
actor.tell "#{The character} has nothing to say."
|
16
16
|
end
|
17
17
|
|
18
|
+
respond :talk, Character, plaintext do |actor, character, text|
|
19
|
+
actor.tell "#{The character} has nothing to say about #{text}."
|
20
|
+
end
|
21
|
+
|
18
22
|
interpret "talk to :character", "talk :character"
|
19
23
|
interpret "talk to :character about :subject", "talk :character :subject"
|
20
24
|
interpret "ask :character :subject", "talk :character :subject"
|
@@ -22,4 +26,12 @@ Gamefic.script do
|
|
22
26
|
interpret "tell :character :subject", "talk :character :subject"
|
23
27
|
interpret "tell :character about :subject", "talk :character :subject"
|
24
28
|
interpret "ask :character for :subject", "talk :character :subject"
|
29
|
+
interpret "speak :character", "talk :character"
|
30
|
+
interpret "speak to :character", "talk :character"
|
31
|
+
interpret "speak :character :subject", "talk :character :subject"
|
32
|
+
interpret "speak :character about :subject", "talk :character :subject"
|
33
|
+
interpret "speak to :character about :subject", "talk :character :subject"
|
34
|
+
interpret "speak to :character :subject", "talk :character :subject"
|
35
|
+
interpret "discuss :subject :character", "talk :character :subject"
|
36
|
+
interpret "discuss :subject with :character", "talk :character :subject"
|
25
37
|
end
|
@@ -1,18 +1,22 @@
|
|
1
|
-
Gamefic.script do
|
2
|
-
respond :unlock,
|
3
|
-
|
1
|
+
Gamefic::Standard.script do
|
2
|
+
respond :unlock, available(Lockable) do |actor, thing|
|
3
|
+
if thing.has_lock_key? && actor.children.include?(thing.lock_key)
|
4
|
+
actor.execute :unlock, thing, thing.lock_key
|
5
|
+
else
|
6
|
+
actor.tell "You can't unlock #{the thing}."
|
7
|
+
end
|
4
8
|
end
|
5
9
|
|
6
|
-
respond :unlock,
|
10
|
+
respond :unlock, available(Lockable, proc(&:has_lock_key?)), children do |actor, thing, key|
|
7
11
|
if thing.lock_key == key
|
8
12
|
thing.locked = false
|
9
|
-
actor.tell "You unlock
|
13
|
+
actor.tell "You unlock #{the thing} with #{the key}."
|
10
14
|
else
|
11
15
|
actor.tell "You can't unlock #{the thing} with #{the key}."
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
15
|
-
respond :unlock,
|
19
|
+
respond :unlock, available(Lockable, proc(&:has_lock_key?)), available do |actor, _thing, key|
|
16
20
|
actor.execute :take, key if key.parent != actor
|
17
21
|
actor.proceed if key.parent == actor
|
18
22
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'gamefic-standard/actions/nil'
|
2
|
+
require 'gamefic-standard/actions/attack'
|
2
3
|
require 'gamefic-standard/actions/drop'
|
3
4
|
require 'gamefic-standard/actions/enter'
|
4
5
|
require 'gamefic-standard/actions/open'
|
@@ -14,5 +15,9 @@ require 'gamefic-standard/actions/search'
|
|
14
15
|
require 'gamefic-standard/actions/place'
|
15
16
|
require 'gamefic-standard/actions/quit'
|
16
17
|
require 'gamefic-standard/actions/take'
|
18
|
+
require 'gamefic-standard/actions/move'
|
17
19
|
require 'gamefic-standard/actions/talk'
|
18
20
|
require 'gamefic-standard/actions/wait'
|
21
|
+
require 'gamefic-standard/actions/repeat'
|
22
|
+
require 'gamefic-standard/actions/help'
|
23
|
+
require 'gamefic-standard/actions/save-restore-undo'
|
@@ -1,6 +1,4 @@
|
|
1
1
|
class Direction
|
2
|
-
include Gamefic::Serialize
|
3
|
-
|
4
2
|
attr_writer :adjective, :adverb, :reverse
|
5
3
|
|
6
4
|
# @return [String]
|
@@ -51,10 +49,11 @@ class Direction
|
|
51
49
|
}
|
52
50
|
end
|
53
51
|
|
54
|
-
# @param dir [Direction,
|
52
|
+
# @param dir [Direction, String]
|
55
53
|
# @return [Direction, nil]
|
56
54
|
def find(dir)
|
57
55
|
return dir if dir.is_a?(Direction)
|
56
|
+
|
58
57
|
compass[dir.to_s.downcase.to_sym]
|
59
58
|
end
|
60
59
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Room < Thing
|
2
4
|
attr_writer :explicit_exits
|
3
5
|
|
@@ -11,10 +13,25 @@ class Room < Thing
|
|
11
13
|
children.each { |c| c.tell message }
|
12
14
|
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
# @return [Array<Portal>]
|
17
|
+
def portals
|
18
|
+
children.that_are(Portal)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param destination [Room]
|
22
|
+
# @param direction [Direction, String, nil]
|
23
|
+
# @param type [Class<Portal>]
|
24
|
+
# @param two_way [Boolean]
|
25
|
+
# @return [Portal, Array<Portal>]
|
26
|
+
def connect destination, direction: nil, type: Portal, two_way: true
|
27
|
+
direction = Direction.find(direction)
|
28
|
+
here = type.new(parent: self,
|
29
|
+
destination: destination,
|
30
|
+
direction: Direction.find(direction))
|
31
|
+
return here unless two_way
|
32
|
+
|
33
|
+
there = type.new(parent: destination, destination: self, direction: direction&.reverse)
|
34
|
+
[here, there]
|
18
35
|
end
|
19
36
|
|
20
37
|
class << self
|
@@ -27,35 +44,3 @@ class Room < Thing
|
|
27
44
|
end
|
28
45
|
end
|
29
46
|
end
|
30
|
-
|
31
|
-
# @todo Monkey patching might not be the best way to handle this. It's only
|
32
|
-
# necessary because of specs that make Plot#connect calls. Consider
|
33
|
-
# changing the specs instead.
|
34
|
-
module Gamefic::World
|
35
|
-
# Create portals between rooms.
|
36
|
-
#
|
37
|
-
# @return [Portal]
|
38
|
-
def connect origin, destination, direction = nil, type: Portal, two_way: true
|
39
|
-
if direction.nil?
|
40
|
-
portal = make type, :parent => origin, :destination => destination
|
41
|
-
if two_way == true
|
42
|
-
portal2 = make type, :parent => destination, :destination => origin
|
43
|
-
end
|
44
|
-
else
|
45
|
-
if direction.kind_of?(String)
|
46
|
-
direction = Direction.find(direction)
|
47
|
-
end
|
48
|
-
portal = make type, :direction => direction, :parent => origin, :destination => destination
|
49
|
-
portal.proper_named = true if type == Portal
|
50
|
-
if two_way == true
|
51
|
-
reverse = direction.reverse
|
52
|
-
if reverse == nil
|
53
|
-
raise "#{direction.name.cap_first} does not have an opposite direction"
|
54
|
-
end
|
55
|
-
portal2 = make type, :direction => reverse, :parent => destination, :destination => origin
|
56
|
-
portal2.proper_named = true if type == Portal
|
57
|
-
end
|
58
|
-
end
|
59
|
-
portal
|
60
|
-
end
|
61
|
-
end
|
@@ -1,20 +1,21 @@
|
|
1
|
-
Gamefic
|
2
|
-
|
3
|
-
actor.tell 'Nothing happens.'
|
4
|
-
end
|
1
|
+
module Gamefic::Standard::Give
|
2
|
+
extend Gamefic::Scriptable
|
5
3
|
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
script do
|
5
|
+
respond :give, available, children do |actor, _character, _gift|
|
6
|
+
actor.tell 'Nothing happens.'
|
7
|
+
end
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
actor.execute :take, gift
|
9
|
+
respond :give, available(Character), available do |actor, character, gift|
|
10
|
+
actor.tell "#{The character} doesn't want #{the gift}."
|
13
11
|
end
|
14
|
-
|
15
|
-
|
12
|
+
|
13
|
+
respond :give, available(Character), available do |actor, _character, gift|
|
14
|
+
actor.execute :take, gift if gift.parent != actor
|
15
|
+
|
16
|
+
actor.proceed if gift.parent == actor
|
16
17
|
end
|
17
|
-
end
|
18
18
|
|
19
|
-
|
19
|
+
interpret 'give :gift to :character', 'give :character :gift'
|
20
|
+
end
|
20
21
|
end
|
@@ -5,97 +5,97 @@ module Grammar
|
|
5
5
|
# gender.
|
6
6
|
#
|
7
7
|
module Pronoun
|
8
|
-
|
9
|
-
# @param entity [#person, #plural?, #gender]
|
10
|
-
# @return [String]
|
11
|
-
def subjective(entity)
|
12
|
-
map(entity)[:subjective]
|
13
|
-
end
|
14
|
-
alias they subjective
|
15
|
-
alias he subjective
|
16
|
-
alias she subjective
|
8
|
+
extend self
|
17
9
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
10
|
+
# @param entity [#person, #plural?, #gender]
|
11
|
+
# @return [String]
|
12
|
+
def subjective(entity)
|
13
|
+
map(entity)[:subjective]
|
14
|
+
end
|
15
|
+
alias they subjective
|
16
|
+
alias he subjective
|
17
|
+
alias she subjective
|
26
18
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
19
|
+
# @param entity [#person, #plural?, #gender]
|
20
|
+
# @return [String]
|
21
|
+
def subjective_(entity)
|
22
|
+
subjective(entity).cap_first
|
23
|
+
end
|
24
|
+
alias they_ subjective_
|
25
|
+
alias he_ subjective_
|
26
|
+
alias she_ subjective_
|
33
27
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
28
|
+
# @param entity [#person, #plural?, #gender]
|
29
|
+
# @return [String]
|
30
|
+
def objective(entity)
|
31
|
+
map(entity)[:objective]
|
32
|
+
end
|
33
|
+
alias them objective
|
40
34
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
35
|
+
# @param entity [#person, #plural?, #gender]
|
36
|
+
# @return [String]
|
37
|
+
def objective_(entity)
|
38
|
+
objective(entity).cap_first
|
39
|
+
end
|
40
|
+
alias them_ objective_
|
47
41
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
42
|
+
# @param entity [#person, #plural?, #gender]
|
43
|
+
# @return [String]
|
44
|
+
def possessive(entity)
|
45
|
+
map(entity)[:possessive]
|
46
|
+
end
|
47
|
+
alias their possessive
|
54
48
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
alias themself reflexive
|
49
|
+
# @param entity [#person, #plural?, #gender]
|
50
|
+
# @return [String]
|
51
|
+
def possessive_(entity)
|
52
|
+
possessive(entity).cap_first
|
53
|
+
end
|
54
|
+
alias their_ possessive_
|
62
55
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
56
|
+
# @param entity [#person, #plural?, #gender]
|
57
|
+
# @return [String]
|
58
|
+
def reflexive(entity)
|
59
|
+
map(entity)[:reflexive]
|
60
|
+
end
|
61
|
+
alias themselves reflexive
|
62
|
+
alias themself reflexive
|
70
63
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
64
|
+
# @param entity [#person, #plural?, #gender]
|
65
|
+
# @return [String]
|
66
|
+
def reflexive_(entity)
|
67
|
+
reflexive(entity).cap_first
|
68
|
+
end
|
69
|
+
alias themselves_ reflexive_
|
70
|
+
alias themself_ reflexive_
|
78
71
|
|
79
|
-
|
72
|
+
# @param entity [#person, #plural?, #gender]
|
73
|
+
# @return [Hash]
|
74
|
+
def map(entity)
|
75
|
+
plurality = (entity.plural? ? :plural : :singular)
|
76
|
+
maps[[(entity.person || 3), plurality, entity.gender]] ||
|
77
|
+
maps[[(entity.person || 3), plurality]]
|
78
|
+
end
|
80
79
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
80
|
+
private
|
81
|
+
|
82
|
+
def maps
|
83
|
+
@maps ||= {
|
84
|
+
[1, :singular] => Hash[map_keys.zip(%w[I me my myself])],
|
85
|
+
[2, :singular] => Hash[map_keys.zip(%w[you you your yourself])],
|
86
|
+
[3, :singular] => Hash[map_keys.zip(%w[it it its itself])],
|
87
|
+
[3, :singular, :male] => Hash[map_keys.zip(%w[he him his himself])],
|
88
|
+
[3, :singular, :female] => Hash[map_keys.zip(%w[she her her herself])],
|
89
|
+
[3, :singular, :other] => Hash[map_keys.zip(%w[they them their themselves])],
|
90
|
+
[3, :singular, :neutral] => Hash[map_keys.zip(%w[it it its itself])],
|
91
|
+
[1, :plural] => Hash[map_keys.zip(%w[we us our ourselves])],
|
92
|
+
[2, :plural] => Hash[map_keys.zip(%w[you you your yourselves])],
|
93
|
+
[3, :plural] => Hash[map_keys.zip(%w[they them their themselves])]
|
94
|
+
}
|
95
|
+
end
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
end
|
97
|
+
def map_keys
|
98
|
+
@map_keys ||= %i[subjective objective possessive reflexive]
|
99
99
|
end
|
100
100
|
end
|
101
101
|
end
|
@@ -8,13 +8,15 @@ module Lockable
|
|
8
8
|
def locked=(bool)
|
9
9
|
@locked = bool
|
10
10
|
if @locked == true
|
11
|
-
|
11
|
+
@open = false
|
12
12
|
end
|
13
|
+
@locked
|
13
14
|
end
|
14
15
|
|
15
16
|
def open=(bool)
|
16
17
|
@open = bool
|
17
18
|
@locked = false if @open == true
|
19
|
+
@open
|
18
20
|
end
|
19
21
|
|
20
22
|
def locked?
|
@@ -32,16 +32,16 @@ module Standardized
|
|
32
32
|
end
|
33
33
|
|
34
34
|
# @param bool [Boolean]
|
35
|
-
def attached=
|
35
|
+
def attached=(bool)
|
36
36
|
@attached = if parent.nil?
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
# @todo Log attachment failure
|
38
|
+
false
|
39
|
+
else
|
40
|
+
bool
|
41
|
+
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def parent=
|
44
|
+
def parent=(new_parent)
|
45
45
|
self.attached = false unless new_parent == parent
|
46
46
|
super
|
47
47
|
end
|
@@ -50,10 +50,8 @@ module Standardized
|
|
50
50
|
#
|
51
51
|
# @return [Room]
|
52
52
|
def room
|
53
|
-
|
54
|
-
until
|
55
|
-
|
56
|
-
end
|
57
|
-
p
|
53
|
+
ascendant = parent
|
54
|
+
ascendant = ascendant.parent until ascendant.is_a?(Room) || ascendant.nil?
|
55
|
+
ascendant
|
58
56
|
end
|
59
57
|
end
|