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,108 @@
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 "drb"
19
+
20
+ require "carps/util"
21
+
22
+ require "carps/ui"
23
+
24
+ module CARPS
25
+
26
+ # Functions which launch mods.
27
+ module Launcher
28
+
29
+ # Print an error message
30
+ def Launcher::usage
31
+ puts "Mod requires argument -p URI for player\nor -h CAMPAIGN URI for DMs."
32
+ CARPS::enter_quit 1
33
+ end
34
+
35
+ def Launcher::get_mailer uri
36
+ DRb.start_service
37
+ mailer = DRbObject.new_with_uri uri
38
+ end
39
+
40
+ # Either get the mod from the mailer or create a new one
41
+ def Launcher::launch_player_mod role, mailer, *args
42
+ mod = nil
43
+ unless mod = mailer.load
44
+ mod = role.create_mod
45
+ end
46
+ mod.mailer = mailer
47
+ role.launch mod
48
+ end
49
+
50
+ # Either get the mod from the mailer or create a new one
51
+ def Launcher::launch_dm_mod role, campaign, mailer
52
+ mod = nil
53
+ unless mod = mailer.load
54
+ mod = role.create_mod campaign
55
+ end
56
+ mod.mailer = mailer
57
+ role.launch mod
58
+ end
59
+
60
+ # Use to launch a mod
61
+ #
62
+ # Pass a module, containing the mod: this will do the rest.
63
+ #
64
+ # The module must contain two further modules, Player and DM
65
+ #
66
+ # Each of Player and DM must also contain a create_mod method (And I mean defined like `def Player::create_mod`).
67
+ #
68
+ # Player::create_mod should take one parameter: the mailer.
69
+ #
70
+ # DM::create_mod should take two parameters: the campaign, then the mailer.
71
+ #
72
+ # Each of Player and DM should also contain a launch method (which should be defined as per above),
73
+ # this method should take one parameter: the mod
74
+ def Launcher::launch mod
75
+
76
+ CARPS::with_crash_report true do
77
+ # Start DRB
78
+ DRb.start_service
79
+ # Should use optparse?
80
+ if ARGV.empty?
81
+ usage
82
+ else
83
+ role = ARGV.shift
84
+ if role == "-h"
85
+ if ARGV.length == 2
86
+ CARPS::config_dir "dm"
87
+ campaign = ARGV.shift
88
+ Launcher::launch_dm_mod mod::DM, campaign, Launcher::get_mailer(ARGV.shift)
89
+ else
90
+ usage
91
+ end
92
+ elsif role == "-p"
93
+ if ARGV.length == 1
94
+ CARPS::config_dir "player"
95
+ Launcher::launch_player_mod mod::Player, Launcher::get_mailer(ARGV.shift)
96
+ else
97
+ Launcher::usage
98
+ end
99
+ else
100
+ Launcher::usage
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ end
@@ -0,0 +1,52 @@
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
+ module CARPS
21
+
22
+ # Mod base class supporting character sheet verification
23
+ #
24
+ # Subclasses should override
25
+ # schema, semantic_verifier
26
+ class Mod
27
+
28
+ # Give a mailer
29
+ def mailer= mail
30
+ @mailer = mail
31
+ end
32
+
33
+ protected
34
+
35
+ # The semantic verifier
36
+ def semantic_verifier
37
+ Sheet::UserVerifier.new
38
+ end
39
+
40
+ # The schema
41
+ def schema
42
+ Sheet::Schema.new({})
43
+ end
44
+
45
+ # Sheet editor
46
+ def editor
47
+ Sheet::Editor.new schema, semantic_verifier
48
+ end
49
+
50
+ end
51
+
52
+ end
@@ -0,0 +1,76 @@
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 Player
25
+
26
+ # Player interface
27
+ class Interface < CARPS::RolePlayInterface
28
+
29
+ def initialize mod
30
+ super()
31
+ @mod = mod
32
+ add_command "act", "Take your turn."
33
+ add_command "save", "Save the game."
34
+ add_command "done", "Send your stuff to the dungeon master and await the next turn."
35
+ add_command "sheet", "Look at your character sheet."
36
+ add_command "edit", "Edit your character sheet."
37
+ end
38
+
39
+ # Output information about the game, then run.
40
+ def run
41
+ if @mod.first_time?
42
+ puts @mod.description
43
+ UI::question "Press enter when you are ready to fill in your character sheet."
44
+ edit
45
+ @mod.configured
46
+ end
47
+ super
48
+ end
49
+
50
+ protected
51
+
52
+ def save
53
+ @mod.save
54
+ end
55
+
56
+ def sheet
57
+ @mod.show_sheet
58
+ end
59
+
60
+ def edit
61
+ @mod.edit_sheet
62
+ end
63
+
64
+ def act
65
+ @mod.take_turn
66
+ end
67
+
68
+ def done
69
+ @mod.next_turn
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,109 @@
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 Player
25
+
26
+ # Player mod
27
+ #
28
+ # subclasses should provide a method called description
29
+ #
30
+ # description should return a string, a summary of the game.
31
+ # Who wrote it, owns the copyright and where to find the rules
32
+ # are appropriate facts.
33
+ class Mod < CARPS::Mod
34
+
35
+ def initialize
36
+ @sheet = Sheet::Character.new({})
37
+ @first_time = true
38
+ end
39
+
40
+ # This game has been configured
41
+ def configured
42
+ @first_time = false
43
+ end
44
+
45
+ # This game has never been run before
46
+ def first_time?
47
+ @first_time
48
+ end
49
+
50
+ # Edit the character sheet
51
+ def edit_sheet
52
+ editor.fill @sheet
53
+ @edited = true
54
+ end
55
+
56
+ # Show the character sheet
57
+ def show_sheet
58
+ puts @sheet.emit
59
+ end
60
+
61
+ # Save the game
62
+ def save
63
+ @mailer.save self
64
+ end
65
+
66
+ # Take a turn
67
+ def take_turn
68
+ if @turn
69
+ @answers = @turn.take
70
+ else
71
+ tu = @mailer.check ClientTurn
72
+ if tu
73
+ @turn = tu
74
+ stats = @turn.sheet.dump
75
+ unless stats.empty?
76
+ @sheet = Sheet::Character.new stats
77
+ UI::highlight "Received new character sheet."
78
+ end
79
+ @answers = @turn.take
80
+ else
81
+ UI::put_error "Turn not received."
82
+ end
83
+ end
84
+ save
85
+ end
86
+
87
+ # Send answers to dungeon master
88
+ def next_turn
89
+ if @answers
90
+ @mailer.relay @answers
91
+ @turn = nil
92
+ done = true
93
+ end
94
+ if @edited
95
+ @edited = false
96
+ @mailer.relay Sheet::NewSheet.new @sheet.attributes
97
+ done = true
98
+ end
99
+ unless done
100
+ UI::put_error "Nothing to send."
101
+ end
102
+ save
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+
109
+ end
@@ -0,0 +1,63 @@
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/protocol"
19
+
20
+ require "carps/mod"
21
+
22
+ require "carps/ui"
23
+
24
+ module CARPS
25
+
26
+ # A question sent by the server, to be asked of the player.
27
+ #
28
+ # Interacts with Answers class
29
+ class Question < Message
30
+
31
+ # Extend the protocol
32
+ protoval :question
33
+
34
+ # Create a question
35
+ def initialize question
36
+ @text = question
37
+ end
38
+
39
+ # Parse from the void
40
+ def Question.parse blob
41
+ question, blob = find K.question, blob
42
+ [Question.new(question), blob]
43
+ end
44
+
45
+ # Emit
46
+ def emit
47
+ V.question @text
48
+ end
49
+
50
+ # Ask the question, store the answer in the answers object
51
+ def ask answers
52
+ response = UI::question @text
53
+ answers.answer @text, response
54
+ end
55
+
56
+ # Preview the question
57
+ def preview
58
+ puts "Question: " + @text
59
+ end
60
+
61
+ end
62
+
63
+ 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
+ module CARPS
19
+
20
+ # A rule.
21
+ #
22
+ # This class uses the TemplateMethod pattern.
23
+ #
24
+ # Subclasses should provide the following methods
25
+ #
26
+ # * 'dice' method which takes needed parameters (ie from apply and show_odds) and returns a Dice
27
+ class Rule
28
+
29
+ # Create the rule
30
+ def initialize
31
+ @actions = {}
32
+ end
33
+
34
+ # Apply the rule to the arguments
35
+ def apply *args
36
+ d = dice *args
37
+ result = d.roll
38
+ action_klass = choose_action_class result
39
+ action = action_klass.new
40
+ action.apply result, *args
41
+ end
42
+
43
+ # Print the odds
44
+ def show_odds *args
45
+ d = dice *args
46
+ odds = {}
47
+ d.odds.each do |result, chance|
48
+ action = choose_action_class result
49
+ odds[action] = odds[action].to_f + chance
50
+ end
51
+ puts "The odds are approximately:"
52
+ puts "\n"
53
+ # Sort the odds
54
+ odds = odds.to_a.sort {|oda, odb| oda[1] <=> odb[1]}
55
+ odds = odds.reverse
56
+ odds.each do |action_klass, chance|
57
+ action = action_klass.new
58
+ percent = (chance * 100.0).to_i
59
+ puts "#{percent}% chance:"
60
+ puts "\t#{action.summary}"
61
+ end
62
+ end
63
+
64
+ protected
65
+
66
+ # Add an action
67
+ #
68
+ # Subclasses should use this method to add new actions
69
+ #
70
+ # Compare may be:
71
+ #
72
+ # * a range of valid values
73
+ #
74
+ # * one of :<, :<=, :==, :>, :>= and then an integer with which to compare
75
+ #
76
+ # * :all which indicates this is action which always applies
77
+ #
78
+ def add_action *compare, action
79
+ cmp = nil
80
+ if compare.length > 1
81
+ cmp = Dice::comparison_to_proc *compare
82
+ else
83
+ cmp = compare[0]
84
+ end
85
+ @actions[cmp] = action
86
+ end
87
+
88
+ # Choose the action
89
+ def choose_action_class result
90
+ @actions.each do |compare, action|
91
+ if compare.class == Range
92
+ if compare.include? result
93
+ return action
94
+ end
95
+ elsif compare.class == Proc
96
+ if compare.call result
97
+ return action
98
+ end
99
+ elsif compare == :all
100
+ return action
101
+ else
102
+ UI::warn "BUG: Removing #{action} from #{self.class} because its result selector was invalid: #{compare}."
103
+ @actions.delete compare
104
+ end
105
+ end
106
+ raise StandardError, "BUG: No action chosen in #{self.class}."
107
+ end
108
+
109
+
110
+ end
111
+
112
+ end
@@ -0,0 +1,82 @@
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 "yaml"
19
+
20
+ module CARPS
21
+
22
+ module Sheet
23
+
24
+ # Allow the dungeon master to inspect and modify character sheets
25
+ #
26
+ # Supports syntactic and semantic verification
27
+ class Character
28
+
29
+ def initialize sheet = {}
30
+ @sheet = sheet
31
+ end
32
+
33
+ # Access a value in the sheet
34
+ def [] attr
35
+ @sheet[attr]
36
+ end
37
+
38
+ # Set a value in the sheet
39
+ def []= attr, val
40
+ @sheet[attr] = val
41
+ end
42
+
43
+ # Dump the attributes
44
+ def attributes
45
+ @sheet
46
+ end
47
+
48
+ # The sheet has no entries - it is uninitialized!
49
+ def empty?
50
+ @sheet.empty?
51
+ end
52
+
53
+ # Emit
54
+ def emit
55
+ @sheet.to_yaml
56
+ end
57
+
58
+ end
59
+
60
+ # Player
61
+ #
62
+ # The mod is an observer on the player. Hence when the player is updated, the mod can send the new character sheet via email
63
+ class Player < Character
64
+
65
+ # Pass a sheet, the moniker used to refer to this sheet, and a reference to the mod
66
+ def initialize mod, moniker, sheet = {}
67
+ super sheet
68
+ @mod = mod
69
+ @moniker = moniker
70
+ end
71
+
72
+ # Update the sheet and notify the mod
73
+ def []= attr, val
74
+ super
75
+ @mod.sheet_updated @moniker
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+
82
+ end
@@ -0,0 +1,97 @@
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/ui"
19
+
20
+ require "carps/mod"
21
+
22
+ module CARPS
23
+
24
+
25
+ module Sheet
26
+
27
+ # Editor for a character sheet
28
+ #
29
+ # Performs validations also, popping open an editor if they fail
30
+ class Editor
31
+
32
+ def initialize schema, semantics
33
+ @schema = schema
34
+ @semantics = semantics
35
+ end
36
+
37
+ # Fill in the sheet
38
+ def fill sheet
39
+ edit sheet
40
+ validate sheet
41
+ end
42
+
43
+ # Is the sheet valid?
44
+ def valid? sheet
45
+ failures = @schema.produce_errors sheet
46
+ unless failures
47
+ failures = @semantics.produce_errors sheet
48
+ end
49
+ if failures
50
+ UI::put_error "Character sheet was incorrect:"
51
+ failures.each do |f|
52
+ puts f
53
+ end
54
+ return false
55
+ else
56
+ return true
57
+ end
58
+ end
59
+
60
+ # Edit the sheet until it is valid
61
+ def validate sheet
62
+ valid = false
63
+ until valid
64
+ if sheet
65
+ valid = valid? sheet
66
+ end
67
+ unless valid
68
+ edit sheet
69
+ end
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ # Edit the sheet
76
+ def edit sheet
77
+ sheet_text = @schema.create_sheet_text sheet
78
+ sheet_map = nil
79
+ begin
80
+ editor = CARPS::Editor.load
81
+ sheet_text = editor.edit sheet_text
82
+ sheet_map = YAML.load sheet_text
83
+ rescue ArgumentError => e
84
+ UI::put_error e.message
85
+ end
86
+ if sheet_map
87
+ sheet_map.each do |attr, val|
88
+ sheet[attr] = val
89
+ end
90
+ end
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+ end