Added a WerewolfAdmin module for administering the Werewolf IRC game.
This commit is contained in:
1 parent
fdfc249ba8
commit
33b50a651a
2 files changed
+373
No files matched your search
@@ -3,6 +3,7 @@ Auto IRC Bot 3.0: Change Log
|
||||
|
||||
3.0 Indev
|
||||
===============================================================================
|
||||
* Added a WerewolfAdmin module for administering the Werewolf IRC game.
|
||||
* Fixed significant state mismatched data bugs.
|
||||
* Added API::IRC::ison for checking if a user is on a channel.
|
||||
* Werewolf: Fixed a bug in harlot staying home.
|
||||
|
||||
@@ -0,0 +1,372 @@
|
||||
# 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 (FJOIN|FWAIT|FSTART|KICK|FSTOP) [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"._getrole(lc $argv[1], 2)."\2.");
|
||||
_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 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:
|
||||
Reference in new issue
Block a user