[QUIZ] IRC Teams (#221)

D

Daniel Moore

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this
quiz until 48 hours have elapsed from the time this message was
sent.

2. Support Ruby Quiz by submitting ideas and responses
as often as you can.

3. Enjoy!

Suggestion: A [QUIZ] in the subject of emails about the problem
helps everyone on Ruby Talk follow the discussion. Please reply to
the original quiz message, if you can.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

RSS Feed: http://rubyquiz.strd6.com/quizzes.rss

Suggestions?: http://rubyquiz.strd6.com/suggestions

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

## IRC Teams (#221)

Tashi dele Rubyists,

This week's quiz was suggested by [Martin DeMello][1]

A common feature in IRC-based games is the ability to create and join
teams. The game bot sits in the channel and watches for messages in a
certain format, which it interprets as commands. Write a small gamebot
that accepts the following commands:

create team <teamname>
join <teamname>
leave team
show teams
show team <teamname>
show my team
delete team <teamname>
reset

Here's a typical transcript

<foo> create team ruby
<bot> - created team ruby -
<bar> create team python
<bot> - created team python -
<foo> show teams
<bot> teams: ruby, python
<foo> show team ruby
<bot> team ruby: foo
<bar> show my team
<bot> bar is in team python
<baz> join ruby
<bot> baz is now in team ruby
<bar> show team ruby
<bot> team ruby: foo, baz

Think up some useful extensions, such as the ability to join a user
rather than a team, and restricting some commands like reset to ops.
There are plenty of IRC bot libraries out there, go explore! If one
already does team formation, that's cheating, though :)

Have fun!

[1]: http://zem.novylen.net
 
M

Martin DeMello

The main idea behind this quiz was to show how easy it is to get an
irc bot up and running in ruby, especially given the number of bot
frameworks out there. I chose to base my bot on rif
[http://gitorious.org/ruby-irc], a nice lightweight library with
everything I needed to get started immediately.

The code consists of a Teams class, which does all the actual work of
maintaining teams, and a TeamBot, which inherits from RIF::Bot and
handles the IRC part of it. For the sake of simplicity, the bot
frontend does no real validation; it just unpacks an incoming message
into a command and arguments, and blindly sends those arguments to the
Teams object. All public methods on the Teams object accept a player
name as a first argument, whether they need it or not, and return
either a string or an array of strings, or raise an exception. The bot
sends the return value to the channel; an array is sent one message at
a time.

-------------------------------------------------------------------------------------

gem 'rif'
require 'rif/bot'

class TeambotError < Exception
end

def TeambotError(foo)
TeambotError.new(foo)
end

class Teams
attr_accessor :teams, :members

def initialize
@teams = {}
@members = {}
end

def create(player, team)
raise TeambotError("team #{team} already created") if teams[team]
teams[team] = true
"created team #{team}"
end

def delete(player, team)
teams.delete(team)
members.delete_if {|k,v| v == team}
"deleted team #{team}"
end

def join(player, team)
raise TeambotError("no such team: #{team}") if not teams[team]
members[player] = team
"#{player} has joined team #{team}"
end

def leave(player, *args)
team = members.delete(player)
"#{player} has left team #{team}"
end

def reset(*args)
@members = {}
@teams = {}
"deleted all teams"
end

def show(player, *args)
if args[0] == 'my'
members[player]
elsif args[0] == 'teams'
teams.map {|team, _| "#{team}: #{show_players(team)}"}
elsif args[0] == 'team'
show_players(team)
end
end

private
def players(team)
members.select {|k,v| v == team}.keys
end

def show_players(team)
players(team).join(" ")
end
end

class TeamBot < RIF::Bot
attr_reader :teams, :channel
def initialize(channel, nick, server, port, username)
@teams = Teams.new
@channel = channel
super(nick, server, port, username)
end

def on_endofmotd(event)
join(channel)
end

def on_message(event)
return unless event.channel == channel
msg, *args = event.message.split(" ")
player = event.nick
begin
*ret = teams.send(msg, player, *args)
rescue NameError
ret = nil
rescue TeambotError => e
ret = [e.message]
end
ret.each {|m| send_message(channel, m)} if ret
end
end

if __FILE__ == $0
channel = "##{ARGV[0]}"
bot = TeamBot.new(channel, "teambot", "irc.freenode.net", 6667, "RIF Bot")
bot.connect
end

martin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top