gamefic 1.5.1 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gamefic.rb +1 -3
  3. data/lib/gamefic/action.rb +140 -79
  4. data/lib/gamefic/character.rb +120 -53
  5. data/lib/gamefic/character/state.rb +12 -0
  6. data/lib/gamefic/core_ext/array.rb +53 -11
  7. data/lib/gamefic/core_ext/string.rb +1 -0
  8. data/lib/gamefic/describable.rb +37 -11
  9. data/lib/gamefic/engine/base.rb +17 -4
  10. data/lib/gamefic/engine/tty.rb +4 -0
  11. data/lib/gamefic/entity.rb +4 -15
  12. data/lib/gamefic/matchable.rb +50 -0
  13. data/lib/gamefic/messaging.rb +45 -0
  14. data/lib/gamefic/node.rb +16 -0
  15. data/lib/gamefic/plot.rb +27 -33
  16. data/lib/gamefic/plot/{article_mount.rb → articles.rb} +22 -22
  17. data/lib/gamefic/plot/callbacks.rb +30 -4
  18. data/lib/gamefic/plot/{command_mount.rb → commands.rb} +121 -121
  19. data/lib/gamefic/plot/entities.rb +3 -3
  20. data/lib/gamefic/plot/host.rb +3 -3
  21. data/lib/gamefic/plot/playbook.rb +74 -30
  22. data/lib/gamefic/plot/scenes.rb +149 -0
  23. data/lib/gamefic/plot/snapshot.rb +14 -39
  24. data/lib/gamefic/plot/theater.rb +73 -0
  25. data/lib/gamefic/query.rb +6 -19
  26. data/lib/gamefic/query/base.rb +127 -246
  27. data/lib/gamefic/query/children.rb +6 -7
  28. data/lib/gamefic/query/descendants.rb +15 -0
  29. data/lib/gamefic/query/family.rb +19 -7
  30. data/lib/gamefic/query/itself.rb +13 -0
  31. data/lib/gamefic/query/matches.rb +67 -11
  32. data/lib/gamefic/query/parent.rb +6 -7
  33. data/lib/gamefic/query/siblings.rb +10 -7
  34. data/lib/gamefic/query/text.rb +39 -35
  35. data/lib/gamefic/scene.rb +1 -1
  36. data/lib/gamefic/scene/active.rb +12 -6
  37. data/lib/gamefic/scene/base.rb +56 -5
  38. data/lib/gamefic/scene/conclusion.rb +3 -0
  39. data/lib/gamefic/scene/custom.rb +0 -83
  40. data/lib/gamefic/scene/multiple_choice.rb +54 -32
  41. data/lib/gamefic/scene/multiple_scene.rb +11 -6
  42. data/lib/gamefic/scene/pause.rb +3 -4
  43. data/lib/gamefic/scene/yes_or_no.rb +23 -9
  44. data/lib/gamefic/script/base.rb +4 -0
  45. data/lib/gamefic/subplot.rb +22 -19
  46. data/lib/gamefic/syntax.rb +7 -15
  47. data/lib/gamefic/user/base.rb +7 -13
  48. data/lib/gamefic/user/buffer.rb +7 -0
  49. data/lib/gamefic/user/tty.rb +13 -12
  50. data/lib/gamefic/version.rb +1 -1
  51. metadata +11 -37
  52. data/lib/gamefic/director.rb +0 -23
  53. data/lib/gamefic/director/delegate.rb +0 -126
  54. data/lib/gamefic/director/order.rb +0 -17
  55. data/lib/gamefic/director/parser.rb +0 -137
  56. data/lib/gamefic/keywords.rb +0 -67
  57. data/lib/gamefic/plot/query_mount.rb +0 -9
  58. data/lib/gamefic/plot/scene_mount.rb +0 -182
  59. data/lib/gamefic/query/ambiguous_children.rb +0 -5
  60. data/lib/gamefic/query/expression.rb +0 -47
  61. data/lib/gamefic/query/many_children.rb +0 -7
  62. data/lib/gamefic/query/plural_children.rb +0 -14
  63. data/lib/gamefic/query/self.rb +0 -10
  64. data/lib/gamefic/scene_data.rb +0 -10
  65. data/lib/gamefic/scene_data/base.rb +0 -12
  66. data/lib/gamefic/scene_data/multiple_choice.rb +0 -19
  67. data/lib/gamefic/scene_data/multiple_scene.rb +0 -21
  68. data/lib/gamefic/scene_data/yes_or_no.rb +0 -18
  69. data/lib/gamefic/serialized.rb +0 -24
  70. data/lib/gamefic/stage.rb +0 -106
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gamefic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-23 00:00:00.000000000 Z
11
+ date: 2017-05-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -90,20 +90,6 @@ dependencies:
90
90
  - - ">="
