gamefic 1.7.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +12 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +16 -0
  5. data/.solargraph.yml +5 -0
  6. data/CHANGELOG.md +10 -0
  7. data/Gemfile +7 -0
  8. data/LICENSE +20 -0
  9. data/README.md +28 -0
  10. data/Rakefile +10 -0
  11. data/gamefic.gemspec +27 -0
  12. data/lib/gamefic.rb +7 -7
  13. data/lib/gamefic/action.rb +66 -60
  14. data/lib/gamefic/active.rb +331 -280
  15. data/lib/gamefic/actor.rb +8 -5
  16. data/lib/gamefic/command.rb +9 -7
  17. data/lib/gamefic/core_ext/array.rb +27 -49
  18. data/lib/gamefic/core_ext/string.rb +25 -16
  19. data/lib/gamefic/describable.rb +21 -23
  20. data/lib/gamefic/element.rb +47 -31
  21. data/lib/gamefic/entity.rb +6 -12
  22. data/lib/gamefic/{matchable.rb → keywords.rb} +52 -50
  23. data/lib/gamefic/messaging.rb +43 -44
  24. data/lib/gamefic/node.rb +14 -5
  25. data/lib/gamefic/plot.rb +69 -91
  26. data/lib/gamefic/plot/darkroom.rb +80 -264
  27. data/lib/gamefic/plot/host.rb +42 -48
  28. data/lib/gamefic/plot/snapshot.rb +14 -19
  29. data/lib/gamefic/query.rb +15 -18
  30. data/lib/gamefic/query/base.rb +50 -37
  31. data/lib/gamefic/query/children.rb +0 -0
  32. data/lib/gamefic/query/descendants.rb +2 -2
  33. data/lib/gamefic/query/external.rb +18 -14
  34. data/lib/gamefic/query/family.rb +3 -7
  35. data/lib/gamefic/query/matches.rb +75 -67
  36. data/lib/gamefic/query/parent.rb +0 -0
  37. data/lib/gamefic/query/siblings.rb +0 -0
  38. data/lib/gamefic/query/text.rb +12 -12
  39. data/lib/gamefic/query/tree.rb +17 -0
  40. data/lib/gamefic/scene.rb +0 -2
  41. data/lib/gamefic/scene/activity.rb +24 -26
  42. data/lib/gamefic/scene/base.rb +71 -10
  43. data/lib/gamefic/scene/conclusion.rb +1 -3
  44. data/lib/gamefic/scene/multiple_choice.rb +19 -14
  45. data/lib/gamefic/scene/multiple_scene.rb +29 -20
  46. data/lib/gamefic/scene/pause.rb +8 -3
  47. data/lib/gamefic/scene/yes_or_no.rb +22 -10
  48. data/lib/gamefic/scriptable.rb +88 -0
  49. data/lib/gamefic/serialize.rb +223 -0
  50. data/lib/gamefic/subplot.rb +38 -35
  51. data/lib/gamefic/syntax.rb +15 -13
  52. data/lib/gamefic/version.rb +3 -3
  53. data/lib/gamefic/world.rb +18 -0
  54. data/lib/gamefic/world/callbacks.rb +135 -0
  55. data/lib/gamefic/world/commands.rb +184 -0
  56. data/lib/gamefic/{plot → world}/entities.rb +33 -35
  57. data/lib/gamefic/{plot → world}/playbook.rb +245 -240
  58. data/lib/gamefic/world/players.rb +37 -0
  59. data/lib/gamefic/world/scenes.rb +226 -0
  60. metadata +37 -88
  61. data/bin/gamefic +0 -9
  62. data/lib/gamefic/engine.rb +0 -7
  63. data/lib/gamefic/engine/base.rb +0 -59
  64. data/lib/gamefic/engine/tty.rb +0 -24
  65. data/lib/gamefic/grammar.rb +0 -13
  66. data/lib/gamefic/grammar/conjugator.rb +0 -20
  67. data/lib/gamefic/grammar/gender.rb +0 -11
  68. data/lib/gamefic/grammar/person.rb +0 -10
  69. data/lib/gamefic/grammar/plural.rb +0 -13
  70. data/lib/gamefic/grammar/pronouns.rb +0 -106
  71. data/lib/gamefic/grammar/tense.rb +0 -6
  72. data/lib/gamefic/grammar/verb_set.rb +0 -43
  73. data/lib/gamefic/grammar/verbs.rb +0 -26
  74. data/lib/gamefic/grammar/word_adapter.rb +0 -49
  75. data/lib/gamefic/plot/articles.rb +0 -22
  76. data/lib/gamefic/plot/callbacks.rb +0 -126
  77. data/lib/gamefic/plot/commands.rb +0 -120
  78. data/lib/gamefic/plot/players.rb +0 -15
  79. data/lib/gamefic/plot/scenes.rb +0 -187
  80. data/lib/gamefic/plot/theater.rb +0 -73
  81. data/lib/gamefic/plot/you_mount.rb +0 -22
  82. data/lib/gamefic/scene/custom.rb +0 -9
  83. data/lib/gamefic/script.rb +0 -13
  84. data/lib/gamefic/script/base.rb +0 -42
  85. data/lib/gamefic/script/file.rb +0 -14
  86. data/lib/gamefic/script/text.rb +0 -14
  87. data/lib/gamefic/shell.rb +0 -76
  88. data/lib/gamefic/source.rb +0 -14
  89. data/lib/gamefic/source/base.rb +0 -12
  90. data/lib/gamefic/source/file.rb +0 -23
  91. data/lib/gamefic/source/text.rb +0 -16
  92. data/lib/gamefic/tester.rb +0 -19
  93. data/lib/gamefic/text.rb +0 -8
  94. data/lib/gamefic/text/ansi.rb +0 -53
  95. data/lib/gamefic/text/html.rb +0 -68
  96. data/lib/gamefic/text/html/conversions.rb +0 -250
  97. data/lib/gamefic/text/html/entities.rb +0 -9
  98. data/lib/gamefic/tty.rb +0 -10
  99. data/lib/gamefic/user.rb +0 -7
  100. data/lib/gamefic/user/base.rb +0 -29
  101. data/lib/gamefic/user/tty.rb +0 -38
