rbot 0.9.14 → 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +6 -2
- data/REQUIREMENTS +7 -1
- data/Rakefile +10 -32
- data/bin/rbot +6 -1
- data/bin/svnwatch-postcommit-hook +68 -0
- data/data/rbot/contrib/plugins/stats.rb +3 -3
- data/data/rbot/contrib/plugins/vandale.rb +1 -1
- data/data/rbot/filters/rss.rb +72 -0
- data/data/rbot/languages/finnish.lang +50 -0
- data/data/rbot/plugins/alias.rb +6 -6
- data/data/rbot/plugins/autorejoin.rb +41 -2
- data/data/rbot/plugins/bans.rb +100 -6
- data/data/rbot/plugins/bash.rb +9 -4
- data/data/rbot/plugins/cal.rb +1 -1
- data/data/rbot/plugins/chucknorris.rb +6 -6
- data/data/rbot/plugins/debugger.rb +7 -3
- data/data/rbot/plugins/deepthoughts.rb +1 -1
- data/data/rbot/plugins/delicious.rb +6 -2
- data/data/rbot/plugins/dice.rb +7 -7
- data/data/rbot/plugins/dict.rb +4 -3
- data/data/rbot/plugins/dictclient.rb +17 -13
- data/data/rbot/plugins/digg.rb +3 -3
- data/data/rbot/plugins/eightball.rb +1 -1
- data/data/rbot/plugins/factoids.rb +13 -4
- data/data/rbot/plugins/figlet.rb +4 -4
- data/data/rbot/plugins/forecast.rb +3 -3
- data/data/rbot/plugins/fortune.rb +14 -8
- data/data/rbot/plugins/freshmeat.rb +2 -2
- data/data/rbot/plugins/games/azgame.rb +72 -19
- data/data/rbot/plugins/games/hangman.rb +499 -0
- data/data/rbot/plugins/games/quiz.rb +15 -13
- data/data/rbot/plugins/games/roshambo.rb +1 -1
- data/data/rbot/plugins/games/roulette.rb +4 -4
- data/data/rbot/plugins/games/shiritori.rb +31 -31
- data/data/rbot/plugins/games/uno.rb +28 -6
- data/data/rbot/plugins/games/wheelfortune.rb +1 -3
- data/data/rbot/plugins/geoip.rb +83 -28
- data/data/rbot/plugins/googlefight.rb +64 -0
- data/data/rbot/plugins/greet.rb +45 -0
- data/data/rbot/plugins/grouphug.rb +40 -12
- data/data/rbot/plugins/imdb.rb +4 -4
- data/data/rbot/plugins/insult.rb +2 -2
- data/data/rbot/plugins/karma.rb +6 -5
- data/data/rbot/plugins/keywords.rb +26 -22
- data/data/rbot/plugins/lart.rb +5 -6
- data/data/rbot/plugins/lastfm.rb +488 -125
- data/data/rbot/plugins/lib_spotify.rb +84 -0
- data/data/rbot/plugins/linkbot.rb +1 -1
- data/data/rbot/plugins/markov.rb +567 -78
- data/data/rbot/plugins/math.rb +3 -3
- data/data/rbot/plugins/modes.rb +1 -1
- data/data/rbot/plugins/nickrecover.rb +1 -1
- data/data/rbot/plugins/nickserv.rb +7 -7
- data/data/rbot/plugins/note.rb +55 -0
- data/data/rbot/plugins/nslookup.rb +2 -2
- data/data/rbot/plugins/quakeauth.rb +4 -4
- data/data/rbot/plugins/quotes.rb +53 -19
- data/data/rbot/plugins/reaction.rb +76 -19
- data/data/rbot/plugins/remind.rb +3 -96
- data/data/rbot/plugins/ri.rb +1 -1
- data/data/rbot/plugins/rot13.rb +1 -1
- data/data/rbot/plugins/rss.rb +296 -190
- data/data/rbot/plugins/salut.rb +8 -8
- data/data/rbot/plugins/script.rb +48 -11
- data/data/rbot/plugins/search.rb +124 -28
- data/data/rbot/plugins/seen.rb +162 -31
- data/data/rbot/plugins/shortenurls.rb +1 -1
- data/data/rbot/plugins/slashdot.rb +19 -6
- data/data/rbot/plugins/spotify.rb +78 -0
- data/data/rbot/plugins/theyfightcrime.rb +10 -10
- data/data/rbot/plugins/time.rb +2 -2
- data/data/rbot/plugins/translator.rb +161 -85
- data/data/rbot/plugins/tube.rb +2 -2
- data/data/rbot/plugins/tumblr.rb +143 -0
- data/data/rbot/plugins/twitter.rb +25 -6
- data/data/rbot/plugins/urban.rb +6 -4
- data/data/rbot/plugins/url.rb +49 -10
- data/data/rbot/plugins/weather.rb +6 -6
- data/data/rbot/plugins/wserver.rb +5 -5
- data/data/rbot/plugins/youtube.rb +12 -12
- data/data/rbot/templates/lart/larts-italian +1 -1
- data/launch_here.rb +68 -0
- data/lib/rbot/botuser.rb +1 -1
- data/lib/rbot/compat19.rb +70 -0
- data/lib/rbot/config.rb +8 -6
- data/lib/rbot/core/auth.rb +37 -21
- data/lib/rbot/core/basics.rb +33 -2
- data/lib/rbot/core/config.rb +24 -17
- data/lib/rbot/core/filters_ui.rb +2 -2
- data/lib/rbot/core/irclog.rb +20 -11
- data/lib/rbot/core/remote.rb +9 -9
- data/lib/rbot/core/unicode.rb +4 -0
- data/lib/rbot/core/userdata.rb +16 -1
- data/lib/rbot/core/utils/extends.rb +76 -0
- data/lib/rbot/core/utils/filters.rb +47 -0
- data/lib/rbot/core/utils/httputil.rb +36 -26
- data/lib/rbot/core/utils/parse_time.rb +193 -0
- data/lib/rbot/core/utils/utils.rb +81 -56
- data/lib/rbot/core/utils/wordlist.rb +66 -0
- data/lib/rbot/core/wordlist_ui.rb +27 -0
- data/lib/rbot/irc.rb +59 -19
- data/lib/rbot/ircbot.rb +190 -58
- data/lib/rbot/ircsocket.rb +14 -8
- data/lib/rbot/language.rb +4 -3
- data/lib/rbot/load-gettext.rb +22 -9
- data/lib/rbot/message.rb +89 -18
- data/lib/rbot/messagemapper.rb +71 -19
- data/lib/rbot/plugins.rb +112 -44
- data/lib/rbot/{registry.rb → registry/bdb.rb} +226 -22
- data/lib/rbot/registry/tc.rb +531 -0
- data/lib/rbot/rfc2812.rb +33 -8
- data/lib/rbot/timer.rb +12 -20
- data/po/en_US/rbot-autorejoin.po +3 -0
- data/po/en_US/rbot-azgame.po +51 -43
- data/po/en_US/rbot-bash.po +15 -0
- data/po/en_US/rbot-dictclient.po +20 -20
- data/po/en_US/rbot-factoids.po +9 -9
- data/po/en_US/rbot-geoip.po +0 -0
- data/po/en_US/rbot-googlefight.po +24 -0
- data/po/en_US/rbot-grouphug.po +4 -4
- data/po/en_US/rbot-hangman.po +114 -0
- data/po/en_US/rbot-keywords.po +3 -3
- data/po/en_US/rbot-lastfm.po +268 -70
- data/po/en_US/rbot-markov.po +73 -2
- data/po/en_US/rbot-quotes.po +21 -21
- data/po/en_US/rbot-rss.po +6 -2
- data/po/en_US/rbot-script.po +3 -0
- data/po/en_US/rbot-seen.po +72 -0
- data/po/en_US/rbot-spell.po +2 -2
- data/po/en_US/rbot-translator.po +13 -13
- data/po/en_US/rbot-twitter.po +3 -3
- data/po/en_US/rbot-uno.po +131 -114
- data/po/en_US/rbot-wall.po +12 -13
- data/po/en_US/rbot-wheelfortune.po +41 -41
- data/po/en_US/rbot.po +254 -194
- data/po/fi/rbot-alias.po +82 -0
- data/po/fi/rbot-autoop.po +0 -0
- data/po/fi/rbot-autorejoin.po +20 -0
- data/po/fi/rbot-azgame.po +194 -0
- data/po/fi/rbot-bans.po +0 -0
- data/po/fi/rbot-bash.po +32 -0
- data/po/fi/rbot-botsnack.po +0 -0
- data/po/fi/rbot-cal.po +20 -0
- data/po/fi/rbot-chanserv.po +0 -0
- data/po/fi/rbot-chucknorris.po +0 -0
- data/po/fi/rbot-debugger.po +0 -0
- data/po/fi/rbot-deepthoughts.po +0 -0
- data/po/fi/rbot-delicious.po +0 -0
- data/po/fi/rbot-dice.po +0 -0
- data/po/fi/rbot-dict.po +0 -0
- data/po/fi/rbot-dictclient.po +111 -0
- data/po/fi/rbot-digg.po +0 -0
- data/po/fi/rbot-eightball.po +0 -0
- data/po/fi/rbot-excuse.po +0 -0
- data/po/fi/rbot-factoids.po +107 -0
- data/po/fi/rbot-figlet.po +36 -0
- data/po/fi/rbot-fish.po +0 -0
- data/po/fi/rbot-forecast.po +0 -0
- data/po/fi/rbot-fortune.po +0 -0
- data/po/fi/rbot-freshmeat.po +0 -0
- data/po/fi/rbot-geoip.po +0 -0
- data/po/fi/rbot-googlefight.po +24 -0
- data/po/fi/rbot-grouphug.po +35 -0
- data/po/fi/rbot-hangman.po +121 -0
- data/po/fi/rbot-hl2.po +0 -0
- data/po/fi/rbot-host.po +20 -0
- data/po/fi/rbot-imdb.po +0 -0
- data/po/fi/rbot-insult.po +0 -0
- data/po/fi/rbot-iplookup.po +0 -0
- data/po/fi/rbot-karma.po +0 -0
- data/po/fi/rbot-keywords.po +24 -0
- data/po/fi/rbot-lart.po +0 -0
- data/po/fi/rbot-lastfm.po +377 -0
- data/po/fi/rbot-linkbot.po +0 -0
- data/po/fi/rbot-markov.po +91 -0
- data/po/fi/rbot-math.po +0 -0
- data/po/fi/rbot-modes.po +0 -0
- data/po/fi/rbot-nickrecover.po +36 -0
- data/po/fi/rbot-nickserv.po +104 -0
- data/po/fi/rbot-nslookup.po +0 -0
- data/po/fi/rbot-quakeauth.po +0 -0
- data/po/fi/rbot-quiz.po +0 -0
- data/po/fi/rbot-quotes.po +108 -0
- data/po/fi/rbot-reaction.po +0 -0
- data/po/fi/rbot-remind.po +0 -0
- data/po/fi/rbot-remotectl.po +0 -0
- data/po/fi/rbot-ri.po +0 -0
- data/po/fi/rbot-roshambo.po +0 -0
- data/po/fi/rbot-rot13.po +0 -0
- data/po/fi/rbot-roulette.po +0 -0
- data/po/fi/rbot-rss.po +24 -0
- data/po/fi/rbot-salut.po +0 -0
- data/po/fi/rbot-script.po +20 -0
- data/po/fi/rbot-search.po +0 -0
- data/po/fi/rbot-seen.po +92 -0
- data/po/fi/rbot-shiritori.po +102 -0
- data/po/fi/rbot-shortenurls.po +0 -0
- data/po/fi/rbot-slashdot.po +0 -0
- data/po/fi/rbot-spell.po +54 -0
- data/po/fi/rbot-theyfightcrime.po +0 -0
- data/po/fi/rbot-threat.po +0 -0
- data/po/fi/rbot-time.po +0 -0
- data/po/fi/rbot-topic.po +0 -0
- data/po/fi/rbot-translator.po +77 -0
- data/po/fi/rbot-tube.po +0 -0
- data/po/fi/rbot-twitter.po +24 -0
- data/po/fi/rbot-uno.po +529 -0
- data/po/fi/rbot-urban.po +0 -0
- data/po/fi/rbot-url.po +0 -0
- data/po/fi/rbot-usermodes.po +0 -0
- data/po/fi/rbot-wall.po +32 -0
- data/po/fi/rbot-weather.po +0 -0
- data/po/fi/rbot-wheelfortune.po +205 -0
- data/po/fi/rbot-wow.po +0 -0
- data/po/fi/rbot-wserver.po +0 -0
- data/po/fi/rbot-youtube.po +58 -0
- data/po/fi/rbot.po +1152 -0
- data/po/fr/rbot-autorejoin.po +3 -0
- data/po/fr/rbot-azgame.po +51 -43
- data/po/fr/rbot-bash.po +15 -0
- data/po/fr/rbot-dictclient.po +20 -20
- data/po/fr/rbot-factoids.po +9 -9
- data/po/fr/rbot-geoip.po +0 -0
- data/po/fr/rbot-googlefight.po +24 -0
- data/po/fr/rbot-grouphug.po +4 -4
- data/po/fr/rbot-hangman.po +114 -0
- data/po/fr/rbot-keywords.po +3 -3
- data/po/fr/rbot-lastfm.po +268 -70
- data/po/fr/rbot-markov.po +74 -2
- data/po/fr/rbot-quotes.po +21 -21
- data/po/fr/rbot-rss.po +6 -2
- data/po/fr/rbot-script.po +3 -0
- data/po/fr/rbot-seen.po +72 -0
- data/po/fr/rbot-spell.po +2 -2
- data/po/fr/rbot-translator.po +13 -13
- data/po/fr/rbot-twitter.po +3 -3
- data/po/fr/rbot-uno.po +132 -114
- data/po/fr/rbot-wall.po +8 -9
- data/po/fr/rbot-wheelfortune.po +41 -41
- data/po/fr/rbot.po +268 -197
- data/po/it/rbot-autorejoin.po +3 -0
- data/po/it/rbot-azgame.po +50 -42
- data/po/it/rbot-bash.po +15 -0
- data/po/it/rbot-dictclient.po +20 -20
- data/po/it/rbot-factoids.po +9 -9
- data/po/it/rbot-geoip.po +0 -0
- data/po/it/rbot-googlefight.po +24 -0
- data/po/it/rbot-grouphug.po +4 -4
- data/po/it/rbot-hangman.po +114 -0
- data/po/it/rbot-keywords.po +3 -3
- data/po/it/rbot-lastfm.po +268 -70
- data/po/it/rbot-markov.po +75 -3
- data/po/it/rbot-quotes.po +21 -21
- data/po/it/rbot-rss.po +7 -3
- data/po/it/rbot-script.po +19 -0
- data/po/it/rbot-seen.po +72 -0
- data/po/it/rbot-spell.po +2 -2
- data/po/it/rbot-translator.po +13 -13
- data/po/it/rbot-twitter.po +3 -3
- data/po/it/rbot-uno.po +137 -116
- data/po/it/rbot-wall.po +8 -9
- data/po/it/rbot-wheelfortune.po +41 -41
- data/po/it/rbot.po +265 -208
- data/po/ja/rbot-autorejoin.po +3 -0
- data/po/ja/rbot-azgame.po +51 -43
- data/po/ja/rbot-bash.po +15 -0
- data/po/ja/rbot-dictclient.po +20 -20
- data/po/ja/rbot-factoids.po +9 -9
- data/po/ja/rbot-geoip.po +0 -0
- data/po/ja/rbot-googlefight.po +24 -0
- data/po/ja/rbot-grouphug.po +4 -4
- data/po/ja/rbot-hangman.po +114 -0
- data/po/ja/rbot-keywords.po +3 -3
- data/po/ja/rbot-lastfm.po +268 -70
- data/po/ja/rbot-markov.po +73 -2
- data/po/ja/rbot-quotes.po +21 -21
- data/po/ja/rbot-rss.po +6 -2
- data/po/ja/rbot-script.po +3 -0
- data/po/ja/rbot-seen.po +72 -0
- data/po/ja/rbot-spell.po +2 -2
- data/po/ja/rbot-translator.po +13 -13
- data/po/ja/rbot-twitter.po +3 -3
- data/po/ja/rbot-uno.po +131 -114
- data/po/ja/rbot-wall.po +8 -9
- data/po/ja/rbot-wheelfortune.po +41 -41
- data/po/ja/rbot.po +248 -192
- data/po/rbot-alias.pot +2 -2
- data/po/rbot-autorejoin.pot +21 -0
- data/po/rbot-azgame.pot +51 -43
- data/po/rbot-bash.pot +33 -0
- data/po/rbot-cal.pot +2 -2
- data/po/rbot-dictclient.pot +21 -21
- data/po/rbot-factoids.pot +10 -10
- data/po/rbot-figlet.pot +2 -2
- data/po/rbot-geoip.pot +0 -0
- data/po/rbot-googlefight.pot +25 -0
- data/po/rbot-grouphug.pot +6 -6
- data/po/rbot-hangman.pot +115 -0
- data/po/rbot-host.pot +2 -2
- data/po/rbot-keywords.pot +4 -4
- data/po/rbot-lastfm.pot +270 -72
- data/po/rbot-markov.pot +74 -3
- data/po/rbot-nickrecover.pot +2 -2
- data/po/rbot-nickserv.pot +2 -2
- data/po/rbot-quotes.pot +22 -22
- data/po/rbot-rss.pot +7 -3
- data/po/rbot-script.pot +21 -0
- data/po/rbot-seen.pot +90 -0
- data/po/rbot-shiritori.pot +2 -2
- data/po/rbot-spell.pot +3 -3
- data/po/rbot-translator.pot +14 -14
- data/po/rbot-twitter.pot +4 -4
- data/po/rbot-uno.pot +132 -115
- data/po/rbot-wall.pot +2 -2
- data/po/rbot-wheelfortune.pot +42 -42
- data/po/rbot-youtube.pot +2 -2
- data/po/rbot.pot +249 -193
- data/po/zh_CN/rbot-autorejoin.po +3 -0
- data/po/zh_CN/rbot-azgame.po +50 -42
- data/po/zh_CN/rbot-bash.po +15 -0
- data/po/zh_CN/rbot-dictclient.po +20 -20
- data/po/zh_CN/rbot-factoids.po +9 -9
- data/po/zh_CN/rbot-geoip.po +0 -0
- data/po/zh_CN/rbot-googlefight.po +24 -0
- data/po/zh_CN/rbot-grouphug.po +4 -4
- data/po/zh_CN/rbot-hangman.po +114 -0
- data/po/zh_CN/rbot-keywords.po +3 -3
- data/po/zh_CN/rbot-lastfm.po +268 -70
- data/po/zh_CN/rbot-markov.po +73 -2
- data/po/zh_CN/rbot-quotes.po +21 -21
- data/po/zh_CN/rbot-rss.po +6 -2
- data/po/zh_CN/rbot-script.po +3 -0
- data/po/zh_CN/rbot-seen.po +72 -0
- data/po/zh_CN/rbot-spell.po +2 -2
- data/po/zh_CN/rbot-translator.po +13 -13
- data/po/zh_CN/rbot-twitter.po +3 -3
- data/po/zh_CN/rbot-uno.po +131 -114
- data/po/zh_CN/rbot-wall.po +7 -8
- data/po/zh_CN/rbot-wheelfortune.po +41 -41
- data/po/zh_CN/rbot.po +248 -192
- data/po/zh_TW/rbot-autorejoin.po +3 -0
- data/po/zh_TW/rbot-azgame.po +50 -42
- data/po/zh_TW/rbot-bash.po +15 -0
- data/po/zh_TW/rbot-dictclient.po +20 -20
- data/po/zh_TW/rbot-factoids.po +9 -9
- data/po/zh_TW/rbot-geoip.po +0 -0
- data/po/zh_TW/rbot-googlefight.po +24 -0
- data/po/zh_TW/rbot-grouphug.po +4 -4
- data/po/zh_TW/rbot-hangman.po +114 -0
- data/po/zh_TW/rbot-keywords.po +3 -3
- data/po/zh_TW/rbot-lastfm.po +268 -70
- data/po/zh_TW/rbot-markov.po +73 -2
- data/po/zh_TW/rbot-quotes.po +21 -21
- data/po/zh_TW/rbot-rss.po +6 -2
- data/po/zh_TW/rbot-script.po +3 -0
- data/po/zh_TW/rbot-seen.po +72 -0
- data/po/zh_TW/rbot-spell.po +2 -2
- data/po/zh_TW/rbot-translator.po +13 -13
- data/po/zh_TW/rbot-twitter.po +3 -3
- data/po/zh_TW/rbot-uno.po +131 -114
- data/po/zh_TW/rbot-wall.po +7 -8
- data/po/zh_TW/rbot-wheelfortune.po +41 -41
- data/po/zh_TW/rbot.po +253 -194
- data/setup.rb +4 -4
- metadata +127 -18
- data/README +0 -43
- data/data/rbot/plugins/fish.rb +0 -121
- data/lib/rbot/dbhash.rb +0 -199
@@ -33,9 +33,6 @@ define_structure :QuizBundle, :question, :answer
|
|
33
33
|
define_structure :PlayerStats, :score, :jokers, :jokers_time
|
34
34
|
# Why do we still need jokers_time? //Firetech
|
35
35
|
|
36
|
-
# Maximum number of jokers a player can gain
|
37
|
-
Max_Jokers = 3
|
38
|
-
|
39
36
|
# Control codes
|
40
37
|
Color = "\003"
|
41
38
|
Bold = "\002"
|
@@ -164,6 +161,11 @@ class QuizPlugin < Plugin
|
|
164
161
|
:default => ['quiz.rbot'],
|
165
162
|
:desc => "List of files and URLs that will be used to retrieve quiz questions")
|
166
163
|
|
164
|
+
|
165
|
+
Config.register Config::IntegerValue.new('quiz.max_jokers',
|
166
|
+
:default => 3,
|
167
|
+
:desc => "Maximum number of jokers a player can gain")
|
168
|
+
|
167
169
|
def initialize()
|
168
170
|
super
|
169
171
|
|
@@ -184,10 +186,11 @@ class QuizPlugin < Plugin
|
|
184
186
|
# (in quiz/) or web pages.
|
185
187
|
#
|
186
188
|
def fetch_data( m )
|
187
|
-
# Read the winning messages file
|
189
|
+
# Read the winning messages file
|
188
190
|
@win_messages = Array.new
|
189
|
-
|
190
|
-
|
191
|
+
winfile = datafile 'win_messages'
|
192
|
+
if File.exists? winfile
|
193
|
+
IO.foreach(winfile) { |line| @win_messages << line.chomp }
|
191
194
|
else
|
192
195
|
warning( "win_messages file not found!" )
|
193
196
|
# Fill the array with a least one message or code accessing it would fail
|
@@ -212,13 +215,12 @@ class QuizPlugin < Plugin
|
|
212
215
|
m.reply "Failed to download questions from #{p}, ignoring sources"
|
213
216
|
end
|
214
217
|
else
|
215
|
-
path =
|
218
|
+
path = datafile p
|
216
219
|
debug "Fetching from #{path}"
|
217
220
|
|
218
221
|
# Local data
|
219
222
|
begin
|
220
|
-
|
221
|
-
data << "\n\n" << datafile.read
|
223
|
+
data << "\n\n" << File.read(path)
|
222
224
|
rescue
|
223
225
|
m.reply "Failed to read from local database file #{p}, skipping."
|
224
226
|
end
|
@@ -338,7 +340,7 @@ class QuizPlugin < Plugin
|
|
338
340
|
end
|
339
341
|
end
|
340
342
|
|
341
|
-
# If less than all other players' scores, append to table
|
343
|
+
# If less than all other players' scores, append to table
|
342
344
|
unless inserted
|
343
345
|
i += 1 unless q.rank_table.empty?
|
344
346
|
q.rank_table << [nick, stats]
|
@@ -369,7 +371,7 @@ class QuizPlugin < Plugin
|
|
369
371
|
|
370
372
|
message = m.message.downcase.strip
|
371
373
|
|
372
|
-
nick = m.sourcenick.to_s
|
374
|
+
nick = m.sourcenick.to_s
|
373
375
|
|
374
376
|
# Support multiple alternate answers and cores
|
375
377
|
answer = q.answers.find { |ans| ans.valid?(message) }
|
@@ -406,7 +408,7 @@ class QuizPlugin < Plugin
|
|
406
408
|
player.score = player.score + points
|
407
409
|
|
408
410
|
# Reward player with a joker every X points
|
409
|
-
if player.score % 15 == 0 and player.jokers <
|
411
|
+
if player.score % 15 == 0 and player.jokers < @bot.config['quiz.max_jokers']
|
410
412
|
player.jokers += 1
|
411
413
|
m.reply "#{nick} gains a new joker. Rejoice :)"
|
412
414
|
end
|
@@ -899,7 +901,7 @@ class QuizPlugin < Plugin
|
|
899
901
|
debug q.rank_table.inspect
|
900
902
|
|
901
903
|
nick = params[:nick]
|
902
|
-
val = [params[:jokers].to_i,
|
904
|
+
val = [params[:jokers].to_i, @bot.config['quiz.max_jokers']].min
|
903
905
|
if q.registry.has_key?(nick)
|
904
906
|
player = q.registry[nick]
|
905
907
|
player.jokers = val
|
@@ -2,13 +2,13 @@ define_structure :RouletteHistory, :games, :shots, :deaths, :misses, :wins
|
|
2
2
|
|
3
3
|
class RoulettePlugin < Plugin
|
4
4
|
Config.register Config::BooleanValue.new('roulette.autospin',
|
5
|
-
:default => true,
|
5
|
+
:default => true,
|
6
6
|
:desc => "Automatically spins the roulette at the butlast shot")
|
7
7
|
Config.register Config::BooleanValue.new('roulette.kick',
|
8
|
-
:default => false,
|
8
|
+
:default => false,
|
9
9
|
:desc => "Kicks shot players from the channel")
|
10
10
|
Config.register Config::BooleanValue.new('roulette.twice_in_a_row',
|
11
|
-
:default => false,
|
11
|
+
:default => false,
|
12
12
|
:desc => "Allow players to go twice in a row")
|
13
13
|
|
14
14
|
def initialize
|
@@ -174,7 +174,7 @@ class RoulettePlugin < Plugin
|
|
174
174
|
k = match[1]
|
175
175
|
|
176
176
|
total_players += 1
|
177
|
-
|
177
|
+
|
178
178
|
win_rate = v.wins.to_f / v.games * 100
|
179
179
|
if h_win_percent[0].nil? || win_rate > h_win_percent[1] && v.games > 2
|
180
180
|
h_win_percent = [[k], win_rate]
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#-- vim:sw=2:et
|
2
2
|
#kate: indent-width 2
|
3
3
|
#++
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# :title: Shiritori Plugin for RBot
|
6
6
|
#
|
7
7
|
# Author:: Yaohan Chen <yaohan.chen@gmail.com>
|
@@ -16,10 +16,10 @@
|
|
16
16
|
# players can interrupt a turn to join, or a free mode where anyone can speak at any
|
17
17
|
# time.
|
18
18
|
#
|
19
|
-
# In Japanese mode, if present, the plugin can use normalize-japanese
|
19
|
+
# In Japanese mode, if present, the plugin can use normalize-japanese
|
20
20
|
# <http://neruchan.mine.nu:60880/normalize-japanese.rb> to allow
|
21
21
|
# katakana words be used like hiragana.
|
22
|
-
#
|
22
|
+
#
|
23
23
|
# TODO
|
24
24
|
# * a system to describe settings, so they can be displayed, changed and saved
|
25
25
|
# * adjust settings during game
|
@@ -35,7 +35,7 @@ class Dictionary
|
|
35
35
|
def has_word?(s)
|
36
36
|
raise NotImplementedError
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# whether any word starts with prefix, excluding words in excludes. This can be
|
40
40
|
# possible with non-enumerable dictionaries since some dictionary engines provide
|
41
41
|
# prefix searching.
|
@@ -51,12 +51,12 @@ class WordlistDictionary < Dictionary
|
|
51
51
|
@words = words
|
52
52
|
# debug "Created dictionary with #{@words.length} words"
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
# whether string s is a word
|
56
56
|
def has_word?(s)
|
57
57
|
@words.include? s
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
# whether any word starts with prefix, excluding words in excludes
|
61
61
|
def any_word_starting?(prefix, excludes)
|
62
62
|
# (@words - except).any? {|w| w =~ /\A#{prefix}.+/}
|
@@ -69,7 +69,7 @@ end
|
|
69
69
|
# whether it's possible to continue a word
|
70
70
|
class Shiritori
|
71
71
|
attr_reader :used_words
|
72
|
-
|
72
|
+
|
73
73
|
# dictionary:: a Dictionary object
|
74
74
|
# overlap_lengths:: a Range for allowed lengths to overlap when continuing words
|
75
75
|
# check_continuable:: whether all words are checked whether they're continuable,
|
@@ -82,7 +82,7 @@ class Shiritori
|
|
82
82
|
@allow_reuse = allow_reuse
|
83
83
|
@used_words = []
|
84
84
|
end
|
85
|
-
|
85
|
+
|
86
86
|
# Prefix of s with length n
|
87
87
|
def head_of(s, n)
|
88
88
|
# TODO ruby2 unicode
|
@@ -102,7 +102,7 @@ class Shiritori
|
|
102
102
|
def range_under(r, n)
|
103
103
|
r.begin .. [r.end, n-1].min
|
104
104
|
end
|
105
|
-
|
105
|
+
|
106
106
|
# TODO allow the ruleset to customize this
|
107
107
|
def continues?(w2, w1)
|
108
108
|
# this uses the definition w1[-n,n] == w2[0,n] && n < [w1.length, w2.length].min
|
@@ -110,7 +110,7 @@ class Shiritori
|
|
110
110
|
range_under(@overlap_lengths, [len(w1), len(w2)].min).any? {|n|
|
111
111
|
tail_of(w1, n)== head_of(w2, n)}
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
# Checks whether *any* unused word in the dictionary completes the word
|
115
115
|
# This has the limitation that it can't detect when a word is continuable, but the
|
116
116
|
# only continuers aren't continuable
|
@@ -118,8 +118,8 @@ class Shiritori
|
|
118
118
|
range_under(@overlap_lengths, len(s)).any? {|n|
|
119
119
|
@dictionary.any_word_starting?(tail_of(s, n), @used_words) }
|
120
120
|
end
|
121
|
-
|
122
|
-
# Given a string, give a verdict based on current shiritori state and dictionary
|
121
|
+
|
122
|
+
# Given a string, give a verdict based on current shiritori state and dictionary
|
123
123
|
def process(s)
|
124
124
|
# TODO optionally allow used words
|
125
125
|
# TODO ruby2 unicode
|
@@ -167,14 +167,14 @@ class ShiritoriGame
|
|
167
167
|
@timer_handle = nil
|
168
168
|
@say = say
|
169
169
|
@when_die = when_die
|
170
|
-
|
170
|
+
|
171
171
|
# TODO allow other forms of dictionaries
|
172
172
|
dictionary = WordlistDictionary.new(@ruleset[:words])
|
173
173
|
@game = Shiritori.new(dictionary, @ruleset[:overlap_lengths],
|
174
174
|
@ruleset[:check_continuable],
|
175
175
|
@ruleset[:allow_reuse])
|
176
176
|
end
|
177
|
-
|
177
|
+
|
178
178
|
def say(s)
|
179
179
|
@say.call(s)
|
180
180
|
end
|
@@ -184,10 +184,10 @@ class ShiritoriGame
|
|
184
184
|
# * when time_limit > 0, new players can join at any time, but existing players must
|
185
185
|
# take turns, each of which expires after time_limit
|
186
186
|
# * when time_imit is 0, anyone can speak in the game at any time
|
187
|
-
def take_turns?
|
187
|
+
def take_turns?
|
188
188
|
@players.length > 1 && @ruleset[:time_limit] > 0
|
189
189
|
end
|
190
|
-
|
190
|
+
|
191
191
|
# the player who has the current turn
|
192
192
|
def current_player
|
193
193
|
@players.first
|
@@ -200,7 +200,7 @@ class ShiritoriGame
|
|
200
200
|
def previous_word
|
201
201
|
@game.used_words[-2]
|
202
202
|
end
|
203
|
-
|
203
|
+
|
204
204
|
# announce the current word, and player if take_turns?
|
205
205
|
def announce
|
206
206
|
say(if take_turns?
|
@@ -237,13 +237,13 @@ class ShiritoriGame
|
|
237
237
|
end
|
238
238
|
announce
|
239
239
|
end
|
240
|
-
|
240
|
+
|
241
241
|
# handle when turn time limit goes out
|
242
242
|
def time_out
|
243
243
|
if @ruleset[:lose_when_timeout]
|
244
244
|
say _("%{player} took too long and is out of the game. Try again next game!") %
|
245
245
|
{ :player => current_player }
|
246
|
-
if @players.length == 2
|
246
|
+
if @players.length == 2
|
247
247
|
# 2 players before, and one should remain now
|
248
248
|
# since the game is ending, save the trouble of removing and booting the player
|
249
249
|
say _("%{player} is the last remaining player and the winner! Congratulations!") %
|
@@ -269,12 +269,12 @@ class ShiritoriGame
|
|
269
269
|
def handle_message(m)
|
270
270
|
message = m.message
|
271
271
|
speaker = m.sourcenick.to_s
|
272
|
-
|
272
|
+
|
273
273
|
return unless @ruleset[:listen] =~ message
|
274
274
|
|
275
275
|
# in take_turns mode, only new players are allowed to interrupt a turn
|
276
276
|
return if @booted_players.include? speaker ||
|
277
|
-
(take_turns? &&
|
277
|
+
(take_turns? &&
|
278
278
|
speaker != current_player &&
|
279
279
|
(@players.length > 1 && @players.include?(speaker)))
|
280
280
|
|
@@ -310,7 +310,7 @@ class ShiritoriGame
|
|
310
310
|
m.reply _("It's impossible to continue the chain from %{word}. Start with another word.") % {:word => message}
|
311
311
|
end
|
312
312
|
end
|
313
|
-
|
313
|
+
|
314
314
|
# end the game
|
315
315
|
def die
|
316
316
|
# redefine restart_timer to no-op
|
@@ -331,11 +331,11 @@ class ShiritoriPlugin < Plugin
|
|
331
331
|
_("A game in which each player must continue the previous player's word, by using its last one or few characters/letters of the word to start a new word. 'shiritori <ruleset>' => Play shiritori with a set of rules. Available rulesets: %{rulesets}. 'shiritori stop' => Stop the current shiritori game.") %
|
332
332
|
{:rulesets => @rulesets.keys.join(', ')}
|
333
333
|
end
|
334
|
-
|
334
|
+
|
335
335
|
def initialize()
|
336
336
|
super
|
337
337
|
@games = {}
|
338
|
-
|
338
|
+
|
339
339
|
# TODO make rulesets more easily customizable
|
340
340
|
# TODO initialize default ruleset from config
|
341
341
|
# Default values of rulesets
|
@@ -390,7 +390,7 @@ class ShiritoriPlugin < Plugin
|
|
390
390
|
if ruleset.has_key?(:wordlist_file)
|
391
391
|
begin
|
392
392
|
ruleset[:words] =
|
393
|
-
File.new(
|
393
|
+
File.new(datafile(ruleset[:wordlist_file])).grep(
|
394
394
|
ruleset[:listen]) {|l| ruleset[:normalize].call l.chomp}
|
395
395
|
rescue
|
396
396
|
raise "unable to load word list"
|
@@ -401,7 +401,7 @@ class ShiritoriPlugin < Plugin
|
|
401
401
|
end
|
402
402
|
return ruleset
|
403
403
|
end
|
404
|
-
|
404
|
+
|
405
405
|
# start shiritori in a channel
|
406
406
|
def cmd_shiritori(m, params)
|
407
407
|
if @games.has_key?( m.channel )
|
@@ -426,7 +426,7 @@ class ShiritoriPlugin < Plugin
|
|
426
426
|
end
|
427
427
|
end
|
428
428
|
end
|
429
|
-
|
429
|
+
|
430
430
|
# change rules for current game
|
431
431
|
def cmd_set(m, params)
|
432
432
|
require 'enumerator'
|
@@ -434,7 +434,7 @@ class ShiritoriPlugin < Plugin
|
|
434
434
|
params[:rules].each_slice(2) {|opt, value| new_rules[opt] = value}
|
435
435
|
raise NotImplementedError
|
436
436
|
end
|
437
|
-
|
437
|
+
|
438
438
|
# stop the current game
|
439
439
|
def cmd_stop(m, params)
|
440
440
|
if @games.has_key? m.channel
|
@@ -446,19 +446,19 @@ class ShiritoriPlugin < Plugin
|
|
446
446
|
m.reply _("No game to stop here, because no game is being played.")
|
447
447
|
end
|
448
448
|
end
|
449
|
-
|
449
|
+
|
450
450
|
# remove the game, so channel messages are no longer processed, and timer removed
|
451
451
|
def remove_game(channel)
|
452
452
|
@games.delete channel
|
453
453
|
end
|
454
|
-
|
454
|
+
|
455
455
|
# all messages from a channel is sent to its shiritori game if any
|
456
456
|
def message(m)
|
457
457
|
return unless @games.has_key?(m.channel)
|
458
458
|
# send the message to the game in the channel to handle it
|
459
459
|
@games[m.channel].handle_message m
|
460
460
|
end
|
461
|
-
|
461
|
+
|
462
462
|
# remove all games
|
463
463
|
def cleanup
|
464
464
|
@games.each_key {|g| g.die}
|
@@ -108,7 +108,7 @@ class UnoGame
|
|
108
108
|
@color = 'Wild'
|
109
109
|
raise if value and not value == '+4'
|
110
110
|
if value
|
111
|
-
@value = value.dup
|
111
|
+
@value = value.dup
|
112
112
|
@shortform = 'w'+value
|
113
113
|
else
|
114
114
|
@value = nil
|
@@ -411,7 +411,7 @@ class UnoGame
|
|
411
411
|
# only be possible if the first W+4 was illegal, so it wouldn't
|
412
412
|
# apply for a W+4 played on a +2 anyway.
|
413
413
|
#
|
414
|
-
if @picker == 0 and Wild === cards.first and cards.first.value
|
414
|
+
if @picker == 0 and Wild === cards.first and cards.first.value
|
415
415
|
# save the previous discard in case of challenge
|
416
416
|
@last_discard = @discard.dup
|
417
417
|
# save the color too, in case it was a Wild
|
@@ -761,7 +761,11 @@ class UnoGame
|
|
761
761
|
}
|
762
762
|
end
|
763
763
|
if @picker > 0 and not halted
|
764
|
-
|
764
|
+
if @discard.value == 'Reverse'
|
765
|
+
p = @players.last
|
766
|
+
else
|
767
|
+
p = @players[1]
|
768
|
+
end
|
765
769
|
announce _("%{p} has to pick %{b}%{n}%{b} cards!") % {
|
766
770
|
:p => p, :n => @picker, :b => Bold
|
767
771
|
}
|
@@ -841,8 +845,14 @@ class UnoPlugin < Plugin
|
|
841
845
|
_("The points won with a game of %{uno} are totalled from the cards remaining in the hands of the other players."),
|
842
846
|
_("Each normal (not special) card is worth its face value (from 0 to 9 points)."),
|
843
847
|
_("Each colored special card (+2, Reverse, Skip) is worth 20 points."),
|
844
|
-
_("Each Wild and Wild +4 is worth 50 points.")
|
848
|
+
_("Each Wild and Wild +4 is worth 50 points."),
|
849
|
+
help(plugin, 'top'),
|
850
|
+
help(plugin, 'topwin'),
|
845
851
|
].join(" ") % { :uno => UnoGame::UNO }
|
852
|
+
when 'top'
|
853
|
+
_("You can see the scoring table with 'uno top N' where N is the number of top scores to show.")
|
854
|
+
when 'topwin'
|
855
|
+
_("You can see the winners table with 'uno topwin N' where N is the number of top winners to show.")
|
846
856
|
when /cards?/
|
847
857
|
[
|
848
858
|
_("There are 108 cards in a standard %{uno} deck."),
|
@@ -859,7 +869,7 @@ class UnoPlugin < Plugin
|
|
859
869
|
_("'uno end' to end the game before its natural completion")
|
860
870
|
].join("; ")
|
861
871
|
else
|
862
|
-
_("%{uno} game. !uno to start a game. see 'help uno rules' for the rules, 'help uno admin' for admin commands. In-game commands: %{cmds}.") % {
|
872
|
+
_("%{uno} game. !uno to start a game. see 'help uno rules' for the rules, 'help uno admin' for admin commands, 'help uno score' for scoring rules. In-game commands: %{cmds}.") % {
|
863
873
|
:uno => UnoGame::UNO,
|
864
874
|
:cmds => help(plugin, 'commands')
|
865
875
|
}
|
@@ -870,6 +880,7 @@ class UnoPlugin < Plugin
|
|
870
880
|
return unless @games.key?(m.channel)
|
871
881
|
return unless m.plugin # skip messages such as: <someuser> botname,
|
872
882
|
g = @games[m.channel]
|
883
|
+
replied = true
|
873
884
|
case m.plugin.intern
|
874
885
|
when :jo # join game
|
875
886
|
return if m.params
|
@@ -931,11 +942,14 @@ class UnoPlugin < Plugin
|
|
931
942
|
when :tu # show whose turn is it
|
932
943
|
return if m.params
|
933
944
|
if g.has_turn?(m.source)
|
934
|
-
m.
|
945
|
+
m.reply _("it's your turn, sleepyhead"), :nick => true
|
935
946
|
else
|
936
947
|
g.show_turn(:cards => false)
|
937
948
|
end
|
949
|
+
else
|
950
|
+
replied=false
|
938
951
|
end
|
952
|
+
m.replied=true if replied
|
939
953
|
end
|
940
954
|
|
941
955
|
def create_game(m, p)
|
@@ -1147,6 +1161,14 @@ class UnoPlugin < Plugin
|
|
1147
1161
|
scores << [v.won.inject(0) { |s, w| s+=w.score }, k]
|
1148
1162
|
end
|
1149
1163
|
|
1164
|
+
if wins.empty?
|
1165
|
+
m.reply(_("no %{uno} games were completed here") % {
|
1166
|
+
:uno => UnoGame::UNO
|
1167
|
+
})
|
1168
|
+
return
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
|
1150
1172
|
if n = p[:scorenum]
|
1151
1173
|
msg = _("%{uno} %{num} highest scores: ") % {
|
1152
1174
|
:uno => UnoGame::UNO, :num => p[:scorenum]
|
@@ -476,9 +476,7 @@ class WheelOfFortune < Plugin
|
|
476
476
|
# m.reply "STUPID! YOU SO STUPID!"
|
477
477
|
return
|
478
478
|
when *game.must_buy
|
479
|
-
m.
|
480
|
-
:vowel => check
|
481
|
-
}
|
479
|
+
m.reply _("You must buy the %{vowel}") % {:vowel => check}, :nick => true
|
482
480
|
when :wrong
|
483
481
|
return
|
484
482
|
when Numeric, :missing
|