91
91
  - !ruby/object:Gem::Version
92
92
  version: 11.3.0
93
- - !ruby/object:Gem::Dependency
94
- name: poltergeist
95
- requirement: !ruby/object:Gem::Requirement
96
- requirements:
97
- - - "~>"
98
- - !ruby/object:Gem::Version
99
- version: '1.11'
100
- type: :development
101
- prerelease: false
102
- version_requirements: !ruby/object:Gem::Requirement
103
- requirements:
104
- - - "~>"
105
- - !ruby/object:Gem::Version
106
- version: '1.11'
107
93
  - !ruby/object:Gem::Dependency
108
94
  name: codeclimate-test-reporter
109
95
  requirement: !ruby/object:Gem::Requirement
@@ -135,14 +121,11 @@ files:
135
121
  - lib/gamefic.rb
136
122
  - lib/gamefic/action.rb
137
123
  - lib/gamefic/character.rb
124
+ - lib/gamefic/character/state.rb
138
125
  - lib/gamefic/command.rb
139
126
  - lib/gamefic/core_ext/array.rb
140
127
  - lib/gamefic/core_ext/string.rb
141
128
  - lib/gamefic/describable.rb
142
- - lib/gamefic/director.rb
143
- - lib/gamefic/director/delegate.rb
144
- - lib/gamefic/director/order.rb
145
- - lib/gamefic/director/parser.rb
146
129
  - lib/gamefic/engine.rb
147
130
  - lib/gamefic/engine/base.rb
148
131
  - lib/gamefic/engine/tty.rb
@@ -157,31 +140,29 @@ files:
157
140
  - lib/gamefic/grammar/verb_set.rb
158
141
  - lib/gamefic/grammar/verbs.rb
159
142
  - lib/gamefic/grammar/word_adapter.rb
160
- - lib/gamefic/keywords.rb
143
+ - lib/gamefic/matchable.rb
144
+ - lib/gamefic/messaging.rb
161
145
  - lib/gamefic/node.rb
162
146
  - lib/gamefic/plot.rb
163
- - lib/gamefic/plot/article_mount.rb
147
+ - lib/gamefic/plot/articles.rb
164
148
  - lib/gamefic/plot/callbacks.rb
165
- - lib/gamefic/plot/command_mount.rb
149
+ - lib/gamefic/plot/commands.rb
166
150
  - lib/gamefic/plot/entities.rb
167
151
  - lib/gamefic/plot/host.rb
168
152
  - lib/gamefic/plot/playbook.rb
169
153
  - lib/gamefic/plot/players.rb
170
- - lib/gamefic/plot/query_mount.rb
171
- - lib/gamefic/plot/scene_mount.rb
154
+ - lib/gamefic/plot/scenes.rb
172
155
  - lib/gamefic/plot/snapshot.rb
156
+ - lib/gamefic/plot/theater.rb
173
157
  - lib/gamefic/plot/you_mount.rb
174
158
  - lib/gamefic/query.rb
175
- - lib/gamefic/query/ambiguous_children.rb
176
159
  - lib/gamefic/query/base.rb
177
160
  - lib/gamefic/query/children.rb
178
- - lib/gamefic/query/expression.rb
161
+ - lib/gamefic/query/descendants.rb
179
162
  - lib/gamefic/query/family.rb
180
- - lib/gamefic/query/many_children.rb
163
+ - lib/gamefic/query/itself.rb
181
164
  - lib/gamefic/query/matches.rb
182
165
  - lib/gamefic/query/parent.rb
