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.
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