X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=data%2Frbot%2Fplugins%2Fazgame.rb;h=9721d8b8b77c3ed398bb5cb2c6dacc7a6c80b5c0;hb=cdb3d2609c8f0ff5c8fca3b5e6d73de8db40a40f;hp=ec80478923e61d892d48770d7cd2a0509bcb99ae;hpb=3be59fb29b5f503916648a476fa0ec607070ca56;p=user%2Fhenk%2Fcode%2Fruby%2Frbot.git diff --git a/data/rbot/plugins/azgame.rb b/data/rbot/plugins/azgame.rb index ec804789..9721d8b8 100644 --- a/data/rbot/plugins/azgame.rb +++ b/data/rbot/plugins/azgame.rb @@ -27,11 +27,15 @@ AZ_RULES = { class AzGame attr_reader :range, :word + attr_accessor :tries, :total_tries, :winner def initialize(plugin, lang, word) @plugin = plugin @lang = lang.to_sym @word = word.downcase @range = [AZ_RULES[lang][:first].dup, AZ_RULES[lang][:last].dup] + @total_tries = 0 + @tries = Hash.new(0) + @winner = nil def @range.to_s return "%s -- %s" % self end @@ -53,6 +57,28 @@ class AzGame return [:in, @range] end +# TODO scoring: base score is t = ceil(100*exp(-(n-1)^2/50))+p for n attempts +# done by p players; players that didn't win but contributed +# with a attempts will get t*a/n points + + include Math + + def score + n = @total_tries + p = @tries.keys.length + t = (100*exp(-(n-1)**2/50**2)).ceil + p + debug "Total score: #{t}" + ret = Hash.new + @tries.each { |k, a| + ret[k] = [t*a/n, "%d tries" % a] + } + if @winner + debug "replacing winner score of %d with %d" % [ret[@winner].first, t] + ret[@winner] = [t, "winner"] + end + return ret.sort_by { |h| h.last.first } + end + end class AzGamePlugin < Plugin @@ -80,7 +106,7 @@ class AzGamePlugin < Plugin def listen(m) return unless m.kind_of?(PrivMessage) return if m.channel.nil? or m.address? - k = m.channel.to_s # to_sym? + k = m.channel.downcase.to_s # to_sym? return unless @games.key?(k) return if m.params word = m.plugin.downcase @@ -93,6 +119,13 @@ class AzGamePlugin < Plugin case isit.first when :bingo m.reply "#{Bold}BINGO!#{Bold}: the word was #{Underline}#{word}#{Underline}. Congrats, #{Bold}#{m.sourcenick}#{Bold}!" + @games[k].total_tries += 1 + @games[k].tries[m.source] += 1 + @games[k].winner = m.source + ar = @games[k].score.inject([]) { |res, kv| + res.push("%s: %d (%s)" % kv.flatten) + } + m.reply "The game was won after #{@games[k].total_tries} tries. Scores for this game: #{ar.join('; ')}" @games.delete(k) when :out m.reply "#{word} is not in the range #{Bold}#{isit.last}#{Bold}" if m.address? @@ -100,6 +133,8 @@ class AzGamePlugin < Plugin m.reply "#{word} doesn't exist or is not acceptable for the game" when :in m.reply "close, but no cigar. New range: #{Bold}#{isit.last}#{Bold}" + @games[k].total_tries += 1 + @games[k].tries[m.source] += 1 when :ignore m.reply "#{word} is already one of the range extrema: #{isit.last}" if m.address? else @@ -108,10 +143,10 @@ class AzGamePlugin < Plugin end def manual_word_check(m, params) - k = m.channel.to_s + k = m.channel.downcase.to_s word = params[:word].downcase if not @games.key?(k) - m.reply "no A-Z game running here, can't check for #{word}, can I?" + m.reply "no A-Z game running here, can't check if #{word} is valid, can I?" return end if word !~ /^[a-z]+$/ @@ -123,9 +158,13 @@ class AzGamePlugin < Plugin def stop_game(m, params) return if m.channel.nil? # Shouldn't happen, but you never know - k = m.channel.to_s # to_sym? + k = m.channel.downcase.to_s # to_sym? if @games.key?(k) m.reply "the word in #{Bold}#{@games[k].range}#{Bold} was: #{Bold}#{@games[k].word}" + ar = @games[k].score.inject([]) { |res, kv| + res.push("%s: %d (%s)" % kv.flatten) + } + m.reply "The game was cancelled after #{@games[k].total_tries} tries. Scores for this game would have been: #{ar.join('; ')}" @games.delete(k) else m.reply "no A-Z game running in this channel ..." @@ -134,7 +173,7 @@ class AzGamePlugin < Plugin def start_game(m, params) return if m.channel.nil? # Shouldn't happen, but you never know - k = m.channel.to_s # to_sym? + k = m.channel.downcase.to_s # to_sym? unless @games.key?(k) lang = (params[:lang] || @bot.config['core.language']).to_sym method = 'random_pick_'+lang.to_s @@ -152,7 +191,8 @@ class AzGamePlugin < Plugin m.reply "got it!" @games[k] = AzGame.new(self, lang, word) end - m.reply "A-Z: #{Bold}#{@games[k].range}#{Bold}" + tr = @games[k].total_tries + m.reply "A-Z: #{Bold}#{@games[k].range}#{Bold}" + (tr > 0 ? "(after #{tr} tries)" : "") return end @@ -333,7 +373,7 @@ class AzGamePlugin < Plugin return false end debug p - if p =~ /#{word}<\/span>([^\n]+?)#{rules[:good]}<\/span>/i + if p =~ /#{word}<\/span>([^\n]+?)#{rules[:good]}<\/span>/i debug "new word #{word}" wc[word.to_sym] = {:who => :dict} return true @@ -383,7 +423,7 @@ class AzGamePlugin < Plugin lemmi = Array.new good = rules[:good] # We look for a lemma composed by a single word and of length at least two - p.scan(/(.*?)<\/span>([^\n]+?)#{rules[:good]}<\/span>/i) { |prelemma, discard| + p.scan(/(.*?)<\/span>([^\n]+?)#{rules[:good]}<\/span>/i) { |prelemma, discard| lemma = prelemma.downcase debug "checking lemma #{lemma} (#{prelemma}) and discarding #{discard}" next if wc.key?(lemma.to_sym)