183
- - lib/gamefic/query/plural_children.rb
184
- - lib/gamefic/query/self.rb
185
166
  - lib/gamefic/query/siblings.rb
186
167
  - lib/gamefic/query/text.rb
187
168
  - lib/gamefic/scene.rb
@@ -193,22 +174,15 @@ files:
193
174
  - lib/gamefic/scene/multiple_scene.rb
194
175
  - lib/gamefic/scene/pause.rb
195
176
  - lib/gamefic/scene/yes_or_no.rb
196
- - lib/gamefic/scene_data.rb
197
- - lib/gamefic/scene_data/base.rb
198
- - lib/gamefic/scene_data/multiple_choice.rb
199
- - lib/gamefic/scene_data/multiple_scene.rb
200
- - lib/gamefic/scene_data/yes_or_no.rb
201
177
  - lib/gamefic/script.rb
202
178
  - lib/gamefic/script/base.rb
203
179
  - lib/gamefic/script/file.rb
204
180
  - lib/gamefic/script/text.rb
205
- - lib/gamefic/serialized.rb
206
181
  - lib/gamefic/shell.rb
207
182
  - lib/gamefic/source.rb
208
183
  - lib/gamefic/source/base.rb
209
184
  - lib/gamefic/source/file.rb
210
185
  - lib/gamefic/source/text.rb
211
- - lib/gamefic/stage.rb
212
186
  - lib/gamefic/subplot.rb
213
187
  - lib/gamefic/syntax.rb
214
188
  - lib/gamefic/tester.rb
