gamefic 0.2.0 → 0.6.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 (128) hide show
  1. checksums.yaml +4 -4
  2. data/lib/gamefic/action.rb +87 -56
  3. data/lib/gamefic/ansi.rb +55 -0
  4. data/lib/gamefic/character.rb +130 -76
  5. data/lib/gamefic/command.rb +19 -0
  6. data/lib/gamefic/core_ext/array.rb +51 -40
  7. data/lib/gamefic/core_ext/string.rb +4 -0
  8. data/lib/gamefic/describable.rb +108 -46
  9. data/lib/gamefic/direction.rb +46 -0
  10. data/lib/gamefic/director/delegate.rb +91 -0
  11. data/lib/gamefic/director/order.rb +10 -0
  12. data/lib/gamefic/director/parser.rb +119 -0
  13. data/lib/gamefic/director.rb +16 -197
  14. data/lib/gamefic/engine/cgi.rb +221 -0
  15. data/lib/gamefic/engine/tty.rb +237 -0
  16. data/lib/gamefic/engine.rb +88 -67
  17. data/lib/gamefic/entity.rb +96 -69
  18. data/lib/gamefic/grammar/conjugator.rb +20 -0
  19. data/lib/gamefic/grammar/gender.rb +11 -0
  20. data/lib/gamefic/grammar/person.rb +10 -0
  21. data/lib/gamefic/grammar/plural.rb +13 -0
  22. data/lib/gamefic/grammar/pronouns.rb +60 -0
  23. data/lib/gamefic/grammar/tense.rb +6 -0
  24. data/lib/gamefic/grammar/verb_set.rb +43 -0
  25. data/lib/gamefic/grammar/verbs.rb +25 -0
  26. data/lib/gamefic/grammar/word_adapter.rb +36 -0
  27. data/lib/gamefic/grammar.rb +13 -0
  28. data/lib/gamefic/html.rb +53 -0
  29. data/lib/gamefic/keywords.rb +51 -33
  30. data/lib/gamefic/node.rb +65 -58
  31. data/lib/gamefic/plot/article_mount.rb +22 -0
  32. data/lib/gamefic/plot/command_mount.rb +88 -0
  33. data/lib/gamefic/plot/entity_mount.rb +45 -0
  34. data/lib/gamefic/plot/query_mount.rb +9 -0
  35. data/lib/gamefic/plot/scene_mount.rb +181 -0
  36. data/lib/gamefic/plot/you_mount.rb +22 -0
  37. data/lib/gamefic/plot.rb +296 -247
  38. data/lib/gamefic/query/ambiguous_children.rb +5 -0
  39. data/lib/gamefic/query/base.rb +265 -0
  40. data/lib/gamefic/query/children.rb +10 -0
  41. data/lib/gamefic/query/expression.rb +47 -0
  42. data/lib/gamefic/query/family.rb +10 -0
  43. data/lib/gamefic/query/many_children.rb +7 -0
  44. data/lib/gamefic/query/matches.rb +11 -0
  45. data/lib/gamefic/query/parent.rb +10 -0
  46. data/lib/gamefic/query/plural_children.rb +14 -0
  47. data/lib/gamefic/query/self.rb +10 -0
  48. data/lib/gamefic/query/siblings.rb +10 -0
  49. data/lib/gamefic/query/text.rb +43 -0
  50. data/lib/gamefic/query.rb +19 -203
  51. data/lib/gamefic/rule.rb +18 -0
  52. data/lib/gamefic/scene/active.rb +25 -0
  53. data/lib/gamefic/scene/concluded.rb +22 -0
  54. data/lib/gamefic/scene/multiplechoice.rb +74 -0
  55. data/lib/gamefic/scene/paused.rb +26 -0
  56. data/lib/gamefic/scene/yesorno.rb +43 -0
  57. data/lib/gamefic/scene.rb +125 -0
  58. data/lib/gamefic/script/base.rb +33 -0
  59. data/lib/gamefic/script/file.rb +14 -0
  60. data/lib/gamefic/script/text.rb +14 -0
  61. data/lib/gamefic/script.rb +9 -0
  62. data/lib/gamefic/serialized.rb +24 -0
  63. data/lib/gamefic/shell.rb +9 -247
  64. data/lib/gamefic/snapshots.rb +134 -0
  65. data/lib/gamefic/source/base.rb +12 -0
  66. data/lib/gamefic/source/file.rb +23 -0
  67. data/lib/gamefic/source/text.rb +16 -0
  68. data/lib/gamefic/source.rb +9 -0
  69. data/lib/gamefic/stage.rb +75 -0
  70. data/lib/gamefic/syntax.rb +106 -124
  71. data/lib/gamefic/tester.rb +20 -0
  72. data/lib/gamefic/version.rb +3 -0
  73. data/lib/gamefic.rb +18 -12
  74. metadata +102 -70
  75. data/lib/gamefic/base.rb +0 -10
  76. data/lib/gamefic/before.rb +0 -12
  77. data/lib/gamefic/import/basics/actions/close.rb +0 -16
  78. data/lib/gamefic/import/basics/actions/commands.rb +0 -3
  79. data/lib/gamefic/import/basics/actions/drop-in.rb +0 -17
  80. data/lib/gamefic/import/basics/actions/drop-on.rb +0 -16
  81. data/lib/gamefic/import/basics/actions/drop.rb +0 -30
  82. data/lib/gamefic/import/basics/actions/enter.rb +0 -16
  83. data/lib/gamefic/import/basics/actions/go.rb +0 -35
  84. data/lib/gamefic/import/basics/actions/inventory.rb +0 -8
  85. data/lib/gamefic/import/basics/actions/leave.rb +0 -29
  86. data/lib/gamefic/import/basics/actions/look-in-at.rb +0 -27
  87. data/lib/gamefic/import/basics/actions/look-under.rb +0 -3
  88. data/lib/gamefic/import/basics/actions/look.rb +0 -71
  89. data/lib/gamefic/import/basics/actions/nil.rb +0 -25
  90. data/lib/gamefic/import/basics/actions/open.rb +0 -23
  91. data/lib/gamefic/import/basics/actions/quit.rb +0 -3
  92. data/lib/gamefic/import/basics/actions/take.rb +0 -107
  93. data/lib/gamefic/import/basics/entities/container.rb +0 -8
  94. data/lib/gamefic/import/basics/entities/entity.rb +0 -11
  95. data/lib/gamefic/import/basics/entities/fixture.rb +0 -5
  96. data/lib/gamefic/import/basics/entities/item.rb +0 -5
  97. data/lib/gamefic/import/basics/entities/portal.rb +0 -40
  98. data/lib/gamefic/import/basics/entities/room.rb +0 -30
  99. data/lib/gamefic/import/basics/entities/scenery.rb +0 -5
  100. data/lib/gamefic/import/basics/entities/supporter.rb +0 -6
  101. data/lib/gamefic/import/basics/entities/thing.rb +0 -16
  102. data/lib/gamefic/import/basics/queries/reachable.rb +0 -38
  103. data/lib/gamefic/import/basics/queries/room.rb +0 -8
  104. data/lib/gamefic/import/basics/queries/visible.rb +0 -32
  105. data/lib/gamefic/import/basics/rules/has-enough-light.rb +0 -14
  106. data/lib/gamefic/import/basics.old/actions/container.rb +0 -112
  107. data/lib/gamefic/import/basics.old/actions/inventory.rb +0 -50
  108. data/lib/gamefic/import/basics.old/actions/look.rb +0 -53
  109. data/lib/gamefic/import/basics.old/actions/meta.rb +0 -6
  110. data/lib/gamefic/import/basics.old/actions/traversal.rb +0 -35
  111. data/lib/gamefic/import/basics.old/actions.rb +0 -1
  112. data/lib/gamefic/import/basics.old/entities/container.rb +0 -3
  113. data/lib/gamefic/import/basics.old/entities/fixture.rb +0 -3
  114. data/lib/gamefic/import/basics.old/entities/item.rb +0 -3
  115. data/lib/gamefic/import/basics.old/entities/portal.rb +0 -43
  116. data/lib/gamefic/import/basics.old/entities/room.rb +0 -27
  117. data/lib/gamefic/import/basics.old/entities/scenery.rb +0 -3
  118. data/lib/gamefic/import/basics.old/entities/supporter.rb +0 -3
  119. data/lib/gamefic/import/basics.old/entities.rb +0 -1
  120. data/lib/gamefic/import/basics.old/room_modes.rb +0 -48
  121. data/lib/gamefic/import/basics.rb +0 -6
  122. data/lib/gamefic/import/room_modes.rb +0 -48
  123. data/lib/gamefic/import/standard.rb +0 -1
  124. data/lib/gamefic/meta.rb +0 -12
  125. data/lib/gamefic/optionset.rb +0 -114
  126. data/lib/gamefic/requirement.rb +0 -14
  127. data/lib/gamefic/story.rb +0 -14
  128. data/lib/gamefic/thing.rb +0 -7
@@ -1,76 +1,103 @@
1
- require "digest/md5"
2
1
  require "gamefic/node"
3
2
  require "gamefic/describable"
4
- require "gamefic/plot"
3
+ require "gamefic/serialized"
5
4
 
6
5
  module Gamefic
7
6
 
8
- class Entity
9
- include Branch
10
- include Describable
11
- include OptionSettings
12
- attr_writer :option_array
13
- attr_reader :session, :plot
14
- def initialize(plot, args = {})
15
- if (plot.kind_of?(Plot) == false)
16
- raise "First argument must be a Plot"
17
- end
18
- pre_initialize
19
- #self.state = State
20
- #@story = Subplot.current
21
- @plot = plot
22
- @option_mapper = @plot
23
- @plot.send :add_entity, self
24
- #@story.add_entity self
25
- args.each { |key, value|
26
- send "#{key}=", value
27
- }
28
- @update_procs = Array.new
29
- @session = Hash.new
30
- post_initialize
31
- end
32
- #def self.present(args = {})
33
- # story = Plot.Loading
34
- # if story == nil
35
- # raise "No plot loading"
36
- # end
37
- # return self.new(story, args)
38
- #end
39
- def uid
40
- if @uid == nil
41
- @uid = Digest::MD5.hexdigest(self.object_id.to_s)[0,8]
42
- end
43
- @uid
44
- end
45
- def pre_initialize
46
- # raise NotImplementedError, "#{self.class} must implement post_initialize"
47
- end
48
- def post_initialize
49
- # raise NotImplementedError, "#{self.class} must implement post_initialize"
50
- end
51
- def tell(message, refresh = false)
52
- #TODO: Should this even be here? In all likelihood, only Characters receive tells, right?
53
- #TODO: On second thought, it might be interesting to see logs from an npc point of view.
54
- end
55
- def update
56
- @update_procs.each { |p|
57
- p.call self
58
- }
59
- end
60
- def on_update(&block)
61
- @update_procs.push block
62
- end
63
- def parent=(node)
64
- if node != nil and node.kind_of?(Entity) == false and node.kind_of?(Zone) == false
65
- raise "Entity's parent must be an Entity or a Zone"
66
- end
67
- super
68
- end
69
- def destroy
70
- self.parent = nil
71
- # TODO: Need to call this private method here?
72
- @plot.send(:rem_entity, self)
73
- end
74
- end
7
+ class Entity
8
+ include Node
9
+ include Describable
10
+ include Serialized
11
+ extend Serialized::ClassMethods
12
+ include Grammar::WordAdapter
13
+
14
+ attr_reader :session, :plot
15
+ serialize :name, :parent, :description
16
+
17
+ def initialize(plot, args = {})
18
+ if (plot.kind_of?(Plot) == false)
19
+ raise "First argument must be a Plot"
20
+ end
21
+ pre_initialize
22
+ @plot = plot
23
+ @plot.send :add_entity, self
24
+ args.each { |key, value|
25
+ send "#{key}=", value
26
+ }
27
+ @update_procs = Array.new
28
+ @session = Hash.new
29
+ yield self if block_given?
30
+ post_initialize
31
+ end
32
+ def uid
33
+ if @uid == nil
34
+ @uid = self.object_id.to_s
35
+ end
36
+ @uid
37
+ end
38
+ def pre_initialize
39
+ # raise NotImplementedError, "#{self.class} must implement post_initialize"
40
+ end
41
+ def post_initialize
42
+ # raise NotImplementedError, "#{self.class} must implement post_initialize"
43
+ end
44
+ def tell(message)
45
+ #TODO: Should this even be here? In all likelihood, only Characters receive tells, right?
46
+ #TODO: On second thought, it might be interesting to see logs from an npc point of view.
47
+ end
48
+ def stream(message)
49
+ # Unlike tell, this method sends raw data without formatting.
50
+ end
51
+
52
+ # Execute the entity's on_update blocks.
53
+ # This method is typically called by the Engine that manages game execution.
54
+ #
55
+ def update
56
+ @update_procs.each { |p|
57
+ p.call self
58
+ }
59
+ end
60
+
61
+ # Add a block to be executed when the game updates a turn.
62
+ #
63
+ # @yieldparam [Entity]
64
+ def on_update(&block)
65
+ @update_procs.push block
66
+ end
67
+
68
+ # Set the Entity's parent.
69
+ #
70
+ # @param node [Entity] The new parent.
71
+ def parent=(node)
72
+ if node != nil and node.kind_of?(Entity) == false
73
+ raise "Entity's parent must be an Entity"
74
+ end
75
+ super
76
+ end
77
+
78
+ # Remove this Entity from its current Plot.
79
+ #
80
+ def destroy
81
+ self.parent = nil
82
+ # TODO: Need to call this private method here?
83
+ @plot.send(:rem_entity, self)
84
+ end
85
+
86
+ # Get an extended property.
87
+ #
88
+ # @param key [Symbol] The property's name.
89
+ def [](key)
90
+ session[key]
91
+ end
92
+
93
+ # Set an extended property.
94
+ #
95
+ # @param key [Symbol] The property's name.
96
+ # @param value The value to set.
97
+ def []=(key, value)
98
+ session[key] = value
99
+ end
100
+
101
+ end
75
102
 
