Files
Autobot/modules/WerewolfAdmin.pm
2011-04-21 20:58:48 -06:00

374 lines
14 KiB
Perl

# Module: WerewolfAdmin. See below for documentation.
# Copyright (C) 2010-2011 Xelhua Development Group, et al.
# This program is free software; rights to this code are stated in doc/LICENSE.
package M::WerewolfAdmin;
use strict;
use warnings;
use feature qw(switch);
use API::Std qw(cmd_add cmd_del timer_add timer_del trans conf_get);
use API::IRC qw(privmsg notice cmode ison);
# Initialization subroutine.
sub _init {
# Create the WOLFA command.
cmd_add('WOLFA', 0, 'werewolf.admin', \%M::WerewolfAdmin::HELP_WOLFA, \&M::WerewolfAdmin::cmd_wolfa) or return;
# Success.
return 1;
}
# Void subroutine.
sub _void {
# Delete the WOLFA command.
cmd_del('WOLFA') or return;
# Success.
return 1;
}
# Help hash for the WOLFA command.
our %HELP_WOLFA = (
en => "This command allows you to perform various administrative actions in a game of Werewolf (A.K.A. Mafia). \2Syntax:\2 WOLFA (JOIN|WAIT|START|KICK|STOP) [parameters]",
);
# Callback for the WOLFA command.
sub cmd_wolfa {
my ($src, @argv) = @_;
# We require at least one parameter.
if (!defined $argv[0]) {
notice($src->{svr}, $src->{nick}, trans('Not enough parameters').q{.});
return;
}
# Iterate the parameter.
given (uc $argv[0]) {
when (/^(JOIN|J)$/) {
# WOLFA JOIN
# Requires an extra parameter.
if (!defined $argv[1]) {
notice($src->{svr}, $src->{nick}, trans('Not enough parameters').q{.});
return;
}
# Check if a game is running.
if (!$M::Werewolf::PGAME and !$M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
}
elsif ($M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'Sorry, but the game is already running. Try again next time.');
}
else {
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Check if this user exists in channel.
if (!ison($src->{svr}, $src->{chan}, lc $argv[1])) {
notice($src->{svr}, $src->{nick}, "No such user \2$argv[1]\2 is on the channel.");
return;
}
# Make sure they're not already playing.
if (exists $M::Werewolf::PLAYERS{lc $argv[1]}) {
notice($src->{svr}, $src->{nick}, 'They\'re already playing!');
return;
}
# Set variables.
$M::Werewolf::PLAYERS{lc $argv[1]} = 0;
my $nick = $M::Werewolf::NICKS{lc $argv[1]} = $Core::IRC::Users::users{$src->{svr}}{lc $argv[1]};
# Send message.
my ($gsvr, $gchan) = split '/', $M::Werewolf::GAMECHAN, 2;
cmode($gsvr, $gchan, "+v $nick");
privmsg($gsvr, $gchan, "\2$nick\2 was forced to join the game by \2$src->{nick}\2.");
}
}
when (/^(WAIT|W)$/) {
# WOLFA WAIT
# Check if a game is running.
if (!$M::Werewolf::PGAME) {
if (!$M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
else {
notice($src->{svr}, $src->{nick}, 'Werewolf is already in play.');
return;
}
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Increase WAIT.
$M::Werewolf::WAIT += 20;
# And WAITED.
$M::Werewolf::WAITED++;
privmsg($src->{svr}, $src->{chan}, "\2$src->{nick}\2 forcibly increased join wait time by 20 seconds.");
}
when ('START') {
# WOLFA START
# Check if a game is running.
if (!$M::Werewolf::PGAME) {
if (!$M::Werewolf::GAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
else {
notice($src->{svr}, $src->{nick}, 'Werewolf is already in play.');
return;
}
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Need four or more players.
if (keys %M::Werewolf::PLAYERS < 4) {
privmsg($src->{svr}, $src->{chan}, "$src->{nick}: Four or more players are required to play.");
return;
}
# First, determine how many players to declare a wolf.
my $cwolves = POSIX::ceil(keys(%M::Werewolf::PLAYERS) * .14);
# Only one seer, harlot, guardian angel, traitor and detective.
my $cseers = 1;
my $charlots = my $cdrunks = my $cangels = my $ctraitors = my $cdetectives = 0;
if (keys %M::Werewolf::PLAYERS >= 6) { $charlots++ unless conf_get('werewolf:rated-g') }
if (keys %M::Werewolf::PLAYERS >= 7) { $cdrunks++ unless conf_get('werewolf:rated-g') }
if (keys %M::Werewolf::PLAYERS >= 9) { $cangels++ unless conf_get('werewolf:no-angels') }
if (keys %M::Werewolf::PLAYERS >= 12 and conf_get('werewolf:traitors')) { $ctraitors++ }
if (keys %M::Werewolf::PLAYERS >= 16 and conf_get('werewolf:detectives')) { $cdetectives++ }
# Give all players a role.
foreach my $plyr (keys %M::Werewolf::PLAYERS) { $M::Werewolf::PLAYERS{$plyr} = 'v' }
# Push players into a temporary array.
my @plyrs = keys %M::Werewolf::PLAYERS;
# Set wolves.
while ($cwolves > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|s|g|h|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'w';
$cwolves--;
$M::Werewolf::STATIC[0] .= ", \2$M::Werewolf::NICKS{$rpi}\2";
}
}
$M::Werewolf::STATIC[0] = substr $M::Werewolf::STATIC[0], 2;
# Set seers.
while ($cseers > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|g|h|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 's';
$cseers--;
$M::Werewolf::STATIC[1] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set harlots.
while ($charlots > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|g|s|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'h';
$charlots--;
$M::Werewolf::STATIC[2] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set drunks.
while ($cdrunks > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} =~ m/v/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'vi';
$cdrunks--;
}
}
# Set guardian angels.
while ($cangels > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|h|s|d|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'g';
$cangels--;
$M::Werewolf::STATIC[3] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set traitors.
while ($ctraitors > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|h|s|d|g)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 't';
$ctraitors--;
$M::Werewolf::STATIC[4] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# Set detectives.
while ($cdetectives > 0) {
my $rpi = $plyrs[int rand scalar @plyrs];
if ($M::Werewolf::PLAYERS{$rpi} !~ m/^(w|h|s|g|t)$/xsm) {
$M::Werewolf::PLAYERS{$rpi} = 'd';
$cdetectives--;
$M::Werewolf::STATIC[5] = "\2$M::Werewolf::NICKS{$rpi}\2";
}
}
# If there's 8 or more players, give one of them a gun.
if (keys %M::Werewolf::PLAYERS >= 8) {
my $rpi = $plyrs[int rand scalar @plyrs];
while ($M::Werewolf::PLAYERS{$rpi} =~ m/w/xsm || $M::Werewolf::PLAYERS{$rpi} =~ m/t/xsm) { $rpi = $plyrs[int rand scalar @plyrs] }
$M::Werewolf::PLAYERS{$rpi} .= 'b';
# And give them PLAYER COUNT * .12 bullets rounded up.
$M::Werewolf::BULLETS = POSIX::ceil(keys(%M::Werewolf::PLAYERS) * .12);
if ($M::Werewolf::PLAYERS{$rpi} =~ m/i/xsm) { $M::Werewolf::BULLETS = $M::Werewolf::BULLETS * 3 }
}
# Set variables.
$M::Werewolf::GAME = 1;
$M::Werewolf::PGAME = 0;
# Set spoke variables.
foreach (keys %M::Werewolf::PLAYERS) { $M::Werewolf::SPOKE{$_} = time }
# All players have their role, so lets begin the game!
my ($gsvr, $gchan) = split '/', $M::Werewolf::GAMECHAN, 2;
privmsg($gsvr, $gchan, "Game is now starting. (forced start by \2$src->{nick}\2)");
cmode($gsvr, $gchan, '+m');
# Delete waiting timer.
timer_del('werewolf.joinwait');
# Start timer for bed checking.
timer_add('werewolf.chkbed', 2, 5, \&M::Werewolf::_chkbed);
# Initialize the nighttime.
M::Werewolf::_init_night();
}
when (/^(KICK|K)$/) {
# WOLFA KICK
# Check if a game is running.
if (!$M::Werewolf::GAME and !$M::Werewolf::PGAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# Requires an extra parameter.
if (!defined $argv[1]) {
notice($src->{svr}, $src->{nick}, trans('Not enough parameters').q{.});
return;
}
# Check if the target is playing.
if (!exists $M::Werewolf::PLAYERS{lc $argv[1]}) {
notice($src->{svr}, $src->{nick}, "\2$argv[1]\2 is not currently playing.");
return;
}
# Kill the target.
privmsg($src->{svr}, $src->{chan}, "\2$argv[1]\2 died of an unknown disease. He/She was a \2".M::Werewolf::_getrole(lc $argv[1], 2)."\2.");
M::Werewolf::_player_del(lc $argv[1]);
}
when ('STOP') {
# WOLFA STOP
# Check if a game is running.
if (!$M::Werewolf::GAME and !$M::Werewolf::PGAME) {
notice($src->{svr}, $src->{nick}, 'No game is currently running.');
return;
}
# Check if this is the game channel.
if ($src->{svr}.'/'.$src->{chan} ne $M::Werewolf::GAMECHAN) {
notice($src->{svr}, $src->{nick}, "Werewolf is currently running in \2$M::Werewolf::GAMECHAN\2.");
return;
}
# End the game.
my ($gsvr, $gchan) = split '/', $M::Werewolf::GAMECHAN, 2;
privmsg($gsvr, $gchan, "\2$src->{nick}\2 is forcing the game to end...");
M::Werewolf::_gameover('n');
}
default { notice($src->{svr}, $src->{nick}, trans('Unknown action', $_).q{.}) }
}
return 1;
}
# Start initialization.
API::Std::mod_init('WerewolfAdmin', 'Xelhua', '1.00', '3.0.0a11');
# build: perl=5.010000
__END__
=head1 NAME
WerewolfAdmin - Administrative functions for Werewolf
=head1 VERSION
1.00
=head1 SYNOPSIS
None
=head1 DESCRIPTION
This module allows one to administer the Werewolf IRC game, provided by the
Werewolf module.
It provides the following commands:
WOLFA JOIN|J - Force join.
WOLFA WAIT - Force wait.
WOLFA START - Force start.
WOLFA KICK|K - Kick a player.
WOLFA STOP - Stop a game forcibly.
And requires the werewolf.admin privilege.
=head1 DEPENDENCIES
This module depends on the following Auto module(s):
=over
=item Werewolf
The Werewolf module provides the game that this module provides administrative
commands for. Using this module without Werewolf will likely cause a fatal
error.
=back
=head1 AUTHOR
This module was written by Elijah Perrault.
This module is maintained by Xelhua Development Group.
=head1 LICENSE AND COPYRIGHT
This module is Copyright (C) 2010-2011, Xelhua Development Group.
This module is released under the same terms as Auto itself.
=cut
# vim: set ai et ts=4 sw=4: