--- bot.v2.2.1.txt Wed Jul 16 07:22:02 2003 +++ bot.v2.2.2.schmolli.txt Wed Jul 16 09:16:27 2003 @@ -95,34 +95,56 @@ use strict; use IO::Socket; use Data::Dumper; - -my $TEST_MODE = 0; # connect to another test server; see lower block +use Getopt::Long; my $version = "2.2.1"; +(my $prog = $0) =~ s/^.*\///; -my $server = "area51.slashnet.org:6667"; -my $botnick = "b0t"; # nick -my $botuser = "bot"; # username -my $botrlnm = "http://www.slashnet.org/~b0t/"; # real name -my $botchan = "#g7"; # game channel -my $botidentify = "identify g7_rocks!!"; # identify to services -my $botopcmd = "PRIVMSG #g7 :opz plzkthx!!1 :)))"; # op self in channel -my $helpurl = "http://jotun.ultrazone.org/g7/"; # URL sent for help -my $admincommurl = "http://jotun.ultrazone.org/g7/admincomms.txt"; - # ^-- URL for admin help -my @access = ('yawnwraith','jotun','drdink'); - # ^-- usernames with admin access - +my %opts = ( + 'server' => 'area51.slashnet.org:6667', + 'botnick' => 'b0t', + 'botuser' => 'bot', + 'botrlnm' => 'http://www.slashnet.org/~b0t/', + 'botchan' => '#g7', + 'botpw' => 'g7_rocks!!', + 'botopcmd' => 'opz plzkthx!!1 :)))', + 'helpurl' => 'http://jotun.ultrazone.org/g7/', + 'admincommurl' => 'http://jotun.ultrazone.org/g7/admincomms.txt', + 'access' => [ 'yawnwraith', 'jotun', 'drdink' ], + 'rpstep' => 1.16, + 'rpbase' => 600, + 'rppenstep' => 1.14, + 'dbfile' => 'irpg.db', +); + +GetOptions(\%opts, + "help|h", + "verbose|v", + "debug", + "server|s=s", + "botnick|n=s", + "botuser|u=s", + "botrlnm|r=s", + "botchan|c=s", + "botpw|p=s", + "botopcmd|o=s", + "helpurl=s", + "admincommurl=s", + "access=s@", + "rpstep=f", + "rpbase=i", + "rppenstep=f", + "dbfile|irpgdb|db|d=s", +) or die "error parsing command line\n"; + +$opts{'help'} and do { help(); exit 0; }; +my $debug = $opts{'debug'} || 0; +my $v = $opts{'verbose'} || $debug; my $outbytes = 0; # sent bytes my $inbytes = 0; # received bytes -my $debug = 0; # print debug yes/no my %onchan; # users on game channel my %rps; # role-players -my $irpgdb = "irpg.db"; # database -my $rpstep = 1.16; # NEXT_LEVEL=(RPBASE*(RPSTEP**CURRENT_LEVEL)) -my $rpbase = 600; # NEXT_LEVEL=(RPBASE*(RPSTEP**CURRENT_LEVEL)) -my $rppenstep = 1.14; # PENALTY_SECS=(PENALTY*(RPPENSTEP**CURRENT_LEVEL)) my $rpreport = 0; # constant for reporting top players my $alrmint = 5; # secs between database rewrites my @prev_online; # user@hosts online on restart, die @@ -130,28 +152,23 @@ $SIG{'HUP'} = 0; # ignore sighup -if ($TEST_MODE) { - $server = "user-33qt3ul.dialup.mindspring.com:7800"; - $rpstep = 0; # 0-second levels - $rpbase = 0; # 0-second levels -} - CONNECT: # cheese. loaddb(); -my $sock = IO::Socket::INET->new(PeerAddr=>$server,PeerPort=>6667); +my $sock = IO::Socket::INET->new(PeerAddr=>$opts{'server'},PeerPort=>6667); die "Could not build socket; $!" unless $sock; -sts("NICK $botnick"); -sts("USER $botuser 0 0 :$botrlnm"); +sts("NICK $opts{botnick}"); +sts("USER $opts{botuser} 0 0 :$opts{botrlnm}"); while (<$sock>) { $inbytes += length; s/[\r\n]//g; + print "<- $_\n" if $debug; my @arg = split/ /; if (lc $arg[0] eq 'ping') { sts("PONG $arg[1]"); } if ($arg[1] eq '433') { - $botnick .= 0; - sts("NICK $botnick"); + $opts{'botnick'} .= 0; + sts("NICK $opts{botnick}"); } if (lc $arg[1] eq 'join') { my $usernick = (split(/!/,$arg[0]))[0]; @@ -165,7 +182,7 @@ if (exists $rps{$k}{nick} && $rps{$k}{nick} eq $usernick && $rps{$k}{online}) { $rps{$k}{online}=0; - $rps{$k}{next}+=int(20 * ($rppenstep**$rps{$k}{level})); + $rps{$k}{next}+=int(20 * ($opts{'rppenstep'}**$rps{$k}{level})); } } delete $onchan{$usernick}; @@ -177,9 +194,9 @@ if ($rps{$k}{nick} eq $usernick && $rps{$k}{online}) { $rps{$k}{nick}=substr($arg[2],1); $rps{$k}{userhost}=substr($arg[0],1); - $rps{$k}{next} += int(30 * ($rppenstep**$rps{$k}{level})); + $rps{$k}{next} += int(30 * ($opts{'rppenstep'}**$rps{$k}{level})); sts("NOTICE $rps{$k}{nick} :Penalty of ". - duration(int(30 * ($rppenstep**$rps{$k}{level}))). + duration(int(30 * ($opts{'rppenstep'}**$rps{$k}{level}))). " added to your timer for changing nicks."); } } @@ -192,9 +209,9 @@ if (exists $rps{$k}{nick} && $rps{$k}{nick} eq $usernick && $rps{$k}{online}) { $rps{$k}{online}=0; - $rps{$k}{next}+=int(200 * ($rppenstep**$rps{$k}{level})); + $rps{$k}{next}+=int(200 * ($opts{'rppenstep'}**$rps{$k}{level})); sts("NOTICE $rps{$k}{nick} :Penalty of ". - duration(int(200 * ($rppenstep**$rps{$k}{level}))). + duration(int(200 * ($opts{'rppenstep'}**$rps{$k}{level}))). " added to your timer for parting."); } } @@ -206,9 +223,9 @@ if (exists $rps{$k}{nick} && $rps{$k}{nick} eq $usernick && $rps{$k}{online}) { $rps{$k}{online}=0; - $rps{$k}{next}+=int(250 * ($rppenstep**$rps{$k}{level})); + $rps{$k}{next}+=int(250 * ($opts{'rppenstep'}**$rps{$k}{level})); sts("NOTICE $rps{$k}{nick} :Penalty of ". - duration(int(250 * ($rppenstep**$rps{$k}{level}))). + duration(int(250 * ($opts{'rppenstep'}**$rps{$k}{level}))). " added to your timer for getting kicked."); } } @@ -216,11 +233,12 @@ } if (lc $arg[1] eq '315') { if (@auto_login) { - sts("PRIVMSG $botchan :".scalar @auto_login." users matching ". + chanmsg(scalar @auto_login . " users matching " . scalar @prev_online." hosts automatically logged in; accounts: ". join(", ",@auto_login)); + } else { + chanmsg("0 users qualified for auto login."); } - else { sts("PRIVMSG $botchan :0 users qualified for auto login."); } undef @prev_online; undef @auto_login; } @@ -240,11 +258,11 @@ } } if ($arg[1] eq '001') { - sts($botidentify); - sts("JOIN $botchan"); - sts("MODE $botchan"); - sts($botopcmd); - sts("WHO $botchan"); + sts("identify $opts{botpw}"); + sts("JOIN $opts{botchan}"); + sts("MODE $opts{botchan}"); + chanmsg($opts{'botopcmd'}); + sts("WHO $opts{botchan}"); $SIG{ALRM} = \&rpcheck; alarm(5); } @@ -255,10 +273,10 @@ if (exists $rps{$k}{nick} && $rps{$k}{nick} eq $usernick && $rps{$k}{online}) { $rps{$k}{next} += int((length("@arg[3..$#arg]")-1) * - ($rppenstep**$rps{$k}{level})); + ($opts{'rppenstep'}**$rps{$k}{level})); sts("NOTICE $rps{$k}{nick} :Penalty of ". duration(int((length("@arg[3..$#arg]")-1) * - ($rppenstep**$rps{$k}{level}))). + ($opts{'rppenstep'}**$rps{$k}{level}))). " added to your timer for notice."); } } @@ -266,125 +284,126 @@ if (lc $arg[1] eq 'privmsg') { $arg[0] = substr($arg[0],1); my $usernick = (split/!/,$arg[0])[0]; - if (lc $arg[2] eq lc $botnick) { + if (lc $arg[2] eq lc $opts{'botnick'}) { if (lc $arg[3] eq ":\1version\1") { sts("NOTICE $usernick :\1VERSION IRPG bot v$version by jotun; ". - "$helpurl\1"); + "$opts{helpurl}\1"); } if (lc $arg[3] eq ":calc" && ha($usernick)) { my $eq = "@arg[4..$#arg]"; $eq =~ s/[^\d\.\+\-\(\)\*\&\^\%\~\!\/]//g; - sts("PRIVMSG $botchan :$_") for eval $eq; + chanmsg($_) for eval $eq; if ($@) { - sts("PRIVMSG $usernick :EVAL ERROR : $@"); - sts("PRIVMSG $usernick :In expression: $eq"); + privmsg("EVAL ERROR : $@", $usernick); + privmsg("In expression: $eq", $usernick); } next; } if (lc $arg[3] eq ":peval") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to PEVAL."); + privmsg("You don't have access to PEVAL.", $usernick); } else { - sts("PRIVMSG $usernick :$_") for eval "@arg[4..$#arg]"; - sts("PRIVMSG $usernick :EVAL ERROR: $@") if $@; + privmsg($_, $usernick) for eval "@arg[4..$#arg]"; + privmsg("EVAL ERROR: $@", $usernick) if $@; next; } } if (lc $arg[3] eq ":register") { if ($#arg < 6 || $arg[6] eq "") { - sts("PRIVMSG $usernick :Try: REGISTER "); - sts("PRIVMSG $usernick :IE : REGISTER Poseidon MyPassword ". - "God of the Sea"); + privmsg("Try: REGISTER ", $usernick); + privmsg("IE : REGISTER Poseidon MyPassword ". + "God of the Sea", $usernick); } elsif (exists $rps{$arg[4]}) { - sts("PRIVMSG $usernick :Sorry, that charname is already in use."); + privmsg("Sorry, that charname is already in use.", $usernick); } elsif (!exists $onchan{$usernick}) { - sts("PRIVMSG $usernick :Sorry, you're not in $botchan."); + privmsg("Sorry, you're not in $opts{botchan}.", $usernick); } elsif (length $arg[4] > 16) { - sts("PRIVMSG $usernick :Sorry, charnames must be < 17 chars long."); + privmsg("Sorry, charnames must be < 17 chars long.", $usernick); } elsif (length "@arg[6..$#arg]" > 30) { - sts("PRIVMSG $usernick :Sorry, char classes must be < 31 chars long."); + privmsg("Sorry, char classes must be < 31 chars long.", $usernick); } else { - $rps{$arg[4]}{next} = $rpbase; + $rps{$arg[4]}{next} = $opts{'rpbase'}; $rps{$arg[4]}{class} = "@arg[6..$#arg]"; $rps{$arg[4]}{level} = 0; $rps{$arg[4]}{online} = 1; $rps{$arg[4]}{nick} = $usernick; $rps{$arg[4]}{userhost} = $arg[0]; $rps{$arg[4]}{lastlogin} = localtime(time()); - $rps{$arg[4]}{pass} = crypt($arg[5],"rp"); - sts("PRIVMSG $botchan :Welcome $usernick"."'s new player $arg[4], ". - "the @arg[6..$#arg]! Next level in ".duration($rpbase)."."); - sts("PRIVMSG $usernick :Success! Account $arg[4] created. ". - "You have $rpbase seconds idleness until you reach level 1. "); - sts("PRIVMSG $usernick :NOTE: The point of the game is to see who ". - "can idle the longest. As such, talking (to channel or the ". - "bot), parting, quitting, and changing nicks penalize you."); + $rps{$arg[4]}{pass} = crypt($arg[5],mksalt()); + chanmsg("Welcome $usernick"."'s new player $arg[4], the " . + "@arg[6..$#arg]! Next level in ".duration($opts{'rpbase'})."."); + privmsg("Success! Account $arg[4] created. You have $opts{rpbase} " . + "seconds idleness until you reach level 1. ", $usernick); + privmsg("NOTE: The point of the game is to see who can idle the " . + "longest. As such, talking (to channel or the bot), parting, ". + "quitting, and changing nicks penalize you.", $usernick); next; } } if (lc $arg[3] eq ":del") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to del."); + privmsg("You don't have access to del.", $usernick); } else { if (!defined $arg[4]) { - sts("PRIVMSG $usernick :Try: DEL "); + privmsg("Try: DEL ", $usernick); } else { if (exists $rps{$arg[4]}) { delete $rps{$arg[4]}; - sts("PRIVMSG $botchan :Account $arg[4] removed by $arg[0]."); + chanmsg("Account $arg[4] removed by $arg[0]."); + } else { + privmsg("No such account $arg[4].", $usernick); } - else { sts("PRIVMSG $usernick :No such account $arg[4]."); } } next; } } if (lc $arg[3] eq ":alert") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to ALERT."); + privmsg("You don't have access to ALERT.", $usernick); } else { if (!defined $arg[4]) { - sts("PRIVMSG $usernick :Try: ALERT "); + privmsg("Try: ALERT ", $usernick); } else { - sts("PRIVMSG $botchan :ALERT from $usernick: @arg[4..$#arg]"); + chanmsg("ALERT from $usernick: @arg[4..$#arg]"); } next; } } if (lc $arg[3] eq ":hog") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to HOG."); + privmsg("You don't have access to HOG.", $usernick); } else { - sts("PRIVMSG $botchan :$usernick has summoned the Hand of God."); + chanmsg("$usernick has summoned the Hand of God."); hog(); next; } } if (lc $arg[3] eq ":chpass") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to CHPASS."); + privmsg("You don't have access to CHPASS.", $usernick); } else { if (!defined $arg[5]) { - sts("PRIVMSG $usernick :Try: CHPASS "); + privmsg("Try: CHPASS ", $usernick); } else { if (exists $rps{$arg[4]}) { - $rps{$arg[4]}{pass} = crypt($arg[5],"rp"); - sts("PRIVMSG $usernick :Password for $arg[4] changed."); + $rps{$arg[4]}{pass} = crypt($arg[5],mksalt()); + privmsg("Password for $arg[4] changed.", $usernick); } else { - sts("PRIVMSG $usernick :No such username $arg[4]."); + privmsg("No such username $arg[4].", $usernick); } } next; @@ -392,63 +411,65 @@ } if (lc $arg[3] eq ":chuser") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to CHUSER."); + privmsg("You don't have access to CHUSER.", $usernick); } else { if (!defined $arg[5]) { - sts("PRIVMSG $usernick :Try: CHUSER "); + privmsg("Try: CHUSER ", $usernick); } elsif (!exists $rps{$arg[4]}) { - sts("PRIVMSG $usernick :No such username $arg[4]."); + privmsg("No such username $arg[4].", $usernick); } elsif (exists $rps{$arg[5]}) { - sts("PRIVMSG $usernick :Username $arg[5] is already taken."); + privmsg("Username $arg[5] is already taken.", $usernick); } else { $rps{$arg[5]} = delete $rps{$arg[4]}; - sts("PRIVMSG $usernick :Username for $arg[4] changed to $arg[5]."); + privmsg("Username for $arg[4] changed to $arg[5].", $usernick); } next; } } if (lc $arg[3] eq ":chclass") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to CHCLASS."); + privmsg("You don't have access to CHCLASS.", $usernick); } else { if (!defined $arg[5]) { - sts("PRIVMSG $usernick :Try: CHCLASS "); + privmsg("Try: CHCLASS ", $usernick); } else { if (exists $rps{$arg[4]}) { $rps{$arg[4]}{class} = "@arg[5..$#arg]"; - sts("PRIVMSG $usernick :Class for $arg[4] changed to @arg[5..$#arg]."); + privmsg("Class for $arg[4] changed to @arg[5..$#arg].", $usernick); + } else { + privmsg("No such username $arg[4].", $usernick); } - else { sts("PRIVMSG $usernick :No such username $arg[4]."); } } next; } } if (lc $arg[3] eq ":push") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You don't have access to PUSH."); + privmsg("You don't have access to PUSH.", $usernick); } else { if (!defined $arg[5]) { - sts("PRIVMSG $usernick :Try: PUSH "); + privmsg("Try: PUSH ", $usernick); } else { if (exists $rps{$arg[4]}) { $rps{$arg[4]}{next} -= $arg[5]; - sts("PRIVMSG $usernick :Time to level for $arg[4] pushed ahead ". + privmsg("Time to level for $arg[4] pushed ahead ". "$arg[5] seconds. $arg[4] reaches next level in ". - duration($rps{$arg[4]}{next})."."); - sts("PRIVMSG $botchan :$usernick has pushed $arg[4] $arg[5] ". + duration($rps{$arg[4]}{next}).".", $usernick); + chanmsg("$usernick has pushed $arg[4] $arg[5] ". "seconds toward level ".($rps{$arg[4]}{level}+1). ". $arg[4] reaches next level in ". duration($rps{$arg[4]}{next})."."); + } else { + privmsg("No such username $arg[4].", $usernick); } - else { sts("PRIVMSG $usernick :No such username $arg[4]."); } } next; } @@ -458,32 +479,32 @@ for (keys %rps) { if (exists $rps{$_}{nick} && $rps{$_}{nick} eq $usernick && $rps{$_}{online}) { - sts("PRIVMSG $usernick :You are logged in as $_."); + privmsg("You are logged in as $_.", $usernick); $f=1; } } - sts("PRIVMSG $usernick :You are not logged in.") if !$f; + privmsg("You are not logged in.", $usernick) if !$f; next; } if (lc $arg[3] eq ":help") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :To register a new account: ". - "/msg $botnick REGISTER"); - sts("PRIVMSG $usernick :To login to an account: ". - "/msg $botnick LOGIN"); - sts("PRIVMSG $usernick :If you forget your password, ask for help ". - "in the channel."); - sts("PRIVMSG $usernick :For more info, see $helpurl"); + privmsg("To register a new account: ". + "/msg $opts{botnick} REGISTER", $usernick); + privmsg("To login to an account: ". + "/msg $opts{botnick} LOGIN", $usernick); + privmsg("If you forget your password, ask for help ". + "in the channel.", $usernick); + privmsg("For more info, see $opts{helpurl}", $usernick); } else { - sts("PRIVMSG $usernick :Help URL is $helpurl"); - sts("PRIVMSG $usernick :Admin commands URL is $admincommurl"); + privmsg("Help URL is $opts{helpurl}", $usernick); + privmsg("Admin commands URL is $opts{admincommurl}", $usernick); } next; } if (lc $arg[3] eq ":die") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You do not have access to DIE."); + privmsg("You do not have access to DIE.", $usernick); } else { sts("QUIT :DIE from $arg[0]"); @@ -492,14 +513,14 @@ } if (lc $arg[3] eq ":jump") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You do not have access to JUMP."); + privmsg("You do not have access to JUMP.", $usernick); } elsif (!defined $arg[4]) { - sts("PRIVMSG $usernick :Try JUMP "); + privmsg("Try JUMP ", $usernick); } else { sts("QUIT :JUMP to $arg[4] from $arg[0]"); - $server = $arg[4]; + $opts{'server'} = $arg[4]; close $sock; sleep 3; goto CONNECT; @@ -507,7 +528,7 @@ } if (lc $arg[3] eq ":restart") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You do not have access to RESTART."); + privmsg("You do not have access to RESTART.", $usernick); } else { sts("QUIT :RESTART from $arg[0]"); @@ -516,41 +537,41 @@ } if (lc $arg[3] eq ":info") { if (!ha($usernick)) { - sts("PRIVMSG $usernick :You do not have access to INFO."); + privmsg("You do not have access to INFO.", $usernick); } else { my $info = sprintf("%.2fkb sent, %.2fkb received in %s. ". "%d IRPG users online.", $outbytes/1024,$inbytes/1024,duration(time-$^T), scalar(grep { $rps{$_}{online} } keys %rps)); - sts("PRIVMSG $usernick :$info"); + privmsg($info, $usernick); next; } } if (lc $arg[3] eq ":login") { if ($#arg < 5 || $arg[5] eq "") { - sts("PRIVMSG $usernick :Try: LOGIN "); + privmsg("Try: LOGIN ", $usernick); } elsif (!exists $rps{$arg[4]}) { - sts("PRIVMSG $usernick :Sorry, no such account name. Note ". - "that account names are case sensitive."); + privmsg("Sorry, no such account name. Note ". + "that account names are case sensitive.", $usernick); } elsif (!exists $onchan{$usernick}) { - sts("PRIVMSG $usernick :Sorry, you're not in $botchan."); + privmsg("Sorry, you're not in $opts{botchan}.", $usernick); } - elsif ($rps{$arg[4]}{pass} ne crypt($arg[5],"rp")) { - sts("PRIVMSG $usernick :Wrong password."); + elsif ($rps{$arg[4]}{pass} ne crypt($arg[5],$rps{$arg[4]}{pass})) { + privmsg("Wrong password.", $usernick); } else { $rps{$arg[4]}{online} = 1; $rps{$arg[4]}{nick} = $usernick; $rps{$arg[4]}{userhost} = $arg[0]; $rps{$arg[4]}{lastlogin} = localtime(time()); - sts("PRIVMSG $botchan :$arg[4], the level $rps{$arg[4]}{level} ". - "$rps{$arg[4]}{class}, is now online from nickname $usernick. ". - "Next level in ".duration($rps{$arg[4]}{next})."."); - sts("PRIVMSG $usernick :Logon successful. Next level in ". - duration($rps{$arg[4]}{next})."."); + chanmsg("$arg[4], the level $rps{$arg[4]}{level} ". + "$rps{$arg[4]}{class}, is now online from nickname $usernick. ". + "Next level in ".duration($rps{$arg[4]}{next})."."); + privmsg("Logon successful. Next level in ". + duration($rps{$arg[4]}{next}).".", $usernick); } next; } @@ -560,28 +581,27 @@ if (exists $rps{$k}{nick} && $rps{$k}{nick} eq $usernick && $rps{$k}{online}) { $rps{$k}{next} += int((length("@arg[3..$#arg]")-1) * - ($rppenstep**$rps{$k}{level})); + ($opts{'rppenstep'}**$rps{$k}{level})); sts("NOTICE $rps{$k}{nick} :Penalty of ". duration(int((length("@arg[3..$#arg]")-1) * - ($rppenstep**$rps{$k}{level}))). + ($opts{'rppenstep'}**$rps{$k}{level}))). " added to your timer for privmsg."); $found=1; } } if (!$found && "@arg" =~ /http:/i && (time()-$onchan{$usernick}) < 90 && "@arg" !~ /ultrazone/i) { - sts("MODE $botchan +b $arg[0]"); + sts("MODE $opts{botchan} +b $arg[0]"); } } - print "in : $_\n" if $debug; } -print "Disconnected.\r\n" if $debug; +print "Disconnected.\n" if $v || $debug; sub sts { # send to server my $text = shift; print $sock "$text\r\n"; - print "out: $text\n" if $debug; + print "-> $text\n" if $debug; $outbytes += length($text) + 2; } @@ -589,7 +609,7 @@ my $nick = shift; for my $k (keys %rps) { if ($rps{$k}{nick} eq $nick && $rps{$k}{online}) { - for my $l (@access) { return 1 if $l eq $k; } + for my $l (@{$opts{'access'}}) { return 1 if $l eq $k; } } } return 0; @@ -613,19 +633,18 @@ my $win = int(rand(5)); my $time = int(((5 + int(rand(70)))/100) * $rps{$player}{next}); if ($win) { - sts("PRIVMSG $botchan :Verily I say unto thee, the Heavens have burst ". - "forth, and the blessed hand of God carried $player ".duration($time). - " toward level ".($rps{$player}{level}+1)."."); + chanmsg("Verily I say unto thee, the Heavens have burst ". + "forth, and the blessed hand of God carried $player ".duration($time). + " toward level ".($rps{$player}{level}+1)."."); $rps{$player}{next} -= $time; } else { - sts("PRIVMSG $botchan :Thereupon He stretched out His little finger ". - "among them and consumed $player with fire, slowing the heathen ". - duration($time)." from level ".($rps{$player}{level}+1)."."); + chanmsg("Thereupon He stretched out His little finger ". + "among them and consumed $player with fire, slowing the heathen ". + duration($time)." from level ".($rps{$player}{level}+1)."."); $rps{$player}{next} += $time; } - sts("PRIVMSG $botchan :$player reaches next level in ". - duration($rps{$player}{next})."."); + chanmsg("$player reaches next level in ". duration($rps{$player}{next})."."); } sub rpcheck { # check levels, update database @@ -634,19 +653,16 @@ if ($rpreport%4320==0) { # 4320 = six hours, if $alrmint is 5 seconds my @u = sort { $rps{$b}{level} <=> $rps{$a}{level} || $rps{$a}{next} <=> $rps{$b}{next} } keys %rps; - sts("PRIVMSG $botchan :#G7 Idle RPG Top Players:"); - sts("PRIVMSG $botchan :$u[0], the level $rps{$u[0]}{level} ". - "$rps{$u[0]}{class}, is #1! Next level in ". - (duration($rps{$u[0]}{next}))."."); - sts("PRIVMSG $botchan :$u[1], the level $rps{$u[1]}{level} ". - "$rps{$u[1]}{class}, is #2! Next level in ". - (duration($rps{$u[1]}{next}))."."); - sts("PRIVMSG $botchan :$u[2], the level $rps{$u[2]}{level} ". - "$rps{$u[2]}{class}, is #3! Next level in ". - (duration($rps{$u[2]}{next}))."."); - system("cp $irpgdb .dbbackup/$irpgdb".time()); + chanmsg("#G7 Idle RPG Top Players:"); + foreach my $i (0..2) { + $#u >= $i and + chanmsg("$u[$i], the level $rps{$u[$i]}{level} ". + "$rps{$u[$i]}{class}, is #" . ($i + 1) . "! Next level in ". + (duration($rps{$u[$i]}{next}))."."); + } + system("cp $opts{dbfile} .dbbackup/$opts{dbfile}".time()); } - open(RPS,">$irpgdb") or die "FAILED WRITING $irpgdb: $!"; + open(RPS,">$opts{dbfile}") or die "$opts{dbfile}: $!"; print RPS "# username\tpass\tlevel\tclass\tnext\tnick\tuserhost\tonline 0/1". "\tlast login time\tamulet\tcharm\thelm\tboots\tgloves\tring\t". @@ -657,8 +673,8 @@ $rps{$k}{next}-=$alrmint; if ($rps{$k}{next} < 1) { $rps{$k}{level}++; - $rps{$k}{next} = int($rpbase*($rpstep**$rps{$k}{level})); - sts("PRIVMSG $botchan :$k, the $rps{$k}{class}, has attained level ". + $rps{$k}{next} = int($opts{'rpbase'}*($opts{'rpstep'}**$rps{$k}{level})); + sts("PRIVMSG $opts{botchan} :$k, the $rps{$k}{class}, has attained level ". "$rps{$k}{level}! Next level in ".duration($rps{$k}{next}). "."); find_item($k); @@ -705,7 +721,7 @@ my $gain = int($rps{$opp}{level}/4); $gain = 7 if $gain < 7; $gain = int(($gain/100)*$rps{$u}{next}); - sts("PRIVMSG $botchan :$u has challenged $opp in combat and won! ". + sts("PRIVMSG $opts{botchan} :$u has challenged $opp in combat and won! ". duration($gain)." is removed from $u"."'s clock."); open(B,">>battles.txt"); print B "$u has challenged $opp in combat and won! ".duration($gain). @@ -718,7 +734,7 @@ print B "$u has dealt $opp a Critical Strike! ".duration($gain). " is added to $opp"."'s clock.\n"; close B; - sts("PRIVMSG $botchan :$u has dealt $opp a Critical Strike! ". + sts("PRIVMSG $opts{botchan} :$u has dealt $opp a Critical Strike! ". duration($gain)." is added to $opp"."'s clock."); $rps{$opp}{next} += $gain; } @@ -727,7 +743,7 @@ my $gain = int($rps{$opp}{level}/7); $gain = 7 if $gain < 7; $gain = int(($gain/100)*$rps{$u}{next}); - sts("PRIVMSG $botchan :$u has challenged $opp in combat and lost! ". + sts("PRIVMSG $opts{botchan} :$u has challenged $opp in combat and lost! ". duration($gain)." is added to $u"."'s clock."); open(B,">>battles.txt"); print B "$u has challenged $opp in combat and lost! ".duration($gain). @@ -754,7 +770,7 @@ $gain = $rps{$opp[$p]}{next} if $gain > $rps{$opp[$p]}{next}; } $gain = int($gain*.20); - sts("PRIVMSG $botchan :$opp[0], $opp[1], and $opp[2] have team battled ". + sts("PRIVMSG $opts{botchan} :$opp[0], $opp[1], and $opp[2] have team battled ". "$opp[3], $opp[4], and $opp[5] and won! ".duration($gain). " is removed from their clocks."); open(B,">>battles.txt"); @@ -767,7 +783,7 @@ $rps{$opp[2]}{next} -= $gain; } else { - sts("PRIVMSG $botchan :$opp[0], $opp[1], and $opp[2] have team battled ". + sts("PRIVMSG $opts{botchan} :$opp[0], $opp[1], and $opp[2] have team battled ". "$opp[3], $opp[4], and $opp[5] and lost! No time is awarded."); open(B,">>battles.txt"); print B "$opp[0], $opp[1], and $opp[2] have team battled $opp[3], ". @@ -828,8 +844,8 @@ } elsif ($level > $rps{$u}{item}{$type}) { sts("NOTICE $rps{$u}{nick} :You found a level $level $type! Your ". - "current $type is only level ".(0+$rps{$u}{item}{$type})." so ". - "it seems Luck is with you."); + "current $type is only level ".(0+$rps{$u}{item}{$type})." so ". + "it seems Luck is with you."); $rps{$u}{item}{$type} = $level; } else { @@ -843,12 +859,13 @@ sub loaddb { # load the players database undef %rps; %rps = (); - (open(RPS,"<$irpgdb") || ! -e $irpgdb) or die "loaddb() failed; $!"; - while (chomp(my $l=)) { + (open(RPS,"<$opts{dbfile}") || ! -e $opts{dbfile}) or die "loaddb() failed; $!"; + while (my $l=) { + chomp $l; next if $l =~ /^#/; # skip comments my @i = split("\t",$l); print Dumper @i if @i != 19; - die "Anomaly in loaddb(); line $. of $irpgdb has wrong fields (". + die "Anomaly in loaddb(); line $. of $opts{dbfile} has wrong fields (". scalar @i.")" if @i != 19; if ($i[7]) { push(@prev_online,$i[6]); } # log back in $rps{$i[0]}{pass} = $i[1]; @@ -871,4 +888,43 @@ $rps{$i[0]}{item}{weapon} = $i[18]; } close RPS; +} + +sub mksalt { # generate a random salt for passwds + join '',('a'..'z','A'..'Z','0'..'9','/','.')[rand 64, rand 64]; +} + +sub chanmsg { # send a message to the channel + my $msg = shift or return undef; + privmsg($msg, $opts{'botchan'}); +} + +sub privmsg { # send a message to an arbitrary entity + my $msg = shift or return undef; + my $target = shift or return undef; + sts("PRIVMSG $target :$msg"); +} + +sub help { # print help message + print " +usage: $prog [OPTIONS] + --help, -h Print this message + --verbose, -v Print verbose messages + --server, -s Specify IRC server:port to connect to + --botnick, -n bot's IRC nick + --botuser, -u bot's local username + --botrlnm, -r bot's real name + --botchan, -c IRC channel to join + --botpw, -p Specify passwd to identify with + --botopcmd, -o Specify message to spit into botchan on init + --helpurl URL to refer newbies to + --admincommurl URL to refer admins to + --access usernames allowed to issue admin commands + + Timing parameters: + --rpbase base time to level up + --rpstep time to next level = rpbase * (rpstep ** CURRENT_LEVEL) + --rppenstep PENALTY_SECS=(PENALTY*(RPPENSTEP**CURRENT_LEVEL)) + +"; }