76
103
  end
@@ -0,0 +1,20 @@
1
+ require 'gamefic'
2
+ require 'gamefic/grammar'
3
+
4
+ module Gamefic::Grammar
5
+ module Conjugator
6
+ module ClassMethods
7
+ @@conjugated_verbs = {}
8
+ def conjugate infinitive, tense, *forms
9
+ @@conjugated_verbs[infinitive] ||= {}
10
+ @@conjugated_verbs[infinitive][tense] = VerbSet.new(infinitive, *forms)
11
+ end
12
+ def conjugated_verbs
13
+ @@conjugated_verbs
14
+ end
15
+ end
16
+ #def self.included(base)
17
+ # base.extend ClassMethods
18
+ #end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ require 'gamefic/grammar'
2
+
3
+ module Gamefic::Grammar
4
+ module Gender
5
+ attr_writer :gender
6
+ def gender
7
+ # Supported values are "male", "female", "other", and "neutral"
8
+ @gender ||= "neutral"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ require 'gamefic/grammar'
2
+
3
+ module Gamefic::Grammar
4
+ module Person
5
+ attr_writer :person
6
+ def person
7
+ @person ||= 3
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ require 'gamefic/grammar'
2
+
3
+ module Gamefic::Grammar
4
+ module Plural
5
+ attr_writer :plural
6
+ def plural?
7
+ if @plural.nil?
8
+ @plural = false
9
+ end
10
+ @plural
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,60 @@
1
+ require 'gamefic'
2
+ require 'gamefic/grammar'
3
+
4
+ module Gamefic::Grammar
5
+ class Pronouns
6
+ def initialize object
7
+ @object = object
8
+ end
9
+ def subj
10
+ Pronouns.get_pronoun_set(@object)[0]
11
+ end
12
+ def obj
13
+ Pronouns.get_pronoun_set(@object)[1]
14
+ end
15
+ def poss
16
+ Pronouns.get_pronoun_set(@object)[2]
17
+ end
18
+ def Subj
19
+ subj.cap_first
20
+ end
21
+ def Obj
22
+ obj.cap_first
23
+ end
24
+ def Poss
25
+ obj.cap_first
26
+ end
27
+ def self.get_pronoun_set(obj)
28
+ set = Pronouns.sets["#{obj.person}"]
29
+ if set.nil?
30
+ set = Pronouns.sets["#{obj.person}:#{obj.plural? ? 'plural' : 'singular'}"]
31
+ end
32
+ if set.nil?
33
+ set = Pronouns.sets["#{obj.person}:#{obj.plural? ? 'plural' : 'singular'}:#{obj.gender}"]
34
+ end
35
+ if set.nil?
36
+ raise "Pronoun set could not be determined"
37
+ end
38
+ set
39
+ end
40
+ # TODO Consider implementing method_missing to determine correct pronoun
41
+ # from example, e.g., "he" would change to "she" for female entities
42
+ def self.sets
43
+ if @sets.nil?
44
+ @sets = {}
45
+ @sets["1:singular"] = ["I", "me", "my"]
46
+ @sets["2"] = ["you", "you", "your"]
47
+ @sets["3:singular:male"] = ["he", "him", "his"]
48
+ @sets["3:singular:female"] = ["she", "her", "her"]
49
+ # "other" refers to a person or living being that is neither
50
+ # male or female or for whom gender is unspecified. It's
51
+ # typically used to avoid referring to a person as "it."
52
+ @sets["3:singular:other"] = ["they", "them", "their"]
53
+ @sets["3:singular:neutral"] = ["it", "it", "its"]
54
+ @sets["1:plural"] = ["we", "us", "our"]
55
+ @sets["3:plural"] = ["they", "them", "their"]
56
+ end
57
+ @sets
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,6 @@
1
+ require 'gamefic/grammar'
2
+
3
+ module Gamefic::Grammar::Tense
4
+ PRESENT = :present
5
+ PAST = :past
6
+ end
@@ -0,0 +1,43 @@
1
+ require 'gamefic/grammar'
2
+
3
+ module Gamefic::Grammar
4
+ class VerbSet
5
+ def initialize infinitive, *forms
6
+ # TODO what to do with the tense?
7
+ @infinitive = infinitive.to_s
8
+ @forms = {}
9
+ form = forms[0]
10
+ @forms["1:singular"] = form.nil? ? @infinitive.to_s : form.to_s
11
+ form = forms[1]
12
+ @forms["2:singular"] = form.nil? ? @infinitive.to_s : form.to_s
13
+ form = forms[2]
14
+ @forms["3:singular"] = form.nil? ? generate_third_singular : form.to_s
15
+ form = forms[3]
16
+ @forms["1:plural"] = form.nil? ? @infinitive.to_s : form.to_s
17
+ form = forms[4]
18
+ @forms["2:plural"] = form.nil? ? @forms["1:plural"] : form.to_s
19
+ form = forms[5]
20
+ @forms["3:plural"] = form.nil? ? @forms["1:plural"] : form.to_s
21
+ end
22
+ def conjugate pronoun
23
+ form = @forms["#{pronoun.person}"]
24
+ if form.nil?
25
+ form = @forms["#{pronoun.person}:#{pronoun.plural? ? 'plural' : 'singular'}"]
26
+ end
27
+ if form.nil?
28
+ raise "Unable to conjugate #{@infinitive}"
29
+ end
30
+ form
31
+ end
32
+ private
33
+ def generate_third_singular
34
+ if @infinitive.end_with?('o')
35
+ @infinitive + "es"
36
+ elsif @infinitive.end_with?('ry')
37
+ @infinitive[0..-2] + "ies"
38
+ else
39
+ @infinitive + "s"
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ require 'gamefic'
2
+ require 'gamefic/grammar'
3
+
4
+ module Gamefic::Grammar
5
+ class Verbs
6
+ extend Gamefic::Grammar::Conjugator::ClassMethods
7
+ def initialize obj
8
+ @pronoun = obj
9
+ self.class.conjugated_verbs.each_pair { |infinitive, verbset|
10
+ define_singleton_method infinitive do
11
+ verbset[:present].conjugate @pronoun
12
+ end
13
+ }
14
+ end
15
+ def method_missing infinitive, *args, &block
16
+ Gamefic::Grammar::VerbSet.new(infinitive, nil, *args).conjugate(@pronoun)
17
+ end
18
+ def [] infinitive
19
+ words = infinitive.split_words
20
+ Gamefic::Grammar::VerbSet.new(words[0], nil).conjugate(@pronoun) + (words.length > 1 ? ' ' + words[1..-1].join(' ') : '')
21
+ end
22
+ conjugate :be, :present, :am, :are, :is, :are
23
+ conjugate :have, :present, :have, :have, :has, :have
24
+ end
25
+ end
@@ -0,0 +1,36 @@
1
+ require 'gamefic/grammar'
2
+ require 'gamefic/grammar/gender'
3
+
4
+ module Gamefic::Grammar
5
+ module WordAdapter
6
+ include Gender
7
+ include Person
8
+ include Plural
9
+ # @return [Gamefic::Grammar::Pronouns]
10
+ def pronoun
11
+ @pronoun ||= Grammar::Pronouns.new(self)
12
+ end
13
+ # @return [Gamefic::Grammar::Verbs]
14
+ def verb
15
+ @verb ||= Grammar::Verbs.new(self)
16
+ end
17
+ def contract words
18
+ @contractions ||= {
19
+ "I am" => "I'm",
20
+ "you are" => "you're",
21
+ "he is" => "he's",
22
+ "she is" => "she's",
23
+ "it is" => "it's",
24
+ "we are" => "we're",
25
+ "they are" => "they're",
26
+ "am not" => "am not",
27
+ "are not" => "aren't",
28
+ "is not" => "isn't",
29
+ "do not" => "don't",
30
+ "does not" => "doesn't"
31
+ }
32
+ src = pronoun.subj + " " + verb.send(words)
33
+ @contractions[src] || src
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ module Gamefic
2
+ module Grammar
3
+ autoload :Tense, 'gamefic/grammar/tense'
4
+ autoload :Pronouns, 'gamefic/grammar/pronouns'
5
+ autoload :Conjugator, 'gamefic/grammar/conjugator'
6
+ autoload :Verbs, 'gamefic/grammar/verbs'
7
+ autoload :VerbSet, 'gamefic/grammar/verb_set'
8
+ autoload :Person, 'gamefic/grammar/person'
9
+ autoload :Plural, 'gamefic/grammar/plural'
10
+ autoload :Gender, 'gamefic/grammar/gender'
11
+ autoload :WordAdapter, 'gamefic/grammar/word_adapter'
12
+ end
13
+ end
@@ -0,0 +1,53 @@
1
+ require 'rexml/document'
2
+
3
+ module Gamefic
4
+
5
+ module Html
6
+ def self.fix_ampersands(text)
7
+ codes = []
8
+ ENTITIES.keys.each { |e|
9
+ codes.push e[1..-1]
10
+ }
11
+ piped = codes.join('|')
12
+ re = Regexp.new("&(?!(#{piped}))")
13
+ text.gsub(re, '&\1')
14
+ end
15
+ def self.encode(text)
16
+ Gamefic::Html::ENTITIES.each { |k, v|
17
+ while text.include?(k)
18
+ text[v] = k
19
+ end
20
+ }
21
+ text
22
+ end
23
+ def self.decode(text)
24
+ Gamefic::Html::ENTITIES.each { |k, v|
25
+ while text.include?(k)
26
+ text[k] = v
27
+ end
28
+ }
29
+ text
30
+ end
31
+ def self.parse(code)
32
+ code = fix_ampersands(code).strip
33
+ last = nil
34
+ begin
35
+ doc = REXML::Document.new code
36
+ rescue REXML::ParseException => e
37
+ if e.source.buffer != last
38
+ if e.source.buffer[0,1] == '<'
39
+ code = code[0,(code.length - e.source.buffer.length)] + '&lt;' + e.source.buffer[1..-1]
40
+ last = e.source.buffer
41
+ retry
42
+ end
43
+ end
44
+ raise e
45
+ end
46
+ end
47
+ end
48
+
49
+ module Html
50
+ ENTITIES = { "&quot;" => "\"", "&amp;" => "&", "&lt;" => "<", "&gt;" => ">", "&nbsp;" => " ", "&iexcl;" => "¡", "&cent;" => "¢", "&pound;" => "£", "&curren;" => "¤", "&yen;" => "¥", "&brvbar;" => "¦", "&sect;" => "§", "&uml;" => "¨", "&copy;" => "©", "&ordf;" => "ª", "&laquo;" => "«", "&not;" => "¬", "&shy;" => "­", "&reg;" => "®", "&macr;" => "¯", "&deg;" => "°", "&plusmn;" => "±", "&sup2;" => "²", "&sup3;" => "³", "&acute;" => "´", "&micro;" => "µ", "&para;" => "¶", "&middot;" => "·", "&cedil;" => "¸", "&sup1;" => "¹", "&ordm;" => "º", "&raquo;" => "»", "&frac14;" => "¼", "&frac12;" => "½", "&frac34;" => "¾", "&iquest;" => "¿", "&Agrave;" => "À", "&Aacute;" => "Á", "&Acirc;" => "Â", "&Atilde;" => "Ã", "&Auml;" => "Ä", "&Aring;" => "Å", "&AElig;" => "Æ", "&Ccedil;" => "Ç", "&Egrave;" => "È", "&Eacute;" => "É", "&Ecirc;" => "Ê", "&Euml;" => "Ë", "&Igrave;" => "Ì", "&Iacute;" => "Í", "&Icirc;" => "Î", "&Iuml;" => "Ï", "&ETH;" => "Ð", "&Ntilde;" => "Ñ", "&Ograve;" => "Ò", "&Oacute;" => "Ó", "&Ocirc;" => "Ô", "&Otilde;" => "Õ", "&Ouml;" => "Ö", "&times;" => "×", "&Oslash;" => "Ø", "&Ugrave;" => "Ù", "&Uacute;" => "Ú", "&Ucirc;" => "Û", "&Uuml;" => "Ü", "&Yacute;" => "Ý", "&THORN;" => "Þ", "&szlig;" => "ß", "&agrave;" => "à", "&aacute;" => "á", "&acirc;" => "â", "&atilde;" => "ã", "&auml;" => "ä", "&aring;" => "å", "&aelig;" => "æ", "&ccedil;" => "ç", "&egrave;" => "è", "&eacute;" => "é", "&ecirc;" => "ê", "&euml;" => "ë", "&igrave;" => "ì", "&iacute;" => "í", "&icirc;" => "î", "&iuml;" => "ï", "&eth;" => "ð", "&ntilde;" => "ñ", "&ograve;" => "ò", "&oacute;" => "ó", "&ocirc;" => "ô", "&otilde;" => "õ", "&ouml;" => "ö", "&divide;" => "÷", "&oslash;" => "ø", "&ugrave;" => "ù", "&uacute;" => "ú", "&ucirc;" => "û", "&uuml;" => "ü", "&yacute;" => "ý", "&thorn;" => "þ", "&yuml;" => "ÿ", "&OElig;" => "Œ", "&oelig;" => "œ", "&Scaron;" => "Š", "&scaron;" => "š", "&Yuml;" => "Ÿ", "&fnof;" => "ƒ", "&circ;" => "ˆ", "&tilde;" => "˜", "&Alpha;" => "Α", "&Beta;" => "Β", "&Gamma;" => "Γ", "&Delta;" => "Δ", "&Epsilon;" => "Ε", "&Zeta;" => "Ζ", "&Eta;" => "Η", "&Theta;" => "Θ", "&Iota;" => "Ι", "&Kappa;" => "Κ", "&Lambda;" => "Λ", "&Mu;" => "Μ", "&Nu;" => "Ν", "&Xi;" => "Ξ", "&Omicron;" => "Ο", "&Pi;" => "Π", "&Rho;" => "Ρ", "&Sigma;" => "Σ", "&Tau;" => "Τ", "&Upsilon;" => "Υ", "&Phi;" => "Φ", "&Chi;" => "Χ", "&Psi;" => "Ψ", "&Omega;" => "Ω", "&alpha;" => "α", "&beta;" => "β", "&gamma;" => "γ", "&delta;" => "δ", "&epsilon;" => "ε", "&zeta;" => "ζ", "&eta;" => "η", "&theta;" => "θ", "&iota;" => "ι", "&kappa;" => "κ", "&lambda;" => "λ", "&mu;" => "μ", "&nu;" => "ν", "&xi;" => "ξ", "&omicron;" => "ο", "&pi;" => "π", "&rho;" => "ρ", "&sigmaf;" => "ς", "&sigma;" => "σ", "&tau;" => "τ", "&upsilon;" => "υ", "&phi;" => "φ", "&chi;" => "χ", "&psi;" => "ψ", "&omega;" => "ω", "&thetasym;" => "ϑ", "&upsih;" => "ϒ", "&piv;" => "ϖ", "&ensp;" => " ", "&emsp;" => " ", "&thinsp;" => " ", "&zwnj;" => "‌", "&zwj;" => "‍", "&lrm;" => "‎", "&rlm;" => "‏", "&ndash;" => "–", "&mdash;" => "—", "&lsquo;" => "‘", "&rsquo;" => "’", "&sbquo;" => "‚", "&ldquo;" => "“", "&rdquo;" => "”", "&bdquo;" => "„", "&dagger;" => "†", "&Dagger;" => "‡", "&bull;" => "•", "&hellip;" => "…", "&permil;" => "‰", "&prime;" => "′", "&Prime;" => "″", "&lsaquo;" => "‹", "&rsaquo;" => "›", "&oline;" => "‾", "&frasl;" => "⁄", "&euro;" => "€", "&image;" => "ℑ", "&weierp;" => "℘", "&real;" => "ℜ", "&trade;" => "™", "&alefsym;" => "ℵ", "&larr;" => "←", "&uarr;" => "↑", "&rarr;" => "→", "&darr;" => "↓", "&harr;" => "↔", "&crarr;" => "↵", "&lArr;" => "⇐", "&uArr;" => "⇑", "&rArr;" => "⇒", "&dArr;" => "⇓", "&hArr;" => "⇔", "&forall;" => "∀", "&part;" => "∂", "&exist;" => "∃", "&empty;" => "∅", "&nabla;" => "∇", "&isin;" => "∈", "&notin;" => "∉", "&ni;" => "∋", "&prod;" => "∏", "&sum;" => "∑", "&minus;" => "−", "&lowast;" => "∗", "&radic;" => "√", "&prop;" => "∝", "&infin;" => "∞", "&ang;" => "∠", "&and;" => "∧", "&or;" => "∨", "&cap;" => "∩", "&cup;" => "∪", "&int;" => "∫", "&there4;" => "∴", "&sim;" => "∼", "&cong;" => "≅", "&asymp;" => "≈", "&ne;" => "≠", "&equiv;" => "≡", "&le;" => "≤", "&ge;" => "≥", "&sub;" => "⊂", "&sup;" => "⊃", "&nsub;" => "⊄", "&sube;" => "⊆", "&supe;" => "⊇", "&oplus;" => "⊕", "&otimes;" => "⊗", "&perp;" => "⊥", "&sdot;" => "⋅", "&lceil;" => "⌈", "&rceil;" => "⌉", "&lfloor;" => "⌊", "&rfloor;" => "⌋", "&lang;" => "〈", "&rang;" => "〉", "&loz;" => "◊", "&spades;" => "♠", "&clubs;" => "♣", "&hearts;" => "♥", "&diams;" => "♦" }
51
+ end
52
+
53
+ end
@@ -2,41 +2,59 @@
2
2
 
