carps 0.2.1

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 (157) hide show
  1. data/COPYING +674 -0
  2. data/GEM_DESCRIPTION +10 -0
  3. data/History.txt +4 -0
  4. data/Manifest.txt +156 -0
  5. data/PostInstall.txt +20 -0
  6. data/README.rdoc +141 -0
  7. data/Rakefile +28 -0
  8. data/bin/carps +123 -0
  9. data/bin/carps_init +29 -0
  10. data/bin/carps_ipc_test +44 -0
  11. data/bin/carps_mod_saver_test +71 -0
  12. data/bin/carps_mod_test +62 -0
  13. data/config/website.yml +2 -0
  14. data/features/character_sheet.feature +40 -0
  15. data/features/crash.feature +15 -0
  16. data/features/crypt.feature +22 -0
  17. data/features/dice.feature +173 -0
  18. data/features/dm.feature +36 -0
  19. data/features/dmll.feature +51 -0
  20. data/features/edit.feature +10 -0
  21. data/features/email.feature +29 -0
  22. data/features/interface.feature +17 -0
  23. data/features/ipc.feature +10 -0
  24. data/features/mailbox.feature +33 -0
  25. data/features/mod.feature +31 -0
  26. data/features/parser.feature +9 -0
  27. data/features/persistent_protocol.feature +14 -0
  28. data/features/player.feature +22 -0
  29. data/features/player_turn.feature +29 -0
  30. data/features/random.feature +15 -0
  31. data/features/rule.feature +19 -0
  32. data/features/safety.feature +13 -0
  33. data/features/sessions.feature +16 -0
  34. data/features/start_dm.feature +18 -0
  35. data/features/start_player.feature +8 -0
  36. data/features/step_definitions/common_steps.rb +170 -0
  37. data/features/steps/character_sheet.rb +89 -0
  38. data/features/steps/crash.rb +27 -0
  39. data/features/steps/crypt.rb +166 -0
  40. data/features/steps/dice.rb +91 -0
  41. data/features/steps/dm.rb +147 -0
  42. data/features/steps/dmll.rb +47 -0
  43. data/features/steps/edit.rb +7 -0
  44. data/features/steps/email.rb +108 -0
  45. data/features/steps/general.rb +5 -0
  46. data/features/steps/interface.rb +64 -0
  47. data/features/steps/ipc.rb +22 -0
  48. data/features/steps/mailbox.rb +126 -0
  49. data/features/steps/mod.rb +25 -0
  50. data/features/steps/parser.rb +23 -0
  51. data/features/steps/persistent_protocol.rb +29 -0
  52. data/features/steps/player.rb +82 -0
  53. data/features/steps/player_turn.rb +56 -0
  54. data/features/steps/random.rb +47 -0
  55. data/features/steps/rule.rb +53 -0
  56. data/features/steps/safety.rb +17 -0
  57. data/features/steps/sessions.rb +37 -0
  58. data/features/steps/start_dm.rb +46 -0
  59. data/features/steps/start_player.rb +65 -0
  60. data/features/steps/timeout.rb +32 -0
  61. data/features/steps/type_verification.rb +36 -0
  62. data/features/steps/wizard.rb +123 -0
  63. data/features/support/common.rb +29 -0
  64. data/features/support/env.rb +14 -0
  65. data/features/support/matchers.rb +11 -0
  66. data/features/timeout.feature +11 -0
  67. data/features/type_verification.feature +48 -0
  68. data/features/wizard.feature +50 -0
  69. data/lib/carps/crypt/accept_handshake.rb +40 -0
  70. data/lib/carps/crypt/default_messages.rb +29 -0
  71. data/lib/carps/crypt/handshake.rb +41 -0
  72. data/lib/carps/crypt/mailbox.rb +265 -0
  73. data/lib/carps/crypt/mailer.rb +220 -0
  74. data/lib/carps/crypt/peer.rb +123 -0
  75. data/lib/carps/crypt/public_key.rb +60 -0
  76. data/lib/carps/crypt.rb +23 -0
  77. data/lib/carps/email/config.rb +122 -0
  78. data/lib/carps/email/imap.rb +156 -0
  79. data/lib/carps/email/smtp.rb +119 -0
  80. data/lib/carps/email/string.rb +30 -0
  81. data/lib/carps/email.rb +21 -0
  82. data/lib/carps/mod/action.rb +36 -0
  83. data/lib/carps/mod/answers.rb +76 -0
  84. data/lib/carps/mod/client_turn.rb +88 -0
  85. data/lib/carps/mod/dice.rb +360 -0
  86. data/lib/carps/mod/dm/interface.rb +160 -0
  87. data/lib/carps/mod/dm/mod.rb +409 -0
  88. data/lib/carps/mod/dm/reporter.rb +112 -0
  89. data/lib/carps/mod/dm/resource.rb +88 -0
  90. data/lib/carps/mod/dm/room.rb +33 -0
  91. data/lib/carps/mod/interface.rb +73 -0
  92. data/lib/carps/mod/launch.rb +108 -0
  93. data/lib/carps/mod/mod.rb +52 -0
  94. data/lib/carps/mod/player/interface.rb +76 -0
  95. data/lib/carps/mod/player/mod.rb +109 -0
  96. data/lib/carps/mod/question.rb +63 -0
  97. data/lib/carps/mod/rule.rb +112 -0
  98. data/lib/carps/mod/sheet/character.rb +82 -0
  99. data/lib/carps/mod/sheet/editor.rb +97 -0
  100. data/lib/carps/mod/sheet/new_sheet.rb +71 -0
  101. data/lib/carps/mod/sheet/schema.rb +84 -0
  102. data/lib/carps/mod/sheet/type.rb +161 -0
  103. data/lib/carps/mod/sheet/verifier.rb +41 -0
  104. data/lib/carps/mod/status_report.rb +51 -0
  105. data/lib/carps/mod.rb +40 -0
  106. data/lib/carps/protocol/keyword.rb +104 -0
  107. data/lib/carps/protocol/message.rb +138 -0
  108. data/lib/carps/protocol.rb +19 -0
  109. data/lib/carps/service/client_parser.rb +34 -0
  110. data/lib/carps/service/dm/config.rb +76 -0
  111. data/lib/carps/service/dm/mailer.rb +70 -0
  112. data/lib/carps/service/dm/new_game.rb +101 -0
  113. data/lib/carps/service/dm/start.rb +47 -0
  114. data/lib/carps/service/game.rb +101 -0
  115. data/lib/carps/service/interface.rb +174 -0
  116. data/lib/carps/service/invite.rb +79 -0
  117. data/lib/carps/service/mod.rb +43 -0
  118. data/lib/carps/service/player/config.rb +78 -0
  119. data/lib/carps/service/player/mailer.rb +49 -0
  120. data/lib/carps/service/player/start.rb +60 -0
  121. data/lib/carps/service/server_parser.rb +33 -0
  122. data/lib/carps/service/session.rb +96 -0
  123. data/lib/carps/service/start/config.rb +71 -0
  124. data/lib/carps/service/start/interface.rb +101 -0
  125. data/lib/carps/service/start/mailer.rb +46 -0
  126. data/lib/carps/service.rb +35 -0
  127. data/lib/carps/test.rb +34 -0
  128. data/lib/carps/ui/colour.rb +28 -0
  129. data/lib/carps/ui/error.rb +39 -0
  130. data/lib/carps/ui/highlight.rb +32 -0
  131. data/lib/carps/ui/question.rb +63 -0
  132. data/lib/carps/ui/warn.rb +37 -0
  133. data/lib/carps/ui.rb +21 -0
  134. data/lib/carps/util/config.rb +162 -0
  135. data/lib/carps/util/editor.rb +147 -0
  136. data/lib/carps/util/error.rb +75 -0
  137. data/lib/carps/util/files.rb +48 -0
  138. data/lib/carps/util/init.rb +93 -0
  139. data/lib/carps/util/process.rb +150 -0
  140. data/lib/carps/util/timeout.rb +31 -0
  141. data/lib/carps/util/windows.rb +29 -0
  142. data/lib/carps/util.rb +24 -0
  143. data/lib/carps/wizard/dm.rb +41 -0
  144. data/lib/carps/wizard/player.rb +40 -0
  145. data/lib/carps/wizard/steps.rb +494 -0
  146. data/lib/carps/wizard/wizard.rb +126 -0
  147. data/lib/carps/wizard.rb +21 -0
  148. data/lib/carps.rb +45 -0
  149. data/permission +16 -0
  150. data/script/console +10 -0
  151. data/script/destroy +14 -0
  152. data/script/generate +14 -0
  153. data/tasks/readme_site.rake +28 -0
  154. data/test/test_carps.rb +11 -0
  155. data/test/test_helper.rb +3 -0
  156. data/website/index.html +271 -0
  157. metadata +304 -0
