From 65bf1c4052c55a96e071d33c693ac5303a9fa24c Mon Sep 17 00:00:00 2001 From: Giuseppe Bilotta Date: Fri, 2 Jul 2010 16:58:50 +0200 Subject: [PATCH] ant's friend's UNO\! changes --- data/rbot/plugins/games/uno.rb | 126 ++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 41 deletions(-) diff --git a/data/rbot/plugins/games/uno.rb b/data/rbot/plugins/games/uno.rb index a86c33db..2b02c89f 100644 --- a/data/rbot/plugins/games/uno.rb +++ b/data/rbot/plugins/games/uno.rb @@ -108,7 +108,7 @@ class UnoGame @color = 'Wild' raise if value and not value == '+4' if value - @value = value.dup + @value = value.dup @shortform = 'w'+value else @value = nil @@ -151,6 +151,8 @@ class UnoGame attr_reader :discard # previous discard, in case of challenge attr_reader :last_discard + # flag indicating someone played a w+4 (0 is no, 1 is yes) + attr_reader :w4_played_flag # channel the game is played in attr_reader :channel # list of players @@ -174,6 +176,7 @@ class UnoGame @dropouts = [] @discard = nil @last_discard = nil + @w4_played_flag = 0 @value = nil @color = nil make_base_stock @@ -411,15 +414,17 @@ class UnoGame # only be possible if the first W+4 was illegal, so it wouldn't # apply for a W+4 played on a +2 anyway. # - if @picker == 0 and Wild === cards.first and cards.first.value + if @picker == 0 and Wild === cards.first and cards.first.value # save the previous discard in case of challenge @last_discard = @discard.dup # save the color too, in case it was a Wild @last_color = @color.dup + @w4_played_flag = 1 else # mark the move as not challengeable @last_discard = nil @last_color = nil + @w4_played_flag = 0 end set_discard(p.cards.delete_one(cards.shift)) if toplay > 1 @@ -451,10 +456,10 @@ class UnoGame announce _("%{p}, choose a color with: co r|b|g|y") % { :p => p } end else - announce _("you don't have two cards of that kind") + announce _("you can't play that card") end else - announce _("you don't have that card") + announce _("you can't play that card") end end @@ -512,6 +517,7 @@ class UnoGame # and restore the turn @players.unshift @players.pop end + @w4_played_flag = 0 end def pass(user) @@ -531,6 +537,7 @@ class UnoGame end end next_turn + @w4_played_flag = 0 end def choose_color(user, color) @@ -662,6 +669,12 @@ class UnoGame return end end + if @w4_played_flag == 1 + announce _("you cannot join until after the Wild +4 is resolved, %{p}") % { + :p => user + } + return + end cards = 7 if @start_time cards = (@players.inject(0) do |s, pl| @@ -761,11 +774,7 @@ class UnoGame } end if @picker > 0 and not halted - if @discard.value == 'Reverse' - p = @players.last - else - p = @players[1] - end + p = @players[1] announce _("%{p} has to pick %{b}%{n}%{b} cards!") % { :p => p, :n => @picker, :b => Bold } @@ -845,14 +854,8 @@ class UnoPlugin < Plugin _("The points won with a game of %{uno} are totalled from the cards remaining in the hands of the other players."), _("Each normal (not special) card is worth its face value (from 0 to 9 points)."), _("Each colored special card (+2, Reverse, Skip) is worth 20 points."), - _("Each Wild and Wild +4 is worth 50 points."), - help(plugin, 'top'), - help(plugin, 'topwin'), + _("Each Wild and Wild +4 is worth 50 points.") ].join(" ") % { :uno => UnoGame::UNO } - when 'top' - _("You can see the scoring table with 'uno top N' where N is the number of top scores to show.") - when 'topwin' - _("You can see the winners table with 'uno topwin N' where N is the number of top winners to show.") when /cards?/ [ _("There are 108 cards in a standard %{uno} deck."), @@ -869,7 +872,7 @@ class UnoPlugin < Plugin _("'uno end' to end the game before its natural completion") ].join("; ") else - _("%{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}.") % { + _("%{uno} game. !uno to start a game. see 'help uno rules' for the rules, 'help uno admin' for admin commands. In-game commands: %{cmds}.") % { :uno => UnoGame::UNO, :cmds => help(plugin, 'commands') } @@ -880,7 +883,6 @@ class UnoPlugin < Plugin return unless @games.key?(m.channel) return unless m.plugin # skip messages such as: botname, g = @games[m.channel] - replied = true case m.plugin.intern when :jo # join game return if m.params @@ -925,7 +927,7 @@ class UnoPlugin < Plugin g.show_discard when :ch if g.has_turn?(m.source) - if g.last_discard + if g.last_discard && (g.w4_played_flag == 1) g.challenge else m.reply _("previous move cannot be challenged") @@ -942,14 +944,11 @@ class UnoPlugin < Plugin when :tu # show whose turn is it return if m.params if g.has_turn?(m.source) - m.reply _("it's your turn, sleepyhead"), :nick => true + m.nickreply _("it's your turn, sleepyhead") else g.show_turn(:cards => false) end - else - replied=false end - m.replied=true if replied end def create_game(m, p) @@ -1109,6 +1108,7 @@ class UnoPlugin < Plugin end np = ps.played nf = ps.forfeits + nfullgames = np - nf nw = ps.won.length score = ps.won.inject(0) { |sum, w| sum += w.score } str = _("%{nick} played %{np} %{uno} games here, ") % { @@ -1117,9 +1117,17 @@ class UnoPlugin < Plugin str << _("forfeited %{nf} games, ") % { :nf => nf } if nf > 0 str << _("won %{nw} games") % { :nw => nw} if nw > 0 - str << _(" with %{score} total points") % { :score => score } - avg = ps.won.inject(0) { |sum, w| sum += w.score/w.opponents }/nw - str << _(" and an average of %{avg} points per opponent") % { :avg => avg } + str << _(" with %{score} total points,") % { :score => score } + avg = Float(ps.won.inject(0) { |sum, w| sum += w.score/w.opponents })/Float(nw) + avgrounded = (avg*100).round/100.0 + str << _(" an average of %{avgrounded} points per opponent,") % { :avgrounded => avgrounded } + avgpergame = 0.0 + avgpergamerounded = 0.0 + if nfullgames > 0 + avgpergame = Float(score)/Float(nfullgames) + avgpergamerounded = (avgpergame*100).round/100.0 + end + str << _(" and an average of %{avgpergamerounded} points per game") % { :avgpergamerounded => avgpergamerounded } end m.reply str end @@ -1156,19 +1164,31 @@ class UnoPlugin < Plugin pstats = chan_pstats(m.channel) scores = [] wins = [] + avgspergame = [] + statshash = Hash.new pstats.each do |k, v| wins << [v.won.length, k] - scores << [v.won.inject(0) { |s, w| s+=w.score }, k] - end - - if wins.empty? - m.reply(_("no %{uno} games were completed here") % { - :uno => UnoGame::UNO - }) - return + np = v.played + nf = v.forfeits + nfullgames = np - nf + score = v.won.inject(0) { |sum, w| sum += w.score } + avgpergame = 0.0 + avgpergamerounded = 0.0 + if nfullgames > 0 + avgpergame = Float(score)/Float(nfullgames) + avgpergamerounded = (avgpergame*100).round/100.0 + end + if p[:mingames] != nil + if nfullgames >= p[:mingames].to_i + avgspergame << [avgpergamerounded, k] + end + else + avgspergame << [avgpergamerounded, k] + end + scores << [score, k] + statshash[k] = [v.won.length, score, nfullgames, avgpergamerounded] end - if n = p[:scorenum] msg = _("%{uno} %{num} highest scores: ") % { :uno => UnoGame::UNO, :num => p[:scorenum] @@ -1179,8 +1199,8 @@ class UnoPlugin < Plugin if scores.length <= 5 list = "\n" + scores.map { |a| i+=1 - _("%{i}. %{b}%{nick}%{b} with %{b}%{score}%{b} points") % { - :i => i, :b => Bold, :nick => a.last, :score => a.first + _("%{i}. %{b}%{nick}%{b} with %{b}%{score}%{b} points (%{gms} games, %{ppg} PPG)") % { + :i => i, :b => Bold, :nick => a.last, :score => a.first, :gms => statshash[a.last][2], :ppg => statshash[a.last][3] } }.join("\n") else @@ -1201,8 +1221,8 @@ class UnoPlugin < Plugin if wins.length <= 5 list = "\n" + wins.map { |a| i+=1 - _("%{i}. %{b}%{nick}%{b} with %{b}%{score}%{b} wins") % { - :i => i, :b => Bold, :nick => a.last, :score => a.first + _("%{i}. %{b}%{nick}%{b} with %{b}%{score}%{b} wins (%{gms} games, %{ppg} PPG)") % { + :i => i, :b => Bold, :nick => a.last, :score => a.first, :gms => statshash[a.last][2], :ppg => statshash[a.last][3] } }.join("\n") else @@ -1213,9 +1233,32 @@ class UnoPlugin < Plugin } }.join(" | ") end + elsif n = p[:avgnum] + msg = _("%{uno} %{num} best average points per game (minimum number of games = %{mingms}): ") % { + :uno => UnoGame::UNO, :num => p[:avgnum], :mingms => p[:mingames] + } + avgspergame.sort! { |a1, a2| -(a1.first <=> a2.first) } + avgspergame = avgspergame[0, n.to_i].compact + i = 0 + if avgspergame.length <= 5 + list = "\n" + avgspergame.map { |a| + i+=1 + _("%{i}. %{b}%{nick}%{b} with %{b}%{avg}%{b} points per game (%{gms} games, %{pts} points)") % { + :i => i, :b => Bold, :nick => a.last, :avg => a.first, :gms => statshash[a.last][2], :pts => statshash[a.last][1] + } + }.join("\n") + else + list = avgspergame.map { |a| + i+=1 + _("%{i}. %{nick} ( %{avg} )") % { + :i => i, :nick => a.last, :avg => a.first + } + }.join(" | ") + end + else msg = _("uh, what kind of score list did you want, again?") - list = _(" I can only show the top scores (with top) and the most wins (with topwin)") + list = _(" I can only show the top scores (with top), the most wins (with topwin), and the best average points per game (with topavg)") end m.reply msg + list, :max_lines => (msg+list).count("\n")+1 end @@ -1235,7 +1278,8 @@ pg.map 'uno chanstats', :private => false, :action => :do_chanstats pg.map 'uno stats [:nick]', :private => false, :action => :do_pstats pg.map 'uno top :scorenum', :private => false, :action => :do_top, :defaults => { :scorenum => 5 } pg.map 'uno topwin :winnum', :private => false, :action => :do_top, :defaults => { :winnum => 5 } +pg.map 'uno topavg :avgnum :mingames', :private => false, :action => :do_top, :defaults => { :avgnum => 5, :mingames => 1 } pg.default_auth('stock', false) pg.default_auth('manage', false) -pg.default_auth('manage::drop::self', true) +pg.default_auth('manage::drop::self', true) \ No newline at end of file -- 2.32.0.93.g670b81a890