3
3
  module Gamefic
4
4
 
5
- class Keywords < Array
6
- def initialize(statement = '')
7
- if statement.kind_of?(Keywords)
8
- self.concat statement
9
- else
5
+ class Keywords < Array
6
+ def initialize(statement = '')
7
+ if statement.kind_of?(Keywords)
8
+ self.concat statement
9
+ else
10
10
  if statement.kind_of?(Array)
11
11
  statement = statement.join(' ')
12
12
  end
13
- self.concat statement.to_s.gsub(/[^a-z0-9]/i, ' ').strip.downcase.split(' ')
14
- end
15
- self.delete_if { |w|
16
- w.length < 2 or w == 'an' or w == 'the'
17
- }
18
- self.uniq!
19
- end
20
- def found_in(other)
21
- matches = 0.0
22
- self.each { |my_word|
23
- if (other.include?(my_word))
24
- matches = matches + 1.0
25
- else
26
- other.each { |other_word|
27
- if my_word.length < other_word.length
28
- if other_word[0, my_word.length] == my_word
29
- matches = matches + (my_word.length.to_f / other_word.length.to_f)
30
- end
31
- end
32
- }
33
- end
34
- }
35
- return matches
36
- end
37
- def to_s
38
- self.join(' ')
39
- end
40
- end
13
+ self.concat statement.to_s.gsub(/[^a-z0-9]/i, ' ').strip.downcase.split(' ')
14
+ end
15
+ # TODO: This routine is stubbed to allow any combination of letters and
16
+ # numbers as a keyword. Since we're doing this, there's a distinct
17
+ # possibility that the Keywords class can be deprecated.
18
+ #self.delete_if { |w|
19
+ # w.length < 2 or w == 'an' or w == 'the'
20
+ #}
21
+ #self.uniq!
22
+ self
23
+ end
24
+ def found_in(other, fuzzy = false)
25
+ matches = 0.0
26
+ self.each { |my_word|
27
+ if other.include?(my_word)
28
+ matches = matches + 1.0
29
+ else
30
+ other.each { |other_word|
31
+ if my_word.length < other_word.length
32
+ if other_word[0, my_word.length] == my_word and my_word.length > 2
33
+ matches = matches + (my_word.length.to_f / other_word.length.to_f)
34
+ end
35
+ elsif fuzzy
36
+ fuzzy_word = my_word
37
+ if fuzzy_word.end_with?('ies')
38
+ fuzzy_word = fuzzy_word[0..-4]
39
+ elsif fuzzy_word.end_with?('ae')
40
+ fuzzy_word = fuzzy_word[0..-3]
41
+ elsif fuzzy_word.end_with?('s') or fuzzy_word.end_with?('i')
42
+ fuzzy_word = fuzzy_word[0..-2]
43
+ end
44
+ if other_word[0, fuzzy_word.length] == fuzzy_word and fuzzy_word.length > 2
45
+ matches = matches + (fuzzy_word.length.to_f / other_word.length.to_f)
46
+ elsif fuzzy_word[0, other_word.length] == other_word and other_word.length > 2
47
+ matches = matches + (fuzzy_word.length.to_f / other_word.length.to_f)
48
+ end
49
+ end
50
+ }
51
+ end
52
+ }
53
+ return matches
54
+ end
55
+ def to_s
56
+ self.join(' ')
57
+ end
58
+ end
41
59
 
42
60
  end