374 lines
14 KiB
Perl
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:
|