From 936b5b6efdb79a888848b606b09dd361b0d9cda0 Mon Sep 17 00:00:00 2001 From: Raine Virta Date: Tue, 27 Jan 2009 03:30:25 +0200 Subject: [PATCH] hangman plugin: various improvements including support for wordlists --- data/rbot/plugins/games/hangman.rb | 107 ++++++++++++++++++----------- 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/data/rbot/plugins/games/hangman.rb b/data/rbot/plugins/games/hangman.rb index 7ad0eb99..197d60e9 100644 --- a/data/rbot/plugins/games/hangman.rb +++ b/data/rbot/plugins/games/hangman.rb @@ -7,28 +7,31 @@ # Copyright:: (C) 2009 Raine Virta # License:: GPL v2 # -# Hangman game for rbot +# Description:: Hangman game for rbot +# +# TODO:: scoring and stats +# some sort of turn-basedness, maybe module RandomWord SITE = "http://coyotecult.com/tools/randomwordgenerator.php" - + def self.get(count=1) res = Net::HTTP.post_form(URI.parse(SITE), {'numwords' => count}) words = res.body.scan(%r{_<) ', ' (-_-) ', ' (o_~) ', ' (^_^) ', '\(^o^)/'] HEALTH = STAGES.size-1 LETTER = /[^\W0-9_]/u def initialize(word, channel=nil) - @word = word.downcase + @word = word @guesses = [] @misses = [] @health = HEALTH @@ -37,7 +40,7 @@ class Hangman def letters # array of the letters in the word - @word.split(//).reject { |c| c !~ LETTER } + @word.split(//u).reject { |c| c !~ LETTER }.map { |c| c.downcase } end def face @@ -45,8 +48,9 @@ class Hangman end def to_s + # creates a string that presents the word with unknown letters shown as underscores @word.split(//).map { |c| - @guesses.include?(c) || c !~ LETTER ? c : "_" + @guesses.include?(c.downcase) || c !~ LETTER ? c : "_" }.join end @@ -54,8 +58,8 @@ class Hangman str.downcase! # full word guess - if str !~ /^#{LETTER}$/ - word == str ? @solved = true : punish + if str !~ /^#{LETTER}$/u + word.downcase == str ? @solved = true : punish else # single letter guess return false if @guesses.include?(str) # letter has been guessed before @@ -63,7 +67,7 @@ class Hangman @misses << str punish end - + @guesses << str end end @@ -73,13 +77,13 @@ class Hangman end def won? - (letters-@guesses).empty? || @solved + (letters - @guesses).empty? || @solved end def lost? @health.zero? end - + def punish @health -= 1 end @@ -89,27 +93,39 @@ class HangmanPlugin < Plugin def initialize super @games = {} + @settings = {} end def help(plugin, topic="") case topic when "" - #plugin.map "hangman [play] [on :channel] [with word :word] [with [:adj] length [:relation :size]]", return "hangman game plugin - topics: play, stop" when "play" - return "hangman play [on ] [with word ] | hangman play with [max|min] length [<|>|==] [] => start a hangman game -- word will be randomed in case it's omitted" + return "hangman play on with word => use in private chat with the bot to start a game with custom word\n"+ + "hangman play random [with [max|min] length [<|>|== ]] => hangman with a random word from #{RandomWord::SITE}\n"+ + "hangman play with wordlist => hangman with random word from " when "stop" return "hangman stop => quits the current game" end end - def start(m, params) - word = unless params[:word] + def get_word(params) + if params[:word] + params[:word].join(" ") + elsif params[:wordlist] + begin + wordlist = Wordlist.get(params[:wordlist].join("/"), :spaces => true) + rescue + raise "no such wordlist" + end + + wordlist[rand(wordlist.size)] + else # getting a random word words = RandomWord::get(100) - + if adj = params[:adj] words = words.sort_by { |e| e.size } - + if adj == "max" words.last else @@ -117,7 +133,7 @@ class HangmanPlugin < Plugin end elsif params[:relation] && params[:size] words = words.select { |w| w.size.send(params[:relation], params[:size].to_i) } - + unless words.empty? words.first else @@ -127,11 +143,16 @@ class HangmanPlugin < Plugin else words.first end - else - params[:word] end - - return unless word + end + + def start(m, params) + begin + word = get_word(params) || return + rescue => e + m.reply e.message + return + end if (params[:channel] || m.public?) target = if m.public? @@ -139,36 +160,37 @@ class HangmanPlugin < Plugin else params[:channel] end - + # is the bot on the channel? unless @bot.server.channels.names.include?(target.to_s) m.reply "i'm not on that channel" return end - + if @games.has_key?(target) - m.reply "there's already a hangman game in progress on that channel" + m.reply "there's already a hangman game in progress on the channel" return end - + @bot.say target, "#{m.source} has started a hangman -- join the fun!" else target = m.source.to_s end - - @games[target] = Hangman.new(word) + + @games[target] = Hangman.new(word) + @settings[target] = params @bot.say target, game_status(@games[target]) end - + def stop(m, params) source = if m.public? m.channel else m.source end - - if @games.has_key?(source.to_s) + + if @games.has_key?(source.to_s) @bot.say source, "oh well, the answer would've been #{Bold}#{@games[source.to_s].word}#{Bold}" @games.delete(source.to_s) end @@ -181,25 +203,29 @@ class HangmanPlugin < Plugin m.source.to_s end - if (game = @games[source]) + if game = @games[source] if m.message =~ /^[^\W0-9_]$/u || m.message =~ prepare_guess_regex(game) return unless game.guess(m.message) - + m.reply game_status(game) end if game.over? if game.won? - m.reply "game over - you win!" + str = "you nailed it!" elsif game.lost? - m.reply "game over - you lose!" + str = "you've killed the poor guy :(" end + m.reply "#{str} go #{Bold}again#{Bold}?" + @games.delete(source) end + elsif @settings[source] && m.message =~ /^(?:again|more!?$)/i + start(m, @settings[source]) end end - + def prepare_guess_regex(game) Regexp.new("^#{game.word.split(//).map { |c| game.guesses.include?(c) || c !~ Hangman::LETTER ? c : '[^\W0-9_]' @@ -216,8 +242,11 @@ class HangmanPlugin < Plugin end plugin = HangmanPlugin.new -plugin.map "hangman [play] [on :channel] [with word :word] [with [:adj] length [:relation :size]]", +plugin.map "hangman [play] with wordlist *wordlist", :action => 'start' +plugin.map "hangman [play] on :channel with word *word", :action => 'start' +plugin.map "hangman [play] [random] [with [:adj] length [:relation :size]]", :action => 'start', :requirements => { :adj => /min|max/, :relation => /<|<=|>=|>|==/, :size => /\d+/ } - + plugin.map "hangman stop", :action => 'stop' + -- 2.39.2