といあえず、お下品さを取り除いた,POE::Component::Server::IRC::WhoIsTagged

クライアントを複数起動しての動作確認が辛いので、もうこれはだめです。
お下品な人は、sample.yamlの値を変更すれば良いと思います。

package POE::Component::Server::IRC::WhoIsTagged;

our $VERSION = '0.01_01';
use strict;
use warnings;
use Data::Dumper;
use List::MoreUtils;
use List::Util;
use base qw/POE::Component::Server::IRC/;

my $wit_user    = {};
my %WIT_STATUS_DEFAULT = ( status => 'stop' , channel => '' , looser => [] );
my $wit_status ;
%{ $wit_status } = %WIT_STATUS_DEFAULT;
my $wit_config  = {};

sub init_who_is_tagged{
    my $self    = shift;
    $wit_config = shift;
    $wit_status->{status} = 'stop';
}

sub _daemon_cmd_message  {
    my $self = shift;
    my $nick = shift || return;
    my $type = shift || return;
    my @args =  @_ ;
    if( $type eq 'PRIVMSG' ){
        my $channel = $args[0];
        my $message = $args[1];

        my $cmd = $self->WIT_get_cmd( $message );

        # cmd_terminate : force to stop. all use can run this.
        if( $channel eq $wit_status->{channel} && $cmd eq 'cmd_terminate' ) {
            $self->WIT_terminate();
        }

        # cmd_stop
        if( $channel eq $wit_status->{channel} && $cmd eq 'cmd_stop' && $wit_status->{status} eq 'king_mode' && $nick eq  $wit_status->{jorker} ) {
            %{ $wit_status } = %WIT_STATUS_DEFAULT;
        }

        # king mode
        if( $channel eq $wit_status->{channel} && $wit_status->{status} eq 'king_mode' && $nick ne  $wit_status->{jorker} ) {
            $args[1] = $self->WIT_looser_message();
        }

        if( $channel eq $wit_status->{channel} && $wit_status->{status} eq 'playing' && $nick eq $wit_status->{jorker} ) {
            $args[1] = $self->WIT_jorker_message( $message );
        }

        if( $channel eq $wit_status->{channel} && $wit_status->{status} eq 'playing'  && $nick ne $wit_status->{jorker} && $self->WIT_is_looser( $nick ) ) {
            $args[1] = $self->WIT_looser_message();
        }

        # cmd_start : no game yet and cmd_start command in message. 
        if( $wit_status->{status} eq 'stop' && $cmd eq 'cmd_start') {
            $self->WIT_start( $channel , $self->{state}{chans}{ uc $channel }{users} );
        }

        # cmd_doubt 
        if(  $channel eq $wit_status->{channel} && $wit_status->{status} eq 'playing' && $cmd eq 'cmd_doubt') {
            $args[1] .= $self->WIT_doubt( $nick , $message );
        }

        # cmd_confess 
        if(  $channel eq $wit_status->{channel} && $wit_status->{status} eq 'playing' && $cmd eq 'cmd_confess') {
            $args[1] .= $self->WIT_confess( $nick , $message );
        }
    }

    $self->SUPER::_daemon_cmd_message( $nick , $type , @args );
}
sub WIT_is_looser{
    my $self = shift;
    my $nick = shift;

    return List::MoreUtils::any { $nick eq $_ } @{ $self->{looser} } ;

}


sub WIT_doubt { 
    my  $self   = shift;
    my $my_nick    = shift;
    my $message = shift;

    my ( undef, $nick ) = split( qq{ } , $message );

    # myself 
    return ' error:myself' if $my_nick eq $nick ;

    if ( defined  $wit_status->{user}{ $nick }  ) {
        if( $wit_status->{user}{ $nick } ) {
            if( $nick eq  $wit_status->{jorker} ) {
                # mach
                %{ $wit_status } = %WIT_STATUS_DEFAULT;
                # TODO : maybe use bot? 
                return " $my_nick is WINNER!";
            }
            else {
                push @{ $wit_status->{looser} } , $my_nick;
                return " $my_nick is LOOSER!";
            }
        }
        else {
            return " error: $nick is already lost this game";
        }
    }
    else {
        return " error: $nick is not playing this game";
    }

}

ub WIT_get_cmd {
    my $self    = shift;
    my $message = shift;

    my ( $cmd ) = split( qq{ }, $message );

    my @cmds = qw(cmd_start cmd_stop cmd_doubt cmd_confess cmd_terminate);

    for my $key ( @cmds ) {
        if( $wit_config->{ $key } eq $cmd ) {
            return $key;
        }
    }



    return '';
}

sub WIT_terminate {
    %{$wit_status} = %WIT_STATUS_DEFAULT;
}

sub WIT_start {
    my $self    = shift;
    my $channel = shift;
    my $users   = shift;
    $wit_status->{status} = 'playing';
    $wit_status->{channel} = $channel;
    my $cnt = 1;
    foreach my $keys ( List::Util::shuffle( keys %{ $users } ) ) {
        my $user  =  lc $keys;
        $wit_status->{user}{ $user } = 1;
        if( $cnt == 1 ) {
            $wit_status->{jorker} = $user ;
        }
        $cnt++;
    }

}

sub WIT_looser_message {
    return $wit_config->{looser};
}
sub WIT_jorker_message {
    my $self = shift;
    my $text = shift;

    # only replace rule for now.
    if( defined $wit_config->{rule}{replace} ) {
        my $index = rand( @{ $wit_config->{rule}{replace} } ) ;
        $text =  $wit_config->{rule}{replace}[ $index ];
    }
    return $text;

}
cmd_start   : --start
cmd_stop    : --stop
cmd_doubt   : --doubt
cmd_confess : --confess
cmd_terminate : --terminate
rule :
    replace :
        - 'ヒデブー'
        - 'アベシー'
        - 'オッパピー'
looser : 私は負け犬の、犬ちきしょうです。
use strict;
use warnings;
use FindBin::libs;
use YAML::Syck;
use File::Spec;

my $file = File::Spec->catfile($FindBin::Bin,'../conf/sample.yml');

use POE qw(Component::Server::IRC::WhoIsTagged);

my %conf
    = (
        config => {
            servername => 'localhost',
            nicklen    => 15,
            network    => 'WhoIsTagged',
        },
    );

my $ircd = POE::Component::Server::IRC::WhoIsTagged->spawn(  %conf );

$ircd->init_who_is_tagged( LoadFile( $file ) );

POE::Session->create(
    package_states => [
        main => [qw(_start)],
    ],
    heap => { ircd => $ircd },
);

$poe_kernel->run();
exit 0;

sub _start {
    my ($kernel,$heap) = @_[KERNEL,HEAP];
    $heap->{ircd}->yield( 'register' );
    $heap->{ircd}->add_listener( port => 6667 );

}

__END__