gamefic 0.1.1 → 0.2.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 +4 -4
- data/lib/gamefic/action.rb +7 -6
- data/lib/gamefic/before.rb +12 -0
- data/lib/gamefic/character.rb +1 -1
- data/lib/gamefic/core_ext/array.rb +4 -0
- data/lib/gamefic/core_ext/string.rb +0 -31
- data/lib/gamefic/describable.rb +68 -8
- data/lib/gamefic/director.rb +108 -75
- data/lib/gamefic/engine.rb +74 -10
- data/lib/gamefic/entity.rb +3 -3
- data/lib/gamefic/import/basics/actions/close.rb +16 -0
- data/lib/gamefic/import/basics/actions/commands.rb +3 -0
- data/lib/gamefic/import/basics/actions/drop-in.rb +17 -0
- data/lib/gamefic/import/basics/actions/drop-on.rb +16 -0
- data/lib/gamefic/import/basics/actions/drop.rb +30 -0
- data/lib/gamefic/import/basics/actions/enter.rb +16 -0
- data/lib/gamefic/import/basics/actions/{traversal.rb → go.rb} +35 -35
- data/lib/gamefic/import/basics/actions/inventory.rb +8 -49
- data/lib/gamefic/import/basics/actions/leave.rb +29 -0
- data/lib/gamefic/import/basics/actions/look-in-at.rb +27 -0
- data/lib/gamefic/import/basics/actions/look-under.rb +3 -0
- data/lib/gamefic/import/basics/actions/look.rb +71 -67
- data/lib/gamefic/import/basics/actions/nil.rb +25 -0
- data/lib/gamefic/import/basics/actions/open.rb +23 -0
- data/lib/gamefic/import/basics/actions/quit.rb +3 -0
- data/lib/gamefic/import/basics/actions/take.rb +107 -0
- data/lib/gamefic/import/basics/entities/container.rb +8 -24
- data/lib/gamefic/import/basics/entities/entity.rb +11 -0
- data/lib/gamefic/import/basics/entities/fixture.rb +5 -5
- data/lib/gamefic/import/basics/entities/item.rb +5 -7
- data/lib/gamefic/import/basics/entities/portal.rb +40 -43
- data/lib/gamefic/import/basics/entities/room.rb +30 -24
- data/lib/gamefic/import/basics/entities/scenery.rb +5 -3
- data/lib/gamefic/import/basics/entities/supporter.rb +6 -0
- data/lib/gamefic/import/basics/entities/thing.rb +16 -0
- data/lib/gamefic/import/basics/queries/reachable.rb +38 -0
- data/lib/gamefic/import/basics/queries/room.rb +8 -0
- data/lib/gamefic/import/basics/queries/visible.rb +32 -0
- data/lib/gamefic/import/basics/rules/has-enough-light.rb +14 -0
- data/lib/gamefic/import/{basics → basics.old}/actions/container.rb +13 -12
- data/lib/gamefic/import/basics.old/actions/inventory.rb +50 -0
- data/lib/gamefic/import/basics.old/actions/look.rb +53 -0
- data/lib/gamefic/import/basics.old/actions/meta.rb +6 -0
- data/lib/gamefic/import/basics.old/actions/traversal.rb +35 -0
- data/lib/gamefic/import/{basics → basics.old}/actions.rb +0 -0
- data/lib/gamefic/import/basics.old/entities/container.rb +3 -0
- data/lib/gamefic/import/basics.old/entities/fixture.rb +3 -0
- data/lib/gamefic/import/basics.old/entities/item.rb +3 -0
- data/lib/gamefic/import/basics.old/entities/portal.rb +43 -0
- data/lib/gamefic/import/basics.old/entities/room.rb +27 -0
- data/lib/gamefic/import/basics.old/entities/scenery.rb +3 -0
- data/lib/gamefic/import/basics.old/entities/supporter.rb +3 -0
- data/lib/gamefic/import/{basics → basics.old}/entities.rb +0 -0
- data/lib/gamefic/import/basics.old/room_modes.rb +48 -0
- data/lib/gamefic/import/basics.rb +6 -2
- data/lib/gamefic/import/{basics/room_modes.rb → room_modes.rb} +6 -6
- data/lib/gamefic/import/standard.rb +1 -0
- data/lib/gamefic/meta.rb +12 -0
- data/lib/gamefic/optionset.rb +114 -0
- data/lib/gamefic/plot.rb +54 -21
- data/lib/gamefic/query.rb +214 -188
- data/lib/gamefic/requirement.rb +14 -0
- data/lib/gamefic/shell.rb +7 -4
- data/lib/gamefic/syntax.rb +35 -18
- data/lib/gamefic/thing.rb +7 -0
- data/lib/gamefic.rb +5 -1
- metadata +46 -12
- data/lib/gamefic/import/basics/actions/meta.rb +0 -6
- data/lib/gamefic/import/basics/entities/itemized.rb +0 -3
- data/lib/gamefic/import/basics/entities/portable.rb +0 -3
- data/lib/gamefic/user.rb +0 -66
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdcd6a0fe04e0a8bbe946261ff8284fb4667e2f7
|
4
|
+
data.tar.gz: 98bafd885d73b32653194ca36ad50285e2656d45
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5cef4896f4506c22cbc82dff02846805b64b8062ccc90ead1e9aeeac1df9e9cc50a2a79bffd0159da33896f497bb2ce4bdeec68a45c7bef715384846e2c9a842
|
7
|
+
data.tar.gz: 2d2f4b0df8f65e54d1da9826e4e4ca1febf3b9a5858f200f81c4163afbbfd75502c8ceb187a4f7db102135683843bfe0dc3f2d6fd5bca258988f60e85a8e69ee
|
data/lib/gamefic/action.rb
CHANGED
@@ -5,9 +5,10 @@ module Gamefic
|
|
5
5
|
@@defaults = Array.new
|
6
6
|
@@order_key_seed = 0
|
7
7
|
def initialize(story, command, *queries, &proc)
|
8
|
+
@plot = story
|
8
9
|
@order_key = @@order_key_seed
|
9
10
|
@@order_key_seed += 1
|
10
|
-
if (command.kind_of?(Symbol) == false)
|
11
|
+
if (command.kind_of?(Symbol) == false and !command.nil?)
|
11
12
|
raise "Action commands must be symbols"
|
12
13
|
end
|
13
14
|
if (queries.length + 1 != proc.arity) and (queries.length == 0 and proc.arity != -1)
|
@@ -29,12 +30,12 @@ module Gamefic
|
|
29
30
|
spec = 0
|
30
31
|
magnitude = 1
|
31
32
|
@queries.each { |q|
|
32
|
-
if q.kind_of?(Query)
|
33
|
+
if q.kind_of?(Query::Base)
|
33
34
|
spec += (q.specificity * magnitude)
|
34
35
|
else
|
35
36
|
spec += magnitude
|
36
37
|
end
|
37
|
-
magnitude = magnitude * 10
|
38
|
+
#magnitude = magnitude * 10
|
38
39
|
}
|
39
40
|
return spec
|
40
41
|
end
|
@@ -44,9 +45,9 @@ module Gamefic
|
|
44
45
|
def queries
|
45
46
|
@queries
|
46
47
|
end
|
47
|
-
|
48
|
-
|
49
|
-
|
48
|
+
def execute *args
|
49
|
+
@proc.call *args
|
50
|
+
end
|
50
51
|
private
|
51
52
|
def self.explode(entity)
|
52
53
|
arr = Array.new
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# Before Actions are processed before Rules. Their primary use is to determine
|
2
|
+
# whether or not a particular Action (or thread of Actions) should be allowed
|
3
|
+
# to happen. A Before Action's proc can use the pass and deny methods to
|
4
|
+
# override the results of rule assertions.
|
5
|
+
|
6
|
+
module Gamefic
|
7
|
+
|
8
|
+
class Before < Action
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
data/lib/gamefic/character.rb
CHANGED
@@ -2,6 +2,8 @@ class Array
|
|
2
2
|
def that_are(cls)
|
3
3
|
if (cls.kind_of?(Class) or cls.kind_of?(Module))
|
4
4
|
return self.clone.delete_if { |i| i.kind_of?(cls) == false }
|
5
|
+
elsif cls.kind_of?(Symbol)
|
6
|
+
return self.clone.delete_if { |i| i.option_selected?(cls) == false }
|
5
7
|
else
|
6
8
|
if self.include?(cls)
|
7
9
|
return [cls]
|
@@ -12,6 +14,8 @@ class Array
|
|
12
14
|
def that_are_not(cls)
|
13
15
|
if (cls.kind_of?(Class) or cls.kind_of?(Module))
|
14
16
|
return self.clone.delete_if { |i| i.kind_of?(cls) == true }
|
17
|
+
elsif cls.kind_of?(Symbol)
|
18
|
+
return self.clone.delete_if { |i| i.option_selected?(cls) == true }
|
15
19
|
else
|
16
20
|
return self.clone - [cls]
|
17
21
|
end
|
@@ -5,37 +5,6 @@ class String
|
|
5
5
|
def cap_first
|
6
6
|
self.capitalize_first
|
7
7
|
end
|
8
|
-
def specify
|
9
|
-
if self[0,2] == 'a ' or self[0,3] == 'an '
|
10
|
-
return "the #{self.split(' ')[1..-1].join(' ')}"
|
11
|
-
end
|
12
|
-
if self[0,2] == 'A ' or self[0,3] == 'An '
|
13
|
-
return "The #{self.split(' ')[1..-1].join(' ')}"
|
14
|
-
end
|
15
|
-
return self
|
16
|
-
end
|
17
|
-
def terminalize
|
18
|
-
output = ''
|
19
|
-
lines = self.split("\n")
|
20
|
-
lines.each { |line|
|
21
|
-
if line.size > 79
|
22
|
-
while (line.size > 79)
|
23
|
-
offset = line.rindex(/[\s\-]/, 79)
|
24
|
-
if (offset == 0 or offset == nil)
|
25
|
-
output = output + line + "\n"
|
26
|
-
line = ''
|
27
|
-
else
|
28
|
-
output = output + line[0,offset + 1] + "\n"
|
29
|
-
line = line[offset + 1, line.size - offset]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
output = output + line + "\n"
|
33
|
-
else
|
34
|
-
output = output + line + "\n"
|
35
|
-
end
|
36
|
-
}
|
37
|
-
return output
|
38
|
-
end
|
39
8
|
def split_words
|
40
9
|
self.gsub(/ +/, ' ').strip.split
|
41
10
|
end
|
data/lib/gamefic/describable.rb
CHANGED
@@ -3,25 +3,85 @@ require "gamefic/keywords"
|
|
3
3
|
module Gamefic
|
4
4
|
|
5
5
|
module Describable
|
6
|
-
|
6
|
+
attr_reader :name
|
7
|
+
attr_accessor :synonyms, :indefinite_article
|
8
|
+
attr_writer :definite_article
|
7
9
|
def keywords
|
8
|
-
Keywords.new "#{name} #{
|
10
|
+
Keywords.new "#{name} #{synonyms}"
|
9
11
|
end
|
10
12
|
def keywords=(value)
|
11
13
|
@keywords = value
|
12
14
|
end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
def indefinitely
|
16
|
+
(proper_named? ? '' : "#{indefinite_article} ") + name
|
17
|
+
end
|
18
|
+
def definitely
|
19
|
+
(proper_named? ? '' : "#{definite_article} ") + name
|
20
|
+
end
|
21
|
+
def definite_article
|
22
|
+
@definite_article || "the"
|
23
|
+
end
|
24
|
+
def proper_named?
|
25
|
+
(@proper_named == true)
|
26
|
+
end
|
27
|
+
def proper_named=(value)
|
28
|
+
if value == true
|
29
|
+
if @definite_article != nil
|
30
|
+
@name = "#{@definite_article} #{@name}"
|
31
|
+
@definite_article = nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
@proper_named = value
|
35
|
+
end
|
36
|
+
def name=(value)
|
37
|
+
# TODO: Split article from name
|
38
|
+
words = value.split_words
|
39
|
+
if ['a','an'].include?(words[0].downcase)
|
40
|
+
@indefinite_article = words[0].downcase
|
41
|
+
@definite_article = 'the'
|
42
|
+
value = value[words[0].length+1..-1].strip
|
43
|
+
else
|
44
|
+
if words[0].downcase == 'the'
|
45
|
+
@definite_article = 'the'
|
46
|
+
value = value[4..-1].strip
|
47
|
+
end
|
48
|
+
# Try to guess the indefinite article
|
49
|
+
if ['a','e','i','o','u'].include?(value[0,1].downcase)
|
50
|
+
@indefinite_article = 'an'
|
51
|
+
else
|
52
|
+
@indefinite_article = 'a'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
@name = value
|
56
|
+
end
|
19
57
|
def description
|
20
58
|
@description.to_s != '' ? @description : "Nothing special."
|
21
59
|
end
|
22
60
|
def description=(value)
|
23
61
|
@description = value
|
24
62
|
end
|
63
|
+
def to_s
|
64
|
+
indefinitely
|
65
|
+
end
|
25
66
|
end
|
26
67
|
|
68
|
+
def self.a(entity)
|
69
|
+
entity.indefinitely
|
70
|
+
end
|
71
|
+
def self.an(entity)
|
72
|
+
entity.indefinitely
|
73
|
+
end
|
74
|
+
def self.the(entity)
|
75
|
+
entity.definitely
|
76
|
+
end
|
77
|
+
def self.A(entity)
|
78
|
+
entity.indefinitely.cap_first
|
79
|
+
end
|
80
|
+
def self.An(entity)
|
81
|
+
entity.indefinitely.cap_first
|
82
|
+
end
|
83
|
+
def self.The(entity)
|
84
|
+
entity.definitely.cap_first
|
85
|
+
end
|
86
|
+
|
27
87
|
end
|
data/lib/gamefic/director.rb
CHANGED
@@ -3,32 +3,24 @@ module Gamefic
|
|
3
3
|
class Director
|
4
4
|
def self.dispatch(actor, command)
|
5
5
|
command.strip!
|
6
|
-
|
7
|
-
|
8
|
-
if verbs.include?(first) == false
|
9
|
-
possibles = []
|
10
|
-
verbs.each { |v|
|
11
|
-
if v.start_with?(first)
|
12
|
-
possibles.push v
|
13
|
-
end
|
14
|
-
}
|
15
|
-
if possibles.length == 1
|
16
|
-
command = possibles[0] + command[first.length..-1]
|
17
|
-
else
|
18
|
-
if possibles.length > 1
|
19
|
-
actor.tell "'#{first.cap_first}' is ambiguous."
|
20
|
-
else
|
21
|
-
actor.tell "I don't understand '#{first}' as a command."
|
22
|
-
end
|
23
|
-
return
|
24
|
-
end
|
6
|
+
if command.to_s == ''
|
7
|
+
return
|
25
8
|
end
|
26
|
-
|
9
|
+
begin
|
10
|
+
handlers = Syntax.match(command, actor.plot)
|
11
|
+
rescue Exception => e
|
12
|
+
puts "#{e}"
|
13
|
+
return
|
14
|
+
end
|
15
|
+
befores = Array.new
|
27
16
|
options = Array.new
|
28
17
|
handlers.each { |handler|
|
29
18
|
actions = actor.plot.commands[handler.command]
|
30
19
|
if actions != nil
|
31
20
|
actions.each { |action|
|
21
|
+
if action.queries.length == 0 and handler.arguments.length > 0
|
22
|
+
next
|
23
|
+
end
|
32
24
|
orders = bind_contexts_in_result(actor, handler, action)
|
33
25
|
orders.each { |order|
|
34
26
|
args = Array.new
|
@@ -37,38 +29,42 @@ module Gamefic
|
|
37
29
|
if a.length > 1
|
38
30
|
longnames = Array.new
|
39
31
|
a.each { |b|
|
40
|
-
longnames.push b.
|
32
|
+
longnames.push "#{b.definitely}"
|
41
33
|
}
|
42
|
-
actor.tell "I don't know which you mean: #{longnames.
|
34
|
+
actor.tell "I don't know which you mean: #{longnames.join_and(', ', ' or ')}."
|
43
35
|
return
|
44
36
|
end
|
45
37
|
args.push a[0]
|
46
38
|
}
|
47
|
-
|
39
|
+
if order.action.kind_of?(Before)
|
40
|
+
befores.push [order.action, args]
|
41
|
+
else
|
42
|
+
options.push [order.action, args]
|
43
|
+
end
|
48
44
|
}
|
49
45
|
}
|
50
46
|
end
|
51
47
|
}
|
52
|
-
|
53
|
-
Proc.new { |actor|
|
54
|
-
first = command.split(' ')[0].downcase
|
55
|
-
if actor.plot.commandwords.include?(first)
|
56
|
-
actor.tell "I know the verb '#{first}' but couldn't understand the rest of your sentence."
|
57
|
-
else
|
58
|
-
actor.tell "I don't understand '#{first}' as a command."
|
59
|
-
end
|
60
|
-
}, [actor], -1
|
61
|
-
])
|
62
|
-
del = Delegate.new(options)
|
48
|
+
del = Delegate.new(actor, befores, options)
|
63
49
|
del.execute
|
64
50
|
end
|
65
51
|
private
|
66
52
|
def self.bind_contexts_in_result(actor, handler, action)
|
53
|
+
queries = action.queries.clone
|
54
|
+
objects = self.execute_query(actor, handler.arguments.clone, queries, action)
|
55
|
+
num_nil = 0
|
56
|
+
while objects.length == 0 and queries.last.optional?
|
57
|
+
num_nil +=1
|
58
|
+
queries.pop
|
59
|
+
objects = self.execute_query(actor, handler.arguments.clone, queries, action, num_nil)
|
60
|
+
end
|
61
|
+
return objects
|
62
|
+
end
|
63
|
+
def self.execute_query(actor, arguments, queries, action, num_nil = 0)
|
64
|
+
prepared = Array.new
|
67
65
|
objects = Array.new
|
68
66
|
valid = true
|
69
|
-
|
70
|
-
arguments = handler.arguments.clone
|
71
|
-
action.queries.each { |context|
|
67
|
+
queries.clone.each { |context|
|
72
68
|
arg = arguments.shift
|
73
69
|
if arg == nil or arg == ''
|
74
70
|
valid = false
|
@@ -76,25 +72,12 @@ module Gamefic
|
|
76
72
|
end
|
77
73
|
if context == String
|
78
74
|
prepared.push [arg]
|
79
|
-
elsif context.kind_of?(Query)
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
end
|
86
|
-
if arg == 'it' and actor.object_of_pronoun != nil
|
87
|
-
result = context.execute(last[0], "#{actor.object_of_pronoun.longname}")
|
88
|
-
else
|
89
|
-
result = context.execute(last[0], arg)
|
90
|
-
end
|
91
|
-
else
|
92
|
-
if arg == 'it' and actor.object_of_pronoun != nil
|
93
|
-
result = context.execute(actor, "#{actor.object_of_pronoun.longname}")
|
94
|
-
else
|
95
|
-
result = context.execute(actor, arg)
|
96
|
-
end
|
97
|
-
end
|
75
|
+
elsif context.kind_of?(Query::Base)
|
76
|
+
if arg == 'it' and actor.object_of_pronoun != nil
|
77
|
+
result = context.execute(actor, "#{actor.object_of_pronoun.name}")
|
78
|
+
else
|
79
|
+
result = context.execute(actor, arg)
|
80
|
+
end
|
98
81
|
if result.objects.length == 0
|
99
82
|
valid = false
|
100
83
|
next
|
@@ -113,43 +96,97 @@ module Gamefic
|
|
113
96
|
prepared.each { |p|
|
114
97
|
p.uniq!
|
115
98
|
}
|
99
|
+
num_nil.times do
|
100
|
+
prepared.push [nil]
|
101
|
+
end
|
116
102
|
objects.push Order.new(action, prepared)
|
117
103
|
end
|
118
|
-
|
119
|
-
|
104
|
+
objects
|
105
|
+
end
|
120
106
|
end
|
121
107
|
|
122
108
|
class Director
|
123
109
|
class Delegate
|
110
|
+
@@assertion_stack = Array.new
|
124
111
|
@@delegation_stack = Array.new
|
125
|
-
def initialize(
|
126
|
-
|
112
|
+
def initialize(actor, befores, actions)
|
113
|
+
@actor = actor
|
114
|
+
@befores = befores
|
115
|
+
@actions = actions
|
127
116
|
end
|
128
117
|
def execute
|
129
|
-
|
130
|
-
|
131
|
-
|
118
|
+
@@assertion_stack.push Hash.new
|
119
|
+
@@delegation_stack.push @befores
|
120
|
+
handle @befores
|
121
|
+
@@delegation_stack.pop
|
122
|
+
if @@assertion_stack.last[:everything] == false
|
123
|
+
@@assertion_stack.pop
|
124
|
+
return
|
125
|
+
end
|
126
|
+
result = true
|
127
|
+
@@delegation_stack.push @actions
|
128
|
+
# Nil commands pass assertions to facilitate error messages.
|
129
|
+
if @@assertion_stack.last[:everything] != true and Director::Delegate.next_command != nil
|
130
|
+
@actor.plot.rules.each { |k, v|
|
131
|
+
if @@assertion_stack.last[k] == true
|
132
|
+
next
|
133
|
+
elsif @@assertion_stack.last[k] == false
|
134
|
+
result = false
|
135
|
+
break
|
136
|
+
end
|
137
|
+
result = v.test(@actor)
|
138
|
+
if result == false
|
139
|
+
break
|
140
|
+
end
|
141
|
+
result = true
|
142
|
+
}
|
143
|
+
end
|
144
|
+
@@assertion_stack.pop
|
145
|
+
if result == true
|
146
|
+
handle @actions
|
147
|
+
end
|
148
|
+
@@delegation_stack.pop
|
149
|
+
end
|
150
|
+
def handle options
|
151
|
+
if options.length > 0
|
152
|
+
opt = options.shift
|
132
153
|
if opt[1].length == 1
|
133
|
-
opt[0].
|
154
|
+
opt[0].execute(opt[1][0])
|
155
|
+
opt[1][0].object_of_pronoun = nil
|
134
156
|
else
|
135
|
-
if opt[1].length == 2 and opt[1][1].kind_of?(Entity)
|
157
|
+
if opt[1].length == 2 and opt[1][1].kind_of?(Entity) and opt[1][0].parent != opt[1][1]
|
136
158
|
opt[1][0].object_of_pronoun = opt[1][1]
|
137
|
-
|
159
|
+
elsif opt[1][0].parent == opt[1][1]
|
138
160
|
opt[1][0].object_of_pronoun = nil
|
139
161
|
end
|
140
|
-
opt[0].
|
162
|
+
opt[0].execute(opt[1])
|
141
163
|
end
|
142
164
|
end
|
143
|
-
|
144
|
-
|
165
|
+
end
|
166
|
+
def self.pass requirement
|
167
|
+
@@assertion_stack.last[requirement] = true
|
168
|
+
end
|
169
|
+
def self.deny requirement
|
170
|
+
@@assertion_stack.last[requirement] = false
|
171
|
+
end
|
172
|
+
def self.next_command
|
173
|
+
return nil if @@delegation_stack.last.nil? or @@delegation_stack.last[0].length == 0
|
174
|
+
return @@delegation_stack.last[0][0].command
|
175
|
+
end
|
145
176
|
def self.passthru
|
146
177
|
if @@delegation_stack.last != nil
|
147
178
|
if @@delegation_stack.last.length > 0
|
148
179
|
opt = @@delegation_stack.last.shift
|
149
180
|
if opt[1].length == 1
|
150
|
-
opt[0].
|
181
|
+
opt[0].execute(opt[1][0])
|
182
|
+
opt[1][0].object_of_pronoun = nil
|
151
183
|
else
|
152
|
-
|
184
|
+
if opt[1].length == 2 and opt[1][1].kind_of?(Entity) and opt[1][0].parent != opt[1][1]
|
185
|
+
opt[1][0].object_of_pronoun = opt[1][1]
|
186
|
+
elsif opt[1][0].parent == opt[1][1]
|
187
|
+
opt[1][0].object_of_pronoun = nil
|
188
|
+
end
|
189
|
+
opt[0].execute(opt[1])
|
153
190
|
end
|
154
191
|
end
|
155
192
|
end
|
@@ -164,8 +201,4 @@ module Gamefic
|
|
164
201
|
end
|
165
202
|
end
|
166
203
|
|
167
|
-
def self.passthru
|
168
|
-
Director::Delegate.passthru
|
169
|
-
end
|
170
|
-
|
171
204
|
end
|
data/lib/gamefic/engine.rb
CHANGED
@@ -3,18 +3,82 @@ module Gamefic
|
|
3
3
|
class Engine
|
4
4
|
def initialize(plot)
|
5
5
|
@plot = plot
|
6
|
+
post_initialize
|
6
7
|
end
|
8
|
+
def post_initialize
|
9
|
+
@user = User.new @plot
|
10
|
+
end
|
7
11
|
def run
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
12
|
+
@plot.introduce @user.character
|
13
|
+
while @user.character.state.kind_of?(GameOverState) == false
|
14
|
+
tick
|
15
|
+
end
|
16
|
+
end
|
17
|
+
def tick
|
18
|
+
proc {
|
19
|
+
$SAFE = Gamefic.safe_level
|
20
|
+
@user.stream.select @user.character.state.prompt
|
21
|
+
@user.state.update
|
22
|
+
@plot.update
|
23
|
+
}.call
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class User
|
28
|
+
attr_reader :state, :character, :story
|
29
|
+
def initialize(plot)
|
30
|
+
@plot = plot
|
31
|
+
@character = Character.new @plot, :name => 'yourself', :synonyms => 'self myself you me'
|
32
|
+
@character.connect self
|
33
|
+
post_initialize
|
34
|
+
end
|
35
|
+
def post_initialize
|
36
|
+
@stream = UserStream.new
|
37
|
+
@state = UserState.new self
|
38
|
+
end
|
39
|
+
def stream
|
40
|
+
@stream ||= UserStream.new
|
41
|
+
end
|
42
|
+
def state
|
43
|
+
@state ||= UserState.new(self)
|
44
|
+
end
|
45
|
+
def state=(state_class)
|
46
|
+
@state = state_class.new self
|
47
|
+
end
|
48
|
+
def refresh
|
49
|
+
# Nothing to do
|
50
|
+
end
|
51
|
+
def quit
|
52
|
+
#exit
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class UserStream
|
57
|
+
def initialize
|
58
|
+
@queue = Array.new
|
59
|
+
end
|
60
|
+
def send(data)
|
61
|
+
puts data
|
62
|
+
end
|
63
|
+
def select(prompt)
|
64
|
+
print prompt
|
65
|
+
line = STDIN.gets
|
66
|
+
@queue.push line.strip
|
67
|
+
end
|
68
|
+
def recv
|
69
|
+
@queue.shift
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
class UserState
|
74
|
+
attr_reader :user
|
75
|
+
def initialize(user)
|
76
|
+
@user = user
|
77
|
+
end
|
78
|
+
def update
|
79
|
+
line = @user.stream.recv
|
80
|
+
if line != nil
|
81
|
+
@user.character.queue.push line
|
18
82
|
end
|
19
83
|
end
|
20
84
|
end
|
data/lib/gamefic/entity.rb
CHANGED
@@ -8,6 +8,8 @@ module Gamefic
|
|
8
8
|
class Entity
|
9
9
|
include Branch
|
10
10
|
include Describable
|
11
|
+
include OptionSettings
|
12
|
+
attr_writer :option_array
|
11
13
|
attr_reader :session, :plot
|
12
14
|
def initialize(plot, args = {})
|
13
15
|
if (plot.kind_of?(Plot) == false)
|
@@ -17,6 +19,7 @@ module Gamefic
|
|
17
19
|
#self.state = State
|
18
20
|
#@story = Subplot.current
|
19
21
|
@plot = plot
|
22
|
+
@option_mapper = @plot
|
20
23
|
@plot.send :add_entity, self
|
21
24
|
#@story.add_entity self
|
22
25
|
args.each { |key, value|
|
@@ -49,9 +52,6 @@ module Gamefic
|
|
49
52
|
#TODO: Should this even be here? In all likelihood, only Characters receive tells, right?
|
50
53
|
#TODO: On second thought, it might be interesting to see logs from an npc point of view.
|
51
54
|
end
|
52
|
-
def to_s
|
53
|
-
name
|
54
|
-
end
|
55
55
|
def update
|
56
56
|
@update_procs.each { |p|
|
57
57
|
p.call self
|
@@ -0,0 +1,16 @@
|
|
1
|
+
respond :close, Query::Text.new() do |actor, string|
|
2
|
+
actor.tell "You don't see any \"#{string}\" here."
|
3
|
+
end
|
4
|
+
|
5
|
+
respond :close, Query::Reachable.new(Entity) do |actor, thing|
|
6
|
+
actor.tell "You can't close #{the thing}."
|
7
|
+
end
|
8
|
+
|
9
|
+
respond :close, Query::Reachable.new(Container, :openable) do |actor, container|
|
10
|
+
if container.is? :closed
|
11
|
+
actor.tell "It's already closed."
|
12
|
+
else
|
13
|
+
actor.tell "You close #{the container}."
|
14
|
+
container.is :closed
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
respond :drop_in, Query::Children.new(), Query::Reachable.new() do |actor, thing, target|
|
2
|
+
puts "You can't put #{the thing} inside #{the target}."
|
3
|
+
end
|
4
|
+
|
5
|
+
respond :drop_in, Query::Children.new(), Query::Reachable.new(Container) do |actor, thing, container|
|
6
|
+
if container.is? :closed
|
7
|
+
actor.tell "#{The container} is closed."
|
8
|
+
else
|
9
|
+
thing.parent = container
|
10
|
+
thing.is :contained
|
11
|
+
actor.tell "You put #{the thing} in #{the container}."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
xlate "drop :item in :container", :drop_in, :item, :container
|
16
|
+
xlate "put :item in :container", :drop_in, :item, :container
|
17
|
+
xlate "place :item in :container", :drop_in, :item, :container
|
@@ -0,0 +1,16 @@
|
|
1
|
+
respond :drop_on, Query::Children.new(), Query::Reachable.new() do |actor, thing, supporter|
|
2
|
+
actor.tell "You can't put #{the thing} on #{the supporter}."
|
3
|
+
end
|
4
|
+
|
5
|
+
respond :drop_on, Query::Children.new(), Query::Reachable.new(Supporter) do |actor, thing, supporter|
|
6
|
+
thing.parent = supporter
|
7
|
+
thing.is :supported
|
8
|
+
actor.tell "You put #{the thing} on #{the supporter}."
|
9
|
+
end
|
10
|
+
|
11
|
+
xlate "put :thing on :supporter", :drop_on, :thing, :supporter
|
12
|
+
xlate "put :thing down on :supporter", :drop_on, :thing, :supporter
|
13
|
+
xlate "set :thing on :supporter", :drop_on, :thing, :supporter
|
14
|
+
xlate "set :thing down on :supporter", :drop_on, :thing, :supporter
|
15
|
+
xlate "drop :thing on :supporter", :drop_on, :thing, :supporter
|
16
|
+
xlate "place :thing on :supporter", :drop_on, :thing, :supporter
|