gamefic 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gamefic/action.rb +7 -6
  3. data/lib/gamefic/before.rb +12 -0
  4. data/lib/gamefic/character.rb +1 -1
  5. data/lib/gamefic/core_ext/array.rb +4 -0
  6. data/lib/gamefic/core_ext/string.rb +0 -31
  7. data/lib/gamefic/describable.rb +68 -8
  8. data/lib/gamefic/director.rb +108 -75
  9. data/lib/gamefic/engine.rb +74 -10
  10. data/lib/gamefic/entity.rb +3 -3
  11. data/lib/gamefic/import/basics/actions/close.rb +16 -0
  12. data/lib/gamefic/import/basics/actions/commands.rb +3 -0
  13. data/lib/gamefic/import/basics/actions/drop-in.rb +17 -0
  14. data/lib/gamefic/import/basics/actions/drop-on.rb +16 -0
  15. data/lib/gamefic/import/basics/actions/drop.rb +30 -0
  16. data/lib/gamefic/import/basics/actions/enter.rb +16 -0
  17. data/lib/gamefic/import/basics/actions/{traversal.rb → go.rb} +35 -35
  18. data/lib/gamefic/import/basics/actions/inventory.rb +8 -49
  19. data/lib/gamefic/import/basics/actions/leave.rb +29 -0
  20. data/lib/gamefic/import/basics/actions/look-in-at.rb +27 -0
  21. data/lib/gamefic/import/basics/actions/look-under.rb +3 -0
  22. data/lib/gamefic/import/basics/actions/look.rb +71 -67
  23. data/lib/gamefic/import/basics/actions/nil.rb +25 -0
  24. data/lib/gamefic/import/basics/actions/open.rb +23 -0
  25. data/lib/gamefic/import/basics/actions/quit.rb +3 -0
  26. data/lib/gamefic/import/basics/actions/take.rb +107 -0
  27. data/lib/gamefic/import/basics/entities/container.rb +8 -24
  28. data/lib/gamefic/import/basics/entities/entity.rb +11 -0
  29. data/lib/gamefic/import/basics/entities/fixture.rb +5 -5
  30. data/lib/gamefic/import/basics/entities/item.rb +5 -7
  31. data/lib/gamefic/import/basics/entities/portal.rb +40 -43
  32. data/lib/gamefic/import/basics/entities/room.rb +30 -24
  33. data/lib/gamefic/import/basics/entities/scenery.rb +5 -3
  34. data/lib/gamefic/import/basics/entities/supporter.rb +6 -0
  35. data/lib/gamefic/import/basics/entities/thing.rb +16 -0
  36. data/lib/gamefic/import/basics/queries/reachable.rb +38 -0
  37. data/lib/gamefic/import/basics/queries/room.rb +8 -0
  38. data/lib/gamefic/import/basics/queries/visible.rb +32 -0
  39. data/lib/gamefic/import/basics/rules/has-enough-light.rb +14 -0
  40. data/lib/gamefic/import/{basics → basics.old}/actions/container.rb +13 -12
  41. data/lib/gamefic/import/basics.old/actions/inventory.rb +50 -0
  42. data/lib/gamefic/import/basics.old/actions/look.rb +53 -0
  43. data/lib/gamefic/import/basics.old/actions/meta.rb +6 -0
  44. data/lib/gamefic/import/basics.old/actions/traversal.rb +35 -0
  45. data/lib/gamefic/import/{basics → basics.old}/actions.rb +0 -0
  46. data/lib/gamefic/import/basics.old/entities/container.rb +3 -0
  47. data/lib/gamefic/import/basics.old/entities/fixture.rb +3 -0
  48. data/lib/gamefic/import/basics.old/entities/item.rb +3 -0
  49. data/lib/gamefic/import/basics.old/entities/portal.rb +43 -0
  50. data/lib/gamefic/import/basics.old/entities/room.rb +27 -0
  51. data/lib/gamefic/import/basics.old/entities/scenery.rb +3 -0
  52. data/lib/gamefic/import/basics.old/entities/supporter.rb +3 -0
  53. data/lib/gamefic/import/{basics → basics.old}/entities.rb +0 -0
  54. data/lib/gamefic/import/basics.old/room_modes.rb +48 -0
  55. data/lib/gamefic/import/basics.rb +6 -2
  56. data/lib/gamefic/import/{basics/room_modes.rb → room_modes.rb} +6 -6
  57. data/lib/gamefic/import/standard.rb +1 -0
  58. data/lib/gamefic/meta.rb +12 -0
  59. data/lib/gamefic/optionset.rb +114 -0
  60. data/lib/gamefic/plot.rb +54 -21
  61. data/lib/gamefic/query.rb +214 -188
  62. data/lib/gamefic/requirement.rb +14 -0
  63. data/lib/gamefic/shell.rb +7 -4
  64. data/lib/gamefic/syntax.rb +35 -18
  65. data/lib/gamefic/thing.rb +7 -0
  66. data/lib/gamefic.rb +5 -1
  67. metadata +46 -12
  68. data/lib/gamefic/import/basics/actions/meta.rb +0 -6
  69. data/lib/gamefic/import/basics/entities/itemized.rb +0 -3
  70. data/lib/gamefic/import/basics/entities/portable.rb +0 -3
  71. data/lib/gamefic/user.rb +0 -66
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ebda04fc06a182081d6516d328bd23501586ecd
4
- data.tar.gz: 1e8aa7db0b490b0f864071fb74317a7a2f1b330d
3
+ metadata.gz: cdcd6a0fe04e0a8bbe946261ff8284fb4667e2f7
4
+ data.tar.gz: 98bafd885d73b32653194ca36ad50285e2656d45
5
5
  SHA512:
6
- metadata.gz: 74a8a6dc8951a30802fb5bb8e6ee764525885572fc0fa18018ea4cd9890f48674830dc94274528ca4e1f0b58de2043d547f1f8e60f14d6e8cb1a41ce30f53d1c
7
- data.tar.gz: 3181204289bc694587d60ffebf14f660a6c85d7f5140927f27f5e3c13fff60684f63c7fd59cf89d1acc8ac0ccaf85f5566f09f5d626a2a9d588518036acacc73
6
+ metadata.gz: 5cef4896f4506c22cbc82dff02846805b64b8062ccc90ead1e9aeeac1df9e9cc50a2a79bffd0159da33896f497bb2ce4bdeec68a45c7bef715384846e2c9a842
7
+ data.tar.gz: 2d2f4b0df8f65e54d1da9826e4e4ca1febf3b9a5858f200f81c4163afbbfd75502c8ceb187a4f7db102135683843bfe0dc3f2d6fd5bca258988f60e85a8e69ee
@@ -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
- def proc
48
- @proc
49
- end
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
@@ -1,6 +1,6 @@
1
1
  module Gamefic
2
2
 
3
- class Character < Entity
3
+ class Character < Thing
4
4
  attr_reader :state, :queue, :user, :last_command
5
5
  attr_accessor :object_of_pronoun
6
6
  def initialize(plot, args = {})
@@ -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
@@ -3,25 +3,85 @@ require "gamefic/keywords"
3
3
  module Gamefic
4
4
 
5
5
  module Describable
6
- attr_accessor :name, :longname, :synonyms
6
+ attr_reader :name
7
+ attr_accessor :synonyms, :indefinite_article
8
+ attr_writer :definite_article
7
9
  def keywords
8
- Keywords.new "#{name} #{longname} #{synonyms}"
10
+ Keywords.new "#{name} #{synonyms}"
9
11
  end
10
12
  def keywords=(value)
11
13
  @keywords = value
12
14
  end
13
- def longname
14
- @longname.to_s != '' ? @longname : name
15
- end
16
- def longname=(value)
17
- @longname = value
18
- end
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
@@ -3,32 +3,24 @@ module Gamefic
3
3
  class Director
4
4
  def self.dispatch(actor, command)
5
5
  command.strip!
6
- verbs = actor.plot.commandwords
7
- first = command.split(' ')[0].downcase
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
- handlers = Syntax.match(command, actor.plot.syntaxes)
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.longname
32
+ longnames.push "#{b.definitely}"
41
33
  }
42
- actor.tell "I don't know which you mean: #{longnames.join(', ')}"
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
- options.push [order.action.proc, args]
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
- options.push([
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
- prepared = Array.new
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
- if context.kind_of?(Subquery)
81
- last = prepared.last
82
- if last == nil or last.length > 1
83
- valid = false
84
- next
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
- return objects
119
- end
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(options)
126
- @options = options
112
+ def initialize(actor, befores, actions)
113
+ @actor = actor
114
+ @befores = befores
115
+ @actions = actions
127
116
  end
128
117
  def execute
129
- @@delegation_stack.push @options
130
- if @options.length > 0
131
- opt = @options.shift
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].call(opt[1][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
- else
159
+ elsif opt[1][0].parent == opt[1][1]
138
160
  opt[1][0].object_of_pronoun = nil
139
161
  end
140
- opt[0].call(opt[1])
162
+ opt[0].execute(opt[1])
141
163
  end
142
164
  end
143
- @@delegation_stack.pop
144
- end
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].call(opt[1][0])
181
+ opt[0].execute(opt[1][0])
182
+ opt[1][0].object_of_pronoun = nil
151
183
  else
152
- opt[0].call(opt[1])
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
@@ -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
- user = User.new @plot
9
- @plot.introduce user.character
10
- while user.character.state.kind_of?(GameOverState) == false
11
- proc {
12
- $SAFE = 3
13
- user.stream.select user.character.state.prompt
14
- print "\n"
15
- user.state.update
16
- @plot.update
17
- }.call
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
@@ -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,3 @@
1
+ meta :commands do |actor|
2
+ actor.tell actor.plot.commandwords.sort.join(", ")
3
+ 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