@@ -0,0 +1,409 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/mod"
19
+
20
+ require "carps/ui"
21
+
22
+ module CARPS
23
+
24
+ module DM
25
+ # Class for DM mods
26
+ #
27
+ # Functions as a facade to the resource, mailer and reporter classes.
28
+ #
29
+ # Subclasses should override schema and semantic_verifier
30
+ #
31
+ # FIXME: This class is WAY too big
32
+ class Mod < CARPS::Mod
33
+
34
+ # Initialize with a resource manager
35
+ def initialize resource
36
+ @resource = resource
37
+ new_reporter
38
+ @players = {}
39
+ @npcs = {}
40
+ @entities = {}
41
+ @monikers = {}
42
+ @mails = {}
43
+ end
44
+
45
+ # Invite a new player
46
+ def invite addr
47
+ @mailer.invite addr
48
+ end
49
+
50
+ # Save the game
51
+ def save
52
+ @mailer.save self
53
+ end
54
+
55
+ # Edit a sheet
56
+ def edit_sheet name
57
+ with_entity name do |char|
58
+ editor.fill char
59
+ end
60
+ end
61
+
62
+ # Ask a question of the player
63
+ def ask_player player
64
+ with_player player do
65
+ edit = Editor.load
66
+ question = edit.edit "# Enter question for #{player}"
67
+ @reporter.ask_player player, question
68
+ end
69
+ end
70
+
71
+ # Ask a question of everyone
72
+ def ask_everyone
73
+ edit = Editor.load
74
+ question = edit.edit "# Enter question for everyone"
75
+ @players.each_key do |player|
76
+ @reporter.ask_player player, question
77
+ end
78
+ end
79
+
80
+ # Delete questions for a player
81
+ def delete_questions player
82
+ with_player player do
83
+ @reporter.delete_questions player
84
+ end
85
+ end
86
+
87
+ # Update a player's report
88
+ def update_player player, report
89
+ @reporter.update_player player, report
90
+ end
91
+
92
+ # Delete all questions
93
+ def delete_all_questions
94
+ @reporter.delete_all_questions
95
+ end
96
+
97
+ # Delete all reports
98
+ def delete_all_reports
99
+ @reporter.delete_reports
100
+ end
101
+
102
+ # Delete a player's report
103
+ def delete_report player
104
+ with_player player do
105
+ @reporter.update_player player, ""
106
+ end
107
+ end
108
+
109
+ # All players are in this room
110
+ def everyone_in room
111
+ @resource.players_in @players.keys, room
112
+ end
113
+
114
+ # A player is in this room
115
+ def player_in player, room
116
+ with_player player do
117
+ @resource.player_in player, room
118
+ end
119
+ end
120
+
121
+ # Create a new npc
122
+ def new_npc type, name
123
+ if moniker_available? name
124
+ if char = @resource.new_npc(type)
125
+ editor.validate char
126
+ @npcs[name] = char
127
+ @entities[name] = :npc
128
+ end
129
+ end
130
+ end
131
+
132
+ # Inspect all turns
133
+ def inspect_reports
134
+ turns = @reporter.player_turns @players.keys
135
+ turns.each do |moniker, t|
136
+ puts "Upcoming turn for " + moniker
137
+ t.preview
138
+ end
139
+ end
140
+
141
+ # Inspect a player's turn
142
+ def inspect_turn player
143
+ with_player player do
144
+ turn = @reporter.player_turn player
145
+ turn.preview
146
+ end
147
+ end
148
+
149
+ # Next turn
150
+ def next_turn
151
+ # Save the game
152
+ send_reports
153
+ new_reporter
154
+ save
155
+ end
156
+
157
+ # Create a report that all players will see
158
+ def create_global_report
159
+ e = Editor.load
160
+ global = e.edit "# Enter report for all players."
161
+ @players.each_key do |player|
162
+ @reporter.update_player player, global
163
+ end
164
+ end
165
+
166
+ # Edit the report for a player
167
+ def tell player
168
+ with_player player do
169
+ @reporter.edit player
170
+ end
171
+ end
172
+
173
+ # Add a player
174
+ def add_player email
175
+ valid = false
176
+ until valid
177
+ moniker = UI::question "Enter moniker for " + email
178
+ valid = moniker_available? moniker
179
+ end
180
+ add_known_player moniker, email
181
+ end
182
+
183
+ # Add a player with a moniker
184
+ def add_known_player moniker, email
185
+ @monikers[moniker] = email
186
+ @mails[email] = moniker
187
+ @entities[moniker] = :player
188
+ end
189
+
190
+ # Describe an entity
191
+ def describe name
192
+ with_entity2 name,
193
+ lambda {unsafe_describe_player name},
194
+ lambda {unsafe_describe_npc name}
195
+ end
196
+
197
+ # Describe all npcs
198
+ def list_npcs
199
+ puts "The NPCs are:"
200
+ @npcs.each_key do |npc|
201
+ puts "\n#{npc}:"
202
+ unsafe_describe_npc npc
203
+ end
204
+ end
205
+
206
+ # Return player stats
207
+ def player_stats player
208
+ @players[player]
209
+ end
210
+
211
+ # Return npc stats
212
+ def npc_stats npc
213
+ @npcs[npc]
214
+ end
215
+
216
+ # List all the players
217
+ def list_players
218
+ puts "The players are:"
219
+ @players.each_key do |player|
220
+ unsafe_describe_player player
221
+ end
222
+ end
223
+
224
+ # Check for mail
225
+ def check_mail
226
+ if mail = @mailer.check(Sheet::NewSheet)
227
+ unless @mails.member? mail.from
228
+ add_player mail.from
229
+ end
230
+ with_valid_mail mail do |moniker|
231
+ new_character_sheet moniker, Sheet::Player.new(self, moniker, mail.dump)
232
+ end
233
+ elsif mail = @mailer.check(Answers)
234
+ with_valid_mail mail do |moniker|
235
+ new_answer moniker, mail
236
+ end
237
+ end
238
+
239
+ if mail
240
+ true
241
+ else
242
+ puts "No new mail."
243
+ false
244
+ end
245
+
246
+ end
247
+
248
+ # A sheet has been updated so inform the player
249
+ def sheet_updated moniker
250
+ @reporter.sheet moniker, @players[moniker]
251
+ end
252
+
253
+ protected
254
+
255
+ # Perform an action with several entities. Doesn't matter if the entity is a player or NPC.
256
+ #
257
+ # blk.arity must == names.length
258
+ def with_entities *names, &blk
259
+ entities = names.map {|name| find_entity_unsafe name}
260
+ if entities.all?
261
+ if blk.arity == entities.length
262
+ blk.call *entities
263
+ else
264
+ raise ArgumentError, "blk.arity != names.length"
265
+ end
266
+ else
267
+ UI::put_error "Some entities did not exist."
268
+ return
269
+ end
270
+ end
271
+
272
+ # Find an entity. UNSAFE.
273
+ def find_entity_unsafe name
274
+ entity = nil
275
+ unless entity = @players[name]
276
+ entity = @npcs[name]
277
+ end
278
+ entity
279
+ end
280
+
281
+ # Perform an action with an entity. Doesn't matter if the entity is a player or NPC.
282
+ def with_entity name
283
+ with_entity2 name,
284
+ lambda {yield @players[name]},
285
+ lambda {yield @npcs[name]}
286
+ end
287
+
288
+ # Perform an action with an entity,
289
+ # where it does not matter if the entity is a player or an NPC.
290
+
291
+ # Perform an action with an entity.
292
+ #
293
+ # The first Proc is called if it's a Player
294
+ #
295
+ # The second is called if it's an NPC
296
+ def with_entity2 name, player_proc, npc_proc
297
+ case @entities[name]
298
+ when :player
299
+ execute_sheet_proc player_proc, @players[name]
300
+ when :npc
301
+ execute_sheet_proc npc_proc, @npcs[name]
302
+ when nil
303
+ UI::put_error "Unknown entity: #{name}"
304
+ end
305
+ end
306
+
307
+ # Execute a proc, passing a sheet if the arity is 1
308
+ def execute_sheet_proc func, sheet
309
+ if func.arity == 0
310
+ func.call
311
+ elsif func.arity == 1
312
+ func.call sheet
313
+ else
314
+ raise ArgumentError, "'func' must have arity of 0 or 1"
315
+ end
316
+ end
317
+
318
+ # Register a new character sheet
319
+ def new_character_sheet moniker, sheet
320
+ UI::highlight "New character sheet for #{moniker}"
321
+ editor.validate sheet
322
+ @players[moniker] = sheet
323
+ end
324
+
325
+ def unsafe_describe_npc npc
326
+ puts @npcs[npc].emit
327
+ end
328
+
329
+ def unsafe_describe_player player
330
+ mail = @monikers[player]
331
+ puts mail + " aka " + player + " aka: "
332
+ puts @players[player].emit
333
+ end
334
+
335
+ # Moniker is available?
336
+ def moniker_available? mon
337
+ not @entities.member? mon
338
+ end
339
+
340
+ # Send the reports
341
+ def send_reports
342
+ turns = @reporter.player_turns @players.keys
343
+ turns.each do |moniker, turn|
344
+ addr = @monikers[moniker]
345
+ @mailer.relay addr, turn
346
+ end
347
+ end
348
+
349
+ # Search for mail
350
+ def search mail
351
+ found = nil
352
+ mail.each do |moniker, inbox|
353
+ unless inbox.empty?
354
+ found = [moniker, inbox.shift]
355
+ break
356
+ end
357
+ end
358
+ return found
359
+ end
360
+
361
+ # Print the answer
362
+ def new_answer moniker, answer
363
+ answer.from = moniker
364
+ answer.display
365
+ end
366
+
367
+ def with_valid_mail mail
368
+ moniker = @mails[mail.from]
369
+ if moniker
370
+ yield moniker
371
+ else
372
+ warn "BUG", "Mod received mail from unregistered player #{mail.from}"
373
+ end
374
+ end
375
+
376
+ # If the player exists, continue
377
+ def with_player player
378
+ if player? player
379
+ yield
380
+ else
381
+ UI::put_error "Unknown player."
382
+ end
383
+ end
384
+
385
+ # Does a player exist?
386
+ def player? player
387
+ @players.member? player
388
+ end
389
+
390
+ # Only execute the block if the npc exists
391
+ def with_npc name
392
+ if @npcs.member? name
393
+ yield
394
+ else
395
+ UI::put_error "Unknown NPC."
396
+ end
397
+ end
398
+
399
+ # Create a new reporter
400
+ def new_reporter
401
+ @reporter = Reporter.new
402
+ @resource.reporter = @reporter
403
+ end
404
+
405
+ end
406
+
407
+ end
408
+
409
+ end
@@ -0,0 +1,112 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/mod"
19
+
20
+ require "carps/util"
21
+
22
+ module CARPS
23
+
24
+ # Used by the dungeon master to generate reports
25
+ #
26
+ # Subclasses should override the "player_turn" method
27
+ class Reporter
28
+
29
+ def initialize
30
+ @status = {}
31
+ @questions = {}
32
+ @sheets = {}
33
+ end
34
+
35
+ # Produce a ClientTurn for the player referred to by the moniker
36
+ def player_turn moniker
37
+ report = @status[moniker]
38
+ unless report
39
+ report = ""
40
+ end
41
+ status = StatusReport.new report
42
+ qtext = @questions[moniker]
43
+ unless qtext
44
+ qtext = []
45
+ end
46
+ questions = qtext.map {|q| que = Question.new q}
47
+ sheet = @sheets[moniker]
48
+ unless sheet
49
+ sheet = Sheet::Character.new({})
50
+ end
51
+ stats = sheet.attributes
52
+ new_sheet = Sheet::NewSheet.new stats
53
+ ClientTurn.new new_sheet, status, questions
54
+ end
55
+
56
+ # Produce a hash of email address to ClientTurn objects
57
+ def player_turns monikers
58
+ turns = {}
59
+ monikers.each do |moniker|
60
+ turns[moniker] = player_turn moniker
61
+ end
62
+ turns
63
+ end
64
+
65
+ # A character sheet has been changed
66
+ def sheet moniker, sheet
67
+ @sheets[moniker] = sheet
68
+ end
69
+
70
+ # Edit the report for a player
71
+ def edit player
72
+ editor = Editor.load
73
+ stat = @status[player]
74
+ unless stat
75
+ stat = ""
76
+ end
77
+ stat = "# Enter report for #{player}\n" + stat
78
+ @status[player] = editor.edit stat
79
+ end
80
+
81
+ # Inform the reporter of updates to a player's status report
82
+ def update_player player, status
83
+ @status[player] = status
84
+ end
85
+
86
+ # Ask a player some questions
87
+ def ask_player moniker, question
88
+ if @questions.member? moniker
89
+ @questions[moniker].push question
90
+ else
91
+ @questions[moniker] = [question]
92
+ end
93
+ end
94
+
95
+ # Delete reports
96
+ def delete_reports
97
+ @status = {}
98
+ end
99
+
100
+ # Delete all questions for a player
101
+ def delete_questions moniker
102
+ @questions.delete moniker
103
+ end
104
+
105
+ # Delete all questions for all players
106
+ def delete_all_questions
107
+ @questions = {}
108
+ end
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,88 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/mod"
19
+
20
+ require "carps/ui"
21
+
22
+ require "yaml"
23
+
24
+ module CARPS
25
+
26
+ # Resource manager
27
+ class Resource
28
+
29
+ # Takes as an argument a directory, within the users campaign directory
30
+ def initialize rdir
31
+ @dir = $CONFIG + "campaigns/#{rdir}"
32
+ end
33
+
34
+ # Create a new npc of a given type
35
+ def new_npc type
36
+ sheet_loc = @dir + "/npcs/" + type + ".yaml"
37
+ begin
38
+ Sheet::Character.new YAML::load File.read sheet_loc
39
+ rescue
40
+ UI::warn "Could not create NPC: " + sheet_loc
41
+ return nil
42
+ end
43
+ end
44
+
45
+ # Put everyone in this room
46
+ def players_in players, room_name
47
+ room = load_room room_name
48
+ if room
49
+ players.each do |player|
50
+ update_reporter player, room
51
+ end
52
+ end
53
+ end
54
+
55
+ # This player is in this room
56
+ def player_in player, room_name
57
+ room = load_room room_name
58
+ if room
59
+ update_reporter player, room
60
+ end
61
+ end
62
+
63
+ # Register a reporter, update the reporter with changes
64
+ def reporter= report
65
+ @reporter = report
66
+ end
67
+
68
+ private
69
+
70
+ # Load a room
71
+ def load_room room
72
+ room_loc = @dir + "/rooms/" + room + ".txt"
73
+ begin
74
+ return Room.new room_loc
75
+ rescue Exception => e
76
+ UI::warn "Could not load room: " + room_loc
77
+ return nil
78
+ end
79
+ end
80
+
81
+ # Update the reporter
82
+ def update_reporter player, room
83
+ @reporter.update_player player, room.describe
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,33 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module CARPS
19
+
20
+ # A room, loaded in by the Resource class
21
+ class Room
22
+
23
+ def initialize filepath
24
+ @desc = File.read filepath
25
+ end
26
+
27
+ def describe
28
+ @desc
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,73 @@
1
+ # Copyright 2010 John Morrice
2
+
3
+ # This file is part of CARPS.
4
+
5
+ # CARPS is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+
10
+ # CARPS is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with CARPS. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require "carps/service"
19
+
20
+ require "carps/mod"
21
+
22
+ require "carps/ui"
23
+
24
+ module CARPS
25
+
26
+ # Interface for roleplaying
27
+ class RolePlayInterface < QuitInterface
28
+
29
+ def initialize
30
+ super
31
+ add_command "d", "Roll a dice with a given number of sides.", "SIDES"
32
+ add_command "int", "An random integer between MIN and MAX.", "MIN", "MAX"
33
+ add_command "dec", "A decimal between MIN and MAX.", "MIN", "MAX"
34
+ end
35
+
36
+ def d n
37
+ i = n.to_i
38
+ if i <= 1
39
+ UI::put_error "A dice must have more than 1 side."
40
+ else
41
+ puts Dice::rint(1, i)
42
+ end
43
+ end
44
+
45
+ def int min, max
46
+ min = min.to_i
47
+ max = max.to_i
48
+ if min >= max
49
+ bounds_err
50
+ else
51
+ puts Dice::rint(min, max)
52
+ end
53
+ end
54
+
55
+ def dec min, max
56
+ min = min.to_f
57
+ max = max.to_f
58
+ if min >= max
59
+ bounds_err
60
+ else
61
+ puts Dice::rfloat(min, max)
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def bounds_err
68
+ UI::put_error "MIN must be less than MAX."
69
+ end
70
+
71
+ end
72
+
73
+ end