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,360 @@
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
+ module Dice
21
+
22
+ # Random integer between min and max
23
+ def Dice::rint min, max
24
+ rfloat(min - 0.5, max + 0.5).round
25
+ end
26
+
27
+ # Random floating point number between min and max
28
+ def Dice::rfloat min, max
29
+ diff = max - min
30
+ r = rand * diff
31
+ r + min
32
+ end
33
+
34
+ # Create a new dice
35
+ def d i
36
+ D.new i
37
+ end
38
+
39
+ # A dice
40
+ #
41
+ # Note that the methods here - including +, *, etc - update the dice's internal state, and do not return a new dice.
42
+ class D
43
+
44
+ # Create the dice from an integer, the number of sides
45
+ #
46
+ # The dice will have sides numbered from 1 to i.
47
+ def initialize i
48
+ @rolls = {}
49
+ @weights = {}
50
+ fair_weight = 1.0 / i
51
+ i.times do |n|
52
+ n = n + 1
53
+ @rolls[n] = n
54
+ @weights[n] = 1.0 / i
55
+ end
56
+ end
57
+
58
+ # Roll the dice
59
+ def roll
60
+ od = []
61
+ results = odds.to_a
62
+ current = 0
63
+ # Build up range arrays corresponding to probabalistic weights
64
+ until results.empty?
65
+ # Manually insert a 1 at the end to make this numerically stable
66
+ last = false
67
+ if results.length == 1
68
+ last = true
69
+ end
70
+ result, weight = results.shift
71
+ if last
72
+ od.push [current..1, result]
73
+ else
74
+ new_top = current + weight
75
+ od.push [current..new_top, result]
76
+ current = new_top
77
+ end
78
+ end
79
+ # Find the appropriate action
80
+ r = rand
81
+ od.each do |range, result|
82
+ if range.include? r
83
+ return result
84
+ end
85
+ end
86
+ raise StandardError, "BUG: Dice has no result."
87
+ end
88
+
89
+ # Output the odds
90
+ #
91
+ # That is, a hash of results to the probabalistic weights of the possible results.
92
+ def odds
93
+ od = {}
94
+ @weights.each do |roll, weight|
95
+ result = @rolls[roll]
96
+ if od.include? result
97
+ od[result] = od[result] + weight
98
+ else
99
+ od[result] = weight
100
+ end
101
+ end
102
+ od
103
+ end
104
+
105
+ # Output the weights table
106
+ def weights
107
+ @weights
108
+ end
109
+
110
+ # Output the roll table
111
+ def rolls
112
+ @rolls
113
+ end
114
+
115
+ # Add a number or another dice
116
+ def + other
117
+ if is_num other
118
+ add_num other
119
+ else
120
+ add_dice other
121
+ end
122
+ end
123
+
124
+ # Subtract a number or another dice
125
+ def - other
126
+ if is_num other
127
+ add_num (other * -1)
128
+ else
129
+ subtract_dice other
130
+ end
131
+ end
132
+
133
+ # Multiply by a number or another dice
134
+ def * other
135
+ if is_num other
136
+ mul_num other
137
+ else
138
+ mul_dice other
139
+ end
140
+ end
141
+
142
+ # Divide by a number or another dice
143
+ def / other
144
+ if is_num other
145
+ div_num other
146
+ else
147
+ div_dice other
148
+ end
149
+ end
150
+
151
+ # Directly inspect the range and supply a number or a dice as output, if the result is in that range
152
+ def in_range range, output
153
+ if is_num output
154
+ in_range_int range, output
155
+ else
156
+ in_range_dice range, output
157
+ end
158
+ end
159
+
160
+ # If the result matches a binary comparison, then return this result
161
+ #
162
+ # compare is one of :<, :<=, :==, :>, :>=
163
+ #
164
+ # other is an integer to compare with
165
+ def is compare, other, output
166
+ cmp = Dice::comparison_to_proc compare, other
167
+
168
+ rng = find_range cmp
169
+ if rng
170
+ in_range rng, output
171
+ end
172
+ end
173
+
174
+ protected
175
+
176
+ # Find the Range of values which when applied to op give true
177
+ #
178
+ # If no results match the operator, return nil instead
179
+ def find_range op
180
+ results = @rolls.values.reject {|result| not op.call result}
181
+ if results.empty?
182
+ nil
183
+ else
184
+ results.min..results.max
185
+ end
186
+ end
187
+
188
+ # Do an arithmetic operation with the results of another dice roll
189
+ def with_dice_arithmetic other
190
+ new_rolls = {}
191
+ new_weights = {}
192
+ # Compute the new weights
193
+ @weights.keys.sort.reverse.each do |roll|
194
+ other.weights.keys.each do |oroll|
195
+ weight = @weights[roll]
196
+ oweight = other.weights[oroll]
197
+ result = @rolls[roll]
198
+ oresult = other.rolls[oroll]
199
+ chance = weight * oweight
200
+ added_roll = roll + oroll
201
+ new_result = yield result, oresult
202
+ new_result = new_result.to_i
203
+ new_side = roll + oroll
204
+ if new_rolls.include? new_side
205
+ new_side = new_weights.keys.max + 1
206
+ end
207
+ new_weights[new_side] = chance
208
+ new_rolls[new_side] = new_result
209
+ end
210
+ end
211
+ @rolls = new_rolls
212
+ @weights = new_weights
213
+ end
214
+
215
+ # Subtract a dice
216
+ def subtract_dice other
217
+ with_dice_arithmetic other do |my, their|
218
+ my - their
219
+ end
220
+ end
221
+
222
+ # Add a dice
223
+ def add_dice other
224
+ with_dice_arithmetic other do |my, their|
225
+ my + their
226
+ end
227
+ end
228
+
229
+ # Multiply by the result of a dice roll
230
+ def mul_dice other
231
+ with_dice_arithmetic other do |my, their|
232
+ my * their
233
+ end
234
+ end
235
+
236
+ # Divide by the result of a dice roll
237
+ def div_dice other
238
+ with_dice_arithmetic other do |my, their|
239
+ my / their
240
+ end
241
+ end
242
+
243
+ # Is this an integer or float?
244
+ def is_num i
245
+ i.class == Fixnum or i.class == Float
246
+ end
247
+
248
+ # Update every result in this range
249
+ def in_range_int range, output
250
+ @rolls.to_a.each do |roll, result|
251
+ if range.include? result
252
+ @rolls[roll] = output
253
+ end
254
+ end
255
+ end
256
+
257
+ # Update every result in this range to be the result of a dice roll
258
+ def in_range_dice range, other
259
+ new_rolls = other.rolls
260
+ new_weights = {}
261
+ affected_rolls = @rolls.reject {|roll, result| not range.include? result}
262
+ affected_rolls.each_key do |roll|
263
+ # Add roll to new_weights and new_rolls
264
+ roll_again roll, other, new_rolls, new_weights
265
+ @weights.delete roll
266
+ @rolls.delete roll
267
+ end
268
+ # Invent new dice sides to cope with multiple roll values
269
+ other.rolls.keys.each do |roll|
270
+ if @weights.include? roll
271
+ weight = new_weights[roll]
272
+ result = new_rolls[roll]
273
+ new_weights.delete roll
274
+ new_rolls.delete roll
275
+ new_max = new_weights.keys.max
276
+ old_max = @weights.keys.max
277
+ new_side = [new_max, old_max].max + 1
278
+ new_weights[new_side] = weight
279
+ new_rolls[new_side] = result
280
+ end
281
+ end
282
+ @weights.merge! new_weights
283
+ @rolls.merge! new_rolls
284
+ end
285
+
286
+ # If this result is rolled, the result shall be given by the other dice
287
+ def roll_again roll, other, new_rolls, new_weights
288
+ weight = @weights[roll]
289
+ other.weights.each do |onum, oweight|
290
+ this_weight = weight * oweight
291
+ if new_weights.include? onum
292
+ new_weights[onum] = new_weights[onum] + this_weight
293
+ else
294
+ new_weights[onum] = this_weight
295
+ end
296
+ end
297
+
298
+ end
299
+
300
+ # Add an integer to the results
301
+ def add_num n
302
+ on_results do |odd|
303
+ n + odd
304
+ end
305
+ end
306
+
307
+ # Multiply results by the integer
308
+ def mul_num n
309
+ on_results do |odd|
310
+ n * odd
311
+ end
312
+ end
313
+
314
+ # Divide results by the integer
315
+ def div_num n
316
+ on_results do |odd|
317
+ odd / n
318
+ end
319
+ end
320
+
321
+ # Perform an operation on the results
322
+ def on_results
323
+ @rolls.each do |roll, result|
324
+ result = yield result
325
+ @rolls[roll] = result.to_i
326
+ end
327
+ end
328
+
329
+ end
330
+
331
+ # When compare is one of
332
+ #
333
+ # :<, :<=, :==, :>, :>=
334
+ #
335
+ # and other is an integer
336
+ #
337
+ # Return a proc which takes an argument a
338
+ # and does
339
+ #
340
+ # a compare other
341
+ def Dice::comparison_to_proc compare, other
342
+ cmp = nil
343
+ case compare
344
+ when :<
345
+ cmp = lambda {|a| a < other}
346
+ when :<=
347
+ cmp = lambda {|a| a <= other}
348
+ when :==
349
+ cmp = lambda {|a| a == other}
350
+ when :>=
351
+ cmp = lambda {|a| a >= other}
352
+ when :>
353
+ cmp = lambda {|a| a > other}
354
+ end
355
+ cmp
356
+ end
357
+
358
+ end
359
+
360
+ end
@@ -0,0 +1,160 @@
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/editor"
21
+
22
+ module CARPS
23
+
24
+ module DM
25
+
26
+ # A basic user interface for the dm
27
+ #
28
+ # Subclass this interface to provide commands
29
+ class Interface < CARPS::RolePlayInterface
30
+
31
+ def initialize mod
32
+ super()
33
+ @mod = mod
34
+ add_command :mail, "Check for new emails."
35
+ add_command :save, "Saves the state of the world."
36
+ add_command :done, "Send all reports and start the next turn."
37
+ add_command :invite, "Invite a new player", "EMAIL"
38
+ add_command :describe, "Describe a player or an NPC.", "PLAYER/NPC"
39
+ add_command :players, "Describe all players."
40
+ add_command :npcs, "Describe all NPCs."
41
+ add_command :edit, "Edit a character sheet belonging to a player or NPC.", "PLAYER/NPC"
42
+ add_command :warp, "Put all player in this room.", "ROOM"
43
+ add_command :room, "Put one player in this room.", "PLAYER", "ROOM"
44
+ add_command :spawn, "Create a new npc", "TYPE", "NAME"
45
+ add_command :decree, "Create a report for all players to see."
46
+ add_command :tell, "Tell a player something.", "PLAYER"
47
+ add_command :census, "Ask a question of every player."
48
+ add_command :ask, "Ask a question of one player.", "PLAYER"
49
+ add_command :survey, "Preview the reports and questions to be sent to every player."
50
+ add_command :inspect, "Preview the report and questions to be sent to one player.", "PLAYER"
51
+ add_command :nuke, "Clear all reports and questions for all players."
52
+ add_command :silence, "Clear all reports for all players."
53
+ add_command :futile, "Clear all questions for all players."
54
+ add_command :remit, "Clear the report for one player", "PLAYER"
55
+ add_command :supress, "Clear the questions for one player", "PLAYER"
56
+ end
57
+
58
+ protected
59
+
60
+ # Invite a new player
61
+ def invite addr
62
+ @mod.invite addr
63
+ end
64
+
65
+ # Quit, but save first
66
+ def quit
67
+ save
68
+ super
69
+ end
70
+
71
+ def save
72
+ @mod.save
73
+ end
74
+
75
+ def done
76
+ @mod.next_turn
77
+ end
78
+
79
+ def edit name
80
+ @mod.edit_sheet name
81
+ end
82
+
83
+ def npcs
84
+ @mod.list_npcs
85
+ end
86
+
87
+ def players
88
+ @mod.list_players
89
+ end
90
+
91
+ def describe name
92
+ @mod.describe name
93
+ end
94
+
95
+ def mail
96
+ @mod.check_mail
97
+ end
98
+
99
+ def supress player
100
+ @mod.delete_questions player
101
+ end
102
+
103
+ def remit player
104
+ @mod.delete_report player
105
+ end
106
+
107
+ def futile
108
+ @mod.delete_all_questions
109
+ end
110
+
111
+ def silence
112
+ @mod.delete_all_reports
113
+ end
114
+
115
+ def decree
116
+ @mod.create_global_report
117
+ end
118
+
119
+ def nuke
120
+ silence
121
+ futile
122
+ end
123
+
124
+ def inspect player
125
+ @mod.inspect_turn player
126
+ end
127
+
128
+ def survey
129
+ @mod.inspect_reports
130
+ end
131
+
132
+ def census
133
+ @mod.ask_everyone
134
+ end
135
+
136
+ def ask player
137
+ @mod.ask_player player
138
+ end
139
+
140
+ def warp room
141
+ @mod.everyone_in room
142
+ end
143
+
144
+ def room player, room
145
+ @mod.player_in player, room
146
+ end
147
+
148
+ def spawn type, name
149
+ @mod.new_npc type, name
150
+ end
151
+
152
+ def tell player
153
+ @mod.tell player
154
+ end
155
+
156
+ end
157
+
158
+ end
159
+
160
+ end