@@ -1,23 +0,0 @@
1
- module Gamefic
2
-
3
- module Director
4
- autoload :Parser, 'gamefic/director/parser'
5
- autoload :Delegate, 'gamefic/director/delegate'
6
- autoload :Order, 'gamefic/director/order'
7
-
8
- def self.dispatch(actor, *args)
9
- orders = []
10
- if args.length > 1
11
- orders = Parser.from_tokens(actor, args)
12
- end
13
- if orders.length == 0
14
- orders = Parser.from_string(actor, args.join(' ').strip)
15
- end
16
- first_order = orders[0]
17
- del = Delegate.new(actor, orders)
18
- del.execute
19
- first_order
20
- end
21
- end
22
-
23
- end
@@ -1,126 +0,0 @@
1
- module Gamefic
2
- module Director
3
- class Delegate
4
-
5
- class << self
6
- def proceed_for actor
7
- return if stack_map[actor].nil?
8
- stack_map[actor].last.proceed unless stack_map[actor].last.nil?
9
- end
10
-
11
- private
12
-
13
- def stack_map
14
- @stack_map ||= {}
15
- end
16
- end
17
-
18
- def initialize(actor, orders)
19
- @actor = actor
20
- @orders = orders
21
- @did = []
22
- @validated = false
23
- end
24
-
25
- def proceed
26
- return if @orders.length == 0
27
- executed = false
28
- while !executed
29
- order = @orders.shift
30
- break if order.nil?
31
- # HACK: Make sure Character#proceed does not repeat an action
32
- next if @did.include?(order.action)
33
- @did.push order.action
34
- @last_action = order.action
35
- executed = attempt(order)
36
- return if order.canceled?
37
- end
38
- end
39
-
40
- def execute
41
- return if @orders.length == 0
42
- stack_map[@actor] ||= []
43
- stack_map[@actor].push self
44
- proceed
45
- stack_map[@actor].pop
46
- stack_map.delete @actor if stack_map[@actor].empty?
47
- end
48
-
49
- private
50
-
51
- def attempt order
52
- executed = false
53
- arg_i = 0
54
- final_arguments = []
55
- order.arguments.each { |argument|
56
- if argument.length > 1 and !order.action.queries[arg_i].allow_many?
57
- if argument[0].kind_of?(Array)
58
- # This thing refers to multiple items. Just keep going.
59
- final_arguments = nil
60
- break
61
- else
62
- ambiguous = argument
63
- end
64
- order = Order.new(@actor, @actor.playbook.disambiguator, [])
65
- final_arguments = [ambiguous]
66
- break
67
- end
68
- if order.action.queries[arg_i].allow_ambiguous?
69
- valid = argument.flatten
70
- else
71
- valid = validate(argument, arg_i, order)
72
- if valid.nil?
73
- final_arguments = nil
74
- break
75
- end
76
- end
77
- if order.action == @actor.playbook.disambiguator or final_arguments.nil?
78
- break
79
- end
80
- if order.action.queries[arg_i].allow_many?
81
- final_arguments.push valid.flatten
82
- elsif valid.length == 1
83
- final_arguments.push valid[0]
84
- else
85
- final_arguments = nil
86
- break
87
- end
88
- arg_i += 1
89
- }
90
- if !final_arguments.nil?
91
- unless @validated or order.action.meta?
92
- @actor.playbook.validators.each { |v|
93
- v.call order
94
- return false if order.canceled?
95
- }
96
- end
97
- @validated = true
98
- # The actor is always the first argument to an Action proc
99
- final_arguments.unshift @actor
100
- order.action.execute(*final_arguments)
101
- executed = true
102
- end
103
- executed
104
- end
105
-
106
- def validate argument, arg_i, order
107
- valid = []
108
- argument.each { |m|
109
- if order.action.queries[arg_i].validate(@actor, m)
110
- valid.push m
111
- else
112
- valid = nil
113
- break
114
- end
115
- }
116
- valid
117
- end
118
-
119
- private
120
-
121
- def stack_map
122
- Delegate.send(:stack_map)
123
- end
124
- end
125
- end
126
- end
@@ -1,17 +0,0 @@
1
- module Gamefic
2
- class Director::Order
3
- attr_reader :actor, :action, :arguments
4
- def initialize(actor, action, arguments)
5
- @actor = actor
6
- @action = action
7
- @arguments = arguments
8
- @canceled = false
9
- end
10
- def cancel
11
- @canceled = true
12
- end
13
- def canceled?
14
- @canceled
15
- end
16
- end
17
- end
@@ -1,137 +0,0 @@
1
- require 'gamefic/director/order'
2
-
3
- module Gamefic
4
- module Director
5
-
6
- module Parser
7
- def self.from_tokens(actor, tokens)
8
- options = []
9
- command = tokens.shift
10
- actions = actor.playbook.actions_for(command.to_sym)
11
- actions.each { |action|
12
- if action.queries.length == tokens.length
13
- valid = true
14
- index = 0
15
- action.queries.each { |query|
16
- if query.validate(actor, tokens[index]) == false
17
- valid = false
18
- break
19
- end
20
- index += 1
21
- }
22
- if valid
23
- arguments = []
24
- tokens.each { |token|
25
- arguments.push [token]
26
- }
27
- options.push Order.new(actor, action, arguments)
28
- end
29
- end
30
- }
31
- if options.length == 0
32
- tokens.unshift command
33
- end
34
- # HACK: This sort is necessary for a problem on Windows.
35
- options.sort{ |a,b|
36
- if a.action.specificity == b.action.specificity
37
- # Newer action takes precedence
38
- b.action.order_key <=> a.action.order_key
39
- else
40
- # Higher specificity takes precedence
41
- b.action.specificity <=> a.action.specificity
42
- end
43
- }
44
- end
45
- def self.from_string(actor, command)
46
- options = []
47
- if command.to_s == ''
48
- return options
49
- end
50
- matches = Syntax.tokenize(command, actor.playbook.syntaxes)
51
- matches.each { |match|
52
- actions = actor.playbook.actions_for(match.verb)
53
- actions.each { |action|
54
- options.concat bind_contexts_in_result(actor, match.arguments, action)
55
- }
56
- }
57
- # HACK: This sort is necessary for a problem on Windows.
58
- options.sort{ |a,b|
59
- if a.action.specificity == b.action.specificity
60
- # Newer action takes precedence
61
- b.action.order_key <=> a.action.order_key
62
- else
63
- # Higher specificity takes precedence
64
- b.action.specificity <=> a.action.specificity
65
- end
66
- }
67
- end
68
- class << self
69
- private
70
- def bind_contexts_in_result(actor, handler, action)
71
- queries = action.queries.clone
72
- objects = execute_query(actor, handler.clone, queries, action)
73
- num_nil = 0
74
- #while objects.length == 0 and queries.last.optional?
75
- # num_nil +=1
76
- # queries.pop
77
- # objects = execute_query(actor, handler.clone, queries, action, num_nil)
78
- #end
79
- return objects
80
- end
81
- def execute_query(actor, arguments, queries, action, num_nil = 0)
82
- # If the action verb is nil, treat the first argument as a query
83
- #arguments.shift unless action.verb.nil?
84
- prepared = []
85
- objects = []
86
- valid = true
87
- last_remainder = nil
88
- queries.clone.each { |context|
89
- arg = arguments.shift.to_s
90
- if last_remainder.to_s > ''
91
- arg = (last_remainder + " " + arg).strip
92
- end
93
- if arg.nil? or arg == ''
94
- valid = false
95
- next
96
- end
97
- if context == String
98
- prepared.push [arg]
99
- elsif context.kind_of?(Query::Base)
100
- result = context.execute(actor, arg)
101
- if result.objects.length == 0
102
- valid = false
103
- next
104
- else
105
- prepared.push result.objects
106
- last_remainder = result.remainder
107
- end
108
- else
109
- raise TypeError.new("Action parameters must inherit from Query::Base")
110
- end
111
- }
112
- if valid == true
113
- if last_remainder.nil? or last_remainder.empty?
114
- prepared.each { |p|
115
- p.uniq!
116
- }
117
- num_nil.times do
118
- prepared.push [nil]
119
- end
120
- objects.push Order.new(actor, action, prepared)
121
- else
122
- if !action.queries.last.allow_many? or action.queries.last.allow_ambiguous?
123
- misunderstood = Action.new nil, Query::Text.new do |actor, text|
124
- actor.tell "I understand the first part of your command but not \"#{text}.\""
125
- end
126
- misunderstood.meta = true
127
- objects.push Order.new(actor, misunderstood, [[last_remainder]])
128
- end
129
- end
130
- end
131
- objects
132
- end
133
- end
134
- end
135
-
136
- end
137
- end
@@ -1,67 +0,0 @@
1
- # Arrays of keywords that can be compared for matches.
2
-
3
- module Gamefic
4
-
5
- class Keywords < Array
6
- def initialize(statement = '')
7
- if statement.kind_of?(Keywords)
8
- self.concat statement
9
- else
10
- if statement.kind_of?(Array)
11
- statement = statement.join(' ')
12
- end
13
- self.concat statement.to_s.gsub(/[^a-z0-9]/i, ' ').strip.downcase.split(' ')
14
- end
15
- self
16
- end
17
-
18
- # Count the number of matching words in another Keywords array.
19
- # The total includes partial matches; for example, "gre" is a 0.6 match
20
- # for "green".
21
- #
22
- # @return [Float] The total number of matches
23
- def found_in(other, fuzzy = false)
24
- matches = 0.0
25
- self.each { |my_word|
26
- if other.include?(my_word)
27
- matches = matches + 1.0
28
- else
29
- other.each { |other_word|
30
- if my_word.length < other_word.length
31
- if other_word[0, my_word.length] == my_word and my_word.length > 2
32
- matches = matches + (my_word.length.to_f / other_word.length.to_f)
33
- end
34
- elsif fuzzy
35
- fuzzy_word = fuzzify my_word
36
- if other_word[0, fuzzy_word.length] == fuzzy_word and fuzzy_word.length > 2
37
- matches = matches + (fuzzy_word.length.to_f / other_word.length.to_f)
38
- elsif fuzzy_word[0, other_word.length] == other_word and other_word.length > 2
39
- matches = matches + (fuzzy_word.length.to_f / other_word.length.to_f)
40
- end
41
- end
42
- }
43
- end
44
- }
45
- matches
46
- end
47
-
48
- def to_s
49
- self.join(' ')
50
- end
51
-
52
- private
53
-
54
- def fuzzify word
55
- if word.end_with?('ies')
56
- word[0..-4]
57
- elsif word.end_with?('ae')
58
- word[0..-3]
59
- elsif word.end_with?('s') or word.end_with?('i')
60
- word[0..-2]
61
- else
62
- word
63
- end
64
- end
65
- end
66
-
67
- end