summaryrefslogtreecommitdiff
path: root/data/rbot/plugins/games/hangman.rb
diff options
context:
space:
mode:
authorRaine Virta <rane@kapsi.fi>2009-01-27 03:30:25 +0200
committerGiuseppe Bilotta <giuseppe.bilotta@gmail.com>2009-01-27 03:29:32 +0100
commit936b5b6efdb79a888848b606b09dd361b0d9cda0 (patch)
tree9eeb5a6ce2a4f2227ecbb33db7996d74dbc33fd7 /data/rbot/plugins/games/hangman.rb
parent0bf6eabdddddafecc42d56eaae1e0db35413390f (diff)
hangman plugin: various improvements including support for wordlists
Diffstat (limited to 'data/rbot/plugins/games/hangman.rb')
-rw-r--r--data/rbot/plugins/games/hangman.rb107
1 files 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{<a.*?\?w=(.*?)\n}).flatten
-
+
count == 1 ? words.first : words
end
end
class Hangman
attr_reader :misses, :guesses, :word, :letters
-
+
STAGES = [' (x_x) ', ' (;_;) ', ' (>_<) ', ' (-_-) ', ' (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 <channel>] [with word <word>] | hangman play with [max|min] length [<|>|==] [<length>] => start a hangman game -- word will be randomed in case it's omitted"
+ return "hangman play on <channel> with word <word> => use in private chat with the bot to start a game with custom word\n"+
+ "hangman play random [with [max|min] length [<|>|== <length>]] => hangman with a random word from #{RandomWord::SITE}\n"+
+ "hangman play with wordlist <wordlist> => hangman with random word from <wordlist>"
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'
+