@@ -1,126 +0,0 @@
1
- module Gamefic
2
-
3
- module Plot::Callbacks
4
- # Add a block to be executed on preparation of every turn.
5
- #
6
- # @example Increment a turn counter
7
- # turn = 0
8
- # on_ready do
9
- # turn += 1
10
- # end
11
- #
12
- def on_ready &block
13
- p_ready_procs.push block
14
- end
15
-
16
- # Add a block to be executed after the Plot is finished updating a turn.
17
- #
18
- def on_update &block
19
- p_update_procs.push block
20
- end
21
-
22
- # Add a block to be executed for each player at the beginning of a turn.
23
- #
24
- # @example Tell the player how many turns they've played.
25
- # on_player_ready do |player|
26
- # player[:turns] ||= 0
27
- # if player[:turns] > 0
28
- # player.tell "Turn #{player[:turns]}"
29
- # end
30
- # player[:turns] += 1
31
- # end
32
- #
33
- # @yieldparam [Gamefic::Performance]
34
- def on_player_ready &block
35
- p_player_ready_procs.push block
36
- end
37
-
38
- # Add a block to be executed for each player before an update.
39
- #
40
- # @yieldparam[Character]
41
- def before_player_update &block
42
- p_before_player_update_procs.push block
43
- end
44
-
45
- # Add a block to be executed for each player at the end of a turn.
46
- #
47
- # @yieldparam [Character]
48
- def on_player_update &block
49
- p_player_update_procs.push block
50
- end
51
-
52
- private
53
-
54
- # Execute the on_ready blocks. This method is typically called by the
55
- # Plot while beginning a turn.
56
- #
57
- def call_ready
58
- p_ready_procs.each { |p| p.call }
59
- end
60
-
61
- # Execute the on_update blocks. This method is typically called by the
62
- # Plot while ending a turn.
63
- #
64
- def call_update
65
- p_update_procs.each { |p| p.call }
66
- end
67
-
68
- # Execute the before_player_update blocks for each player. This method is
69
- # typically called by the Plot while updating a turn, immediately before
70
- # processing player input.
71
- #
72
- def call_before_player_update
73
- p_players.each { |player|
74
- player.flush
75
- p_before_player_update_procs.each { |block| block.call player }
76
- }
77
- end
78
-
79
- # Execute the on_player_ready blocks for each player. This method is
80
- # typically called by the Plot while beginning a turn, immediately after
81
- # the on_ready blocks.
82
- #
83
- def call_player_ready
84
- p_players.each { |player|
85
- unless player.next_scene.nil?
86
- player.cue player.next_scene
87
- end
88
- player.cue default_scene if player.scene.nil?
89
- #player.prepare nil
90
- #player.cue this_scene #unless player.scene.class == this_scene
91
- p_player_ready_procs.each { |block| block.call player }
92
- }
93
- end
94
-
95
- # Execute the on_player_update blocks for each player. This method is
96
- # typically called by the Plot while ending a turn, immediately before the
97
- # on_ready blocks.
98
- #
99
- def call_player_update
100
- p_players.each { |player|
101
- p_player_update_procs.each { |block| block.call player }
102
- }
103
- end
104
-
105
- def p_ready_procs
106
- @p_ready_procs ||= []
107
- end
108
-
109
- def p_update_procs
110
- @p_update_procs ||= []
111
- end
112
-
113
- def p_before_player_update_procs
114
- @p_before_player_update_procs ||= []
115
- end
116
-
117
- def p_player_ready_procs
118
- @p_player_ready_procs ||= []
119
- end
120
-
121
- def p_player_update_procs
122
- @p_player_update_procs ||= []
123
- end
124
- end
125
-
126
- end
@@ -1,120 +0,0 @@
1
- require 'gamefic/action'
2
-
3
- module Gamefic
4
-
5
- module Plot::Commands
6
- # Create an Action that responds to a command.
7
- # An Action uses the command argument to identify the imperative verb that
8
- # triggers the action.
9
- # It can also accept queries to tokenize the remainder of the input and
10
- # filter for particular entities or properties.
11
- # The block argument contains the code to be executed when the input
12
- # matches all of the Action's criteria (i.e., verb and queries).
13
- #
14
- # @example A simple Action.
15
- # respond :salute do |actor|
16
- # actor.tell "Hello, sir!"
17
- # end
18
- # # The command "salute" will respond "Hello, sir!"
19
- #
20
- # @example An Action that accepts a Character
21
- # respond :salute, Use.visible(Character) do |actor, character|
22
- # actor.tell "#{The character} returns your salute."
23
- # end
24
- #
25
- # @param command [Symbol] An imperative verb for the command
26
- # @param queries [Array<Query::Base>] Filters for the command's tokens
27
- # @yieldparam [Character]
28
- def respond(command, *queries, &proc)
29
- playbook.respond(command, *queries, &proc)
30
- end
31
-
32
- # Create a Meta Action that responds to a command.
33
- # Meta Actions are very similar to standard Actions, except the Plot
34
- # understands them to be commands that operate above and/or outside of the
35
- # actual game world. Examples of Meta Actions are commands that report the
36
- # player's current score, save and restore saved games, or list the game's
37
- # credits.
38
- #
39
- # @example A simple Meta Action
40
- # meta :credits do |actor|
41
- # actor.tell "This game was written by John Smith."
42
- # end
43
- #
44
- # @param command [Symbol] An imperative verb for the command
45
- # @param queries [Array<Query::Base>] Filters for the command's tokens
46
- # @yieldparam [Character]
47
- def meta(command, *queries, &proc)
48
- playbook.meta command, *queries, &proc
49
- end
50
-
51
- # @deprecated
52
- def action(command, *queries, &proc)
53
- respond command, *queries, &proc
54
- end
55
-
56
- # Declare a dismabiguation response for actions.
57
- # The disambigurator is executed when an action expects an argument to
58
- # reference a specific entity but its query matched more than one. For
59
- # example, "red" might refer to either a red key or a red book.
60
- #
61
- # If a disambiguator is not defined, the playbook will use its default
62
- # implementation.
63
- #
64
- # @example Tell the player the list of ambiguous entities.
65
- # disambiguate do |actor, entities|
66
- # actor.tell "I don't know which you mean: #{entities.join_or}."
67
- # end
68
- #
69
- # @yieldparam [Gamefic::Character]
70
- # @yieldparam [Array<Gamefic::Entity>]
71
- def disambiguate &block
72
- playbook.disambiguate &block
73
- end
74
-
75
- # Validate an order before a character can execute its command.
76
- #
77
- # @yieldparam [Gamefic::Director::Order]
78
- def validate &block
79
- playbook.validate &block
80
- end
81
-
82
- # Create an alternate Syntax for an Action.
83
- # The command and its translation can be parameterized.
84
- #
85
- # @example Create a synonym for the Inventory Action.
86
- # interpret "catalogue", "inventory"
87
- # # The command "catalogue" will be translated to "inventory"
88
- #
89
- # @example Create a parameterized synonym for the Look Action.
90
- # interpret "scrutinize :entity", "look :entity"
91
- # # The command "scrutinize chair" will be translated to "look chair"
92
- #
93
- # @param command [String] The format of the original command
94
- # @param translation [String] The format of the translated command
95
- # @return [Syntax] the Syntax object
96
- def interpret command, translation
97
- playbook.interpret command, translation
98
- end
99
-
100
- # @deprecated
101
- def xlate command, translation
102
- interpret command, translation
103
- end
104
-
105
- # Get an Array of available verbs.
106
- #
107
- # @return [Array<String>]
108
- def verbs
109
- playbook.verbs.map { |v| v.to_s }.reject{ |v| v.start_with?('_') }
110
- end
111
-
112
- # Get an Array of all Actions defined in the Plot.
113
- #
114
- # @return [Array<Action>]
115
- def actions
116
- playbook.actions
117
- end
118
- end
119
-
120
- end
@@ -1,15 +0,0 @@
1
- module Gamefic
2
-
3
- module Plot::Players
4
- def players
5
- p_players.clone
6
- end
7
-
8
- private
9
-
10
- def p_players
11
- @p_players ||= []
12
- end
13
- end
14
-
15
- end
@@ -1,187 +0,0 @@
1
- module Gamefic
2
-
3
- module Plot::Scenes
4
- def default_scene
5
- @default_scene ||= Scene::Activity
6
- end
7
-
8
- def default_conclusion
9
- @default_conclusion ||= Scene::Conclusion
10
- end
11
-
12
- # Add a block to be executed when a player is added to the game.
13
- # Each Plot can only have one introduction. Subsequent calls will
14
- # overwrite the existing one.
15
- #
16
- # @example Welcome the player to the game
17
- # introduction do |actor|
18
- # actor.tell "Welcome to the game!"
19
- # end
20
- #
21
- # @yieldparam [Gamefic::Character]
22
- def introduction(&proc)
23
- @introduction = proc
24
- end
25
-
26
- # Introduce a player to the game.
27
- # This method is typically called by the Engine that manages game execution.
28
- #
29
- # @param [Gamefic::Character]
30
- def introduce(player)
31
- player.playbooks.push playbook unless player.playbooks.include?(playbook)
32
- player.cue default_scene
33
- p_players.push player
34
- @introduction.call(player) unless @introduction.nil?
35
- end
36
-
37
- # Create a multiple-choice scene.
38
- # The user will be required to make a valid choice to continue.
39
- #
40
- # @yieldparam [Gamefic::Character]
41
- # @yieldparam [Gamefic::Scene::Data::MultipleChoice]
42
- def multiple_choice *choices, &block
43
- s = Scene::MultipleChoice.subclass do |actor, scene|
44
- scene.options.concat choices
45
- scene.on_finish &block
46
- end
47
- scene_classes.push s
48
- s
49
- end
50
-
51
- # Create a yes-or-no scene.
52
- # The user will be required to answer Yes or No to continue.
53
- #
54
- # @yieldparam [Gamefic::Character]
55
- # @yieldparam [Gamefic::Scene::YesOrNo]
56
- def yes_or_no prompt = nil, &block
57
- s = Scene::YesOrNo.subclass do |actor, scene|
58
- scene.prompt = prompt
59
- scene.on_finish &block
60
- end
61
- scene_classes.push s
62
- s
63
- end
64
-
65
- # Create a scene with custom processing on user input.
66
- #
67
- # @example Echo the user's response
68
- # @scene = question 'What do you say?' do |actor, scene|
69
- # actor.tell "You said #{scene.input}"
70
- # end
71
- #
72
- # @yieldparam [Gamefic::Character]
73
- # @yieldparam [Gamefic::Scene::YesOrNo]
74
- def question prompt = 'What is your answer?', &block
75
- s = Scene::Custom.subclass do |actor, scene|
76
- scene.prompt = prompt
77
- scene.on_finish &block
78
- end
79
- scene_classes.push s
80
- s
81
- end
82
-
83
- # Create a scene that pauses the game.
84
- # This scene will execute the specified block and wait for input from the
85
- # the user (e.g., pressing Enter) to continue.
86
- #
87
- # @param prompt [String] The text to display when prompting the user to continue.
88
- # @yieldparam [Gamefic::Character]
89
- # @yieldparam [Gamefic::Scene::Pause]
90
- def pause prompt = nil, &block
91
- s = Scene::Pause.subclass do |actor, scene|
92
- scene.prompt = prompt unless prompt.nil?
93
- block.call(actor, scene) unless block.nil?
94
- end
95
- scene_classes.push s
96
- s
97
- end
98
-
99
- # Create a conclusion.
100
- # The game (or the character's participation in it) will end after this
101
- # scene is complete.
102
- #
103
- # @yieldparam [Gamefic::Character]
104
- # @yieldparam [Gamefic::Scene::Conclusion]
105
- def conclusion &block
106
- s = Scene::Conclusion.subclass &block
107
- scene_classes.push s
108
- s
109
- end
110
-
111
- # Create a custom scene.
112
- #
113
- # Custom scenes should always specify the next scene to be cued or
114
- # prepared. If not, the scene will get repeated on the next turn.
115
- #
116
- # This method creates a Scene::Custom by default. You can customize other
117
- # scene types by specifying the class to create.
118
- #
119
- # @example Ask the user for a name
120
- # @scene = custom do |scene|
121
- # data.prompt = "What's your name?"
122
- # scene.on_finish do |actor, data|
123
- # actor.name = data.input
124
- # actor.tell "Hello, #{actor.name}!"
125
- # actor.cue :active
126
- # end
127
- # end
128
- #
129
- # @param cls [Class] The class of scene to be instantiated.
130
- # @yieldparam [Gamefic::Character]
131
- # @yieldparam [Scene::Custom] The instantiated scene.
132
- def custom cls = Scene::Custom, &block
133
- s = cls.subclass &block
134
- scene_classes.push s
135
- s
136
- end
137
-
138
- # Choose a new scene based on a list of options.
139
- # This is a specialized type of multiple-choice scene that determines
140
- # which scene to cue based on a Hash of choices and scene keys.
141
- #
142
- # @example Select a scene
143
- # scene_one = pause do |actor|
144
- # actor.tell "You went to scene one"
145
- # end
146
- #
147
- # scene_two = pause do |actor|
148
- # actor.tell "You went to scene two"
149
- # end
150
- #
151
- # select_one_or_two = multiple_scene "One" => scene_one, "Two" => scene_two
152
- #
153
- # introduction do |actor|
154
- # actor.cue select_one_or_two # The actor will be prompted to select "one" or "two" and get sent to the corresponding scene
155
- # end
156
- #
157
- # @example Customize options
158
- # scene_one = pause # do...
159
- # scene_two = pause # do...
160
- #
161
- # # Some event in the game sets actor[:can_go_to_scene_two] to true
162
- #
163
- # select_one_or_two = multiple_scene do |actor, scene|
164
- # scene.map "Go to scene one", scene_one
165
- # scene.map "Go to scene two", scene_two if actor[:can_go_to_scene_two]
166
- # end
167
- #
168
- # @param map [Hash] A Hash of options and associated scenes.
169
- # @yieldparam [Gamefic::Character]
170
- # @yieldparam [Gamefic::Scene::MultipleScene]
171
- def multiple_scene map = {}, &block
172
- s = Scene::MultipleScene.subclass do |actor, scene|
173
- map.each_pair { |k, v|
174
- scene.map k, v
175
- }
176
- block.call actor, scene unless block.nil?
177
- end
178
- scene_classes.push s
179
- s
180
- end
181
-
182
- def scene_classes
183
- @scene_classes ||= []
184
- end
185
- end
186
-
187
- end