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.
- data/COPYING +674 -0
- data/GEM_DESCRIPTION +10 -0
- data/History.txt +4 -0
- data/Manifest.txt +156 -0
- data/PostInstall.txt +20 -0
- data/README.rdoc +141 -0
- data/Rakefile +28 -0
- data/bin/carps +123 -0
- data/bin/carps_init +29 -0
- data/bin/carps_ipc_test +44 -0
- data/bin/carps_mod_saver_test +71 -0
- data/bin/carps_mod_test +62 -0
- data/config/website.yml +2 -0
- data/features/character_sheet.feature +40 -0
- data/features/crash.feature +15 -0
- data/features/crypt.feature +22 -0
- data/features/dice.feature +173 -0
- data/features/dm.feature +36 -0
- data/features/dmll.feature +51 -0
- data/features/edit.feature +10 -0
- data/features/email.feature +29 -0
- data/features/interface.feature +17 -0
- data/features/ipc.feature +10 -0
- data/features/mailbox.feature +33 -0
- data/features/mod.feature +31 -0
- data/features/parser.feature +9 -0
- data/features/persistent_protocol.feature +14 -0
- data/features/player.feature +22 -0
- data/features/player_turn.feature +29 -0
- data/features/random.feature +15 -0
- data/features/rule.feature +19 -0
- data/features/safety.feature +13 -0
- data/features/sessions.feature +16 -0
- data/features/start_dm.feature +18 -0
- data/features/start_player.feature +8 -0
- data/features/step_definitions/common_steps.rb +170 -0
- data/features/steps/character_sheet.rb +89 -0
- data/features/steps/crash.rb +27 -0
- data/features/steps/crypt.rb +166 -0
- data/features/steps/dice.rb +91 -0
- data/features/steps/dm.rb +147 -0
- data/features/steps/dmll.rb +47 -0
- data/features/steps/edit.rb +7 -0
- data/features/steps/email.rb +108 -0
- data/features/steps/general.rb +5 -0
- data/features/steps/interface.rb +64 -0
- data/features/steps/ipc.rb +22 -0
- data/features/steps/mailbox.rb +126 -0
- data/features/steps/mod.rb +25 -0
- data/features/steps/parser.rb +23 -0
- data/features/steps/persistent_protocol.rb +29 -0
- data/features/steps/player.rb +82 -0
- data/features/steps/player_turn.rb +56 -0
- data/features/steps/random.rb +47 -0
- data/features/steps/rule.rb +53 -0
- data/features/steps/safety.rb +17 -0
- data/features/steps/sessions.rb +37 -0
- data/features/steps/start_dm.rb +46 -0
- data/features/steps/start_player.rb +65 -0
- data/features/steps/timeout.rb +32 -0
- data/features/steps/type_verification.rb +36 -0
- data/features/steps/wizard.rb +123 -0
- data/features/support/common.rb +29 -0
- data/features/support/env.rb +14 -0
- data/features/support/matchers.rb +11 -0
- data/features/timeout.feature +11 -0
- data/features/type_verification.feature +48 -0
- data/features/wizard.feature +50 -0
- data/lib/carps/crypt/accept_handshake.rb +40 -0
- data/lib/carps/crypt/default_messages.rb +29 -0
- data/lib/carps/crypt/handshake.rb +41 -0
- data/lib/carps/crypt/mailbox.rb +265 -0
- data/lib/carps/crypt/mailer.rb +220 -0
- data/lib/carps/crypt/peer.rb +123 -0
- data/lib/carps/crypt/public_key.rb +60 -0
- data/lib/carps/crypt.rb +23 -0
- data/lib/carps/email/config.rb +122 -0
- data/lib/carps/email/imap.rb +156 -0
- data/lib/carps/email/smtp.rb +119 -0
- data/lib/carps/email/string.rb +30 -0
- data/lib/carps/email.rb +21 -0
- data/lib/carps/mod/action.rb +36 -0
- data/lib/carps/mod/answers.rb +76 -0
- data/lib/carps/mod/client_turn.rb +88 -0
- data/lib/carps/mod/dice.rb +360 -0
- data/lib/carps/mod/dm/interface.rb +160 -0
- data/lib/carps/mod/dm/mod.rb +409 -0
- data/lib/carps/mod/dm/reporter.rb +112 -0
- data/lib/carps/mod/dm/resource.rb +88 -0
- data/lib/carps/mod/dm/room.rb +33 -0
- data/lib/carps/mod/interface.rb +73 -0
- data/lib/carps/mod/launch.rb +108 -0
- data/lib/carps/mod/mod.rb +52 -0
- data/lib/carps/mod/player/interface.rb +76 -0
- data/lib/carps/mod/player/mod.rb +109 -0
- data/lib/carps/mod/question.rb +63 -0
- data/lib/carps/mod/rule.rb +112 -0
- data/lib/carps/mod/sheet/character.rb +82 -0
- data/lib/carps/mod/sheet/editor.rb +97 -0
- data/lib/carps/mod/sheet/new_sheet.rb +71 -0
- data/lib/carps/mod/sheet/schema.rb +84 -0
- data/lib/carps/mod/sheet/type.rb +161 -0
- data/lib/carps/mod/sheet/verifier.rb +41 -0
- data/lib/carps/mod/status_report.rb +51 -0
- data/lib/carps/mod.rb +40 -0
- data/lib/carps/protocol/keyword.rb +104 -0
- data/lib/carps/protocol/message.rb +138 -0
- data/lib/carps/protocol.rb +19 -0
- data/lib/carps/service/client_parser.rb +34 -0
- data/lib/carps/service/dm/config.rb +76 -0
- data/lib/carps/service/dm/mailer.rb +70 -0
- data/lib/carps/service/dm/new_game.rb +101 -0
- data/lib/carps/service/dm/start.rb +47 -0
- data/lib/carps/service/game.rb +101 -0
- data/lib/carps/service/interface.rb +174 -0
- data/lib/carps/service/invite.rb +79 -0
- data/lib/carps/service/mod.rb +43 -0
- data/lib/carps/service/player/config.rb +78 -0
- data/lib/carps/service/player/mailer.rb +49 -0
- data/lib/carps/service/player/start.rb +60 -0
- data/lib/carps/service/server_parser.rb +33 -0
- data/lib/carps/service/session.rb +96 -0
- data/lib/carps/service/start/config.rb +71 -0
- data/lib/carps/service/start/interface.rb +101 -0
- data/lib/carps/service/start/mailer.rb +46 -0
- data/lib/carps/service.rb +35 -0
- data/lib/carps/test.rb +34 -0
- data/lib/carps/ui/colour.rb +28 -0
- data/lib/carps/ui/error.rb +39 -0
- data/lib/carps/ui/highlight.rb +32 -0
- data/lib/carps/ui/question.rb +63 -0
- data/lib/carps/ui/warn.rb +37 -0
- data/lib/carps/ui.rb +21 -0
- data/lib/carps/util/config.rb +162 -0
- data/lib/carps/util/editor.rb +147 -0
- data/lib/carps/util/error.rb +75 -0
- data/lib/carps/util/files.rb +48 -0
- data/lib/carps/util/init.rb +93 -0
- data/lib/carps/util/process.rb +150 -0
- data/lib/carps/util/timeout.rb +31 -0
- data/lib/carps/util/windows.rb +29 -0
- data/lib/carps/util.rb +24 -0
- data/lib/carps/wizard/dm.rb +41 -0
- data/lib/carps/wizard/player.rb +40 -0
- data/lib/carps/wizard/steps.rb +494 -0
- data/lib/carps/wizard/wizard.rb +126 -0
- data/lib/carps/wizard.rb +21 -0
- data/lib/carps.rb +45 -0
- data/permission +16 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/tasks/readme_site.rake +28 -0
- data/test/test_carps.rb +11 -0
- data/test/test_helper.rb +3 -0
- data/website/index.html +271 -0
- 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
|