Skip to content

Instantly share code, notes, and snippets.

@nooodl
Last active September 26, 2015 21:38
Show Gist options
  • Save nooodl/1163165 to your computer and use it in GitHub Desktop.
Save nooodl/1163165 to your computer and use it in GitHub Desktop.
irc bot for nethack monster spoilers in 45 lines of code
=begin
<nooodl> @mind flayer
<Kroisos> mind flayer (h) | AC: 5 | Speed: 12 | MR: 90 | Attacks: 1d4 weapon
physical, 2d1 tentacle eatbrain, 2d1 tentacle eatbrain, 2d1 tentacle
eatbrain | Corpse: none | Resist: none
<nooodl> @s ac<0 speed<=6 mr
<Kroisos> ghost (ac: -5, speed: 3, mr: 50), hezrou (ac: -2, speed: 6, mr:55),
ice devil (ac: -4, speed: 6, mr: 55), pit fiend (ac: -3, speed: 6, mr: 65),
balrog (ac: -2, speed: 5, mr: 75), Juiblex (ac: -7, speed: 3, mr: 65),
Geryon (ac: -3, speed: 3, mr: 75)
=end
%w(rubygems psych cinch).each {|m| require m}; $, = ', '
class Hash; def method_missing(key); self[key.to_s]; end; end
$colors = %w(white black blue green red brown magenta orange yellow
bright_green cyan bright_cyan bright_blue bright_magenta black gray)
$monstdata = {}
Psych::load_documents(open 'data.yml').each do |i|
$monstdata[i.name.downcase] = i
end
def monst_info(name)
m = $monstdata[name.downcase]
return "I've never heard of such monsters." unless m
color = sprintf '%02d', $colors.index(m.color)
corpse = m._corpse.keys.join; resist = m.resist.keys.join
attacks = m.attacks.map {|i| i.sort.transpose[1] * ' '}.group_by {|i| i}
attacks = attacks.map {|k, v| v.length > 1 ? "#{k} (x#{v.length})" : k}.join
%w(corpse resist attacks).each {|i| eval "#{i} = 'none' if #{i}.empty?"}
"#{m.name} (\x3#{color}#{m.glyph}\xF) | AC: #{m.ac} | Speed: #{m.speed} | " \
"MR: #{m.mr} | Attacks: #{attacks} | Corpse: #{corpse} | Resist: #{resist}"
end
def find_monsts(query)
query = query.split.map do |i|
k, op, v = i.split /([<>]=?|!?=)/
[k, (op == '=') ? '==' : op, (v =~ /\d+/) ? v.to_i : v]
end
res = $monstdata.values.select do |m|
query.all? {|k, op, v| op.nil? or m[k.downcase].send op, v}
end.map do |i|
fields = query.transpose[0].uniq.map {|k| "#{k}: #{i[k]}"}
"#{i.name} (#{fields.join})"
end
return "No matches." if res.empty?
return res.join if res.length < 25
"Too many results (#{res.length})."
end
Cinch::Bot.new do
configure do |c|
c.nick = c.realname = c.user = 'Kroisos'
c.server = 'irc.freenode.org'
c.channels = %w(#acehack)
end
on :channel, /^@(.*)$/ do |m, query|
query = query.strip
m.reply(query =~ /^s / ? find_monsts($') : monst_info(query))
end
end.start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment