gamefic 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|