butler 1.8.0

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 (164) hide show
  1. data/CHANGELOG +4 -0
  2. data/GPL.txt +340 -0
  3. data/LICENSE.txt +52 -0
  4. data/README +37 -0
  5. data/Rakefile +334 -0
  6. data/bin/botcontrol +230 -0
  7. data/data/butler/config_template.yaml +4 -0
  8. data/data/butler/dialogs/backup.rb +19 -0
  9. data/data/butler/dialogs/botcontrol.rb +4 -0
  10. data/data/butler/dialogs/config.rb +1 -0
  11. data/data/butler/dialogs/create.rb +53 -0
  12. data/data/butler/dialogs/delete.rb +3 -0
  13. data/data/butler/dialogs/en/backup.yaml +6 -0
  14. data/data/butler/dialogs/en/botcontrol.yaml +5 -0
  15. data/data/butler/dialogs/en/create.yaml +11 -0
  16. data/data/butler/dialogs/en/delete.yaml +2 -0
  17. data/data/butler/dialogs/en/help.yaml +17 -0
  18. data/data/butler/dialogs/en/info.yaml +13 -0
  19. data/data/butler/dialogs/en/list.yaml +4 -0
  20. data/data/butler/dialogs/en/notyetimplemented.yaml +2 -0
  21. data/data/butler/dialogs/en/rename.yaml +3 -0
  22. data/data/butler/dialogs/en/start.yaml +3 -0
  23. data/data/butler/dialogs/en/sync_plugins.yaml +3 -0
  24. data/data/butler/dialogs/en/uninstall.yaml +5 -0
  25. data/data/butler/dialogs/en/unknown_command.yaml +2 -0
  26. data/data/butler/dialogs/help.rb +11 -0
  27. data/data/butler/dialogs/info.rb +27 -0
  28. data/data/butler/dialogs/interactive.rb +1 -0
  29. data/data/butler/dialogs/list.rb +10 -0
  30. data/data/butler/dialogs/notyetimplemented.rb +1 -0
  31. data/data/butler/dialogs/rename.rb +4 -0
  32. data/data/butler/dialogs/selectbot.rb +2 -0
  33. data/data/butler/dialogs/start.rb +5 -0
  34. data/data/butler/dialogs/sync_plugins.rb +30 -0
  35. data/data/butler/dialogs/uninstall.rb +17 -0
  36. data/data/butler/dialogs/unknown_command.rb +1 -0
  37. data/data/butler/plugins/core/logout.rb +41 -0
  38. data/data/butler/plugins/core/plugins.rb +134 -0
  39. data/data/butler/plugins/core/privilege.rb +103 -0
  40. data/data/butler/plugins/core/user.rb +166 -0
  41. data/data/butler/plugins/dev/eval.rb +64 -0
  42. data/data/butler/plugins/dev/nometa.rb +14 -0
  43. data/data/butler/plugins/dev/onhandlers.rb +93 -0
  44. data/data/butler/plugins/dev/raw.rb +36 -0
  45. data/data/butler/plugins/dev/rawlog.rb +77 -0
  46. data/data/butler/plugins/games/eightball.rb +54 -0
  47. data/data/butler/plugins/games/mastermind.rb +174 -0
  48. data/data/butler/plugins/irc/action.rb +36 -0
  49. data/data/butler/plugins/irc/join.rb +38 -0
  50. data/data/butler/plugins/irc/notice.rb +36 -0
  51. data/data/butler/plugins/irc/part.rb +38 -0
  52. data/data/butler/plugins/irc/privmsg.rb +36 -0
  53. data/data/butler/plugins/irc/quit.rb +36 -0
  54. data/data/butler/plugins/operator/deop.rb +41 -0
  55. data/data/butler/plugins/operator/devoice.rb +41 -0
  56. data/data/butler/plugins/operator/limit.rb +47 -0
  57. data/data/butler/plugins/operator/op.rb +41 -0
  58. data/data/butler/plugins/operator/voice.rb +41 -0
  59. data/data/butler/plugins/public/help.rb +69 -0
  60. data/data/butler/plugins/public/login.rb +72 -0
  61. data/data/butler/plugins/public/usage.rb +49 -0
  62. data/data/butler/plugins/service/clones.rb +56 -0
  63. data/data/butler/plugins/service/define.rb +47 -0
  64. data/data/butler/plugins/service/log.rb +183 -0
  65. data/data/butler/plugins/service/svn.rb +91 -0
  66. data/data/butler/plugins/util/cycle.rb +98 -0
  67. data/data/butler/plugins/util/load.rb +41 -0
  68. data/data/butler/plugins/util/pong.rb +29 -0
  69. data/data/butler/strings/random/acknowledge.en.yaml +5 -0
  70. data/data/butler/strings/random/gratitude.en.yaml +3 -0
  71. data/data/butler/strings/random/hello.en.yaml +4 -0
  72. data/data/butler/strings/random/ignorance.en.yaml +7 -0
  73. data/data/butler/strings/random/ignorance_about.en.yaml +3 -0
  74. data/data/butler/strings/random/insult.en.yaml +3 -0
  75. data/data/butler/strings/random/rejection.en.yaml +12 -0
  76. data/data/man/botcontrol.1 +17 -0
  77. data/lib/access.rb +187 -0
  78. data/lib/access/admin.rb +16 -0
  79. data/lib/access/privilege.rb +122 -0
  80. data/lib/access/role.rb +102 -0
  81. data/lib/access/savable.rb +18 -0
  82. data/lib/access/user.rb +180 -0
  83. data/lib/access/yamlbase.rb +126 -0
  84. data/lib/butler.rb +188 -0
  85. data/lib/butler/bot.rb +247 -0
  86. data/lib/butler/control.rb +93 -0
  87. data/lib/butler/dialog.rb +64 -0
  88. data/lib/butler/initialvalues.rb +40 -0
  89. data/lib/butler/irc/channel.rb +135 -0
  90. data/lib/butler/irc/channels.rb +96 -0
  91. data/lib/butler/irc/client.rb +351 -0
  92. data/lib/butler/irc/hostmask.rb +53 -0
  93. data/lib/butler/irc/message.rb +184 -0
  94. data/lib/butler/irc/parser.rb +125 -0
  95. data/lib/butler/irc/parser/commands.rb +83 -0
  96. data/lib/butler/irc/parser/generic.rb +343 -0
  97. data/lib/butler/irc/socket.rb +378 -0
  98. data/lib/butler/irc/string.rb +186 -0
  99. data/lib/butler/irc/topic.rb +15 -0
  100. data/lib/butler/irc/user.rb +265 -0
  101. data/lib/butler/irc/users.rb +112 -0
  102. data/lib/butler/plugin.rb +249 -0
  103. data/lib/butler/plugin/configproxy.rb +35 -0
  104. data/lib/butler/plugin/mapper.rb +85 -0
  105. data/lib/butler/plugin/matcher.rb +55 -0
  106. data/lib/butler/plugin/onhandlers.rb +70 -0
  107. data/lib/butler/plugin/trigger.rb +58 -0
  108. data/lib/butler/plugins.rb +147 -0
  109. data/lib/butler/version.rb +17 -0
  110. data/lib/cloptions.rb +217 -0
  111. data/lib/cloptions/adapters.rb +24 -0
  112. data/lib/cloptions/switch.rb +132 -0
  113. data/lib/configuration.rb +223 -0
  114. data/lib/dialogline.rb +296 -0
  115. data/lib/dialogline/localizations.rb +24 -0
  116. data/lib/durations.rb +57 -0
  117. data/lib/event.rb +295 -0
  118. data/lib/event/at.rb +64 -0
  119. data/lib/event/every.rb +56 -0
  120. data/lib/event/timed.rb +112 -0
  121. data/lib/installer.rb +75 -0
  122. data/lib/iterator.rb +34 -0
  123. data/lib/log.rb +68 -0
  124. data/lib/log/comfort.rb +85 -0
  125. data/lib/log/converter.rb +23 -0
  126. data/lib/log/entry.rb +152 -0
  127. data/lib/log/fakeio.rb +55 -0
  128. data/lib/log/file.rb +54 -0
  129. data/lib/log/filereader.rb +81 -0
  130. data/lib/log/forward.rb +49 -0
  131. data/lib/log/methods.rb +39 -0
  132. data/lib/log/nolog.rb +18 -0
  133. data/lib/log/splitter.rb +26 -0
  134. data/lib/ostructfixed.rb +26 -0
  135. data/lib/ruby/array/columnize.rb +38 -0
  136. data/lib/ruby/dir/mktree.rb +28 -0
  137. data/lib/ruby/enumerable/join.rb +13 -0
  138. data/lib/ruby/exception/detailed.rb +24 -0
  139. data/lib/ruby/file/append.rb +11 -0
  140. data/lib/ruby/file/write.rb +11 -0
  141. data/lib/ruby/hash/zip.rb +15 -0
  142. data/lib/ruby/kernel/bench.rb +15 -0
  143. data/lib/ruby/kernel/daemonize.rb +42 -0
  144. data/lib/ruby/kernel/non_verbose.rb +17 -0
  145. data/lib/ruby/kernel/safe_fork.rb +18 -0
  146. data/lib/ruby/range/stepped.rb +11 -0
  147. data/lib/ruby/string/arguments.rb +72 -0
  148. data/lib/ruby/string/chunks.rb +15 -0
  149. data/lib/ruby/string/post_arguments.rb +44 -0
  150. data/lib/ruby/string/unescaped.rb +17 -0
  151. data/lib/scheduler.rb +164 -0
  152. data/lib/scriptfile.rb +101 -0
  153. data/lib/templater.rb +86 -0
  154. data/test/cloptions.rb +134 -0
  155. data/test/cv.rb +28 -0
  156. data/test/irc/client.rb +85 -0
  157. data/test/irc/client_login.txt +53 -0
  158. data/test/irc/client_subscribe.txt +8 -0
  159. data/test/irc/message.rb +30 -0
  160. data/test/irc/messages.txt +64 -0
  161. data/test/irc/parser.rb +13 -0
  162. data/test/irc/profile_parser.rb +12 -0
  163. data/test/irc/users.rb +28 -0
  164. metadata +256 -0
@@ -0,0 +1,64 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ trigger "eval"
10
+
11
+ @state = Array.new(10)
12
+ class <<self
13
+ attr_accessor :state
14
+ end
15
+
16
+ def previous(*n)
17
+ n.empty? ? plugin.state : plugin.state[*n]
18
+ end
19
+
20
+ def _0; previous(0); end
21
+ def _1; previous(1); end
22
+ def _2; previous(2); end
23
+ def _3; previous(3); end
24
+ def _4; previous(4); end
25
+ def _5; previous(5); end
26
+ def _6; previous(6); end
27
+ def _7; previous(7); end
28
+ def _8; previous(8); end
29
+ def _9; previous(9); end
30
+
31
+ def on_trigger
32
+ begin
33
+ result = eval(@message.post_arguments[1])
34
+ plugin.state.unshift(result)
35
+ plugin.state.pop
36
+ rescue Exception => e
37
+ answer(:exception, :exception => e)
38
+ else
39
+ answer(">> "+result.inspect[0,300].split(/\n/).first(3).join("\n"))
40
+ end
41
+ end
42
+
43
+ __END__
44
+ ---
45
+ :revision:
46
+ :plugin: 1
47
+ :summary:
48
+ en: Let butler eval a piece of code.
49
+ :about:
50
+ :mail: "apeiros@gmx.net"
51
+ :version: "1.0.0"
52
+ :author: "Stefan Rusterholz"
53
+ :strings:
54
+ :exception:
55
+ en: |
56
+ Exception <%= exception.class %> '<%= exception.message %>' in:
57
+ <%= exception.backtrace.first(3).join("\n") %>
58
+ :usage:
59
+ en: |
60
+ ![b]eval![o] *![c(blue)]code![o]
61
+ :help:
62
+ en:
63
+ "": |
64
+ Let butler eval a piece of code.
@@ -0,0 +1,14 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ trigger "nometa"
10
+
11
+ def on_trigger
12
+ answer("I'm just a test, I don't do anything.")
13
+ end
14
+ __END__
@@ -0,0 +1,93 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ extend OnHandlers
10
+
11
+ configuration(
12
+ "active" => false
13
+ )
14
+
15
+ trigger "onhandlers"
16
+
17
+ def on_trigger
18
+ if @message.arguments[1] && @message.arguments[1].downcase == "on" then
19
+ plugin.config["active"] = true
20
+ else
21
+ plugin.config["active"] = false
22
+ end
23
+ end
24
+
25
+ def on_join(listener, user, channel)
26
+ debug("on_join triggered, #{user} joined #{channel}") if plugin.config["active"]
27
+ end
28
+ def on_privmsg(listener, user, text)
29
+ debug("on_privmsg triggered, #{user} wrote #{text}") if plugin.config["active"]
30
+ end
31
+ def on_notice(listener, user, text)
32
+ debug("on_notice triggered, #{user} wrote #{text}") if plugin.config["active"]
33
+ end
34
+ def on_nick(listener, user, old_nick)
35
+ debug("on_nick triggered, #{user} changed his nick from #{old_nick}") if plugin.config["active"]
36
+ end
37
+ def on_topic(listener, user, channel, topic)
38
+ debug("on_topic triggered, #{user} changed topic of #{channel} to #{topic}") if plugin.config["active"]
39
+ end
40
+ def on_part(listener, user, channel)
41
+ debug("on_part triggered, #{user} parted #{channel}") if plugin.config["active"]
42
+ end
43
+ def on_quit(listener, user, reason)
44
+ debug("on_quit triggered, #{user} has quit with #{reason}") if plugin.config["active"]
45
+ end
46
+ def on_kick(listener)
47
+ debug("on_kick triggered with #{@message}") if plugin.config["active"]
48
+ end
49
+ def on_kill(listener)
50
+ debug("on_kill triggered with #{@message}") if plugin.config["active"]
51
+ end
52
+ def on_kline(listener)
53
+ debug("on_kline triggered with #{@message}") if plugin.config["active"]
54
+ end
55
+ def on_invocation(listener)
56
+ debug("on_invocation triggered with #{@message}") if plugin.config["active"]
57
+ end
58
+ def on_ban(listener, *masks)
59
+ debug("on_ban triggered with #{@message}") if plugin.config["active"]
60
+ end
61
+ def on_unban(listener, *masks)
62
+ debug("on_unban triggered with #{@message}") if plugin.config["active"]
63
+ end
64
+ def on_op(listener, *users)
65
+ debug("on_op triggered with #{@message}") if plugin.config["active"]
66
+ end
67
+ def on_deop(listener, *users)
68
+ debug("on_deop triggered with #{@message}") if plugin.config["active"]
69
+ end
70
+ def on_voice(listener, *users)
71
+ debug("on_voice triggered with #{@message}") if plugin.config["active"]
72
+ end
73
+ def on_devoice(listener, *users)
74
+ debug("on_devoice triggered with #{@message}") if plugin.config["active"]
75
+ end
76
+
77
+ __END__
78
+ ---
79
+ :revision:
80
+ :plugin: 1
81
+ :summary:
82
+ en: Testing all possible on_handlers
83
+ :about:
84
+ :mail: "apeiros@gmx.net"
85
+ :version: "1.0.0"
86
+ :author: "Stefan Rusterholz"
87
+ :strings:
88
+ :usage:
89
+ en: "This plugin does not offer a specific interface."
90
+ :help:
91
+ en:
92
+ "": |
93
+ This plugin is meant for diagnostic purposes only.
@@ -0,0 +1,36 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ trigger "raw"
10
+
11
+ def on_trigger
12
+ return answer(usage) if @message.arguments.length < 2
13
+ @butler.irc.write(@message.post_arguments[1])
14
+ answer(:sent)
15
+ end
16
+
17
+ __END__
18
+ ---
19
+ :revision:
20
+ :plugin: 1
21
+ :summary:
22
+ en: Let butler send a raw message to the server.
23
+ :about:
24
+ :mail: "apeiros@gmx.net"
25
+ :version: "1.0.0"
26
+ :author: "Stefan Rusterholz"
27
+ :strings:
28
+ :sent:
29
+ en: Sent the raw message
30
+ :usage:
31
+ en: |
32
+ ![b]raw![o] *![c(blue)]raw-message![o])
33
+ :help:
34
+ en:
35
+ "": |
36
+ Let butler send a raw message to the server.
@@ -0,0 +1,77 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ configuration(
10
+ "active" => true
11
+ )
12
+
13
+ @logfile = nil
14
+
15
+ def self.on_load(*a)
16
+ @logfile = File.open(@butler.path.log+"/rawlog.txt", "a")
17
+ @logfile.sync = true
18
+ end
19
+
20
+ def self.on_unload(*a)
21
+ @logfile.close
22
+ end
23
+
24
+ subscribe(nil, 10) { |listener, message|
25
+ if @config["active"] && @logfile then
26
+ @logfile.puts("#{Time.now.strftime('%F %T')}> #{message.raw}")
27
+ end
28
+ }
29
+
30
+ trigger "rawlog"
31
+
32
+ def on_trigger
33
+ arg = @message.arguments[1] && @message.arguments[1].downcase
34
+ case arg
35
+ when nil
36
+ usage
37
+
38
+ when _(:on)
39
+ plugin.config["active"] = true
40
+ answer(:activated)
41
+
42
+ when _(:off)
43
+ plugin.config["active"] = false
44
+ answer(:deactivated)
45
+
46
+ end
47
+ end
48
+
49
+ __END__
50
+ ---
51
+ :revision:
52
+ :configuration: 1
53
+ :summary:
54
+ en: |
55
+ Writes all messages butler receives into a raw log.
56
+ :about:
57
+ :mail: "apeiros@gmx.net"
58
+ :version: "1.0.0"
59
+ :author: "Stefan Rusterholz"
60
+ :strings:
61
+ :on:
62
+ en: "on"
63
+ :off:
64
+ en: "off"
65
+ :activated:
66
+ en: |
67
+ Activated raw logging
68
+ :deactivated:
69
+ en: |
70
+ Deactivated raw logging
71
+ :usage:
72
+ en: |
73
+ ![b]rawlog![o] ('on' | 'off')
74
+ :help:
75
+ en:
76
+ "": |
77
+ Writes all messages butler receives into a raw log.
@@ -0,0 +1,54 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ trigger "8ball"
10
+
11
+ Answers = [:yes, :no, :notgood, :signs_yes, :signs_no, :why_ask, :unclear]
12
+
13
+ def on_trigger
14
+ return answer(usage) if @message.arguments.length < 2
15
+ answer = Answers[rand(Answers.length)]
16
+ @butler.irc.action(_(:shake), message.channel ? message.channel : message.from)
17
+ sleep(1.5)
18
+ answer(answer)
19
+ end
20
+
21
+ __END__
22
+ ---
23
+ :revision:
24
+ :plugin: 1
25
+ :summary:
26
+ en: Ask butler a question and get an answer from the magic eightball.
27
+ :about:
28
+ :mail: "apeiros@gmx.net"
29
+ :version: "1.0.0"
30
+ :author: "Stefan Rusterholz"
31
+ :strings:
32
+ :shake:
33
+ en: 'Shakes the magic 8-ball...'
34
+ :yes:
35
+ en: 'Yes.'
36
+ :no:
37
+ en: 'no.'
38
+ :notgood:
39
+ en: 'Outlook is not so good.'
40
+ :signs_yes:
41
+ en: 'All signs point to yes.'
42
+ :signs no:
43
+ en: 'All signs point to no.'
44
+ :why_ask:
45
+ en: 'Why the hell are you asking me?'
46
+ :unclear:
47
+ en: 'The answer is unclear.'
48
+ :usage:
49
+ en: |
50
+ ![b]8ball![o] *![c(blue)]question![o]
51
+ :help:
52
+ en:
53
+ "": |
54
+ Ask butler a question and get an answer from the magic eightball.
@@ -0,0 +1,174 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'abbrev'
10
+
11
+ Stone = "![c(%s),(%s)]<>![r]"
12
+ None = "![c(red),(red)]<>![r]"
13
+ Wrong = "![c(blue),(blue)]<>![r]"
14
+ Correct = "![c(green),(green)]<>![r]"
15
+
16
+ trigger(
17
+ "en" => "mastermind",
18
+ "de" => "mastermind"
19
+ )
20
+
21
+ def on_trigger
22
+ case message.arguments.first.downcase
23
+ when _(:colors)
24
+ message.answer(_(:colors))
25
+ when _(:rules)
26
+ message.answer(_(:rules))
27
+ when _(:stop)
28
+ game = MasterGame[message.from]
29
+ game.stop if game
30
+ when _(:start)
31
+ game = MasterGame.new
32
+ message.dialog(self, game) # timeout after 10min
33
+ else
34
+ message.answer(_(:illegal))
35
+ end
36
+ end
37
+
38
+ class MasterGame < Butler::Dialog
39
+ reminder 10.minutes, :reminder
40
+ timeout 15.minutes, :timeout
41
+
42
+ def initialize(stones=5, difficulty=:easy)
43
+ @game = Mastermind.new(stones, difficulty)
44
+ end
45
+
46
+ def dialog(responder, message, *data)
47
+ case message.arguments[1]
48
+ when _(:colors)
49
+ message.answer(_(:colors))
50
+ when _(:rules)
51
+ message.answer(_(:rules))
52
+ when _(:stop)
53
+ game = MasterGame[message.from]
54
+ game.stop if game
55
+ when _(:start)
56
+ game = MasterGame.new
57
+ message.dialog(game) # timeout after 10min
58
+ else
59
+ if stones = map_stones(*message.arguments) then
60
+ @game.try_stones(*stones)
61
+ else
62
+ message.answer(_(:illegal))
63
+ end
64
+ end
65
+ end
66
+
67
+ def reminder(user)
68
+ _(:reminder)
69
+ end
70
+
71
+ def timout(*a)
72
+ _(:timeout)
73
+ end
74
+ end
75
+
76
+ class Mastermind
77
+ attr_reader :stones
78
+ attr_reader :amount
79
+ attr_reader :turns
80
+ attr_reader :mode
81
+
82
+ Colors = [:red, :green, :blue, :yellow, :orange, :pink, :black]
83
+
84
+ def initialize(amount, mode=:easy)
85
+ @stones = Array.new(amount) { Colors[rand(Colors.length)] }
86
+ @amount = amount
87
+ @mode = mode
88
+ @turns = 0
89
+ end
90
+
91
+ def try_stones(*stones)
92
+ @turns += 1
93
+ return true if stones == @stones
94
+
95
+ if @mode == :difficult then
96
+ correct, wrong, none = 0, 0, 0
97
+ @stones.zip(stones) { |a, b|
98
+ if a == b then
99
+ correct += 1
100
+ elsif @stones.include?(b) then
101
+ wrong += 1
102
+ else
103
+ none += 1
104
+ end
105
+ }
106
+ [:correct]*correct + [:wrong]*wrong + [:none]*none
107
+ else
108
+ feedback = []
109
+ @stones.zip(stones) { |a, b|
110
+ if a == b then
111
+ feedback << :correct
112
+ elsif @stones.include?(b) then
113
+ feedback << :wrong
114
+ else
115
+ feedback << :none
116
+ end
117
+ }
118
+ feedback
119
+ end
120
+ end
121
+ end
122
+
123
+ __END__
124
+ ---
125
+ :revision:
126
+ :plugin: 1
127
+ :about:
128
+ :mail: "apeiros@gmx.net"
129
+ :version: "1.2.0"
130
+ :author: "Stefan Rusterholz"
131
+ :description:
132
+ en: "Mastermind - the game for brainsters"
133
+ :strings:
134
+ :red:
135
+ en: red
136
+ de: rot
137
+ :green:
138
+ en: green
139
+ de: grün
140
+ :blue:
141
+ en: blue
142
+ de: blau
143
+ :yellow:
144
+ en: yellow
145
+ de: gelb
146
+ :orange:
147
+ en: orange
148
+ de: orange
149
+ :pink:
150
+ en: pink
151
+ de: pink
152
+ :black:
153
+ en: black
154
+ de: black
155
+ :rules:
156
+ en: |
157
+ The rules are simple: try to guess the color combination of the stones.
158
+ If you place a stone correct in color and location, it will display a white stone in that position.
159
+ If you place a stone whichs color appears on another location, it will display a black stone in that position.
160
+ The target is it, to get the combination in as little tries as possible.
161
+ :illegal:
162
+ de: |
163
+ Unbekannter Befehl. Benutzen Sie:
164
+ mm (regeln|farben|start|stop|<steine>)
165
+ Steine: ... (jede eindeutige Abkürzung funktioniert).
166
+ :reminder:
167
+ en: |
168
+ Sie haben noch ein laufendes Mastermind-Spiel.
169
+ Benutzen Sie 'mm stop' um das Spiel zu beenden.
170
+ de: |
171
+ Sie haben noch ein laufendes Mastermind-Spiel.
172
+ Benutzen Sie 'mm stop' um das Spiel zu beenden.
173
+ :stop:
174
+ de: "Spiel gestoppt, die richtige Lösung wäre gewesen: <%= stones %>"